Merge branch 'flipperdevices:dev' into dev

This commit is contained in:
Eng1n33r
2022-04-14 17:52:45 +03:00
committed by GitHub
149 changed files with 2368 additions and 529 deletions

3
.gitignore vendored
View File

@@ -36,3 +36,6 @@ CMakeLists.txt
# bundle output
dist
# kde
.directory

View File

@@ -21,13 +21,23 @@ bool archive_app_is_available(void* context, const char* path) {
ArchiveAppTypeEnum app = archive_get_app_type(path);
if(app == ArchiveAppTypeU2f) {
FileWorker* file_worker = file_worker_alloc(true);
bool file_exists = false;
file_worker_is_file_exist(file_worker, "/any/u2f/key.u2f", &file_exists);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
file_exists = storage_file_open(file, "/any/u2f/key.u2f", FSAM_READ, FSOM_OPEN_EXISTING);
if(file_exists) {
file_worker_is_file_exist(file_worker, "/any/u2f/cnt.u2f", &file_exists);
storage_file_close(file);
file_exists =
storage_file_open(file, "/any/u2f/cnt.u2f", FSAM_READ, FSOM_OPEN_EXISTING);
if(file_exists) {
storage_file_close(file);
}
file_worker_free(file_worker);
}
storage_file_free(file);
furi_record_close("storage");
return file_exists;
} else {
return false;
@@ -60,10 +70,10 @@ void archive_app_delete_file(void* context, const char* path) {
bool res = false;
if(app == ArchiveAppTypeU2f) {
FileWorker* file_worker = file_worker_alloc(true);
res = file_worker_remove(file_worker, "/any/u2f/key.u2f");
res |= file_worker_remove(file_worker, "/any/u2f/cnt.u2f");
file_worker_free(file_worker);
Storage* fs_api = furi_record_open("storage");
res = (storage_common_remove(fs_api, "/any/u2f/key.u2f") == FSE_OK);
res |= (storage_common_remove(fs_api, "/any/u2f/cnt.u2f") == FSE_OK);
furi_record_close("storage");
if(archive_is_favorite("/app:u2f/U2F Token")) {
archive_favorites_delete("/app:u2f/U2F Token");

View File

@@ -392,6 +392,17 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) {
furi_assert(browser);
furi_assert(name);
uint8_t browser_depth = 0;
with_view_model(
browser->view, (ArchiveBrowserViewModel * model) {
browser_depth = idx_last_array_size(model->idx_last);
return false;
});
if(browser_depth > BROWSER_DEPTH_MAX) {
return;
}
archive_dir_count_items(browser, string_get_cstr(name));
with_view_model(

View File

@@ -4,6 +4,7 @@
#define TAB_RIGHT InputKeyRight //default tab swith direction
#define FILE_LIST_BUF_LEN 100
#define BROWSER_DEPTH_MAX 8
static const char* tab_default_paths[] = {
[ArchiveTabFavorites] = "/any/favorites",

View File

@@ -4,20 +4,63 @@
#include "archive_apps.h"
#include "archive_browser.h"
#define ARCHIVE_FAV_FILE_BUF_LEN 32
static bool archive_favorites_read_line(File* file, string_t str_result) {
string_reset(str_result);
uint8_t buffer[ARCHIVE_FAV_FILE_BUF_LEN];
bool result = false;
do {
uint16_t read_count = storage_file_read(file, buffer, ARCHIVE_FAV_FILE_BUF_LEN);
if(storage_file_get_error(file) != FSE_OK) {
return false;
}
for(uint16_t i = 0; i < read_count; i++) {
if(buffer[i] == '\n') {
uint32_t position = storage_file_tell(file);
if(storage_file_get_error(file) != FSE_OK) {
return false;
}
position = position - read_count + i + 1;
storage_file_seek(file, position, true);
if(storage_file_get_error(file) != FSE_OK) {
return false;
}
result = true;
break;
} else {
string_push_back(str_result, buffer[i]);
}
}
if(result || read_count == 0) {
break;
}
} while(true);
return result;
}
uint16_t archive_favorites_count(void* context) {
furi_assert(context);
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
string_t buffer;
string_init(buffer);
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
uint16_t lines = 0;
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -27,21 +70,26 @@ uint16_t archive_favorites_count(void* context) {
}
}
storage_file_close(file);
string_clear(buffer);
file_worker_close(file_worker);
file_worker_free(file_worker);
storage_file_free(file);
furi_record_close("storage");
return lines;
}
static bool archive_favourites_rescan() {
string_t buffer;
string_init(buffer);
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
File* fav_item_file = storage_file_alloc(fs_api);
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -53,9 +101,10 @@ static bool archive_favourites_rescan() {
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer));
}
} else {
bool file_exists = false;
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
bool file_exists = storage_file_open(
fav_item_file, string_get_cstr(buffer), FSAM_READ, FSOM_OPEN_EXISTING);
if(file_exists) {
storage_file_close(fav_item_file);
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer));
}
}
@@ -64,11 +113,13 @@ static bool archive_favourites_rescan() {
string_clear(buffer);
file_worker_close(file_worker);
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
storage_file_close(file);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
file_worker_free(file_worker);
storage_file_free(file);
storage_file_free(fav_item_file);
furi_record_close("storage");
return result;
}
@@ -77,7 +128,9 @@ bool archive_favorites_read(void* context) {
furi_assert(context);
ArchiveBrowserView* browser = context;
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
File* fav_item_file = storage_file_alloc(fs_api);
string_t buffer;
FileInfo file_info;
@@ -88,11 +141,11 @@ bool archive_favorites_read(void* context) {
archive_file_array_rm_all(browser);
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -107,10 +160,10 @@ bool archive_favorites_read(void* context) {
need_refresh = true;
}
} else {
bool file_exists = false;
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
bool file_exists = storage_file_open(
fav_item_file, string_get_cstr(buffer), FSAM_READ, FSOM_OPEN_EXISTING);
if(file_exists) {
storage_file_close(fav_item_file);
archive_add_file_item(browser, &file_info, string_get_cstr(buffer));
file_count++;
} else {
@@ -121,9 +174,11 @@ bool archive_favorites_read(void* context) {
string_reset(buffer);
}
}
storage_file_close(file);
string_clear(buffer);
file_worker_close(file_worker);
file_worker_free(file_worker);
storage_file_free(file);
storage_file_free(fav_item_file);
furi_record_close("storage");
archive_set_item_count(browser, file_count);
@@ -143,12 +198,14 @@ bool archive_favorites_delete(const char* format, ...) {
va_end(args);
string_init(buffer);
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -164,11 +221,12 @@ bool archive_favorites_delete(const char* format, ...) {
string_clear(buffer);
string_clear(filename);
file_worker_close(file_worker);
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
storage_file_close(file);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
file_worker_free(file_worker);
storage_file_free(file);
furi_record_close("storage");
return result;
}
@@ -182,14 +240,15 @@ bool archive_is_favorite(const char* format, ...) {
va_end(args);
string_init(buffer);
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
bool found = false;
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -202,10 +261,11 @@ bool archive_is_favorite(const char* format, ...) {
}
}
storage_file_close(file);
string_clear(buffer);
string_clear(filename);
file_worker_close(file_worker);
file_worker_free(file_worker);
storage_file_free(file);
furi_record_close("storage");
return found;
}
@@ -214,7 +274,8 @@ bool archive_favorites_rename(const char* src, const char* dst) {
furi_assert(src);
furi_assert(dst);
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
string_t path;
string_t buffer;
@@ -223,11 +284,11 @@ bool archive_favorites_rename(const char* src, const char* dst) {
string_init(path);
string_printf(path, "%s", src);
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) {
while(1) {
if(!file_worker_read_until(file_worker, buffer, '\n')) {
if(!archive_favorites_read_line(file, buffer)) {
break;
}
if(!string_size(buffer)) {
@@ -244,11 +305,12 @@ bool archive_favorites_rename(const char* src, const char* dst) {
string_clear(buffer);
string_clear(path);
file_worker_close(file_worker);
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
storage_file_close(file);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
file_worker_free(file_worker);
storage_file_free(file);
furi_record_close("storage");
return result;
}
@@ -263,15 +325,17 @@ void archive_favorites_save(void* context) {
furi_assert(context);
ArchiveBrowserView* browser = context;
FileWorker* file_worker = file_worker_alloc(true);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
for(size_t i = 0; i < archive_file_get_array_size(browser); i++) {
ArchiveFile_t* item = archive_get_file_at(browser, i);
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(item->name));
}
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
file_worker_free(file_worker);
storage_file_free(file);
furi_record_close("storage");
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "file_worker.h"
#include <storage/storage.h>
#define ARCHIVE_FAV_PATH "/any/favorites.txt"
#define ARCHIVE_FAV_TEMP_PATH "/any/favorites.tmp"

View File

@@ -201,18 +201,18 @@ void archive_file_append(const char* path, const char* format, ...) {
string_init_vprintf(string, format, args);
va_end(args);
FileWorker* file_worker = file_worker_alloc(false);
Storage* fs_api = furi_record_open("storage");
File* file = storage_file_alloc(fs_api);
if(!file_worker_open(file_worker, path, FSAM_WRITE, FSOM_OPEN_APPEND)) {
FURI_LOG_E(TAG, "Append open error");
bool res = storage_file_open(file, path, FSAM_WRITE, FSOM_OPEN_APPEND);
if(res) {
storage_file_write(file, string_get_cstr(string), string_size(string));
}
if(!file_worker_write(file_worker, string_get_cstr(string), string_size(string))) {
FURI_LOG_E(TAG, "Append write error");
}
file_worker_close(file_worker);
file_worker_free(file_worker);
storage_file_close(file);
storage_file_free(file);
furi_record_close("storage");
}
void archive_delete_file(void* context, const char* format, ...) {

View File

@@ -1,6 +1,8 @@
#pragma once
#include "file_worker.h"
#include <m-array.h>
#include <m-string.h>
#include <storage/storage.h>
typedef enum {
ArchiveFileTypeIButton,

View File

@@ -54,6 +54,10 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
ArchiveFile_t* selected = files_array_get(model->files, model->item_idx - model->array_offset);
if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) {
string_set_str(menu[1], "Unpin");
}
if(!archive_is_known_app(selected->type)) {
string_set_str(menu[0], "---");
string_set_str(menu[1], "---");
@@ -67,10 +71,6 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
}
}
if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) {
string_set_str(menu[1], "Unpin");
}
for(size_t i = 0; i < MENU_ITEMS; i++) {
canvas_draw_str(canvas, 82, 27 + i * 11, string_get_cstr(menu[i]));
string_clear(menu[i]);

View File

@@ -401,6 +401,8 @@ void cli_delete_command(Cli* cli, const char* name) {
int32_t cli_srv(void* p) {
Cli* cli = cli_alloc();
furi_hal_vcp_init();
// Init basic cli commands
cli_commands_init(cli);

View File

@@ -1,6 +1,9 @@
#include <storage/storage.h>
#include <assets_icons.h>
#include <gui/gui.h>
#include <gui/view_stack.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <furi.h>
#include <furi_hal.h>
@@ -13,6 +16,10 @@
#include "desktop_i.h"
#include "desktop_helpers.h"
static void desktop_auto_lock_arm(Desktop*);
static void desktop_auto_lock_inhibit(Desktop*);
static void desktop_start_auto_lock_timer(Desktop*);
static void desktop_loader_callback(const void* message, void* context) {
furi_assert(context);
Desktop* desktop = context;
@@ -37,9 +44,19 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
switch(event) {
case DesktopGlobalBeforeAppStarted:
animation_manager_unload_and_stall_animation(desktop->animation_manager);
desktop_auto_lock_inhibit(desktop);
return true;
case DesktopGlobalAfterAppFinished:
animation_manager_load_and_continue_animation(desktop->animation_manager);
// TODO: Implement a message mechanism for loading settings and (optionally)
// locking and unlocking
LOAD_DESKTOP_SETTINGS(&desktop->settings);
desktop_auto_lock_arm(desktop);
return true;
case DesktopGlobalAutoLock:
if(!loader_is_locked(desktop->loader)) {
desktop_lock(desktop);
}
return true;
}
@@ -58,6 +75,63 @@ static void desktop_tick_event_callback(void* context) {
scene_manager_handle_tick_event(app->scene_manager);
}
static void desktop_input_event_callback(const void* value, void* context) {
furi_assert(value);
furi_assert(context);
const InputEvent* event = value;
Desktop* desktop = context;
if(event->type == InputTypePress) {
desktop_start_auto_lock_timer(desktop);
}
}
static void desktop_auto_lock_timer_callback(void* context) {
furi_assert(context);
Desktop* desktop = context;
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAutoLock);
}
static void desktop_start_auto_lock_timer(Desktop* desktop) {
osTimerStart(
desktop->auto_lock_timer, furi_hal_ms_to_ticks(desktop->settings.auto_lock_delay_ms));
}
static void desktop_stop_auto_lock_timer(Desktop* desktop) {
osTimerStop(desktop->auto_lock_timer);
}
static void desktop_auto_lock_arm(Desktop* desktop) {
if(desktop->settings.auto_lock_delay_ms) {
desktop->input_events_subscription = furi_pubsub_subscribe(
desktop->input_events_pubsub, desktop_input_event_callback, desktop);
desktop_start_auto_lock_timer(desktop);
}
}
static void desktop_auto_lock_inhibit(Desktop* desktop) {
desktop_stop_auto_lock_timer(desktop);
if(desktop->input_events_subscription) {
furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription);
desktop->input_events_subscription = NULL;
}
}
void desktop_lock(Desktop* desktop) {
desktop_auto_lock_inhibit(desktop);
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
notification_message(desktop->notification, &sequence_display_off_delay_1000);
}
void desktop_unlock(Desktop* desktop) {
furi_hal_rtc_set_pin_fails(0);
desktop_helpers_unlock_system(desktop);
desktop_view_locked_unlock(desktop->locked_view);
scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain);
desktop_auto_lock_arm(desktop);
}
Desktop* desktop_alloc() {
Desktop* desktop = malloc(sizeof(Desktop));
@@ -146,9 +220,17 @@ Desktop* desktop_alloc() {
animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager);
}
desktop->notification = furi_record_open("notification");
desktop->app_start_stop_subscription = furi_pubsub_subscribe(
loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop);
desktop->input_events_pubsub = furi_record_open("input_events");
desktop->input_events_subscription = NULL;
desktop->auto_lock_timer =
osTimerNew(desktop_auto_lock_timer_callback, osTimerOnce, desktop, NULL);
return desktop;
}
@@ -157,8 +239,17 @@ void desktop_free(Desktop* desktop) {
furi_pubsub_unsubscribe(
loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription);
if(desktop->input_events_subscription) {
furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription);
desktop->input_events_subscription = NULL;
}
desktop->loader = NULL;
desktop->input_events_pubsub = NULL;
furi_record_close("loader");
furi_record_close("notification");
furi_record_close("input_events");
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain);
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
@@ -191,6 +282,8 @@ void desktop_free(Desktop* desktop) {
furi_record_close("menu");
osTimerDelete(desktop->auto_lock_timer);
free(desktop);
}
@@ -214,14 +307,16 @@ int32_t desktop_srv(void* p) {
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
if(desktop->settings.pin_code.length > 0) {
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
} else {
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock) && !desktop->settings.pin_code.length) {
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
}
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
if(!loader_is_locked(desktop->loader)) {
desktop_auto_lock_arm(desktop);
}
} else {
desktop_lock(desktop);
}
if(desktop_is_first_start()) {

View File

@@ -19,6 +19,7 @@
#include <gui/scene_manager.h>
#include <loader/loader.h>
#include <notification/notification_app.h>
#define STATUS_BAR_Y_SHIFT 13
@@ -59,10 +60,18 @@ struct Desktop {
ViewPort* lock_viewport;
AnimationManager* animation_manager;
Loader* loader;
NotificationApp* notification;
FuriPubSubSubscription* app_start_stop_subscription;
FuriPubSub* input_events_pubsub;
FuriPubSubSubscription* input_events_subscription;
osTimerId_t auto_lock_timer;
};
Desktop* desktop_alloc();
void desktop_free(Desktop* desktop);
void desktop_lock(Desktop* desktop);
void desktop_unlock(Desktop* desktop);

View File

@@ -5,7 +5,7 @@
#include <stdbool.h>
#include <toolbox/saved_struct.h>
#define DESKTOP_SETTINGS_VER (1)
#define DESKTOP_SETTINGS_VER (2)
#define DESKTOP_SETTINGS_PATH "/int/desktop.settings"
#define DESKTOP_SETTINGS_MAGIC (0x17)
#define PIN_MAX_LENGTH 12
@@ -39,6 +39,7 @@ typedef struct {
typedef struct {
uint16_t favorite;
PinCode pin_code;
uint32_t auto_lock_delay_ms;
} DesktopSettings;
static inline bool pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2) {

View File

@@ -36,12 +36,17 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
app->popup = popup_alloc();
app->submenu = submenu_alloc();
app->variable_item_list = variable_item_list_alloc();
app->pin_input_view = desktop_view_pin_input_alloc();
app->pin_setup_howto_view = desktop_settings_view_pin_setup_howto_alloc();
app->pin_setup_howto2_view = desktop_settings_view_pin_setup_howto2_alloc();
view_dispatcher_add_view(
app->view_dispatcher, DesktopSettingsAppViewMenu, submenu_get_view(app->submenu));
view_dispatcher_add_view(
app->view_dispatcher,
DesktopSettingsAppViewVarItemList,
variable_item_list_get_view(app->variable_item_list));
view_dispatcher_add_view(
app->view_dispatcher, DesktopSettingsAppViewIdPopup, popup_get_view(app->popup));
view_dispatcher_add_view(
@@ -63,10 +68,12 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
furi_assert(app);
// Variable item list
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
variable_item_list_free(app->variable_item_list);
submenu_free(app->submenu);
popup_free(app->popup);
desktop_view_pin_input_free(app->pin_input_view);

View File

@@ -5,6 +5,7 @@
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include "desktop_settings.h"
#include "desktop/views/desktop_view_pin_input.h"
@@ -13,6 +14,7 @@
typedef enum {
DesktopSettingsAppViewMenu,
DesktopSettingsAppViewVarItemList,
DesktopSettingsAppViewIdPopup,
DesktopSettingsAppViewIdPinInput,
DesktopSettingsAppViewIdPinSetupHowto,
@@ -25,6 +27,7 @@ typedef struct {
Gui* gui;
SceneManager* scene_manager;
ViewDispatcher* view_dispatcher;
VariableItemList* variable_item_list;
Submenu* submenu;
Popup* popup;
DesktopViewPinInput* pin_input_view;

View File

@@ -1,35 +1,65 @@
#include <applications.h>
#include <lib/toolbox/value_index.h>
#include "../desktop_settings_app.h"
#include "desktop_settings_scene.h"
#define SCENE_EVENT_SELECT_FAVORITE 0
#define SCENE_EVENT_SELECT_PIN_SETUP 1
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 2
static void desktop_settings_scene_start_submenu_callback(void* context, uint32_t index) {
#define AUTO_LOCK_DELAY_COUNT 6
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
"OFF",
"30s",
"60s",
"2min",
"5min",
"10min",
};
const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] =
{0, 30000, 60000, 120000, 300000, 600000};
static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) {
DesktopSettingsApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, index);
}
static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) {
DesktopSettingsApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, auto_lock_delay_text[index]);
app->settings.auto_lock_delay_ms = auto_lock_delay_value[index];
}
void desktop_settings_scene_start_on_enter(void* context) {
DesktopSettingsApp* app = context;
Submenu* submenu = app->submenu;
VariableItemList* variable_item_list = app->variable_item_list;
submenu_add_item(
submenu,
"Favorite App",
SCENE_EVENT_SELECT_FAVORITE,
desktop_settings_scene_start_submenu_callback,
VariableItem* item;
uint8_t value_index;
variable_item_list_add(variable_item_list, "Favorite App", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "PIN Setup", 1, NULL, NULL);
item = variable_item_list_add(
variable_item_list,
"Auto Lock Time",
AUTO_LOCK_DELAY_COUNT,
desktop_settings_scene_start_auto_lock_delay_changed,
app);
submenu_add_item(
submenu,
"PIN Setup",
SCENE_EVENT_SELECT_PIN_SETUP,
desktop_settings_scene_start_submenu_callback,
app);
variable_item_list_set_enter_callback(
variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app);
value_index = value_index_uint32(
app->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, auto_lock_delay_text[value_index]);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
}
bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent event) {
@@ -46,6 +76,9 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu);
consumed = true;
break;
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
consumed = true;
break;
}
}
return consumed;
@@ -53,5 +86,6 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
void desktop_settings_scene_start_on_exit(void* context) {
DesktopSettingsApp* app = context;
submenu_reset(app->submenu);
variable_item_list_reset(app->variable_item_list);
SAVE_DESKTOP_SETTINGS(&app->settings);
}

View File

@@ -48,17 +48,13 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
switch(event.event) {
case DesktopLockMenuEventLock:
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
desktop_lock(desktop);
consumed = true;
break;
case DesktopLockMenuEventPinLock:
if(desktop->settings.pin_code.length > 0) {
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
desktop_lock(desktop);
} else {
LoaderStatus status =
loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG);

View File

@@ -81,13 +81,13 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case DesktopLockedEventUnlocked:
furi_hal_rtc_set_pin_fails(0);
desktop_helpers_unlock_system(desktop);
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneMain);
desktop_unlock(desktop);
consumed = true;
break;
case DesktopLockedEventUpdate:
if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) {
notification_message(desktop->notification, &sequence_display_off);
}
desktop_view_locked_update(desktop->locked_view);
consumed = true;
break;

View File

@@ -129,16 +129,13 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
consumed = true;
break;
case DesktopPinInputEventUnlocked:
desktop_view_locked_unlock(desktop->locked_view);
furi_hal_rtc_set_pin_fails(0);
desktop_helpers_unlock_system(desktop);
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneMain);
desktop_unlock(desktop);
consumed = true;
break;
case DesktopPinInputEventBack:
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneLocked);
notification_message(desktop->notification, &sequence_display_off);
consumed = true;
break;
}

View File

@@ -38,4 +38,5 @@ typedef enum {
// Global events
DesktopGlobalBeforeAppStarted,
DesktopGlobalAfterAppFinished,
DesktopGlobalAutoLock,
} DesktopEvent;

View File

@@ -114,14 +114,8 @@ bool desktop_debug_input(InputEvent* event, void* context) {
DesktopViewStatsScreens current = 0;
with_view_model(
debug_view->view, (DesktopDebugViewModel * model) {
#if SRV_DOLPHIN_STATE_DEBUG == 1
if(event->key == InputKeyDown) {
model->screen = (model->screen + 1) % DesktopViewStatsTotalCount;
} else if(event->key == InputKeyUp) {
model->screen = ((model->screen - 1) + DesktopViewStatsTotalCount) %
DesktopViewStatsTotalCount;
}
#else
#ifdef SRV_DOLPHIN_STATE_DEBUG
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
model->screen = !model->screen;
}

View File

@@ -11,6 +11,7 @@
#include "desktop_view_locked.h"
#define DOOR_MOVING_INTERVAL_MS (1000 / 16)
#define LOCKED_HINT_TIMEOUT_MS (1000)
#define UNLOCKED_HINT_TIMEOUT_MS (2000)
#define DOOR_OFFSET_START -55
@@ -32,14 +33,18 @@ struct DesktopViewLocked {
uint32_t lock_lastpress;
};
typedef struct {
uint32_t hint_icon_expire_at;
bool unlocked_hint;
bool locked;
bool pin_locked;
typedef enum {
DesktopViewLockedStateUnlocked,
DesktopViewLockedStateLocked,
DesktopViewLockedStateDoorsClosing,
DesktopViewLockedStateLockedHintShown,
DesktopViewLockedStateUnlockedHintShown
} DesktopViewLockedState;
typedef struct {
bool pin_locked;
int8_t door_offset;
bool doors_closing;
DesktopViewLockedState view_state;
} DesktopViewLockedModel;
void desktop_view_locked_set_callback(
@@ -78,52 +83,55 @@ static bool desktop_view_locked_doors_move(DesktopViewLockedModel* model) {
static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* locked_view) {
DesktopViewLockedModel* model = view_get_model(locked_view->view);
model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
view_commit_model(locked_view->view, true);
const bool change_state = (model->view_state == DesktopViewLockedStateLocked) &&
!model->pin_locked;
if(change_state) {
model->view_state = DesktopViewLockedStateLockedHintShown;
}
view_commit_model(locked_view->view, change_state);
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(LOCKED_HINT_TIMEOUT_MS), portMAX_DELAY);
}
void desktop_view_locked_update(DesktopViewLocked* locked_view) {
bool stop_timer = false;
DesktopViewLockedModel* model = view_get_model(locked_view->view);
if(model->locked) {
model->doors_closing = desktop_view_locked_doors_move(model);
stop_timer = !model->doors_closing;
} else {
model->unlocked_hint = false;
stop_timer = true;
DesktopViewLockedState view_state = model->view_state;
if(view_state == DesktopViewLockedStateDoorsClosing &&
!desktop_view_locked_doors_move(model)) {
model->view_state = DesktopViewLockedStateLocked;
} else if(view_state == DesktopViewLockedStateLockedHintShown) {
model->view_state = DesktopViewLockedStateLocked;
} else if(view_state == DesktopViewLockedStateUnlockedHintShown) {
model->view_state = DesktopViewLockedStateUnlocked;
}
view_commit_model(locked_view->view, true);
if(stop_timer) {
if(view_state != DesktopViewLockedStateDoorsClosing) {
xTimerStop(locked_view->timer, portMAX_DELAY);
}
}
static void desktop_view_locked_draw(Canvas* canvas, void* model) {
DesktopViewLockedModel* m = model;
uint32_t now = osKernelGetTickCount();
DesktopViewLockedState view_state = m->view_state;
canvas_set_color(canvas, ColorBlack);
if(m->locked) {
if(m->doors_closing) {
if(view_state == DesktopViewLockedStateDoorsClosing) {
desktop_view_locked_doors_draw(canvas, m);
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked");
} else if((now < m->hint_icon_expire_at) && !m->pin_locked) {
} else if(view_state == DesktopViewLockedStateLockedHintShown) {
canvas_set_font(canvas, FontSecondary);
elements_bold_rounded_frame(canvas, 14, 2 + STATUS_BAR_Y_SHIFT, 99, 48);
elements_multiline_text(canvas, 65, 20 + STATUS_BAR_Y_SHIFT, "To unlock\npress:");
canvas_draw_icon(canvas, 65, 36 + STATUS_BAR_Y_SHIFT, &I_Back3_45x8);
canvas_draw_icon(canvas, 16, 7 + STATUS_BAR_Y_SHIFT, &I_WarningDolphin_45x42);
canvas_draw_dot(canvas, 17, 61);
}
} else {
if(m->unlocked_hint) {
} else if(view_state == DesktopViewLockedStateUnlockedHintShown) {
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked");
}
}
}
View* desktop_view_locked_get_view(DesktopViewLocked* locked_view) {
@@ -134,43 +142,38 @@ View* desktop_view_locked_get_view(DesktopViewLocked* locked_view) {
static bool desktop_view_locked_input(InputEvent* event, void* context) {
furi_assert(event);
furi_assert(context);
bool is_changed = false;
const uint32_t press_time = xTaskGetTickCount();
DesktopViewLocked* locked_view = context;
bool locked = false;
bool locked_with_pin = false;
bool doors_closing = false;
uint32_t press_time = xTaskGetTickCount();
{
DesktopViewLockedModel* model = view_get_model(locked_view->view);
bool changed = false;
locked = model->locked;
locked_with_pin = model->pin_locked;
doors_closing = model->doors_closing;
if(!locked && model->unlocked_hint && event->type == InputTypePress) {
model->unlocked_hint = false;
changed = true;
}
view_commit_model(locked_view->view, changed);
if(model->view_state == DesktopViewLockedStateUnlockedHintShown &&
event->type == InputTypePress) {
model->view_state = DesktopViewLockedStateUnlocked;
is_changed = true;
}
const DesktopViewLockedState view_state = model->view_state;
const bool pin_locked = model->pin_locked;
view_commit_model(locked_view->view, is_changed);
if(!locked || doors_closing || (event->type != InputTypeShort)) {
return locked;
}
if(locked_with_pin) {
if(view_state == DesktopViewLockedStateUnlocked || event->type != InputTypeShort) {
return view_state != DesktopViewLockedStateUnlocked;
} else if(view_state == DesktopViewLockedStateLocked && pin_locked) {
locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
} else {
} else if(
view_state == DesktopViewLockedStateLocked ||
view_state == DesktopViewLockedStateLockedHintShown) {
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
locked_view->lock_lastpress = press_time;
locked_view->lock_count = 0;
}
desktop_view_locked_update_hint_icon_timeout(locked_view);
if(event->key == InputKeyBack) {
locked_view->lock_lastpress = press_time;
locked_view->lock_count++;
if(locked_view->lock_count == UNLOCK_CNT) {
desktop_view_locked_unlock(locked_view);
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
}
} else {
@@ -180,7 +183,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
locked_view->lock_lastpress = press_time;
}
return locked;
return true;
}
DesktopViewLocked* desktop_view_locked_alloc() {
@@ -189,7 +192,6 @@ DesktopViewLocked* desktop_view_locked_alloc() {
locked_view->timer =
xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
locked_view->view = view_alloc();
view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopViewLockedModel));
view_set_context(locked_view->view, locked_view);
view_set_draw_callback(locked_view->view, desktop_view_locked_draw);
@@ -207,7 +209,8 @@ void desktop_view_locked_free(DesktopViewLocked* locked_view) {
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) {
DesktopViewLockedModel* model = view_get_model(locked_view->view);
model->doors_closing = true;
furi_assert(model->view_state == DesktopViewLockedStateLocked);
model->view_state = DesktopViewLockedStateDoorsClosing;
model->door_offset = DOOR_OFFSET_START;
view_commit_model(locked_view->view, true);
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(DOOR_MOVING_INTERVAL_MS), portMAX_DELAY);
@@ -215,19 +218,24 @@ void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) {
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) {
DesktopViewLockedModel* model = view_get_model(locked_view->view);
model->locked = true;
furi_assert(model->view_state == DesktopViewLockedStateUnlocked);
model->view_state = DesktopViewLockedStateLocked;
model->pin_locked = pin_locked;
view_commit_model(locked_view->view, true);
}
void desktop_view_locked_unlock(DesktopViewLocked* locked_view) {
furi_assert(locked_view);
locked_view->lock_count = 0;
DesktopViewLockedModel* model = view_get_model(locked_view->view);
model->locked = false;
model->view_state = DesktopViewLockedStateUnlockedHintShown;
model->pin_locked = false;
model->unlocked_hint = true;
view_commit_model(locked_view->view, true);
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(UNLOCKED_HINT_TIMEOUT_MS), portMAX_DELAY);
}
bool desktop_view_locked_is_locked_hint_visible(DesktopViewLocked* locked_view) {
DesktopViewLockedModel* model = view_get_model(locked_view->view);
const DesktopViewLockedState view_state = model->view_state;
view_commit_model(locked_view->view, false);
return view_state == DesktopViewLockedStateLockedHintShown;
}

View File

@@ -19,3 +19,4 @@ void desktop_view_locked_free(DesktopViewLocked* locked_view);
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked);
void desktop_view_locked_unlock(DesktopViewLocked* locked_view);
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view);
bool desktop_view_locked_is_locked_hint_visible(DesktopViewLocked* locked_view);

View File

@@ -9,7 +9,9 @@
#include "scene/ibutton_scene_read_crc_error.h"
#include "scene/ibutton_scene_read_not_key_error.h"
#include "scene/ibutton_scene_read_success.h"
#include "scene/ibutton_scene_readed_key_menu.h"
#include "scene/ibutton_scene_retry_confirm.h"
#include "scene/ibutton_scene_exit_confirm.h"
#include "scene/ibutton_scene_read_key_menu.h"
#include "scene/ibutton_scene_write.h"
#include "scene/ibutton_scene_write_success.h"
#include "scene/ibutton_scene_saved_key_menu.h"
@@ -42,7 +44,9 @@ public:
SceneReadNotKeyError,
SceneReadCRCError,
SceneReadSuccess,
SceneReadedKeyMenu,
SceneRetryConfirm,
SceneExitConfirm,
SceneReadKeyMenu,
SceneWrite,
SceneWriteSuccess,
SceneEmulate,
@@ -105,7 +109,9 @@ private:
{Scene::SceneReadCRCError, new iButtonSceneReadCRCError()},
{Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()},
{Scene::SceneReadSuccess, new iButtonSceneReadSuccess()},
{Scene::SceneReadedKeyMenu, new iButtonSceneReadedKeyMenu()},
{Scene::SceneRetryConfirm, new iButtonSceneRetryConfirm()},
{Scene::SceneExitConfirm, new iButtonSceneExitConfirm()},
{Scene::SceneReadKeyMenu, new iButtonSceneReadKeyMenu()},
{Scene::SceneWrite, new iButtonSceneWrite()},
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
{Scene::SceneEmulate, new iButtonSceneEmulate()},

View File

@@ -14,7 +14,7 @@ void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) {
Popup* popup = view_manager->get_popup();
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
popup_set_text(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
popup_set_callback(popup, popup_callback);
popup_set_context(popup, app);

View File

@@ -0,0 +1,51 @@
#include "ibutton_scene_exit_confirm.h"
#include "../ibutton_app.h"
static void widget_callback(GuiButtonType result, InputType type, void* context) {
furi_assert(context);
iButtonApp* app = static_cast<iButtonApp*>(context);
iButtonEvent event;
if(type == InputTypeShort) {
event.type = iButtonEvent::Type::EventTypeWidgetButtonResult;
event.payload.widget_button_result = result;
app->get_view_manager()->send_event(&event);
}
}
void iButtonSceneExitConfirm::on_enter(iButtonApp* app) {
iButtonAppViewManager* view_manager = app->get_view_manager();
Widget* widget = view_manager->get_widget();
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", widget_callback, app);
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", widget_callback, app);
widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu");
widget_add_string_element(
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
}
bool iButtonSceneExitConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
bool consumed = false;
if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) {
if(event->payload.widget_button_result == GuiButtonTypeLeft) {
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart});
} else if(event->payload.widget_button_result == GuiButtonTypeRight) {
app->switch_to_previous_scene();
}
consumed = true;
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
consumed = true;
}
return consumed;
}
void iButtonSceneExitConfirm::on_exit(iButtonApp* app) {
iButtonAppViewManager* view_manager = app->get_view_manager();
Widget* widget = view_manager->get_widget();
widget_reset(widget);
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "ibutton_scene_generic.h"
class iButtonSceneExitConfirm : public iButtonScene {
public:
void on_enter(iButtonApp* app) final;
bool on_event(iButtonApp* app, iButtonEvent* event) final;
void on_exit(iButtonApp* app) final;
};

View File

@@ -34,15 +34,22 @@ bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) {
consumed = true;
iButtonKey* key = app->get_key();
bool success = false;
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
if(!ibutton_key_dallas_crc_is_valid(key)) {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError);
} else if(!ibutton_key_dallas_is_1990_key(key)) {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError);
} else {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
success = true;
}
} else {
success = true;
}
if(success) {
app->notify_success();
app->notify_green_on();
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
}
} else if(event->type == iButtonEvent::Type::EventTypeTick) {

View File

@@ -47,7 +47,7 @@ bool iButtonSceneReadCRCError::on_event(iButtonApp* app, iButtonEvent* event) {
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
if(event->payload.dialog_result == DialogExResultRight) {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
} else {
app->switch_to_previous_scene();
}

View File

@@ -1,11 +1,10 @@
#include "ibutton_scene_readed_key_menu.h"
#include "ibutton_scene_read_key_menu.h"
#include "../ibutton_app.h"
typedef enum {
SubmenuIndexWrite,
SubmenuIndexEmulate,
SubmenuIndexSave,
SubmenuIndexReadNewKey,
} SubmenuIndex;
static void submenu_callback(void* context, uint32_t index) {
@@ -19,7 +18,7 @@ static void submenu_callback(void* context, uint32_t index) {
app->get_view_manager()->send_event(&event);
}
void iButtonSceneReadedKeyMenu::on_enter(iButtonApp* app) {
void iButtonSceneReadKeyMenu::on_enter(iButtonApp* app) {
iButtonAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
@@ -28,13 +27,12 @@ void iButtonSceneReadedKeyMenu::on_enter(iButtonApp* app) {
}
submenu_add_item(submenu, "Save", SubmenuIndexSave, submenu_callback, app);
submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app);
submenu_add_item(submenu, "Read new key", SubmenuIndexReadNewKey, submenu_callback, app);
submenu_set_selected_item(submenu, submenu_item_selected);
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
}
bool iButtonSceneReadedKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
bool iButtonSceneReadKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
bool consumed = false;
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
@@ -49,20 +47,17 @@ bool iButtonSceneReadedKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
case SubmenuIndexSave:
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName);
break;
case SubmenuIndexReadNewKey:
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneRead});
break;
}
consumed = true;
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart});
app->switch_to_previous_scene();
consumed = true;
}
return consumed;
}
void iButtonSceneReadedKeyMenu::on_exit(iButtonApp* app) {
void iButtonSceneReadKeyMenu::on_exit(iButtonApp* app) {
iButtonAppViewManager* view = app->get_view_manager();
Submenu* submenu = view->get_submenu();

View File

@@ -1,7 +1,7 @@
#pragma once
#include "ibutton_scene_generic.h"
class iButtonSceneReadedKeyMenu : public iButtonScene {
class iButtonSceneReadKeyMenu : public iButtonScene {
public:
void on_enter(iButtonApp* app) final;
bool on_event(iButtonApp* app, iButtonEvent* event) final;

View File

@@ -47,7 +47,7 @@ bool iButtonSceneReadNotKeyError::on_event(iButtonApp* app, iButtonEvent* event)
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
if(event->payload.dialog_result == DialogExResultRight) {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
} else {
app->switch_to_previous_scene();
}

View File

@@ -18,7 +18,6 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) {
DialogEx* dialog_ex = view_manager->get_dialog_ex();
iButtonKey* key = app->get_key();
const uint8_t* key_data = ibutton_key_get_data_p(key);
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
switch(ibutton_key_get_type(key)) {
case iButtonKeyDS1990:
@@ -50,9 +49,6 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) {
dialog_ex_set_context(dialog_ex, app);
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
app->notify_success();
app->notify_green_on();
}
bool iButtonSceneReadSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
@@ -60,11 +56,13 @@ bool iButtonSceneReadSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
if(event->payload.dialog_result == DialogExResultRight) {
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
} else {
app->switch_to_previous_scene();
app->switch_to_next_scene(iButtonApp::Scene::SceneRetryConfirm);
}
consumed = true;
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
app->switch_to_next_scene(iButtonApp::Scene::SceneExitConfirm);
consumed = true;
}

View File

@@ -0,0 +1,51 @@
#include "ibutton_scene_retry_confirm.h"
#include "../ibutton_app.h"
static void widget_callback(GuiButtonType result, InputType type, void* context) {
furi_assert(context);
iButtonApp* app = static_cast<iButtonApp*>(context);
iButtonEvent event;
if(type == InputTypeShort) {
event.type = iButtonEvent::Type::EventTypeWidgetButtonResult;
event.payload.widget_button_result = result;
app->get_view_manager()->send_event(&event);
}
}
void iButtonSceneRetryConfirm::on_enter(iButtonApp* app) {
iButtonAppViewManager* view_manager = app->get_view_manager();
Widget* widget = view_manager->get_widget();
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", widget_callback, app);
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", widget_callback, app);
widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
widget_add_string_element(
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
}
bool iButtonSceneRetryConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
bool consumed = false;
if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) {
if(event->payload.widget_button_result == GuiButtonTypeLeft) {
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneRead});
} else if(event->payload.widget_button_result == GuiButtonTypeRight) {
app->switch_to_previous_scene();
}
consumed = true;
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
consumed = true;
}
return consumed;
}
void iButtonSceneRetryConfirm::on_exit(iButtonApp* app) {
iButtonAppViewManager* view_manager = app->get_view_manager();
Widget* widget = view_manager->get_widget();
widget_reset(widget);
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "ibutton_scene_generic.h"
class iButtonSceneRetryConfirm : public iButtonScene {
public:
void on_enter(iButtonApp* app) final;
bool on_event(iButtonApp* app, iButtonEvent* event) final;
void on_exit(iButtonApp* app) final;
};

View File

@@ -49,7 +49,7 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) {
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
} else {
app->search_and_switch_to_previous_scene(
{iButtonApp::Scene::SceneReadedKeyMenu,
{iButtonApp::Scene::SceneReadKeyMenu,
iButtonApp::Scene::SceneSavedKeyMenu,
iButtonApp::Scene::SceneAddType});
}

View File

@@ -16,7 +16,7 @@ void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) {
DOLPHIN_DEED(DolphinDeedIbuttonSave);
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_text(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
popup_set_callback(popup, popup_callback);
popup_set_context(popup, app);
@@ -31,7 +31,7 @@ bool iButtonSceneSaveSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
if(event->type == iButtonEvent::Type::EventTypeBack) {
app->search_and_switch_to_previous_scene(
{iButtonApp::Scene::SceneReadedKeyMenu,
{iButtonApp::Scene::SceneReadKeyMenu,
iButtonApp::Scene::SceneSavedKeyMenu,
iButtonApp::Scene::SceneAddType});
consumed = true;

View File

@@ -33,7 +33,7 @@ bool iButtonSceneWriteSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
if(event->type == iButtonEvent::Type::EventTypeBack) {
app->search_and_switch_to_previous_scene(
{iButtonApp::Scene::SceneReadedKeyMenu, iButtonApp::Scene::SceneStart});
{iButtonApp::Scene::SceneReadKeyMenu, iButtonApp::Scene::SceneStart});
consumed = true;
}

View File

@@ -5,7 +5,6 @@ void InfraredAppSceneEditRenameDone::on_enter(InfraredApp* app) {
Popup* popup = view_manager->get_popup();
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
popup_set_callback(popup, InfraredApp::popup_callback);

View File

@@ -15,7 +15,7 @@ constexpr uint32_t long_time_high = long_time + jitter_time;
void DecoderEMMarin::reset_state() {
ready = false;
readed_data = 0;
read_data = 0;
manchester_advance(
manchester_saved_state, ManchesterEventReset, &manchester_saved_state, nullptr);
}
@@ -26,7 +26,7 @@ bool DecoderEMMarin::read(uint8_t* data, uint8_t data_size) {
if(ready) {
result = true;
em_marin.decode(
reinterpret_cast<const uint8_t*>(&readed_data), sizeof(uint64_t), data, data_size);
reinterpret_cast<const uint8_t*>(&read_data), sizeof(uint64_t), data, data_size);
ready = false;
}
@@ -59,10 +59,10 @@ void DecoderEMMarin::process_front(bool polarity, uint32_t time) {
manchester_advance(manchester_saved_state, event, &manchester_saved_state, &data);
if(data_ok) {
readed_data = (readed_data << 1) | data;
read_data = (read_data << 1) | data;
ready = em_marin.can_be_decoded(
reinterpret_cast<const uint8_t*>(&readed_data), sizeof(uint64_t));
reinterpret_cast<const uint8_t*>(&read_data), sizeof(uint64_t));
}
}
}

View File

@@ -13,7 +13,7 @@ public:
private:
void reset_state();
uint64_t readed_data = 0;
uint64_t read_data = 0;
std::atomic<bool> ready;
ManchesterState manchester_saved_state;

View File

@@ -78,7 +78,7 @@ void RfidReader::start() {
start_comparator();
switch_timer_reset();
last_readed_count = 0;
last_read_count = 0;
}
void RfidReader::start_forced(RfidReader::Type _type) {
@@ -97,45 +97,45 @@ void RfidReader::stop() {
bool RfidReader::read(LfrfidKeyType* _type, uint8_t* data, uint8_t data_size, bool switch_enable) {
bool result = false;
bool something_readed = false;
bool something_read = false;
// reading
if(decoder_em.read(data, data_size)) {
*_type = LfrfidKeyType::KeyEM4100;
something_readed = true;
something_read = true;
}
if(decoder_hid26.read(data, data_size)) {
*_type = LfrfidKeyType::KeyH10301;
something_readed = true;
something_read = true;
}
if(decoder_indala.read(data, data_size)) {
*_type = LfrfidKeyType::KeyI40134;
something_readed = true;
something_read = true;
}
// validation
if(something_readed) {
if(something_read) {
switch_timer_reset();
if(last_readed_type == *_type && memcmp(last_readed_data, data, data_size) == 0) {
last_readed_count = last_readed_count + 1;
if(last_read_type == *_type && memcmp(last_read_data, data, data_size) == 0) {
last_read_count = last_read_count + 1;
if(last_readed_count > 2) {
if(last_read_count > 2) {
result = true;
}
} else {
last_readed_type = *_type;
memcpy(last_readed_data, data, data_size);
last_readed_count = 0;
last_read_type = *_type;
memcpy(last_read_data, data, data_size);
last_read_count = 0;
}
}
// mode switching
if(switch_enable && switch_timer_elapsed()) {
switch_mode();
last_readed_count = 0;
last_read_count = 0;
}
return result;
@@ -152,7 +152,7 @@ bool RfidReader::detect() {
}
bool RfidReader::any_read() {
return last_readed_count > 0;
return last_read_count > 0;
}
void RfidReader::start_comparator(void) {

View File

@@ -49,9 +49,9 @@ private:
void switch_timer_reset();
void switch_mode();
LfrfidKeyType last_readed_type;
uint8_t last_readed_data[LFRFID_KEY_SIZE];
uint8_t last_readed_count;
LfrfidKeyType last_read_type;
uint8_t last_read_data[LFRFID_KEY_SIZE];
uint8_t last_read_count;
Type type = Type::Normal;
};

View File

@@ -2,7 +2,9 @@
#include "scene/lfrfid_app_scene_start.h"
#include "scene/lfrfid_app_scene_read.h"
#include "scene/lfrfid_app_scene_read_success.h"
#include "scene/lfrfid_app_scene_readed_menu.h"
#include "scene/lfrfid_app_scene_retry_confirm.h"
#include "scene/lfrfid_app_scene_exit_confirm.h"
#include "scene/lfrfid_app_scene_read_menu.h"
#include "scene/lfrfid_app_scene_write.h"
#include "scene/lfrfid_app_scene_write_success.h"
#include "scene/lfrfid_app_scene_emulate.h"
@@ -48,8 +50,10 @@ void LfRfidApp::run(void* _args) {
} else {
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
scene_controller.add_scene(SceneType::ExitConfirm, new LfRfidAppSceneExitConfirm());
scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess());
scene_controller.add_scene(SceneType::ReadedMenu, new LfRfidAppSceneReadedMenu());
scene_controller.add_scene(SceneType::ReadKeyMenu, new LfRfidAppSceneReadKeyMenu());
scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite());
scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());

View File

@@ -27,13 +27,17 @@ public:
GENERIC_EVENT_ENUM_VALUES,
Next,
MenuSelected,
Stay,
Retry,
};
enum class SceneType : uint8_t {
GENERIC_SCENE_ENUM_VALUES,
Read,
ReadSuccess,
ReadedMenu,
RetryConfirm,
ExitConfirm,
ReadKeyMenu,
Write,
WriteSuccess,
Emulate,

View File

@@ -73,6 +73,11 @@ bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* eve
app->delete_key(&app->worker.key);
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
consumed = true;
} else if(event->type == LfRfidApp::EventType::Stay) {
app->scene_controller.switch_to_previous_scene();
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
consumed = true;
}
return consumed;
@@ -88,7 +93,7 @@ void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) {
void LfRfidAppSceneDeleteConfirm::back_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Back;
event.type = LfRfidApp::EventType::Stay;
app->view_controller.send_event(&event);
}

View File

@@ -4,7 +4,7 @@ void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool need_restore) {
auto popup = app->view_controller.get<PopupVM>();
popup->set_icon(0, 2, &I_DolphinMafia_115x62);
popup->set_text("Deleted", 83, 19, AlignLeft, AlignBottom);
popup->set_header("Deleted", 83, 19, AlignLeft, AlignBottom);
popup->set_context(app);
popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback);
popup->set_timeout(1500);

View File

@@ -0,0 +1,59 @@
#include "lfrfid_app_scene_exit_confirm.h"
#include "../view/elements/button_element.h"
#include "../view/elements/icon_element.h"
#include "../view/elements/string_element.h"
void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool need_restore) {
auto container = app->view_controller.get<ContainerVM>();
auto button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Left, "Exit");
button->set_callback(app, LfRfidAppSceneExitConfirm::exit_callback);
button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Right, "Stay");
button->set_callback(app, LfRfidAppSceneExitConfirm::stay_callback);
auto line_1 = container->add<StringElement>();
auto line_2 = container->add<StringElement>();
line_1->set_text("Exit to RFID menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_2->set_text(
"All unsaved data will be lost", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
app->view_controller.switch_to<ContainerVM>();
}
bool LfRfidAppSceneExitConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::Next) {
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
consumed = true;
} else if(event->type == LfRfidApp::EventType::Stay) {
app->scene_controller.switch_to_previous_scene();
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
consumed = true;
}
return consumed;
}
void LfRfidAppSceneExitConfirm::on_exit(LfRfidApp* app) {
app->view_controller.get<ContainerVM>()->clean();
}
void LfRfidAppSceneExitConfirm::exit_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Next;
app->view_controller.send_event(&event);
}
void LfRfidAppSceneExitConfirm::stay_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Stay;
app->view_controller.send_event(&event);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../lfrfid_app.h"
class LfRfidAppSceneExitConfirm : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
void on_exit(LfRfidApp* app) final;
private:
static void exit_callback(void* context);
static void stay_callback(void* context);
};

