mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-20 04:54:45 -07:00
Merge branch 'flipperdevices:dev' into dev
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -36,3 +36,6 @@ CMakeLists.txt
|
|||||||
|
|
||||||
# bundle output
|
# bundle output
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
# kde
|
||||||
|
.directory
|
||||||
|
|||||||
@@ -21,13 +21,23 @@ bool archive_app_is_available(void* context, const char* path) {
|
|||||||
ArchiveAppTypeEnum app = archive_get_app_type(path);
|
ArchiveAppTypeEnum app = archive_get_app_type(path);
|
||||||
|
|
||||||
if(app == ArchiveAppTypeU2f) {
|
if(app == ArchiveAppTypeU2f) {
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
|
||||||
bool file_exists = false;
|
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) {
|
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;
|
return file_exists;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -60,10 +70,10 @@ void archive_app_delete_file(void* context, const char* path) {
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
if(app == ArchiveAppTypeU2f) {
|
if(app == ArchiveAppTypeU2f) {
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
Storage* fs_api = furi_record_open("storage");
|
||||||
res = file_worker_remove(file_worker, "/any/u2f/key.u2f");
|
res = (storage_common_remove(fs_api, "/any/u2f/key.u2f") == FSE_OK);
|
||||||
res |= file_worker_remove(file_worker, "/any/u2f/cnt.u2f");
|
res |= (storage_common_remove(fs_api, "/any/u2f/cnt.u2f") == FSE_OK);
|
||||||
file_worker_free(file_worker);
|
furi_record_close("storage");
|
||||||
|
|
||||||
if(archive_is_favorite("/app:u2f/U2F Token")) {
|
if(archive_is_favorite("/app:u2f/U2F Token")) {
|
||||||
archive_favorites_delete("/app:u2f/U2F Token");
|
archive_favorites_delete("/app:u2f/U2F Token");
|
||||||
|
|||||||
@@ -392,6 +392,17 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) {
|
|||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
furi_assert(name);
|
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));
|
archive_dir_count_items(browser, string_get_cstr(name));
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#define TAB_RIGHT InputKeyRight //default tab swith direction
|
#define TAB_RIGHT InputKeyRight //default tab swith direction
|
||||||
#define FILE_LIST_BUF_LEN 100
|
#define FILE_LIST_BUF_LEN 100
|
||||||
|
#define BROWSER_DEPTH_MAX 8
|
||||||
|
|
||||||
static const char* tab_default_paths[] = {
|
static const char* tab_default_paths[] = {
|
||||||
[ArchiveTabFavorites] = "/any/favorites",
|
[ArchiveTabFavorites] = "/any/favorites",
|
||||||
|
|||||||
@@ -4,20 +4,63 @@
|
|||||||
#include "archive_apps.h"
|
#include "archive_apps.h"
|
||||||
#include "archive_browser.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) {
|
uint16_t archive_favorites_count(void* context) {
|
||||||
furi_assert(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_t buffer;
|
||||||
string_init(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;
|
uint16_t lines = 0;
|
||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
@@ -27,21 +70,26 @@ uint16_t archive_favorites_count(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storage_file_close(file);
|
||||||
|
|
||||||
string_clear(buffer);
|
string_clear(buffer);
|
||||||
file_worker_close(file_worker);
|
storage_file_free(file);
|
||||||
file_worker_free(file_worker);
|
furi_record_close("storage");
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool archive_favourites_rescan() {
|
static bool archive_favourites_rescan() {
|
||||||
string_t buffer;
|
string_t buffer;
|
||||||
string_init(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) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
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));
|
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool file_exists = false;
|
bool file_exists = storage_file_open(
|
||||||
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
|
fav_item_file, string_get_cstr(buffer), FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
if(file_exists) {
|
if(file_exists) {
|
||||||
|
storage_file_close(fav_item_file);
|
||||||
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer));
|
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);
|
string_clear(buffer);
|
||||||
|
|
||||||
file_worker_close(file_worker);
|
storage_file_close(file);
|
||||||
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
|
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
|
||||||
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, 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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -77,7 +128,9 @@ bool archive_favorites_read(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
ArchiveBrowserView* browser = 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;
|
string_t buffer;
|
||||||
FileInfo file_info;
|
FileInfo file_info;
|
||||||
@@ -88,11 +141,11 @@ bool archive_favorites_read(void* context) {
|
|||||||
|
|
||||||
archive_file_array_rm_all(browser);
|
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) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
@@ -107,10 +160,10 @@ bool archive_favorites_read(void* context) {
|
|||||||
need_refresh = true;
|
need_refresh = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool file_exists = false;
|
bool file_exists = storage_file_open(
|
||||||
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
|
fav_item_file, string_get_cstr(buffer), FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
|
|
||||||
if(file_exists) {
|
if(file_exists) {
|
||||||
|
storage_file_close(fav_item_file);
|
||||||
archive_add_file_item(browser, &file_info, string_get_cstr(buffer));
|
archive_add_file_item(browser, &file_info, string_get_cstr(buffer));
|
||||||
file_count++;
|
file_count++;
|
||||||
} else {
|
} else {
|
||||||
@@ -121,9 +174,11 @@ bool archive_favorites_read(void* context) {
|
|||||||
string_reset(buffer);
|
string_reset(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
storage_file_close(file);
|
||||||
string_clear(buffer);
|
string_clear(buffer);
|
||||||
file_worker_close(file_worker);
|
storage_file_free(file);
|
||||||
file_worker_free(file_worker);
|
storage_file_free(fav_item_file);
|
||||||
|
furi_record_close("storage");
|
||||||
|
|
||||||
archive_set_item_count(browser, file_count);
|
archive_set_item_count(browser, file_count);
|
||||||
|
|
||||||
@@ -143,12 +198,14 @@ bool archive_favorites_delete(const char* format, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
string_init(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);
|
||||||
|
|
||||||
|
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) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
@@ -164,11 +221,12 @@ bool archive_favorites_delete(const char* format, ...) {
|
|||||||
string_clear(buffer);
|
string_clear(buffer);
|
||||||
string_clear(filename);
|
string_clear(filename);
|
||||||
|
|
||||||
file_worker_close(file_worker);
|
storage_file_close(file);
|
||||||
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
|
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
|
||||||
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, 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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -182,14 +240,15 @@ bool archive_is_favorite(const char* format, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
string_init(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);
|
||||||
|
|
||||||
bool found = false;
|
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) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
@@ -202,10 +261,11 @@ bool archive_is_favorite(const char* format, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storage_file_close(file);
|
||||||
string_clear(buffer);
|
string_clear(buffer);
|
||||||
string_clear(filename);
|
string_clear(filename);
|
||||||
file_worker_close(file_worker);
|
storage_file_free(file);
|
||||||
file_worker_free(file_worker);
|
furi_record_close("storage");
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@@ -214,7 +274,8 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
|||||||
furi_assert(src);
|
furi_assert(src);
|
||||||
furi_assert(dst);
|
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 path;
|
||||||
string_t buffer;
|
string_t buffer;
|
||||||
@@ -223,11 +284,11 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
|||||||
string_init(path);
|
string_init(path);
|
||||||
|
|
||||||
string_printf(path, "%s", src);
|
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) {
|
if(result) {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
if(!archive_favorites_read_line(file, buffer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
@@ -244,11 +305,12 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
|||||||
string_clear(buffer);
|
string_clear(buffer);
|
||||||
string_clear(path);
|
string_clear(path);
|
||||||
|
|
||||||
file_worker_close(file_worker);
|
storage_file_close(file);
|
||||||
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
|
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
|
||||||
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, 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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -263,15 +325,17 @@ void archive_favorites_save(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
ArchiveBrowserView* browser = 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++) {
|
for(size_t i = 0; i < archive_file_get_array_size(browser); i++) {
|
||||||
ArchiveFile_t* item = archive_get_file_at(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));
|
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(item->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
|
storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
|
||||||
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, 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");
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "file_worker.h"
|
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
#define ARCHIVE_FAV_PATH "/any/favorites.txt"
|
#define ARCHIVE_FAV_PATH "/any/favorites.txt"
|
||||||
#define ARCHIVE_FAV_TEMP_PATH "/any/favorites.tmp"
|
#define ARCHIVE_FAV_TEMP_PATH "/any/favorites.tmp"
|
||||||
|
|||||||
@@ -201,18 +201,18 @@ void archive_file_append(const char* path, const char* format, ...) {
|
|||||||
string_init_vprintf(string, format, args);
|
string_init_vprintf(string, format, args);
|
||||||
va_end(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)) {
|
bool res = storage_file_open(file, path, FSAM_WRITE, FSOM_OPEN_APPEND);
|
||||||
FURI_LOG_E(TAG, "Append open error");
|
|
||||||
|
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))) {
|
storage_file_close(file);
|
||||||
FURI_LOG_E(TAG, "Append write error");
|
storage_file_free(file);
|
||||||
}
|
furi_record_close("storage");
|
||||||
|
|
||||||
file_worker_close(file_worker);
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_delete_file(void* context, const char* format, ...) {
|
void archive_delete_file(void* context, const char* format, ...) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "file_worker.h"
|
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
|
#include <m-string.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ArchiveFileTypeIButton,
|
ArchiveFileTypeIButton,
|
||||||
|
|||||||
@@ -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);
|
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)) {
|
if(!archive_is_known_app(selected->type)) {
|
||||||
string_set_str(menu[0], "---");
|
string_set_str(menu[0], "---");
|
||||||
string_set_str(menu[1], "---");
|
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++) {
|
for(size_t i = 0; i < MENU_ITEMS; i++) {
|
||||||
canvas_draw_str(canvas, 82, 27 + i * 11, string_get_cstr(menu[i]));
|
canvas_draw_str(canvas, 82, 27 + i * 11, string_get_cstr(menu[i]));
|
||||||
string_clear(menu[i]);
|
string_clear(menu[i]);
|
||||||
|
|||||||
@@ -401,6 +401,8 @@ void cli_delete_command(Cli* cli, const char* name) {
|
|||||||
int32_t cli_srv(void* p) {
|
int32_t cli_srv(void* p) {
|
||||||
Cli* cli = cli_alloc();
|
Cli* cli = cli_alloc();
|
||||||
|
|
||||||
|
furi_hal_vcp_init();
|
||||||
|
|
||||||
// Init basic cli commands
|
// Init basic cli commands
|
||||||
cli_commands_init(cli);
|
cli_commands_init(cli);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
#include <gui/view_stack.h>
|
#include <gui/view_stack.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
@@ -13,6 +16,10 @@
|
|||||||
#include "desktop_i.h"
|
#include "desktop_i.h"
|
||||||
#include "desktop_helpers.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) {
|
static void desktop_loader_callback(const void* message, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
Desktop* desktop = context;
|
Desktop* desktop = context;
|
||||||
@@ -37,9 +44,19 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
|
|||||||
switch(event) {
|
switch(event) {
|
||||||
case DesktopGlobalBeforeAppStarted:
|
case DesktopGlobalBeforeAppStarted:
|
||||||
animation_manager_unload_and_stall_animation(desktop->animation_manager);
|
animation_manager_unload_and_stall_animation(desktop->animation_manager);
|
||||||
|
desktop_auto_lock_inhibit(desktop);
|
||||||
return true;
|
return true;
|
||||||
case DesktopGlobalAfterAppFinished:
|
case DesktopGlobalAfterAppFinished:
|
||||||
animation_manager_load_and_continue_animation(desktop->animation_manager);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +75,63 @@ static void desktop_tick_event_callback(void* context) {
|
|||||||
scene_manager_handle_tick_event(app->scene_manager);
|
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_alloc() {
|
||||||
Desktop* desktop = malloc(sizeof(Desktop));
|
Desktop* desktop = malloc(sizeof(Desktop));
|
||||||
|
|
||||||
@@ -146,9 +220,17 @@ Desktop* desktop_alloc() {
|
|||||||
animation_manager_is_animation_loaded(desktop->animation_manager)) {
|
animation_manager_is_animation_loaded(desktop->animation_manager)) {
|
||||||
animation_manager_unload_and_stall_animation(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(
|
desktop->app_start_stop_subscription = furi_pubsub_subscribe(
|
||||||
loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop);
|
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;
|
return desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,8 +239,17 @@ void desktop_free(Desktop* desktop) {
|
|||||||
|
|
||||||
furi_pubsub_unsubscribe(
|
furi_pubsub_unsubscribe(
|
||||||
loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription);
|
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->loader = NULL;
|
||||||
|
desktop->input_events_pubsub = NULL;
|
||||||
furi_record_close("loader");
|
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, DesktopViewIdMain);
|
||||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
|
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
|
||||||
@@ -191,6 +282,8 @@ void desktop_free(Desktop* desktop) {
|
|||||||
|
|
||||||
furi_record_close("menu");
|
furi_record_close("menu");
|
||||||
|
|
||||||
|
osTimerDelete(desktop->auto_lock_timer);
|
||||||
|
|
||||||
free(desktop);
|
free(desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,14 +307,16 @@ int32_t desktop_srv(void* p) {
|
|||||||
|
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||||
|
|
||||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock) && !desktop->settings.pin_code.length) {
|
||||||
if(desktop->settings.pin_code.length > 0) {
|
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||||
scene_manager_set_scene_state(
|
}
|
||||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
||||||
} else {
|
if(!loader_is_locked(desktop->loader)) {
|
||||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
desktop_auto_lock_arm(desktop);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
desktop_lock(desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(desktop_is_first_start()) {
|
if(desktop_is_first_start()) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
|
#include <notification/notification_app.h>
|
||||||
|
|
||||||
#define STATUS_BAR_Y_SHIFT 13
|
#define STATUS_BAR_Y_SHIFT 13
|
||||||
|
|
||||||
@@ -59,10 +60,18 @@ struct Desktop {
|
|||||||
ViewPort* lock_viewport;
|
ViewPort* lock_viewport;
|
||||||
|
|
||||||
AnimationManager* animation_manager;
|
AnimationManager* animation_manager;
|
||||||
|
|
||||||
Loader* loader;
|
Loader* loader;
|
||||||
|
NotificationApp* notification;
|
||||||
|
|
||||||
FuriPubSubSubscription* app_start_stop_subscription;
|
FuriPubSubSubscription* app_start_stop_subscription;
|
||||||
|
FuriPubSub* input_events_pubsub;
|
||||||
|
FuriPubSubSubscription* input_events_subscription;
|
||||||
|
osTimerId_t auto_lock_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
Desktop* desktop_alloc();
|
Desktop* desktop_alloc();
|
||||||
|
|
||||||
void desktop_free(Desktop* desktop);
|
void desktop_free(Desktop* desktop);
|
||||||
|
void desktop_lock(Desktop* desktop);
|
||||||
|
void desktop_unlock(Desktop* desktop);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <toolbox/saved_struct.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_PATH "/int/desktop.settings"
|
||||||
#define DESKTOP_SETTINGS_MAGIC (0x17)
|
#define DESKTOP_SETTINGS_MAGIC (0x17)
|
||||||
#define PIN_MAX_LENGTH 12
|
#define PIN_MAX_LENGTH 12
|
||||||
@@ -39,6 +39,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t favorite;
|
uint16_t favorite;
|
||||||
PinCode pin_code;
|
PinCode pin_code;
|
||||||
|
uint32_t auto_lock_delay_ms;
|
||||||
} DesktopSettings;
|
} DesktopSettings;
|
||||||
|
|
||||||
static inline bool pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2) {
|
static inline bool pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2) {
|
||||||
|
|||||||
@@ -36,12 +36,17 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
|
|||||||
|
|
||||||
app->popup = popup_alloc();
|
app->popup = popup_alloc();
|
||||||
app->submenu = submenu_alloc();
|
app->submenu = submenu_alloc();
|
||||||
|
app->variable_item_list = variable_item_list_alloc();
|
||||||
app->pin_input_view = desktop_view_pin_input_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_howto_view = desktop_settings_view_pin_setup_howto_alloc();
|
||||||
app->pin_setup_howto2_view = desktop_settings_view_pin_setup_howto2_alloc();
|
app->pin_setup_howto2_view = desktop_settings_view_pin_setup_howto2_alloc();
|
||||||
|
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
app->view_dispatcher, DesktopSettingsAppViewMenu, submenu_get_view(app->submenu));
|
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(
|
view_dispatcher_add_view(
|
||||||
app->view_dispatcher, DesktopSettingsAppViewIdPopup, popup_get_view(app->popup));
|
app->view_dispatcher, DesktopSettingsAppViewIdPopup, popup_get_view(app->popup));
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@@ -63,10 +68,12 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
|
|||||||
furi_assert(app);
|
furi_assert(app);
|
||||||
// Variable item list
|
// Variable item list
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
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, DesktopSettingsAppViewIdPopup);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
|
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
|
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
|
||||||
|
variable_item_list_free(app->variable_item_list);
|
||||||
submenu_free(app->submenu);
|
submenu_free(app->submenu);
|
||||||
popup_free(app->popup);
|
popup_free(app->popup);
|
||||||
desktop_view_pin_input_free(app->pin_input_view);
|
desktop_view_pin_input_free(app->pin_input_view);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
#include <gui/modules/submenu.h>
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/modules/variable_item_list.h>
|
||||||
|
|
||||||
#include "desktop_settings.h"
|
#include "desktop_settings.h"
|
||||||
#include "desktop/views/desktop_view_pin_input.h"
|
#include "desktop/views/desktop_view_pin_input.h"
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DesktopSettingsAppViewMenu,
|
DesktopSettingsAppViewMenu,
|
||||||
|
DesktopSettingsAppViewVarItemList,
|
||||||
DesktopSettingsAppViewIdPopup,
|
DesktopSettingsAppViewIdPopup,
|
||||||
DesktopSettingsAppViewIdPinInput,
|
DesktopSettingsAppViewIdPinInput,
|
||||||
DesktopSettingsAppViewIdPinSetupHowto,
|
DesktopSettingsAppViewIdPinSetupHowto,
|
||||||
@@ -25,6 +27,7 @@ typedef struct {
|
|||||||
Gui* gui;
|
Gui* gui;
|
||||||
SceneManager* scene_manager;
|
SceneManager* scene_manager;
|
||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
|
VariableItemList* variable_item_list;
|
||||||
Submenu* submenu;
|
Submenu* submenu;
|
||||||
Popup* popup;
|
Popup* popup;
|
||||||
DesktopViewPinInput* pin_input_view;
|
DesktopViewPinInput* pin_input_view;
|
||||||
|
|||||||
@@ -1,35 +1,65 @@
|
|||||||
#include <applications.h>
|
#include <applications.h>
|
||||||
|
#include <lib/toolbox/value_index.h>
|
||||||
|
|
||||||
#include "../desktop_settings_app.h"
|
#include "../desktop_settings_app.h"
|
||||||
#include "desktop_settings_scene.h"
|
#include "desktop_settings_scene.h"
|
||||||
|
|
||||||
#define SCENE_EVENT_SELECT_FAVORITE 0
|
#define SCENE_EVENT_SELECT_FAVORITE 0
|
||||||
#define SCENE_EVENT_SELECT_PIN_SETUP 1
|
#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;
|
DesktopSettingsApp* app = context;
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
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) {
|
void desktop_settings_scene_start_on_enter(void* context) {
|
||||||
DesktopSettingsApp* app = context;
|
DesktopSettingsApp* app = context;
|
||||||
Submenu* submenu = app->submenu;
|
VariableItemList* variable_item_list = app->variable_item_list;
|
||||||
|
|
||||||
submenu_add_item(
|
VariableItem* item;
|
||||||
submenu,
|
uint8_t value_index;
|
||||||
"Favorite App",
|
|
||||||
SCENE_EVENT_SELECT_FAVORITE,
|
variable_item_list_add(variable_item_list, "Favorite App", 1, NULL, NULL);
|
||||||
desktop_settings_scene_start_submenu_callback,
|
|
||||||
|
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);
|
app);
|
||||||
|
|
||||||
submenu_add_item(
|
variable_item_list_set_enter_callback(
|
||||||
submenu,
|
variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app);
|
||||||
"PIN Setup",
|
value_index = value_index_uint32(
|
||||||
SCENE_EVENT_SELECT_PIN_SETUP,
|
app->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT);
|
||||||
desktop_settings_scene_start_submenu_callback,
|
variable_item_set_current_value_index(item, value_index);
|
||||||
app);
|
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) {
|
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);
|
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
|
||||||
|
consumed = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
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) {
|
void desktop_settings_scene_start_on_exit(void* context) {
|
||||||
DesktopSettingsApp* app = context;
|
DesktopSettingsApp* app = context;
|
||||||
submenu_reset(app->submenu);
|
variable_item_list_reset(app->variable_item_list);
|
||||||
|
SAVE_DESKTOP_SETTINGS(&app->settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,17 +48,13 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
case DesktopLockMenuEventLock:
|
case DesktopLockMenuEventLock:
|
||||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||||
scene_manager_set_scene_state(
|
desktop_lock(desktop);
|
||||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopLockMenuEventPinLock:
|
case DesktopLockMenuEventPinLock:
|
||||||
if(desktop->settings.pin_code.length > 0) {
|
if(desktop->settings.pin_code.length > 0) {
|
||||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||||
scene_manager_set_scene_state(
|
desktop_lock(desktop);
|
||||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
|
||||||
} else {
|
} else {
|
||||||
LoaderStatus status =
|
LoaderStatus status =
|
||||||
loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG);
|
loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG);
|
||||||
|
|||||||
@@ -81,13 +81,13 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
case DesktopLockedEventUnlocked:
|
case DesktopLockedEventUnlocked:
|
||||||
furi_hal_rtc_set_pin_fails(0);
|
desktop_unlock(desktop);
|
||||||
desktop_helpers_unlock_system(desktop);
|
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
|
||||||
desktop->scene_manager, DesktopSceneMain);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopLockedEventUpdate:
|
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);
|
desktop_view_locked_update(desktop->locked_view);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -129,16 +129,13 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopPinInputEventUnlocked:
|
case DesktopPinInputEventUnlocked:
|
||||||
desktop_view_locked_unlock(desktop->locked_view);
|
desktop_unlock(desktop);
|
||||||
furi_hal_rtc_set_pin_fails(0);
|
|
||||||
desktop_helpers_unlock_system(desktop);
|
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
|
||||||
desktop->scene_manager, DesktopSceneMain);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopPinInputEventBack:
|
case DesktopPinInputEventBack:
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
desktop->scene_manager, DesktopSceneLocked);
|
desktop->scene_manager, DesktopSceneLocked);
|
||||||
|
notification_message(desktop->notification, &sequence_display_off);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,4 +38,5 @@ typedef enum {
|
|||||||
// Global events
|
// Global events
|
||||||
DesktopGlobalBeforeAppStarted,
|
DesktopGlobalBeforeAppStarted,
|
||||||
DesktopGlobalAfterAppFinished,
|
DesktopGlobalAfterAppFinished,
|
||||||
|
DesktopGlobalAutoLock,
|
||||||
} DesktopEvent;
|
} DesktopEvent;
|
||||||
|
|||||||
@@ -114,14 +114,8 @@ bool desktop_debug_input(InputEvent* event, void* context) {
|
|||||||
DesktopViewStatsScreens current = 0;
|
DesktopViewStatsScreens current = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
debug_view->view, (DesktopDebugViewModel * model) {
|
debug_view->view, (DesktopDebugViewModel * model) {
|
||||||
#if SRV_DOLPHIN_STATE_DEBUG == 1
|
|
||||||
if(event->key == InputKeyDown) {
|
#ifdef SRV_DOLPHIN_STATE_DEBUG
|
||||||
model->screen = (model->screen + 1) % DesktopViewStatsTotalCount;
|
|
||||||
} else if(event->key == InputKeyUp) {
|
|
||||||
model->screen = ((model->screen - 1) + DesktopViewStatsTotalCount) %
|
|
||||||
DesktopViewStatsTotalCount;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
|
if((event->key == InputKeyDown) || (event->key == InputKeyUp)) {
|
||||||
model->screen = !model->screen;
|
model->screen = !model->screen;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "desktop_view_locked.h"
|
#include "desktop_view_locked.h"
|
||||||
|
|
||||||
#define DOOR_MOVING_INTERVAL_MS (1000 / 16)
|
#define DOOR_MOVING_INTERVAL_MS (1000 / 16)
|
||||||
|
#define LOCKED_HINT_TIMEOUT_MS (1000)
|
||||||
#define UNLOCKED_HINT_TIMEOUT_MS (2000)
|
#define UNLOCKED_HINT_TIMEOUT_MS (2000)
|
||||||
|
|
||||||
#define DOOR_OFFSET_START -55
|
#define DOOR_OFFSET_START -55
|
||||||
@@ -32,14 +33,18 @@ struct DesktopViewLocked {
|
|||||||
uint32_t lock_lastpress;
|
uint32_t lock_lastpress;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef enum {
|
||||||
uint32_t hint_icon_expire_at;
|
DesktopViewLockedStateUnlocked,
|
||||||
bool unlocked_hint;
|
DesktopViewLockedStateLocked,
|
||||||
bool locked;
|
DesktopViewLockedStateDoorsClosing,
|
||||||
bool pin_locked;
|
DesktopViewLockedStateLockedHintShown,
|
||||||
|
DesktopViewLockedStateUnlockedHintShown
|
||||||
|
} DesktopViewLockedState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool pin_locked;
|
||||||
int8_t door_offset;
|
int8_t door_offset;
|
||||||
bool doors_closing;
|
DesktopViewLockedState view_state;
|
||||||
} DesktopViewLockedModel;
|
} DesktopViewLockedModel;
|
||||||
|
|
||||||
void desktop_view_locked_set_callback(
|
void desktop_view_locked_set_callback(
|
||||||
@@ -78,51 +83,54 @@ static bool desktop_view_locked_doors_move(DesktopViewLockedModel* model) {
|
|||||||
|
|
||||||
static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* locked_view) {
|
static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* locked_view) {
|
||||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||||
model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
|
const bool change_state = (model->view_state == DesktopViewLockedStateLocked) &&
|
||||||
view_commit_model(locked_view->view, true);
|
!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) {
|
void desktop_view_locked_update(DesktopViewLocked* locked_view) {
|
||||||
bool stop_timer = false;
|
|
||||||
|
|
||||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||||
if(model->locked) {
|
DesktopViewLockedState view_state = model->view_state;
|
||||||
model->doors_closing = desktop_view_locked_doors_move(model);
|
|
||||||
stop_timer = !model->doors_closing;
|
if(view_state == DesktopViewLockedStateDoorsClosing &&
|
||||||
} else {
|
!desktop_view_locked_doors_move(model)) {
|
||||||
model->unlocked_hint = false;
|
model->view_state = DesktopViewLockedStateLocked;
|
||||||
stop_timer = true;
|
} 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);
|
view_commit_model(locked_view->view, true);
|
||||||
|
|
||||||
if(stop_timer) {
|
if(view_state != DesktopViewLockedStateDoorsClosing) {
|
||||||
xTimerStop(locked_view->timer, portMAX_DELAY);
|
xTimerStop(locked_view->timer, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void desktop_view_locked_draw(Canvas* canvas, void* model) {
|
static void desktop_view_locked_draw(Canvas* canvas, void* model) {
|
||||||
DesktopViewLockedModel* m = model;
|
DesktopViewLockedModel* m = model;
|
||||||
uint32_t now = osKernelGetTickCount();
|
DesktopViewLockedState view_state = m->view_state;
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
if(m->locked) {
|
if(view_state == DesktopViewLockedStateDoorsClosing) {
|
||||||
if(m->doors_closing) {
|
desktop_view_locked_doors_draw(canvas, m);
|
||||||
desktop_view_locked_doors_draw(canvas, m);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
canvas_set_font(canvas, FontPrimary);
|
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked");
|
||||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked");
|
} else if(view_state == DesktopViewLockedStateLockedHintShown) {
|
||||||
} else if((now < m->hint_icon_expire_at) && !m->pin_locked) {
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_set_font(canvas, FontSecondary);
|
elements_bold_rounded_frame(canvas, 14, 2 + STATUS_BAR_Y_SHIFT, 99, 48);
|
||||||
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:");
|
||||||
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, 65, 36 + STATUS_BAR_Y_SHIFT, &I_Back3_45x8);
|
canvas_draw_icon(canvas, 16, 7 + STATUS_BAR_Y_SHIFT, &I_WarningDolphin_45x42);
|
||||||
canvas_draw_icon(canvas, 16, 7 + STATUS_BAR_Y_SHIFT, &I_WarningDolphin_45x42);
|
canvas_draw_dot(canvas, 17, 61);
|
||||||
canvas_draw_dot(canvas, 17, 61);
|
} else if(view_state == DesktopViewLockedStateUnlockedHintShown) {
|
||||||
}
|
canvas_set_font(canvas, FontPrimary);
|
||||||
} else {
|
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked");
|
||||||
if(m->unlocked_hint) {
|
|
||||||
canvas_set_font(canvas, FontPrimary);
|
|
||||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,43 +142,38 @@ View* desktop_view_locked_get_view(DesktopViewLocked* locked_view) {
|
|||||||
static bool desktop_view_locked_input(InputEvent* event, void* context) {
|
static bool desktop_view_locked_input(InputEvent* event, void* context) {
|
||||||
furi_assert(event);
|
furi_assert(event);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
|
bool is_changed = false;
|
||||||
|
const uint32_t press_time = xTaskGetTickCount();
|
||||||
DesktopViewLocked* locked_view = context;
|
DesktopViewLocked* locked_view = context;
|
||||||
bool locked = false;
|
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||||
bool locked_with_pin = false;
|
if(model->view_state == DesktopViewLockedStateUnlockedHintShown &&
|
||||||
bool doors_closing = false;
|
event->type == InputTypePress) {
|
||||||
uint32_t press_time = xTaskGetTickCount();
|
model->view_state = DesktopViewLockedStateUnlocked;
|
||||||
|
is_changed = true;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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)) {
|
if(view_state == DesktopViewLockedStateUnlocked || event->type != InputTypeShort) {
|
||||||
return locked;
|
return view_state != DesktopViewLockedStateUnlocked;
|
||||||
}
|
} else if(view_state == DesktopViewLockedStateLocked && pin_locked) {
|
||||||
|
|
||||||
if(locked_with_pin) {
|
|
||||||
locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
|
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) {
|
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
|
||||||
locked_view->lock_lastpress = press_time;
|
locked_view->lock_lastpress = press_time;
|
||||||
locked_view->lock_count = 0;
|
locked_view->lock_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop_view_locked_update_hint_icon_timeout(locked_view);
|
desktop_view_locked_update_hint_icon_timeout(locked_view);
|
||||||
|
|
||||||
if(event->key == InputKeyBack) {
|
if(event->key == InputKeyBack) {
|
||||||
locked_view->lock_lastpress = press_time;
|
locked_view->lock_lastpress = press_time;
|
||||||
locked_view->lock_count++;
|
locked_view->lock_count++;
|
||||||
if(locked_view->lock_count == UNLOCK_CNT) {
|
if(locked_view->lock_count == UNLOCK_CNT) {
|
||||||
desktop_view_locked_unlock(locked_view);
|
|
||||||
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
|
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -180,7 +183,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
|
|||||||
locked_view->lock_lastpress = press_time;
|
locked_view->lock_lastpress = press_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
return locked;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopViewLocked* desktop_view_locked_alloc() {
|
DesktopViewLocked* desktop_view_locked_alloc() {
|
||||||
@@ -189,7 +192,6 @@ DesktopViewLocked* desktop_view_locked_alloc() {
|
|||||||
locked_view->timer =
|
locked_view->timer =
|
||||||
xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
|
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_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopViewLockedModel));
|
||||||
view_set_context(locked_view->view, locked_view);
|
view_set_context(locked_view->view, locked_view);
|
||||||
view_set_draw_callback(locked_view->view, desktop_view_locked_draw);
|
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) {
|
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) {
|
||||||
DesktopViewLockedModel* model = view_get_model(locked_view->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;
|
model->door_offset = DOOR_OFFSET_START;
|
||||||
view_commit_model(locked_view->view, true);
|
view_commit_model(locked_view->view, true);
|
||||||
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(DOOR_MOVING_INTERVAL_MS), portMAX_DELAY);
|
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) {
|
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) {
|
||||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
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;
|
model->pin_locked = pin_locked;
|
||||||
view_commit_model(locked_view->view, true);
|
view_commit_model(locked_view->view, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_view_locked_unlock(DesktopViewLocked* locked_view) {
|
void desktop_view_locked_unlock(DesktopViewLocked* locked_view) {
|
||||||
furi_assert(locked_view);
|
|
||||||
|
|
||||||
locked_view->lock_count = 0;
|
locked_view->lock_count = 0;
|
||||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||||
model->locked = false;
|
model->view_state = DesktopViewLockedStateUnlockedHintShown;
|
||||||
model->pin_locked = false;
|
model->pin_locked = false;
|
||||||
model->unlocked_hint = true;
|
|
||||||
view_commit_model(locked_view->view, true);
|
view_commit_model(locked_view->view, true);
|
||||||
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(UNLOCKED_HINT_TIMEOUT_MS), portMAX_DELAY);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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_lock(DesktopViewLocked* locked_view, bool pin_locked);
|
||||||
void desktop_view_locked_unlock(DesktopViewLocked* locked_view);
|
void desktop_view_locked_unlock(DesktopViewLocked* locked_view);
|
||||||
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view);
|
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view);
|
||||||
|
bool desktop_view_locked_is_locked_hint_visible(DesktopViewLocked* locked_view);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
#include "scene/ibutton_scene_read_crc_error.h"
|
#include "scene/ibutton_scene_read_crc_error.h"
|
||||||
#include "scene/ibutton_scene_read_not_key_error.h"
|
#include "scene/ibutton_scene_read_not_key_error.h"
|
||||||
#include "scene/ibutton_scene_read_success.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.h"
|
||||||
#include "scene/ibutton_scene_write_success.h"
|
#include "scene/ibutton_scene_write_success.h"
|
||||||
#include "scene/ibutton_scene_saved_key_menu.h"
|
#include "scene/ibutton_scene_saved_key_menu.h"
|
||||||
@@ -42,7 +44,9 @@ public:
|
|||||||
SceneReadNotKeyError,
|
SceneReadNotKeyError,
|
||||||
SceneReadCRCError,
|
SceneReadCRCError,
|
||||||
SceneReadSuccess,
|
SceneReadSuccess,
|
||||||
SceneReadedKeyMenu,
|
SceneRetryConfirm,
|
||||||
|
SceneExitConfirm,
|
||||||
|
SceneReadKeyMenu,
|
||||||
SceneWrite,
|
SceneWrite,
|
||||||
SceneWriteSuccess,
|
SceneWriteSuccess,
|
||||||
SceneEmulate,
|
SceneEmulate,
|
||||||
@@ -105,7 +109,9 @@ private:
|
|||||||
{Scene::SceneReadCRCError, new iButtonSceneReadCRCError()},
|
{Scene::SceneReadCRCError, new iButtonSceneReadCRCError()},
|
||||||
{Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()},
|
{Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()},
|
||||||
{Scene::SceneReadSuccess, new iButtonSceneReadSuccess()},
|
{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::SceneWrite, new iButtonSceneWrite()},
|
||||||
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
|
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
|
||||||
{Scene::SceneEmulate, new iButtonSceneEmulate()},
|
{Scene::SceneEmulate, new iButtonSceneEmulate()},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) {
|
|||||||
Popup* popup = view_manager->get_popup();
|
Popup* popup = view_manager->get_popup();
|
||||||
|
|
||||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
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_callback(popup, popup_callback);
|
||||||
popup_set_context(popup, app);
|
popup_set_context(popup, app);
|
||||||
|
|||||||
51
applications/ibutton/scene/ibutton_scene_exit_confirm.cpp
Normal file
51
applications/ibutton/scene/ibutton_scene_exit_confirm.cpp
Normal 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);
|
||||||
|
}
|
||||||
9
applications/ibutton/scene/ibutton_scene_exit_confirm.h
Normal file
9
applications/ibutton/scene/ibutton_scene_exit_confirm.h
Normal 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;
|
||||||
|
};
|
||||||
@@ -34,15 +34,22 @@ bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
|
|
||||||
iButtonKey* key = app->get_key();
|
iButtonKey* key = app->get_key();
|
||||||
|
bool success = false;
|
||||||
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
||||||
if(!ibutton_key_dallas_crc_is_valid(key)) {
|
if(!ibutton_key_dallas_crc_is_valid(key)) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError);
|
||||||
} else if(!ibutton_key_dallas_is_1990_key(key)) {
|
} else if(!ibutton_key_dallas_is_1990_key(key)) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError);
|
||||||
} else {
|
} else {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
|
success = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
if(success) {
|
||||||
|
app->notify_success();
|
||||||
|
app->notify_green_on();
|
||||||
|
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
|
||||||
}
|
}
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeTick) {
|
} else if(event->type == iButtonEvent::Type::EventTypeTick) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ bool iButtonSceneReadCRCError::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
if(event->payload.dialog_result == DialogExResultRight) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
||||||
} else {
|
} else {
|
||||||
app->switch_to_previous_scene();
|
app->switch_to_previous_scene();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#include "ibutton_scene_readed_key_menu.h"
|
#include "ibutton_scene_read_key_menu.h"
|
||||||
#include "../ibutton_app.h"
|
#include "../ibutton_app.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexWrite,
|
||||||
SubmenuIndexEmulate,
|
SubmenuIndexEmulate,
|
||||||
SubmenuIndexSave,
|
SubmenuIndexSave,
|
||||||
SubmenuIndexReadNewKey,
|
|
||||||
} SubmenuIndex;
|
} SubmenuIndex;
|
||||||
|
|
||||||
static void submenu_callback(void* context, uint32_t index) {
|
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);
|
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();
|
iButtonAppViewManager* view_manager = app->get_view_manager();
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
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, "Save", SubmenuIndexSave, submenu_callback, app);
|
||||||
submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, 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);
|
submenu_set_selected_item(submenu, submenu_item_selected);
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
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;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
||||||
@@ -49,20 +47,17 @@ bool iButtonSceneReadedKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
case SubmenuIndexSave:
|
case SubmenuIndexSave:
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName);
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexReadNewKey:
|
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneRead});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart});
|
app->switch_to_previous_scene();
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iButtonSceneReadedKeyMenu::on_exit(iButtonApp* app) {
|
void iButtonSceneReadKeyMenu::on_exit(iButtonApp* app) {
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
iButtonAppViewManager* view = app->get_view_manager();
|
||||||
Submenu* submenu = view->get_submenu();
|
Submenu* submenu = view->get_submenu();
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ibutton_scene_generic.h"
|
#include "ibutton_scene_generic.h"
|
||||||
|
|
||||||
class iButtonSceneReadedKeyMenu : public iButtonScene {
|
class iButtonSceneReadKeyMenu : public iButtonScene {
|
||||||
public:
|
public:
|
||||||
void on_enter(iButtonApp* app) final;
|
void on_enter(iButtonApp* app) final;
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
||||||
@@ -47,7 +47,7 @@ bool iButtonSceneReadNotKeyError::on_event(iButtonApp* app, iButtonEvent* event)
|
|||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
if(event->payload.dialog_result == DialogExResultRight) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
||||||
} else {
|
} else {
|
||||||
app->switch_to_previous_scene();
|
app->switch_to_previous_scene();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) {
|
|||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
||||||
iButtonKey* key = app->get_key();
|
iButtonKey* key = app->get_key();
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
|
||||||
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
switch(ibutton_key_get_type(key)) {
|
||||||
case iButtonKeyDS1990:
|
case iButtonKeyDS1990:
|
||||||
@@ -50,9 +49,6 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) {
|
|||||||
dialog_ex_set_context(dialog_ex, app);
|
dialog_ex_set_context(dialog_ex, app);
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
|
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
|
||||||
|
|
||||||
app->notify_success();
|
|
||||||
app->notify_green_on();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool iButtonSceneReadSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
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->type == iButtonEvent::Type::EventTypeDialogResult) {
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
if(event->payload.dialog_result == DialogExResultRight) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadedKeyMenu);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
||||||
} else {
|
} 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;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
applications/ibutton/scene/ibutton_scene_retry_confirm.cpp
Normal file
51
applications/ibutton/scene/ibutton_scene_retry_confirm.cpp
Normal 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);
|
||||||
|
}
|
||||||
9
applications/ibutton/scene/ibutton_scene_retry_confirm.h
Normal file
9
applications/ibutton/scene/ibutton_scene_retry_confirm.h
Normal 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;
|
||||||
|
};
|
||||||
@@ -49,7 +49,7 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
|
||||||
} else {
|
} else {
|
||||||
app->search_and_switch_to_previous_scene(
|
app->search_and_switch_to_previous_scene(
|
||||||
{iButtonApp::Scene::SceneReadedKeyMenu,
|
{iButtonApp::Scene::SceneReadKeyMenu,
|
||||||
iButtonApp::Scene::SceneSavedKeyMenu,
|
iButtonApp::Scene::SceneSavedKeyMenu,
|
||||||
iButtonApp::Scene::SceneAddType});
|
iButtonApp::Scene::SceneAddType});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) {
|
|||||||
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
||||||
|
|
||||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
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_callback(popup, popup_callback);
|
||||||
popup_set_context(popup, app);
|
popup_set_context(popup, app);
|
||||||
@@ -31,7 +31,7 @@ bool iButtonSceneSaveSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
||||||
app->search_and_switch_to_previous_scene(
|
app->search_and_switch_to_previous_scene(
|
||||||
{iButtonApp::Scene::SceneReadedKeyMenu,
|
{iButtonApp::Scene::SceneReadKeyMenu,
|
||||||
iButtonApp::Scene::SceneSavedKeyMenu,
|
iButtonApp::Scene::SceneSavedKeyMenu,
|
||||||
iButtonApp::Scene::SceneAddType});
|
iButtonApp::Scene::SceneAddType});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ bool iButtonSceneWriteSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
||||||
app->search_and_switch_to_previous_scene(
|
app->search_and_switch_to_previous_scene(
|
||||||
{iButtonApp::Scene::SceneReadedKeyMenu, iButtonApp::Scene::SceneStart});
|
{iButtonApp::Scene::SceneReadKeyMenu, iButtonApp::Scene::SceneStart});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ void InfraredAppSceneEditRenameDone::on_enter(InfraredApp* app) {
|
|||||||
Popup* popup = view_manager->get_popup();
|
Popup* popup = view_manager->get_popup();
|
||||||
|
|
||||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||||
|
|
||||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||||
|
|
||||||
popup_set_callback(popup, InfraredApp::popup_callback);
|
popup_set_callback(popup, InfraredApp::popup_callback);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ constexpr uint32_t long_time_high = long_time + jitter_time;
|
|||||||
|
|
||||||
void DecoderEMMarin::reset_state() {
|
void DecoderEMMarin::reset_state() {
|
||||||
ready = false;
|
ready = false;
|
||||||
readed_data = 0;
|
read_data = 0;
|
||||||
manchester_advance(
|
manchester_advance(
|
||||||
manchester_saved_state, ManchesterEventReset, &manchester_saved_state, nullptr);
|
manchester_saved_state, ManchesterEventReset, &manchester_saved_state, nullptr);
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ bool DecoderEMMarin::read(uint8_t* data, uint8_t data_size) {
|
|||||||
if(ready) {
|
if(ready) {
|
||||||
result = true;
|
result = true;
|
||||||
em_marin.decode(
|
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;
|
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);
|
manchester_advance(manchester_saved_state, event, &manchester_saved_state, &data);
|
||||||
|
|
||||||
if(data_ok) {
|
if(data_ok) {
|
||||||
readed_data = (readed_data << 1) | data;
|
read_data = (read_data << 1) | data;
|
||||||
|
|
||||||
ready = em_marin.can_be_decoded(
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void reset_state();
|
void reset_state();
|
||||||
|
|
||||||
uint64_t readed_data = 0;
|
uint64_t read_data = 0;
|
||||||
std::atomic<bool> ready;
|
std::atomic<bool> ready;
|
||||||
|
|
||||||
ManchesterState manchester_saved_state;
|
ManchesterState manchester_saved_state;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ void RfidReader::start() {
|
|||||||
start_comparator();
|
start_comparator();
|
||||||
|
|
||||||
switch_timer_reset();
|
switch_timer_reset();
|
||||||
last_readed_count = 0;
|
last_read_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfidReader::start_forced(RfidReader::Type _type) {
|
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 RfidReader::read(LfrfidKeyType* _type, uint8_t* data, uint8_t data_size, bool switch_enable) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool something_readed = false;
|
bool something_read = false;
|
||||||
|
|
||||||
// reading
|
// reading
|
||||||
if(decoder_em.read(data, data_size)) {
|
if(decoder_em.read(data, data_size)) {
|
||||||
*_type = LfrfidKeyType::KeyEM4100;
|
*_type = LfrfidKeyType::KeyEM4100;
|
||||||
something_readed = true;
|
something_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(decoder_hid26.read(data, data_size)) {
|
if(decoder_hid26.read(data, data_size)) {
|
||||||
*_type = LfrfidKeyType::KeyH10301;
|
*_type = LfrfidKeyType::KeyH10301;
|
||||||
something_readed = true;
|
something_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(decoder_indala.read(data, data_size)) {
|
if(decoder_indala.read(data, data_size)) {
|
||||||
*_type = LfrfidKeyType::KeyI40134;
|
*_type = LfrfidKeyType::KeyI40134;
|
||||||
something_readed = true;
|
something_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
if(something_readed) {
|
if(something_read) {
|
||||||
switch_timer_reset();
|
switch_timer_reset();
|
||||||
|
|
||||||
if(last_readed_type == *_type && memcmp(last_readed_data, data, data_size) == 0) {
|
if(last_read_type == *_type && memcmp(last_read_data, data, data_size) == 0) {
|
||||||
last_readed_count = last_readed_count + 1;
|
last_read_count = last_read_count + 1;
|
||||||
|
|
||||||
if(last_readed_count > 2) {
|
if(last_read_count > 2) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
last_readed_type = *_type;
|
last_read_type = *_type;
|
||||||
memcpy(last_readed_data, data, data_size);
|
memcpy(last_read_data, data, data_size);
|
||||||
last_readed_count = 0;
|
last_read_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mode switching
|
// mode switching
|
||||||
if(switch_enable && switch_timer_elapsed()) {
|
if(switch_enable && switch_timer_elapsed()) {
|
||||||
switch_mode();
|
switch_mode();
|
||||||
last_readed_count = 0;
|
last_read_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -152,7 +152,7 @@ bool RfidReader::detect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RfidReader::any_read() {
|
bool RfidReader::any_read() {
|
||||||
return last_readed_count > 0;
|
return last_read_count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfidReader::start_comparator(void) {
|
void RfidReader::start_comparator(void) {
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ private:
|
|||||||
void switch_timer_reset();
|
void switch_timer_reset();
|
||||||
void switch_mode();
|
void switch_mode();
|
||||||
|
|
||||||
LfrfidKeyType last_readed_type;
|
LfrfidKeyType last_read_type;
|
||||||
uint8_t last_readed_data[LFRFID_KEY_SIZE];
|
uint8_t last_read_data[LFRFID_KEY_SIZE];
|
||||||
uint8_t last_readed_count;
|
uint8_t last_read_count;
|
||||||
|
|
||||||
Type type = Type::Normal;
|
Type type = Type::Normal;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#include "scene/lfrfid_app_scene_start.h"
|
#include "scene/lfrfid_app_scene_start.h"
|
||||||
#include "scene/lfrfid_app_scene_read.h"
|
#include "scene/lfrfid_app_scene_read.h"
|
||||||
#include "scene/lfrfid_app_scene_read_success.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.h"
|
||||||
#include "scene/lfrfid_app_scene_write_success.h"
|
#include "scene/lfrfid_app_scene_write_success.h"
|
||||||
#include "scene/lfrfid_app_scene_emulate.h"
|
#include "scene/lfrfid_app_scene_emulate.h"
|
||||||
@@ -48,8 +50,10 @@ void LfRfidApp::run(void* _args) {
|
|||||||
} else {
|
} else {
|
||||||
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
||||||
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
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::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::Write, new LfRfidAppSceneWrite());
|
||||||
scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
|
scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
|
||||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||||
|
|||||||
@@ -27,13 +27,17 @@ public:
|
|||||||
GENERIC_EVENT_ENUM_VALUES,
|
GENERIC_EVENT_ENUM_VALUES,
|
||||||
Next,
|
Next,
|
||||||
MenuSelected,
|
MenuSelected,
|
||||||
|
Stay,
|
||||||
|
Retry,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceneType : uint8_t {
|
enum class SceneType : uint8_t {
|
||||||
GENERIC_SCENE_ENUM_VALUES,
|
GENERIC_SCENE_ENUM_VALUES,
|
||||||
Read,
|
Read,
|
||||||
ReadSuccess,
|
ReadSuccess,
|
||||||
ReadedMenu,
|
RetryConfirm,
|
||||||
|
ExitConfirm,
|
||||||
|
ReadKeyMenu,
|
||||||
Write,
|
Write,
|
||||||
WriteSuccess,
|
WriteSuccess,
|
||||||
Emulate,
|
Emulate,
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* eve
|
|||||||
app->delete_key(&app->worker.key);
|
app->delete_key(&app->worker.key);
|
||||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
|
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
|
||||||
consumed = true;
|
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;
|
return consumed;
|
||||||
@@ -88,7 +93,7 @@ void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) {
|
|||||||
void LfRfidAppSceneDeleteConfirm::back_callback(void* context) {
|
void LfRfidAppSceneDeleteConfirm::back_callback(void* context) {
|
||||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::Back;
|
event.type = LfRfidApp::EventType::Stay;
|
||||||
app->view_controller.send_event(&event);
|
app->view_controller.send_event(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool need_restore) {
|
|||||||
auto popup = app->view_controller.get<PopupVM>();
|
auto popup = app->view_controller.get<PopupVM>();
|
||||||
|
|
||||||
popup->set_icon(0, 2, &I_DolphinMafia_115x62);
|
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_context(app);
|
||||||
popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback);
|
popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback);
|
||||||
popup->set_timeout(1500);
|
popup->set_timeout(1500);
|
||||||
|
|||||||
59
applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp
Normal file
59
applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp
Normal 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);
|
||||||
|
}
|
||||||
13
applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h
Normal file
13
applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h
Normal 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);
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "lfrfid_app_scene_readed_menu.h"
|
#include "lfrfid_app_scene_read_menu.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubmenuWrite,
|
SubmenuWrite,
|
||||||
@@ -6,7 +6,7 @@ typedef enum {
|
|||||||
SubmenuEmulate,
|
SubmenuEmulate,
|
||||||
} SubmenuIndex;
|
} 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>();
|
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||||
|
|
||||||
submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
|
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>();
|
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;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||||
@@ -38,18 +38,18 @@ bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event)
|
|||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
} 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;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LfRfidAppSceneReadedMenu::on_exit(LfRfidApp* app) {
|
void LfRfidAppSceneReadKeyMenu::on_exit(LfRfidApp* app) {
|
||||||
app->view_controller.get<SubmenuVM>()->clean();
|
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* app = static_cast<LfRfidApp*>(context);
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../lfrfid_app.h"
|
#include "../lfrfid_app.h"
|
||||||
|
|
||||||
class LfRfidAppSceneReadedMenu : public GenericScene<LfRfidApp> {
|
class LfRfidAppSceneReadKeyMenu : public GenericScene<LfRfidApp> {
|
||||||
public:
|
public:
|
||||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||||
@@ -85,7 +85,13 @@ bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == LfRfidApp::EventType::Next) {
|
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;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +109,7 @@ void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
|
|||||||
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
|
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
|
||||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::Back;
|
event.type = LfRfidApp::EventType::Retry;
|
||||||
app->view_controller.send_event(&event);
|
app->view_controller.send_event(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp
Normal file
59
applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp
Normal 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);
|
||||||
|
}
|
||||||
13
applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h
Normal file
13
applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h
Normal 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);
|
||||||
|
};
|
||||||
@@ -42,7 +42,7 @@ bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
|
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
|
||||||
} else {
|
} else {
|
||||||
app->scene_controller.search_and_switch_to_previous_scene(
|
app->scene_controller.search_and_switch_to_previous_scene(
|
||||||
{LfRfidApp::SceneType::ReadedMenu});
|
{LfRfidApp::SceneType::ReadKeyMenu});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool need_restore) {
|
|||||||
|
|
||||||
DOLPHIN_DEED(DolphinDeedRfidSave);
|
DOLPHIN_DEED(DolphinDeedRfidSave);
|
||||||
popup->set_icon(32, 5, &I_DolphinNice_96x59);
|
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_context(app);
|
||||||
popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback);
|
popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback);
|
||||||
popup->set_timeout(1500);
|
popup->set_timeout(1500);
|
||||||
@@ -22,11 +22,11 @@ bool LfRfidAppSceneSaveSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event
|
|||||||
|
|
||||||
if(event->type == LfRfidApp::EventType::Back) {
|
if(event->type == LfRfidApp::EventType::Back) {
|
||||||
bool result = app->scene_controller.has_previous_scene(
|
bool result = app->scene_controller.has_previous_scene(
|
||||||
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
|
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
app->scene_controller.search_and_switch_to_previous_scene(
|
app->scene_controller.search_and_switch_to_previous_scene(
|
||||||
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
|
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||||
} else {
|
} else {
|
||||||
app->scene_controller.search_and_switch_to_another_scene(
|
app->scene_controller.search_and_switch_to_another_scene(
|
||||||
{LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey);
|
{LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ bool LfRfidAppSceneWriteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* even
|
|||||||
|
|
||||||
if(event->type == LfRfidApp::EventType::Back) {
|
if(event->type == LfRfidApp::EventType::Back) {
|
||||||
app->scene_controller.search_and_switch_to_previous_scene(
|
app->scene_controller.search_and_switch_to_previous_scene(
|
||||||
{LfRfidApp::SceneType::ReadedMenu, LfRfidApp::SceneType::SelectKey});
|
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
#include <input/input.h>
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
#include "notification_messages.h"
|
#include "notification_messages.h"
|
||||||
#include "notification_app.h"
|
#include "notification_app.h"
|
||||||
@@ -163,7 +164,6 @@ void notification_process_notification_message(
|
|||||||
notification_message = (*message->sequence)[notification_message_index];
|
notification_message = (*message->sequence)[notification_message_index];
|
||||||
|
|
||||||
bool led_active = false;
|
bool led_active = false;
|
||||||
uint8_t display_led_lock = 0;
|
|
||||||
uint8_t led_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00};
|
uint8_t led_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00};
|
||||||
bool reset_notifications = true;
|
bool reset_notifications = true;
|
||||||
float speaker_volume_setting = app->settings.speaker_volume;
|
float speaker_volume_setting = app->settings.speaker_volume;
|
||||||
@@ -191,18 +191,18 @@ void notification_process_notification_message(
|
|||||||
reset_mask |= reset_display_mask;
|
reset_mask |= reset_display_mask;
|
||||||
break;
|
break;
|
||||||
case NotificationMessageTypeLedDisplayLock:
|
case NotificationMessageTypeLedDisplayLock:
|
||||||
furi_assert(display_led_lock < UINT8_MAX);
|
furi_assert(app->display_led_lock < UINT8_MAX);
|
||||||
display_led_lock++;
|
app->display_led_lock++;
|
||||||
if(display_led_lock == 1) {
|
if(app->display_led_lock == 1) {
|
||||||
notification_apply_internal_led_layer(
|
notification_apply_internal_led_layer(
|
||||||
&app->display,
|
&app->display,
|
||||||
notification_message->data.led.value * display_brightness_setting);
|
notification_message->data.led.value * display_brightness_setting);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NotificationMessageTypeLedDisplayUnlock:
|
case NotificationMessageTypeLedDisplayUnlock:
|
||||||
furi_assert(display_led_lock > 0);
|
furi_assert(app->display_led_lock > 0);
|
||||||
display_led_lock--;
|
app->display_led_lock--;
|
||||||
if(display_led_lock == 0) {
|
if(app->display_led_lock == 0) {
|
||||||
notification_apply_internal_led_layer(
|
notification_apply_internal_led_layer(
|
||||||
&app->display,
|
&app->display,
|
||||||
notification_message->data.led.value * display_brightness_setting);
|
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) {
|
static void input_event_callback(const void* value, void* context) {
|
||||||
|
furi_assert(value);
|
||||||
|
furi_assert(context);
|
||||||
|
const InputEvent* event = value;
|
||||||
NotificationApp* app = context;
|
NotificationApp* app = context;
|
||||||
notification_message(app, &sequence_display_on);
|
if(event->type == InputTypePress) {
|
||||||
|
notification_message(app, &sequence_display_on);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// App alloc
|
// App alloc
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ struct NotificationApp {
|
|||||||
|
|
||||||
NotificationLedLayer display;
|
NotificationLedLayer display;
|
||||||
NotificationLedLayer led[NOTIFICATION_LED_COUNT];
|
NotificationLedLayer led[NOTIFICATION_LED_COUNT];
|
||||||
|
uint8_t display_led_lock;
|
||||||
|
|
||||||
NotificationSettings settings;
|
NotificationSettings settings;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const NotificationMessage message_display_lock = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NotificationMessage message_display_unlock = {
|
const NotificationMessage message_display_unlock = {
|
||||||
.type = NotificationMessageTypeLedDisplayLock,
|
.type = NotificationMessageTypeLedDisplayUnlock,
|
||||||
.data.led.value = 0x00,
|
.data.led.value = 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,6 +208,12 @@ const NotificationSequence sequence_display_unlock = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NotificationSequence sequence_display_off_delay_1000 = {
|
||||||
|
&message_delay_1000,
|
||||||
|
&message_display_off,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
// Charging
|
// Charging
|
||||||
const NotificationSequence sequence_charging = {
|
const NotificationSequence sequence_charging = {
|
||||||
&message_red_255,
|
&message_red_255,
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ extern const NotificationSequence sequence_display_off;
|
|||||||
extern const NotificationSequence sequence_display_lock;
|
extern const NotificationSequence sequence_display_lock;
|
||||||
/** Display: backlight always on unlock */
|
/** Display: backlight always on unlock */
|
||||||
extern const NotificationSequence sequence_display_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
|
// Charging
|
||||||
extern const NotificationSequence sequence_charging;
|
extern const NotificationSequence sequence_charging;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "notification_app.h"
|
#include "notification_app.h"
|
||||||
#include <gui/modules/variable_item_list.h>
|
#include <gui/modules/variable_item_list.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <lib/toolbox/value_index.h>
|
||||||
|
|
||||||
#define MAX_NOTIFICATION_SETTINGS 4
|
#define MAX_NOTIFICATION_SETTINGS 4
|
||||||
|
|
||||||
@@ -63,44 +64,6 @@ const char* const vibro_text[VIBRO_COUNT] = {
|
|||||||
};
|
};
|
||||||
const bool vibro_value[VIBRO_COUNT] = {false, true};
|
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) {
|
static void backlight_changed(VariableItem* item) {
|
||||||
NotificationAppSettings* app = variable_item_get_context(item);
|
NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
uint8_t index = variable_item_get_current_value_index(item);
|
uint8_t index = variable_item_get_current_value_index(item);
|
||||||
@@ -164,21 +127,21 @@ static NotificationAppSettings* alloc_settings() {
|
|||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
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);
|
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||||
variable_item_set_current_value_index(item, value_index);
|
variable_item_set_current_value_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, backlight_text[value_index]);
|
variable_item_set_current_value_text(item, backlight_text[value_index]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
app->variable_item_list, "Backlight Time", DELAY_COUNT, screen_changed, app);
|
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);
|
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_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, delay_text[value_index]);
|
variable_item_set_current_value_text(item, delay_text[value_index]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
app->variable_item_list, "LED Brightness", BACKLIGHT_COUNT, led_changed, app);
|
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);
|
app->notification->settings.led_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||||
variable_item_set_current_value_index(item, value_index);
|
variable_item_set_current_value_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, backlight_text[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(
|
item = variable_item_list_add(
|
||||||
app->variable_item_list, "Volume", VOLUME_COUNT, volume_changed, app);
|
app->variable_item_list, "Volume", VOLUME_COUNT, volume_changed, app);
|
||||||
value_index =
|
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_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, volume_text[value_index]);
|
variable_item_set_current_value_text(item, volume_text[value_index]);
|
||||||
|
|
||||||
item =
|
item =
|
||||||
variable_item_list_add(app->variable_item_list, "Vibro", VIBRO_COUNT, vibro_changed, app);
|
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_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, vibro_text[value_index]);
|
variable_item_set_current_value_text(item, vibro_text[value_index]);
|
||||||
|
|
||||||
|
|||||||
@@ -473,17 +473,17 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
|||||||
File* file = storage_file_alloc(fs_api);
|
File* file = storage_file_alloc(fs_api);
|
||||||
|
|
||||||
if(storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
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;
|
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);
|
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||||
|
|
||||||
md5_starts(md5_ctx);
|
md5_starts(md5_ctx);
|
||||||
while(true) {
|
while(true) {
|
||||||
uint16_t readed_size = storage_file_read(file, data, read_size);
|
uint16_t read_size = storage_file_read(file, data, size_to_read);
|
||||||
if(readed_size == 0) break;
|
if(read_size == 0) break;
|
||||||
md5_update(md5_ctx, data, readed_size);
|
md5_update(md5_ctx, data, read_size);
|
||||||
}
|
}
|
||||||
md5_finish(md5_ctx, hash);
|
md5_finish(md5_ctx, hash);
|
||||||
free(md5_ctx);
|
free(md5_ctx);
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ struct File {
|
|||||||
* @param file pointer to file object
|
* @param file pointer to file object
|
||||||
* @param buff pointer to buffer for reading
|
* @param buff pointer to buffer for reading
|
||||||
* @param bytes_to_read how many bytes to read, must be smaller or equal to buffer size
|
* @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
|
* @var FS_File_Api::write
|
||||||
* @brief Write bytes from buffer to file
|
* @brief Write bytes from buffer to file
|
||||||
* @param file pointer to file object
|
* @param file pointer to file object
|
||||||
* @param buff pointer to buffer for writing
|
* @param buff pointer to buffer for writing
|
||||||
* @param bytes_to_read how many bytes to write, must be smaller or equal to buffer size
|
* @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
|
* @var FS_File_Api::seek
|
||||||
* @brief Move r/w pointer
|
* @brief Move r/w pointer
|
||||||
@@ -107,7 +107,7 @@ typedef struct {
|
|||||||
* @var FS_Dir_Api::read
|
* @var FS_Dir_Api::read
|
||||||
* @brief Read next object info in directory
|
* @brief Read next object info in directory
|
||||||
* @param file pointer to file object
|
* @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 pointer to name buffer, can be NULL
|
||||||
* @param name_length name buffer length
|
* @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)
|
* @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
|
* @var FS_Common_Api::stat
|
||||||
* @brief Open directory to get objects from
|
* @brief Open directory to get objects from
|
||||||
* @param path path to file/directory
|
* @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 pointer to name buffer, can be NULL
|
||||||
* @param name_length name buffer length
|
* @param name_length name buffer length
|
||||||
* @return FS_Error error info
|
* @return FS_Error error info
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ bool storage_file_is_dir(File* file);
|
|||||||
* @param file pointer to file object.
|
* @param file pointer to file object.
|
||||||
* @param buff pointer to a buffer, for reading
|
* @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.
|
* @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);
|
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
|
/** Reads the next object in the directory
|
||||||
* @param file pointer to file object.
|
* @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 pointer to name buffer, may be NULL
|
||||||
* @param name_length name buffer length
|
* @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)
|
* @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
|
/** Retrieves information about a file/directory
|
||||||
* @param app pointer to the api
|
* @param app pointer to the api
|
||||||
* @param path path to file/directory
|
* @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
|
* @return FS_Error operation result
|
||||||
*/
|
*/
|
||||||
FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo);
|
FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo);
|
||||||
|
|||||||
@@ -112,10 +112,10 @@ static void storage_cli_list(Cli* cli, string_t path) {
|
|||||||
if(storage_dir_open(file, string_get_cstr(path))) {
|
if(storage_dir_open(file, string_get_cstr(path))) {
|
||||||
FileInfo fileinfo;
|
FileInfo fileinfo;
|
||||||
char name[MAX_NAME_LENGTH];
|
char name[MAX_NAME_LENGTH];
|
||||||
bool readed = false;
|
bool read_done = false;
|
||||||
|
|
||||||
while(storage_dir_read(file, &fileinfo, name, MAX_NAME_LENGTH)) {
|
while(storage_dir_read(file, &fileinfo, name, MAX_NAME_LENGTH)) {
|
||||||
readed = true;
|
read_done = true;
|
||||||
if(fileinfo.flags & FSF_DIRECTORY) {
|
if(fileinfo.flags & FSF_DIRECTORY) {
|
||||||
printf("\t[D] %s\r\n", name);
|
printf("\t[D] %s\r\n", name);
|
||||||
} else {
|
} else {
|
||||||
@@ -123,7 +123,7 @@ static void storage_cli_list(Cli* cli, string_t path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!readed) {
|
if(!read_done) {
|
||||||
printf("\tEmpty\r\n");
|
printf("\tEmpty\r\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -141,18 +141,18 @@ static void storage_cli_read(Cli* cli, string_t path) {
|
|||||||
File* file = storage_file_alloc(api);
|
File* file = storage_file_alloc(api);
|
||||||
|
|
||||||
if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
const uint16_t read_size = 128;
|
const uint16_t size_to_read = 128;
|
||||||
uint16_t readed_size = 0;
|
uint16_t read_size = 0;
|
||||||
uint8_t* data = malloc(read_size);
|
uint8_t* data = malloc(read_size);
|
||||||
|
|
||||||
printf("Size: %lu\r\n", (uint32_t)storage_file_size(file));
|
printf("Size: %lu\r\n", (uint32_t)storage_file_size(file));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
readed_size = storage_file_read(file, data, read_size);
|
read_size = storage_file_read(file, data, size_to_read);
|
||||||
for(uint16_t i = 0; i < readed_size; i++) {
|
for(uint16_t i = 0; i < read_size; i++) {
|
||||||
printf("%c", data[i]);
|
printf("%c", data[i]);
|
||||||
}
|
}
|
||||||
} while(readed_size > 0);
|
} while(read_size > 0);
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
|
|
||||||
free(data);
|
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)) {
|
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");
|
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) {
|
while(true) {
|
||||||
uint8_t symbol = cli_getc(cli);
|
uint8_t symbol = cli_getc(cli);
|
||||||
|
|
||||||
if(symbol == CliSymbolAsciiETX) {
|
if(symbol == CliSymbolAsciiETX) {
|
||||||
uint16_t write_size = readed_index % buffer_size;
|
uint16_t write_size = read_index % buffer_size;
|
||||||
|
|
||||||
if(write_size > 0) {
|
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));
|
storage_cli_print_error(storage_file_get_error(file));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[readed_index % buffer_size] = symbol;
|
buffer[read_index % buffer_size] = symbol;
|
||||||
printf("%c", buffer[readed_index % buffer_size]);
|
printf("%c", buffer[read_index % buffer_size]);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
readed_index++;
|
read_index++;
|
||||||
|
|
||||||
if(((readed_index % buffer_size) == 0)) {
|
if(((read_index % buffer_size) == 0)) {
|
||||||
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));
|
storage_cli_print_error(storage_file_get_error(file));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -239,11 +239,11 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) {
|
|||||||
printf("\r\nReady?\r\n");
|
printf("\r\nReady?\r\n");
|
||||||
cli_getc(cli);
|
cli_getc(cli);
|
||||||
|
|
||||||
uint16_t readed_size = storage_file_read(file, data, buffer_size);
|
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
||||||
for(uint16_t i = 0; i < readed_size; i++) {
|
for(uint16_t i = 0; i < read_size; i++) {
|
||||||
putchar(data[i]);
|
putchar(data[i]);
|
||||||
}
|
}
|
||||||
file_size -= readed_size;
|
file_size -= read_size;
|
||||||
}
|
}
|
||||||
printf("\r\n");
|
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);
|
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));
|
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);
|
File* file = storage_file_alloc(api);
|
||||||
|
|
||||||
if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
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;
|
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);
|
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||||
|
|
||||||
md5_starts(md5_ctx);
|
md5_starts(md5_ctx);
|
||||||
while(true) {
|
while(true) {
|
||||||
uint16_t readed_size = storage_file_read(file, data, read_size);
|
uint16_t read_size = storage_file_read(file, data, size_to_read);
|
||||||
if(readed_size == 0) break;
|
if(read_size == 0) break;
|
||||||
md5_update(md5_ctx, data, readed_size);
|
md5_update(md5_ctx, data, read_size);
|
||||||
}
|
}
|
||||||
md5_finish(md5_ctx, hash);
|
md5_finish(md5_ctx, hash);
|
||||||
free(md5_ctx);
|
free(md5_ctx);
|
||||||
|
|||||||
@@ -340,10 +340,10 @@ static uint16_t
|
|||||||
storage_ext_file_read(void* ctx, File* file, void* buff, uint16_t const bytes_to_read) {
|
storage_ext_file_read(void* ctx, File* file, void* buff, uint16_t const bytes_to_read) {
|
||||||
StorageData* storage = ctx;
|
StorageData* storage = ctx;
|
||||||
SDFile* file_data = storage_get_storage_file_data(file, storage);
|
SDFile* file_data = storage_get_storage_file_data(file, storage);
|
||||||
uint16_t bytes_readed = 0;
|
uint16_t bytes_read = 0;
|
||||||
file->internal_error_id = f_read(file_data, buff, bytes_to_read, &bytes_readed);
|
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);
|
file->error_id = storage_ext_parse_error(file->internal_error_id);
|
||||||
return bytes_readed;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ static uint16_t
|
|||||||
lfs_t* lfs = lfs_get_from_storage(storage);
|
lfs_t* lfs = lfs_get_from_storage(storage);
|
||||||
LFSHandle* handle = storage_get_storage_file_data(file, 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)) {
|
if(lfs_handle_is_open(handle)) {
|
||||||
file->internal_error_id =
|
file->internal_error_id =
|
||||||
@@ -361,10 +361,10 @@ static uint16_t
|
|||||||
file->error_id = storage_int_parse_error(file->internal_error_id);
|
file->error_id = storage_int_parse_error(file->internal_error_id);
|
||||||
|
|
||||||
if(file->error_id == FSE_OK) {
|
if(file->error_id == FSE_OK) {
|
||||||
bytes_readed = file->internal_error_id;
|
bytes_read = file->internal_error_id;
|
||||||
file->internal_error_id = 0;
|
file->internal_error_id = 0;
|
||||||
}
|
}
|
||||||
return bytes_readed;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct SubGhzFrequencyAnalyzerWorker {
|
|||||||
volatile bool worker_running;
|
volatile bool worker_running;
|
||||||
uint8_t count_repet;
|
uint8_t count_repet;
|
||||||
FrequencyRSSI frequency_rssi_buf;
|
FrequencyRSSI frequency_rssi_buf;
|
||||||
|
SubGhzSetting* setting;
|
||||||
|
|
||||||
float filVal;
|
float filVal;
|
||||||
|
|
||||||
@@ -77,10 +78,12 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
|||||||
frequency_rssi.rssi = -127.0f;
|
frequency_rssi.rssi = -127.0f;
|
||||||
furi_hal_subghz_idle();
|
furi_hal_subghz_idle();
|
||||||
furi_hal_subghz_load_registers(subghz_preset_ook_650khz);
|
furi_hal_subghz_load_registers(subghz_preset_ook_650khz);
|
||||||
for(size_t i = 0; i < subghz_frequencies_count; i++) {
|
for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
|
||||||
if(furi_hal_subghz_is_frequency_valid(subghz_frequencies[i])) {
|
if(furi_hal_subghz_is_frequency_valid(
|
||||||
|
subghz_setting_get_frequency(instance->setting, i))) {
|
||||||
furi_hal_subghz_idle();
|
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();
|
furi_hal_subghz_rx();
|
||||||
osDelay(3);
|
osDelay(3);
|
||||||
rssi = furi_hal_subghz_get_rssi();
|
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_context(instance->thread, instance);
|
||||||
furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread);
|
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;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +162,7 @@ void subghz_frequency_analyzer_worker_free(SubGhzFrequencyAnalyzerWorker* instan
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
|
subghz_setting_free(instance->setting);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
|||||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
||||||
} else {
|
} else {
|
||||||
//Restore default setting
|
//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;
|
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||||
subghz->scene_manager, SubGhzSceneSaved)) {
|
subghz->scene_manager, SubGhzSceneSaved)) {
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
|||||||
subghz_sleep(subghz);
|
subghz_sleep(subghz);
|
||||||
};
|
};
|
||||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
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->preset = FuriHalSubGhzPresetOok650Async;
|
||||||
subghz->txrx->idx_menu_chosen = 0;
|
subghz->txrx->idx_menu_chosen = 0;
|
||||||
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);
|
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);
|
||||||
|
|||||||
@@ -40,6 +40,21 @@ uint8_t subghz_scene_receiver_config_uint32_value_index(
|
|||||||
return 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(
|
uint8_t subghz_scene_receiver_config_hopper_value_index(
|
||||||
const uint32_t value,
|
const uint32_t value,
|
||||||
const uint32_t values[],
|
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);
|
uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
|
||||||
if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) {
|
if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) {
|
||||||
variable_item_set_current_value_text(item, subghz_frequencies_text[index]);
|
char text_buf[10] = {0};
|
||||||
subghz->txrx->frequency = subghz_frequencies[index];
|
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 {
|
} 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]);
|
variable_item_set_current_value_text(item, hopping_text[index]);
|
||||||
if(hopping_value[index] == SubGhzHopperStateOFF) {
|
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(
|
variable_item_set_current_value_text(
|
||||||
(VariableItem*)scene_manager_get_scene_state(
|
(VariableItem*)scene_manager_get_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
||||||
subghz_frequencies_text[subghz_frequencies_433_92]);
|
text_buf);
|
||||||
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));
|
||||||
variable_item_set_current_value_index(
|
variable_item_set_current_value_index(
|
||||||
(VariableItem*)scene_manager_get_scene_state(
|
(VariableItem*)scene_manager_get_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
||||||
subghz_frequencies_433_92);
|
subghz_setting_get_frequency_default_index(subghz->setting));
|
||||||
} else {
|
} else {
|
||||||
variable_item_set_current_value_text(
|
variable_item_set_current_value_text(
|
||||||
(VariableItem*)scene_manager_get_scene_state(
|
(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(
|
variable_item_set_current_value_index(
|
||||||
(VariableItem*)scene_manager_get_scene_state(
|
(VariableItem*)scene_manager_get_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
subghz->scene_manager, SubGhzSceneReceiverConfig),
|
||||||
subghz_frequencies_433_92);
|
subghz_setting_get_frequency_default_index(subghz->setting));
|
||||||
}
|
}
|
||||||
|
|
||||||
subghz->txrx->hopper_state = hopping_value[index];
|
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(
|
item = variable_item_list_add(
|
||||||
subghz->variable_item_list,
|
subghz->variable_item_list,
|
||||||
"Frequency:",
|
"Frequency:",
|
||||||
subghz_frequencies_count,
|
subghz_setting_get_frequency_count(subghz->setting),
|
||||||
subghz_scene_receiver_config_set_frequency,
|
subghz_scene_receiver_config_set_frequency,
|
||||||
subghz);
|
subghz);
|
||||||
value_index = subghz_scene_receiver_config_uint32_value_index(
|
value_index = subghz_scene_receiver_config_next_frequency(subghz->txrx->frequency, subghz);
|
||||||
subghz->txrx->frequency, subghz_frequencies, subghz_frequencies_count);
|
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item);
|
subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item);
|
||||||
variable_item_set_current_value_index(item, value_index);
|
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) !=
|
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||||
SubGhzCustomEventManagerSet) {
|
SubGhzCustomEventManagerSet) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
|
|||||||
if(!subghz_protocol_decoder_base_serialize(
|
if(!subghz_protocol_decoder_base_serialize(
|
||||||
subghz->txrx->decoder_result,
|
subghz->txrx->decoder_result,
|
||||||
subghz->txrx->fff_data,
|
subghz->txrx->fff_data,
|
||||||
subghz_frequencies[subghz_frequencies_433_92],
|
subghz_setting_get_frequency_default_index(subghz->setting),
|
||||||
FuriHalSubGhzPresetOok650Async)) {
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
FURI_LOG_E(TAG, "Unable to serialize");
|
FURI_LOG_E(TAG, "Unable to serialize");
|
||||||
break;
|
break;
|
||||||
@@ -213,7 +213,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
0x2,
|
0x2,
|
||||||
0x0003,
|
0x0003,
|
||||||
"DoorHan",
|
"DoorHan",
|
||||||
subghz_frequencies[subghz_frequencies_433_92],
|
subghz_setting_get_frequency_default_index(subghz->setting),
|
||||||
FuriHalSubGhzPresetOok650Async);
|
FuriHalSubGhzPresetOok650Async);
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -237,7 +237,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
0x2,
|
0x2,
|
||||||
0x0003,
|
0x0003,
|
||||||
"DoorHan",
|
"DoorHan",
|
||||||
subghz_frequencies[subghz_frequencies_315_00],
|
315000000,
|
||||||
FuriHalSubGhzPresetOok650Async);
|
FuriHalSubGhzPresetOok650Async);
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,68 +3,6 @@
|
|||||||
#include "subghz_i.h"
|
#include "subghz_i.h"
|
||||||
#include <lib/toolbox/path.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) {
|
bool subghz_custom_event_callback(void* context, uint32_t event) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
@@ -186,9 +124,14 @@ SubGhz* subghz_alloc() {
|
|||||||
SubGhzViewIdStatic,
|
SubGhzViewIdStatic,
|
||||||
subghz_test_static_get_view(subghz->subghz_test_static));
|
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
|
//init Worker & Protocol & History
|
||||||
subghz->txrx = malloc(sizeof(SubGhzTxRx));
|
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->preset = FuriHalSubGhzPresetOok650Async;
|
||||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||||
@@ -281,6 +224,9 @@ void subghz_free(SubGhz* subghz) {
|
|||||||
furi_record_close("gui");
|
furi_record_close("gui");
|
||||||
subghz->gui = NULL;
|
subghz->gui = NULL;
|
||||||
|
|
||||||
|
//setting
|
||||||
|
subghz_setting_free(subghz->setting);
|
||||||
|
|
||||||
//Worker & Protocol & History
|
//Worker & Protocol & History
|
||||||
subghz_receiver_free(subghz->txrx->receiver);
|
subghz_receiver_free(subghz->txrx->receiver);
|
||||||
subghz_environment_free(subghz->txrx->environment);
|
subghz_environment_free(subghz->txrx->environment);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <lib/subghz/receiver.h>
|
#include <lib/subghz/receiver.h>
|
||||||
#include <lib/subghz/transmitter.h>
|
#include <lib/subghz/transmitter.h>
|
||||||
|
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||||
|
|
||||||
#include "helpers/subghz_chat.h"
|
#include "helpers/subghz_chat.h"
|
||||||
|
|
||||||
@@ -294,6 +295,110 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
|||||||
free(instance);
|
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() {
|
static void subghz_cli_command_print_usage() {
|
||||||
printf("Usage:\r\n");
|
printf("Usage:\r\n");
|
||||||
printf("subghz <cmd> <args>\r\n");
|
printf("subghz <cmd> <args>\r\n");
|
||||||
@@ -303,6 +408,7 @@ static void subghz_cli_command_print_usage() {
|
|||||||
printf(
|
printf(
|
||||||
"\ttx <3 byte Key: in hex> <frequency: in Hz> <repeat: count>\t - Transmitting key\r\n");
|
"\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("\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)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
printf("\r\n");
|
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);
|
subghz_cli_command_rx(cli, args, context);
|
||||||
break;
|
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(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
if(string_cmp_str(cmd, "encrypt_keeloq") == 0) {
|
if(string_cmp_str(cmd, "encrypt_keeloq") == 0) {
|
||||||
subghz_cli_command_encrypt_keeloq(cli, args);
|
subghz_cli_command_encrypt_keeloq(cli, args);
|
||||||
|
|||||||
@@ -514,9 +514,9 @@ void subghz_hopper_update(SubGhz* subghz) {
|
|||||||
} else {
|
} else {
|
||||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select next frequency
|
// 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++;
|
subghz->txrx->hopper_idx_frequency++;
|
||||||
} else {
|
} else {
|
||||||
subghz->txrx->hopper_idx_frequency = 0;
|
subghz->txrx->hopper_idx_frequency = 0;
|
||||||
@@ -527,7 +527,8 @@ void subghz_hopper_update(SubGhz* subghz) {
|
|||||||
};
|
};
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
|
||||||
subghz_receiver_reset(subghz->txrx->receiver);
|
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);
|
subghz_rx(subghz, subghz->txrx->frequency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,18 +31,11 @@
|
|||||||
#include <lib/subghz/transmitter.h>
|
#include <lib/subghz/transmitter.h>
|
||||||
|
|
||||||
#include "subghz_history.h"
|
#include "subghz_history.h"
|
||||||
|
#include "subghz_setting.h"
|
||||||
|
|
||||||
#include <gui/modules/variable_item_list.h>
|
#include <gui/modules/variable_item_list.h>
|
||||||
|
|
||||||
#define SUBGHZ_MAX_LEN_NAME 21
|
#define SUBGHZ_MAX_LEN_NAME 40
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/** SubGhzNotification state */
|
/** SubGhzNotification state */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -145,6 +138,7 @@ struct SubGhz {
|
|||||||
SubGhzTestCarrier* subghz_test_carrier;
|
SubGhzTestCarrier* subghz_test_carrier;
|
||||||
SubGhzTestPacket* subghz_test_packet;
|
SubGhzTestPacket* subghz_test_packet;
|
||||||
string_t error_str;
|
string_t error_str;
|
||||||
|
SubGhzSetting* setting;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
361
applications/subghz/subghz_setting.c
Normal file
361
applications/subghz/subghz_setting.c
Normal 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;
|
||||||
|
}
|
||||||
17
applications/subghz/subghz_setting.h
Normal file
17
applications/subghz/subghz_setting.h
Normal 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);
|
||||||
@@ -1,19 +1,6 @@
|
|||||||
#include "system_settings.h"
|
#include "system_settings.h"
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
|
#include <lib/toolbox/value_index.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* const log_level_text[] = {
|
const char* const log_level_text[] = {
|
||||||
"Default",
|
"Default",
|
||||||
@@ -80,7 +67,7 @@ SystemSettings* system_settings_alloc() {
|
|||||||
|
|
||||||
item = variable_item_list_add(
|
item = variable_item_list_add(
|
||||||
app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app);
|
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));
|
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_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, log_level_text[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
Reference in New Issue
Block a user