View File

@@ -1,4 +1,4 @@
#include "lfrfid_app_scene_readed_menu.h"
#include "lfrfid_app_scene_read_menu.h"
typedef enum {
SubmenuWrite,
@@ -6,7 +6,7 @@ typedef enum {
SubmenuEmulate,
} SubmenuIndex;
void LfRfidAppSceneReadedMenu::on_enter(LfRfidApp* app, bool need_restore) {
void LfRfidAppSceneReadKeyMenu::on_enter(LfRfidApp* app, bool need_restore) {
auto submenu = app->view_controller.get<SubmenuVM>();
submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
@@ -20,7 +20,7 @@ void LfRfidAppSceneReadedMenu::on_enter(LfRfidApp* app, bool need_restore) {
app->view_controller.switch_to<SubmenuVM>();
}
bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool LfRfidAppSceneReadKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::MenuSelected) {
@@ -38,18 +38,18 @@ bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event)
}
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
app->scene_controller.switch_to_previous_scene();
consumed = true;
}
return consumed;
}
void LfRfidAppSceneReadedMenu::on_exit(LfRfidApp* app) {
void LfRfidAppSceneReadKeyMenu::on_exit(LfRfidApp* app) {
app->view_controller.get<SubmenuVM>()->clean();
}
void LfRfidAppSceneReadedMenu::submenu_callback(void* context, uint32_t index) {
void LfRfidAppSceneReadKeyMenu::submenu_callback(void* context, uint32_t index) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;

View File

@@ -1,7 +1,7 @@
#pragma once
#include "../lfrfid_app.h"
class LfRfidAppSceneReadedMenu : public GenericScene<LfRfidApp> {
class LfRfidAppSceneReadKeyMenu : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;

View File

@@ -85,7 +85,13 @@ bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event
bool consumed = false;
if(event->type == LfRfidApp::EventType::Next) {
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadedMenu);
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadKeyMenu);
consumed = true;
} else if(event->type == LfRfidApp::EventType::Retry) {
app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::RetryConfirm});
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::ExitConfirm});
consumed = true;
}
@@ -103,7 +109,7 @@ void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Back;
event.type = LfRfidApp::EventType::Retry;
app->view_controller.send_event(&event);
}

View File

@@ -0,0 +1,59 @@
#include "lfrfid_app_scene_retry_confirm.h"
#include "../view/elements/button_element.h"
#include "../view/elements/icon_element.h"
#include "../view/elements/string_element.h"
void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool need_restore) {
auto container = app->view_controller.get<ContainerVM>();
auto button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Left, "Exit");
button->set_callback(app, LfRfidAppSceneRetryConfirm::exit_callback);
button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Right, "Stay");
button->set_callback(app, LfRfidAppSceneRetryConfirm::stay_callback);
auto line_1 = container->add<StringElement>();
auto line_2 = container->add<StringElement>();
line_1->set_text("Return to reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_2->set_text(
"All unsaved data will be lost", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
app->view_controller.switch_to<ContainerVM>();
}
bool LfRfidAppSceneRetryConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::Next) {
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Read});
consumed = true;
} else if(event->type == LfRfidApp::EventType::Stay) {
app->scene_controller.switch_to_previous_scene();
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
consumed = true;
}
return consumed;
}
void LfRfidAppSceneRetryConfirm::on_exit(LfRfidApp* app) {
app->view_controller.get<ContainerVM>()->clean();
}
void LfRfidAppSceneRetryConfirm::exit_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Next;
app->view_controller.send_event(&event);
}
void LfRfidAppSceneRetryConfirm::stay_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Stay;
app->view_controller.send_event(&event);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../lfrfid_app.h"
class LfRfidAppSceneRetryConfirm : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
void on_exit(LfRfidApp* app) final;
private:
static void exit_callback(void* context);
static void stay_callback(void* context);
};

View File

@@ -42,7 +42,7 @@ bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
} else {
app->scene_controller.search_and_switch_to_previous_scene(
{LfRfidApp::SceneType::ReadedMenu});
{LfRfidApp::SceneType::ReadKeyMenu});
}
}

View File

@@ -8,7 +8,7 @@ void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool need_restore) {
DOLPHIN_DEED(DolphinDeedRfidSave);
popup->set_icon(32, 5, &I_DolphinNice_96x59);
popup->set_text("Saved!", 13, 22, AlignLeft, AlignBottom);
popup->set_header("Saved!", 5, 7, AlignLeft, AlignTop);
popup->set_context(app);
popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback);
popup->set_timeout(1500);
@@ -22,11 +22,11 @@ bool LfRfidAppSceneSaveSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event
if(event->type == LfRfidApp::EventType::Back) {
bool result = app->scene_controller.has_previous_scene(
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
if(result) {
app->scene_controller.search_and_switch_to_previous_scene(
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
} else {
app->scene_controller.search_and_switch_to_another_scene(
{LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey);

View File

@@ -18,7 +18,7 @@ bool LfRfidAppSceneWriteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* even
if(event->type == LfRfidApp::EventType::Back) {
app->scene_controller.search_and_switch_to_previous_scene(
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
consumed = true;
}

View File

@@ -1,6 +1,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <storage/storage.h>
#include <input/input.h>
#include "notification.h"
#include "notification_messages.h"
#include "notification_app.h"
@@ -163,7 +164,6 @@ void notification_process_notification_message(
notification_message = (*message->sequence)[notification_message_index];
bool led_active = false;
uint8_t display_led_lock = 0;
uint8_t led_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00};
bool reset_notifications = true;
float speaker_volume_setting = app->settings.speaker_volume;
@@ -191,18 +191,18 @@ void notification_process_notification_message(
reset_mask |= reset_display_mask;
break;
case NotificationMessageTypeLedDisplayLock:
furi_assert(display_led_lock < UINT8_MAX);
display_led_lock++;
if(display_led_lock == 1) {
furi_assert(app->display_led_lock < UINT8_MAX);
app->display_led_lock++;
if(app->display_led_lock == 1) {
notification_apply_internal_led_layer(
&app->display,
notification_message->data.led.value * display_brightness_setting);
}
break;
case NotificationMessageTypeLedDisplayUnlock:
furi_assert(display_led_lock > 0);
display_led_lock--;
if(display_led_lock == 0) {
furi_assert(app->display_led_lock > 0);
app->display_led_lock--;
if(app->display_led_lock == 0) {
notification_apply_internal_led_layer(
&app->display,
notification_message->data.led.value * display_brightness_setting);
@@ -416,8 +416,13 @@ static bool notification_save_settings(NotificationApp* app) {
};
static void input_event_callback(const void* value, void* context) {
furi_assert(value);
furi_assert(context);
const InputEvent* event = value;
NotificationApp* app = context;
if(event->type == InputTypePress) {
notification_message(app, &sequence_display_on);
}
}
// App alloc

View File

@@ -49,6 +49,7 @@ struct NotificationApp {
NotificationLedLayer display;
NotificationLedLayer led[NOTIFICATION_LED_COUNT];
uint8_t display_led_lock;
NotificationSettings settings;
};

View File

@@ -21,7 +21,7 @@ const NotificationMessage message_display_lock = {
};
const NotificationMessage message_display_unlock = {
.type = NotificationMessageTypeLedDisplayLock,
.type = NotificationMessageTypeLedDisplayUnlock,
.data.led.value = 0x00,
};
@@ -208,6 +208,12 @@ const NotificationSequence sequence_display_unlock = {
NULL,
};
const NotificationSequence sequence_display_off_delay_1000 = {
&message_delay_1000,
&message_display_off,
NULL,
};
// Charging
const NotificationSequence sequence_charging = {
&message_red_255,

View File

@@ -78,6 +78,8 @@ extern const NotificationSequence sequence_display_off;
extern const NotificationSequence sequence_display_lock;
/** Display: backlight always on unlock */
extern const NotificationSequence sequence_display_unlock;
/** Display: backlight force off after a delay of 1000ms */
extern const NotificationSequence sequence_display_off_delay_1000;
// Charging
extern const NotificationSequence sequence_charging;

View File

@@ -2,6 +2,7 @@
#include "notification_app.h"
#include <gui/modules/variable_item_list.h>
#include <gui/view_dispatcher.h>
#include <lib/toolbox/value_index.h>
#define MAX_NOTIFICATION_SETTINGS 4
@@ -63,44 +64,6 @@ const char* const vibro_text[VIBRO_COUNT] = {
};
const bool vibro_value[VIBRO_COUNT] = {false, true};
uint8_t float_value_index(const float value, const float values[], uint8_t values_count) {
const float epsilon = 0.01f;
float last_value = values[0];
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if((value >= last_value - epsilon) && (value <= values[i] + epsilon)) {
index = i;
break;
}
last_value = values[i];
}
return index;
}
uint8_t uint32_value_index(const uint32_t value, const uint32_t values[], uint8_t values_count) {
int64_t last_value = INT64_MIN;
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if((value >= last_value) && (value <= values[i])) {
index = i;
break;
}
last_value = values[i];
}
return index;
}
uint8_t bool_value_index(const bool value, const bool values[], uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}
static void backlight_changed(VariableItem* item) {
NotificationAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -164,21 +127,21 @@ static NotificationAppSettings* alloc_settings() {
item = variable_item_list_add(
app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
value_index = float_value_index(
value_index = value_index_float(
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, backlight_text[value_index]);
item = variable_item_list_add(
app->variable_item_list, "Backlight Time", DELAY_COUNT, screen_changed, app);
value_index = uint32_value_index(
value_index = value_index_uint32(
app->notification->settings.display_off_delay_ms, delay_value, DELAY_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, delay_text[value_index]);
item = variable_item_list_add(
app->variable_item_list, "LED Brightness", BACKLIGHT_COUNT, led_changed, app);
value_index = float_value_index(
value_index = value_index_float(
app->notification->settings.led_brightness, backlight_value, BACKLIGHT_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, backlight_text[value_index]);
@@ -186,13 +149,13 @@ static NotificationAppSettings* alloc_settings() {
item = variable_item_list_add(
app->variable_item_list, "Volume", VOLUME_COUNT, volume_changed, app);
value_index =
float_value_index(app->notification->settings.speaker_volume, volume_value, VOLUME_COUNT);
value_index_float(app->notification->settings.speaker_volume, volume_value, VOLUME_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, volume_text[value_index]);
item =
variable_item_list_add(app->variable_item_list, "Vibro", VIBRO_COUNT, vibro_changed, app);
value_index = bool_value_index(app->notification->settings.vibro_on, vibro_value, VIBRO_COUNT);
value_index = value_index_bool(app->notification->settings.vibro_on, vibro_value, VIBRO_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, vibro_text[value_index]);

View File

@@ -473,17 +473,17 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
File* file = storage_file_alloc(fs_api);
if(storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) {
const uint16_t read_size = 512;
const uint16_t size_to_read = 512;
const uint8_t hash_size = 16;
uint8_t* data = malloc(read_size);
uint8_t* data = malloc(size_to_read);
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
md5_context* md5_ctx = malloc(sizeof(md5_context));
md5_starts(md5_ctx);
while(true) {
uint16_t readed_size = storage_file_read(file, data, read_size);
if(readed_size == 0) break;
md5_update(md5_ctx, data, readed_size);
uint16_t read_size = storage_file_read(file, data, size_to_read);
if(read_size == 0) break;
md5_update(md5_ctx, data, read_size);
}
md5_finish(md5_ctx, hash);
free(md5_ctx);

View File

@@ -33,14 +33,14 @@ struct File {
* @param file pointer to file object
* @param buff pointer to buffer for reading
* @param bytes_to_read how many bytes to read, must be smaller or equal to buffer size
* @return how many bytes actually has been readed
* @return how many bytes actually has been read
*
* @var FS_File_Api::write
* @brief Write bytes from buffer to file
* @param file pointer to file object
* @param buff pointer to buffer for writing
* @param bytes_to_read how many bytes to write, must be smaller or equal to buffer size
* @return how many bytes actually has been writed
* @return how many bytes actually has been written
*
* @var FS_File_Api::seek
* @brief Move r/w pointer
@@ -107,7 +107,7 @@ typedef struct {
* @var FS_Dir_Api::read
* @brief Read next object info in directory
* @param file pointer to file object
* @param fileinfo pointer to readed FileInfo, can be NULL
* @param fileinfo pointer to read FileInfo, can be NULL
* @param name pointer to name buffer, can be NULL
* @param name_length name buffer length
* @return success flag (if next object not exist also returns false and set error_id to FSE_NOT_EXIST)
@@ -133,7 +133,7 @@ typedef struct {
* @var FS_Common_Api::stat
* @brief Open directory to get objects from
* @param path path to file/directory
* @param fileinfo pointer to readed FileInfo, can be NULL
* @param fileinfo pointer to read FileInfo, can be NULL
* @param name pointer to name buffer, can be NULL
* @param name_length name buffer length
* @return FS_Error error info

View File

@@ -76,7 +76,7 @@ bool storage_file_is_dir(File* file);
* @param file pointer to file object.
* @param buff pointer to a buffer, for reading
* @param bytes_to_read how many bytes to read. Must be less than or equal to the size of the buffer.
* @return uint16_t how many bytes were actually readed
* @return uint16_t how many bytes were actually read
*/
uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read);
@@ -144,7 +144,7 @@ bool storage_dir_close(File* file);
/** Reads the next object in the directory
* @param file pointer to file object.
* @param fileinfo pointer to the readed FileInfo, may be NULL
* @param fileinfo pointer to the read FileInfo, may be NULL
* @param name pointer to name buffer, may be NULL
* @param name_length name buffer length
* @return success flag (if the next object does not exist, it also returns false and sets the file error id to FSE_NOT_EXIST)
@@ -162,7 +162,7 @@ bool storage_dir_rewind(File* file);
/** Retrieves information about a file/directory
* @param app pointer to the api
* @param path path to file/directory
* @param fileinfo pointer to the readed FileInfo, may be NULL
* @param fileinfo pointer to the read FileInfo, may be NULL
* @return FS_Error operation result
*/
FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo);

View File

@@ -112,10 +112,10 @@ static void storage_cli_list(Cli* cli, string_t path) {
if(storage_dir_open(file, string_get_cstr(path))) {
FileInfo fileinfo;
char name[MAX_NAME_LENGTH];
bool readed = false;
bool read_done = false;
while(storage_dir_read(file, &fileinfo, name, MAX_NAME_LENGTH)) {
readed = true;
read_done = true;
if(fileinfo.flags & FSF_DIRECTORY) {
printf("\t[D] %s\r\n", name);
} else {
@@ -123,7 +123,7 @@ static void storage_cli_list(Cli* cli, string_t path) {
}
}
if(!readed) {
if(!read_done) {
printf("\tEmpty\r\n");
}
} else {
@@ -141,18 +141,18 @@ static void storage_cli_read(Cli* cli, string_t path) {
File* file = storage_file_alloc(api);
if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
const uint16_t read_size = 128;
uint16_t readed_size = 0;
const uint16_t size_to_read = 128;
uint16_t read_size = 0;
uint8_t* data = malloc(read_size);
printf("Size: %lu\r\n", (uint32_t)storage_file_size(file));
do {
readed_size = storage_file_read(file, data, read_size);
for(uint16_t i = 0; i < readed_size; i++) {
read_size = storage_file_read(file, data, size_to_read);
for(uint16_t i = 0; i < read_size; i++) {
printf("%c", data[i]);
}
} while(readed_size > 0);
} while(read_size > 0);
printf("\r\n");
free(data);
@@ -176,33 +176,33 @@ static void storage_cli_write(Cli* cli, string_t path) {
if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) {
printf("Just write your text data. New line by Ctrl+Enter, exit by Ctrl+C.\r\n");
uint32_t readed_index = 0;
uint32_t read_index = 0;
while(true) {
uint8_t symbol = cli_getc(cli);
if(symbol == CliSymbolAsciiETX) {
uint16_t write_size = readed_index % buffer_size;
uint16_t write_size = read_index % buffer_size;
if(write_size > 0) {
uint16_t writed_size = storage_file_write(file, buffer, write_size);
uint16_t written_size = storage_file_write(file, buffer, write_size);
if(writed_size != write_size) {
if(written_size != write_size) {
storage_cli_print_error(storage_file_get_error(file));
}
break;
}
}
buffer[readed_index % buffer_size] = symbol;
printf("%c", buffer[readed_index % buffer_size]);
buffer[read_index % buffer_size] = symbol;
printf("%c", buffer[read_index % buffer_size]);
fflush(stdout);
readed_index++;
read_index++;
if(((readed_index % buffer_size) == 0)) {
uint16_t writed_size = storage_file_write(file, buffer, buffer_size);
if(((read_index % buffer_size) == 0)) {
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
if(writed_size != buffer_size) {
if(written_size != buffer_size) {
storage_cli_print_error(storage_file_get_error(file));
break;
}
@@ -239,11 +239,11 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) {
printf("\r\nReady?\r\n");
cli_getc(cli);
uint16_t readed_size = storage_file_read(file, data, buffer_size);
for(uint16_t i = 0; i < readed_size; i++) {
uint16_t read_size = storage_file_read(file, data, buffer_size);
for(uint16_t i = 0; i < read_size; i++) {
putchar(data[i]);
}
file_size -= readed_size;
file_size -= read_size;
}
printf("\r\n");
@@ -277,9 +277,9 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) {
buffer[i] = cli_getc(cli);
}
uint16_t writed_size = storage_file_write(file, buffer, buffer_size);
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
if(writed_size != buffer_size) {
if(written_size != buffer_size) {
storage_cli_print_error(storage_file_get_error(file));
}
@@ -400,17 +400,17 @@ static void storage_cli_md5(Cli* cli, string_t path) {
File* file = storage_file_alloc(api);
if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
const uint16_t read_size = 512;
const uint16_t size_to_read = 512;
const uint8_t hash_size = 16;
uint8_t* data = malloc(read_size);
uint8_t* data = malloc(size_to_read);
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
md5_context* md5_ctx = malloc(sizeof(md5_context));
md5_starts(md5_ctx);
while(true) {
uint16_t readed_size = storage_file_read(file, data, read_size);
if(readed_size == 0) break;
md5_update(md5_ctx, data, readed_size);
uint16_t read_size = storage_file_read(file, data, size_to_read);
if(read_size == 0) break;
md5_update(md5_ctx, data, read_size);
}
md5_finish(md5_ctx, hash);
free(md5_ctx);

View File

@@ -340,10 +340,10 @@ static uint16_t
storage_ext_file_read(void* ctx, File* file, void* buff, uint16_t const bytes_to_read) {
StorageData* storage = ctx;
SDFile* file_data = storage_get_storage_file_data(file, storage);
uint16_t bytes_readed = 0;
file->internal_error_id = f_read(file_data, buff, bytes_to_read, &bytes_readed);
uint16_t bytes_read = 0;
file->internal_error_id = f_read(file_data, buff, bytes_to_read, &bytes_read);
file->error_id = storage_ext_parse_error(file->internal_error_id);
return bytes_readed;
return bytes_read;
}
static uint16_t

View File

@@ -349,7 +349,7 @@ static uint16_t
lfs_t* lfs = lfs_get_from_storage(storage);
LFSHandle* handle = storage_get_storage_file_data(file, storage);
uint16_t bytes_readed = 0;
uint16_t bytes_read = 0;
if(lfs_handle_is_open(handle)) {
file->internal_error_id =
@@ -361,10 +361,10 @@ static uint16_t
file->error_id = storage_int_parse_error(file->internal_error_id);
if(file->error_id == FSE_OK) {
bytes_readed = file->internal_error_id;
bytes_read = file->internal_error_id;
file->internal_error_id = 0;
}
return bytes_readed;
return bytes_read;
}
static uint16_t

View File

@@ -29,6 +29,7 @@ struct SubGhzFrequencyAnalyzerWorker {
volatile bool worker_running;
uint8_t count_repet;
FrequencyRSSI frequency_rssi_buf;
SubGhzSetting* setting;
float filVal;
@@ -77,10 +78,12 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
frequency_rssi.rssi = -127.0f;
furi_hal_subghz_idle();
furi_hal_subghz_load_registers(subghz_preset_ook_650khz);
for(size_t i = 0; i < subghz_frequencies_count; i++) {
if(furi_hal_subghz_is_frequency_valid(subghz_frequencies[i])) {
for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
if(furi_hal_subghz_is_frequency_valid(
subghz_setting_get_frequency(instance->setting, i))) {
furi_hal_subghz_idle();
frequency = furi_hal_subghz_set_frequency(subghz_frequencies[i]);
frequency = furi_hal_subghz_set_frequency(
subghz_setting_get_frequency(instance->setting, i));
furi_hal_subghz_rx();
osDelay(3);
rssi = furi_hal_subghz_get_rssi();
@@ -150,6 +153,8 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() {
furi_thread_set_context(instance->thread, instance);
furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread);
instance->setting = subghz_setting_alloc();
subghz_setting_load(instance->setting, "/ext/subghz/assets/setting_frequency_analyzer_user");
return instance;
}
@@ -157,7 +162,7 @@ void subghz_frequency_analyzer_worker_free(SubGhzFrequencyAnalyzerWorker* instan
furi_assert(instance);
furi_thread_free(instance->thread);
subghz_setting_free(instance->setting);
free(instance);
}

View File

@@ -127,7 +127,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else {
//Restore default setting
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
subghz->txrx->frequency = subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting));
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {

View File

@@ -120,7 +120,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_sleep(subghz);
};
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
subghz->txrx->frequency = subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting));
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
subghz->txrx->idx_menu_chosen = 0;
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);

View File

@@ -40,6 +40,21 @@ uint8_t subghz_scene_receiver_config_uint32_value_index(
return index;
}
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
furi_assert(context);
SubGhz* subghz = context;
int64_t last_value = INT64_MIN;
uint8_t index = 0;
for(uint8_t i = 0; i < subghz_setting_get_frequency_count(subghz->setting); i++) {
if((value >= last_value) && (value <= subghz_setting_get_frequency(subghz->setting, i))) {
index = i;
break;
}
last_value = subghz_setting_get_frequency(subghz->setting, i);
}
return index;
}
uint8_t subghz_scene_receiver_config_hopper_value_index(
const uint32_t value,
const uint32_t values[],
@@ -64,10 +79,17 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
uint8_t index = variable_item_get_current_value_index(item);
if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) {
variable_item_set_current_value_text(item, subghz_frequencies_text[index]);
subghz->txrx->frequency = subghz_frequencies[index];
char text_buf[10] = {0};
sprintf(
text_buf,
"%lu.%02lu",
subghz_setting_get_frequency(subghz->setting, index) / 1000000,
(subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000);
variable_item_set_current_value_text(item, text_buf);
subghz->txrx->frequency = subghz_setting_get_frequency(subghz->setting, index);
} else {
variable_item_set_current_value_index(item, subghz_frequencies_433_92);
variable_item_set_current_value_index(
item, subghz_setting_get_frequency_default_index(subghz->setting));
}
}
@@ -85,15 +107,27 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item)
variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
sprintf(
text_buf,
"%lu.%02lu",
subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)) /
1000000,
(subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)) %
1000000) /
10000);
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_frequencies_text[subghz_frequencies_433_92]);
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
text_buf);
subghz->txrx->frequency = subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting));
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_frequencies_433_92);
subghz_setting_get_frequency_default_index(subghz->setting));
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
@@ -102,7 +136,7 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item)
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_frequencies_433_92);
subghz_setting_get_frequency_default_index(subghz->setting));
}
subghz->txrx->hopper_state = hopping_value[index];
@@ -116,15 +150,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
item = variable_item_list_add(
subghz->variable_item_list,
"Frequency:",
subghz_frequencies_count,
subghz_setting_get_frequency_count(subghz->setting),
subghz_scene_receiver_config_set_frequency,
subghz);
value_index = subghz_scene_receiver_config_uint32_value_index(
subghz->txrx->frequency, subghz_frequencies, subghz_frequencies_count);
value_index = subghz_scene_receiver_config_next_frequency(subghz->txrx->frequency, subghz);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, subghz_frequencies_text[value_index]);
char text_buf[10] = {0};
sprintf(
text_buf,
"%lu.%02lu",
subghz_setting_get_frequency(subghz->setting, value_index) / 1000000,
(subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000);
variable_item_set_current_value_text(item, text_buf);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {

View File

@@ -46,7 +46,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
if(!subghz_protocol_decoder_base_serialize(
subghz->txrx->decoder_result,
subghz->txrx->fff_data,
subghz_frequencies[subghz_frequencies_433_92],
subghz_setting_get_frequency_default_index(subghz->setting),
FuriHalSubGhzPresetOok650Async)) {
FURI_LOG_E(TAG, "Unable to serialize");
break;
@@ -213,7 +213,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
0x2,
0x0003,
"DoorHan",
subghz_frequencies[subghz_frequencies_433_92],
subghz_setting_get_frequency_default_index(subghz->setting),
FuriHalSubGhzPresetOok650Async);
generated_protocol = true;
} else {
@@ -237,7 +237,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
0x2,
0x0003,
"DoorHan",
subghz_frequencies[subghz_frequencies_315_00],
315000000,
FuriHalSubGhzPresetOok650Async);
generated_protocol = true;
} else {

View File

@@ -3,68 +3,6 @@
#include "subghz_i.h"
#include <lib/toolbox/path.h>
const char* const subghz_frequencies_text[] = {
"300.00",
"303.88",
"304.25",
"315.00",
"318.00",
"390.00",
"418.00",
"433.08",
"433.42",
"433.92",
"434.42",
"434.78",
"438.90",
"868.35",
"915.00",
"925.00",
};
const uint32_t subghz_frequencies[] = {
/* 300 - 348 */
300000000,
303875000,
304250000,
315000000,
318000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433420000,
433920000, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
/* 779 - 928 */
868350000,
915000000,
925000000,
};
const uint32_t subghz_hopper_frequencies[] = {
315000000,
318000000,
390000000,
433920000,
868350000,
};
const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t);
const uint32_t subghz_hopper_frequencies_count =
sizeof(subghz_hopper_frequencies) / sizeof(uint32_t);
const uint32_t subghz_frequencies_433_92 = 9;
const uint32_t subghz_frequencies_315_00 = 3;
bool subghz_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
SubGhz* subghz = context;
@@ -186,9 +124,14 @@ SubGhz* subghz_alloc() {
SubGhzViewIdStatic,
subghz_test_static_get_view(subghz->subghz_test_static));
//init setting
subghz->setting = subghz_setting_alloc();
subghz_setting_load(subghz->setting, "/ext/subghz/assets/setting_user");
//init Worker & Protocol & History
subghz->txrx = malloc(sizeof(SubGhzTxRx));
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
subghz->txrx->frequency = subghz_setting_get_frequency(
subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting));
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
@@ -281,6 +224,9 @@ void subghz_free(SubGhz* subghz) {
furi_record_close("gui");
subghz->gui = NULL;
//setting
subghz_setting_free(subghz->setting);
//Worker & Protocol & History
subghz_receiver_free(subghz->txrx->receiver);
subghz_environment_free(subghz->txrx->environment);

View File

@@ -9,6 +9,7 @@
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_file_encoder_worker.h>
#include "helpers/subghz_chat.h"
@@ -294,6 +295,110 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
free(instance);
}
void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) {
string_t file_name;
string_init(file_name);
string_set(file_name, "/any/subghz/test.sub");
Storage* storage = furi_record_open("storage");
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
string_t temp_str;
string_init(temp_str);
uint32_t temp_data32;
bool check_file = false;
do {
if(string_size(args)) {
if(!args_read_string_and_trim(args, file_name)) {
cli_print_usage(
"subghz decode_raw", "<file_name: path_RAW_file>", string_get_cstr(args));
break;
}
}
if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) {
printf(
"subghz decode_raw \033[0;31mError open file\033[0m %s\r\n",
string_get_cstr(file_name));
break;
}
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
printf("subghz decode_raw \033[0;31mMissing or incorrect header\033[0m\r\n");
break;
}
if(!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE) &&
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
} else {
printf("subghz decode_raw \033[0;31mType or version mismatch\033[0m\r\n");
break;
}
check_file = true;
} while(false);
string_clear(temp_str);
flipper_format_free(fff_data_file);
furi_record_close("storage");
if(check_file) {
// Allocate context
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
SubGhzEnvironment* environment = subghz_environment_alloc();
if(subghz_environment_load_keystore(environment, "/ext/subghz/assets/keeloq_mfcodes")) {
printf("SubGhz test: Load_keystore \033[0;32mOK\033[0m\r\n");
} else {
printf("SubGhz test: Load_keystore \033[0;31mERROR\033[0m\r\n");
}
subghz_environment_set_came_atomo_rainbow_table_file_name(
environment, "/ext/subghz/assets/came_atomo");
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, "/ext/subghz/assets/nice_flor_s");
SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);
subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance);
SubGhzFileEncoderWorker* file_worker_encoder = subghz_file_encoder_worker_alloc();
if(subghz_file_encoder_worker_start(file_worker_encoder, string_get_cstr(file_name))) {
//the worker needs a file in order to open and read part of the file
osDelay(100);
}
printf(
"Listening at \033[0;33m%s\033[0m.\r\n\r\nPress CTRL+C to stop\r\n\r\n",
string_get_cstr(file_name));
LevelDuration level_duration;
while(!cli_cmd_interrupt_received(cli)) {
furi_hal_delay_us(500); //you need to have time to read from the file from the SD card
level_duration = subghz_file_encoder_worker_get_level_duration(file_worker_encoder);
if(!level_duration_is_reset(level_duration)) {
bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration);
subghz_receiver_decode(receiver, level, duration);
} else {
break;
}
}
printf("\r\nPackets recieved \033[0;32m%u\033[0m\r\n", instance->packet_count);
// Cleanup
subghz_receiver_free(receiver);
subghz_environment_free(environment);
if(subghz_file_encoder_worker_is_running(file_worker_encoder)) {
subghz_file_encoder_worker_stop(file_worker_encoder);
}
subghz_file_encoder_worker_free(file_worker_encoder);
free(instance);
}
string_clear(file_name);
}
static void subghz_cli_command_print_usage() {
printf("Usage:\r\n");
printf("subghz <cmd> <args>\r\n");
@@ -303,6 +408,7 @@ static void subghz_cli_command_print_usage() {
printf(
"\ttx <3 byte Key: in hex> <frequency: in Hz> <repeat: count>\t - Transmitting key\r\n");
printf("\trx <frequency:in Hz>\t - Reception key\r\n");
printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
printf("\r\n");
@@ -595,6 +701,12 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) {
subghz_cli_command_rx(cli, args, context);
break;
}
if(string_cmp_str(cmd, "decode_raw") == 0) {
subghz_cli_command_decode_raw(cli, args, context);
break;
}
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
if(string_cmp_str(cmd, "encrypt_keeloq") == 0) {
subghz_cli_command_encrypt_keeloq(cli, args);

View File

@@ -514,9 +514,9 @@ void subghz_hopper_update(SubGhz* subghz) {
} else {
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
}
// Select next frequency
if(subghz->txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
if(subghz->txrx->hopper_idx_frequency <
subghz_setting_get_hopper_frequency_count(subghz->setting) - 1) {
subghz->txrx->hopper_idx_frequency++;
} else {
subghz->txrx->hopper_idx_frequency = 0;
@@ -527,7 +527,8 @@ void subghz_hopper_update(SubGhz* subghz) {
};
if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
subghz_receiver_reset(subghz->txrx->receiver);
subghz->txrx->frequency = subghz_hopper_frequencies[subghz->txrx->hopper_idx_frequency];
subghz->txrx->frequency = subghz_setting_get_hopper_frequency(
subghz->setting, subghz->txrx->hopper_idx_frequency);
subghz_rx(subghz, subghz->txrx->frequency);
}
}

View File

@@ -31,18 +31,11 @@
#include <lib/subghz/transmitter.h>
#include "subghz_history.h"
#include "subghz_setting.h"
#include <gui/modules/variable_item_list.h>
#define SUBGHZ_MAX_LEN_NAME 21
extern const char* const subghz_frequencies_text[];
extern const uint32_t subghz_frequencies[];
extern const uint32_t subghz_hopper_frequencies[];
extern const uint32_t subghz_frequencies_count;
extern const uint32_t subghz_hopper_frequencies_count;
extern const uint32_t subghz_frequencies_433_92;
extern const uint32_t subghz_frequencies_315_00;
#define SUBGHZ_MAX_LEN_NAME 40
/** SubGhzNotification state */
typedef enum {
@@ -145,6 +138,7 @@ struct SubGhz {
SubGhzTestCarrier* subghz_test_carrier;
SubGhzTestPacket* subghz_test_packet;
string_t error_str;
SubGhzSetting* setting;
};
typedef enum {

View File

@@ -0,0 +1,361 @@
#include "subghz_setting.h"
#include "subghz_i.h"
#include <furi.h>
#include <m-list.h>
#include <lib/flipper_format/flipper_format.h>
#define TAG "SubGhzSetting"
#define SUBGHZ_SETTING_FILE_VERSION 1
#define SUBGHZ_SETTING_FILE_TYPE "Flipper SubGhz Setting File"
typedef enum {
SubGhzSettingStateNoLoad = 0,
SubGhzSettingStateLoadFrequencyDefault,
SubGhzSettingStateOkLoad,
} SubGhzSettingState;
static const uint32_t subghz_frequencies[] = {
/* 300 - 348 */
300000000,
303875000,
304250000,
315000000,
318000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433420000,
433920000, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
/* 779 - 928 */
868350000,
915000000,
925000000,
0,
};
static const uint32_t subghz_hopper_frequencies[] = {
315000000,
318000000,
390000000,
433920000,
868350000,
0,
};
static const uint32_t subghz_frequency_default_index = 9;
static const uint32_t subghz_frequencies_region_eu_ru[] = {
/* 300 - 348 */
300000000,
303875000,
304250000,
315000000,
318000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433420000,
433920000, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
/* 779 - 928 */
868350000,
915000000,
925000000,
0,
};
static const uint32_t subghz_hopper_frequencies_region_eu_ru[] = {
315000000,
318000000,
390000000,
433920000,
868350000,
0,
};
static const uint32_t subghz_frequency_default_index_region_eu_ru = 9;
static const uint32_t subghz_frequencies_region_us_ca_au[] = {
/* 300 - 348 */
300000000,
303875000,
304250000,
315000000,
318000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433420000,
433920000, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
/* 779 - 928 */
868350000,
915000000,
925000000,
0,
};
static const uint32_t subghz_hopper_frequencies_region_us_ca_au[] = {
315000000,
318000000,
390000000,
433920000,
868350000,
0,
};
static const uint32_t subghz_frequency_default_index_region_us_ca_au = 9;
static const uint32_t subghz_frequencies_region_jp[] = {
/* 300 - 348 */
300000000,
303875000,
304250000,
315000000,
318000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433420000,
433920000, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
/* 779 - 928 */
868350000,
915000000,
925000000,
0,
};
static const uint32_t subghz_hopper_frequencies_region_jp[] = {
315000000,
318000000,
390000000,
433920000,
868350000,
0,
};
static const uint32_t subghz_frequency_default_index_region_jp = 9;
LIST_DEF(frequencies_list, uint32_t)
LIST_DEF(hopper_frequencies_list, uint32_t)
struct SubGhzSetting {
frequencies_list_t frequencies;
hopper_frequencies_list_t hopper_frequencies;
size_t frequencies_count;
size_t hopper_frequencies_count;
uint32_t frequency_default_index;
};
SubGhzSetting* subghz_setting_alloc(void) {
SubGhzSetting* instance = malloc(sizeof(SubGhzSetting));
frequencies_list_init(instance->frequencies);
hopper_frequencies_list_init(instance->hopper_frequencies);
return instance;
}
void subghz_setting_free(SubGhzSetting* instance) {
furi_assert(instance);
frequencies_list_clear(instance->frequencies);
hopper_frequencies_list_clear(instance->hopper_frequencies);
free(instance);
}
void subghz_setting_load_default(
SubGhzSetting* instance,
const uint32_t frequencies[],
const uint32_t hopper_frequencies[],
const uint32_t frequency_default_index) {
furi_assert(instance);
size_t i = 0;
frequencies_list_clear(instance->frequencies);
hopper_frequencies_list_clear(instance->hopper_frequencies);
i = 0;
while(frequencies[i]) {
frequencies_list_push_back(instance->frequencies, frequencies[i]);
i++;
}
instance->frequencies_count = i;
i = 0;
while(hopper_frequencies[i]) {
hopper_frequencies_list_push_back(instance->hopper_frequencies, hopper_frequencies[i]);
i++;
}
instance->hopper_frequencies_count = i;
instance->frequency_default_index = frequency_default_index;
}
void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
furi_assert(instance);
frequencies_list_clear(instance->frequencies);
hopper_frequencies_list_clear(instance->hopper_frequencies);
Storage* storage = furi_record_open("storage");
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
string_t temp_str;
string_init(temp_str);
uint32_t temp_data32;
SubGhzSettingState loading = SubGhzSettingStateNoLoad;
uint16_t i = 0;
if(file_path) {
do {
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
FURI_LOG_E(TAG, "Error open file %s", file_path);
break;
}
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
FURI_LOG_E(TAG, "Missing or incorrect header");
break;
}
if((!strcmp(string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) &&
temp_data32 == SUBGHZ_SETTING_FILE_VERSION) {
} else {
FURI_LOG_E(TAG, "Type or version mismatch");
break;
}
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
i = 0;
while(flipper_format_read_uint32(
fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
frequencies_list_push_back(instance->frequencies, temp_data32);
i++;
} else {
FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32);
}
}
instance->frequencies_count = i;
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
i = 0;
while(flipper_format_read_uint32(
fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32);
hopper_frequencies_list_push_back(instance->hopper_frequencies, temp_data32);
i++;
} else {
FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32);
}
}
instance->hopper_frequencies_count = i;
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(!flipper_format_read_uint32(
fff_data_file, "Frequency_default", (uint32_t*)&temp_data32, 1)) {
FURI_LOG_E(TAG, "Frequency default missing");
break;
}
for(i = 0; i < instance->frequencies_count; i++) {
if(subghz_setting_get_frequency(instance, i) == temp_data32) {
instance->frequency_default_index = i;
FURI_LOG_I(TAG, "Frequency default index %lu", i);
loading = SubGhzSettingStateLoadFrequencyDefault;
break;
}
}
if(loading == SubGhzSettingStateLoadFrequencyDefault) {
loading = SubGhzSettingStateOkLoad;
} else {
FURI_LOG_E(TAG, "Frequency default index missing");
}
} while(false);
}
flipper_format_free(fff_data_file);
furi_record_close("storage");
if(loading != SubGhzSettingStateOkLoad) {
switch(furi_hal_version_get_hw_region()) {
case FuriHalVersionRegionEuRu:
subghz_setting_load_default(
instance,
subghz_frequencies_region_eu_ru,
subghz_hopper_frequencies_region_eu_ru,
subghz_frequency_default_index_region_eu_ru);
break;
case FuriHalVersionRegionUsCaAu:
subghz_setting_load_default(
instance,
subghz_frequencies_region_us_ca_au,
subghz_hopper_frequencies_region_us_ca_au,
subghz_frequency_default_index_region_us_ca_au);
break;
case FuriHalVersionRegionJp:
subghz_setting_load_default(
instance,
subghz_frequencies_region_jp,
subghz_hopper_frequencies_region_jp,
subghz_frequency_default_index_region_jp);
break;
default:
subghz_setting_load_default(
instance,
subghz_frequencies,
subghz_hopper_frequencies,
subghz_frequency_default_index);
break;
}
}
}
size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) {
furi_assert(instance);
return instance->frequencies_count;
}
size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) {
furi_assert(instance);
return instance->hopper_frequencies_count;
}
uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) {
furi_assert(instance);
return *frequencies_list_get(instance->frequencies, idx);
}
uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) {
furi_assert(instance);
return *hopper_frequencies_list_get(instance->hopper_frequencies, idx);
}
uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance) {
furi_assert(instance);
return instance->frequency_default_index;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <math.h>
#include <furi.h>
#include <furi_hal.h>
typedef struct SubGhzSetting SubGhzSetting;
SubGhzSetting* subghz_setting_alloc(void);
void subghz_setting_free(SubGhzSetting* instance);
void subghz_setting_load(SubGhzSetting* instance, const char* file_path);
size_t subghz_setting_get_frequency_count(SubGhzSetting* instance);
size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance);
uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx);
uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx);
uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance);

View File

@@ -1,19 +1,6 @@
#include "system_settings.h"
#include <loader/loader.h>
static uint8_t
uint32_value_index(const uint32_t value, const uint32_t values[], uint8_t values_count) {
int64_t last_value = INT64_MIN;
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if((value >= last_value) && (value <= values[i])) {
index = i;
break;
}
last_value = values[i];
}
return index;
}
#include <lib/toolbox/value_index.h>
const char* const log_level_text[] = {
"Default",
@@ -80,7 +67,7 @@ SystemSettings* system_settings_alloc() {
item = variable_item_list_add(
app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app);
value_index = uint32_value_index(
value_index = value_index_uint32(
furi_hal_rtc_get_log_level(), log_level_value, COUNT_OF(log_level_text));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, log_level_text[value_index]);

Some files were not shown because too many files have changed in this diff Show More