diff --git a/.clang-format b/.clang-format index ad9757ab..3337a740 100644 --- a/.clang-format +++ b/.clang-format @@ -83,4 +83,4 @@ SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp03 TabWidth: 4 -UseTab: Never \ No newline at end of file +UseTab: Never diff --git a/.github/workflows/build_toolchain.yml b/.github/workflows/build_toolchain.yml index 2068730c..452dfbee 100644 --- a/.github/workflows/build_toolchain.yml +++ b/.github/workflows/build_toolchain.yml @@ -43,4 +43,4 @@ jobs: labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 cache-from: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache - cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max \ No newline at end of file + cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml index db3a3afb..b02f9a8d 100644 --- a/.github/workflows/check_submodules.yml +++ b/.github/workflows/check_submodules.yml @@ -14,4 +14,4 @@ jobs: with: path: assets/protobuf branch: dev - fetch_depth: 50 \ No newline at end of file + fetch_depth: 50 diff --git a/applications/about/about.c b/applications/about/about.c index 9e3fd34e..7c8a4c69 100644 --- a/applications/about/about.c +++ b/applications/about/about.c @@ -149,6 +149,7 @@ const AboutDialogScreen about_screens[] = { const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); int32_t about_settings_app(void* p) { + UNUSED(p); DialogsApp* dialogs = furi_record_open("dialogs"); DialogMessage* message = dialog_message_alloc(); diff --git a/applications/accessor/accessor.cpp b/applications/accessor/accessor.cpp index 000c214b..d7b687ed 100644 --- a/applications/accessor/accessor.cpp +++ b/applications/accessor/accessor.cpp @@ -2,9 +2,10 @@ // app enter function extern "C" int32_t accessor_app(void* p) { + UNUSED(p); AccessorApp* app = new AccessorApp(); app->run(); delete app; return 255; -} \ No newline at end of file +} diff --git a/applications/accessor/accessor_app.h b/applications/accessor/accessor_app.h index ce18c177..2afd796d 100644 --- a/applications/accessor/accessor_app.h +++ b/applications/accessor/accessor_app.h @@ -51,4 +51,4 @@ private: OneWireHost* onewire_host; NotificationApp* notification; -}; \ No newline at end of file +}; diff --git a/applications/accessor/accessor_view_manager.cpp b/applications/accessor/accessor_view_manager.cpp index 604e4304..f54ad62f 100644 --- a/applications/accessor/accessor_view_manager.cpp +++ b/applications/accessor/accessor_view_manager.cpp @@ -64,7 +64,7 @@ void AccessorAppViewManager::send_event(AccessorEvent* event) { furi_check(result == osOK); } -uint32_t AccessorAppViewManager::previous_view_callback(void* context) { +uint32_t AccessorAppViewManager::previous_view_callback(void*) { if(event_queue != NULL) { AccessorEvent event; event.type = AccessorEvent::Type::Back; @@ -76,4 +76,4 @@ uint32_t AccessorAppViewManager::previous_view_callback(void* context) { void AccessorAppViewManager::add_view(ViewType view_type, View* view) { view_dispatcher_add_view(view_dispatcher, static_cast(view_type), view); -} \ No newline at end of file +} diff --git a/applications/accessor/accessor_view_manager.h b/applications/accessor/accessor_view_manager.h index 1e9d8e04..f2c6f2bb 100644 --- a/applications/accessor/accessor_view_manager.h +++ b/applications/accessor/accessor_view_manager.h @@ -36,4 +36,4 @@ private: // view elements Submenu* submenu; Popup* popup; -}; \ No newline at end of file +}; diff --git a/applications/accessor/helpers/wiegand.h b/applications/accessor/helpers/wiegand.h index 2822d95a..8127f428 100644 --- a/applications/accessor/helpers/wiegand.h +++ b/applications/accessor/helpers/wiegand.h @@ -27,4 +27,4 @@ private: static int _wiegandType; static unsigned long _code; static unsigned long _codeHigh; -}; \ No newline at end of file +}; diff --git a/applications/accessor/scene/accessor_scene_generic.h b/applications/accessor/scene/accessor_scene_generic.h index b403f152..62a4eafe 100644 --- a/applications/accessor/scene/accessor_scene_generic.h +++ b/applications/accessor/scene/accessor_scene_generic.h @@ -10,4 +10,4 @@ public: virtual void on_exit(AccessorApp* app) = 0; private: -}; \ No newline at end of file +}; diff --git a/applications/accessor/scene/accessor_scene_start.h b/applications/accessor/scene/accessor_scene_start.h index 3be88bb3..1717d1e7 100644 --- a/applications/accessor/scene/accessor_scene_start.h +++ b/applications/accessor/scene/accessor_scene_start.h @@ -6,4 +6,4 @@ public: void on_enter(AccessorApp* app) final; bool on_event(AccessorApp* app, AccessorEvent* event) final; void on_exit(AccessorApp* app) final; -}; \ No newline at end of file +}; diff --git a/applications/applications.c b/applications/applications.c index b9e8bbd4..4deae885 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -55,6 +55,7 @@ extern void crypto_on_system_start(); extern void ibutton_on_system_start(); extern void infrared_on_system_start(); extern void lfrfid_on_system_start(); +extern void music_player_on_system_start(); extern void nfc_on_system_start(); extern void storage_on_system_start(); extern void subghz_on_system_start(); @@ -280,6 +281,10 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { infrared_on_system_start, #endif +#ifdef APP_MUSIC_PLAYER + music_player_on_system_start, +#endif + #ifdef APP_NFC nfc_on_system_start, #endif @@ -332,7 +337,7 @@ const FlipperApplication FLIPPER_PLUGINS[] = { #ifdef APP_MUSIC_PLAYER {.app = music_player_app, .name = "Music Player", - .stack_size = 1024, + .stack_size = 2048, .icon = &A_Plugins_14, .flags = FlipperApplicationFlagDefault}, #endif diff --git a/applications/archive/archive.c b/applications/archive/archive.c index 79f26f0e..5a38700b 100644 --- a/applications/archive/archive.c +++ b/applications/archive/archive.c @@ -66,6 +66,7 @@ void archive_free(ArchiveApp* archive) { } int32_t archive_app(void* p) { + UNUSED(p); ArchiveApp* archive = archive_alloc(); scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); view_dispatcher_run(archive->view_dispatcher); diff --git a/applications/archive/helpers/archive_apps.c b/applications/archive/helpers/archive_apps.c index e1c429a7..f5edbbb3 100644 --- a/applications/archive/helpers/archive_apps.c +++ b/applications/archive/helpers/archive_apps.c @@ -7,8 +7,8 @@ static const char* known_apps[] = { }; ArchiveAppTypeEnum archive_get_app_type(const char* path) { - for(size_t i = 0; i < SIZEOF_ARRAY(known_apps); i++) { - if(strncmp(path, known_apps[i], strlen(known_apps[i])) != STRING_FAILURE) { + for(size_t i = 0; i < COUNT_OF(known_apps); i++) { + if(strncmp(path, known_apps[i], strlen(known_apps[i])) == 0) { return i; } } @@ -16,6 +16,7 @@ ArchiveAppTypeEnum archive_get_app_type(const char* path) { } bool archive_app_is_available(void* context, const char* path) { + UNUSED(context); furi_assert(path); ArchiveAppTypeEnum app = archive_get_app_type(path); diff --git a/applications/archive/helpers/archive_apps.h b/applications/archive/helpers/archive_apps.h index 5abc27a5..8bc90458 100644 --- a/applications/archive/helpers/archive_apps.h +++ b/applications/archive/helpers/archive_apps.h @@ -11,7 +11,7 @@ static const ArchiveFileTypeEnum app_file_types[] = { [ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown, }; -static inline const ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { +static inline ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { return app_file_types[app]; } diff --git a/applications/archive/helpers/archive_browser.c b/applications/archive/helpers/archive_browser.c index b1e1e3ef..cb3d3ca8 100644 --- a/applications/archive/helpers/archive_browser.c +++ b/applications/archive/helpers/archive_browser.c @@ -6,7 +6,8 @@ bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { size_t array_size = files_array_size(model->files); - if((idx >= model->array_offset + array_size) || (idx < model->array_offset)) { + if((idx >= (uint32_t)model->array_offset + array_size) || + (idx < (uint32_t)model->array_offset)) { return false; } @@ -20,12 +21,14 @@ void archive_update_offset(ArchiveBrowserView* browser) { browser->view, (ArchiveBrowserViewModel * model) { uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt; - if(model->item_cnt > 3 && model->item_idx >= model->item_cnt - 1) { + if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) { model->list_offset = model->item_idx - 3; } else if(model->list_offset < model->item_idx - bounds) { - model->list_offset = CLAMP(model->item_idx - 2, model->item_cnt - bounds, 0); + model->list_offset = + CLAMP(model->item_idx - 2, (int32_t)model->item_cnt - bounds, 0); } else if(model->list_offset > model->item_idx - bounds) { - model->list_offset = CLAMP(model->item_idx - 1, model->item_cnt - bounds, 0); + model->list_offset = + CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); } return true; @@ -77,9 +80,10 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) { with_view_model( browser->view, (ArchiveBrowserViewModel * model) { model->item_cnt = count; - model->item_idx = CLAMP(model->item_idx, model->item_cnt - 1, 0); + model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); return false; }); + archive_update_offset(browser); } void archive_file_array_rm_selected(ArchiveBrowserView* browser) { @@ -93,7 +97,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { model->item_idx - model->array_offset, model->item_idx - model->array_offset + 1); model->item_cnt--; - model->item_idx = CLAMP(model->item_idx, model->item_cnt - 1, 0); + model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); items_cnt = model->item_cnt; return false; }); @@ -112,14 +116,14 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) { browser->view, (ArchiveBrowserViewModel * model) { ArchiveFile_t temp; size_t array_size = files_array_size(model->files) - 1; - uint8_t swap_idx = CLAMP(model->item_idx + dir, array_size, 0); + uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u); if(model->item_idx == 0 && dir < 0) { ArchiveFile_t_init(&temp); files_array_pop_at(&temp, model->files, array_size); files_array_push_at(model->files, model->item_idx, temp); ArchiveFile_t_clear(&temp); - } else if(model->item_idx == array_size && dir > 0) { + } else if(((uint32_t)model->item_idx == array_size) && (dir > 0)) { ArchiveFile_t_init(&temp); files_array_pop_at(&temp, model->files, 0); files_array_push_at(model->files, array_size, temp); @@ -156,7 +160,7 @@ bool archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { } else { offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 1; } - offset_new = CLAMP(offset_new, model->item_cnt - FILE_LIST_BUF_LEN, 0); + offset_new = CLAMP(offset_new, (int32_t)model->item_cnt - FILE_LIST_BUF_LEN, 0); } return false; }); @@ -195,7 +199,7 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { with_view_model( browser->view, (ArchiveBrowserViewModel * model) { - idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0); + idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u); selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL; return false; }); @@ -246,6 +250,7 @@ void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { }); } void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { + UNUSED(tab); // FIXME? furi_assert(browser); with_view_model( @@ -396,8 +401,6 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { return; } - archive_dir_count_items(browser, string_get_cstr(name)); - if(string_cmp(browser->path, name) != 0) { with_view_model( browser->view, (ArchiveBrowserViewModel * model) { @@ -410,6 +413,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { string_set(browser->path, name); } + archive_dir_count_items(browser, string_get_cstr(name)); archive_switch_dir(browser, string_get_cstr(browser->path)); } diff --git a/applications/archive/helpers/archive_browser.h b/applications/archive/helpers/archive_browser.h index 593a9be0..3395541e 100644 --- a/applications/archive/helpers/archive_browser.h +++ b/applications/archive/helpers/archive_browser.h @@ -42,7 +42,7 @@ static const ArchiveFileTypeEnum known_type[] = { [ArchiveTabBrowser] = ArchiveFileTypeUnknown, }; -static inline const ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { +static inline ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { return known_type[tab]; } diff --git a/applications/archive/helpers/archive_files.c b/applications/archive/helpers/archive_files.c index 156e66f5..3b1e8944 100644 --- a/applications/archive/helpers/archive_files.c +++ b/applications/archive/helpers/archive_files.c @@ -54,7 +54,7 @@ void archive_set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* } else { furi_assert(file_info); - for(size_t i = 0; i < SIZEOF_ARRAY(known_ext); i++) { + for(size_t i = 0; i < COUNT_OF(known_ext); i++) { if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { if(i == ArchiveFileTypeBadUsb) { diff --git a/applications/archive/scenes/archive_scene_browser.c b/applications/archive/scenes/archive_scene_browser.c index bcfd63ba..9df3463b 100644 --- a/applications/archive/scenes/archive_scene_browser.c +++ b/applications/archive/scenes/archive_scene_browser.c @@ -31,6 +31,7 @@ static void archive_loader_callback(const void* message, void* context) { } static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { + UNUSED(browser); Loader* loader = furi_record_open("loader"); LoaderStatus status; @@ -95,6 +96,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { if(known_app) { archive_run_in_app(browser, selected); } + archive_show_file_menu(browser, false); consumed = true; break; case ArchiveBrowserEventFileMenuPin: diff --git a/applications/archive/views/archive_browser_view.c b/applications/archive/views/archive_browser_view.c index ed75621d..fc578b36 100644 --- a/applications/archive/views/archive_browser_view.c +++ b/applications/archive/views/archive_browser_view.c @@ -106,17 +106,17 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { size_t array_size = files_array_size(model->files); bool scrollbar = model->item_cnt > 4; - for(size_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { + for(uint32_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { string_t str_buff; char cstr_buff[MAX_NAME_LEN]; - size_t idx = CLAMP(i + model->list_offset, model->item_cnt, 0); + int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0; ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; if(archive_is_item_in_array(model, idx)) { - ArchiveFile_t* file = - files_array_get(model->files, CLAMP(idx - model->array_offset, array_size - 1, 0)); + ArchiveFile_t* file = files_array_get( + model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); string_init_set_str(str_buff, cstr_buff); @@ -161,21 +161,21 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m canvas_draw_box(canvas, 107, 0, 20, 13); canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 1, 0, 50, 12); - canvas_draw_line(canvas, 0, 1, 0, 11); - canvas_draw_line(canvas, 1, 12, 49, 12); - canvas_draw_str_aligned(canvas, 26, 9, AlignCenter, AlignBottom, tab_name); + canvas_draw_rframe(canvas, 0, 0, 51, 13, 1); // frame + canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right + canvas_draw_line(canvas, 1, 11, 49, 11); // shadow bottom + canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); - canvas_draw_frame(canvas, 108, 0, 20, 12); - canvas_draw_line(canvas, 107, 1, 107, 11); - canvas_draw_line(canvas, 108, 12, 126, 12); + canvas_draw_rframe(canvas, 107, 0, 21, 13, 1); + canvas_draw_line(canvas, 126, 1, 126, 11); + canvas_draw_line(canvas, 108, 11, 126, 11); if(model->move_fav) { - canvas_draw_icon(canvas, 111, 4, &I_ButtonUp_7x4); - canvas_draw_icon(canvas, 118, 4, &I_ButtonDown_7x4); + canvas_draw_icon(canvas, 110, 4, &I_ButtonUp_7x4); + canvas_draw_icon(canvas, 117, 4, &I_ButtonDown_7x4); } else { - canvas_draw_icon(canvas, 112, 2, &I_ButtonLeft_4x7); - canvas_draw_icon(canvas, 120, 2, &I_ButtonRight_4x7); + canvas_draw_icon(canvas, 111, 2, &I_ButtonLeft_4x7); + canvas_draw_icon(canvas, 119, 2, &I_ButtonRight_4x7); } canvas_set_color(canvas, ColorWhite); @@ -216,7 +216,7 @@ static bool is_file_list_load_required(ArchiveBrowserViewModel* model) { } if(((model->array_offset + array_size) < model->item_cnt) && - (model->item_idx > (model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { + (model->item_idx > (int32_t)(model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { return true; } @@ -347,7 +347,7 @@ ArchiveBrowserView* browser_alloc() { browser->view = view_alloc(); view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel)); view_set_context(browser->view, browser); - view_set_draw_callback(browser->view, (ViewDrawCallback)archive_view_render); + view_set_draw_callback(browser->view, archive_view_render); view_set_input_callback(browser->view, archive_view_input); string_init(browser->path); @@ -376,4 +376,4 @@ void browser_free(ArchiveBrowserView* browser) { view_free(browser->view); free(browser); -} \ No newline at end of file +} diff --git a/applications/archive/views/archive_browser_view.h b/applications/archive/views/archive_browser_view.h index 3aabe962..db079d6b 100644 --- a/applications/archive/views/archive_browser_view.h +++ b/applications/archive/views/archive_browser_view.h @@ -13,8 +13,8 @@ #define MAX_NAME_LEN 255 #define MAX_EXT_LEN 6 #define FRAME_HEIGHT 12 -#define MENU_ITEMS 4 -#define MOVE_OFFSET 5 +#define MENU_ITEMS 4u +#define MOVE_OFFSET 5u typedef enum { ArchiveTabFavorites, diff --git a/applications/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/bad_usb/scenes/bad_usb_scene_file_select.c index b1ab3194..82f03bab 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/bad_usb/scenes/bad_usb_scene_file_select.c @@ -31,10 +31,13 @@ void bad_usb_scene_file_select_on_enter(void* context) { } bool bad_usb_scene_file_select_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); // BadUsbApp* bad_usb = context; return false; } void bad_usb_scene_file_select_on_exit(void* context) { + UNUSED(context); // BadUsbApp* bad_usb = context; } diff --git a/applications/bad_usb/views/bad_usb_view.c b/applications/bad_usb/views/bad_usb_view.c index 22e5143d..5b6fe6e8 100644 --- a/applications/bad_usb/views/bad_usb_view.c +++ b/applications/bad_usb/views/bad_usb_view.c @@ -142,6 +142,7 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c furi_assert(callback); with_view_model( bad_usb->view, (BadUsbModel * model) { + UNUSED(model); bad_usb->callback = callback; bad_usb->context = context; return true; diff --git a/applications/bt/bt_cli.c b/applications/bt/bt_cli.c index 64d69a12..1c9b198b 100644 --- a/applications/bt/bt_cli.c +++ b/applications/bt/bt_cli.c @@ -13,6 +13,9 @@ static const char* bt_cli_address_types[] = { }; static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); string_t buffer; string_init(buffer); furi_hal_bt_dump_state(buffer); @@ -21,6 +24,7 @@ static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { } static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { + UNUSED(context); int channel = 0; int power = 0; @@ -47,6 +51,7 @@ static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { } static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { + UNUSED(context); int channel = 0; do { @@ -63,7 +68,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - printf("RSSI: %6.1f dB\r", furi_hal_bt_get_rssi()); + printf("RSSI: %6.1f dB\r", (double)furi_hal_bt_get_rssi()); fflush(stdout); } @@ -72,6 +77,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { } static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { + UNUSED(context); int channel = 0; int pattern = 0; int datarate = 1; @@ -115,6 +121,7 @@ static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { } static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { + UNUSED(context); int channel = 0; int datarate = 1; @@ -133,11 +140,9 @@ static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { printf("Press CTRL+C to stop\r\n"); furi_hal_bt_start_packet_rx(channel, datarate); - float rssi_raw = 0; while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - rssi_raw = furi_hal_bt_get_rssi(); - printf("RSSI: %03.1f dB\r", rssi_raw); + printf("RSSI: %03.1f dB\r", (double)furi_hal_bt_get_rssi()); fflush(stdout); } uint16_t packets_received = furi_hal_bt_stop_packet_test(); @@ -152,6 +157,8 @@ static void bt_cli_scan_callback(GapAddress address, void* context) { } static void bt_cli_command_scan(Cli* cli, string_t args, void* context) { + UNUSED(context); + UNUSED(args); osMessageQueueId_t queue = osMessageQueueNew(20, sizeof(GapAddress), NULL); furi_hal_bt_start_scan(bt_cli_scan_callback, queue); @@ -189,6 +196,7 @@ static void bt_cli_print_usage() { } static void bt_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); furi_record_open("bt"); string_t cmd; diff --git a/applications/bt/bt_debug_app/bt_debug_app.c b/applications/bt/bt_debug_app/bt_debug_app.c index a4363b91..58119f5d 100644 --- a/applications/bt/bt_debug_app/bt_debug_app.c +++ b/applications/bt/bt_debug_app/bt_debug_app.c @@ -19,10 +19,12 @@ void bt_debug_submenu_callback(void* context, uint32_t index) { } uint32_t bt_debug_exit(void* context) { + UNUSED(context); return VIEW_NONE; } uint32_t bt_debug_start_view(void* context) { + UNUSED(context); return BtDebugAppViewSubmenu; } @@ -94,6 +96,7 @@ void bt_debug_app_free(BtDebugApp* app) { } int32_t bt_debug_app(void* p) { + UNUSED(p); if(furi_hal_bt_get_radio_stack() != FuriHalBtStackHciLayer) { FURI_LOG_E(TAG, "Incorrect radio stack, replace with HciLayer for tests."); DialogsApp* dialogs = furi_record_open("dialogs"); diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.c b/applications/bt/bt_debug_app/views/bt_carrier_test.c index 22b80cd8..0e0b3792 100755 --- a/applications/bt/bt_debug_app/views/bt_carrier_test.c +++ b/applications/bt/bt_debug_app/views/bt_carrier_test.c @@ -141,7 +141,7 @@ BtCarrierTest* bt_carrier_test_alloc() { param = bt_test_param_add( bt_carrier_test->bt_test, "Mode", - SIZEOF_ARRAY(bt_param_mode), + COUNT_OF(bt_param_mode), bt_carrier_test_mode_changed, bt_carrier_test); bt_test_set_current_value_index(param, 0); @@ -151,7 +151,7 @@ BtCarrierTest* bt_carrier_test_alloc() { param = bt_test_param_add( bt_carrier_test->bt_test, "Channel", - SIZEOF_ARRAY(bt_param_channel), + COUNT_OF(bt_param_channel), bt_carrier_test_channel_changed, bt_carrier_test); bt_test_set_current_value_index(param, 0); @@ -162,7 +162,7 @@ BtCarrierTest* bt_carrier_test_alloc() { param = bt_test_param_add( bt_carrier_test->bt_test, "Power", - SIZEOF_ARRAY(bt_param_power), + COUNT_OF(bt_param_power), bt_carrier_test_param_channel, bt_carrier_test); bt_test_set_current_value_index(param, 0); diff --git a/applications/bt/bt_debug_app/views/bt_packet_test.c b/applications/bt/bt_debug_app/views/bt_packet_test.c index e9d3883a..e9b3bd75 100644 --- a/applications/bt/bt_debug_app/views/bt_packet_test.c +++ b/applications/bt/bt_debug_app/views/bt_packet_test.c @@ -109,7 +109,7 @@ BtPacketTest* bt_packet_test_alloc() { param = bt_test_param_add( bt_packet_test->bt_test, "Mode", - SIZEOF_ARRAY(bt_param_mode), + COUNT_OF(bt_param_mode), bt_packet_test_mode_changed, bt_packet_test); bt_test_set_current_value_index(param, 0); @@ -119,7 +119,7 @@ BtPacketTest* bt_packet_test_alloc() { param = bt_test_param_add( bt_packet_test->bt_test, "Channel", - SIZEOF_ARRAY(bt_param_channel), + COUNT_OF(bt_param_channel), bt_packet_test_channel_changed, bt_packet_test); bt_test_set_current_value_index(param, 0); @@ -129,7 +129,7 @@ BtPacketTest* bt_packet_test_alloc() { param = bt_test_param_add( bt_packet_test->bt_test, "Data rate", - SIZEOF_ARRAY(bt_param_data_rate), + COUNT_OF(bt_param_data_rate), bt_packet_test_param_channel, bt_packet_test); bt_test_set_current_value_index(param, 0); diff --git a/applications/bt/bt_debug_app/views/bt_test.c b/applications/bt/bt_debug_app/views/bt_test.c index ac10e0a8..70f57c12 100755 --- a/applications/bt/bt_debug_app/views/bt_test.c +++ b/applications/bt/bt_debug_app/views/bt_test.c @@ -99,7 +99,7 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) { canvas_draw_str(canvas, 6, 60, model->message); if(model->state == BtTestStateStarted) { if(model->rssi != 0.0f) { - snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", model->rssi); + snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi); canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); } } else if(model->state == BtTestStateStopped) { diff --git a/applications/bt/bt_hid_app/bt_hid.c b/applications/bt/bt_hid_app/bt_hid.c index ab13f6f3..4b1037cd 100755 --- a/applications/bt/bt_hid_app/bt_hid.c +++ b/applications/bt/bt_hid_app/bt_hid.c @@ -33,10 +33,12 @@ void bt_hid_dialog_callback(DialogExResult result, void* context) { } uint32_t bt_hid_exit_confirm_view(void* context) { + UNUSED(context); return BtHidViewExitConfirm; } uint32_t bt_hid_exit(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -139,6 +141,7 @@ void bt_hid_app_free(BtHid* app) { } int32_t bt_hid_app(void* p) { + UNUSED(p); // Switch profile to Hid BtHid* app = bt_hid_app_alloc(); bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); diff --git a/applications/bt/bt_settings_app/bt_settings_app.c b/applications/bt/bt_settings_app/bt_settings_app.c index d9dfa74d..cb55e931 100755 --- a/applications/bt/bt_settings_app/bt_settings_app.c +++ b/applications/bt/bt_settings_app/bt_settings_app.c @@ -76,6 +76,7 @@ void bt_settings_app_free(BtSettingsApp* app) { } extern int32_t bt_settings_app(void* p) { + UNUSED(p); BtSettingsApp* app = bt_settings_app_alloc(); view_dispatcher_run(app->view_dispatcher); bt_settings_save(&app->settings); diff --git a/applications/cli/cli.c b/applications/cli/cli.c index 4e200d6b..eefbb305 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -130,10 +130,12 @@ void cli_motd() { } void cli_nl(Cli* cli) { + UNUSED(cli); printf("\r\n"); } void cli_prompt(Cli* cli) { + UNUSED(cli); printf("\r\n>: %s", string_get_cstr(cli->line)); fflush(stdout); } @@ -451,6 +453,7 @@ void cli_session_close(Cli* cli) { } int32_t cli_srv(void* p) { + UNUSED(p); Cli* cli = cli_alloc(); // Init basic cli commands diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index bdec231b..2d059bd3 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -12,6 +12,8 @@ #define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d" void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) { + UNUSED(context); + UNUSED(last); printf("%-24s: %s\r\n", key, value); } @@ -20,11 +22,14 @@ void cli_command_device_info_callback(const char* key, const char* value, bool l * This command is intended to be used by humans */ void cli_command_device_info(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); furi_hal_info_get(cli_command_device_info_callback, context); } void cli_command_help(Cli* cli, string_t args, void* context) { - (void)args; + UNUSED(args); + UNUSED(context); printf("Commands we have:"); // Command count @@ -62,6 +67,9 @@ void cli_command_help(Cli* cli, string_t args, void* context) { } void cli_command_date(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); + FuriHalRtcDateTime datetime = {0}; if(string_size(args) > 0) { @@ -135,6 +143,8 @@ void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* conte } void cli_command_log(Cli* cli, string_t args, void* context) { + UNUSED(args); + UNUSED(context); StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1); uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE]; @@ -152,6 +162,8 @@ void cli_command_log(Cli* cli, string_t args, void* context) { } void cli_command_vibro(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); if(!string_cmp(args, "0")) { NotificationApp* notification = furi_record_open("notification"); notification_message_block(notification, &sequence_reset_vibro); @@ -166,6 +178,8 @@ void cli_command_vibro(Cli* cli, string_t args, void* context) { } void cli_command_debug(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); if(!string_cmp(args, "0")) { furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); loader_update_menu(); @@ -180,6 +194,8 @@ void cli_command_debug(Cli* cli, string_t args, void* context) { } void cli_command_led(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); // Get first word as light name NotificationMessage notification_led_message; string_t light_name; @@ -233,6 +249,7 @@ void cli_command_led(Cli* cli, string_t args, void* context) { } void cli_command_gpio_set(Cli* cli, string_t args, void* context) { + UNUSED(context); char pin_names[][4] = { "PC0", "PC1", @@ -313,6 +330,8 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { return; } } +#else + UNUSED(cli); #endif LL_GPIO_SetPinMode(gpio[num].port, gpio[num].pin, LL_GPIO_MODE_OUTPUT); @@ -325,6 +344,10 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { } void cli_command_ps(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); + const uint8_t threads_num_max = 32; osThreadId_t threads_id[threads_num_max]; uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max); @@ -344,6 +367,10 @@ void cli_command_ps(Cli* cli, string_t args, void* context) { } void cli_command_free(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); + printf("Free heap size: %d\r\n", memmgr_get_free_heap()); printf("Total heap size: %d\r\n", memmgr_get_total_heap()); printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap()); @@ -351,10 +378,18 @@ void cli_command_free(Cli* cli, string_t args, void* context) { } void cli_command_free_blocks(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); + memmgr_heap_printf_free_blocks(); } void cli_command_i2c(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); + furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); printf("Scanning external i2c on PC0(SCL)/PC1(SDA)\r\n" "Clock: 100khz, 7bit address\r\n" @@ -391,4 +426,4 @@ void cli_commands_init(Cli* cli) { cli_add_command(cli, "led", CliCommandFlagDefault, cli_command_led, NULL); cli_add_command(cli, "gpio_set", CliCommandFlagDefault, cli_command_gpio_set, NULL); cli_add_command(cli, "i2c", CliCommandFlagDefault, cli_command_i2c, NULL); -} +} \ No newline at end of file diff --git a/applications/cli/cli_commands.h b/applications/cli/cli_commands.h index b82dae29..184eeb37 100644 --- a/applications/cli/cli_commands.h +++ b/applications/cli/cli_commands.h @@ -2,4 +2,4 @@ #include "cli_i.h" -void cli_commands_init(Cli* cli); \ No newline at end of file +void cli_commands_init(Cli* cli); diff --git a/applications/cli/cli_vcp.c b/applications/cli/cli_vcp.c index f570aee1..84edca18 100644 --- a/applications/cli/cli_vcp.c +++ b/applications/cli/cli_vcp.c @@ -86,6 +86,7 @@ static void cli_vcp_deinit() { } static int32_t vcp_worker(void* context) { + UNUSED(context); bool tx_idle = true; size_t missed_rx = 0; uint8_t last_tx_pkt_len = 0; @@ -148,7 +149,7 @@ static int32_t vcp_worker(void* context) { if(len > 0) { furi_check( xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == - len); + (size_t)len); } } else { #ifdef CLI_VCP_DEBUG @@ -275,16 +276,19 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) { } static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { + UNUSED(_cookie); cli_vcp_tx((const uint8_t*)data, size); } static void vcp_state_callback(void* context, uint8_t state) { + UNUSED(context); if(state == 0) { osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); } } static void vcp_on_cdc_control_line(void* context, uint8_t state) { + UNUSED(context); // bit 0: DTR state, bit 1: RTS state bool dtr = state & (1 << 0); @@ -296,11 +300,13 @@ static void vcp_on_cdc_control_line(void* context, uint8_t state) { } static void vcp_on_cdc_rx(void* context) { + UNUSED(context); uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); furi_check((ret & osFlagsError) == 0); } static void vcp_on_cdc_tx_complete(void* context) { + UNUSED(context); osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); } diff --git a/applications/crypto/crypto_cli.c b/applications/crypto/crypto_cli.c index 7cd9d5cc..a5ea80f8 100644 --- a/applications/crypto/crypto_cli.c +++ b/applications/crypto/crypto_cli.c @@ -164,6 +164,7 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { } void crypto_cli_has_key(Cli* cli, string_t args) { + UNUSED(cli); int key_slot = 0; uint8_t iv[16]; @@ -185,6 +186,7 @@ void crypto_cli_has_key(Cli* cli, string_t args) { } void crypto_cli_store_key(Cli* cli, string_t args) { + UNUSED(cli); int key_slot = 0; int key_size = 0; string_t key_type; @@ -277,6 +279,7 @@ void crypto_cli_store_key(Cli* cli, string_t args) { } static void crypto_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); diff --git a/applications/debug_tools/blink_test.c b/applications/debug_tools/blink_test.c index 35f9f434..2efaa4da 100644 --- a/applications/debug_tools/blink_test.c +++ b/applications/debug_tools/blink_test.c @@ -27,6 +27,7 @@ static void blink_test_update(void* ctx) { } static void blink_test_draw_callback(Canvas* canvas, void* ctx) { + UNUSED(ctx); canvas_clear(canvas); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 2, 10, "Blink application"); @@ -41,6 +42,7 @@ static void blink_test_input_callback(InputEvent* input_event, void* ctx) { } int32_t blink_test_app(void* p) { + UNUSED(p); osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(BlinkEvent), NULL); // Configure view port diff --git a/applications/debug_tools/display_test/display_test.c b/applications/debug_tools/display_test/display_test.c index 1a9a0e43..95aea1de 100644 --- a/applications/debug_tools/display_test/display_test.c +++ b/applications/debug_tools/display_test/display_test.c @@ -70,10 +70,12 @@ static void display_test_submenu_callback(void* context, uint32_t index) { } static uint32_t display_test_previous_callback(void* context) { + UNUSED(context); return DisplayTestViewSubmenu; } static uint32_t display_test_exit_callback(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -210,6 +212,7 @@ void display_test_free(DisplayTest* instance) { } int32_t display_test_run(DisplayTest* instance) { + UNUSED(instance); view_dispatcher_switch_to_view(instance->view_dispatcher, DisplayTestViewSubmenu); view_dispatcher_run(instance->view_dispatcher); @@ -217,6 +220,8 @@ int32_t display_test_run(DisplayTest* instance) { } int32_t display_test_app(void* p) { + UNUSED(p); + DisplayTest* instance = display_test_alloc(); int32_t ret = display_test_run(instance); diff --git a/applications/debug_tools/display_test/view_display_test.c b/applications/debug_tools/display_test/view_display_test.c index cc5f5dcf..133195d0 100644 --- a/applications/debug_tools/display_test/view_display_test.c +++ b/applications/debug_tools/display_test/view_display_test.c @@ -13,6 +13,7 @@ struct ViewDisplayTest { }; static void view_display_test_draw_callback_intro(Canvas* canvas, void* _model) { + UNUSED(_model); canvas_draw_str(canvas, 12, 24, "Use < and > to switch tests"); canvas_draw_str(canvas, 12, 36, "Use ^ and v to switch size"); canvas_draw_str(canvas, 32, 48, "Use (o) to flip"); diff --git a/applications/debug_tools/keypad_test.c b/applications/debug_tools/keypad_test.c index ae980317..705a1542 100644 --- a/applications/debug_tools/keypad_test.c +++ b/applications/debug_tools/keypad_test.c @@ -60,6 +60,7 @@ static void keypad_test_input_callback(InputEvent* input_event, void* ctx) { } int32_t keypad_test_app(void* p) { + UNUSED(p); osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); furi_check(event_queue); diff --git a/applications/debug_tools/text_box_test.c b/applications/debug_tools/text_box_test.c index 1c7ce18b..bc56e88b 100644 --- a/applications/debug_tools/text_box_test.c +++ b/applications/debug_tools/text_box_test.c @@ -70,6 +70,7 @@ static void text_box_test_input_callback(InputEvent* input_event, void* ctx) { } int32_t text_box_test_app(void* p) { + UNUSED(p); osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); furi_check(event_queue); @@ -90,7 +91,7 @@ int32_t text_box_test_app(void* p) { Gui* gui = furi_record_open("gui"); gui_add_view_port(gui, view_port, GuiLayerFullscreen); - uint32_t test_renders_num = SIZEOF_ARRAY(text_box_test_render); + uint32_t test_renders_num = COUNT_OF(text_box_test_render); InputEvent event; while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { TextBoxTestState* state = acquire_mutex_block(&state_mutex); diff --git a/applications/debug_tools/uart_echo.c b/applications/debug_tools/uart_echo.c index 0e4ee1d8..206c6c06 100644 --- a/applications/debug_tools/uart_echo.c +++ b/applications/debug_tools/uart_echo.c @@ -80,11 +80,13 @@ static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { } static bool uart_echo_view_input_callback(InputEvent* event, void* context) { - bool consumed = false; - return consumed; + UNUSED(event); + UNUSED(context); + return false; } static uint32_t uart_echo_exit(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -170,7 +172,10 @@ static int32_t uart_echo_worker(void* context) { notification_message(app->notification, &sequence_notification); with_view_model( - app->view, (UartDumpModel * model) { return true; }); + app->view, (UartDumpModel * model) { + UNUSED(model); + return true; + }); } } @@ -261,6 +266,7 @@ static void uart_echo_app_free(UartEchoApp* app) { } int32_t uart_echo_app(void* p) { + UNUSED(p); UartEchoApp* app = uart_echo_app_alloc(); view_dispatcher_run(app->view_dispatcher); uart_echo_app_free(app); diff --git a/applications/debug_tools/usb_mouse.c b/applications/debug_tools/usb_mouse.c index 6943e189..a136375a 100644 --- a/applications/debug_tools/usb_mouse.c +++ b/applications/debug_tools/usb_mouse.c @@ -18,6 +18,7 @@ typedef struct { } UsbMouseEvent; static void usb_mouse_render_callback(Canvas* canvas, void* ctx) { + UNUSED(ctx); canvas_clear(canvas); canvas_set_font(canvas, FontPrimary); @@ -37,6 +38,7 @@ static void usb_mouse_input_callback(InputEvent* input_event, void* ctx) { } int32_t usb_mouse_app(void* p) { + UNUSED(p); osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(UsbMouseEvent), NULL); furi_check(event_queue); ViewPort* view_port = view_port_alloc(); diff --git a/applications/debug_tools/usb_test.c b/applications/debug_tools/usb_test.c index 0e8f068f..44a17ceb 100644 --- a/applications/debug_tools/usb_test.c +++ b/applications/debug_tools/usb_test.c @@ -51,6 +51,7 @@ void usb_test_submenu_callback(void* context, uint32_t index) { } uint32_t usb_test_exit(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -113,6 +114,7 @@ void usb_test_app_free(UsbTestApp* app) { } int32_t usb_test_app(void* p) { + UNUSED(p); UsbTestApp* app = usb_test_app_alloc(); view_dispatcher_run(app->view_dispatcher); diff --git a/applications/debug_tools/vibro_test.c b/applications/debug_tools/vibro_test.c index 07ce93b7..af6d336d 100644 --- a/applications/debug_tools/vibro_test.c +++ b/applications/debug_tools/vibro_test.c @@ -6,6 +6,7 @@ #include void vibro_test_draw_callback(Canvas* canvas, void* ctx) { + UNUSED(ctx); canvas_clear(canvas); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 2, 10, "Vibro application"); @@ -22,6 +23,7 @@ void vibro_test_input_callback(InputEvent* input_event, void* ctx) { } int32_t vibro_test_app(void* p) { + UNUSED(p); osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); // Configure view port diff --git a/applications/desktop/animations/animation_manager.c b/applications/desktop/animations/animation_manager.c index ea241ec3..75d45ef7 100644 --- a/applications/desktop/animations/animation_manager.c +++ b/applications/desktop/animations/animation_manager.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -364,6 +365,7 @@ static bool animation_manager_is_valid_idle_animation( static StorageAnimation* animation_manager_select_idle_animation(AnimationManager* animation_manager) { + UNUSED(animation_manager); StorageAnimationList_t animation_list; StorageAnimationList_init(animation_list); animation_storage_fill_animation_list(&animation_list); @@ -390,7 +392,7 @@ static StorageAnimation* } } - uint32_t lucky_number = random() % whole_weight; + uint32_t lucky_number = furi_hal_random_get() % whole_weight; uint32_t weight = 0; StorageAnimation* selected = NULL; diff --git a/applications/desktop/animations/animation_storage.c b/applications/desktop/animations/animation_storage.c index aa0f274b..8f2740a7 100644 --- a/applications/desktop/animations/animation_storage.c +++ b/applications/desktop/animations/animation_storage.c @@ -130,7 +130,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis flipper_format_free(file); // add hard-coded animations - for(int i = 0; i < dolphin_internal_size; ++i) { + for(size_t i = 0; i < dolphin_internal_size; ++i) { StorageAnimationList_push_back(*animation_list, (StorageAnimation*)&dolphin_internal[i]); } @@ -142,7 +142,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { furi_assert(strlen(name)); StorageAnimation* storage_animation = NULL; - for(int i = 0; i < dolphin_blocking_size; ++i) { + for(size_t i = 0; i < dolphin_blocking_size; ++i) { if(!strcmp(dolphin_blocking[i].manifest_info.name, name)) { storage_animation = (StorageAnimation*)&dolphin_blocking[i]; break; @@ -150,7 +150,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { } if(!storage_animation) { - for(int i = 0; i < dolphin_internal_size; ++i) { + for(size_t i = 0; i < dolphin_internal_size; ++i) { if(!strcmp(dolphin_internal[i].manifest_info.name, name)) { storage_animation = (StorageAnimation*)&dolphin_internal[i]; break; @@ -365,7 +365,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo animation->frame_bubble_sequences = malloc(sizeof(FrameBubble*) * animation->frame_bubble_sequences_count); - uint32_t current_slot = 0; + int32_t current_slot = 0; for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { FURI_CONST_ASSIGN_PTR( animation->frame_bubble_sequences[i], malloc(sizeof(FrameBubble))); @@ -374,7 +374,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo const FrameBubble* bubble = animation->frame_bubble_sequences[0]; int8_t index = -1; for(;;) { - if(!flipper_format_read_uint32(ff, "Slot", ¤t_slot, 1)) break; + if(!flipper_format_read_int32(ff, "Slot", ¤t_slot, 1)) break; if((current_slot != 0) && (index == -1)) break; if(current_slot == index) { diff --git a/applications/desktop/animations/views/bubble_animation_view.c b/applications/desktop/animations/views/bubble_animation_view.c index 9b60d45c..380664c8 100644 --- a/applications/desktop/animations/views/bubble_animation_view.c +++ b/applications/desktop/animations/views/bubble_animation_view.c @@ -100,7 +100,8 @@ static const FrameBubble* return NULL; } - uint8_t index = random() % (active ? model->active_bubbles : model->passive_bubbles); + uint8_t index = + furi_hal_random_get() % (active ? model->active_bubbles : model->passive_bubbles); const BubbleAnimation* animation = model->current; for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index 7686a145..34c169e0 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -33,6 +33,7 @@ static void desktop_loader_callback(const void* message, void* context) { } static void desktop_lock_icon_callback(Canvas* canvas, void* context) { + UNUSED(context); furi_assert(canvas); canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); } @@ -298,6 +299,7 @@ static bool desktop_is_first_start() { } int32_t desktop_srv(void* p) { + UNUSED(p); Desktop* desktop = desktop_alloc(); bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c index 7486d4aa..c0b3190e 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -53,4 +53,5 @@ bool desktop_settings_scene_pin_disable_on_event(void* context, SceneManagerEven } void desktop_settings_scene_pin_disable_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c index 882b8f0a..a023d6b7 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -18,6 +18,7 @@ static void pin_error_back_callback(void* context) { } static void pin_error_done_callback(const PinCode* pin_code, void* context) { + UNUSED(pin_code); furi_assert(context); DesktopSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c index 22727a7a..b8d630f2 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c @@ -41,4 +41,5 @@ bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManager } void desktop_settings_scene_pin_setup_howto_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/scenes/desktop_scene_fault.c b/applications/desktop/scenes/desktop_scene_fault.c index b75b32aa..36c958af 100644 --- a/applications/desktop/scenes/desktop_scene_fault.c +++ b/applications/desktop/scenes/desktop_scene_fault.c @@ -47,5 +47,6 @@ bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_fault_on_exit(void* context) { + UNUSED(context); furi_hal_rtc_set_fault_data(0); } diff --git a/applications/desktop/scenes/desktop_scene_first_start.c b/applications/desktop/scenes/desktop_scene_first_start.c index 9563094c..dbdf8919 100644 --- a/applications/desktop/scenes/desktop_scene_first_start.c +++ b/applications/desktop/scenes/desktop_scene_first_start.c @@ -50,4 +50,5 @@ bool desktop_scene_first_start_on_event(void* context, SceneManagerEvent event) } void desktop_scene_first_start_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/desktop/scenes/desktop_scene_lock_menu.c index 11478810..a86bb184 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/desktop/scenes/desktop_scene_lock_menu.c @@ -81,4 +81,5 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_lock_menu_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/scenes/desktop_scene_locked.c b/applications/desktop/scenes/desktop_scene_locked.c index 90df2226..f4c08d32 100644 --- a/applications/desktop/scenes/desktop_scene_locked.c +++ b/applications/desktop/scenes/desktop_scene_locked.c @@ -109,4 +109,5 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_locked_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/scenes/desktop_scene_pin_timeout.c b/applications/desktop/scenes/desktop_scene_pin_timeout.c index 3c267a0d..ebe825e6 100644 --- a/applications/desktop/scenes/desktop_scene_pin_timeout.c +++ b/applications/desktop/scenes/desktop_scene_pin_timeout.c @@ -43,4 +43,5 @@ bool desktop_scene_pin_timeout_on_event(void* context, SceneManagerEvent event) } void desktop_scene_pin_timeout_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/desktop/views/desktop_view_pin_timeout.c b/applications/desktop/views/desktop_view_pin_timeout.c index d9827339..6e1e807f 100644 --- a/applications/desktop/views/desktop_view_pin_timeout.c +++ b/applications/desktop/views/desktop_view_pin_timeout.c @@ -51,6 +51,8 @@ static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { } static bool desktop_view_pin_timeout_input(InputEvent* event, void* context) { + UNUSED(event); + UNUSED(context); return true; } diff --git a/applications/dialogs/dialogs.c b/applications/dialogs/dialogs.c index 2c8d2418..cf4a2ad6 100644 --- a/applications/dialogs/dialogs.c +++ b/applications/dialogs/dialogs.c @@ -11,6 +11,7 @@ static DialogsApp* dialogs_app_alloc() { } static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) { + UNUSED(app); switch(message->command) { case DialogsAppCommandFileOpen: message->return_data->bool_value = @@ -25,6 +26,7 @@ static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* mess } int32_t dialogs_srv(void* p) { + UNUSED(p); DialogsApp* app = dialogs_app_alloc(); furi_record_create("dialogs", app); diff --git a/applications/dialogs/dialogs.h b/applications/dialogs/dialogs.h index 2a05ef41..9c71c098 100644 --- a/applications/dialogs/dialogs.h +++ b/applications/dialogs/dialogs.h @@ -132,4 +132,4 @@ void dialog_message_show_storage_error(DialogsApp* context, const char* error_te #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dialogs/dialogs_api.c b/applications/dialogs/dialogs_api.c index 261d9d4e..c4efb287 100644 --- a/applications/dialogs/dialogs_api.c +++ b/applications/dialogs/dialogs_api.c @@ -70,4 +70,4 @@ void dialog_message_show_storage_error(DialogsApp* context, const char* error_te dialog_message_set_buttons(message, "Back", NULL, NULL); dialog_message_show(context, message); dialog_message_free(message); -} \ No newline at end of file +} diff --git a/applications/dialogs/dialogs_i.h b/applications/dialogs/dialogs_i.h index 7b601eda..b61e10ab 100644 --- a/applications/dialogs/dialogs_i.h +++ b/applications/dialogs/dialogs_i.h @@ -12,4 +12,4 @@ struct DialogsApp { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dialogs/dialogs_message.h b/applications/dialogs/dialogs_message.h index 48324b15..d7b5fabf 100644 --- a/applications/dialogs/dialogs_message.h +++ b/applications/dialogs/dialogs_message.h @@ -43,4 +43,4 @@ typedef struct { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dialogs/dialogs_module_file_select.h b/applications/dialogs/dialogs_module_file_select.h index da012fb4..749fe9c1 100644 --- a/applications/dialogs/dialogs_module_file_select.h +++ b/applications/dialogs/dialogs_module_file_select.h @@ -9,4 +9,4 @@ bool dialogs_app_process_module_file_select(const DialogsAppMessageDataFileSelec #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dialogs/dialogs_module_message.h b/applications/dialogs/dialogs_module_message.h index 189870ac..b4f1b162 100644 --- a/applications/dialogs/dialogs_module_message.h +++ b/applications/dialogs/dialogs_module_message.h @@ -9,4 +9,4 @@ DialogMessageButton dialogs_app_process_module_message(const DialogsAppMessageDa #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dialogs/view_holder.h b/applications/dialogs/view_holder.h index 785ad20a..8e7db3b8 100644 --- a/applications/dialogs/view_holder.h +++ b/applications/dialogs/view_holder.h @@ -95,4 +95,4 @@ void view_holder_update(View* view, void* context); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index 60068aff..47960286 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -118,6 +118,7 @@ void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event) { } void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) { + UNUSED(dolphin); if(event->flag) { osEventFlagsSet(event->flag, DOLPHIN_LOCK_EVENT_FLAG); } @@ -149,6 +150,7 @@ static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin) { } int32_t dolphin_srv(void* p) { + UNUSED(p); Dolphin* dolphin = dolphin_alloc(); furi_record_create("dolphin", dolphin); diff --git a/applications/dolphin/helpers/dolphin_state.h b/applications/dolphin/helpers/dolphin_state.h index 07d0b427..3e02fb87 100644 --- a/applications/dolphin/helpers/dolphin_state.h +++ b/applications/dolphin/helpers/dolphin_state.h @@ -12,7 +12,7 @@ typedef struct { uint32_t flags; uint32_t icounter; - uint32_t butthurt; + int32_t butthurt; uint64_t timestamp; } DolphinStoreData; diff --git a/applications/dolphin/passport/passport.c b/applications/dolphin/passport/passport.c index 3df88a83..13bf086b 100644 --- a/applications/dolphin/passport/passport.c +++ b/applications/dolphin/passport/passport.c @@ -90,6 +90,7 @@ static void render_callback(Canvas* canvas, void* ctx) { } int32_t passport_app(void* p) { + UNUSED(p); osSemaphoreId_t semaphore = osSemaphoreNew(1, 0, NULL); furi_assert(semaphore); diff --git a/applications/gpio/gpio_app.c b/applications/gpio/gpio_app.c index 7dfce836..b5f5184a 100644 --- a/applications/gpio/gpio_app.c +++ b/applications/gpio/gpio_app.c @@ -95,6 +95,7 @@ void gpio_app_free(GpioApp* app) { } int32_t gpio_app(void* p) { + UNUSED(p); GpioApp* gpio_app = gpio_app_alloc(); view_dispatcher_run(gpio_app->view_dispatcher); diff --git a/applications/gpio/scenes/gpio_scene_test.c b/applications/gpio/scenes/gpio_scene_test.c index 009e2ff4..b015d809 100644 --- a/applications/gpio/scenes/gpio_scene_test.c +++ b/applications/gpio/scenes/gpio_scene_test.c @@ -19,9 +19,12 @@ void gpio_scene_test_on_enter(void* context) { } bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); return false; } void gpio_scene_test_on_exit(void* context) { + UNUSED(context); gpio_item_configure_all_pins(GpioModeAnalog); } diff --git a/applications/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/gpio/scenes/gpio_scene_usb_uart_config.c index 6fba0d1e..653a306a 100644 --- a/applications/gpio/scenes/gpio_scene_usb_uart_config.c +++ b/applications/gpio/scenes/gpio_scene_usb_uart_config.c @@ -28,12 +28,9 @@ static const uint32_t baudrate_list[] = { }; bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) { - //GpioApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - } - return consumed; + UNUSED(context); + UNUSED(event); + return false; } static void line_vcp_cb(VariableItem* item) { diff --git a/applications/gpio/usb_uart_bridge.c b/applications/gpio/usb_uart_bridge.c index 8f27340e..f70cf640 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/gpio/usb_uart_bridge.c @@ -101,6 +101,7 @@ static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) { } static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) { + UNUSED(usb_uart); furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); FURI_LOG_I("", "Deinit %d", vcp_ch); if(vcp_ch != 0) { @@ -120,6 +121,7 @@ static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) { } static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) { + UNUSED(usb_uart); furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL); if(uart_ch == FuriHalUartIdUSART1) furi_hal_console_enable(); @@ -143,7 +145,7 @@ static void usb_uart_set_baudrate(UsbUartBridge* usb_uart, uint32_t baudrate) { static void usb_uart_update_ctrl_lines(UsbUartBridge* usb_uart) { if(usb_uart->cfg.flow_pins != 0) { - furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); + furi_assert((size_t)(usb_uart->cfg.flow_pins - 1) < COUNT_OF(flow_pins)); uint8_t state = furi_hal_cdc_get_ctrl_line_state(usb_uart->cfg.vcp_ch); furi_hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][0], !(state & USB_CDC_BIT_RTS)); @@ -171,7 +173,7 @@ static int32_t usb_uart_worker(void* context) { usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch); usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); if(usb_uart->cfg.flow_pins != 0) { - furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); + furi_assert((size_t)(usb_uart->cfg.flow_pins - 1) < COUNT_OF(flow_pins)); furi_hal_gpio_init_simple( flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); furi_hal_gpio_init_simple( @@ -238,9 +240,7 @@ static int32_t usb_uart_worker(void* context) { flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); } if(usb_uart->cfg_new.flow_pins != 0) { - furi_assert( - (usb_uart->cfg_new.flow_pins - 1) < - (sizeof(flow_pins) / sizeof(flow_pins[0]))); + furi_assert((size_t)(usb_uart->cfg_new.flow_pins - 1) < COUNT_OF(flow_pins)); furi_hal_gpio_init_simple( flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); furi_hal_gpio_init_simple( @@ -318,14 +318,18 @@ static void vcp_on_cdc_rx(void* context) { } static void vcp_state_callback(void* context, uint8_t state) { + UNUSED(context); + UNUSED(state); } static void vcp_on_cdc_control_line(void* context, uint8_t state) { + UNUSED(state); UsbUartBridge* usb_uart = (UsbUartBridge*)context; osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet); } static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { + UNUSED(config); UsbUartBridge* usb_uart = (UsbUartBridge*)context; osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtLineCfgSet); } diff --git a/applications/gpio/views/gpio_test.c b/applications/gpio/views/gpio_test.c index cf05dafa..37c2f408 100755 --- a/applications/gpio/views/gpio_test.c +++ b/applications/gpio/views/gpio_test.c @@ -123,6 +123,7 @@ void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback, furi_assert(callback); with_view_model( gpio_test->view, (GpioTestModel * model) { + UNUSED(model); gpio_test->callback = callback; gpio_test->context = context; return false; diff --git a/applications/gpio/views/gpio_usb_uart.c b/applications/gpio/views/gpio_usb_uart.c index cd507570..d2d371b6 100644 --- a/applications/gpio/views/gpio_usb_uart.c +++ b/applications/gpio/views/gpio_usb_uart.c @@ -130,6 +130,7 @@ void gpio_usb_uart_set_callback(GpioUsbUart* usb_uart, GpioUsbUartCallback callb with_view_model( usb_uart->view, (GpioUsbUartModel * model) { + UNUSED(model); usb_uart->callback = callback; usb_uart->context = context; return false; diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 9ecfdebb..77ee4487 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -47,10 +47,9 @@ bool gui_redraw_fs(Gui* gui) { static void gui_redraw_status_bar(Gui* gui, bool need_attention) { ViewPortArray_it_t it; - uint8_t x; - uint8_t x_used = 0; + uint8_t left_used = 0; + uint8_t right_used = 0; uint8_t width; - ViewPort* view_port; canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); canvas_frame_set( gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); @@ -69,100 +68,126 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { canvas_set_bitmap_mode(gui->canvas, 0); // Right side - x = GUI_DISPLAY_WIDTH; + uint8_t x = GUI_DISPLAY_WIDTH - 1; ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); - while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { - // Render view_port; - view_port = *ViewPortArray_ref(it); + while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) { + ViewPort* view_port = *ViewPortArray_ref(it); if(view_port_is_enabled(view_port)) { width = view_port_get_width(view_port); if(!width) width = 8; - x_used += width; + // Recalculate next position + right_used += (width + 2); x -= (width + 2); + // Prepare work area background canvas_frame_set( - gui->canvas, x - 3, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); - - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); - canvas_set_color(gui->canvas, ColorBlack); - - canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); - canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); - canvas_draw_line( gui->canvas, - 2, - canvas_height(gui->canvas) - 2, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - + x - 1, + GUI_STATUS_BAR_Y + 1, + width + 2, + GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); + canvas_set_color(gui->canvas, ColorWhite); + canvas_draw_box( + gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); + canvas_set_color(gui->canvas, ColorBlack); + // ViewPort draw canvas_frame_set( - gui->canvas, x, GUI_STATUS_BAR_Y + 1, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); - + gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); view_port_draw(view_port, gui->canvas); } ViewPortArray_next(it); } + // Draw frame around icons on the right + if(right_used) { + canvas_frame_set( + gui->canvas, + GUI_DISPLAY_WIDTH - 3 - right_used, + GUI_STATUS_BAR_Y, + right_used + 3, + GUI_STATUS_BAR_HEIGHT); + canvas_set_color(gui->canvas, ColorBlack); + canvas_draw_rframe( + gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); + canvas_draw_line( + gui->canvas, + canvas_width(gui->canvas) - 2, + 1, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + canvas_draw_line( + gui->canvas, + 1, + canvas_height(gui->canvas) - 2, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + } + // Left side - x = 0; + x = 2; ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); - while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { - // Render view_port; - view_port = *ViewPortArray_ref(it); + while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { + ViewPort* view_port = *ViewPortArray_ref(it); if(view_port_is_enabled(view_port)) { width = view_port_get_width(view_port); if(!width) width = 8; - x_used += width; - + // Prepare work area background canvas_frame_set( - gui->canvas, 0, GUI_STATUS_BAR_Y, x + width + 5, GUI_STATUS_BAR_HEIGHT); - canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); - canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); - canvas_draw_line( gui->canvas, - 2, - canvas_height(gui->canvas) - 2, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - - canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); - + x - 1, + GUI_STATUS_BAR_Y + 1, + width + 2, + GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); + canvas_draw_box( + gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); canvas_set_color(gui->canvas, ColorBlack); - + // ViewPort draw canvas_frame_set( - gui->canvas, x + 3, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); + gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); view_port_draw(view_port, gui->canvas); - + // Recalculate next position + left_used += (width + 2); x += (width + 2); } ViewPortArray_next(it); } - + // Extra notification if(need_attention) { width = icon_get_width(&I_Attention_5x8); - canvas_frame_set(gui->canvas, 0, GUI_STATUS_BAR_Y, x + width + 5, GUI_STATUS_BAR_HEIGHT); + // Prepare work area background + canvas_frame_set( + gui->canvas, + x - 1, + GUI_STATUS_BAR_Y + 1, + width + 2, + GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); + canvas_set_color(gui->canvas, ColorWhite); + canvas_draw_box(gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); + canvas_set_color(gui->canvas, ColorBlack); + // Draw Icon + canvas_frame_set( + gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); + canvas_draw_icon(gui->canvas, 0, 0, &I_Attention_5x8); + // Recalculate next position + left_used += (width + 2); + x += (width + 2); + } + // Draw frame around icons on the left + if(left_used) { + canvas_frame_set(gui->canvas, 0, 0, left_used + 3, GUI_STATUS_BAR_HEIGHT); canvas_draw_rframe( gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); - canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); canvas_draw_line( gui->canvas, - 2, + canvas_width(gui->canvas) - 2, + 1, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + canvas_draw_line( + gui->canvas, + 1, canvas_height(gui->canvas) - 2, canvas_width(gui->canvas) - 2, canvas_height(gui->canvas) - 2); - - canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); - - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); - canvas_set_color(gui->canvas, ColorBlack); - - canvas_frame_set( - gui->canvas, x + 3, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); - canvas_draw_icon(gui->canvas, 0, 0, &I_Attention_5x8); } } @@ -469,6 +494,7 @@ Gui* gui_alloc() { } int32_t gui_srv(void* p) { + UNUSED(p); Gui* gui = gui_alloc(); furi_record_create("gui", gui); diff --git a/applications/gui/icon.c b/applications/gui/icon.c index bbc77516..98f35b12 100644 --- a/applications/gui/icon.c +++ b/applications/gui/icon.c @@ -10,4 +10,4 @@ uint8_t icon_get_height(const Icon* instance) { const uint8_t* icon_get_data(const Icon* instance) { return instance->frames[0]; -} \ No newline at end of file +} diff --git a/applications/gui/icon.h b/applications/gui/icon.h index ebe40266..e33c4d34 100644 --- a/applications/gui/icon.h +++ b/applications/gui/icon.h @@ -39,4 +39,4 @@ const uint8_t* icon_get_data(const Icon* instance); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/button_menu.c b/applications/gui/modules/button_menu.c index 8f38efc4..36fd6f3a 100644 --- a/applications/gui/modules/button_menu.c +++ b/applications/gui/modules/button_menu.c @@ -331,7 +331,7 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) { ButtonMenuItemArray_it_t it; for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); ButtonMenuItemArray_next(it), ++item_position) { - if(ButtonMenuItemArray_cref(it)->index == index) { + if((uint32_t)ButtonMenuItemArray_cref(it)->index == index) { model->position = item_position; break; } diff --git a/applications/gui/modules/button_panel.c b/applications/gui/modules/button_panel.c index c2328d20..e3ae59a3 100644 --- a/applications/gui/modules/button_panel.c +++ b/applications/gui/modules/button_panel.c @@ -215,8 +215,8 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) { static void button_panel_process_down(ButtonPanel* button_panel) { with_view_model( button_panel->view, (ButtonPanelModel * model) { - size_t new_selected_item_x = model->selected_item_x; - size_t new_selected_item_y = model->selected_item_y; + uint16_t new_selected_item_x = model->selected_item_x; + uint16_t new_selected_item_y = model->selected_item_y; size_t i; if(new_selected_item_y >= (model->reserve_y - 1)) return false; @@ -291,8 +291,8 @@ static void button_panel_process_left(ButtonPanel* button_panel) { static void button_panel_process_right(ButtonPanel* button_panel) { with_view_model( button_panel->view, (ButtonPanelModel * model) { - size_t new_selected_item_x = model->selected_item_x; - size_t new_selected_item_y = model->selected_item_y; + uint16_t new_selected_item_x = model->selected_item_x; + uint16_t new_selected_item_y = model->selected_item_y; size_t i; if(new_selected_item_x >= (model->reserve_x - 1)) return false; diff --git a/applications/gui/modules/byte_input.h b/applications/gui/modules/byte_input.h index b2f94f3c..42c4b5d6 100644 --- a/applications/gui/modules/byte_input.h +++ b/applications/gui/modules/byte_input.h @@ -66,4 +66,4 @@ void byte_input_set_header_text(ByteInput* byte_input, const char* text); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/empty_screen.c b/applications/gui/modules/empty_screen.c index 61b4af36..0a51bc71 100644 --- a/applications/gui/modules/empty_screen.c +++ b/applications/gui/modules/empty_screen.c @@ -6,10 +6,13 @@ struct EmptyScreen { }; static void empty_screen_view_draw_callback(Canvas* canvas, void* _model) { + UNUSED(_model); canvas_clear(canvas); } static bool empty_screen_view_input_callback(InputEvent* event, void* context) { + UNUSED(event); + UNUSED(context); return false; } diff --git a/applications/gui/modules/empty_screen.h b/applications/gui/modules/empty_screen.h index 43d2fe04..23ebeb3a 100644 --- a/applications/gui/modules/empty_screen.h +++ b/applications/gui/modules/empty_screen.h @@ -38,4 +38,4 @@ View* empty_screen_get_view(EmptyScreen* empty_screen); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/file_select.h b/applications/gui/modules/file_select.h index 7318c87c..ed3d5b60 100644 --- a/applications/gui/modules/file_select.h +++ b/applications/gui/modules/file_select.h @@ -28,4 +28,4 @@ void file_select_set_selected_file(FileSelect* file_select, const char* filename #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/loading.c b/applications/gui/modules/loading.c index 7f623e24..60dc8338 100644 --- a/applications/gui/modules/loading.c +++ b/applications/gui/modules/loading.c @@ -34,6 +34,7 @@ static void loading_draw_callback(Canvas* canvas, void* _model) { } static bool loading_input_callback(InputEvent* event, void* context) { + UNUSED(event); furi_assert(context); return true; } diff --git a/applications/gui/modules/text_box.c b/applications/gui/modules/text_box.c index a7d0d763..52307ec2 100755 --- a/applications/gui/modules/text_box.c +++ b/applications/gui/modules/text_box.c @@ -87,7 +87,7 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { model->scroll_num = line_num - 4; model->scroll_pos = line_num - 5; } else { - model->scroll_num = MAX(line_num - 4, 0); + model->scroll_num = MAX(line_num - 4, 0u); model->scroll_pos = 0; } } diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c index 058762ad..04cd2d7f 100644 --- a/applications/gui/modules/text_input.c +++ b/applications/gui/modules/text_input.c @@ -122,15 +122,15 @@ static const TextInputKey* get_row(uint8_t row_index) { return row; } -static const char get_selected_char(TextInputModel* model) { +static char get_selected_char(TextInputModel* model) { return get_row(model->selected_row)[model->selected_column].text; } -static const bool char_is_lowercase(char letter) { +static bool char_is_lowercase(char letter) { return (letter >= 0x61 && letter <= 0x7A); } -static const char char_to_uppercase(const char letter) { +static char char_to_uppercase(const char letter) { if(isalpha(letter)) { return (letter - 0x20); } else { @@ -260,6 +260,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { } static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { + UNUSED(text_input); if(model->selected_row > 0) { model->selected_row--; if(model->selected_column > get_row_size(model->selected_row) - 6) { @@ -269,6 +270,7 @@ static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { } static void text_input_handle_down(TextInput* text_input, TextInputModel* model) { + UNUSED(text_input); if(model->selected_row < keyboard_row_count - 1) { model->selected_row++; if(model->selected_column > get_row_size(model->selected_row) - 4) { @@ -278,6 +280,7 @@ static void text_input_handle_down(TextInput* text_input, TextInputModel* model) } static void text_input_handle_left(TextInput* text_input, TextInputModel* model) { + UNUSED(text_input); if(model->selected_column > 0) { model->selected_column--; } else { @@ -286,6 +289,7 @@ static void text_input_handle_left(TextInput* text_input, TextInputModel* model) } static void text_input_handle_right(TextInput* text_input, TextInputModel* model) { + UNUSED(text_input); if(model->selected_column < get_row_size(model->selected_row) - 1) { model->selected_column++; } else { diff --git a/applications/gui/modules/validators.h b/applications/gui/modules/validators.h index 3a834a8a..15dbe901 100644 --- a/applications/gui/modules/validators.h +++ b/applications/gui/modules/validators.h @@ -19,4 +19,4 @@ bool validator_is_file_callback(const char* text, string_t error, void* context) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/variable_item_list.c b/applications/gui/modules/variable_item_list.c index ebbdd434..4e5e4664 100644 --- a/applications/gui/modules/variable_item_list.c +++ b/applications/gui/modules/variable_item_list.c @@ -364,6 +364,7 @@ void variable_item_list_set_enter_callback( furi_assert(callback); with_view_model( variable_item_list->view, (VariableItemListModel * model) { + UNUSED(model); variable_item_list->callback = callback; variable_item_list->context = context; return false; diff --git a/applications/gui/view.c b/applications/gui/view.c index e9642d9b..ec73882d 100644 --- a/applications/gui/view.c +++ b/applications/gui/view.c @@ -126,6 +126,7 @@ void view_commit_model(View* view, bool update) { } void view_icon_animation_callback(IconAnimation* instance, void* context) { + UNUSED(instance); furi_assert(context); View* view = context; if(view->update_callback) { diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c new file mode 100644 index 00000000..a38f077f --- /dev/null +++ b/applications/ibutton/ibutton.c @@ -0,0 +1,349 @@ +#include "ibutton.h" +#include "ibutton_i.h" +#include "ibutton/scenes/ibutton_scene.h" + +#include +#include + +static const NotificationSequence* ibutton_notification_sequences[] = { + &sequence_error, + &sequence_success, + &sequence_blink_cyan_10, + &sequence_blink_magenta_10, + &sequence_blink_yellow_10, + &sequence_set_red_255, + &sequence_reset_red, + &sequence_set_green_255, + &sequence_reset_green, +}; + +static void ibutton_make_app_folder(iButton* ibutton) { + if(!storage_simply_mkdir(ibutton->storage, IBUTTON_APP_FOLDER)) { + dialog_message_show_storage_error(ibutton->dialogs, "Cannot create\napp folder"); + } +} + +static bool ibutton_load_key_data(iButton* ibutton, string_t key_path) { + FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); + bool result = false; + string_t data; + string_init(data); + + do { + if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break; + + // header + uint32_t version; + if(!flipper_format_read_header(file, data, &version)) break; + if(string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break; + if(version != 1) break; + + // key type + iButtonKeyType type; + if(!flipper_format_read_string(file, "Key type", data)) break; + if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; + + // key data + uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; + if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) + break; + + ibutton_key_set_type(ibutton->key, type); + ibutton_key_set_data(ibutton->key, key_data, IBUTTON_KEY_DATA_SIZE); + + result = true; + } while(false); + + flipper_format_free(file); + string_clear(data); + + if(!result) { + dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); + } + + return result; +} + +bool ibutton_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + iButton* ibutton = context; + return scene_manager_handle_custom_event(ibutton->scene_manager, event); +} + +bool ibutton_back_event_callback(void* context) { + furi_assert(context); + iButton* ibutton = context; + return scene_manager_handle_back_event(ibutton->scene_manager); +} + +void ibutton_tick_event_callback(void* context) { + furi_assert(context); + iButton* ibutton = context; + scene_manager_handle_tick_event(ibutton->scene_manager); +} + +iButton* ibutton_alloc() { + iButton* ibutton = malloc(sizeof(iButton)); + + ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton); + + ibutton->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(ibutton->view_dispatcher); + view_dispatcher_set_event_callback_context(ibutton->view_dispatcher, ibutton); + view_dispatcher_set_custom_event_callback( + ibutton->view_dispatcher, ibutton_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + ibutton->view_dispatcher, ibutton_back_event_callback); + view_dispatcher_set_tick_event_callback( + ibutton->view_dispatcher, ibutton_tick_event_callback, 100); + + ibutton->gui = furi_record_open("gui"); + view_dispatcher_attach_to_gui( + ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); + + ibutton->storage = furi_record_open("storage"); + ibutton->dialogs = furi_record_open("dialogs"); + ibutton->notifications = furi_record_open("notification"); + + ibutton->key = ibutton_key_alloc(); + ibutton->key_worker = ibutton_worker_alloc(); + ibutton_worker_start_thread(ibutton->key_worker); + + ibutton->submenu = submenu_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewSubmenu, submenu_get_view(ibutton->submenu)); + + ibutton->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewByteInput, byte_input_get_view(ibutton->byte_input)); + + ibutton->text_input = text_input_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewTextInput, text_input_get_view(ibutton->text_input)); + + ibutton->popup = popup_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewPopup, popup_get_view(ibutton->popup)); + + ibutton->widget = widget_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget)); + + ibutton->dialog_ex = dialog_ex_alloc(); + view_dispatcher_add_view( + ibutton->view_dispatcher, iButtonViewDialogEx, dialog_ex_get_view(ibutton->dialog_ex)); + + return ibutton; +} + +void ibutton_free(iButton* ibutton) { + furi_assert(ibutton); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewDialogEx); + dialog_ex_free(ibutton->dialog_ex); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget); + widget_free(ibutton->widget); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewPopup); + popup_free(ibutton->popup); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewTextInput); + text_input_free(ibutton->text_input); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewByteInput); + byte_input_free(ibutton->byte_input); + + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewSubmenu); + submenu_free(ibutton->submenu); + + view_dispatcher_free(ibutton->view_dispatcher); + scene_manager_free(ibutton->scene_manager); + + furi_record_close("storage"); + ibutton->storage = NULL; + + furi_record_close("notification"); + ibutton->notifications = NULL; + + furi_record_close("dialogs"); + ibutton->dialogs = NULL; + + furi_record_close("gui"); + ibutton->gui = NULL; + + ibutton_worker_stop_thread(ibutton->key_worker); + ibutton_worker_free(ibutton->key_worker); + ibutton_key_free(ibutton->key); + + free(ibutton); +} + +bool ibutton_file_select(iButton* ibutton) { + bool success = dialog_file_select_show( + ibutton->dialogs, + IBUTTON_APP_FOLDER, + IBUTTON_APP_EXTENSION, + ibutton->file_name, + IBUTTON_FILE_NAME_SIZE, + ibutton_key_get_name_p(ibutton->key)); + + if(success) { + string_t key_str; + string_init_printf( + key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION); + success = ibutton_load_key_data(ibutton, key_str); + + if(success) { + ibutton_key_set_name(ibutton->key, ibutton->file_name); + } + + string_clear(key_str); + } + + return success; +} + +bool ibutton_load_key(iButton* ibutton, const char* key_name) { + string_t key_path; + string_init_set_str(key_path, key_name); + + const bool success = ibutton_load_key_data(ibutton, key_path); + + if(success) { + path_extract_filename_no_ext(key_name, key_path); + ibutton_key_set_name(ibutton->key, string_get_cstr(key_path)); + } + + string_clear(key_path); + return success; +} + +bool ibutton_save_key(iButton* ibutton, const char* key_name) { + // Create ibutton directory if necessary + ibutton_make_app_folder(ibutton); + + FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); + iButtonKey* key = ibutton->key; + + string_t key_file_name; + bool result = false; + string_init(key_file_name); + + do { + // First remove key if it was saved (we rename the key) + if(!ibutton_delete_key(ibutton)) break; + + // Save the key + ibutton_key_set_name(key, key_name); + + // Set full file name, for new key + string_printf( + key_file_name, + "%s/%s%s", + IBUTTON_APP_FOLDER, + ibutton_key_get_name_p(key), + IBUTTON_APP_EXTENSION); + + // Open file for write + if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; + + // Write header + if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break; + + // Write key type + if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) + break; + const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); + if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; + + // Write data + if(!flipper_format_write_comment_cstr( + file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) + break; + + if(!flipper_format_write_hex( + file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) + break; + result = true; + + } while(false); + + flipper_format_free(file); + + string_clear(key_file_name); + + if(!result) { + dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file"); + } + + return result; +} + +bool ibutton_delete_key(iButton* ibutton) { + string_t file_name; + bool result = false; + + string_init_printf( + file_name, + "%s/%s%s", + IBUTTON_APP_FOLDER, + ibutton_key_get_name_p(ibutton->key), + IBUTTON_APP_EXTENSION); + result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name)); + string_clear(file_name); + + return result; +} + +void ibutton_text_store_set(iButton* ibutton, const char* text, ...) { + va_list args; + va_start(args, text); + + vsnprintf(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE, text, args); + + va_end(args); +} + +void ibutton_text_store_clear(iButton* ibutton) { + memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE); +} + +void ibutton_switch_to_previous_scene_one_of( + iButton* ibutton, + const uint32_t* scene_ids, + size_t scene_ids_size) { + furi_assert(scene_ids_size); + SceneManager* scene_manager = ibutton->scene_manager; + + for(size_t i = 0; i < scene_ids_size; ++i) { + const uint32_t scene_id = scene_ids[i]; + if(scene_manager_has_previous_scene(scene_manager, scene_id)) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, scene_id); + return; + } + } +} + +void ibutton_notification_message(iButton* ibutton, uint32_t message) { + furi_assert(message < sizeof(ibutton_notification_sequences) / sizeof(NotificationSequence*)); + notification_message(ibutton->notifications, ibutton_notification_sequences[message]); +} + +int32_t ibutton_app(void* p) { + iButton* ibutton = ibutton_alloc(); + + ibutton_make_app_folder(ibutton); + + if(p && ibutton_load_key(ibutton, (const char*)p)) { + // TODO: Display an error if the key from p could not be loaded + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + } else { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); + } + + view_dispatcher_run(ibutton->view_dispatcher); + + ibutton_free(ibutton); + return 0; +} diff --git a/applications/ibutton/ibutton.cpp b/applications/ibutton/ibutton.cpp deleted file mode 100644 index 35dc2ce6..00000000 --- a/applications/ibutton/ibutton.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "ibutton_app.h" - -// app enter function -extern "C" int32_t ibutton_app(void* p) { - iButtonApp* app = new iButtonApp(); - app->run(p); - delete app; - - return 255; -} \ No newline at end of file diff --git a/applications/ibutton/ibutton.h b/applications/ibutton/ibutton.h new file mode 100644 index 00000000..56d6e3b6 --- /dev/null +++ b/applications/ibutton/ibutton.h @@ -0,0 +1,3 @@ +#pragma once + +typedef struct iButton iButton; diff --git a/applications/ibutton/ibutton_app.cpp b/applications/ibutton/ibutton_app.cpp deleted file mode 100644 index 43eb3692..00000000 --- a/applications/ibutton/ibutton_app.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include "ibutton_app.h" -#include -#include -#include -#include -#include - -const char* iButtonApp::app_folder = "/any/ibutton"; -const char* iButtonApp::app_extension = ".ibtn"; -const char* iButtonApp::app_filetype = "Flipper iButton key"; - -void iButtonApp::run(void* args) { - iButtonEvent event; - bool consumed; - bool exit = false; - - make_app_folder(); - - if(args && load_key((const char*)args)) { - current_scene = Scene::SceneEmulate; - } - - scenes[current_scene]->on_enter(this); - - while(!exit) { - view.receive_event(&event); - - consumed = scenes[current_scene]->on_event(this, &event); - - if(!consumed) { - if(event.type == iButtonEvent::Type::EventTypeBack) { - exit = switch_to_previous_scene(); - } - } - }; - - scenes[current_scene]->on_exit(this); -} - -iButtonApp::iButtonApp() - : notification{"notification"} - , storage{"storage"} - , dialogs{"dialogs"} { - key = ibutton_key_alloc(); - key_worker = ibutton_worker_alloc(); - ibutton_worker_start_thread(key_worker); -} - -iButtonApp::~iButtonApp() { - for(std::map::iterator it = scenes.begin(); it != scenes.end(); ++it) { - delete it->second; - } - scenes.clear(); - - ibutton_worker_stop_thread(key_worker); - ibutton_worker_free(key_worker); - ibutton_key_free(key); -} - -iButtonAppViewManager* iButtonApp::get_view_manager() { - return &view; -} - -void iButtonApp::switch_to_next_scene(Scene next_scene) { - previous_scenes_list.push_front(current_scene); - - if(next_scene != Scene::SceneExit) { - scenes[current_scene]->on_exit(this); - current_scene = next_scene; - scenes[current_scene]->on_enter(this); - } -} - -void iButtonApp::search_and_switch_to_previous_scene(std::initializer_list scenes_list) { - Scene previous_scene = Scene::SceneStart; - bool scene_found = false; - - while(!scene_found) { - previous_scene = get_previous_scene(); - for(Scene element : scenes_list) { - if(previous_scene == element || previous_scene == Scene::SceneStart) { - scene_found = true; - break; - } - } - } - - scenes[current_scene]->on_exit(this); - current_scene = previous_scene; - scenes[current_scene]->on_enter(this); -} - -bool iButtonApp::switch_to_previous_scene(uint8_t count) { - Scene previous_scene = Scene::SceneStart; - - for(uint8_t i = 0; i < count; i++) { - previous_scene = get_previous_scene(); - if(previous_scene == Scene::SceneExit) break; - } - - if(previous_scene == Scene::SceneExit) { - return true; - } else { - scenes[current_scene]->on_exit(this); - current_scene = previous_scene; - scenes[current_scene]->on_enter(this); - return false; - } -} - -iButtonApp::Scene iButtonApp::get_previous_scene() { - Scene scene = previous_scenes_list.front(); - previous_scenes_list.pop_front(); - return scene; -} - -iButtonWorker* iButtonApp::get_key_worker() { - return key_worker; -} - -iButtonKey* iButtonApp::get_key() { - return key; -} - -char* iButtonApp::get_file_name() { - return file_name; -} - -uint8_t iButtonApp::get_file_name_size() { - return file_name_size; -} - -void iButtonApp::notify_read() { - notification_message(notification, &sequence_blink_cyan_10); -} - -void iButtonApp::notify_emulate() { - notification_message(notification, &sequence_blink_magenta_10); -} - -void iButtonApp::notify_yellow_blink() { - notification_message(notification, &sequence_blink_yellow_10); -} - -void iButtonApp::notify_error() { - notification_message(notification, &sequence_error); -} - -void iButtonApp::notify_success() { - notification_message(notification, &sequence_success); -} - -void iButtonApp::notify_green_on() { - notification_message_block(notification, &sequence_set_green_255); -} - -void iButtonApp::notify_green_off() { - notification_message(notification, &sequence_reset_green); -} - -void iButtonApp::notify_red_on() { - notification_message_block(notification, &sequence_set_red_255); -} - -void iButtonApp::notify_red_off() { - notification_message(notification, &sequence_reset_red); -} - -void iButtonApp::set_text_store(const char* text...) { - va_list args; - va_start(args, text); - - vsnprintf(text_store, text_store_size, text, args); - - va_end(args); -} - -char* iButtonApp::get_text_store() { - return text_store; -} - -uint8_t iButtonApp::get_text_store_size() { - return text_store_size; -} - -// file managment -bool iButtonApp::save_key(const char* key_name) { - // Create ibutton directory if necessary - make_app_folder(); - - FlipperFormat* file = flipper_format_file_alloc(storage); - string_t key_file_name; - bool result = false; - string_init(key_file_name); - - do { - // First remove key if it was saved (we rename the key) - if(!delete_key()) break; - - // Save the key - ibutton_key_set_name(key, key_name); - - // Set full file name, for new key - string_printf( - key_file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); - - // Open file for write - if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; - - // Write header - if(!flipper_format_write_header_cstr(file, iButtonApp::app_filetype, 1)) break; - - // Write key type - if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) - break; - const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); - if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; - - // Write data - if(!flipper_format_write_comment_cstr( - file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) - break; - - if(!flipper_format_write_hex( - file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) - break; - result = true; - - } while(false); - - flipper_format_free(file); - - string_clear(key_file_name); - - if(!result) { - dialog_message_show_storage_error(dialogs, "Cannot save\nkey file"); - } - - return result; -} - -bool iButtonApp::load_key_data(string_t key_path) { - FlipperFormat* file = flipper_format_file_alloc(storage); - bool result = false; - string_t data; - string_init(data); - - do { - if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break; - - // header - uint32_t version; - if(!flipper_format_read_header(file, data, &version)) break; - if(string_cmp_str(data, iButtonApp::app_filetype) != 0) break; - if(version != 1) break; - - // key type - iButtonKeyType type; - if(!flipper_format_read_string(file, "Key type", data)) break; - if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; - - // key data - uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; - if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) - break; - - ibutton_key_set_type(key, type); - ibutton_key_set_data(key, key_data, IBUTTON_KEY_DATA_SIZE); - - result = true; - } while(false); - - flipper_format_free(file); - string_clear(data); - - if(!result) { - dialog_message_show_storage_error(dialogs, "Cannot load\nkey file"); - } - - return result; -} - -bool iButtonApp::load_key(const char* key_name) { - bool result = false; - string_t key_path; - - string_init_set_str(key_path, key_name); - - result = load_key_data(key_path); - if(result) { - path_extract_filename_no_ext(key_name, key_path); - ibutton_key_set_name(key, string_get_cstr(key_path)); - } - string_clear(key_path); - return result; -} - -bool iButtonApp::load_key() { - bool result = false; - - // Input events and views are managed by file_select - bool res = dialog_file_select_show( - dialogs, - app_folder, - app_extension, - get_file_name(), - get_file_name_size(), - ibutton_key_get_name_p(key)); - - if(res) { - string_t key_str; - - // Get key file path - string_init_printf(key_str, "%s/%s%s", app_folder, get_file_name(), app_extension); - - result = load_key_data(key_str); - if(result) { - ibutton_key_set_name(key, get_file_name()); - } - string_clear(key_str); - } - - return result; -} - -bool iButtonApp::delete_key() { - string_t file_name; - bool result = false; - - string_init_printf( - file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); - result = storage_simply_remove(storage, string_get_cstr(file_name)); - string_clear(file_name); - - return result; -} - -void iButtonApp::make_app_folder() { - if(!storage_simply_mkdir(storage, app_folder)) { - dialog_message_show_storage_error(dialogs, "Cannot create\napp folder"); - } -} diff --git a/applications/ibutton/ibutton_app.h b/applications/ibutton/ibutton_app.h deleted file mode 100644 index d3d8cac6..00000000 --- a/applications/ibutton/ibutton_app.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include -#include - -#include "ibutton_view_manager.h" -#include "scene/ibutton_scene_generic.h" -#include "scene/ibutton_scene_start.h" -#include "scene/ibutton_scene_read.h" -#include "scene/ibutton_scene_read_crc_error.h" -#include "scene/ibutton_scene_read_not_key_error.h" -#include "scene/ibutton_scene_read_success.h" -#include "scene/ibutton_scene_retry_confirm.h" -#include "scene/ibutton_scene_exit_confirm.h" -#include "scene/ibutton_scene_read_key_menu.h" -#include "scene/ibutton_scene_write.h" -#include "scene/ibutton_scene_write_success.h" -#include "scene/ibutton_scene_saved_key_menu.h" -#include "scene/ibutton_scene_delete_confirm.h" -#include "scene/ibutton_scene_delete_success.h" -#include "scene/ibutton_scene_emulate.h" -#include "scene/ibutton_scene_save_name.h" -#include "scene/ibutton_scene_save_success.h" -#include "scene/ibutton_scene_info.h" -#include "scene/ibutton_scene_select_key.h" -#include "scene/ibutton_scene_add_type.h" -#include "scene/ibutton_scene_add_value.h" -#include -#include -#include -#include -#include - -class iButtonApp { -public: - void run(void* args); - - iButtonApp(); - ~iButtonApp(); - - enum class Scene : uint8_t { - SceneExit, - SceneStart, - SceneRead, - SceneReadNotKeyError, - SceneReadCRCError, - SceneReadSuccess, - SceneRetryConfirm, - SceneExitConfirm, - SceneReadKeyMenu, - SceneWrite, - SceneWriteSuccess, - SceneEmulate, - SceneSavedKeyMenu, - SceneDeleteConfirm, - SceneDeleteSuccess, - SceneSaveName, - SceneSaveSuccess, - SceneInfo, - SceneSelectKey, - SceneAddType, - SceneAddValue, - }; - - static const char* app_folder; - static const char* app_extension; - static const char* app_filetype; - - iButtonAppViewManager* get_view_manager(); - void switch_to_next_scene(Scene index); - void search_and_switch_to_previous_scene(std::initializer_list scenes_list); - bool switch_to_previous_scene(uint8_t count = 1); - Scene get_previous_scene(); - - const GpioPin* get_ibutton_pin(); - iButtonWorker* get_key_worker(); - iButtonKey* get_key(); - - void notify_read(); - void notify_yellow_blink(); - void notify_emulate(); - - void notify_error(); - void notify_success(); - void notify_green_on(); - void notify_green_off(); - void notify_red_on(); - void notify_red_off(); - - void set_text_store(const char* text...); - char* get_text_store(); - uint8_t get_text_store_size(); - - char* get_file_name(); - uint8_t get_file_name_size(); - - bool save_key(const char* key_name); - bool load_key(); - bool load_key(const char* key_name); - bool delete_key(); - -private: - std::list previous_scenes_list = {Scene::SceneExit}; - Scene current_scene = Scene::SceneStart; - iButtonAppViewManager view; - - std::map scenes = { - {Scene::SceneStart, new iButtonSceneStart()}, - {Scene::SceneRead, new iButtonSceneRead()}, - {Scene::SceneReadCRCError, new iButtonSceneReadCRCError()}, - {Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()}, - {Scene::SceneReadSuccess, new iButtonSceneReadSuccess()}, - {Scene::SceneRetryConfirm, new iButtonSceneRetryConfirm()}, - {Scene::SceneExitConfirm, new iButtonSceneExitConfirm()}, - {Scene::SceneReadKeyMenu, new iButtonSceneReadKeyMenu()}, - {Scene::SceneWrite, new iButtonSceneWrite()}, - {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, - {Scene::SceneEmulate, new iButtonSceneEmulate()}, - {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, - {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, - {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, - {Scene::SceneSaveName, new iButtonSceneSaveName()}, - {Scene::SceneSaveSuccess, new iButtonSceneSaveSuccess()}, - {Scene::SceneInfo, new iButtonSceneInfo()}, - {Scene::SceneSelectKey, new iButtonSceneSelectKey()}, - {Scene::SceneAddType, new iButtonSceneAddType()}, - {Scene::SceneAddValue, new iButtonSceneAddValue()}, - }; - - iButtonWorker* key_worker; - iButtonKey* key; - - RecordController notification; - RecordController storage; - RecordController dialogs; - - static const uint8_t file_name_size = 100; - char file_name[file_name_size]; - - static const uint8_t text_store_size = 128; - char text_store[text_store_size + 1]; - - bool load_key_data(string_t key_path); - void make_app_folder(); -}; \ No newline at end of file diff --git a/applications/ibutton/ibutton_cli.c b/applications/ibutton/ibutton_cli.c index c50ec210..4592cdad 100644 --- a/applications/ibutton/ibutton_cli.c +++ b/applications/ibutton/ibutton_cli.c @@ -240,6 +240,7 @@ void ibutton_cli_emulate(Cli* cli, string_t args) { }; static void ibutton_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); @@ -268,6 +269,7 @@ void onewire_cli_print_usage() { }; static void onewire_cli_search(Cli* cli) { + UNUSED(cli); OneWireHost* onewire = onewire_host_alloc(); uint8_t address[8]; bool done = false; @@ -297,6 +299,7 @@ static void onewire_cli_search(Cli* cli) { } void onewire_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); @@ -311,4 +314,4 @@ void onewire_cli(Cli* cli, string_t args, void* context) { } string_clear(cmd); -} \ No newline at end of file +} diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/ibutton/ibutton_custom_event.h new file mode 100644 index 00000000..2be42d66 --- /dev/null +++ b/applications/ibutton/ibutton_custom_event.h @@ -0,0 +1,12 @@ +#pragma once + +enum iButtonCustomEvent { + // Reserve first 100 events for button types and indexes, starting from 0 + iButtonCustomEventReserved = 100, + + iButtonCustomEventBack, + iButtonCustomEventTextEditResult, + iButtonCustomEventByteEditResult, + iButtonCustomEventWorkerEmulated, + iButtonCustomEventWorkerRead, +}; diff --git a/applications/ibutton/ibutton_event.h b/applications/ibutton/ibutton_event.h deleted file mode 100644 index b4dac2f4..00000000 --- a/applications/ibutton/ibutton_event.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class iButtonApp; - -class iButtonEvent { -public: - // events enum - enum class Type : uint8_t { - EventTypeTick, - EventTypeBack, - EventTypeMenuSelected, - EventTypeDialogResult, - EventTypeTextEditResult, - EventTypeByteEditResult, - EventTypeWidgetButtonResult, - EventTypeWorkerEmulated, - EventTypeWorkerRead, - EventTypeWorkerWrite, - }; - - // payload - union { - uint32_t menu_index; - DialogExResult dialog_result; - GuiButtonType widget_button_result; - iButtonWorkerWriteResult worker_write_result; - } payload; - - // event type - Type type; -}; diff --git a/applications/ibutton/ibutton_i.h b/applications/ibutton/ibutton_i.h new file mode 100644 index 00000000..36857fd6 --- /dev/null +++ b/applications/ibutton/ibutton_i.h @@ -0,0 +1,86 @@ +#pragma once + +#include "ibutton.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ibutton_custom_event.h" +#include "scenes/ibutton_scene.h" + +#define IBUTTON_FILE_NAME_SIZE 100 +#define IBUTTON_TEXT_STORE_SIZE 128 + +#define IBUTTON_APP_FOLDER "/any/ibutton" +#define IBUTTON_APP_EXTENSION ".ibtn" +#define IBUTTON_APP_FILE_TYPE "Flipper iButton key" + +struct iButton { + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + + Gui* gui; + Storage* storage; + DialogsApp* dialogs; + NotificationApp* notifications; + + iButtonWorker* key_worker; + iButtonKey* key; + + char file_name[IBUTTON_FILE_NAME_SIZE]; + char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; + + Submenu* submenu; + ByteInput* byte_input; + TextInput* text_input; + Popup* popup; + Widget* widget; + DialogEx* dialog_ex; +}; + +typedef enum { + iButtonViewSubmenu, + iButtonViewByteInput, + iButtonViewTextInput, + iButtonViewPopup, + iButtonViewWidget, + iButtonViewDialogEx, +} iButtonView; + +typedef enum { + iButtonNotificationMessageError, + iButtonNotificationMessageSuccess, + iButtonNotificationMessageRead, + iButtonNotificationMessageEmulate, + iButtonNotificationMessageYellowBlink, + iButtonNotificationMessageRedOn, + iButtonNotificationMessageRedOff, + iButtonNotificationMessageGreenOn, + iButtonNotificationMessageGreenOff, +} iButtonNotificationMessage; + +bool ibutton_file_select(iButton* ibutton); +bool ibutton_load_key(iButton* ibutton, const char* key_name); +bool ibutton_save_key(iButton* ibutton, const char* key_name); +bool ibutton_delete_key(iButton* ibutton); +void ibutton_text_store_set(iButton* ibutton, const char* text, ...); +void ibutton_text_store_clear(iButton* ibutton); +void ibutton_switch_to_previous_scene_one_of( + iButton* ibutton, + const uint32_t* scene_ids, + size_t scene_ids_size); +void ibutton_notification_message(iButton* ibutton, uint32_t message); diff --git a/applications/ibutton/ibutton_view_manager.cpp b/applications/ibutton/ibutton_view_manager.cpp deleted file mode 100755 index efaa6f81..00000000 --- a/applications/ibutton/ibutton_view_manager.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "ibutton_view_manager.h" -#include "ibutton_event.h" -#include - -iButtonAppViewManager::iButtonAppViewManager() { - event_queue = osMessageQueueNew(10, sizeof(iButtonEvent), NULL); - - view_dispatcher = view_dispatcher_alloc(); - auto callback = cbc::obtain_connector(this, &iButtonAppViewManager::previous_view_callback); - - dialog_ex = dialog_ex_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewDialogEx), - dialog_ex_get_view(dialog_ex)); - - submenu = submenu_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewSubmenu), - submenu_get_view(submenu)); - - text_input = text_input_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewTextInput), - text_input_get_view(text_input)); - - byte_input = byte_input_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewByteInput), - byte_input_get_view(byte_input)); - - popup = popup_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewPopup), - popup_get_view(popup)); - - widget = widget_alloc(); - view_dispatcher_add_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewWidget), - widget_get_view(widget)); - - gui = static_cast(furi_record_open("gui")); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - //TODO think about that method, seems unsafe and over-engineered - view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback); - view_set_previous_callback(submenu_get_view(submenu), callback); - view_set_previous_callback(text_input_get_view(text_input), callback); - view_set_previous_callback(byte_input_get_view(byte_input), callback); - view_set_previous_callback(popup_get_view(popup), callback); - view_set_previous_callback(widget_get_view(widget), callback); -} - -iButtonAppViewManager::~iButtonAppViewManager() { - // remove views - view_dispatcher_remove_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewDialogEx)); - view_dispatcher_remove_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewSubmenu)); - view_dispatcher_remove_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewTextInput)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(iButtonAppViewManager::Type::iButtonAppViewPopup)); - view_dispatcher_remove_view( - view_dispatcher, - static_cast(iButtonAppViewManager::Type::iButtonAppViewByteInput)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(iButtonAppViewManager::Type::iButtonAppViewWidget)); - - // free view modules - popup_free(popup); - text_input_free(text_input); - byte_input_free(byte_input); - submenu_free(submenu); - dialog_ex_free(dialog_ex); - widget_free(widget); - - // free dispatcher - view_dispatcher_free(view_dispatcher); - - // free event queue - osMessageQueueDelete(event_queue); -} - -void iButtonAppViewManager::switch_to(Type type) { - view_dispatcher_switch_to_view(view_dispatcher, static_cast(type)); -} - -Submenu* iButtonAppViewManager::get_submenu() { - return submenu; -} - -Popup* iButtonAppViewManager::get_popup() { - return popup; -} - -DialogEx* iButtonAppViewManager::get_dialog_ex() { - return dialog_ex; -} - -TextInput* iButtonAppViewManager::get_text_input() { - return text_input; -} - -ByteInput* iButtonAppViewManager::get_byte_input() { - return byte_input; -} - -Widget* iButtonAppViewManager::get_widget() { - return widget; -} - -void iButtonAppViewManager::receive_event(iButtonEvent* event) { - if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { - event->type = iButtonEvent::Type::EventTypeTick; - } -} - -void iButtonAppViewManager::send_event(iButtonEvent* event) { - osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0); - furi_check(result == osOK); -} - -uint32_t iButtonAppViewManager::previous_view_callback(void* context) { - if(event_queue != NULL) { - iButtonEvent event; - event.type = iButtonEvent::Type::EventTypeBack; - send_event(&event); - } - - return VIEW_IGNORE; -} \ No newline at end of file diff --git a/applications/ibutton/ibutton_view_manager.h b/applications/ibutton/ibutton_view_manager.h deleted file mode 100644 index 89d084ba..00000000 --- a/applications/ibutton/ibutton_view_manager.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include "ibutton_event.h" - -class iButtonAppViewManager { -public: - enum class Type : uint8_t { - iButtonAppViewTextInput, - iButtonAppViewByteInput, - iButtonAppViewSubmenu, - iButtonAppViewDialogEx, - iButtonAppViewPopup, - iButtonAppViewWidget, - }; - - osMessageQueueId_t event_queue; - - iButtonAppViewManager(); - ~iButtonAppViewManager(); - - void switch_to(Type type); - - Submenu* get_submenu(); - Popup* get_popup(); - DialogEx* get_dialog_ex(); - TextInput* get_text_input(); - ByteInput* get_byte_input(); - Widget* get_widget(); - - void receive_event(iButtonEvent* event); - void send_event(iButtonEvent* event); - -private: - ViewDispatcher* view_dispatcher; - DialogEx* dialog_ex; - Submenu* submenu; - TextInput* text_input; - ByteInput* byte_input; - Popup* popup; - Widget* widget; - Gui* gui; - - uint32_t previous_view_callback(void* context); -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_add_type.cpp b/applications/ibutton/scene/ibutton_scene_add_type.cpp deleted file mode 100644 index c9537768..00000000 --- a/applications/ibutton/scene/ibutton_scene_add_type.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "ibutton_scene_add_type.h" -#include "../ibutton_app.h" -#include - -typedef enum { - SubmenuIndexCyfral, - SubmenuIndexDallas, - SubmenuIndexMetakom, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeMenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneAddType::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "Cyfral", SubmenuIndexCyfral, submenu_callback, app); - submenu_add_item(submenu, "Dallas", SubmenuIndexDallas, submenu_callback, app); - submenu_add_item(submenu, "Metakom", SubmenuIndexMetakom, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); -} - -bool iButtonSceneAddType::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { - submenu_item_selected = event->payload.menu_index; - iButtonKey* key = app->get_key(); - - switch(event->payload.menu_index) { - case SubmenuIndexCyfral: - ibutton_key_set_type(key, iButtonKeyCyfral); - break; - case SubmenuIndexDallas: - ibutton_key_set_type(key, iButtonKeyDS1990); - break; - case SubmenuIndexMetakom: - ibutton_key_set_type(key, iButtonKeyMetakom); - break; - } - ibutton_key_set_name(key, ""); - ibutton_key_clear_data(key); - app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue); - consumed = true; - } - - return consumed; -} - -void iButtonSceneAddType::on_exit(iButtonApp* app) { - iButtonAppViewManager* view = app->get_view_manager(); - Submenu* submenu = view->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/ibutton/scene/ibutton_scene_add_type.h b/applications/ibutton/scene/ibutton_scene_add_type.h deleted file mode 100644 index d49ac128..00000000 --- a/applications/ibutton/scene/ibutton_scene_add_type.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneAddType : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - uint32_t submenu_item_selected = 0; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_add_value.cpp b/applications/ibutton/scene/ibutton_scene_add_value.cpp deleted file mode 100755 index cb1e287c..00000000 --- a/applications/ibutton/scene/ibutton_scene_add_value.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "ibutton_scene_add_value.h" -#include "../ibutton_app.h" -#include - -static void byte_input_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeByteEditResult; - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneAddValue::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - ByteInput* byte_input = view_manager->get_byte_input(); - iButtonKey* key = app->get_key(); - - memcpy(this->new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)); - - byte_input_set_result_callback( - byte_input, - byte_input_callback, - NULL, - app, - this->new_key_data, - ibutton_key_get_data_size(key)); - - byte_input_set_header_text(byte_input, "Enter the key"); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput); -} - -bool iButtonSceneAddValue::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeByteEditResult) { - ibutton_key_set_data(app->get_key(), this->new_key_data, IBUTTON_KEY_DATA_SIZE); - DOLPHIN_DEED(DolphinDeedIbuttonAdd); - app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); - consumed = true; - } - - return consumed; -} - -void iButtonSceneAddValue::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - ByteInput* byte_input = view_manager->get_byte_input(); - - byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(byte_input, {0}); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_add_value.h b/applications/ibutton/scene/ibutton_scene_add_value.h deleted file mode 100644 index ff6de577..00000000 --- a/applications/ibutton/scene/ibutton_scene_add_value.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" -#include - -class iButtonSceneAddValue : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {}; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp b/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp deleted file mode 100755 index 8e782e33..00000000 --- a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "ibutton_scene_delete_confirm.h" -#include "../ibutton_app.h" - -static void widget_callback(GuiButtonType result, InputType type, void* context) { - furi_assert(context); - iButtonApp* app = static_cast(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 iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Widget* widget = view_manager->get_widget(); - iButtonKey* key = app->get_key(); - const uint8_t* key_data = ibutton_key_get_data_p(key); - - app->set_text_store("\e#Delete %s?\e#", ibutton_key_get_name_p(key)); - widget_add_text_box_element( - widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store(), false); - widget_add_button_element(widget, GuiButtonTypeLeft, "Cancel", widget_callback, app); - widget_add_button_element(widget, GuiButtonTypeRight, "Delete", widget_callback, app); - - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - app->set_text_store( - "%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - widget_add_string_element( - widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); - break; - case iButtonKeyCyfral: - app->set_text_store("%02X %02X", key_data[0], key_data[1]); - widget_add_string_element( - widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); - break; - case iButtonKeyMetakom: - app->set_text_store( - "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - widget_add_string_element( - widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom"); - break; - } - widget_add_string_element( - widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, app->get_text_store()); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget); -} - -bool iButtonSceneDeleteConfirm::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) { - if(event->payload.widget_button_result == GuiButtonTypeRight) { - if(app->delete_key()) { - app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess); - } - } else { - app->switch_to_previous_scene(); - } - - consumed = true; - } - - return consumed; -} - -void iButtonSceneDeleteConfirm::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Widget* widget = view_manager->get_widget(); - - app->set_text_store(""); - - widget_reset(widget); -} diff --git a/applications/ibutton/scene/ibutton_scene_delete_confirm.h b/applications/ibutton/scene/ibutton_scene_delete_confirm.h deleted file mode 100644 index d82c376d..00000000 --- a/applications/ibutton/scene/ibutton_scene_delete_confirm.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneDeleteConfirm : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_delete_success.cpp b/applications/ibutton/scene/ibutton_scene_delete_success.cpp deleted file mode 100644 index 8c645a5f..00000000 --- a/applications/ibutton/scene/ibutton_scene_delete_success.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "ibutton_scene_delete_success.h" -#include "../ibutton_app.h" - -static void popup_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - event.type = iButtonEvent::Type::EventTypeBack; - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); - popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); - - popup_set_callback(popup, popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); -} - -bool iButtonSceneDeleteSuccess::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeBack) { - app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneSelectKey}); - consumed = true; - } - - return consumed; -} - -void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); - - popup_disable_timeout(popup); - popup_set_context(popup, NULL); - popup_set_callback(popup, NULL); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_delete_success.h b/applications/ibutton/scene/ibutton_scene_delete_success.h deleted file mode 100644 index 0c17c7ed..00000000 --- a/applications/ibutton/scene/ibutton_scene_delete_success.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneDeleteSuccess : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_emulate.h b/applications/ibutton/scene/ibutton_scene_emulate.h deleted file mode 100644 index c2bedcc5..00000000 --- a/applications/ibutton/scene/ibutton_scene_emulate.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneEmulate : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_exit_confirm.cpp b/applications/ibutton/scene/ibutton_scene_exit_confirm.cpp deleted file mode 100644 index 2c9fe94c..00000000 --- a/applications/ibutton/scene/ibutton_scene_exit_confirm.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#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(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); -} diff --git a/applications/ibutton/scene/ibutton_scene_exit_confirm.h b/applications/ibutton/scene/ibutton_scene_exit_confirm.h deleted file mode 100644 index dc5981e1..00000000 --- a/applications/ibutton/scene/ibutton_scene_exit_confirm.h +++ /dev/null @@ -1,9 +0,0 @@ -#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; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_generic.h b/applications/ibutton/scene/ibutton_scene_generic.h deleted file mode 100644 index 0e2444b5..00000000 --- a/applications/ibutton/scene/ibutton_scene_generic.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../ibutton_event.h" - -class iButtonApp; - -class iButtonScene { -public: - virtual void on_enter(iButtonApp* app) = 0; - virtual bool on_event(iButtonApp* app, iButtonEvent* event) = 0; - virtual void on_exit(iButtonApp* app) = 0; - virtual ~iButtonScene(){}; - -private: -}; diff --git a/applications/ibutton/scene/ibutton_scene_info.cpp b/applications/ibutton/scene/ibutton_scene_info.cpp deleted file mode 100755 index e51b2095..00000000 --- a/applications/ibutton/scene/ibutton_scene_info.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "ibutton_scene_info.h" -#include "../ibutton_app.h" - -void iButtonSceneInfo::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Widget* widget = view_manager->get_widget(); - iButtonKey* key = app->get_key(); - const uint8_t* key_data = ibutton_key_get_data_p(key); - - app->set_text_store("%s", ibutton_key_get_name_p(key)); - widget_add_text_box_element( - widget, 0, 0, 128, 28, AlignCenter, AlignCenter, app->get_text_store(), false); - - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - app->set_text_store( - "%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - widget_add_string_element( - widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas"); - break; - case iButtonKeyMetakom: - app->set_text_store( - "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - widget_add_string_element( - widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom"); - break; - case iButtonKeyCyfral: - app->set_text_store("%02X %02X", key_data[0], key_data[1]); - widget_add_string_element( - widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); - break; - } - widget_add_string_element( - widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, app->get_text_store()); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget); -} - -bool iButtonSceneInfo::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - return consumed; -} - -void iButtonSceneInfo::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Widget* widget = view_manager->get_widget(); - - app->set_text_store(""); - - widget_reset(widget); -} diff --git a/applications/ibutton/scene/ibutton_scene_info.h b/applications/ibutton/scene/ibutton_scene_info.h deleted file mode 100644 index e2c6b2cf..00000000 --- a/applications/ibutton/scene/ibutton_scene_info.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneInfo : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read.cpp b/applications/ibutton/scene/ibutton_scene_read.cpp deleted file mode 100644 index 7162652d..00000000 --- a/applications/ibutton/scene/ibutton_scene_read.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "ibutton_scene_read.h" -#include "../ibutton_app.h" -#include - -static void read_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event = {.type = iButtonEvent::Type::EventTypeWorkerRead}; - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneRead::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - iButtonKey* key = app->get_key(); - iButtonWorker* worker = app->get_key_worker(); - DOLPHIN_DEED(DolphinDeedIbuttonRead); - - popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); - popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); - ibutton_key_set_name(key, ""); - - ibutton_worker_read_set_callback(worker, read_callback, app); - ibutton_worker_read_start(worker, key); -} - -bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeWorkerRead) { - consumed = true; - - iButtonKey* key = app->get_key(); - bool success = false; - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - if(!ibutton_key_dallas_crc_is_valid(key)) { - app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError); - } else if(!ibutton_key_dallas_is_1990_key(key)) { - app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError); - } else { - success = true; - } - } else { - success = true; - } - if(success) { - app->notify_success(); - app->notify_green_on(); - DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); - app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess); - } - } else if(event->type == iButtonEvent::Type::EventTypeTick) { - consumed = true; - app->notify_read(); - } - - return consumed; -} - -void iButtonSceneRead::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - ibutton_worker_stop(app->get_key_worker()); - popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); -} diff --git a/applications/ibutton/scene/ibutton_scene_read.h b/applications/ibutton/scene/ibutton_scene_read.h deleted file mode 100644 index b9fefb0c..00000000 --- a/applications/ibutton/scene/ibutton_scene_read.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneRead : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_crc_error.cpp b/applications/ibutton/scene/ibutton_scene_read_crc_error.cpp deleted file mode 100644 index 213266cb..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_crc_error.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "ibutton_scene_read_crc_error.h" -#include "../ibutton_app.h" -#include - -static void dialog_ex_callback(DialogExResult result, void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeDialogResult; - event.payload.dialog_result = result; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneReadCRCError::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); - - app->set_text_store( - "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7], - maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); - - dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); - dialog_ex_set_context(dialog_ex, app); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); - app->notify_error(); - app->notify_red_on(); -} - -bool iButtonSceneReadCRCError::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeDialogResult) { - if(event->payload.dialog_result == DialogExResultRight) { - app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu); - } else { - app->switch_to_previous_scene(); - } - - consumed = true; - } - - return consumed; -} - -void iButtonSceneReadCRCError::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - app->set_text_store(""); - - dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, NULL); - dialog_ex_set_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); - - app->notify_red_off(); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_crc_error.h b/applications/ibutton/scene/ibutton_scene_read_crc_error.h deleted file mode 100644 index 43a4dfac..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_crc_error.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneReadCRCError : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_key_menu.cpp b/applications/ibutton/scene/ibutton_scene_read_key_menu.cpp deleted file mode 100644 index 215eb76f..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_key_menu.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "ibutton_scene_read_key_menu.h" -#include "../ibutton_app.h" - -typedef enum { - SubmenuIndexSave, - SubmenuIndexEmulate, - SubmenuIndexWrite, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeMenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneReadKeyMenu::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "Save", SubmenuIndexSave, submenu_callback, app); - submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app); - if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) { - submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app); - } - submenu_set_selected_item(submenu, submenu_item_selected); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); -} - -bool iButtonSceneReadKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexWrite: - app->switch_to_next_scene(iButtonApp::Scene::SceneWrite); - break; - case SubmenuIndexEmulate: - app->switch_to_next_scene(iButtonApp::Scene::SceneEmulate); - break; - case SubmenuIndexSave: - app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); - break; - } - consumed = true; - } else if(event->type == iButtonEvent::Type::EventTypeBack) { - app->switch_to_previous_scene(); - consumed = true; - } - - return consumed; -} - -void iButtonSceneReadKeyMenu::on_exit(iButtonApp* app) { - iButtonAppViewManager* view = app->get_view_manager(); - Submenu* submenu = view->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/ibutton/scene/ibutton_scene_read_key_menu.h b/applications/ibutton/scene/ibutton_scene_read_key_menu.h deleted file mode 100644 index e85ad815..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_key_menu.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneReadKeyMenu : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - uint32_t submenu_item_selected = 0; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_not_key_error.cpp b/applications/ibutton/scene/ibutton_scene_read_not_key_error.cpp deleted file mode 100644 index 7d0a235f..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_not_key_error.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "ibutton_scene_read_not_key_error.h" -#include "../ibutton_app.h" -#include - -static void dialog_ex_callback(DialogExResult result, void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeDialogResult; - event.payload.dialog_result = result; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); - - app->set_text_store( - "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7], - maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); - - dialog_ex_set_header(dialog_ex, "ERROR:", 64, 10, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); - dialog_ex_set_context(dialog_ex, app); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); - app->notify_error(); - app->notify_red_on(); -} - -bool iButtonSceneReadNotKeyError::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeDialogResult) { - if(event->payload.dialog_result == DialogExResultRight) { - app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu); - } else { - app->switch_to_previous_scene(); - } - - consumed = true; - } - - return consumed; -} - -void iButtonSceneReadNotKeyError::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - app->set_text_store(""); - - dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, NULL); - dialog_ex_set_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); - - app->notify_red_off(); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_not_key_error.h b/applications/ibutton/scene/ibutton_scene_read_not_key_error.h deleted file mode 100644 index 6643a206..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_not_key_error.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneReadNotKeyError : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_read_success.cpp b/applications/ibutton/scene/ibutton_scene_read_success.cpp deleted file mode 100644 index c4523904..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_success.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "ibutton_scene_read_success.h" -#include "../ibutton_app.h" -#include - -static void dialog_ex_callback(DialogExResult result, void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeDialogResult; - event.payload.dialog_result = result; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneReadSuccess::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - iButtonKey* key = app->get_key(); - const uint8_t* key_data = ibutton_key_get_data_p(key); - - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - app->set_text_store( - "Dallas\n%02X %02X %02X %02X\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - break; - case iButtonKeyCyfral: - app->set_text_store("Cyfral\n%02X %02X", key_data[0], key_data[1]); - break; - case iButtonKeyMetakom: - app->set_text_store( - "Metakom\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - break; - } - - dialog_ex_set_text(dialog_ex, app->get_text_store(), 95, 30, AlignCenter, AlignCenter); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); - dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); - dialog_ex_set_context(dialog_ex, app); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); -} - -bool iButtonSceneReadSuccess::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeDialogResult) { - if(event->payload.dialog_result == DialogExResultRight) { - app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu); - } else { - 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; - } - - return consumed; -} - -void iButtonSceneReadSuccess::on_exit(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - app->set_text_store(""); - - dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, NULL); - dialog_ex_set_right_button_text(dialog_ex, NULL); - dialog_ex_set_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); - dialog_ex_set_icon(dialog_ex, 0, 0, NULL); - - app->notify_green_off(); -} diff --git a/applications/ibutton/scene/ibutton_scene_read_success.h b/applications/ibutton/scene/ibutton_scene_read_success.h deleted file mode 100644 index 9548d6b4..00000000 --- a/applications/ibutton/scene/ibutton_scene_read_success.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneReadSuccess : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_retry_confirm.cpp b/applications/ibutton/scene/ibutton_scene_retry_confirm.cpp deleted file mode 100644 index aa3483b3..00000000 --- a/applications/ibutton/scene/ibutton_scene_retry_confirm.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#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(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); -} diff --git a/applications/ibutton/scene/ibutton_scene_retry_confirm.h b/applications/ibutton/scene/ibutton_scene_retry_confirm.h deleted file mode 100644 index 2f96e13f..00000000 --- a/applications/ibutton/scene/ibutton_scene_retry_confirm.h +++ /dev/null @@ -1,9 +0,0 @@ -#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; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_save_name.cpp b/applications/ibutton/scene/ibutton_scene_save_name.cpp deleted file mode 100644 index 71eee148..00000000 --- a/applications/ibutton/scene/ibutton_scene_save_name.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "ibutton_scene_save_name.h" -#include "../ibutton_app.h" -#include - -static void text_input_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeTextEditResult; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneSaveName::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - TextInput* text_input = view_manager->get_text_input(); - - const char* key_name = ibutton_key_get_name_p(app->get_key()); - bool key_name_empty = !strcmp(key_name, ""); - - if(key_name_empty) { - set_random_name(app->get_text_store(), app->get_text_store_size()); - } else { - app->set_text_store("%s", key_name); - } - - text_input_set_header_text(text_input, "Name the key"); - text_input_set_result_callback( - text_input, - text_input_callback, - app, - app->get_text_store(), - IBUTTON_KEY_NAME_SIZE, - key_name_empty); - - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput); -} - -bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeTextEditResult) { - if(app->save_key(app->get_text_store())) { - app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess); - } else { - app->search_and_switch_to_previous_scene( - {iButtonApp::Scene::SceneReadKeyMenu, - iButtonApp::Scene::SceneSavedKeyMenu, - iButtonApp::Scene::SceneAddType}); - } - consumed = true; - } - - return consumed; -} - -void iButtonSceneSaveName::on_exit(iButtonApp* app) { - TextInput* text_input = app->get_view_manager()->get_text_input(); - - void* validator_context = text_input_get_validator_callback_context(text_input); - text_input_set_validator(text_input, NULL, NULL); - validator_is_file_free((ValidatorIsFile*)validator_context); - - text_input_reset(text_input); -} diff --git a/applications/ibutton/scene/ibutton_scene_save_name.h b/applications/ibutton/scene/ibutton_scene_save_name.h deleted file mode 100644 index 8be593da..00000000 --- a/applications/ibutton/scene/ibutton_scene_save_name.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneSaveName : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_save_success.cpp b/applications/ibutton/scene/ibutton_scene_save_success.cpp deleted file mode 100644 index 13e173d2..00000000 --- a/applications/ibutton/scene/ibutton_scene_save_success.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "ibutton_scene_save_success.h" -#include "../ibutton_app.h" -#include - -static void popup_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - event.type = iButtonEvent::Type::EventTypeBack; - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - DOLPHIN_DEED(DolphinDeedIbuttonSave); - - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); - - popup_set_callback(popup, popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); -} - -bool iButtonSceneSaveSuccess::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeBack) { - app->search_and_switch_to_previous_scene( - {iButtonApp::Scene::SceneReadKeyMenu, - iButtonApp::Scene::SceneSavedKeyMenu, - iButtonApp::Scene::SceneAddType}); - consumed = true; - } - - return consumed; -} - -void iButtonSceneSaveSuccess::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); - - popup_disable_timeout(popup); - popup_set_context(popup, NULL); - popup_set_callback(popup, NULL); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_save_success.h b/applications/ibutton/scene/ibutton_scene_save_success.h deleted file mode 100644 index 95742bda..00000000 --- a/applications/ibutton/scene/ibutton_scene_save_success.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneSaveSuccess : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp b/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp deleted file mode 100644 index d9d042d9..00000000 --- a/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "ibutton_scene_saved_key_menu.h" -#include "../ibutton_app.h" -#include - -typedef enum { - SubmenuIndexEmulate, - SubmenuIndexWrite, - SubmenuIndexEdit, - SubmenuIndexDelete, - SubmenuIndexInfo, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeMenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneSavedKeyMenu::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app); - if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) { - submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app); - } - submenu_add_item(submenu, "Edit", SubmenuIndexEdit, submenu_callback, app); - submenu_add_item(submenu, "Delete", SubmenuIndexDelete, submenu_callback, app); - submenu_add_item(submenu, "Info", SubmenuIndexInfo, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); -} - -bool iButtonSceneSavedKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexWrite: - app->switch_to_next_scene(iButtonApp::Scene::SceneWrite); - break; - case SubmenuIndexEmulate: - app->switch_to_next_scene(iButtonApp::Scene::SceneEmulate); - break; - case SubmenuIndexEdit: - app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue); - break; - case SubmenuIndexDelete: - app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteConfirm); - break; - case SubmenuIndexInfo: - app->switch_to_next_scene(iButtonApp::Scene::SceneInfo); - break; - } - consumed = true; - } - - return consumed; -} - -void iButtonSceneSavedKeyMenu::on_exit(iButtonApp* app) { - iButtonAppViewManager* view = app->get_view_manager(); - Submenu* submenu = view->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/ibutton/scene/ibutton_scene_saved_key_menu.h b/applications/ibutton/scene/ibutton_scene_saved_key_menu.h deleted file mode 100644 index 399ed1ce..00000000 --- a/applications/ibutton/scene/ibutton_scene_saved_key_menu.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneSavedKeyMenu : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - uint32_t submenu_item_selected = 0; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_select_key.cpp b/applications/ibutton/scene/ibutton_scene_select_key.cpp deleted file mode 100644 index 1f1ece35..00000000 --- a/applications/ibutton/scene/ibutton_scene_select_key.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "ibutton_scene_select_key.h" -#include "../ibutton_app.h" - -void iButtonSceneSelectKey::on_enter(iButtonApp* app) { - // Process file_select return - if(app->load_key()) { - app->switch_to_next_scene(iButtonApp::Scene::SceneSavedKeyMenu); - } else { - app->switch_to_previous_scene(); - } -} - -bool iButtonSceneSelectKey::on_event(iButtonApp* app, iButtonEvent* event) { - return false; -} - -void iButtonSceneSelectKey::on_exit(iButtonApp* app) { -} diff --git a/applications/ibutton/scene/ibutton_scene_select_key.h b/applications/ibutton/scene/ibutton_scene_select_key.h deleted file mode 100644 index 39e8d9a3..00000000 --- a/applications/ibutton/scene/ibutton_scene_select_key.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneSelectKey : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_start.cpp b/applications/ibutton/scene/ibutton_scene_start.cpp deleted file mode 100644 index f7465459..00000000 --- a/applications/ibutton/scene/ibutton_scene_start.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "ibutton_scene_start.h" -#include "../ibutton_app.h" - -typedef enum { - SubmenuIndexRead, - SubmenuIndexSaved, - SubmenuIndexAdd, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - - event.type = iButtonEvent::Type::EventTypeMenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneStart::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "Read", SubmenuIndexRead, submenu_callback, app); - submenu_add_item(submenu, "Saved", SubmenuIndexSaved, submenu_callback, app); - submenu_add_item(submenu, "Add Manually", SubmenuIndexAdd, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); -} - -bool iButtonSceneStart::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexRead: - app->switch_to_next_scene(iButtonApp::Scene::SceneRead); - break; - case SubmenuIndexSaved: - app->switch_to_next_scene(iButtonApp::Scene::SceneSelectKey); - break; - case SubmenuIndexAdd: - app->switch_to_next_scene(iButtonApp::Scene::SceneAddType); - break; - } - consumed = true; - } - - return consumed; -} - -void iButtonSceneStart::on_exit(iButtonApp* app) { - iButtonAppViewManager* view = app->get_view_manager(); - Submenu* submenu = view->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/ibutton/scene/ibutton_scene_start.h b/applications/ibutton/scene/ibutton_scene_start.h deleted file mode 100644 index be1ce79f..00000000 --- a/applications/ibutton/scene/ibutton_scene_start.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneStart : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - uint32_t submenu_item_selected = 0; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_write.cpp b/applications/ibutton/scene/ibutton_scene_write.cpp deleted file mode 100644 index 31da6dbe..00000000 --- a/applications/ibutton/scene/ibutton_scene_write.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "ibutton_scene_write.h" -#include "../ibutton_app.h" - -static void ibutton_worker_write_cb(void* context, iButtonWorkerWriteResult result) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - event.type = iButtonEvent::Type::EventTypeWorkerWrite; - event.payload.worker_write_result = result; - - app->get_view_manager()->send_event(&event); -} - -void iButtonSceneWrite::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - iButtonKey* key = app->get_key(); - iButtonWorker* worker = app->get_key_worker(); - const uint8_t* key_data = ibutton_key_get_data_p(key); - const char* key_name = ibutton_key_get_name_p(key); - uint8_t line_count = 2; - - // check that stored key has name - if(strcmp(key_name, "") != 0) { - app->set_text_store("writing\n%s", key_name); - line_count = 2; - } else { - // if not, show key data - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - app->set_text_store( - "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - line_count = 3; - break; - case iButtonKeyCyfral: - app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); - line_count = 2; - break; - case iButtonKeyMetakom: - app->set_text_store( - "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - line_count = 2; - break; - } - } - - switch(line_count) { - case 3: - popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom); - popup_set_text(popup, app->get_text_store(), 82, 22, AlignCenter, AlignTop); - break; - - default: - popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom); - popup_set_text(popup, app->get_text_store(), 82, 28, AlignCenter, AlignTop); - break; - } - - popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); - - blink_yellow = false; - ibutton_worker_write_set_callback(worker, ibutton_worker_write_cb, app); - ibutton_worker_write_start(worker, key); -} - -bool iButtonSceneWrite::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeWorkerWrite) { - consumed = true; - - switch(event->payload.worker_write_result) { - case iButtonWorkerWriteOK: - case iButtonWorkerWriteSameKey: - app->switch_to_next_scene(iButtonApp::Scene::SceneWriteSuccess); - break; - case iButtonWorkerWriteNoDetect: - blink_yellow = false; - break; - case iButtonWorkerWriteCannotWrite: - blink_yellow = true; - break; - } - } else if(event->type == iButtonEvent::Type::EventTypeTick) { - if(blink_yellow) { - app->notify_yellow_blink(); - } else { - app->notify_emulate(); - } - } - - return consumed; -} - -void iButtonSceneWrite::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - ibutton_worker_stop(app->get_key_worker()); - popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_write.h b/applications/ibutton/scene/ibutton_scene_write.h deleted file mode 100644 index bd99b377..00000000 --- a/applications/ibutton/scene/ibutton_scene_write.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneWrite : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; - -private: - bool blink_yellow; -}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_write_success.cpp b/applications/ibutton/scene/ibutton_scene_write_success.cpp deleted file mode 100644 index 39734704..00000000 --- a/applications/ibutton/scene/ibutton_scene_write_success.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "ibutton_scene_write_success.h" -#include "../ibutton_app.h" - -static void popup_callback(void* context) { - furi_assert(context); - iButtonApp* app = static_cast(context); - iButtonEvent event; - event.type = iButtonEvent::Type::EventTypeBack; - app->get_view_manager()->send_event(&event); - app->notify_green_off(); -} - -void iButtonSceneWriteSuccess::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - - popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52); - popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom); - - popup_set_callback(popup, popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); - - app->notify_success(); - app->notify_green_on(); -} - -bool iButtonSceneWriteSuccess::on_event(iButtonApp* app, iButtonEvent* event) { - bool consumed = false; - - if(event->type == iButtonEvent::Type::EventTypeBack) { - app->search_and_switch_to_previous_scene( - {iButtonApp::Scene::SceneReadKeyMenu, iButtonApp::Scene::SceneStart}); - consumed = true; - } - - return consumed; -} - -void iButtonSceneWriteSuccess::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); - - popup_disable_timeout(popup); - popup_set_context(popup, NULL); - popup_set_callback(popup, NULL); -} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_write_success.h b/applications/ibutton/scene/ibutton_scene_write_success.h deleted file mode 100644 index c6e76885..00000000 --- a/applications/ibutton/scene/ibutton_scene_write_success.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ibutton_scene_generic.h" - -class iButtonSceneWriteSuccess : public iButtonScene { -public: - void on_enter(iButtonApp* app) final; - bool on_event(iButtonApp* app, iButtonEvent* event) final; - void on_exit(iButtonApp* app) final; -}; \ No newline at end of file diff --git a/applications/ibutton/scenes/ibutton_scene.c b/applications/ibutton/scenes/ibutton_scene.c new file mode 100644 index 00000000..c36a0eb5 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene.c @@ -0,0 +1,30 @@ +#include "ibutton_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const ibutton_on_enter_handlers[])(void*) = { +#include "ibutton_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const ibutton_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "ibutton_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const ibutton_on_exit_handlers[])(void* context) = { +#include "ibutton_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers ibutton_scene_handlers = { + .on_enter_handlers = ibutton_on_enter_handlers, + .on_event_handlers = ibutton_on_event_handlers, + .on_exit_handlers = ibutton_on_exit_handlers, + .scene_num = iButtonSceneNum, +}; diff --git a/applications/ibutton/scenes/ibutton_scene.h b/applications/ibutton/scenes/ibutton_scene.h new file mode 100644 index 00000000..60d2353e --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) iButtonScene##id, +typedef enum { +#include "ibutton_scene_config.h" + iButtonSceneNum, +} iButtonScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers ibutton_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "ibutton_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "ibutton_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "ibutton_scene_config.h" +#undef ADD_SCENE diff --git a/applications/ibutton/scenes/ibutton_scene_add_type.c b/applications/ibutton/scenes/ibutton_scene_add_type.c new file mode 100644 index 00000000..db129295 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_add_type.c @@ -0,0 +1,58 @@ +#include "../ibutton_i.h" + +enum SubmenuIndex { + SubmenuIndexCyfral, + SubmenuIndexDallas, + SubmenuIndexMetakom, +}; + +void ibutton_scene_add_type_submenu_callback(void* context, uint32_t index) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); +} + +void ibutton_scene_add_type_on_enter(void* context) { + iButton* ibutton = context; + Submenu* submenu = ibutton->submenu; + + submenu_add_item( + submenu, "Cyfral", SubmenuIndexCyfral, ibutton_scene_add_type_submenu_callback, ibutton); + submenu_add_item( + submenu, "Dallas", SubmenuIndexDallas, ibutton_scene_add_type_submenu_callback, ibutton); + submenu_add_item( + submenu, "Metakom", SubmenuIndexMetakom, ibutton_scene_add_type_submenu_callback, ibutton); + + submenu_set_selected_item(submenu, SubmenuIndexCyfral); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); +} + +bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + iButtonKey* key = ibutton->key; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == SubmenuIndexCyfral) { + ibutton_key_set_type(key, iButtonKeyCyfral); + } else if(event.event == SubmenuIndexDallas) { + ibutton_key_set_type(key, iButtonKeyDS1990); + } else if(event.event == SubmenuIndexMetakom) { + ibutton_key_set_type(key, iButtonKeyMetakom); + } else { + furi_crash("Unknown key type"); + } + + ibutton_key_set_name(key, ""); + ibutton_key_clear_data(key); + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); + } + + return consumed; +} + +void ibutton_scene_add_type_on_exit(void* context) { + iButton* ibutton = context; + submenu_reset(ibutton->submenu); +} diff --git a/applications/ibutton/scenes/ibutton_scene_add_value.c b/applications/ibutton/scenes/ibutton_scene_add_value.c new file mode 100644 index 00000000..b3ec11a5 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_add_value.c @@ -0,0 +1,57 @@ +#include "../ibutton_i.h" + +#include + +void ibutton_scene_add_type_byte_input_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult); +} + +void ibutton_scene_add_value_on_enter(void* context) { + iButton* ibutton = context; + iButtonKey* key = ibutton->key; + uint8_t* new_key_data = malloc(IBUTTON_KEY_DATA_SIZE); + + scene_manager_set_scene_state( + ibutton->scene_manager, iButtonSceneAddValue, (uint32_t)new_key_data); + memcpy(new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)); + + byte_input_set_result_callback( + ibutton->byte_input, + ibutton_scene_add_type_byte_input_callback, + NULL, + ibutton, + new_key_data, + ibutton_key_get_data_size(key)); + + byte_input_set_header_text(ibutton->byte_input, "Enter the key"); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewByteInput); +} + +bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + uint8_t* new_key_data = + (uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue); + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventByteEditResult) { + ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE); + DOLPHIN_DEED(DolphinDeedIbuttonAdd); + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); + } + } + + return consumed; +} + +void ibutton_scene_add_value_on_exit(void* context) { + iButton* ibutton = context; + uint8_t* new_key_data = + (uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue); + + byte_input_set_result_callback(ibutton->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(ibutton->byte_input, NULL); + free(new_key_data); +} diff --git a/applications/ibutton/scenes/ibutton_scene_config.h b/applications/ibutton/scenes/ibutton_scene_config.h new file mode 100644 index 00000000..d30b43be --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_config.h @@ -0,0 +1,20 @@ +ADD_SCENE(ibutton, start, Start) +ADD_SCENE(ibutton, emulate, Emulate) +ADD_SCENE(ibutton, write, Write) +ADD_SCENE(ibutton, write_success, WriteSuccess) +ADD_SCENE(ibutton, info, Info) +ADD_SCENE(ibutton, read, Read) +ADD_SCENE(ibutton, read_key_menu, ReadKeyMenu) +ADD_SCENE(ibutton, read_success, ReadSuccess) +ADD_SCENE(ibutton, read_crc_error, ReadCRCError) +ADD_SCENE(ibutton, read_not_key_error, ReadNotKeyError) +ADD_SCENE(ibutton, select_key, SelectKey) +ADD_SCENE(ibutton, add_type, AddType) +ADD_SCENE(ibutton, add_value, AddValue) +ADD_SCENE(ibutton, saved_key_menu, SavedKeyMenu) +ADD_SCENE(ibutton, save_name, SaveName) +ADD_SCENE(ibutton, save_success, SaveSuccess) +ADD_SCENE(ibutton, delete_confirm, DeleteConfirm) +ADD_SCENE(ibutton, delete_success, DeleteSuccess) +ADD_SCENE(ibutton, retry_confirm, RetryConfirm) +ADD_SCENE(ibutton, exit_confirm, ExitConfirm) diff --git a/applications/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/ibutton/scenes/ibutton_scene_delete_confirm.c new file mode 100644 index 00000000..73ea97cc --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -0,0 +1,91 @@ +#include "../ibutton_i.h" + +static void ibutton_scene_delete_confirm_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + iButton* ibutton = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); + } +} + +void ibutton_scene_delete_confirm_on_enter(void* context) { + iButton* ibutton = context; + Widget* widget = ibutton->widget; + iButtonKey* key = ibutton->key; + const uint8_t* key_data = ibutton_key_get_data_p(key); + + ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", ibutton_key_get_name_p(key)); + widget_add_text_box_element( + widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, false); + widget_add_button_element( + widget, GuiButtonTypeLeft, "Cancel", ibutton_scene_delete_confirm_widget_callback, ibutton); + widget_add_button_element( + widget, + GuiButtonTypeRight, + "Delete", + ibutton_scene_delete_confirm_widget_callback, + ibutton); + + switch(ibutton_key_get_type(key)) { + case iButtonKeyDS1990: + ibutton_text_store_set( + ibutton, + "%02X %02X %02X %02X %02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + widget_add_string_element( + widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); + break; + + case iButtonKeyCyfral: + ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); + widget_add_string_element( + widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); + break; + + case iButtonKeyMetakom: + ibutton_text_store_set( + ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); + widget_add_string_element( + widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom"); + break; + } + widget_add_string_element( + widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); +} + +bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeRight) { + if(ibutton_delete_key(ibutton)) { + scene_manager_next_scene(scene_manager, iButtonSceneDeleteSuccess); + } + //TODO: What if the key could not be deleted? + } else if(event.event == GuiButtonTypeLeft) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void ibutton_scene_delete_confirm_on_exit(void* context) { + iButton* ibutton = context; + ibutton_text_store_clear(ibutton); + widget_reset(ibutton->widget); +} diff --git a/applications/ibutton/scenes/ibutton_scene_delete_success.c b/applications/ibutton/scenes/ibutton_scene_delete_success.c new file mode 100644 index 00000000..8b7d9dfc --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_delete_success.c @@ -0,0 +1,48 @@ +#include "../ibutton_i.h" + +static void ibutton_scene_delete_success_popup_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack); +} + +void ibutton_scene_delete_success_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); + popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); + + popup_set_callback(popup, ibutton_scene_delete_success_popup_callback); + popup_set_context(popup, ibutton); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); +} + +bool ibutton_scene_delete_success_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventBack) { + scene_manager_search_and_switch_to_previous_scene( + ibutton->scene_manager, iButtonSceneSelectKey); + } + } + + return consumed; +} + +void ibutton_scene_delete_success_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + + popup_disable_timeout(popup); + popup_set_context(popup, NULL); + popup_set_callback(popup, NULL); +} diff --git a/applications/ibutton/scene/ibutton_scene_emulate.cpp b/applications/ibutton/scenes/ibutton_scene_emulate.c similarity index 50% rename from applications/ibutton/scene/ibutton_scene_emulate.cpp rename to applications/ibutton/scenes/ibutton_scene_emulate.c index da6021fe..8ffe73b6 100644 --- a/applications/ibutton/scene/ibutton_scene_emulate.cpp +++ b/applications/ibutton/scenes/ibutton_scene_emulate.c @@ -1,34 +1,35 @@ -#include "ibutton_scene_emulate.h" -#include "../ibutton_app.h" +#include "../ibutton_i.h" #include -static void emulate_callback(void* context, bool emulated) { - furi_assert(context); +static void ibutton_scene_emulate_callback(void* context, bool emulated) { + iButton* ibutton = context; if(emulated) { - iButtonApp* app = static_cast(context); - iButtonEvent event = {.type = iButtonEvent::Type::EventTypeWorkerEmulated}; - app->get_view_manager()->send_event(&event); + view_dispatcher_send_custom_event( + ibutton->view_dispatcher, iButtonCustomEventWorkerEmulated); } } -void iButtonSceneEmulate::on_enter(iButtonApp* app) { - iButtonAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - iButtonKey* key = app->get_key(); +void ibutton_scene_emulate_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + iButtonKey* key = ibutton->key; + const uint8_t* key_data = ibutton_key_get_data_p(key); const char* key_name = ibutton_key_get_name_p(key); + uint8_t line_count = 2; DOLPHIN_DEED(DolphinDeedIbuttonEmulate); // check that stored key has name if(strcmp(key_name, "") != 0) { - app->set_text_store("emulating\n%s", key_name); + ibutton_text_store_set(ibutton, "emulating\n%s", key_name); line_count = 2; } else { // if not, show key data switch(ibutton_key_get_type(key)) { case iButtonKeyDS1990: - app->set_text_store( + ibutton_text_store_set( + ibutton, "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", key_data[0], key_data[1], @@ -41,11 +42,12 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) { line_count = 3; break; case iButtonKeyCyfral: - app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); + ibutton_text_store_set(ibutton, "emulating\n%02X %02X", key_data[0], key_data[1]); line_count = 2; break; case iButtonKeyMetakom: - app->set_text_store( + ibutton_text_store_set( + ibutton, "emulating\n%02X %02X %02X %02X", key_data[0], key_data[1], @@ -59,40 +61,45 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) { switch(line_count) { case 3: popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom); - popup_set_text(popup, app->get_text_store(), 82, 22, AlignCenter, AlignTop); + popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop); break; default: popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom); - popup_set_text(popup, app->get_text_store(), 82, 28, AlignCenter, AlignTop); + popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop); break; } popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44); - view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); - ibutton_worker_emulate_set_callback(app->get_key_worker(), emulate_callback, app); - ibutton_worker_emulate_start(app->get_key_worker(), key); + ibutton_worker_emulate_set_callback( + ibutton->key_worker, ibutton_scene_emulate_callback, ibutton); + ibutton_worker_emulate_start(ibutton->key_worker, key); } -bool iButtonSceneEmulate::on_event(iButtonApp* app, iButtonEvent* event) { +bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; bool consumed = false; - if(event->type == iButtonEvent::Type::EventTypeWorkerEmulated) { - app->notify_yellow_blink(); + if(event.type == SceneManagerEventTypeTick) { consumed = true; - } else if(event->type == iButtonEvent::Type::EventTypeTick) { - app->notify_emulate(); + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulate); + } else if(event.type == SceneManagerEventTypeCustom) { consumed = true; + if(event.event == iButtonCustomEventWorkerEmulated) { + ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); + } } return consumed; } -void iButtonSceneEmulate::on_exit(iButtonApp* app) { - Popup* popup = app->get_view_manager()->get_popup(); - ibutton_worker_stop(app->get_key_worker()); +void ibutton_scene_emulate_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + ibutton_worker_stop(ibutton->key_worker); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); popup_set_icon(popup, 0, 0, NULL); diff --git a/applications/ibutton/scenes/ibutton_scene_exit_confirm.c b/applications/ibutton/scenes/ibutton_scene_exit_confirm.c new file mode 100644 index 00000000..abd171f6 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_exit_confirm.c @@ -0,0 +1,51 @@ +#include "../ibutton_i.h" + +static void ibutton_scene_exit_confirm_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + iButton* ibutton = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); + } +} + +void ibutton_scene_exit_confirm_on_enter(void* context) { + iButton* ibutton = context; + Widget* widget = ibutton->widget; + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Exit", ibutton_scene_exit_confirm_widget_callback, ibutton); + widget_add_button_element( + widget, GuiButtonTypeRight, "Stay", ibutton_scene_exit_confirm_widget_callback, ibutton); + 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_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); +} + +bool ibutton_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; // Ignore Back button presses + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, iButtonSceneStart); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void ibutton_scene_exit_confirm_on_exit(void* context) { + iButton* ibutton = context; + widget_reset(ibutton->widget); +} diff --git a/applications/ibutton/scenes/ibutton_scene_info.c b/applications/ibutton/scenes/ibutton_scene_info.c new file mode 100644 index 00000000..5b0af1d8 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_info.c @@ -0,0 +1,61 @@ +#include "../ibutton_i.h" + +void ibutton_scene_info_on_enter(void* context) { + iButton* ibutton = context; + Widget* widget = ibutton->widget; + iButtonKey* key = ibutton->key; + + const uint8_t* key_data = ibutton_key_get_data_p(key); + + ibutton_text_store_set(ibutton, "%s", ibutton_key_get_name_p(key)); + widget_add_text_box_element( + widget, 0, 0, 128, 28, AlignCenter, AlignCenter, ibutton->text_store, false); + + switch(ibutton_key_get_type(key)) { + case iButtonKeyDS1990: + ibutton_text_store_set( + ibutton, + "%02X %02X %02X %02X %02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + widget_add_string_element( + widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas"); + break; + + case iButtonKeyMetakom: + ibutton_text_store_set( + ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); + widget_add_string_element( + widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom"); + break; + + case iButtonKeyCyfral: + ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); + widget_add_string_element( + widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); + break; + } + + widget_add_string_element( + widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, ibutton->text_store); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); +} + +bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void ibutton_scene_info_on_exit(void* context) { + iButton* ibutton = context; + ibutton_text_store_clear(ibutton); + widget_reset(ibutton->widget); +} diff --git a/applications/ibutton/scenes/ibutton_scene_read.c b/applications/ibutton/scenes/ibutton_scene_read.c new file mode 100644 index 00000000..a25f27e6 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_read.c @@ -0,0 +1,72 @@ +#include "../ibutton_i.h" +#include + +static void ibutton_scene_read_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventWorkerRead); +} + +void ibutton_scene_read_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + iButtonKey* key = ibutton->key; + iButtonWorker* worker = ibutton->key_worker; + DOLPHIN_DEED(DolphinDeedIbuttonRead); + + popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); + popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); + ibutton_key_set_name(key, ""); + + ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton); + ibutton_worker_read_start(worker, key); +} + +bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + consumed = true; + ibutton_notification_message(ibutton, iButtonNotificationMessageRead); + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventWorkerRead) { + bool success = false; + iButtonKey* key = ibutton->key; + + if(ibutton_key_get_type(key) == iButtonKeyDS1990) { + if(!ibutton_key_dallas_crc_is_valid(key)) { + scene_manager_next_scene(scene_manager, iButtonSceneReadCRCError); + } else if(!ibutton_key_dallas_is_1990_key(key)) { + scene_manager_next_scene(scene_manager, iButtonSceneReadNotKeyError); + } else { + success = true; + } + } else { + success = true; + } + + if(success) { + ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess); + ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn); + DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); + scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess); + } + } + } + + return consumed; +} + +void ibutton_scene_read_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + ibutton_worker_stop(ibutton->key_worker); + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); +} diff --git a/applications/ibutton/scenes/ibutton_scene_read_crc_error.c b/applications/ibutton/scenes/ibutton_scene_read_crc_error.c new file mode 100644 index 00000000..4df96d64 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_read_crc_error.c @@ -0,0 +1,71 @@ +#include "../ibutton_i.h" +#include + +static void ibutton_scene_read_crc_error_dialog_ex_callback(DialogExResult result, void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); +} + +void ibutton_scene_read_crc_error_on_enter(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + iButtonKey* key = ibutton->key; + const uint8_t* key_data = ibutton_key_get_data_p(key); + + ibutton_text_store_set( + ibutton, + "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7], + maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); + + dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); + dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog_ex, "Retry"); + dialog_ex_set_right_button_text(dialog_ex, "More"); + dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_crc_error_dialog_ex_callback); + dialog_ex_set_context(dialog_ex, ibutton); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); + + ibutton_notification_message(ibutton, iButtonNotificationMessageError); + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn); +} + +bool ibutton_scene_read_crc_error_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == DialogExResultRight) { + scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); + } else if(event.event == DialogExResultLeft) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void ibutton_scene_read_crc_error_on_exit(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + + ibutton_text_store_clear(ibutton); + + dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); + dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog_ex, NULL); + dialog_ex_set_result_callback(dialog_ex, NULL); + dialog_ex_set_context(dialog_ex, NULL); + + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff); +} diff --git a/applications/ibutton/scenes/ibutton_scene_read_key_menu.c b/applications/ibutton/scenes/ibutton_scene_read_key_menu.c new file mode 100644 index 00000000..7d479a46 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_read_key_menu.c @@ -0,0 +1,61 @@ +#include "../ibutton_i.h" + +typedef enum { + SubmenuIndexSave, + SubmenuIndexEmulate, + SubmenuIndexWrite, +} SubmenuIndex; + +void ibutton_scene_read_key_menu_submenu_callback(void* context, uint32_t index) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); +} + +void ibutton_scene_read_key_menu_on_enter(void* context) { + iButton* ibutton = context; + Submenu* submenu = ibutton->submenu; + + submenu_add_item( + submenu, "Save", SubmenuIndexSave, ibutton_scene_read_key_menu_submenu_callback, ibutton); + submenu_add_item( + submenu, + "Emulate", + SubmenuIndexEmulate, + ibutton_scene_read_key_menu_submenu_callback, + ibutton); + if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) { + submenu_add_item( + submenu, + "Write", + SubmenuIndexWrite, + ibutton_scene_read_key_menu_submenu_callback, + ibutton); + } + + submenu_set_selected_item(submenu, SubmenuIndexSave); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); +} + +bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == SubmenuIndexSave) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); + } else if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + } else if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); + } + } + + return consumed; +} + +void ibutton_scene_read_key_menu_on_exit(void* context) { + iButton* ibutton = context; + submenu_reset(ibutton->submenu); +} diff --git a/applications/ibutton/scenes/ibutton_scene_read_not_key_error.c b/applications/ibutton/scenes/ibutton_scene_read_not_key_error.c new file mode 100644 index 00000000..76f14dae --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_read_not_key_error.c @@ -0,0 +1,72 @@ +#include "../ibutton_i.h" +#include + +static void + ibutton_scene_read_not_key_error_dialog_ex_callback(DialogExResult result, void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); +} + +void ibutton_scene_read_not_key_error_on_enter(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + iButtonKey* key = ibutton->key; + const uint8_t* key_data = ibutton_key_get_data_p(key); + + ibutton_text_store_set( + ibutton, + "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7], + maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); + + dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); + dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog_ex, "Retry"); + dialog_ex_set_right_button_text(dialog_ex, "More"); + dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_not_key_error_dialog_ex_callback); + dialog_ex_set_context(dialog_ex, ibutton); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); + + ibutton_notification_message(ibutton, iButtonNotificationMessageError); + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn); +} + +bool ibutton_scene_read_not_key_error_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == DialogExResultRight) { + scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); + } else if(event.event == DialogExResultLeft) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void ibutton_scene_read_not_key_error_on_exit(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + + ibutton_text_store_clear(ibutton); + + dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); + dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog_ex, NULL); + dialog_ex_set_result_callback(dialog_ex, NULL); + dialog_ex_set_context(dialog_ex, NULL); + + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff); +} diff --git a/applications/ibutton/scenes/ibutton_scene_read_success.c b/applications/ibutton/scenes/ibutton_scene_read_success.c new file mode 100644 index 00000000..c3a13478 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_read_success.c @@ -0,0 +1,87 @@ +#include "../ibutton_i.h" +#include + +static void ibutton_scene_read_success_dialog_ex_callback(DialogExResult result, void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); +} + +void ibutton_scene_read_success_on_enter(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + iButtonKey* key = ibutton->key; + const uint8_t* key_data = ibutton_key_get_data_p(key); + + switch(ibutton_key_get_type(key)) { + case iButtonKeyDS1990: + ibutton_text_store_set( + ibutton, + "Dallas\n%02X %02X %02X %02X\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + break; + case iButtonKeyCyfral: + ibutton_text_store_set(ibutton, "Cyfral\n%02X %02X", key_data[0], key_data[1]); + break; + case iButtonKeyMetakom: + ibutton_text_store_set( + ibutton, + "Metakom\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3]); + break; + } + + dialog_ex_set_text(dialog_ex, ibutton->text_store, 95, 30, AlignCenter, AlignCenter); + dialog_ex_set_left_button_text(dialog_ex, "Retry"); + dialog_ex_set_right_button_text(dialog_ex, "More"); + dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); + dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_success_dialog_ex_callback); + dialog_ex_set_context(dialog_ex, ibutton); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); +} + +bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; + scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm); + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == DialogExResultRight) { + scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); + } else if(event.event == DialogExResultLeft) { + scene_manager_next_scene(scene_manager, iButtonSceneRetryConfirm); + } + } + + return consumed; +} + +void ibutton_scene_read_success_on_exit(void* context) { + iButton* ibutton = context; + DialogEx* dialog_ex = ibutton->dialog_ex; + + ibutton_text_store_clear(ibutton); + + dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog_ex, NULL); + dialog_ex_set_right_button_text(dialog_ex, NULL); + dialog_ex_set_result_callback(dialog_ex, NULL); + dialog_ex_set_context(dialog_ex, NULL); + dialog_ex_set_icon(dialog_ex, 0, 0, NULL); + + ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff); +} diff --git a/applications/ibutton/scenes/ibutton_scene_retry_confirm.c b/applications/ibutton/scenes/ibutton_scene_retry_confirm.c new file mode 100644 index 00000000..d2778ac1 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_retry_confirm.c @@ -0,0 +1,51 @@ +#include "../ibutton_i.h" + +static void ibutton_scene_retry_confirm_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + iButton* ibutton = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); + } +} + +void ibutton_scene_retry_confirm_on_enter(void* context) { + iButton* ibutton = context; + Widget* widget = ibutton->widget; + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Exit", ibutton_scene_retry_confirm_widget_callback, ibutton); + widget_add_button_element( + widget, GuiButtonTypeRight, "Stay", ibutton_scene_retry_confirm_widget_callback, ibutton); + 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_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); +} + +bool ibutton_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; // Ignore Back button presses + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, iButtonSceneRead); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void ibutton_scene_retry_confirm_on_exit(void* context) { + iButton* ibutton = context; + widget_reset(ibutton->widget); +} diff --git a/applications/ibutton/scenes/ibutton_scene_save_name.c b/applications/ibutton/scenes/ibutton_scene_save_name.c new file mode 100644 index 00000000..b1baf6af --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_save_name.c @@ -0,0 +1,68 @@ +#include "../ibutton_i.h" +#include + +static void ibutton_scene_save_name_text_input_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventTextEditResult); +} + +void ibutton_scene_save_name_on_enter(void* context) { + iButton* ibutton = context; + TextInput* text_input = ibutton->text_input; + + const char* key_name = ibutton_key_get_name_p(ibutton->key); + const bool key_name_is_empty = !strcmp(key_name, ""); + + if(key_name_is_empty) { + set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE); + } else { + ibutton_text_store_set(ibutton, "%s", key_name); + } + + text_input_set_header_text(text_input, "Name the key"); + text_input_set_result_callback( + text_input, + ibutton_scene_save_name_text_input_callback, + ibutton, + ibutton->text_store, + IBUTTON_KEY_NAME_SIZE, + key_name_is_empty); + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, key_name); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); +} + +bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventTextEditResult) { + if(ibutton_save_key(ibutton, ibutton->text_store)) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess); + } else { + const uint32_t possible_scenes[] = { + iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType}; + ibutton_switch_to_previous_scene_one_of( + ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } + } + } + + return consumed; +} + +void ibutton_scene_save_name_on_exit(void* context) { + iButton* ibutton = context; + TextInput* text_input = ibutton->text_input; + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + + text_input_reset(text_input); +} diff --git a/applications/ibutton/scenes/ibutton_scene_save_success.c b/applications/ibutton/scenes/ibutton_scene_save_success.c new file mode 100644 index 00000000..dffda6a0 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_save_success.c @@ -0,0 +1,52 @@ +#include "../ibutton_i.h" +#include + +static void ibutton_scene_save_success_popup_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack); +} + +void ibutton_scene_save_success_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + DOLPHIN_DEED(DolphinDeedIbuttonSave); + + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); + + popup_set_callback(popup, ibutton_scene_save_success_popup_callback); + popup_set_context(popup, ibutton); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); +} + +bool ibutton_scene_save_success_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventBack) { + const uint32_t possible_scenes[] = { + iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType}; + ibutton_switch_to_previous_scene_one_of( + ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } + } + + return consumed; +} + +void ibutton_scene_save_success_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + + popup_disable_timeout(popup); + popup_set_context(popup, NULL); + popup_set_callback(popup, NULL); +} diff --git a/applications/ibutton/scenes/ibutton_scene_saved_key_menu.c b/applications/ibutton/scenes/ibutton_scene_saved_key_menu.c new file mode 100644 index 00000000..36529772 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_saved_key_menu.c @@ -0,0 +1,75 @@ +#include "../ibutton_i.h" + +enum SubmenuIndex { + SubmenuIndexEmulate, + SubmenuIndexWrite, + SubmenuIndexEdit, + SubmenuIndexDelete, + SubmenuIndexInfo, +}; + +void ibutton_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); +} + +void ibutton_scene_saved_key_menu_on_enter(void* context) { + iButton* ibutton = context; + Submenu* submenu = ibutton->submenu; + + submenu_add_item( + submenu, + "Emulate", + SubmenuIndexEmulate, + ibutton_scene_saved_key_menu_submenu_callback, + ibutton); + if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) { + submenu_add_item( + submenu, + "Write", + SubmenuIndexWrite, + ibutton_scene_saved_key_menu_submenu_callback, + ibutton); + } + submenu_add_item( + submenu, "Edit", SubmenuIndexEdit, ibutton_scene_saved_key_menu_submenu_callback, ibutton); + submenu_add_item( + submenu, + "Delete", + SubmenuIndexDelete, + ibutton_scene_saved_key_menu_submenu_callback, + ibutton); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, ibutton_scene_saved_key_menu_submenu_callback, ibutton); + + submenu_set_selected_item(submenu, SubmenuIndexEmulate); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); +} + +bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + } else if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); + } else if(event.event == SubmenuIndexEdit) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); + } else if(event.event == SubmenuIndexDelete) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneDeleteConfirm); + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneInfo); + } + } + + return consumed; +} + +void ibutton_scene_saved_key_menu_on_exit(void* context) { + iButton* ibutton = context; + submenu_reset(ibutton->submenu); +} diff --git a/applications/ibutton/scenes/ibutton_scene_select_key.c b/applications/ibutton/scenes/ibutton_scene_select_key.c new file mode 100644 index 00000000..32169a9c --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_select_key.c @@ -0,0 +1,22 @@ +#include "../ibutton_i.h" + +void ibutton_scene_select_key_on_enter(void* context) { + iButton* ibutton = context; + + if(!ibutton_file_select(ibutton)) { + scene_manager_search_and_switch_to_previous_scene( + ibutton->scene_manager, iButtonSceneStart); + } else { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSavedKeyMenu); + } +} + +bool ibutton_scene_select_key_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void ibutton_scene_select_key_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/ibutton/scenes/ibutton_scene_start.c b/applications/ibutton/scenes/ibutton_scene_start.c new file mode 100644 index 00000000..a3141f5a --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_start.c @@ -0,0 +1,51 @@ +#include "../ibutton_i.h" + +enum SubmenuIndex { + SubmenuIndexRead, + SubmenuIndexSaved, + SubmenuIndexAdd, +}; + +void ibutton_scene_start_submenu_callback(void* context, uint32_t index) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); +} + +void ibutton_scene_start_on_enter(void* context) { + iButton* ibutton = context; + Submenu* submenu = ibutton->submenu; + + submenu_add_item( + submenu, "Read", SubmenuIndexRead, ibutton_scene_start_submenu_callback, ibutton); + submenu_add_item( + submenu, "Saved", SubmenuIndexSaved, ibutton_scene_start_submenu_callback, ibutton); + submenu_add_item( + submenu, "Add Manually", SubmenuIndexAdd, ibutton_scene_start_submenu_callback, ibutton); + + submenu_set_selected_item(submenu, SubmenuIndexRead); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); +} + +bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == SubmenuIndexRead) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); + } else if(event.event == SubmenuIndexSaved) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey); + } else if(event.event == SubmenuIndexAdd) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType); + } + } + + return consumed; +} + +void ibutton_scene_start_on_exit(void* context) { + iButton* ibutton = context; + submenu_reset(ibutton->submenu); +} diff --git a/applications/ibutton/scenes/ibutton_scene_write.c b/applications/ibutton/scenes/ibutton_scene_write.c new file mode 100644 index 00000000..35e45d83 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_write.c @@ -0,0 +1,121 @@ +#include "../ibutton_i.h" + +typedef enum { + iButtonSceneWriteStateDefault, + iButtonSceneWriteStateBlinkYellow, +} iButtonSceneWriteState; + +static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult result) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); +} + +void ibutton_scene_write_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + iButtonKey* key = ibutton->key; + iButtonWorker* worker = ibutton->key_worker; + + const uint8_t* key_data = ibutton_key_get_data_p(key); + const char* key_name = ibutton_key_get_name_p(key); + + uint8_t line_count = 2; + + // check that stored key has name + if(strcmp(key_name, "") != 0) { + ibutton_text_store_set(ibutton, "writing\n%s", key_name); + line_count = 2; + } else { + // if not, show key data + switch(ibutton_key_get_type(key)) { + case iButtonKeyDS1990: + ibutton_text_store_set( + ibutton, + "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + line_count = 3; + break; + case iButtonKeyCyfral: + ibutton_text_store_set(ibutton, "writing\n%02X %02X", key_data[0], key_data[1]); + line_count = 2; + break; + case iButtonKeyMetakom: + ibutton_text_store_set( + ibutton, + "writing\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3]); + line_count = 2; + break; + } + } + + switch(line_count) { + case 3: + popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom); + popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop); + break; + + default: + popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom); + popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop); + break; + } + + popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44); + + scene_manager_set_scene_state( + ibutton->scene_manager, iButtonSceneWrite, iButtonSceneWriteStateDefault); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); + + ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton); + ibutton_worker_write_start(worker, key); +} + +bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if((event.event == iButtonWorkerWriteOK) || (event.event == iButtonWorkerWriteSameKey)) { + scene_manager_next_scene(scene_manager, iButtonSceneWriteSuccess); + } else if(event.event == iButtonWorkerWriteNoDetect) { + scene_manager_set_scene_state( + scene_manager, iButtonSceneWrite, iButtonSceneWriteStateDefault); + } else if(event.event == iButtonWorkerWriteCannotWrite) { + scene_manager_set_scene_state( + scene_manager, iButtonSceneWrite, iButtonSceneWriteStateBlinkYellow); + } + + } else if(event.type == SceneManagerEventTypeTick) { + consumed = true; + if(scene_manager_get_scene_state(scene_manager, iButtonSceneWrite) == + iButtonSceneWriteStateBlinkYellow) { + ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); + } else { + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulate); + } + } + + return consumed; +} + +void ibutton_scene_write_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + ibutton_worker_stop(ibutton->key_worker); + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); +} diff --git a/applications/ibutton/scenes/ibutton_scene_write_success.c b/applications/ibutton/scenes/ibutton_scene_write_success.c new file mode 100644 index 00000000..6abafbb3 --- /dev/null +++ b/applications/ibutton/scenes/ibutton_scene_write_success.c @@ -0,0 +1,52 @@ +#include "../ibutton_i.h" + +static void ibutton_scene_write_success_popup_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack); + ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff); +} + +void ibutton_scene_write_success_on_enter(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + + popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52); + popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom); + + popup_set_callback(popup, ibutton_scene_write_success_popup_callback); + popup_set_context(popup, ibutton); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); + ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess); + ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn); +} + +bool ibutton_scene_write_success_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == iButtonCustomEventBack) { + const uint32_t possible_scenes[] = {iButtonSceneReadKeyMenu, iButtonSceneStart}; + ibutton_switch_to_previous_scene_one_of( + ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } + } + + return consumed; +} + +void ibutton_scene_write_success_on_exit(void* context) { + iButton* ibutton = context; + Popup* popup = ibutton->popup; + + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + + popup_disable_timeout(popup); + popup_set_context(popup, NULL); + popup_set_callback(popup, NULL); +} diff --git a/applications/infrared/cli/infrared_cli.cpp b/applications/infrared/cli/infrared_cli.cpp index 15de2d85..b60e4599 100644 --- a/applications/infrared/cli/infrared_cli.cpp +++ b/applications/infrared/cli/infrared_cli.cpp @@ -60,6 +60,8 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv } static void infrared_cli_start_ir_rx(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); InfraredWorker* worker = infrared_worker_alloc(); infrared_worker_rx_start(worker); infrared_worker_rx_set_received_signal_callback(worker, signal_received_callback, cli); @@ -140,6 +142,7 @@ static bool parse_signal_raw( } static void infrared_cli_start_ir_tx(Cli* cli, string_t args) { + UNUSED(cli); InfraredMessage message; const char* str = string_get_cstr(args); uint32_t frequency; @@ -160,6 +163,7 @@ static void infrared_cli_start_ir_tx(Cli* cli, string_t args) { } static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { + UNUSED(context); if(furi_hal_infrared_is_busy()) { printf("INFRARED is busy. Exit."); return; diff --git a/applications/infrared/helpers/infrared_parser.cpp b/applications/infrared/helpers/infrared_parser.cpp index 12a93924..d85a7269 100644 --- a/applications/infrared/helpers/infrared_parser.cpp +++ b/applications/infrared/helpers/infrared_parser.cpp @@ -145,7 +145,7 @@ bool infrared_parser_is_raw_signal_valid( frequency); result = false; } else if((duty_cycle <= 0) || (duty_cycle > 1)) { - FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", duty_cycle); + FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)duty_cycle); result = false; } else if((timings_cnt <= 0) || (timings_cnt > MAX_TIMINGS_AMOUNT)) { FURI_LOG_E( diff --git a/applications/infrared/infrared_app_event.h b/applications/infrared/infrared_app_event.h index fdea826a..168ba0b1 100644 --- a/applications/infrared/infrared_app_event.h +++ b/applications/infrared/infrared_app_event.h @@ -36,6 +36,7 @@ public: }; union { + int32_t dummy; /** Menu selected event type payload. Selected index. */ int32_t menu_index; /** DialogEx view module event type payload */ diff --git a/applications/infrared/infrared_app_view_manager.cpp b/applications/infrared/infrared_app_view_manager.cpp index 1e08471d..f1e48ed4 100644 --- a/applications/infrared/infrared_app_view_manager.cpp +++ b/applications/infrared/infrared_app_view_manager.cpp @@ -148,7 +148,7 @@ void InfraredAppViewManager::send_event(InfraredAppEvent* event) { osMessageQueuePut(event_queue, event, 0, timeout); } -uint32_t InfraredAppViewManager::previous_view_callback(void* context) { +uint32_t InfraredAppViewManager::previous_view_callback(void*) { if(event_queue != NULL) { InfraredAppEvent event; event.type = InfraredAppEvent::Type::Back; diff --git a/applications/infrared/scene/infrared_app_scene_ask_back.cpp b/applications/infrared/scene/infrared_app_scene_ask_back.cpp index 751816af..65d7ca57 100644 --- a/applications/infrared/scene/infrared_app_scene_ask_back.cpp +++ b/applications/infrared/scene/infrared_app_scene_ask_back.cpp @@ -69,5 +69,5 @@ bool InfraredAppSceneAskBack::on_event(InfraredApp* app, InfraredAppEvent* event return consumed; } -void InfraredAppSceneAskBack::on_exit(InfraredApp* app) { +void InfraredAppSceneAskBack::on_exit(InfraredApp*) { } diff --git a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp b/applications/infrared/scene/infrared_app_scene_edit_delete.cpp index d49acec5..e17cfee0 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_delete.cpp @@ -96,5 +96,5 @@ bool InfraredAppSceneEditDelete::on_event(InfraredApp* app, InfraredAppEvent* ev return consumed; } -void InfraredAppSceneEditDelete::on_exit(InfraredApp* app) { +void InfraredAppSceneEditDelete::on_exit(InfraredApp*) { } diff --git a/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp b/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp index 2b6afafd..803481f6 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp @@ -26,5 +26,5 @@ bool InfraredAppSceneEditRenameDone::on_event(InfraredApp* app, InfraredAppEvent return consumed; } -void InfraredAppSceneEditRenameDone::on_exit(InfraredApp* app) { +void InfraredAppSceneEditRenameDone::on_exit(InfraredApp*) { } diff --git a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp b/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp index 0f148e80..7d15a7c5 100644 --- a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp +++ b/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp @@ -56,5 +56,5 @@ bool InfraredAppSceneLearnEnterName::on_event(InfraredApp* app, InfraredAppEvent return consumed; } -void InfraredAppSceneLearnEnterName::on_exit(InfraredApp* app) { +void InfraredAppSceneLearnEnterName::on_exit(InfraredApp*) { } diff --git a/applications/infrared/scene/infrared_app_scene_remote_list.cpp b/applications/infrared/scene/infrared_app_scene_remote_list.cpp index 95ef2e41..f59ff3e9 100644 --- a/applications/infrared/scene/infrared_app_scene_remote_list.cpp +++ b/applications/infrared/scene/infrared_app_scene_remote_list.cpp @@ -40,11 +40,9 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) { } } -bool InfraredAppSceneRemoteList::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - return consumed; +bool InfraredAppSceneRemoteList::on_event(InfraredApp*, InfraredAppEvent*) { + return false; } -void InfraredAppSceneRemoteList::on_exit(InfraredApp* app) { +void InfraredAppSceneRemoteList::on_exit(InfraredApp*) { } diff --git a/applications/infrared/scene/infrared_app_scene_universal_common.cpp b/applications/infrared/scene/infrared_app_scene_universal_common.cpp index a9220eaf..9e7a18f4 100644 --- a/applications/infrared/scene/infrared_app_scene_universal_common.cpp +++ b/applications/infrared/scene/infrared_app_scene_universal_common.cpp @@ -25,6 +25,7 @@ static void infrared_progress_back_callback(void* context) { auto app = static_cast(context); InfraredAppEvent infrared_event = { + .payload = {.dummy = 0}, .type = InfraredAppEvent::Type::Back, }; app->get_view_manager()->clear_events(); @@ -57,7 +58,10 @@ bool InfraredAppSceneUniversalCommon::on_event(InfraredApp* app, InfraredAppEven if(event->type == InfraredAppEvent::Type::Tick) { auto view_manager = app->get_view_manager(); app->notify_blink_send(); - InfraredAppEvent tick_event = {.type = InfraredAppEvent::Type::Tick}; + InfraredAppEvent tick_event = { + .payload = {.dummy = 0}, + .type = InfraredAppEvent::Type::Tick, + }; view_manager->send_event(&tick_event); bool result = brute_force.send_next_bruteforce(); if(result) { diff --git a/applications/input/input.c b/applications/input/input.c index a2dd62f7..dd824dcb 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -35,6 +35,7 @@ void input_press_timer_callback(void* arg) { } void input_isr(void* _ctx) { + UNUSED(_ctx); osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR); } diff --git a/applications/input/input_cli.c b/applications/input/input_cli.c index 00591a75..afb05afd 100644 --- a/applications/input/input_cli.c +++ b/applications/input/input_cli.c @@ -20,6 +20,7 @@ static void input_cli_dump_events_callback(const void* value, void* ctx) { } static void input_cli_dump(Cli* cli, string_t args, Input* input) { + UNUSED(args); osMessageQueueId_t input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); FuriPubSubSubscription* input_subscription = furi_pubsub_subscribe(input->event_pubsub, input_cli_dump_events_callback, input_queue); @@ -47,6 +48,7 @@ static void input_cli_send_print_usage() { } static void input_cli_send(Cli* cli, string_t args, Input* input) { + UNUSED(cli); InputEvent event; string_t key_str; string_init(key_str); diff --git a/applications/lfrfid/helpers/decoder_analyzer.cpp b/applications/lfrfid/helpers/decoder_analyzer.cpp index 8142f14c..8d344b88 100644 --- a/applications/lfrfid/helpers/decoder_analyzer.cpp +++ b/applications/lfrfid/helpers/decoder_analyzer.cpp @@ -2,7 +2,8 @@ #include #include -bool DecoderAnalyzer::read(uint8_t* _data, uint8_t _data_size) { +// FIXME: unused args? +bool DecoderAnalyzer::read(uint8_t* /* _data */, uint8_t /* _data_size */) { bool result = false; if(ready) { @@ -21,6 +22,7 @@ bool DecoderAnalyzer::read(uint8_t* _data, uint8_t _data_size) { } void DecoderAnalyzer::process_front(bool polarity, uint32_t time) { + UNUSED(polarity); if(ready) return; data[data_index] = time; diff --git a/applications/lfrfid/helpers/decoder_gpio_out.cpp b/applications/lfrfid/helpers/decoder_gpio_out.cpp index 03e03994..dfb43426 100644 --- a/applications/lfrfid/helpers/decoder_gpio_out.cpp +++ b/applications/lfrfid/helpers/decoder_gpio_out.cpp @@ -2,7 +2,7 @@ #include #include -void DecoderGpioOut::process_front(bool polarity, uint32_t time) { +void DecoderGpioOut::process_front(bool polarity, uint32_t /* time */) { furi_hal_gpio_write(&gpio_ext_pa7, polarity); } diff --git a/applications/lfrfid/helpers/decoder_hid26.h b/applications/lfrfid/helpers/decoder_hid26.h index b409ca43..c73ff88c 100644 --- a/applications/lfrfid/helpers/decoder_hid26.h +++ b/applications/lfrfid/helpers/decoder_hid26.h @@ -21,4 +21,4 @@ private: void reset_state(); ProtocolHID10301 hid; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/decoder_indala.cpp b/applications/lfrfid/helpers/decoder_indala.cpp index eb711fa2..100dde73 100644 --- a/applications/lfrfid/helpers/decoder_indala.cpp +++ b/applications/lfrfid/helpers/decoder_indala.cpp @@ -73,4 +73,4 @@ void DecoderIndala::reset_state() { cursed_raw_data = 0; ready = false; cursed_data_valid = false; -} \ No newline at end of file +} diff --git a/applications/lfrfid/helpers/decoder_indala.h b/applications/lfrfid/helpers/decoder_indala.h index 94ad8b16..5fbde7b6 100644 --- a/applications/lfrfid/helpers/decoder_indala.h +++ b/applications/lfrfid/helpers/decoder_indala.h @@ -22,4 +22,4 @@ private: std::atomic ready; std::atomic cursed_data_valid; ProtocolIndala40134 indala; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/emmarin.h b/applications/lfrfid/helpers/emmarin.h index 5d2e2439..ff8273bf 100644 --- a/applications/lfrfid/helpers/emmarin.h +++ b/applications/lfrfid/helpers/emmarin.h @@ -12,4 +12,4 @@ #define EM_STOP_MASK (0x1LLU << EM_STOP_POS) #define EM_HEADER_AND_STOP_MASK (EM_HEADER_MASK | EM_STOP_MASK) -#define EM_HEADER_AND_STOP_DATA (EM_HEADER_MASK) \ No newline at end of file +#define EM_HEADER_AND_STOP_DATA (EM_HEADER_MASK) diff --git a/applications/lfrfid/helpers/encoder_emmarin.h b/applications/lfrfid/helpers/encoder_emmarin.h index fa78122f..560daec1 100644 --- a/applications/lfrfid/helpers/encoder_emmarin.h +++ b/applications/lfrfid/helpers/encoder_emmarin.h @@ -19,4 +19,4 @@ private: uint64_t card_data; uint8_t card_data_index; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/encoder_hid_h10301.h b/applications/lfrfid/helpers/encoder_hid_h10301.h index e5edd0a0..8cc5aa5c 100644 --- a/applications/lfrfid/helpers/encoder_hid_h10301.h +++ b/applications/lfrfid/helpers/encoder_hid_h10301.h @@ -23,4 +23,4 @@ private: void write_raw_bit(bool bit, uint8_t position); OscFSK* fsk; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/encoder_indala_40134.h b/applications/lfrfid/helpers/encoder_indala_40134.h index 8bdb3acd..eda29457 100644 --- a/applications/lfrfid/helpers/encoder_indala_40134.h +++ b/applications/lfrfid/helpers/encoder_indala_40134.h @@ -20,4 +20,4 @@ private: bool last_bit; bool current_polarity; static const uint8_t clock_per_bit = 16; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/key_info.cpp b/applications/lfrfid/helpers/key_info.cpp index 74b4fa5c..ed2b20a9 100644 --- a/applications/lfrfid/helpers/key_info.cpp +++ b/applications/lfrfid/helpers/key_info.cpp @@ -63,4 +63,4 @@ uint8_t lfrfid_key_get_type_data_count(LfrfidKeyType type) { } return 0; -} \ No newline at end of file +} diff --git a/applications/lfrfid/helpers/key_info.h b/applications/lfrfid/helpers/key_info.h index 277ede08..e465011d 100644 --- a/applications/lfrfid/helpers/key_info.h +++ b/applications/lfrfid/helpers/key_info.h @@ -13,4 +13,4 @@ enum class LfrfidKeyType : uint8_t { const char* lfrfid_key_get_type_string(LfrfidKeyType type); const char* lfrfid_key_get_manufacturer_string(LfrfidKeyType type); bool lfrfid_key_get_string_type(const char* string, LfrfidKeyType* type); -uint8_t lfrfid_key_get_type_data_count(LfrfidKeyType type); \ No newline at end of file +uint8_t lfrfid_key_get_type_data_count(LfrfidKeyType type); diff --git a/applications/lfrfid/helpers/osc_fsk.h b/applications/lfrfid/helpers/osc_fsk.h index e9bd322b..eaaaa10a 100644 --- a/applications/lfrfid/helpers/osc_fsk.h +++ b/applications/lfrfid/helpers/osc_fsk.h @@ -27,4 +27,4 @@ private: const uint16_t freq[2]; const uint16_t osc_phase_max; int32_t osc_phase_current; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/protocols/protocol_generic.h b/applications/lfrfid/helpers/protocols/protocol_generic.h index 8d8edfb2..d593f708 100644 --- a/applications/lfrfid/helpers/protocols/protocol_generic.h +++ b/applications/lfrfid/helpers/protocols/protocol_generic.h @@ -57,4 +57,4 @@ public: virtual bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) = 0; virtual ~ProtocolGeneric(){}; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/protocols/protocol_hid_h10301.h b/applications/lfrfid/helpers/protocols/protocol_hid_h10301.h index d769e874..fbd6e0b2 100644 --- a/applications/lfrfid/helpers/protocols/protocol_hid_h10301.h +++ b/applications/lfrfid/helpers/protocols/protocol_hid_h10301.h @@ -19,4 +19,4 @@ public: const uint8_t decoded_data_size) final; bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) final; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/protocols/protocol_indala_40134.cpp b/applications/lfrfid/helpers/protocols/protocol_indala_40134.cpp index e77c808f..482339de 100644 --- a/applications/lfrfid/helpers/protocols/protocol_indala_40134.cpp +++ b/applications/lfrfid/helpers/protocols/protocol_indala_40134.cpp @@ -234,4 +234,4 @@ bool ProtocolIndala40134::can_be_decoded( } while(false); return can_be_decoded; -} \ No newline at end of file +} diff --git a/applications/lfrfid/helpers/pulse_joiner.h b/applications/lfrfid/helpers/pulse_joiner.h index 96d4482e..1639d837 100644 --- a/applications/lfrfid/helpers/pulse_joiner.h +++ b/applications/lfrfid/helpers/pulse_joiner.h @@ -33,4 +33,4 @@ private: uint8_t pulse_index = 0; static const uint8_t pulse_max = 6; Pulse pulses[pulse_max]; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/rfid_key.cpp b/applications/lfrfid/helpers/rfid_key.cpp index 4a54e470..02e45e68 100644 --- a/applications/lfrfid/helpers/rfid_key.cpp +++ b/applications/lfrfid/helpers/rfid_key.cpp @@ -36,7 +36,7 @@ const char* RfidKey::get_type_text() { return lfrfid_key_get_type_string(type); } -const uint8_t RfidKey::get_type_data_count() { +uint8_t RfidKey::get_type_data_count() const { return lfrfid_key_get_type_data_count(type); } diff --git a/applications/lfrfid/helpers/rfid_key.h b/applications/lfrfid/helpers/rfid_key.h index 83251625..29b87cf9 100644 --- a/applications/lfrfid/helpers/rfid_key.h +++ b/applications/lfrfid/helpers/rfid_key.h @@ -14,7 +14,7 @@ public: LfrfidKeyType get_type(); const uint8_t* get_data(); const char* get_type_text(); - const uint8_t get_type_data_count(); + uint8_t get_type_data_count() const; char* get_name(); uint8_t get_name_length(); void clear(); diff --git a/applications/lfrfid/helpers/rfid_worker.h b/applications/lfrfid/helpers/rfid_worker.h index 27ec145c..2c49ad14 100644 --- a/applications/lfrfid/helpers/rfid_worker.h +++ b/applications/lfrfid/helpers/rfid_worker.h @@ -45,4 +45,4 @@ private: void sq_write_validate(); uint16_t validate_counts; void sq_write_stop_validate(); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/rfid_writer.h b/applications/lfrfid/helpers/rfid_writer.h index 3ec3c1dd..38329877 100644 --- a/applications/lfrfid/helpers/rfid_writer.h +++ b/applications/lfrfid/helpers/rfid_writer.h @@ -17,4 +17,4 @@ private: void write_byte(uint8_t value); void write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data); void write_reset(); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/helpers/state_sequencer.h b/applications/lfrfid/helpers/state_sequencer.h index e0ad135f..12512ab5 100644 --- a/applications/lfrfid/helpers/state_sequencer.h +++ b/applications/lfrfid/helpers/state_sequencer.h @@ -22,4 +22,4 @@ private: uint32_t tick_count; void do_nothing(); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/lfrfid_cli.cpp b/applications/lfrfid/lfrfid_cli.cpp index 235dd68f..dbd37ddc 100644 --- a/applications/lfrfid/lfrfid_cli.cpp +++ b/applications/lfrfid/lfrfid_cli.cpp @@ -100,6 +100,8 @@ static void lfrfid_cli_read(Cli* cli, string_t args) { } static void lfrfid_cli_write(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); // TODO implement rfid write printf("Not implemented :(\r\n"); } @@ -147,6 +149,7 @@ static void lfrfid_cli_emulate(Cli* cli, string_t args) { } static void lfrfid_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp index 5b7ac0f9..40bd9e36 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp @@ -3,7 +3,7 @@ #include "../view/elements/icon_element.h" #include "../view/elements/string_element.h" -void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { string_init(string_data); string_init(string_decrypted); string_init(string_header); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h index 36d436a4..e30764f0 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h @@ -14,4 +14,4 @@ private: string_t string_header; string_t string_data; string_t string_decrypted; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp index a4f2bf38..9820338d 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp @@ -1,6 +1,6 @@ #include "lfrfid_app_scene_delete_success.h" -void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); popup->set_icon(0, 2, &I_DolphinMafia_115x62); @@ -35,4 +35,4 @@ void LfRfidAppSceneDeleteSuccess::timeout_callback(void* context) { LfRfidApp::Event event; event.type = LfRfidApp::EventType::Back; app->view_controller.send_event(&event); -} \ No newline at end of file +} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h index 01f929e7..009b9f25 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h @@ -9,4 +9,4 @@ public: private: static void timeout_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp index 17472e16..f1118a48 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp @@ -1,7 +1,7 @@ #include "lfrfid_app_scene_emulate.h" #include -void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) { string_init(data_string); DOLPHIN_DEED(DolphinDeedRfidEmulate); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h b/applications/lfrfid/scene/lfrfid_app_scene_emulate.h index ad5c8418..937e49af 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_emulate.h @@ -9,4 +9,4 @@ public: private: string_t data_string; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp index 262dfca1..d423cec9 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp @@ -3,7 +3,7 @@ #include "../view/elements/icon_element.h" #include "../view/elements/string_element.h" -void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { auto container = app->view_controller.get(); auto button = container->add(); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h index 4f960d22..a0a10232 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h @@ -10,4 +10,4 @@ public: private: static void exit_callback(void* context); static void stay_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read.cpp index 48175590..f87aa200 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_read.cpp @@ -1,7 +1,7 @@ #include "lfrfid_app_scene_read.h" #include -void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); DOLPHIN_DEED(DolphinDeedRfidRead); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.h b/applications/lfrfid/scene/lfrfid_app_scene_read.h index b978270c..b5035b72 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_read.h @@ -6,4 +6,4 @@ 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; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h index 43d68a81..2b50b96f 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h @@ -10,4 +10,4 @@ public: private: static void submenu_callback(void* context, uint32_t index); uint32_t submenu_item_selected = 0; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp index 8f6a0b57..2b81a58a 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp @@ -3,7 +3,7 @@ #include "../view/elements/icon_element.h" #include "../view/elements/string_element.h" -void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { string_init(string[0]); string_init(string[1]); string_init(string[2]); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h b/applications/lfrfid/scene/lfrfid_app_scene_read_success.h index e2c182ea..ac0e3c1b 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_read_success.h @@ -12,4 +12,4 @@ private: static void more_callback(void* context); string_t string[3]; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp index 092a5f02..e62b91bd 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp @@ -3,7 +3,7 @@ #include "../view/elements/icon_element.h" #include "../view/elements/string_element.h" -void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { auto container = app->view_controller.get(); auto button = container->add(); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h index af2373f0..01b7329c 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h @@ -10,4 +10,4 @@ public: private: static void exit_callback(void* context); static void stay_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h b/applications/lfrfid/scene/lfrfid_app_scene_save_data.h index d735fba1..6458ae64 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_data.h @@ -30,4 +30,4 @@ private: 0xBB, 0xBB, }; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp index f755f0e3..d460724e 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp @@ -1,7 +1,7 @@ #include "lfrfid_app_scene_save_name.h" #include -void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) { const char* key_name = app->worker.key.get_name(); bool key_name_empty = !strcmp(key_name, ""); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h b/applications/lfrfid/scene/lfrfid_app_scene_save_name.h index 39201c34..ced42cc0 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_name.h @@ -9,4 +9,4 @@ public: private: static void save_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp index 184a445a..64efafa7 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp @@ -3,7 +3,7 @@ #include #include -void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); DOLPHIN_DEED(DolphinDeedRfidSave); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h b/applications/lfrfid/scene/lfrfid_app_scene_save_success.h index 36aebf3e..62273a76 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_success.h @@ -9,4 +9,4 @@ public: private: static void timeout_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h b/applications/lfrfid/scene/lfrfid_app_scene_save_type.h index 7e57a93d..1f6f6d74 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_type.h @@ -12,4 +12,4 @@ private: uint32_t submenu_item_selected = 0; static const uint8_t keys_count = static_cast(LfrfidKeyType::KeyI40134); string_t submenu_name[keys_count + 1]; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp index b054e141..73c9a403 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp @@ -3,7 +3,7 @@ #include "../view/elements/icon_element.h" #include "../view/elements/string_element.h" -void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool /* need_restore */) { string_init(string_data); string_init(string_decrypted); @@ -59,10 +59,8 @@ void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) { app->view_controller.switch_to(); } -bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - return consumed; +bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) { + return false; } void LfRfidAppSceneSavedInfo::on_exit(LfRfidApp* app) { diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h index ec15c6dc..5aa33e8a 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h @@ -12,4 +12,4 @@ private: string_t string_data; string_t string_decrypted; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h index b3ad10ec..69a6e5e5 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h @@ -10,4 +10,4 @@ public: private: static void submenu_callback(void* context, uint32_t index); uint32_t submenu_item_selected = 0; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp b/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp index d376056b..6d5df73c 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp @@ -8,11 +8,9 @@ void LfRfidAppSceneSelectKey::on_enter(LfRfidApp* app, bool need_restore) { } } -bool LfRfidAppSceneSelectKey::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - return consumed; +bool LfRfidAppSceneSelectKey::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) { + return false; } -void LfRfidAppSceneSelectKey::on_exit(LfRfidApp* app) { -} \ No newline at end of file +void LfRfidAppSceneSelectKey::on_exit(LfRfidApp* /* app */) { +} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h b/applications/lfrfid/scene/lfrfid_app_scene_select_key.h index 10f11c61..be565a91 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_select_key.h @@ -6,4 +6,4 @@ 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; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_start.h b/applications/lfrfid/scene/lfrfid_app_scene_start.h index 3f48db70..255590d6 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_start.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_start.h @@ -10,4 +10,4 @@ public: private: static void submenu_callback(void* context, uint32_t index); uint32_t submenu_item_selected = 0; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp index 24f9fd0c..d6c9e9f4 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp @@ -1,6 +1,6 @@ #include "lfrfid_app_scene_write.h" -void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) { card_not_supported = false; string_init(data_string); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.h b/applications/lfrfid/scene/lfrfid_app_scene_write.h index 603f59d8..3abadeba 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_write.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_write.h @@ -10,4 +10,4 @@ public: private: string_t data_string; bool card_not_supported; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp index 0539e623..3cf00183 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp @@ -1,6 +1,6 @@ #include "lfrfid_app_scene_write_success.h" -void LfRfidAppSceneWriteSuccess::on_enter(LfRfidApp* app, bool need_restore) { +void LfRfidAppSceneWriteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); popup->set_header("Successfully\nwritten!", 94, 3, AlignCenter, AlignTop); popup->set_icon(0, 6, &I_RFIDDolphinSuccess_108x57); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h b/applications/lfrfid/scene/lfrfid_app_scene_write_success.h index 94b8efc1..4ac9f089 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h +++ b/applications/lfrfid/scene/lfrfid_app_scene_write_success.h @@ -9,4 +9,4 @@ public: private: static void timeout_callback(void* context); -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/view/container_vm.cpp b/applications/lfrfid/view/container_vm.cpp index 8c0e72e2..3c01ba30 100644 --- a/applications/lfrfid/view/container_vm.cpp +++ b/applications/lfrfid/view/container_vm.cpp @@ -112,4 +112,4 @@ bool ContainerVM::view_input_callback(InputEvent* event, void* context) { template StringElement* ContainerVM::add(); template IconElement* ContainerVM::add(); -template ButtonElement* ContainerVM::add(); \ No newline at end of file +template ButtonElement* ContainerVM::add(); diff --git a/applications/lfrfid/view/elements/generic_element.h b/applications/lfrfid/view/elements/generic_element.h index 269373f1..f5a58b2d 100644 --- a/applications/lfrfid/view/elements/generic_element.h +++ b/applications/lfrfid/view/elements/generic_element.h @@ -18,4 +18,4 @@ public: private: View* view = nullptr; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid/view/elements/icon_element.cpp b/applications/lfrfid/view/elements/icon_element.cpp index e4cb19ad..0b6fba7d 100644 --- a/applications/lfrfid/view/elements/icon_element.cpp +++ b/applications/lfrfid/view/elements/icon_element.cpp @@ -12,7 +12,7 @@ void IconElement::draw(Canvas* canvas) { } } -bool IconElement::input(InputEvent* event) { +bool IconElement::input(InputEvent* /* event */) { return false; } diff --git a/applications/lfrfid/view/elements/string_element.cpp b/applications/lfrfid/view/elements/string_element.cpp index 028bd7fd..44c11e01 100644 --- a/applications/lfrfid/view/elements/string_element.cpp +++ b/applications/lfrfid/view/elements/string_element.cpp @@ -23,7 +23,7 @@ void StringElement::draw(Canvas* canvas) { } } -bool StringElement::input(InputEvent* event) { +bool StringElement::input(InputEvent* /* event */) { return false; } @@ -44,4 +44,4 @@ void StringElement::set_text( vertical = _vertical; font = _font; unlock_model(true); -} \ No newline at end of file +} diff --git a/applications/lfrfid_debug/lfrfid_debug_app.cpp b/applications/lfrfid_debug/lfrfid_debug_app.cpp index 5de1de71..9cd9dcad 100644 --- a/applications/lfrfid_debug/lfrfid_debug_app.cpp +++ b/applications/lfrfid_debug/lfrfid_debug_app.cpp @@ -13,4 +13,4 @@ void LfRfidDebugApp::run() { scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart()); scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune()); scene_controller.process(100); -} \ No newline at end of file +} diff --git a/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp b/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp index 0ee458f4..4551a17c 100644 --- a/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp +++ b/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp @@ -2,6 +2,7 @@ // app enter function extern "C" int32_t lfrfid_debug_app(void* p) { + UNUSED(p); LfRfidDebugApp* app = new LfRfidDebugApp(); app->run(); delete app; diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h index b8f811d0..7fc0b07d 100644 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h +++ b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h @@ -10,4 +10,4 @@ public: private: void submenu_callback(void* context, uint32_t index); uint32_t submenu_item_selected = 0; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp index 53679402..4b627649 100644 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp +++ b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp @@ -2,10 +2,11 @@ #include static void comparator_trigger_callback(bool level, void* comp_ctx) { + UNUSED(comp_ctx); furi_hal_gpio_write(&gpio_ext_pa7, !level); } -void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) { +void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool /* need_restore */) { app->view_controller.switch_to(); furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); @@ -17,7 +18,7 @@ void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) { furi_hal_rfid_tim_read_start(); } -bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) { +bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* /* event */) { bool consumed = false; LfRfidViewTuneVM* tune = app->view_controller; @@ -30,7 +31,7 @@ bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Even return consumed; } -void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) { +void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* /* app */) { furi_hal_rfid_comp_stop(); furi_hal_rfid_comp_set_callback(NULL, NULL); diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h index 94dfea97..53399efc 100644 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h +++ b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h @@ -6,4 +6,4 @@ public: void on_enter(LfRfidDebugApp* app, bool need_restore) final; bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final; void on_exit(LfRfidDebugApp* app) final; -}; \ No newline at end of file +}; diff --git a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp index 3039517e..5c244b92 100644 --- a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp +++ b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp @@ -29,6 +29,8 @@ void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { constexpr uint8_t buffer_size = 128; char buffer[buffer_size + 1]; + double freq = ((float)SystemCoreClock / ((float)model->ARR + 1)); + double duty = ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f; snprintf( buffer, buffer_size, @@ -38,10 +40,10 @@ void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { "duty = %.4f", model->pos == 0 ? ">" : "", model->ARR, - (float)SystemCoreClock / ((float)model->ARR + 1), + freq, model->pos == 1 ? ">" : "", model->CCR, - ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f); + duty); elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer); } diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 43e275ab..e5d59702 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -39,6 +39,7 @@ static bool } static void loader_menu_callback(void* _ctx, uint32_t index) { + UNUSED(index); const FlipperApplication* application = _ctx; furi_assert(application->app); @@ -53,6 +54,7 @@ static void loader_menu_callback(void* _ctx, uint32_t index) { } static void loader_submenu_callback(void* context, uint32_t index) { + UNUSED(index); uint32_t view_id = (uint32_t)context; view_dispatcher_switch_to_view(loader_instance->view_dispatcher, view_id); } @@ -101,6 +103,7 @@ const FlipperApplication* loader_find_application_by_name(const char* name) { } void loader_cli_open(Cli* cli, string_t args, Loader* instance) { + UNUSED(cli); if(loader_is_locked(instance)) { printf("Can't start, furi application is running"); return; @@ -139,6 +142,9 @@ void loader_cli_open(Cli* cli, string_t args, Loader* instance) { } void loader_cli_list(Cli* cli, string_t args, Loader* instance) { + UNUSED(cli); + UNUSED(args); + UNUSED(instance); printf("Applications:\r\n"); for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { printf("\t%s\r\n", FLIPPER_APPS[i].name); @@ -187,6 +193,7 @@ static void loader_cli(Cli* cli, string_t args, void* _ctx) { } LoaderStatus loader_start(Loader* instance, const char* name, const char* args) { + UNUSED(instance); furi_assert(name); const FlipperApplication* application = loader_find_application_by_name(name); @@ -265,6 +272,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con } static uint32_t loader_hide_menu(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -445,6 +453,7 @@ void loader_update_menu() { } int32_t loader_srv(void* p) { + UNUSED(p); FURI_LOG_I(TAG, "Executing system start hooks"); for(size_t i = 0; i < FLIPPER_ON_SYSTEM_START_COUNT; i++) { FLIPPER_ON_SYSTEM_START[i](); diff --git a/applications/music_player/music_player.c b/applications/music_player/music_player.c index 4f8813d6..73f4bd2c 100644 --- a/applications/music_player/music_player.c +++ b/applications/music_player/music_player.c @@ -2,132 +2,93 @@ #include #include -#include +#include +#include "music_player_worker.h" -// TODO float note freq -typedef enum { - // Delay - N = 0, - // Octave 4 - B4 = 494, - // Octave 5 - C5 = 523, - D5 = 587, - E5 = 659, - F_5 = 740, - G5 = 784, - A5 = 880, - B5 = 988, - // Octave 6 - C6 = 1046, - D6 = 1175, - E6 = 1319, -} MelodyEventNote; +#define TAG "MusicPlayer" -typedef enum { - L1 = 1, - L2 = 2, - L4 = 4, - L8 = 8, - L16 = 16, - L32 = 32, - L64 = 64, - L128 = 128, -} MelodyEventLength; +#define MUSIC_PLAYER_APP_PATH_FOLDER "/any/music_player" +#define MUSIC_PLAYER_APP_EXTENSION "*" + +#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4 typedef struct { - MelodyEventNote note; - MelodyEventLength length; -} MelodyEventRecord; + uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; + uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; + + uint8_t volume; + uint8_t semitone; + uint8_t dots; + uint8_t duration; + float position; +} MusicPlayerModel; typedef struct { - const MelodyEventRecord* record; - int8_t loop_count; -} SongPattern; + MusicPlayerModel* model; + osMutexId_t* model_mutex; -const MelodyEventRecord melody_start[] = { - {E6, L8}, {N, L8}, {E5, L8}, {B5, L8}, {N, L4}, {E5, L8}, {A5, L8}, {G5, L8}, {A5, L8}, - {E5, L8}, {B5, L8}, {N, L8}, {G5, L8}, {A5, L8}, {D6, L8}, {N, L4}, {D5, L8}, {B5, L8}, - {N, L4}, {D5, L8}, {A5, L8}, {G5, L8}, {A5, L8}, {D5, L8}, {F_5, L8}, {N, L8}, {G5, L8}, - {A5, L8}, {D6, L8}, {N, L4}, {F_5, L8}, {B5, L8}, {N, L4}, {F_5, L8}, {D6, L8}, {C6, L8}, - {B5, L8}, {F_5, L8}, {A5, L8}, {N, L8}, {G5, L8}, {F_5, L8}, {E5, L8}, {N, L8}, {C5, L8}, - {E5, L8}, {B5, L8}, {B4, L8}, {C5, L8}, {D5, L8}, {D6, L8}, {C6, L8}, {B5, L8}, {F_5, L8}, - {A5, L8}, {N, L8}, {G5, L8}, {A5, L8}, {E6, L8}}; + osMessageQueueId_t input_queue; -const MelodyEventRecord melody_loop[] = { - {N, L4}, {E5, L8}, {B5, L8}, {N, L4}, {E5, L8}, {A5, L8}, {G5, L8}, {A5, L8}, {E5, L8}, - {B5, L8}, {N, L8}, {G5, L8}, {A5, L8}, {D6, L8}, {N, L4}, {D5, L8}, {B5, L8}, {N, L4}, - {D5, L8}, {A5, L8}, {G5, L8}, {A5, L8}, {D5, L8}, {F_5, L8}, {N, L8}, {G5, L8}, {A5, L8}, - {D6, L8}, {N, L4}, {F_5, L8}, {B5, L8}, {N, L4}, {F_5, L8}, {D6, L8}, {C6, L8}, {B5, L8}, - {F_5, L8}, {A5, L8}, {N, L8}, {G5, L8}, {F_5, L8}, {E5, L8}, {N, L8}, {C5, L8}, {E5, L8}, - {B5, L8}, {B4, L8}, {C5, L8}, {D5, L8}, {D6, L8}, {C6, L8}, {B5, L8}, {F_5, L8}, {A5, L8}, - {N, L8}, {G5, L8}, {A5, L8}, {E6, L8}}; + ViewPort* view_port; + Gui* gui; -const MelodyEventRecord melody_chords_1bar[] = { - {E6, L8}, {N, L8}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, - {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, - {B4, L128}, {E5, L128}, {B5, L8}, {N, L4}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, - {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, - {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {A5, L8}}; + MusicPlayerWorker* worker; +} MusicPlayer; -const SongPattern song[] = {{melody_start, 1}, {melody_loop, -1}}; +static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; -typedef enum { - EventTypeTick, - EventTypeKey, - EventTypeNote, - // add your events type -} MusicDemoEventType; +static const char* semitone_to_note(int8_t semitone) { + switch(semitone) { + case 0: + return "C"; + case 1: + return "C#"; + case 2: + return "D"; + case 3: + return "D#"; + case 4: + return "E"; + case 5: + return "F"; + case 6: + return "F#"; + case 7: + return "G"; + case 8: + return "G#"; + case 9: + return "A"; + case 10: + return "A#"; + case 11: + return "B"; + default: + return "--"; + } +} -typedef struct { - union { - InputEvent input; - const MelodyEventRecord* note_record; - } value; - MusicDemoEventType type; -} MusicDemoEvent; - -typedef struct { - ValueMutex* state_mutex; - osMessageQueueId_t event_queue; - -} MusicDemoContext; - -#define note_stack_size 4 -typedef struct { - // describe state here - const MelodyEventRecord* note_record; - const MelodyEventRecord* note_stack[note_stack_size]; - uint8_t volume_id; - uint8_t volume_id_max; -} State; - -const float volumes[] = {0, .25, .5, .75, 1}; - -bool is_white_note(const MelodyEventRecord* note_record, uint8_t id) { - if(note_record == NULL) return false; - - switch(note_record->note) { - case C5: - case C6: +static bool is_white_note(uint8_t semitone, uint8_t id) { + switch(semitone) { + case 0: if(id == 0) return true; break; - case D5: - case D6: + case 2: if(id == 1) return true; break; - case E5: - case E6: + case 4: if(id == 2) return true; break; - case G5: + case 5: + if(id == 3) return true; + break; + case 7: if(id == 4) return true; break; - case A5: + case 9: if(id == 5) return true; break; - case B4: - case B5: + case 11: if(id == 6) return true; break; default: @@ -137,13 +98,23 @@ bool is_white_note(const MelodyEventRecord* note_record, uint8_t id) { return false; } -bool is_black_note(const MelodyEventRecord* note_record, uint8_t id) { - if(note_record == NULL) return false; - - switch(note_record->note) { - case F_5: +static bool is_black_note(uint8_t semitone, uint8_t id) { + switch(semitone) { + case 1: + if(id == 0) return true; + break; + case 3: + if(id == 1) return true; + break; + case 6: if(id == 3) return true; break; + case 8: + if(id == 4) return true; + break; + case 10: + if(id == 5) return true; + break; default: break; } @@ -151,87 +122,9 @@ bool is_black_note(const MelodyEventRecord* note_record, uint8_t id) { return false; } -const char* get_note_name(const MelodyEventRecord* note_record) { - if(note_record == NULL) return ""; - - switch(note_record->note) { - case N: - return "---"; - break; - case B4: - return "B4-"; - break; - case C5: - return "C5-"; - break; - case D5: - return "D5-"; - break; - case E5: - return "E5-"; - break; - case F_5: - return "F#5"; - break; - case G5: - return "G5-"; - break; - case A5: - return "A5-"; - break; - case B5: - return "B5-"; - break; - case C6: - return "C6-"; - break; - case D6: - return "D6-"; - break; - case E6: - return "E6-"; - break; - default: - return "UNK"; - break; - } -} -const char* get_note_len_name(const MelodyEventRecord* note_record) { - if(note_record == NULL) return ""; - - switch(note_record->length) { - case L1: - return "1-"; - break; - case L2: - return "2-"; - break; - case L4: - return "4-"; - break; - case L8: - return "8-"; - break; - case L16: - return "16"; - break; - case L32: - return "32"; - break; - case L64: - return "64"; - break; - case L128: - return "1+"; - break; - default: - return "--"; - break; - } -} - static void render_callback(Canvas* canvas, void* ctx) { - State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); + MusicPlayer* music_player = ctx; + furi_check(osMutexAcquire(music_player->model_mutex, osWaitForever) == osOK); canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); @@ -250,7 +143,7 @@ static void render_callback(Canvas* canvas, void* ctx) { // white keys for(size_t i = 0; i < 7; i++) { - if(is_white_note(state->note_record, i)) { + if(is_white_note(music_player->model->semitone, i)) { canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); } else { canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); @@ -264,7 +157,7 @@ static void render_callback(Canvas* canvas, void* ctx) { canvas_draw_box( canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); canvas_set_color(canvas, ColorBlack); - if(is_black_note(state->note_record, i)) { + if(is_black_note(music_player->model->semitone, i)) { canvas_draw_box( canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); } else { @@ -277,7 +170,8 @@ static void render_callback(Canvas* canvas, void* ctx) { // volume view_port x_pos = 124; y_pos = 0; - const uint8_t volume_h = (64 / (state->volume_id_max - 1)) * state->volume_id; + const uint8_t volume_h = + (64 / (COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1)) * music_player->model->volume; canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h); @@ -289,171 +183,175 @@ static void render_callback(Canvas* canvas, void* ctx) { canvas_draw_frame(canvas, x_pos, y_pos, 49, 64); canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64); - for(uint8_t i = 0; i < note_stack_size; i++) { + char duration_text[16]; + for(uint8_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE; i++) { + if(music_player->model->duration_history[i] == 0xFF) { + snprintf(duration_text, 15, "--"); + } else { + snprintf(duration_text, 15, "%d", music_player->model->duration_history[i]); + } + if(i == 0) { canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16); canvas_set_color(canvas, ColorWhite); } else { canvas_set_color(canvas, ColorBlack); } - canvas_draw_str(canvas, x_pos + 4, 64 - 16 * i - 3, get_note_name(state->note_stack[i])); canvas_draw_str( - canvas, x_pos + 31, 64 - 16 * i - 3, get_note_len_name(state->note_stack[i])); + canvas, + x_pos + 4, + 64 - 16 * i - 3, + semitone_to_note(music_player->model->semitone_history[i])); + canvas_draw_str(canvas, x_pos + 31, 64 - 16 * i - 3, duration_text); canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i); } - release_mutex((ValueMutex*)ctx, state); + osMutexRelease(music_player->model_mutex); } static void input_callback(InputEvent* input_event, void* ctx) { - osMessageQueueId_t event_queue = ctx; - - MusicDemoEvent event; - event.type = EventTypeKey; - event.value.input = *input_event; - osMessageQueuePut(event_queue, &event, 0, 0); + MusicPlayer* music_player = ctx; + if(input_event->type == InputTypeShort) { + osMessageQueuePut(music_player->input_queue, input_event, 0, 0); + } } -void process_note( - const MelodyEventRecord* note_record, - float bar_length_ms, - MusicDemoContext* context) { - MusicDemoEvent event; - // send note event - event.type = EventTypeNote; - event.value.note_record = note_record; - osMessageQueuePut(context->event_queue, &event, 0, 0); +static void music_player_worker_callback( + uint8_t semitone, + uint8_t dots, + uint8_t duration, + float position, + void* context) { + MusicPlayer* music_player = context; + furi_check(osMutexAcquire(music_player->model_mutex, osWaitForever) == osOK); - // read volume - State* state = (State*)acquire_mutex(context->state_mutex, 25); - float volume = volumes[state->volume_id]; - release_mutex(context->state_mutex, state); - - // play note - float note_delay = bar_length_ms / (float)note_record->length; - if(note_record->note != N) { - furi_hal_speaker_start(note_record->note, volume); + for(size_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1; i++) { + size_t r = MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1 - i; + music_player->model->duration_history[r] = music_player->model->duration_history[r - 1]; + music_player->model->semitone_history[r] = music_player->model->semitone_history[r - 1]; } - furi_hal_delay_ms(note_delay); - furi_hal_speaker_stop(); + + semitone = (semitone == 0xFF) ? 0xFF : semitone % 12; + + music_player->model->semitone = semitone; + music_player->model->dots = dots; + music_player->model->duration = duration; + music_player->model->position = position; + + music_player->model->semitone_history[0] = semitone; + music_player->model->duration_history[0] = duration; + + osMutexRelease(music_player->model_mutex); + view_port_update(music_player->view_port); } -void music_player_thread(void* p) { - MusicDemoContext* context = (MusicDemoContext*)p; +MusicPlayer* music_player_alloc() { + MusicPlayer* instance = malloc(sizeof(MusicPlayer)); - const float bpm = 130.0f; - // 4/4 - const float bar_length_ms = (60.0f * 1000.0f / bpm) * 4; - const uint16_t melody_start_events_count = sizeof(melody_start) / sizeof(melody_start[0]); - const uint16_t melody_loop_events_count = sizeof(melody_loop) / sizeof(melody_loop[0]); + instance->model = malloc(sizeof(MusicPlayerModel)); + memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); + memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); + instance->model->volume = 3; - for(size_t i = 0; i < melody_start_events_count; i++) { - process_note(&melody_start[i], bar_length_ms, context); - } + instance->model_mutex = osMutexNew(NULL); - while(1) { - for(size_t i = 0; i < melody_loop_events_count; i++) { - process_note(&melody_loop[i], bar_length_ms, context); - } - } + instance->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); + + instance->worker = music_player_worker_alloc(); + music_player_worker_set_volume( + instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); + music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance); + + instance->view_port = view_port_alloc(); + view_port_draw_callback_set(instance->view_port, render_callback, instance); + view_port_input_callback_set(instance->view_port, input_callback, instance); + + // Open GUI and register view_port + instance->gui = furi_record_open("gui"); + gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); + + return instance; +} + +void music_player_free(MusicPlayer* instance) { + gui_remove_view_port(instance->gui, instance->view_port); + furi_record_close("gui"); + view_port_free(instance->view_port); + + music_player_worker_free(instance->worker); + + osMessageQueueDelete(instance->input_queue); + + osMutexDelete(instance->model_mutex); + + free(instance->model); + free(instance); } int32_t music_player_app(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(MusicDemoEvent), NULL); + MusicPlayer* music_player = music_player_alloc(); - State _state; - _state.note_record = NULL; - for(size_t i = 0; i < note_stack_size; i++) { - _state.note_stack[i] = NULL; - } - _state.volume_id = 1; - _state.volume_id_max = sizeof(volumes) / sizeof(volumes[0]); + string_t file_path; + string_init(file_path); - ValueMutex state_mutex; - if(!init_mutex(&state_mutex, &_state, sizeof(State))) { - printf("cannot create mutex\r\n"); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, &state_mutex); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // start player thread - // TODO change to fuirac_start - osThreadAttr_t player_attr = {.name = "music_player_thread", .stack_size = 512}; - MusicDemoContext context = {.state_mutex = &state_mutex, .event_queue = event_queue}; - osThreadId_t player = osThreadNew(music_player_thread, &context, &player_attr); - - if(player == NULL) { - printf("cannot create player thread\r\n"); - return 255; - } - - MusicDemoEvent event; - while(1) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); - - State* state = (State*)acquire_mutex_block(&state_mutex); - - if(event_status == osOK) { - if(event.type == EventTypeKey) { - // press events - if(event.value.input.type == InputTypeShort && - event.value.input.key == InputKeyBack) { - release_mutex(&state_mutex, state); - break; - } - - if(event.value.input.type == InputTypePress && - event.value.input.key == InputKeyUp) { - if(state->volume_id < state->volume_id_max - 1) state->volume_id++; - } - - if(event.value.input.type == InputTypePress && - event.value.input.key == InputKeyDown) { - if(state->volume_id > 0) state->volume_id--; - } - - if(event.value.input.type == InputTypePress && - event.value.input.key == InputKeyLeft) { - } - - if(event.value.input.type == InputTypePress && - event.value.input.key == InputKeyRight) { - } - - if(event.value.input.key == InputKeyOk) { - } - - } else if(event.type == EventTypeNote) { - state->note_record = event.value.note_record; - - for(size_t i = note_stack_size - 1; i > 0; i--) { - state->note_stack[i] = state->note_stack[i - 1]; - } - state->note_stack[0] = state->note_record; - } + do { + if(p) { + string_cat_str(file_path, p); } else { - // event timeout + char* file_name = malloc(256); + DialogsApp* dialogs = furi_record_open("dialogs"); + bool res = dialog_file_select_show( + dialogs, + MUSIC_PLAYER_APP_PATH_FOLDER, + MUSIC_PLAYER_APP_EXTENSION, + file_name, + 255, + NULL); + furi_record_close("dialogs"); + if(!res) { + FURI_LOG_E(TAG, "No file selected"); + break; + } + string_cat_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); + string_cat_str(file_path, "/"); + string_cat_str(file_path, file_name); + free(file_name); } - view_port_update(view_port); - release_mutex(&state_mutex, state); - } + if(!music_player_worker_load(music_player->worker, string_get_cstr(file_path))) { + FURI_LOG_E(TAG, "Unable to load file"); + break; + } - osThreadTerminate(player); - furi_hal_speaker_stop(); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - osMessageQueueDelete(event_queue); - delete_mutex(&state_mutex); + music_player_worker_start(music_player->worker); + + InputEvent input; + while(osMessageQueueGet(music_player->input_queue, &input, NULL, osWaitForever) == osOK) { + furi_check(osMutexAcquire(music_player->model_mutex, osWaitForever) == osOK); + + if(input.key == InputKeyBack) { + osMutexRelease(music_player->model_mutex); + break; + } else if(input.key == InputKeyUp) { + if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) + music_player->model->volume++; + music_player_worker_set_volume( + music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); + } else if(input.key == InputKeyDown) { + if(music_player->model->volume > 0) music_player->model->volume--; + music_player_worker_set_volume( + music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); + } + + osMutexRelease(music_player->model_mutex); + view_port_update(music_player->view_port); + } + + music_player_worker_stop(music_player->worker); + } while(0); + + string_clear(file_path); + music_player_free(music_player); return 0; } diff --git a/applications/music_player/music_player_cli.c b/applications/music_player/music_player_cli.c new file mode 100644 index 00000000..0d98101e --- /dev/null +++ b/applications/music_player/music_player_cli.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include "music_player_worker.h" + +static void music_player_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); + MusicPlayerWorker* music_player_worker = music_player_worker_alloc(); + Storage* storage = furi_record_open("storage"); + + do { + if(storage_common_stat(storage, string_get_cstr(args), NULL) == FSE_OK) { + if(!music_player_worker_load(music_player_worker, string_get_cstr(args))) { + printf("Failed to open file %s\r\n", string_get_cstr(args)); + break; + } + } else { + if(!music_player_worker_load_rtttl_from_string( + music_player_worker, string_get_cstr(args))) { + printf("Argument is not a file or RTTTL\r\n"); + break; + } + } + + printf("Press CTRL+C to stop\r\n"); + music_player_worker_start(music_player_worker); + while(!cli_cmd_interrupt_received(cli)) { + osDelay(50); + } + music_player_worker_stop(music_player_worker); + } while(0); + + furi_record_close("storage"); + music_player_worker_free(music_player_worker); +} + +void music_player_on_system_start() { +#ifdef SRV_CLI + Cli* cli = furi_record_open("cli"); + + cli_add_command(cli, "music_player", CliCommandFlagDefault, music_player_cli, NULL); + + furi_record_close("cli"); +#else + UNUSED(music_player_cli); +#endif +} diff --git a/applications/music_player/music_player_worker.c b/applications/music_player/music_player_worker.c new file mode 100644 index 00000000..9a0087aa --- /dev/null +++ b/applications/music_player/music_player_worker.c @@ -0,0 +1,496 @@ +#include "music_player_worker.h" + +#include +#include + +#include +#include + +#include + +#define TAG "MusicPlayerWorker" + +#define MUSIC_PLAYER_FILETYPE "Flipper Music Format" +#define MUSIC_PLAYER_VERSION 0 + +#define SEMITONE_PAUSE 0xFF + +#define NOTE_C4 261.63f +#define NOTE_C4_SEMITONE (4.0f * 12.0f) +#define TWO_POW_TWELTH_ROOT 1.059463094359f + +typedef struct { + uint8_t semitone; + uint8_t duration; + uint8_t dots; +} NoteBlock; + +ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST); + +struct MusicPlayerWorker { + FuriThread* thread; + bool should_work; + + MusicPlayerWorkerCallback callback; + void* callback_context; + + float volume; + uint32_t bpm; + uint32_t duration; + uint32_t octave; + NoteBlockArray_t notes; +}; + +static int32_t music_player_worker_thread_callback(void* context) { + furi_assert(context); + MusicPlayerWorker* instance = context; + + NoteBlockArray_it_t it; + NoteBlockArray_it(it, instance->notes); + + while(instance->should_work) { + if(NoteBlockArray_end_p(it)) { + NoteBlockArray_it(it, instance->notes); + osDelay(10); + } else { + NoteBlock* note_block = NoteBlockArray_ref(it); + + float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE; + float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4); + float duration = + 60.0 * osKernelGetTickFreq() * 4 / instance->bpm / note_block->duration; + while(note_block->dots > 0) { + duration += duration / 2; + note_block->dots--; + } + uint32_t next_tick = furi_hal_get_tick() + duration; + float volume = instance->volume; + + if(instance->callback) { + instance->callback( + note_block->semitone, + note_block->dots, + note_block->duration, + 0.0, + instance->callback_context); + } + + furi_hal_speaker_stop(); + furi_hal_speaker_start(frequency, volume); + while(instance->should_work && furi_hal_get_tick() < next_tick) { + volume *= 0.9945679; + furi_hal_speaker_set_volume(volume); + furi_hal_delay_ms(2); + } + NoteBlockArray_next(it); + } + } + + furi_hal_speaker_stop(); + + return 0; +} + +MusicPlayerWorker* music_player_worker_alloc() { + MusicPlayerWorker* instance = malloc(sizeof(MusicPlayerWorker)); + + NoteBlockArray_init(instance->notes); + + instance->thread = furi_thread_alloc(); + furi_thread_set_name(instance->thread, "MusicPlayerWorker"); + furi_thread_set_stack_size(instance->thread, 1024); + furi_thread_set_context(instance->thread, instance); + furi_thread_set_callback(instance->thread, music_player_worker_thread_callback); + + return instance; +} + +void music_player_worker_free(MusicPlayerWorker* instance) { + furi_assert(instance); + furi_thread_free(instance->thread); + NoteBlockArray_clear(instance->notes); + free(instance); +} + +static bool is_digit(const char c) { + return isdigit(c) != 0; +} + +static bool is_letter(const char c) { + return islower(c) != 0 || isupper(c) != 0; +} + +static bool is_space(const char c) { + return c == ' ' || c == '\t'; +} + +static size_t extract_number(const char* string, uint32_t* number) { + size_t ret = 0; + while(is_digit(*string)) { + *number *= 10; + *number += (*string - '0'); + string++; + ret++; + } + return ret; +} + +static size_t extract_dots(const char* string, uint32_t* number) { + size_t ret = 0; + while(*string == '.') { + *number += 1; + string++; + ret++; + } + return ret; +} + +static size_t extract_char(const char* string, char* symbol) { + if(is_letter(*string)) { + *symbol = *string; + return 1; + } else { + return 0; + } +} + +static size_t extract_sharp(const char* string, char* symbol) { + if(*string == '#' || *string == '_') { + *symbol = '#'; + return 1; + } else { + return 0; + } +} + +static size_t skip_till(const char* string, const char symbol) { + size_t ret = 0; + while(*string != '\0' && *string != symbol) { + string++; + ret++; + } + if(*string != symbol) { + ret = 0; + } + return ret; +} + +static bool music_player_worker_add_note( + MusicPlayerWorker* instance, + uint8_t semitone, + uint8_t duration, + uint8_t dots) { + NoteBlock note_block; + + note_block.semitone = semitone; + note_block.duration = duration; + note_block.dots = dots; + + NoteBlockArray_push_back(instance->notes, note_block); + + return true; +} + +static int8_t note_to_semitone(const char note) { + switch(note) { + case 'C': + return 0; + // C# + case 'D': + return 2; + // D# + case 'E': + return 4; + case 'F': + return 5; + // F# + case 'G': + return 7; + // G# + case 'A': + return 9; + // A# + case 'B': + return 11; + default: + return 0; + } +} + +static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const char* string) { + const char* cursor = string; + bool result = true; + + while(*cursor != '\0') { + if(!is_space(*cursor)) { + uint32_t duration = 0; + char note_char = '\0'; + char sharp_char = '\0'; + uint32_t octave = 0; + uint32_t dots = 0; + + // Parsing + cursor += extract_number(cursor, &duration); + cursor += extract_char(cursor, ¬e_char); + cursor += extract_sharp(cursor, &sharp_char); + cursor += extract_number(cursor, &octave); + cursor += extract_dots(cursor, &dots); + + // Post processing + note_char = toupper(note_char); + if(!duration) { + duration = instance->duration; + } + if(!octave) { + octave = instance->octave; + } + + // Validation + bool is_valid = true; + is_valid &= (duration >= 1 && duration <= 128); + is_valid &= ((note_char >= 'A' && note_char <= 'G') || note_char == 'P'); + is_valid &= (sharp_char == '#' || sharp_char == '\0'); + is_valid &= (octave <= 16); + is_valid &= (dots <= 16); + if(!is_valid) { + FURI_LOG_E( + TAG, + "Invalid note: %u%c%c%u.%u", + duration, + note_char == '\0' ? '_' : note_char, + sharp_char == '\0' ? '_' : sharp_char, + octave, + dots); + result = false; + break; + } + + // Note to semitones + uint8_t semitone = 0; + if(note_char == 'P') { + semitone = SEMITONE_PAUSE; + } else { + semitone += octave * 12; + semitone += note_to_semitone(note_char); + semitone += sharp_char == '#' ? 1 : 0; + } + + if(music_player_worker_add_note(instance, semitone, duration, dots)) { + FURI_LOG_D( + TAG, + "Added note: %c%c%u.%u = %u %u", + note_char == '\0' ? '_' : note_char, + sharp_char == '\0' ? '_' : sharp_char, + octave, + dots, + semitone, + duration); + } else { + FURI_LOG_E( + TAG, + "Invalid note: %c%c%u.%u = %u %u", + note_char == '\0' ? '_' : note_char, + sharp_char == '\0' ? '_' : sharp_char, + octave, + dots, + semitone, + duration); + } + cursor += skip_till(cursor, ','); + } + + if(*cursor != '\0') cursor++; + } + + return result; +} + +bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path) { + furi_assert(instance); + furi_assert(file_path); + + bool ret = false; + if(strcasestr(file_path, ".fmf")) { + ret = music_player_worker_load_fmf_from_file(instance, file_path); + } else { + ret = music_player_worker_load_rtttl_from_file(instance, file_path); + } + return ret; +} + +bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path) { + furi_assert(instance); + furi_assert(file_path); + + bool result = false; + string_t temp_str; + string_init(temp_str); + + Storage* storage = furi_record_open("storage"); + FlipperFormat* file = flipper_format_file_alloc(storage); + + do { + if(!flipper_format_file_open_existing(file, file_path)) break; + + uint32_t version = 0; + if(!flipper_format_read_header(file, temp_str, &version)) break; + if(string_cmp_str(temp_str, MUSIC_PLAYER_FILETYPE) || (version != MUSIC_PLAYER_VERSION)) { + FURI_LOG_E(TAG, "Incorrect file format or version"); + break; + } + + if(!flipper_format_read_uint32(file, "BPM", &instance->bpm, 1)) { + FURI_LOG_E(TAG, "BPM is missing"); + break; + } + if(!flipper_format_read_uint32(file, "Duration", &instance->duration, 1)) { + FURI_LOG_E(TAG, "Duration is missing"); + break; + } + if(!flipper_format_read_uint32(file, "Octave", &instance->octave, 1)) { + FURI_LOG_E(TAG, "Octave is missing"); + break; + } + + if(!flipper_format_read_string(file, "Notes", temp_str)) { + FURI_LOG_E(TAG, "Notes is missing"); + break; + } + + if(!music_player_worker_parse_notes(instance, string_get_cstr(temp_str))) { + break; + } + + result = true; + } while(false); + + furi_record_close("storage"); + flipper_format_free(file); + string_clear(temp_str); + + return result; +} + +bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path) { + furi_assert(instance); + furi_assert(file_path); + + bool result = false; + string_t content; + string_init(content); + Storage* storage = furi_record_open("storage"); + File* file = storage_file_alloc(storage); + + do { + if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E(TAG, "Unable to open file"); + break; + }; + + uint16_t ret = 0; + do { + uint8_t buffer[65] = {0}; + ret = storage_file_read(file, buffer, sizeof(buffer) - 1); + for(size_t i = 0; i < ret; i++) { + string_push_back(content, buffer[i]); + } + } while(ret > 0); + + string_strim(content); + if(!string_size(content)) { + FURI_LOG_E(TAG, "Empty file"); + break; + } + + if(!music_player_worker_load_rtttl_from_string(instance, string_get_cstr(content))) { + FURI_LOG_E(TAG, "Invalid file content"); + break; + } + + result = true; + } while(0); + + storage_file_free(file); + furi_record_close("storage"); + string_clear(content); + + return result; +} + +bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string) { + furi_assert(instance); + + const char* cursor = string; + + // Skip name + cursor += skip_till(cursor, ':'); + if(*cursor != ':') { + return false; + } + + // Duration + cursor += skip_till(cursor, '='); + if(*cursor != '=') { + return false; + } + cursor++; + cursor += extract_number(cursor, &instance->duration); + + // Octave + cursor += skip_till(cursor, '='); + if(*cursor != '=') { + return false; + } + cursor++; + cursor += extract_number(cursor, &instance->octave); + + // BPM + cursor += skip_till(cursor, '='); + if(*cursor != '=') { + return false; + } + cursor++; + cursor += extract_number(cursor, &instance->bpm); + + // Notes + cursor += skip_till(cursor, ':'); + if(*cursor != ':') { + return false; + } + cursor++; + if(!music_player_worker_parse_notes(instance, cursor)) { + return false; + } + + return true; +} + +void music_player_worker_set_callback( + MusicPlayerWorker* instance, + MusicPlayerWorkerCallback callback, + void* context) { + furi_assert(instance); + instance->callback = callback; + instance->callback_context = context; +} + +void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume) { + furi_assert(instance); + instance->volume = volume; +} + +void music_player_worker_start(MusicPlayerWorker* instance) { + furi_assert(instance); + furi_assert(instance->should_work == false); + + instance->should_work = true; + furi_thread_start(instance->thread); +} + +void music_player_worker_stop(MusicPlayerWorker* instance) { + furi_assert(instance); + furi_assert(instance->should_work == true); + + instance->should_work = false; + furi_thread_join(instance->thread); +} diff --git a/applications/music_player/music_player_worker.h b/applications/music_player/music_player_worker.h new file mode 100644 index 00000000..3aa99ea3 --- /dev/null +++ b/applications/music_player/music_player_worker.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +typedef void (*MusicPlayerWorkerCallback)( + uint8_t semitone, + uint8_t dots, + uint8_t duration, + float position, + void* context); + +typedef struct MusicPlayerWorker MusicPlayerWorker; + +MusicPlayerWorker* music_player_worker_alloc(); + +void music_player_worker_free(MusicPlayerWorker* instance); + +bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path); + +bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path); + +bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path); + +bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string); + +void music_player_worker_set_callback( + MusicPlayerWorker* instance, + MusicPlayerWorkerCallback callback, + void* context); + +void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume); + +void music_player_worker_start(MusicPlayerWorker* instance); + +void music_player_worker_stop(MusicPlayerWorker* instance); diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h index bab7c0aa..5de44001 100644 --- a/applications/nfc/helpers/nfc_custom_event.h +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -9,4 +9,4 @@ enum NfcCustomEvent { NfcCustomEventByteInputDone, NfcCustomEventTextInputDone, NfcCustomEventDictAttackDone, -}; \ No newline at end of file +}; diff --git a/applications/nfc/nfc_cli.c b/applications/nfc/nfc_cli.c index 52c971ef..9b77a29f 100755 --- a/applications/nfc/nfc_cli.c +++ b/applications/nfc/nfc_cli.c @@ -17,6 +17,7 @@ static void nfc_cli_print_usage() { } static void nfc_cli_detect(Cli* cli, string_t args) { + UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); @@ -45,6 +46,7 @@ static void nfc_cli_detect(Cli* cli, string_t args) { } static void nfc_cli_emulate(Cli* cli, string_t args) { + UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); @@ -74,6 +76,7 @@ static void nfc_cli_emulate(Cli* cli, string_t args) { } static void nfc_cli_field(Cli* cli, string_t args) { + UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); @@ -95,6 +98,7 @@ static void nfc_cli_field(Cli* cli, string_t args) { } static void nfc_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index 6b769803..9970cbfe 100644 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -373,7 +373,7 @@ bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication if(!flipper_format_read_hex(file, string_get_cstr(key), tmp, n_files)) break; MifareDesfireFile** file_head = &app->file_head; bool parsed_files = true; - for(int i = 0; i < n_files; i++) { + for(uint32_t i = 0; i < n_files; i++) { parsed_files = false; f = malloc(sizeof(MifareDesfireFile)); memset(f, 0, sizeof(MifareDesfireFile)); @@ -528,7 +528,7 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break; bool parsed_apps = true; MifareDesfireApplication** app_head = &data->app_head; - for(int i = 0; i < n_apps; i++) { + for(uint32_t i = 0; i < n_apps; i++) { MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication)); memset(app, 0, sizeof(MifareDesfireApplication)); memcpy(app->id, &tmp[i * 3], 3); @@ -764,7 +764,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { uint32_t data_cnt = 0; string_t temp_str; string_init(temp_str); - bool depricated_version = false; + bool deprecated_version = false; do { // Check existance of shadow file @@ -783,7 +783,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) { - depricated_version = true; + deprecated_version = true; break; } // Read Nfc device type @@ -810,8 +810,8 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { } while(false); if(!parsed) { - if(depricated_version) { - dialog_message_show_storage_error(dev->dialogs, "File format depricated"); + if(deprecated_version) { + dialog_message_show_storage_error(dev->dialogs, "File format deprecated"); } else { dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile"); } diff --git a/applications/nfc/scenes/nfc_scene_delete_success.c b/applications/nfc/scenes/nfc_scene_delete_success.c index a52c40d8..547aeab7 100755 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/nfc/scenes/nfc_scene_delete_success.c @@ -37,4 +37,4 @@ void nfc_scene_delete_success_on_exit(void* context) { // Clear view popup_reset(nfc->popup); -} \ No newline at end of file +} diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 10851e86..03464c66 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -21,6 +21,7 @@ void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) } void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) { + UNUSED(result); Nfc* nfc = context; if(type == InputTypeShort) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); diff --git a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c index 871ca636..eda7637c 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c @@ -5,6 +5,7 @@ #define NFC_MF_UL_DATA_CHANGED (1UL) void nfc_emulate_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; scene_manager_set_scene_state( diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index 58ac138e..e67b7274 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -9,6 +9,7 @@ enum { }; void nfc_emulate_uid_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); furi_assert(context); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); diff --git a/applications/nfc/scenes/nfc_scene_field.c b/applications/nfc/scenes/nfc_scene_field.c index 31cf74b8..e3eb6a70 100644 --- a/applications/nfc/scenes/nfc_scene_field.c +++ b/applications/nfc/scenes/nfc_scene_field.c @@ -19,6 +19,8 @@ void nfc_scene_field_on_enter(void* context) { } bool nfc_scene_field_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); return false; } diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c index a8126456..36614bb8 100755 --- a/applications/nfc/scenes/nfc_scene_file_select.c +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -11,8 +11,11 @@ void nfc_scene_file_select_on_enter(void* context) { } bool nfc_scene_file_select_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); return false; } void nfc_scene_file_select_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c b/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c index 0974c062..fdfbd2ec 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c +++ b/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c @@ -11,7 +11,7 @@ MifareDesfireApplication* nfc_scene_mifare_desfire_app_get_app(Nfc* nfc) { uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp) >> 1; MifareDesfireApplication* app = nfc->dev->dev_data.mf_df_data.app_head; - for(int i = 0; i < app_idx && app; i++) { + for(uint32_t i = 0; i < app_idx && app; i++) { app = app->next; } return app; diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c index 4d151c08..645b8deb 100755 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ b/applications/nfc/scenes/nfc_scene_read_card.c @@ -2,6 +2,7 @@ #include void nfc_read_card_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app.c b/applications/nfc/scenes/nfc_scene_read_emv_app.c index f0192cb9..4a64622d 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app.c @@ -2,6 +2,7 @@ #include void nfc_read_emv_app_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c index b72c873e..85df4121 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data.c @@ -2,6 +2,7 @@ #include void nfc_read_emv_data_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c b/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c index ebd7289b..f14f81ba 100644 --- a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c @@ -2,6 +2,7 @@ #include void nfc_read_mifare_desfire_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c index 8903e2c4..659e08fb 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c @@ -2,6 +2,7 @@ #include void nfc_read_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } diff --git a/applications/notification/notification_app.c b/applications/notification/notification_app.c index 4db12bbf..7db4986d 100644 --- a/applications/notification/notification_app.c +++ b/applications/notification/notification_app.c @@ -298,7 +298,6 @@ void notification_process_notification_message( need_minimal_delay = true; } - led_active = false; notification_apply_notification_leds(app, led_values); reset_mask |= reset_red_mask; reset_mask |= reset_green_mask; @@ -489,6 +488,7 @@ static NotificationApp* notification_app_alloc() { // App int32_t notification_srv(void* p) { + UNUSED(p); NotificationApp* app = notification_app_alloc(); if(!notification_load_settings(app)) { diff --git a/applications/notification/notification_app_api.c b/applications/notification/notification_app_api.c index ed39b7d6..d11a289b 100644 --- a/applications/notification/notification_app_api.c +++ b/applications/notification/notification_app_api.c @@ -34,4 +34,4 @@ void notification_internal_message_block( furi_check(osMessageQueuePut(app->queue, &m, 0, osWaitForever) == osOK); osEventFlagsWait(m.back_event, NOTIFICATION_EVENT_COMPLETE, osFlagsWaitAny, osWaitForever); osEventFlagsDelete(m.back_event); -}; \ No newline at end of file +}; diff --git a/applications/notification/notification_settings_app.c b/applications/notification/notification_settings_app.c index eef14ebf..bcb1b6a2 100644 --- a/applications/notification/notification_settings_app.c +++ b/applications/notification/notification_settings_app.c @@ -120,6 +120,7 @@ static void vibro_changed(VariableItem* item) { } static uint32_t notification_app_settings_exit(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -189,6 +190,7 @@ static void free_settings(NotificationAppSettings* app) { } int32_t notification_settings_app(void* p) { + UNUSED(p); NotificationAppSettings* app = alloc_settings(); view_dispatcher_run(app->view_dispatcher); notification_message_save_settings(app->notification); diff --git a/applications/power/battery_test_app/battery_test_app.c b/applications/power/battery_test_app/battery_test_app.c index 1588a525..f24de32b 100755 --- a/applications/power/battery_test_app/battery_test_app.c +++ b/applications/power/battery_test_app/battery_test_app.c @@ -89,6 +89,7 @@ void battery_test_free(BatteryTestApp* app) { } int32_t battery_test_app(void* p) { + UNUSED(p); BatteryTestApp* app = battery_test_alloc(); // Disable battery low level notification power_enable_low_battery_level_notification(app->power, false); diff --git a/applications/power/power_cli.c b/applications/power/power_cli.c index 09e75fa9..d474a729 100644 --- a/applications/power/power_cli.c +++ b/applications/power/power_cli.c @@ -6,6 +6,8 @@ #include void power_cli_off(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); Power* power = furi_record_open("power"); printf("It's now safe to disconnect USB from your flipper\r\n"); osDelay(666); @@ -13,26 +15,37 @@ void power_cli_off(Cli* cli, string_t args) { } void power_cli_reboot(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); power_reboot(PowerBootModeNormal); } void power_cli_reboot2dfu(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); power_reboot(PowerBootModeDfu); } static void power_cli_info_callback(const char* key, const char* value, bool last, void* context) { + UNUSED(last); + UNUSED(context); printf("%-24s: %s\r\n", key, value); } void power_cli_info(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); furi_hal_power_info_get(power_cli_info_callback, NULL); } void power_cli_debug(Cli* cli, string_t args) { + UNUSED(cli); + UNUSED(args); furi_hal_power_dump_state(); } void power_cli_5v(Cli* cli, string_t args) { + UNUSED(cli); if(!string_cmp(args, "0")) { furi_hal_power_disable_otg(); } else if(!string_cmp(args, "1")) { @@ -43,6 +56,7 @@ void power_cli_5v(Cli* cli, string_t args) { } void power_cli_3v3(Cli* cli, string_t args) { + UNUSED(cli); if(!string_cmp(args, "0")) { furi_hal_power_disable_external_3_3v(); } else if(!string_cmp(args, "1")) { @@ -69,6 +83,7 @@ static void power_cli_command_print_usage() { } void power_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_init(cmd); diff --git a/applications/power/power_service/power.c b/applications/power/power_service/power.c index 5f7eeb84..ac1856e7 100644 --- a/applications/power/power_service/power.c +++ b/applications/power/power_service/power.c @@ -11,20 +11,21 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { furi_assert(context); Power* power = context; - canvas_draw_icon(canvas, 0, 1, &I_Battery_26x8); + canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8); if(power->info.gauge_is_ok) { - canvas_draw_box(canvas, 2, 3, (power->info.charge + 4) / 5, 4); + canvas_draw_box(canvas, 2, 2, (power->info.charge + 4) / 5, 4); if(power->state == PowerStateCharging) { canvas_set_bitmap_mode(canvas, 1); canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, 8, 0, &I_Charging_lightning_mask_9x10); + // TODO: replace -1 magic for uint8_t with re-framing + canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_mask_9x10); canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 8, 0, &I_Charging_lightning_9x10); + canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_9x10); canvas_set_bitmap_mode(canvas, 0); } } else { - canvas_draw_box(canvas, 8, 4, 8, 2); + canvas_draw_box(canvas, 8, 3, 8, 2); } } diff --git a/applications/power/power_service/power_api.c b/applications/power/power_service/power_api.c index b290cb83..865c21c8 100644 --- a/applications/power/power_service/power_api.c +++ b/applications/power/power_service/power_api.c @@ -2,6 +2,7 @@ #include #include +#include void power_off(Power* power) { furi_hal_power_off(); @@ -14,7 +15,7 @@ void power_off(Power* power) { void power_reboot(PowerBootMode mode) { if(mode == PowerBootModeNormal) { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); + update_operation_disarm(); } else if(mode == PowerBootModeDfu) { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeDfu); } else if(mode == PowerBootModeUpdateStart) { diff --git a/applications/power/power_settings_app/power_settings_app.c b/applications/power/power_settings_app/power_settings_app.c index 1e87e7d6..822c51bc 100755 --- a/applications/power/power_settings_app/power_settings_app.c +++ b/applications/power/power_settings_app/power_settings_app.c @@ -75,6 +75,7 @@ void power_settings_app_free(PowerSettingsApp* app) { } int32_t power_settings_app(void* p) { + UNUSED(p); PowerSettingsApp* app = power_settings_app_alloc(); view_dispatcher_run(app->view_dispatcher); power_settings_app_free(app); diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c b/applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c index 4dd04f8c..0085c31d 100755 --- a/applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c @@ -31,4 +31,5 @@ bool power_settings_scene_battery_info_on_event(void* context, SceneManagerEvent } void power_settings_scene_battery_info_on_exit(void* context) { + UNUSED(context); } diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c b/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c index 8edc8138..2d879612 100755 --- a/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c @@ -33,6 +33,7 @@ void power_settings_scene_reboot_on_enter(void* context) { } bool power_settings_scene_reboot_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { diff --git a/applications/rpc/rpc.c b/applications/rpc/rpc.c index efd5ed87..7d51defd 100644 --- a/applications/rpc/rpc.c +++ b/applications/rpc/rpc.c @@ -102,7 +102,7 @@ static size_t rpc_sprintf_msg_file( size_t msg_files_size) { size_t cnt = 0; - for(int i = 0; i < msg_files_size; ++i, ++msg_file) { + for(size_t i = 0; i < msg_files_size; ++i, ++msg_file) { string_cat_printf( str, "%s[%c] size: %5ld", @@ -136,7 +136,7 @@ void rpc_print_data(const char* prefix, uint8_t* buffer, size_t size) { string_reserve(str, 100 + size * 5); string_cat_printf(str, "\r\n%s DEC(%d): {", prefix, size); - for(int i = 0; i < size; ++i) { + for(size_t i = 0; i < size; ++i) { string_cat_printf(str, "%d, ", buffer[i]); } string_cat_printf(str, "}\r\n"); @@ -146,7 +146,7 @@ void rpc_print_data(const char* prefix, uint8_t* buffer, size_t size) { string_reserve(str, 100 + size * 3); string_cat_printf(str, "%s HEX(%d): {", prefix, size); - for(int i = 0; i < size; ++i) { + for(size_t i = 0; i < size; ++i) { string_cat_printf(str, "%02X", buffer[i]); } string_cat_printf(str, "}\r\n\r\n"); @@ -573,7 +573,7 @@ static void rpc_session_free_callback(FuriThreadState thread_state, void* contex RpcSession* session = (RpcSession*)context; if(thread_state == FuriThreadStateStopped) { - for(int i = 0; i < COUNT_OF(rpc_systems); ++i) { + for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) { if(rpc_systems[i].free) { rpc_systems[i].free(session->system_contexts[i]); } @@ -611,7 +611,7 @@ RpcSession* rpc_session_open(Rpc* rpc) { session->decoded_message->cb_content.arg = session; session->system_contexts = malloc(COUNT_OF(rpc_systems) * sizeof(void*)); - for(int i = 0; i < COUNT_OF(rpc_systems); ++i) { + for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) { session->system_contexts[i] = rpc_systems[i].alloc(session); } @@ -647,6 +647,7 @@ void rpc_session_close(RpcSession* session) { } int32_t rpc_srv(void* p) { + UNUSED(p); Rpc* rpc = malloc(sizeof(Rpc)); rpc->busy_mutex = osMutexNew(NULL); diff --git a/applications/rpc/rpc_cli.c b/applications/rpc/rpc_cli.c index b9304367..1c8991bc 100644 --- a/applications/rpc/rpc_cli.c +++ b/applications/rpc/rpc_cli.c @@ -38,6 +38,7 @@ static void rpc_session_terminated_callback(void* context) { } void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) { + UNUSED(args); Rpc* rpc = context; uint32_t mem_before = memmgr_get_free_heap(); diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index a21fec8e..e6a59ea8 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -31,8 +31,6 @@ typedef struct { uint32_t current_command_id; } RpcStorageSystem; -void rpc_print_message(const PB_Main* message); - static void rpc_system_storage_reset_state( RpcStorageSystem* rpc_storage, RpcSession* session, diff --git a/applications/rpc/rpc_system.c b/applications/rpc/rpc_system.c index 9ce7e34a..45ae2e5a 100644 --- a/applications/rpc/rpc_system.c +++ b/applications/rpc/rpc_system.c @@ -275,15 +275,22 @@ static void rpc_system_system_update_request_process(const PB_Main* request, voi RpcSession* session = (RpcSession*)context; furi_assert(session); - bool update_prepare_result = - update_operation_prepare(request->content.system_update_request.update_manifest) == - UpdatePrepareResultOK; + UpdatePrepareResult update_prepare_result = + update_operation_prepare(request->content.system_update_request.update_manifest); + /* RPC enum does not have such entry; setting to closest one */ + if(update_prepare_result == UpdatePrepareResultOutdatedManifestVersion) { + update_prepare_result = UpdatePrepareResultManifestInvalid; + } PB_Main* response = malloc(sizeof(PB_Main)); response->command_id = request->command_id; response->has_next = false; - response->command_status = update_prepare_result ? PB_CommandStatus_OK : - PB_CommandStatus_ERROR_INVALID_PARAMETERS; + response->command_status = (update_prepare_result == UpdatePrepareResultOK) ? + PB_CommandStatus_OK : + PB_CommandStatus_ERROR_INVALID_PARAMETERS; + response->which_content = PB_Main_system_update_response_tag; + response->content.system_update_response.code = + (PB_System_UpdateResponse_UpdateResultCode)update_prepare_result; rpc_send_and_release(session, response); free(response); } diff --git a/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp b/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp index 6d618748..200252ad 100644 --- a/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp +++ b/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp @@ -1,6 +1,6 @@ #include "scened_app_scene_byte_input.h" -void ScenedAppSceneByteInput::on_enter(ScenedApp* app, bool need_restore) { +void ScenedAppSceneByteInput::on_enter(ScenedApp* app, bool /* need_restore */) { ByteInputVM* byte_input = app->view_controller; auto callback = cbc::obtain_connector(this, &ScenedAppSceneByteInput::result_callback); diff --git a/applications/scened_app_example/scene/scened_app_scene_byte_input.h b/applications/scened_app_example/scene/scened_app_scene_byte_input.h index 12daf310..0f0b02ac 100644 --- a/applications/scened_app_example/scene/scened_app_scene_byte_input.h +++ b/applications/scened_app_example/scene/scened_app_scene_byte_input.h @@ -16,4 +16,4 @@ private: 0xF4, 0xD3, }; -}; \ No newline at end of file +}; diff --git a/applications/scened_app_example/scene/scened_app_scene_start.h b/applications/scened_app_example/scene/scened_app_scene_start.h index 19e1b78d..8324a20f 100644 --- a/applications/scened_app_example/scene/scened_app_scene_start.h +++ b/applications/scened_app_example/scene/scened_app_scene_start.h @@ -10,4 +10,4 @@ public: private: void submenu_callback(void* context, uint32_t index); uint32_t submenu_item_selected = 0; -}; \ No newline at end of file +}; diff --git a/applications/scened_app_example/scened_app.cpp b/applications/scened_app_example/scened_app.cpp index e658d6d0..64040b22 100644 --- a/applications/scened_app_example/scened_app.cpp +++ b/applications/scened_app_example/scened_app.cpp @@ -17,4 +17,4 @@ void ScenedApp::run() { notification_message(notification, &sequence_blink_green_10); scene_controller.process(100); -} \ No newline at end of file +} diff --git a/applications/scened_app_example/scened_app_launcher.cpp b/applications/scened_app_example/scened_app_launcher.cpp index 1664b87d..3d0bdfca 100644 --- a/applications/scened_app_example/scened_app_launcher.cpp +++ b/applications/scened_app_example/scened_app_launcher.cpp @@ -2,6 +2,7 @@ // app enter function extern "C" int32_t scened_app(void* p) { + UNUSED(p); ScenedApp* app = new ScenedApp(); app->run(); delete app; diff --git a/applications/snake_game/snake_game.c b/applications/snake_game/snake_game.c index 2bc0a6a3..bb9e207d 100644 --- a/applications/snake_game/snake_game.c +++ b/applications/snake_game/snake_game.c @@ -313,6 +313,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { } int32_t snake_game_app(void* p) { + UNUSED(p); srand(DWT->CYCCNT); osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(SnakeEvent), NULL); diff --git a/applications/storage/filesystem_api.c b/applications/storage/filesystem_api.c index 42a10c6b..b979967a 100644 --- a/applications/storage/filesystem_api.c +++ b/applications/storage/filesystem_api.c @@ -35,4 +35,4 @@ const char* filesystem_api_error_get_desc(FS_Error error_id) { break; } return result; -} \ No newline at end of file +} diff --git a/applications/storage/filesystem_api_defines.h b/applications/storage/filesystem_api_defines.h index cc33de26..b6f1d8f1 100644 --- a/applications/storage/filesystem_api_defines.h +++ b/applications/storage/filesystem_api_defines.h @@ -57,4 +57,4 @@ const char* filesystem_api_error_get_desc(FS_Error error_id); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage.c b/applications/storage/storage.c index 078a136c..b280547b 100644 --- a/applications/storage/storage.c +++ b/applications/storage/storage.c @@ -100,6 +100,7 @@ void storage_tick(Storage* app) { } int32_t storage_srv(void* p) { + UNUSED(p); Storage* app = storage_app_alloc(); furi_record_create("storage", app); diff --git a/applications/storage/storage.h b/applications/storage/storage.h index eb51adef..1e6ced23 100644 --- a/applications/storage/storage.h +++ b/applications/storage/storage.h @@ -282,7 +282,7 @@ FS_Error storage_int_restore(Storage* api, const char* dstname); /***************** Simplified Functions ******************/ /** - * Removes a file/directory from the repository, the directory must be empty and the file/directory must not be open + * Removes a file/directory, the directory must be empty and the file/directory must not be open * @param storage pointer to the api * @param path * @return true on success or if file/dir is not exist @@ -290,7 +290,7 @@ FS_Error storage_int_restore(Storage* api, const char* dstname); bool storage_simply_remove(Storage* storage, const char* path); /** - * Removes a file/directory from the repository, the directory can be not empty + * Recursively removes a file/directory, the directory can be not empty * @param storage pointer to the api * @param path * @return true on success or if file/dir is not exist @@ -325,4 +325,4 @@ void storage_get_next_filename( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage_cli.c b/applications/storage/storage_cli.c index 3cb345bd..b35e37a8 100644 --- a/applications/storage/storage_cli.c +++ b/applications/storage/storage_cli.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ static void storage_cli_print_usage() { printf("\tinfo\t - get FS info\r\n"); printf("\tformat\t - format filesystem\r\n"); printf("\tlist\t - list files and dirs\r\n"); + printf("\ttree\t - list files and dirs, recursive\r\n"); printf("\tremove\t - delete the file or directory\r\n"); printf("\tread\t - read text from file and print file size and content to cli\r\n"); printf( @@ -37,6 +39,7 @@ static void storage_cli_print_error(FS_Error error) { } static void storage_cli_info(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); if(string_cmp_str(path, "/int") == 0) { @@ -101,6 +104,7 @@ static void storage_cli_format(Cli* cli, string_t path) { }; static void storage_cli_list(Cli* cli, string_t path) { + UNUSED(cli); if(string_cmp_str(path, "/") == 0) { printf("\t[D] int\r\n"); printf("\t[D] ext\r\n"); @@ -136,7 +140,46 @@ static void storage_cli_list(Cli* cli, string_t path) { } } +static void storage_cli_tree(Cli* cli, string_t path) { + if(string_cmp_str(path, "/") == 0) { + string_set(path, "/int"); + storage_cli_tree(cli, path); + string_set(path, "/ext"); + storage_cli_tree(cli, path); + } else { + Storage* api = furi_record_open("storage"); + DirWalk* dir_walk = dir_walk_alloc(api); + string_t name; + string_init(name); + + if(dir_walk_open(dir_walk, string_get_cstr(path))) { + FileInfo fileinfo; + bool read_done = false; + + while(dir_walk_read(dir_walk, name, &fileinfo) == DirWalkOK) { + read_done = true; + if(fileinfo.flags & FSF_DIRECTORY) { + printf("\t[D] %s\r\n", string_get_cstr(name)); + } else { + printf("\t[F] %s %lub\r\n", string_get_cstr(name), (uint32_t)(fileinfo.size)); + } + } + + if(!read_done) { + printf("\tEmpty\r\n"); + } + } else { + storage_cli_print_error(dir_walk_get_error(dir_walk)); + } + + string_clear(name); + dir_walk_free(dir_walk); + furi_record_close("storage"); + } +} + static void storage_cli_read(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); File* file = storage_file_alloc(api); @@ -295,6 +338,7 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) { } static void storage_cli_stat(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); if(string_cmp_str(path, "/") == 0) { @@ -334,6 +378,7 @@ static void storage_cli_stat(Cli* cli, string_t path) { } static void storage_cli_copy(Cli* cli, string_t old_path, string_t args) { + UNUSED(cli); Storage* api = furi_record_open("storage"); string_t new_path; string_init(new_path); @@ -354,6 +399,7 @@ static void storage_cli_copy(Cli* cli, string_t old_path, string_t args) { } static void storage_cli_remove(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); FS_Error error = storage_common_remove(api, string_get_cstr(path)); @@ -365,6 +411,7 @@ static void storage_cli_remove(Cli* cli, string_t path) { } static void storage_cli_rename(Cli* cli, string_t old_path, string_t args) { + UNUSED(cli); Storage* api = furi_record_open("storage"); string_t new_path; string_init(new_path); @@ -385,6 +432,7 @@ static void storage_cli_rename(Cli* cli, string_t old_path, string_t args) { } static void storage_cli_mkdir(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); FS_Error error = storage_common_mkdir(api, string_get_cstr(path)); @@ -396,6 +444,7 @@ static void storage_cli_mkdir(Cli* cli, string_t path) { } static void storage_cli_md5(Cli* cli, string_t path) { + UNUSED(cli); Storage* api = furi_record_open("storage"); File* file = storage_file_alloc(api); @@ -433,6 +482,7 @@ static void storage_cli_md5(Cli* cli, string_t path) { } void storage_cli(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t cmd; string_t path; string_init(cmd); @@ -464,6 +514,11 @@ void storage_cli(Cli* cli, string_t args, void* context) { break; } + if(string_cmp_str(cmd, "tree") == 0) { + storage_cli_tree(cli, path); + break; + } + if(string_cmp_str(cmd, "read") == 0) { storage_cli_read(cli, path); break; @@ -522,6 +577,8 @@ void storage_cli(Cli* cli, string_t args, void* context) { } static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) { + UNUSED(args); + UNUSED(context); printf("All data will be lost. Are you sure (y/n)?\r\n"); char c = cli_getc(cli); if(c == 'y' || c == 'Y') { diff --git a/applications/storage/storage_external_api.c b/applications/storage/storage_external_api.c index 1335c708..7f600af2 100644 --- a/applications/storage/storage_external_api.c +++ b/applications/storage/storage_external_api.c @@ -4,6 +4,7 @@ #include "storage_i.h" #include "storage_message.h" #include +#include #define MAX_NAME_LENGTH 256 @@ -332,12 +333,69 @@ FS_Error storage_common_remove(Storage* storage, const char* path) { FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) { FS_Error error = storage_common_copy(storage, old_path, new_path); if(error == FSE_OK) { - error = storage_common_remove(storage, old_path); + if(storage_simply_remove_recursive(storage, old_path)) { + error = FSE_OK; + } else { + error = FSE_INTERNAL; + } } return error; } +static FS_Error + storage_copy_recursive(Storage* storage, const char* old_path, const char* new_path) { + FS_Error error = storage_common_mkdir(storage, new_path); + DirWalk* dir_walk = dir_walk_alloc(storage); + string_t path; + string_t tmp_new_path; + string_t tmp_old_path; + FileInfo fileinfo; + string_init(path); + string_init(tmp_new_path); + string_init(tmp_old_path); + + do { + if(error != FSE_OK) break; + + if(!dir_walk_open(dir_walk, old_path)) { + error = dir_walk_get_error(dir_walk); + break; + } + + while(1) { + DirWalkResult res = dir_walk_read(dir_walk, path, &fileinfo); + + if(res == DirWalkError) { + error = dir_walk_get_error(dir_walk); + break; + } else if(res == DirWalkLast) { + break; + } else { + string_set(tmp_old_path, path); + string_right(path, strlen(old_path)); + string_printf(tmp_new_path, "%s%s", new_path, string_get_cstr(path)); + + if(fileinfo.flags & FSF_DIRECTORY) { + error = storage_common_mkdir(storage, string_get_cstr(tmp_new_path)); + } else { + error = storage_common_copy( + storage, string_get_cstr(tmp_old_path), string_get_cstr(tmp_new_path)); + } + + if(error != FSE_OK) break; + } + } + + } while(false); + + string_clear(tmp_new_path); + string_clear(tmp_old_path); + string_clear(path); + dir_walk_free(dir_walk); + return error; +} + FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* new_path) { FS_Error error; @@ -346,7 +404,7 @@ FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* if(error == FSE_OK) { if(fileinfo.flags & FSF_DIRECTORY) { - error = storage_common_mkdir(storage, new_path); + error = storage_copy_recursive(storage, old_path, new_path); } else { Stream* stream_from = file_stream_alloc(storage); Stream* stream_to = file_stream_alloc(storage); diff --git a/applications/storage/storage_glue.h b/applications/storage/storage_glue.h index 21147dce..0d50e39b 100644 --- a/applications/storage/storage_glue.h +++ b/applications/storage/storage_glue.h @@ -72,4 +72,4 @@ bool storage_pop_storage_file(File* file, StorageData* storage); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage_internal_api.c b/applications/storage/storage_internal_api.c index 754ae0dd..ee49d672 100644 --- a/applications/storage/storage_internal_api.c +++ b/applications/storage/storage_internal_api.c @@ -19,4 +19,4 @@ FS_Error storage_int_restore(Storage* api, const char* srcname) { tar_archive_unpack_to(archive, INT_PATH); tar_archive_free(archive); return success ? FSE_OK : FSE_INTERNAL; -} \ No newline at end of file +} diff --git a/applications/storage/storage_message.h b/applications/storage/storage_message.h index 0e58fff2..f3aeaf32 100644 --- a/applications/storage/storage_message.h +++ b/applications/storage/storage_message.h @@ -131,4 +131,4 @@ typedef struct { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage_processing.c b/applications/storage/storage_processing.c index 6120a345..30e6b5e7 100644 --- a/applications/storage/storage_processing.c +++ b/applications/storage/storage_processing.c @@ -40,7 +40,7 @@ static StorageData* get_storage_by_file(File* file, StorageData* storages) { } static const char* remove_vfs(const char* path) { - return path + MIN(4, strlen(path)); + return path + MIN(4u, strlen(path)); } static const char* ext_path = "/ext"; diff --git a/applications/storage/storage_processing.h b/applications/storage/storage_processing.h index fe2cd1a6..bb779c7a 100644 --- a/applications/storage/storage_processing.h +++ b/applications/storage/storage_processing.h @@ -13,4 +13,4 @@ void storage_process_message(Storage* app, StorageMessage* message); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage_sd_api.c b/applications/storage/storage_sd_api.c index 78064624..9e9ca45c 100644 --- a/applications/storage/storage_sd_api.c +++ b/applications/storage/storage_sd_api.c @@ -18,4 +18,4 @@ const char* sd_api_get_fs_type_text(SDFsType fs_type) { return "UNKNOWN"; break; } -} \ No newline at end of file +} diff --git a/applications/storage/storage_sd_api.h b/applications/storage/storage_sd_api.h index 2db35866..f8336095 100644 --- a/applications/storage/storage_sd_api.h +++ b/applications/storage/storage_sd_api.h @@ -30,4 +30,4 @@ const char* sd_api_get_fs_type_text(SDFsType fs_type); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storage_test_app.c b/applications/storage/storage_test_app.c index 096276ad..f11d2d72 100644 --- a/applications/storage/storage_test_app.c +++ b/applications/storage/storage_test_app.c @@ -316,6 +316,7 @@ static void do_test_end(Storage* api, const char* path) { } int32_t storage_test_app(void* p) { + UNUSED(p); Storage* api = furi_record_open("storage"); do_test_start(api, "/int"); do_test_start(api, "/any"); diff --git a/applications/storage/storages/sd_notify.c b/applications/storage/storages/sd_notify.c index 8c38ac8e..25ec67c1 100644 --- a/applications/storage/storages/sd_notify.c +++ b/applications/storage/storages/sd_notify.c @@ -79,4 +79,4 @@ void sd_notify_eject(NotificationApp* notifications) { void sd_notify_error(NotificationApp* notifications) { notification_message(notifications, &sd_sequence_error); -} \ No newline at end of file +} diff --git a/applications/storage/storages/sd_notify.h b/applications/storage/storages/sd_notify.h index 49e82edf..f5aefc74 100644 --- a/applications/storage/storages/sd_notify.h +++ b/applications/storage/storages/sd_notify.h @@ -14,4 +14,4 @@ void sd_notify_error(NotificationApp* notifications); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storages/storage_ext.c b/applications/storage/storages/storage_ext.c index bf201d56..49c52f77 100644 --- a/applications/storage/storages/storage_ext.c +++ b/applications/storage/storages/storage_ext.c @@ -113,6 +113,7 @@ FS_Error sd_unmount_card(StorageData* storage) { FS_Error sd_format_card(StorageData* storage) { #ifdef FURI_RAM_EXEC + UNUSED(storage); return FSE_NOT_READY; #else uint8_t* work_area; @@ -349,6 +350,10 @@ static uint16_t static uint16_t storage_ext_file_write(void* ctx, File* file, const void* buff, uint16_t const bytes_to_write) { #ifdef FURI_RAM_EXEC + UNUSED(ctx); + UNUSED(file); + UNUSED(buff); + UNUSED(bytes_to_write); return FSE_NOT_READY; #else StorageData* storage = ctx; @@ -389,6 +394,8 @@ static uint64_t storage_ext_file_tell(void* ctx, File* file) { static bool storage_ext_file_truncate(void* ctx, File* file) { #ifdef FURI_RAM_EXEC + UNUSED(ctx); + UNUSED(file); return FSE_NOT_READY; #else StorageData* storage = ctx; @@ -402,6 +409,8 @@ static bool storage_ext_file_truncate(void* ctx, File* file) { static bool storage_ext_file_sync(void* ctx, File* file) { #ifdef FURI_RAM_EXEC + UNUSED(ctx); + UNUSED(file); return FSE_NOT_READY; #else StorageData* storage = ctx; @@ -497,6 +506,7 @@ static bool storage_ext_dir_rewind(void* ctx, File* file) { /******************* Common FS Functions *******************/ static FS_Error storage_ext_common_stat(void* ctx, const char* path, FileInfo* fileinfo) { + UNUSED(ctx); SDFileInfo _fileinfo; SDError result = f_stat(path, &_fileinfo); @@ -511,7 +521,9 @@ static FS_Error storage_ext_common_stat(void* ctx, const char* path, FileInfo* f } static FS_Error storage_ext_common_remove(void* ctx, const char* path) { + UNUSED(ctx); #ifdef FURI_RAM_EXEC + UNUSED(path); return FSE_NOT_READY; #else SDError result = f_unlink(path); @@ -520,7 +532,9 @@ static FS_Error storage_ext_common_remove(void* ctx, const char* path) { } static FS_Error storage_ext_common_mkdir(void* ctx, const char* path) { + UNUSED(ctx); #ifdef FURI_RAM_EXEC + UNUSED(path); return FSE_NOT_READY; #else SDError result = f_mkdir(path); @@ -533,7 +547,11 @@ static FS_Error storage_ext_common_fs_info( const char* fs_path, uint64_t* total_space, uint64_t* free_space) { + UNUSED(fs_path); #ifdef FURI_RAM_EXEC + UNUSED(ctx); + UNUSED(total_space); + UNUSED(free_space); return FSE_NOT_READY; #else StorageData* storage = ctx; @@ -610,4 +628,4 @@ void storage_ext_init(StorageData* storage) { // do not notify on first launch, notifications app is waiting for our thread to read settings storage_ext_tick_internal(storage, false); -} \ No newline at end of file +} diff --git a/applications/storage/storages/storage_ext.h b/applications/storage/storages/storage_ext.h index fa5a5ab1..07ddbcf2 100644 --- a/applications/storage/storages/storage_ext.h +++ b/applications/storage/storages/storage_ext.h @@ -13,4 +13,4 @@ FS_Error sd_format_card(StorageData* storage); FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage/storages/storage_int.c b/applications/storage/storages/storage_int.c index 7f7dd770..291fb426 100644 --- a/applications/storage/storages/storage_int.c +++ b/applications/storage/storages/storage_int.c @@ -129,6 +129,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc } static int storage_int_device_sync(const struct lfs_config* c) { + UNUSED(c); FURI_LOG_D(TAG, "Device sync: skipping, cause "); return 0; } @@ -648,6 +649,7 @@ static FS_Error storage_int_common_fs_info( const char* fs_path, uint64_t* total_space, uint64_t* free_space) { + UNUSED(fs_path); StorageData* storage = ctx; lfs_t* lfs = lfs_get_from_storage(storage); diff --git a/applications/storage/storages/storage_int.h b/applications/storage/storages/storage_int.h index 40588f68..456d7240 100644 --- a/applications/storage/storages/storage_int.h +++ b/applications/storage/storages/storage_int.h @@ -10,4 +10,4 @@ void storage_int_init(StorageData* storage); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/storage_settings/scenes/storage_settings_scene_config.h b/applications/storage_settings/scenes/storage_settings_scene_config.h index 7628d143..18e7ba5a 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_config.h +++ b/applications/storage_settings/scenes/storage_settings_scene_config.h @@ -6,4 +6,4 @@ ADD_SCENE(storage_settings, formatting, Formatting) ADD_SCENE(storage_settings, sd_info, SDInfo) ADD_SCENE(storage_settings, internal_info, InternalInfo) ADD_SCENE(storage_settings, benchmark, Benchmark) -ADD_SCENE(storage_settings, factory_reset, FactoryReset) \ No newline at end of file +ADD_SCENE(storage_settings, factory_reset, FactoryReset) diff --git a/applications/storage_settings/storage_settings.c b/applications/storage_settings/storage_settings.c index bc982b16..b89fdf06 100644 --- a/applications/storage_settings/storage_settings.c +++ b/applications/storage_settings/storage_settings.c @@ -66,6 +66,7 @@ static void storage_settings_free(StorageSettings* app) { } int32_t storage_settings_app(void* p) { + UNUSED(p); StorageSettings* app = storage_settings_alloc(); view_dispatcher_run(app->view_dispatcher); diff --git a/applications/storage_settings/storage_settings.h b/applications/storage_settings/storage_settings.h index be77a52d..f2d071c4 100644 --- a/applications/storage_settings/storage_settings.h +++ b/applications/storage_settings/storage_settings.h @@ -44,4 +44,4 @@ typedef enum { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c index b6b3a1ed..c0e1fdba 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -44,7 +44,7 @@ static uint32_t subghz_frequency_analyzer_worker_expRunningAverageAdaptive( float k; float newValFloat = newVal; // the sharpness of the filter depends on the absolute value of the difference - if(abs(newValFloat - instance->filVal) > 500000) + if(fabs(newValFloat - instance->filVal) > 500000) k = 0.9; else k = 0.03; @@ -71,6 +71,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_set_frequency(433920000); furi_hal_subghz_flush_rx(); + furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); furi_hal_subghz_rx(); while(instance->worker_running) { diff --git a/applications/subghz/helpers/subghz_testing.h b/applications/subghz/helpers/subghz_testing.h index 3a154966..29ce578a 100644 --- a/applications/subghz/helpers/subghz_testing.h +++ b/applications/subghz/helpers/subghz_testing.h @@ -3,4 +3,4 @@ extern const uint32_t subghz_frequencies_testing[]; extern const uint32_t subghz_frequencies_count_testing; -extern const uint32_t subghz_frequencies_433_92_testing; \ No newline at end of file +extern const uint32_t subghz_frequencies_433_92_testing; diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/subghz/scenes/subghz_scene_config.h index 71cd2668..1cb217ad 100644 --- a/applications/subghz/scenes/subghz_scene_config.h +++ b/applications/subghz/scenes/subghz_scene_config.h @@ -21,4 +21,4 @@ ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) ADD_SCENE(subghz, read_raw, ReadRAW) ADD_SCENE(subghz, more_raw, MoreRAW) ADD_SCENE(subghz, delete_raw, DeleteRAW) -ADD_SCENE(subghz, need_saving, NeedSaving) \ No newline at end of file +ADD_SCENE(subghz, need_saving, NeedSaving) diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 88d0686b..767f0924 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -202,7 +202,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { DOLPHIN_DEED(DolphinDeedSubGhzSend); // set callback end tx subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz->txrx->transmitter->protocol_instance, + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( + subghz->txrx->transmitter), subghz_scene_read_raw_callback_end_tx, subghz); subghz->state_notifications = SubGhzNotificationStateTx; diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index 19242def..01005148 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -60,7 +60,6 @@ static void subghz_scene_add_to_history_callback( if(subghz_history_add_to_history( subghz->txrx->history, decoder_base, subghz->txrx->frequency, subghz->txrx->preset)) { - subghz_receiver_reset(receiver); string_reset(str_buff); subghz->state_notifications = SubGhzNotificationStateRxDone; @@ -75,6 +74,7 @@ static void subghz_scene_add_to_history_callback( subghz_scene_receiver_update_statusbar(subghz); } + subghz_receiver_reset(receiver); string_clear(str_buff); subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; } @@ -191,5 +191,5 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { } void subghz_scene_receiver_on_exit(void* context) { - // SubGhz* subghz = context; + UNUSED(context); } diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index d98f45af..7c2d031f 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -61,6 +61,7 @@ uint8_t subghz_scene_receiver_config_hopper_value_index( uint8_t values_count, void* context) { furi_assert(context); + UNUSED(values_count); SubGhz* subghz = context; if(value == values[0]) { @@ -188,7 +189,8 @@ void subghz_scene_receiver_config_on_enter(void* context) { } bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { - //SubGhz* subghz = context; + UNUSED(context); + UNUSED(event); return false; } diff --git a/applications/subghz/scenes/subghz_scene_saved.c b/applications/subghz/scenes/subghz_scene_saved.c index ae64b797..62ade350 100644 --- a/applications/subghz/scenes/subghz_scene_saved.c +++ b/applications/subghz/scenes/subghz_scene_saved.c @@ -16,10 +16,11 @@ void subghz_scene_saved_on_enter(void* context) { } bool subghz_scene_saved_on_event(void* context, SceneManagerEvent event) { - // SubGhz* subghz = context; + UNUSED(context); + UNUSED(event); return false; } void subghz_scene_saved_on_exit(void* context) { - // SubGhz* subghz = context; + UNUSED(context); } diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index 964b85b2..9dad8cd9 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -268,7 +268,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( - subghz->txrx->transmitter->protocol_instance, + subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), subghz->txrx->fff_data, key & 0x0FFFFFFF, 0x2, @@ -292,7 +292,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( - subghz->txrx->transmitter->protocol_instance, + subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), subghz->txrx->fff_data, key & 0x0FFFFFFF, 0x2, diff --git a/applications/subghz/scenes/subghz_scene_show_only_rx.c b/applications/subghz/scenes/subghz_scene_show_only_rx.c index d5069940..48fa751e 100644 --- a/applications/subghz/scenes/subghz_scene_show_only_rx.c +++ b/applications/subghz/scenes/subghz_scene_show_only_rx.c @@ -26,7 +26,7 @@ void subghz_scene_show_only_rx_on_enter(void* context) { view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdPopup); } -const bool subghz_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) { +bool subghz_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneShowOnlyRX) { diff --git a/applications/subghz/scenes/subghz_scene_test_carrier.c b/applications/subghz/scenes/subghz_scene_test_carrier.c index c6d336ea..9677792b 100644 --- a/applications/subghz/scenes/subghz_scene_test_carrier.c +++ b/applications/subghz/scenes/subghz_scene_test_carrier.c @@ -26,5 +26,5 @@ bool subghz_scene_test_carrier_on_event(void* context, SceneManagerEvent event) } void subghz_scene_test_carrier_on_exit(void* context) { - // SubGhz* subghz = context; + UNUSED(context); } diff --git a/applications/subghz/scenes/subghz_scene_test_packet.c b/applications/subghz/scenes/subghz_scene_test_packet.c index 243dfd55..99f0ab17 100644 --- a/applications/subghz/scenes/subghz_scene_test_packet.c +++ b/applications/subghz/scenes/subghz_scene_test_packet.c @@ -26,5 +26,5 @@ bool subghz_scene_test_packet_on_event(void* context, SceneManagerEvent event) { } void subghz_scene_test_packet_on_exit(void* context) { - // SubGhz* subghz = context; + UNUSED(context); } diff --git a/applications/subghz/scenes/subghz_scene_test_static.c b/applications/subghz/scenes/subghz_scene_test_static.c index 2ca47a08..10e6d02a 100644 --- a/applications/subghz/scenes/subghz_scene_test_static.c +++ b/applications/subghz/scenes/subghz_scene_test_static.c @@ -26,5 +26,5 @@ bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) { } void subghz_scene_test_static_on_exit(void* context) { - // SubGhz* subghz = context; + UNUSED(context); } diff --git a/applications/subghz/subghz.h b/applications/subghz/subghz.h index 16e1e857..54d3017e 100644 --- a/applications/subghz/subghz.h +++ b/applications/subghz/subghz.h @@ -1,3 +1,3 @@ #pragma once -typedef struct SubGhz SubGhz; \ No newline at end of file +typedef struct SubGhz SubGhz; diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 65ea0cf2..f919e1cf 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -20,6 +20,7 @@ "299999755...348000000 or 386999938...464000000 or 778999847...928000000" void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; if(string_size(args)) { @@ -63,6 +64,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { } void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; if(string_size(args)) { @@ -92,7 +94,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - printf("RSSI: %03.1fdbm\r", furi_hal_subghz_get_rssi()); + printf("RSSI: %03.1fdbm\r", (double)furi_hal_subghz_get_rssi()); fflush(stdout); } @@ -103,6 +105,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { } void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; uint32_t key = 0x0074BADE; uint32_t repeat = 10; @@ -218,6 +221,7 @@ static void subghz_cli_command_rx_callback( } void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; if(string_size(args)) { @@ -296,6 +300,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { } void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { + UNUSED(context); string_t file_name; string_init(file_name); string_set(file_name, "/any/subghz/test.sub"); @@ -423,6 +428,7 @@ static void subghz_cli_command_print_usage() { } static void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { + UNUSED(cli); uint8_t iv[16]; string_t source; @@ -465,6 +471,7 @@ static void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { } static void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { + UNUSED(cli); uint8_t iv[16]; string_t source; diff --git a/applications/subghz/views/receiver.c b/applications/subghz/views/receiver.c index 03ba5bd2..7b19cbcf 100644 --- a/applications/subghz/views/receiver.c +++ b/applications/subghz/views/receiver.c @@ -10,7 +10,7 @@ #define FRAME_HEIGHT 12 #define MAX_LEN_PX 100 -#define MENU_ITEMS 4 +#define MENU_ITEMS 4u typedef struct { string_t item_str; @@ -68,12 +68,13 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv size_t history_item = model->history_item; uint16_t bounds = history_item > 3 ? 2 : history_item; - if(history_item > 3 && model->idx >= history_item - 1) { + if(history_item > 3 && model->idx >= (int16_t)(history_item - 1)) { model->list_offset = model->idx - 3; } else if(model->list_offset < model->idx - bounds) { - model->list_offset = CLAMP(model->list_offset + 1, history_item - bounds, 0); + model->list_offset = + CLAMP(model->list_offset + 1, (int16_t)(history_item - bounds), 0); } else if(model->list_offset > model->idx - bounds) { - model->list_offset = CLAMP(model->idx - 1, history_item - bounds, 0); + model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); } return true; }); @@ -157,7 +158,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { SubGhzReceiverMenuItem* item_menu; for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP(i + model->list_offset, model->history_item, 0); + size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx); string_set(str_buff, item_menu->item_str); elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); @@ -218,7 +219,6 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { void subghz_view_receiver_enter(void* context) { furi_assert(context); - //SubGhzViewReceiver* subghz_receiver = context; } void subghz_view_receiver_exit(void* context) { diff --git a/applications/subghz/views/subghz_test_packet.c b/applications/subghz/views/subghz_test_packet.c index fea3bd89..57f85085 100644 --- a/applications/subghz/views/subghz_test_packet.c +++ b/applications/subghz/views/subghz_test_packet.c @@ -57,6 +57,7 @@ static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void* //todo static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) { + UNUSED(parser); furi_assert(context); SubGhzTestPacket* instance = context; instance->packet_rx++; diff --git a/applications/system/system_settings.c b/applications/system/system_settings.c index f06292ec..97017c8d 100644 --- a/applications/system/system_settings.c +++ b/applications/system/system_settings.c @@ -46,6 +46,7 @@ static void debug_changed(VariableItem* item) { } static uint32_t system_settings_exit(void* context) { + UNUSED(context); return VIEW_NONE; } @@ -103,6 +104,7 @@ void system_settings_free(SystemSettings* app) { } int32_t system_settings_app(void* p) { + UNUSED(p); SystemSettings* app = system_settings_alloc(); view_dispatcher_run(app->view_dispatcher); system_settings_free(app); diff --git a/applications/u2f/scenes/u2f_scene_main.c b/applications/u2f/scenes/u2f_scene_main.c index d0957b59..f6264338 100644 --- a/applications/u2f/scenes/u2f_scene_main.c +++ b/applications/u2f/scenes/u2f_scene_main.c @@ -8,6 +8,7 @@ #define U2F_SUCCESS_TIMEOUT 3000 static void u2f_scene_main_ok_callback(InputType type, void* context) { + UNUSED(type); furi_assert(context); U2fApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, U2fCustomEventConfirm); diff --git a/applications/u2f/u2f_app.c b/applications/u2f/u2f_app.c index 8a673dbc..2c3ff562 100644 --- a/applications/u2f/u2f_app.c +++ b/applications/u2f/u2f_app.c @@ -86,6 +86,7 @@ void u2f_app_free(U2fApp* app) { } int32_t u2f_app(void* p) { + UNUSED(p); U2fApp* u2f_app = u2f_app_alloc(); view_dispatcher_run(u2f_app->view_dispatcher); diff --git a/applications/u2f/views/u2f_view.c b/applications/u2f/views/u2f_view.c index d04c656d..11e2c9b0 100644 --- a/applications/u2f/views/u2f_view.c +++ b/applications/u2f/views/u2f_view.c @@ -86,6 +86,7 @@ void u2f_view_set_ok_callback(U2fView* u2f, U2fOkCallback callback, void* contex furi_assert(callback); with_view_model( u2f->view, (U2fModel * model) { + UNUSED(model); u2f->callback = callback; u2f->context = context; return false; diff --git a/applications/unit_tests/flipper_format/flipper_format_string_test.c b/applications/unit_tests/flipper_format/flipper_format_string_test.c index ebc3008f..7158ffd8 100644 --- a/applications/unit_tests/flipper_format/flipper_format_string_test.c +++ b/applications/unit_tests/flipper_format/flipper_format_string_test.c @@ -334,4 +334,4 @@ MU_TEST_SUITE(flipper_format_string_suite) { int run_minunit_test_flipper_format_string() { MU_RUN_SUITE(flipper_format_string_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} diff --git a/applications/unit_tests/furi_pubsub_test.c b/applications/unit_tests/furi_pubsub_test.c index 010a00ab..57c970b8 100644 --- a/applications/unit_tests/furi_pubsub_test.c +++ b/applications/unit_tests/furi_pubsub_test.c @@ -42,4 +42,4 @@ void test_furi_pubsub() { // delete pubsub case furi_pubsub_free(test_pubsub); -} \ No newline at end of file +} diff --git a/applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c b/applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c index ca9120ed..0c3e685d 100644 --- a/applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c +++ b/applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c @@ -55,7 +55,7 @@ static void run_encoder_fill_array( bool level = false; bool level_read; InfraredStatus status = InfraredStatusError; - int i = 0; + size_t i = 0; bool first = true; while(1) { @@ -100,7 +100,7 @@ static void run_encoder( run_encoder_fill_array(encoder_handler, timings, &timings_len, NULL); furi_check(timings_len <= 200); - for(int i = 0; i < timings_len; ++i, ++j) { + for(size_t i = 0; i < timings_len; ++i, ++j) { mu_check(MATCH_TIMING(timings[i], expected_timings[j], 120)); mu_assert(j < expected_timings_len, "encoded more timings than expected"); } @@ -127,7 +127,7 @@ static void furi_check(timings_len <= 200); const InfraredMessage* message_decoded = 0; - for(int i = 0; i < timings_len; ++i) { + for(size_t i = 0; i < timings_len; ++i) { message_decoded = infrared_decode(decoder_handler, level, timings[i]); if((i == timings_len - 2) && level && message_decoded) { /* In case we end with space timing - message can be decoded at last mark */ diff --git a/applications/unit_tests/minunit_vars.h b/applications/unit_tests/minunit_vars.h index 7ef5f825..8289fbe2 100644 --- a/applications/unit_tests/minunit_vars.h +++ b/applications/unit_tests/minunit_vars.h @@ -12,4 +12,4 @@ double minunit_real_timer = 0; double minunit_proc_timer = 0; /* Last message */ -char minunit_last_message[MINUNIT_MESSAGE_LEN]; \ No newline at end of file +char minunit_last_message[MINUNIT_MESSAGE_LEN]; diff --git a/applications/unit_tests/minunit_vars_ex.h b/applications/unit_tests/minunit_vars_ex.h index e2743d1c..7d6a486c 100644 --- a/applications/unit_tests/minunit_vars_ex.h +++ b/applications/unit_tests/minunit_vars_ex.h @@ -12,4 +12,4 @@ extern double minunit_real_timer; extern double minunit_proc_timer; /* Last message */ -extern char minunit_last_message[MINUNIT_MESSAGE_LEN]; \ No newline at end of file +extern char minunit_last_message[MINUNIT_MESSAGE_LEN]; diff --git a/applications/unit_tests/rpc/rpc_test.c b/applications/unit_tests/rpc/rpc_test.c index 2a52ebb0..2f97343e 100644 --- a/applications/unit_tests/rpc/rpc_test.c +++ b/applications/unit_tests/rpc/rpc_test.c @@ -45,7 +45,7 @@ static RpcSessionContext rpc_session[TEST_RPC_SESSIONS]; #define TAG "UnitTestsRpc" #define MAX_RECEIVE_OUTPUT_TIMEOUT 3000 #define MAX_NAME_LENGTH 255 -#define MAX_DATA_SIZE 512 // have to be exact as in rpc_storage.c +#define MAX_DATA_SIZE 512u // have to be exact as in rpc_storage.c #define TEST_DIR TEST_DIR_NAME "/" #define TEST_DIR_NAME "/ext/unit_tests_tmp" #define MD5SUM_SIZE 16 @@ -217,6 +217,8 @@ static void test_rpc_print_message_list(MsgList_t msg_list) { rpc_print_message(msg); } MsgList_reverse(msg_list); +#else + UNUSED(msg_list); #endif } @@ -494,7 +496,7 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { size_t expected_msg_files = expected->content.storage_list_response.file_count; size_t result_msg_files = result->content.storage_list_response.file_count; mu_check(result_msg_files == expected_msg_files); - for(int i = 0; i < expected_msg_files; ++i) { + for(size_t i = 0; i < expected_msg_files; ++i) { PB_Storage_File* result_msg_file = &result->content.storage_list_response.file[i]; PB_Storage_File* expected_msg_file = &expected->content.storage_list_response.file[i]; test_rpc_compare_file(result_msg_file, expected_msg_file); @@ -794,7 +796,7 @@ static void test_create_file(const char* path, size_t size) { if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { uint8_t buf[128] = {0}; - for(int i = 0; i < sizeof(buf); ++i) { + for(size_t i = 0; i < sizeof(buf); ++i) { buf[i] = '0' + (i % 10); } while(size) { @@ -928,7 +930,7 @@ static void test_storage_write_run( MsgList_init(expected_msg_list); uint8_t* buf = malloc(write_size); - for(int i = 0; i < write_size; ++i) { + for(size_t i = 0; i < write_size; ++i) { buf[i] = '0' + (i % 10); } @@ -1551,8 +1553,9 @@ MU_TEST_SUITE(test_rpc_app) { static void test_send_rubbish(RpcSession* session, const char* pattern, size_t pattern_size, size_t size) { + UNUSED(session); uint8_t* buf = malloc(size); - for(int i = 0; i < size; ++i) { + for(size_t i = 0; i < size; ++i) { buf[i] = pattern[i % pattern_size]; } diff --git a/applications/unit_tests/storage/dirwalk_test.c b/applications/unit_tests/storage/dirwalk_test.c new file mode 100644 index 00000000..25e12259 --- /dev/null +++ b/applications/unit_tests/storage/dirwalk_test.c @@ -0,0 +1,272 @@ +#include "../minunit.h" +#include +#include +#include + +static const char* const storage_test_dirwalk_paths[] = { + "1", + "11", + "111", + "1/2", + "1/22", + "1/222", + "11/2", + "111/2", + "111/22", + "111/22/33", +}; + +static const char* const storage_test_dirwalk_files[] = { + "file1.test", + "file2.test", + "file3.ext_test", + "1/file1.test", + "111/22/33/file1.test", + "111/22/33/file2.test", + "111/22/33/file3.ext_test", + "111/22/33/file4.ext_test", +}; + +typedef struct { + const char* const path; + bool is_dir; +} StorageTestPathDesc; + +const StorageTestPathDesc storage_test_dirwalk_full[] = { + {.path = "1", .is_dir = true}, + {.path = "11", .is_dir = true}, + {.path = "111", .is_dir = true}, + {.path = "1/2", .is_dir = true}, + {.path = "1/22", .is_dir = true}, + {.path = "1/222", .is_dir = true}, + {.path = "11/2", .is_dir = true}, + {.path = "111/2", .is_dir = true}, + {.path = "111/22", .is_dir = true}, + {.path = "111/22/33", .is_dir = true}, + {.path = "file1.test", .is_dir = false}, + {.path = "file2.test", .is_dir = false}, + {.path = "file3.ext_test", .is_dir = false}, + {.path = "1/file1.test", .is_dir = false}, + {.path = "111/22/33/file1.test", .is_dir = false}, + {.path = "111/22/33/file2.test", .is_dir = false}, + {.path = "111/22/33/file3.ext_test", .is_dir = false}, + {.path = "111/22/33/file4.ext_test", .is_dir = false}, +}; + +const StorageTestPathDesc storage_test_dirwalk_no_recursive[] = { + {.path = "1", .is_dir = true}, + {.path = "11", .is_dir = true}, + {.path = "111", .is_dir = true}, + {.path = "file1.test", .is_dir = false}, + {.path = "file2.test", .is_dir = false}, + {.path = "file3.ext_test", .is_dir = false}, +}; + +const StorageTestPathDesc storage_test_dirwalk_filter[] = { + {.path = "file1.test", .is_dir = false}, + {.path = "file2.test", .is_dir = false}, + {.path = "1/file1.test", .is_dir = false}, + {.path = "111/22/33/file1.test", .is_dir = false}, + {.path = "111/22/33/file2.test", .is_dir = false}, +}; + +typedef struct { + bool is_dir; + bool visited; +} StorageTestPath; + +DICT_DEF2(StorageTestPathDict, string_t, STRING_OPLIST, StorageTestPath, M_POD_OPLIST) + +static StorageTestPathDict_t* + storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) { + StorageTestPathDict_t* data = malloc(sizeof(StorageTestPathDict_t)); + StorageTestPathDict_init(*data); + + for(size_t i = 0; i < paths_count; i++) { + string_t key; + string_init_set(key, paths[i].path); + StorageTestPath value = { + .is_dir = paths[i].is_dir, + .visited = false, + }; + + StorageTestPathDict_set_at(*data, key, value); + string_clear(key); + } + + return data; +} + +static void storage_test_paths_free(StorageTestPathDict_t* data) { + StorageTestPathDict_clear(*data); + free(data); +} + +static bool storage_test_paths_mark(StorageTestPathDict_t* data, string_t path, bool is_dir) { + bool found = false; + + StorageTestPath* record = StorageTestPathDict_get(*data, path); + if(record) { + if(is_dir == record->is_dir) { + if(record->visited == false) { + record->visited = true; + found = true; + } + } + } + + return found; +} + +static bool storage_test_paths_check(StorageTestPathDict_t* data) { + bool error = false; + + StorageTestPathDict_it_t it; + for(StorageTestPathDict_it(it, *data); !StorageTestPathDict_end_p(it); + StorageTestPathDict_next(it)) { + const StorageTestPathDict_itref_t* itref = StorageTestPathDict_cref(it); + + if(itref->value.visited == false) { + error = true; + break; + } + } + + return error; +} + +static bool write_file_13DA(Storage* storage, const char* path) { + File* file = storage_file_alloc(storage); + bool result = false; + if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + result = storage_file_write(file, "13DA", 4) == 4; + } + storage_file_close(file); + storage_file_free(file); + + return result; +} + +static void storage_dirs_create(Storage* storage, const char* base) { + string_t path; + string_init(path); + + storage_common_mkdir(storage, base); + + for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) { + string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]); + storage_common_mkdir(storage, string_get_cstr(path)); + } + + for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) { + string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]); + write_file_13DA(storage, string_get_cstr(path)); + } + + string_clear(path); +} + +MU_TEST_1(test_dirwalk_full, Storage* storage) { + string_t path; + string_init(path); + FileInfo fileinfo; + + StorageTestPathDict_t* paths = + storage_test_paths_alloc(storage_test_dirwalk_full, COUNT_OF(storage_test_dirwalk_full)); + + DirWalk* dir_walk = dir_walk_alloc(storage); + mu_check(dir_walk_open(dir_walk, "/ext/dirwalk")); + + while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { + string_right(path, strlen("/ext/dirwalk/")); + mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + } + + dir_walk_free(dir_walk); + string_clear(path); + + mu_check(storage_test_paths_check(paths) == false); + + storage_test_paths_free(paths); +} + +MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) { + string_t path; + string_init(path); + FileInfo fileinfo; + + StorageTestPathDict_t* paths = storage_test_paths_alloc( + storage_test_dirwalk_no_recursive, COUNT_OF(storage_test_dirwalk_no_recursive)); + + DirWalk* dir_walk = dir_walk_alloc(storage); + dir_walk_set_recursive(dir_walk, false); + mu_check(dir_walk_open(dir_walk, "/ext/dirwalk")); + + while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { + string_right(path, strlen("/ext/dirwalk/")); + mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + } + + dir_walk_free(dir_walk); + string_clear(path); + + mu_check(storage_test_paths_check(paths) == false); + + storage_test_paths_free(paths); +} + +static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* fileinfo, void* ctx) { + UNUSED(ctx); + + // only files + if(!(fileinfo->flags & FSF_DIRECTORY)) { + // with ".test" in name + if(strstr(name, ".test") != NULL) { + return true; + } + } + + return false; +} + +MU_TEST_1(test_dirwalk_filter, Storage* storage) { + string_t path; + string_init(path); + FileInfo fileinfo; + + StorageTestPathDict_t* paths = storage_test_paths_alloc( + storage_test_dirwalk_filter, COUNT_OF(storage_test_dirwalk_filter)); + + DirWalk* dir_walk = dir_walk_alloc(storage); + dir_walk_set_filter_cb(dir_walk, test_dirwalk_filter_no_folder_ext, NULL); + mu_check(dir_walk_open(dir_walk, "/ext/dirwalk")); + + while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { + string_right(path, strlen("/ext/dirwalk/")); + mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + } + + dir_walk_free(dir_walk); + string_clear(path); + + mu_check(storage_test_paths_check(paths) == false); + + storage_test_paths_free(paths); +} + +MU_TEST_SUITE(test_dirwalk_suite) { + Storage* storage = furi_record_open("storage"); + storage_dirs_create(storage, "/ext/dirwalk"); + + MU_RUN_TEST_1(test_dirwalk_full, storage); + MU_RUN_TEST_1(test_dirwalk_no_recursive, storage); + MU_RUN_TEST_1(test_dirwalk_filter, storage); + + storage_simply_remove_recursive(storage, "/ext/dirwalk"); + furi_record_close("storage"); +} + +int run_minunit_test_dirwalk() { + MU_RUN_SUITE(test_dirwalk_suite); + return MU_EXIT_CODE; +} \ No newline at end of file diff --git a/applications/unit_tests/storage/storage_test.c b/applications/unit_tests/storage/storage_test.c index 3fccc68f..9f237bd0 100644 --- a/applications/unit_tests/storage/storage_test.c +++ b/applications/unit_tests/storage/storage_test.c @@ -164,8 +164,153 @@ MU_TEST_SUITE(storage_dir) { MU_RUN_TEST(storage_dir_open_lock); } +static const char* const storage_copy_test_paths[] = { + "1", + "11", + "111", + "1/2", + "1/22", + "1/222", + "11/1", + "111/2", + "111/22", + "111/22/33", +}; + +static const char* const storage_copy_test_files[] = { + "file.test", + "1/file.test", + "111/22/33/file.test", +}; + +static bool write_file_13DA(Storage* storage, const char* path) { + File* file = storage_file_alloc(storage); + bool result = false; + if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + result = storage_file_write(file, "13DA", 4) == 4; + } + storage_file_close(file); + storage_file_free(file); + + return result; +} + +static bool check_file_13DA(Storage* storage, const char* path) { + File* file = storage_file_alloc(storage); + bool result = false; + if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) { + char data[10] = {0}; + result = storage_file_read(file, data, 4) == 4; + if(result) { + result = memcmp(data, "13DA", 4) == 0; + } + } + storage_file_close(file); + storage_file_free(file); + + return result; +} + +static void storage_dir_create(Storage* storage, const char* base) { + string_t path; + string_init(path); + + storage_common_mkdir(storage, base); + + for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { + string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); + storage_common_mkdir(storage, string_get_cstr(path)); + } + + for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { + string_printf(path, "%s/%s", base, storage_copy_test_files[i]); + write_file_13DA(storage, string_get_cstr(path)); + } + + string_clear(path); +} + +static void storage_dir_remove(Storage* storage, const char* base) { + storage_simply_remove_recursive(storage, base); +} + +static bool storage_dir_rename_check(Storage* storage, const char* base) { + bool result = false; + string_t path; + string_init(path); + + result = (storage_common_stat(storage, base, NULL) == FSE_OK); + + if(result) { + for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { + string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); + result = (storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK); + if(!result) { + break; + } + } + } + + if(result) { + for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { + string_printf(path, "%s/%s", base, storage_copy_test_files[i]); + result = check_file_13DA(storage, string_get_cstr(path)); + if(!result) { + break; + } + } + } + + string_clear(path); + return result; +} + +MU_TEST(storage_file_rename) { + Storage* storage = furi_record_open("storage"); + File* file = storage_file_alloc(storage); + + mu_check(write_file_13DA(storage, "/ext/file.old")); + mu_check(check_file_13DA(storage, "/ext/file.old")); + mu_assert_int_eq(FSE_OK, storage_common_rename(storage, "/ext/file.old", "/ext/file.new")); + mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, "/ext/file.old", NULL)); + mu_assert_int_eq(FSE_OK, storage_common_stat(storage, "/ext/file.new", NULL)); + mu_check(check_file_13DA(storage, "/ext/file.new")); + mu_assert_int_eq(FSE_OK, storage_common_remove(storage, "/ext/file.new")); + + storage_file_free(file); + furi_record_close("storage"); +} + +MU_TEST(storage_dir_rename) { + Storage* storage = furi_record_open("storage"); + + storage_dir_create(storage, "/ext/dir.old"); + + mu_check(storage_dir_rename_check(storage, "/ext/dir.old")); + + mu_assert_int_eq(FSE_OK, storage_common_rename(storage, "/ext/dir.old", "/ext/dir.new")); + mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, "/ext/dir.old", NULL)); + mu_check(storage_dir_rename_check(storage, "/ext/dir.new")); + + storage_dir_remove(storage, "/ext/dir.new"); + mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, "/ext/dir.new", NULL)); + + furi_record_close("storage"); +} + +MU_TEST_SUITE(storage_rename) { + MU_RUN_TEST(storage_file_rename); + MU_RUN_TEST(storage_dir_rename); + + Storage* storage = furi_record_open("storage"); + storage_dir_remove(storage, "/ext/dir.old"); + storage_dir_remove(storage, "/ext/dir.new"); + furi_record_close("storage"); +} + int run_minunit_test_storage() { MU_RUN_SUITE(storage_file); MU_RUN_SUITE(storage_dir); + MU_RUN_SUITE(storage_rename); return MU_EXIT_CODE; -} \ No newline at end of file +} diff --git a/applications/unit_tests/stream/stream_test.c b/applications/unit_tests/stream/stream_test.c index eed8a7bc..b5e8a18b 100644 --- a/applications/unit_tests/stream/stream_test.c +++ b/applications/unit_tests/stream/stream_test.c @@ -378,4 +378,4 @@ MU_TEST_SUITE(stream_suite) { int run_minunit_test_stream() { MU_RUN_SUITE(stream_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} diff --git a/applications/unit_tests/subghz/subghz_test.c b/applications/unit_tests/subghz/subghz_test.c index 48613868..879deae8 100644 --- a/applications/unit_tests/subghz/subghz_test.c +++ b/applications/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME "/ext/subghz/assets/came_atomo" #define NICE_FLOR_S_DIR_NAME "/ext/subghz/assets/nice_flor_s" #define TEST_RANDOM_DIR_NAME "/ext/unit_tests/subghz/test_random_raw.sub" -#define TEST_RANDOM_COUNT_PARSE 101 +#define TEST_RANDOM_COUNT_PARSE 113 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -26,10 +26,13 @@ static void subghz_test_rx_callback( SubGhzReceiver* receiver, SubGhzProtocolDecoderBase* decoder_base, void* context) { + UNUSED(receiver); + UNUSED(context); string_t text; string_init(text); subghz_protocol_decoder_base_get_string(decoder_base, text); - FURI_LOG_I(TAG, "\r\n%s", string_get_cstr(text)); + subghz_receiver_reset(receiver_handler); + FURI_LOG_T(TAG, "\r\n%s", string_get_cstr(text)); string_clear(text); subghz_test_decoder_count++; } @@ -51,7 +54,7 @@ static void subghz_test_deinit(void) { subghz_environment_free(environment_handler); } -static bool subghz_decode_test(const char* path, const char* name_decoder) { +static bool subghz_decoder_test(const char* path, const char* name_decoder) { subghz_test_decoder_count = 0; uint32_t test_start = furi_hal_get_tick(); @@ -61,18 +64,18 @@ static bool subghz_decode_test(const char* path, const char* name_decoder) { if(decoder) { file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) { - //the worker needs a file in order to open and read part of the file + // the worker needs a file in order to open and read part of the file osDelay(100); LevelDuration level_duration; while(furi_hal_get_tick() - test_start < TEST_TIMEOUT) { - 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_handler); if(!level_duration_is_reset(level_duration)) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); + // Yield, to load data inside the worker + osThreadYield(); decoder->protocol->decoder->feed(decoder, level, duration); } else { break; @@ -85,7 +88,7 @@ static bool subghz_decode_test(const char* path, const char* name_decoder) { } subghz_file_encoder_worker_free(file_worker_encoder_handler); } - FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); + FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); if(furi_hal_get_tick() - test_start > TEST_TIMEOUT) { printf("\033[0;31mTest decoder %s ERROR TimeOut\033[0m\r\n", name_decoder); return false; @@ -94,24 +97,25 @@ static bool subghz_decode_test(const char* path, const char* name_decoder) { } } -static bool subghz_decode_ramdom_test(const char* path) { +static bool subghz_decode_random_test(const char* path) { subghz_test_decoder_count = 0; subghz_receiver_reset(receiver_handler); uint32_t test_start = furi_hal_get_tick(); file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) { - //the worker needs a file in order to open and read part of the file + // the worker needs a file in order to open and read part of the file osDelay(100); LevelDuration level_duration; while(furi_hal_get_tick() - test_start < TEST_TIMEOUT * 10) { - 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_handler); if(!level_duration_is_reset(level_duration)) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); + // Yield, to load data inside the worker + osThreadYield(); subghz_receiver_decode(receiver_handler, level, duration); } else { break; @@ -123,7 +127,7 @@ static bool subghz_decode_ramdom_test(const char* path) { } subghz_file_encoder_worker_free(file_worker_encoder_handler); } - FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); + FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); if(furi_hal_get_tick() - test_start > TEST_TIMEOUT * 10) { printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n"); return false; @@ -134,7 +138,7 @@ static bool subghz_decode_ramdom_test(const char* path) { } } -static bool subghz_ecode_test(const char* path) { +static bool subghz_encoder_test(const char* path) { subghz_test_decoder_count = 0; uint32_t test_start = furi_hal_get_tick(); string_t temp_str; @@ -186,7 +190,7 @@ static bool subghz_ecode_test(const char* path) { subghz_transmitter_free(transmitter); } flipper_format_free(fff_data_file); - FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); + FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); if(furi_hal_get_tick() - test_start > TEST_TIMEOUT) { printf("\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", string_get_cstr(temp_str)); subghz_test_decoder_count = 0; @@ -202,169 +206,221 @@ MU_TEST(subghz_keystore_test) { "Test keystore error"); } +//test decoders MU_TEST(subghz_decoder_came_atomo_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/came_atomo_raw.sub", SUBGHZ_PROTOCOL_CAME_ATOMO_NAME), "Test decoder " SUBGHZ_PROTOCOL_CAME_ATOMO_NAME " error\r\n"); } MU_TEST(subghz_decoder_came_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/came_raw.sub", SUBGHZ_PROTOCOL_CAME_NAME), + subghz_decoder_test("/ext/unit_tests/subghz/came_raw.sub", SUBGHZ_PROTOCOL_CAME_NAME), "Test decoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n"); } MU_TEST(subghz_decoder_came_twee_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/came_twee_raw.sub", SUBGHZ_PROTOCOL_CAME_TWEE_NAME), "Test decoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n"); } MU_TEST(subghz_decoder_faac_slh_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/faac_slh_raw.sub", SUBGHZ_PROTOCOL_FAAC_SLH_NAME), "Test decoder " SUBGHZ_PROTOCOL_FAAC_SLH_NAME " error\r\n"); } MU_TEST(subghz_decoder_gate_tx_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/gate_tx_raw.sub", SUBGHZ_PROTOCOL_GATE_TX_NAME), + subghz_decoder_test("/ext/unit_tests/subghz/gate_tx_raw.sub", SUBGHZ_PROTOCOL_GATE_TX_NAME), "Test decoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n"); } MU_TEST(subghz_decoder_hormann_hsm_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/hormann_hsm_raw.sub", SUBGHZ_PROTOCOL_HORMANN_HSM_NAME), "Test decoder " SUBGHZ_PROTOCOL_HORMANN_HSM_NAME " error\r\n"); } MU_TEST(subghz_decoder_ido_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/ido_117_111_raw.sub", SUBGHZ_PROTOCOL_IDO_NAME), + subghz_decoder_test("/ext/unit_tests/subghz/ido_117_111_raw.sub", SUBGHZ_PROTOCOL_IDO_NAME), "Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n"); } MU_TEST(subghz_decoder_keelog_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/doorhan_raw.sub", SUBGHZ_PROTOCOL_KEELOQ_NAME), + subghz_decoder_test("/ext/unit_tests/subghz/doorhan_raw.sub", SUBGHZ_PROTOCOL_KEELOQ_NAME), "Test decoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n"); } MU_TEST(subghz_decoder_kia_seed_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/kia_seed_raw.sub", SUBGHZ_PROTOCOL_KIA_NAME), + subghz_decoder_test("/ext/unit_tests/subghz/kia_seed_raw.sub", SUBGHZ_PROTOCOL_KIA_NAME), "Test decoder " SUBGHZ_PROTOCOL_KIA_NAME " error\r\n"); } MU_TEST(subghz_decoder_nero_radio_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/nero_radio_raw.sub", SUBGHZ_PROTOCOL_NERO_RADIO_NAME), "Test decoder " SUBGHZ_PROTOCOL_NERO_RADIO_NAME " error\r\n"); } MU_TEST(subghz_decoder_nero_sketch_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/nero_sketch_raw.sub", SUBGHZ_PROTOCOL_NERO_SKETCH_NAME), "Test decoder " SUBGHZ_PROTOCOL_NERO_SKETCH_NAME " error\r\n"); } MU_TEST(subghz_decoder_nice_flo_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/nice_flo_raw.sub", SUBGHZ_PROTOCOL_NICE_FLO_NAME), "Test decoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n"); } MU_TEST(subghz_decoder_nice_flor_s_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/nice_flor_s_raw.sub", SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME), "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n"); } MU_TEST(subghz_decoder_princeton_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/Princeton_raw.sub", SUBGHZ_PROTOCOL_PRINCETON_NAME), "Test decoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n"); } MU_TEST(subghz_decoder_scher_khan_magic_code_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/scher_khan_magic_code.sub", SUBGHZ_PROTOCOL_SCHER_KHAN_NAME), "Test decoder " SUBGHZ_PROTOCOL_SCHER_KHAN_NAME " error\r\n"); } MU_TEST(subghz_decoder_somfy_keytis_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/Somfy_keytis_raw.sub", SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME), "Test decoder " SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME " error\r\n"); } MU_TEST(subghz_decoder_somfy_telis_test) { mu_assert( - subghz_decode_test( + subghz_decoder_test( "/ext/unit_tests/subghz/somfy_telis_raw.sub", SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME), "Test decoder " SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME " error\r\n"); } MU_TEST(subghz_decoder_star_line_test) { mu_assert( - subghz_decode_test("/ext/unit_tests/subghz/cenmax_raw.sub", SUBGHZ_PROTOCOL_STAR_LINE_NAME), + subghz_decoder_test( + "/ext/unit_tests/subghz/cenmax_raw.sub", SUBGHZ_PROTOCOL_STAR_LINE_NAME), "Test decoder " SUBGHZ_PROTOCOL_STAR_LINE_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_princeton_test) { +MU_TEST(subghz_decoder_firefly_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/princeton.sub"), + subghz_decoder_test("/ext/unit_tests/subghz/firefly_raw.sub", SUBGHZ_PROTOCOL_FIREFLY_NAME), + "Test decoder " SUBGHZ_PROTOCOL_FIREFLY_NAME " error\r\n"); +} + +MU_TEST(subghz_decoder_megacode_test) { + mu_assert( + subghz_decoder_test( + "/ext/unit_tests/subghz/megacode_raw.sub", SUBGHZ_PROTOCOL_MEGACODE_NAME), + "Test decoder " SUBGHZ_PROTOCOL_MEGACODE_NAME " error\r\n"); +} + +MU_TEST(subghz_decoder_secplus_v1_test) { + mu_assert( + subghz_decoder_test( + "/ext/unit_tests/subghz/security_pls_1_0_raw.sub", SUBGHZ_PROTOCOL_SECPLUS_V1_NAME), + "Test decoder " SUBGHZ_PROTOCOL_SECPLUS_V1_NAME " error\r\n"); +} + +MU_TEST(subghz_decoder_secplus_v2_test) { + mu_assert( + subghz_decoder_test( + "/ext/unit_tests/subghz/security_pls_2_0_raw.sub", SUBGHZ_PROTOCOL_SECPLUS_V2_NAME), + "Test decoder " SUBGHZ_PROTOCOL_SECPLUS_V2_NAME " error\r\n"); +} + +MU_TEST(subghz_decoder_holtek_test) { + mu_assert( + subghz_decoder_test("/ext/unit_tests/subghz/holtek_raw.sub", SUBGHZ_PROTOCOL_HOLTEK_NAME), + "Test decoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n"); +} + +//test encoders +MU_TEST(subghz_encoder_princeton_test) { + mu_assert( + subghz_encoder_test("/ext/unit_tests/subghz/princeton.sub"), "Test encoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_came_test) { +MU_TEST(subghz_encoder_came_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/came.sub"), + subghz_encoder_test("/ext/unit_tests/subghz/came.sub"), "Test encoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_came_twee_test) { +MU_TEST(subghz_encoder_came_twee_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/came_twee.sub"), + subghz_encoder_test("/ext/unit_tests/subghz/came_twee.sub"), "Test encoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_gate_tx_test) { +MU_TEST(subghz_encoder_gate_tx_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/gate_tx.sub"), + subghz_encoder_test("/ext/unit_tests/subghz/gate_tx.sub"), "Test encoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_nice_flo_test) { +MU_TEST(subghz_encoder_nice_flo_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/nice_flo.sub"), + subghz_encoder_test("/ext/unit_tests/subghz/nice_flo.sub"), "Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n"); } -MU_TEST(subghz_ecoder_keelog_test) { +MU_TEST(subghz_encoder_keelog_test) { mu_assert( - subghz_ecode_test("/ext/unit_tests/subghz/doorhan.sub"), + subghz_encoder_test("/ext/unit_tests/subghz/doorhan.sub"), "Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n"); } +MU_TEST(subghz_encoder_firefly_test) { + mu_assert( + subghz_encoder_test("/ext/unit_tests/subghz/firely.sub"), + "Test encoder " SUBGHZ_PROTOCOL_FIREFLY_NAME " error\r\n"); +} + +MU_TEST(subghz_encoder_megacode_test) { + mu_assert( + subghz_encoder_test("/ext/unit_tests/subghz/megacode.sub"), + "Test encoder " SUBGHZ_PROTOCOL_MEGACODE_NAME " error\r\n"); +} + +MU_TEST(subghz_encoder_holtek_test) { + mu_assert( + subghz_encoder_test("/ext/unit_tests/subghz/holtek.sub"), + "Test encoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { - mu_assert(subghz_decode_ramdom_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); + mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } MU_TEST_SUITE(subghz) { - //MU_SUITE_CONFIGURE(&subghz_test_init, &subghz_test_deinit); - subghz_test_init(); MU_RUN_TEST(subghz_keystore_test); @@ -386,13 +442,21 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_somfy_keytis_test); MU_RUN_TEST(subghz_decoder_somfy_telis_test); MU_RUN_TEST(subghz_decoder_star_line_test); + MU_RUN_TEST(subghz_decoder_firefly_test); + MU_RUN_TEST(subghz_decoder_megacode_test); + MU_RUN_TEST(subghz_decoder_secplus_v1_test); + MU_RUN_TEST(subghz_decoder_secplus_v2_test); + MU_RUN_TEST(subghz_decoder_holtek_test); - MU_RUN_TEST(subghz_ecoder_princeton_test); - MU_RUN_TEST(subghz_ecoder_came_test); - MU_RUN_TEST(subghz_ecoder_came_twee_test); - MU_RUN_TEST(subghz_ecoder_gate_tx_test); - MU_RUN_TEST(subghz_ecoder_nice_flo_test); - MU_RUN_TEST(subghz_ecoder_keelog_test); + MU_RUN_TEST(subghz_encoder_princeton_test); + MU_RUN_TEST(subghz_encoder_came_test); + MU_RUN_TEST(subghz_encoder_came_twee_test); + MU_RUN_TEST(subghz_encoder_gate_tx_test); + MU_RUN_TEST(subghz_encoder_nice_flo_test); + MU_RUN_TEST(subghz_encoder_keelog_test); + MU_RUN_TEST(subghz_encoder_firefly_test); + MU_RUN_TEST(subghz_encoder_megacode_test); + MU_RUN_TEST(subghz_encoder_holtek_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/applications/unit_tests/test_index.c b/applications/unit_tests/test_index.c index ef12224c..a1acbed4 100644 --- a/applications/unit_tests/test_index.c +++ b/applications/unit_tests/test_index.c @@ -18,6 +18,7 @@ int run_minunit_test_flipper_format_string(); int run_minunit_test_stream(); int run_minunit_test_storage(); int run_minunit_test_subghz(); +int run_minunit_test_dirwalk(); void minunit_print_progress(void) { static char progress[] = {'\\', '|', '/', '-'}; @@ -35,6 +36,9 @@ void minunit_print_fail(const char* str) { } void unit_tests_cli(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); uint32_t test_result = 0; minunit_run = 0; minunit_assert = 0; @@ -57,6 +61,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { test_result |= run_minunit(); test_result |= run_minunit_test_storage(); test_result |= run_minunit_test_stream(); + test_result |= run_minunit_test_dirwalk(); test_result |= run_minunit_test_flipper_format(); test_result |= run_minunit_test_flipper_format_string(); test_result |= run_minunit_test_infrared_decoder_encoder(); @@ -65,7 +70,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { cycle_counter = (furi_hal_get_tick() - cycle_counter); - FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / 1000); + FURI_LOG_I(TAG, "Consumed: %u us", cycle_counter); if(test_result == 0) { furi_hal_delay_ms(200); /* wait for tested services and apps to deallocate */ diff --git a/applications/updater/cli/updater_cli.c b/applications/updater/cli/updater_cli.c index aa08bc61..fb2edeb9 100644 --- a/applications/updater/cli/updater_cli.c +++ b/applications/updater/cli/updater_cli.c @@ -52,7 +52,7 @@ static void updater_cli_restore(string_t args) { static void updater_cli_help(string_t args) { UNUSED(args); printf("Commands:\r\n" - "\tinstall /ext/update/PACKAGE/update.fuf - verify & apply update package\r\n" + "\tinstall /ext/path/to/update.fuf - verify & apply update package\r\n" "\tbackup /ext/path/to/backup.tar - create internal storage backup\r\n" "\trestore /ext/path/to/backup.tar - restore internal storage backup\r\n"); } @@ -65,6 +65,8 @@ static const CliSubcommand update_cli_subcommands[] = { }; static void updater_cli_ep(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); string_t subcommand; string_init(subcommand); if(!args_read_string_and_trim(args, subcommand) || string_empty_p(args)) { @@ -85,6 +87,7 @@ static void updater_cli_ep(Cli* cli, string_t args, void* context) { } static int32_t updater_spawner_thread_worker(void* arg) { + UNUSED(arg); Loader* loader = furi_record_open("loader"); loader_start(loader, "UpdaterApp", NULL); furi_record_close("loader"); @@ -131,4 +134,4 @@ void updater_on_system_start() { #else UNUSED(updater_start_app); #endif -} +} \ No newline at end of file diff --git a/applications/updater/scenes/updater_scene_config.h b/applications/updater/scenes/updater_scene_config.h index d2441c59..59601965 100644 --- a/applications/updater/scenes/updater_scene_config.h +++ b/applications/updater/scenes/updater_scene_config.h @@ -2,4 +2,4 @@ ADD_SCENE(updater, main, Main) #ifndef FURI_RAM_EXEC ADD_SCENE(updater, loadcfg, LoadCfg) ADD_SCENE(updater, error, Error) -#endif \ No newline at end of file +#endif diff --git a/applications/updater/scenes/updater_scene_loadcfg.c b/applications/updater/scenes/updater_scene_loadcfg.c index 78423b07..8e477b14 100644 --- a/applications/updater/scenes/updater_scene_loadcfg.c +++ b/applications/updater/scenes/updater_scene_loadcfg.c @@ -102,4 +102,4 @@ void updater_scene_loadcfg_on_exit(void* context) { widget_reset(updater->widget); free(updater->pending_update); -} \ No newline at end of file +} diff --git a/applications/updater/scenes/updater_scene_main.c b/applications/updater/scenes/updater_scene_main.c index c5fc99ff..5f7aeaca 100644 --- a/applications/updater/scenes/updater_scene_main.c +++ b/applications/updater/scenes/updater_scene_main.c @@ -45,8 +45,8 @@ void updater_scene_main_on_enter(void* context) { view_dispatcher_switch_to_view(updater->view_dispatcher, UpdaterViewMain); } -static void updater_scene_restart_to_postupdate() { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePostUpdate); +static void updater_scene_cancel_update() { + update_operation_disarm(); furi_hal_power_reset(); } @@ -57,7 +57,7 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeTick) { if(!update_task_is_running(updater->update_task)) { if(updater->idle_ticks++ >= (UPDATE_DELAY_OPERATION_ERROR / UPDATER_APP_TICK)) { - updater_scene_restart_to_postupdate(); + updater_scene_cancel_update(); } } else { updater->idle_ticks = 0; @@ -74,7 +74,7 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) { case UpdaterCustomEventCancelUpdate: if(!update_task_is_running(updater->update_task)) { - updater_scene_restart_to_postupdate(); + updater_scene_cancel_update(); } consumed = true; break; diff --git a/applications/updater/updater.c b/applications/updater/updater.c index c1115ce1..4c9fe41f 100644 --- a/applications/updater/updater.c +++ b/applications/updater/updater.c @@ -26,15 +26,10 @@ static bool updater_back_event_callback(void* context) { return scene_manager_handle_back_event(updater->scene_manager); } -static void status_update_cb( - const char* message, - const uint8_t progress, - const uint8_t idx_stage, - const uint8_t total_stages, - bool failed, - void* context) { +static void + status_update_cb(const char* message, const uint8_t progress, bool failed, void* context) { UpdaterMainView* main_view = context; - updater_main_model_set_state(main_view, message, progress, idx_stage, total_stages, failed); + updater_main_model_set_state(main_view, message, progress, failed); } Updater* updater_alloc(const char* arg) { @@ -64,9 +59,7 @@ Updater* updater_alloc(const char* arg) { updater->view_dispatcher, updater_tick_event_callback, UPDATER_APP_TICK); view_dispatcher_attach_to_gui( - updater->view_dispatcher, - updater->gui, - arg ? ViewDispatcherTypeFullscreen : ViewDispatcherTypeWindow); + updater->view_dispatcher, updater->gui, ViewDispatcherTypeFullscreen); updater->main_view = updater_main_alloc(); view_dispatcher_add_view( @@ -133,4 +126,4 @@ int32_t updater_srv(void* p) { updater_free(updater); return 0; -} \ No newline at end of file +} diff --git a/applications/updater/updater_i.h b/applications/updater/updater_i.h index 89201e1e..8a021a08 100644 --- a/applications/updater/updater_i.h +++ b/applications/updater/updater_i.h @@ -64,4 +64,4 @@ void updater_free(Updater* updater); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/updater/util/update_task.c b/applications/updater/util/update_task.c index 9fde086a..1238bdb0 100644 --- a/applications/updater/util/update_task.c +++ b/applications/updater/util/update_task.c @@ -14,54 +14,139 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageReadManifest] = "Loading update manifest", [UpdateTaskStageValidateDFUImage] = "Checking DFU file", [UpdateTaskStageFlashWrite] = "Writing flash", - [UpdateTaskStageFlashValidate] = "Validating", - [UpdateTaskStageRadioImageValidate] = "Checking radio image", - [UpdateTaskStageRadioErase] = "Removing radio stack", - [UpdateTaskStageRadioWrite] = "Writing radio stack", - [UpdateTaskStageRadioInstall] = "Installing radio stack", - [UpdateTaskStageRadioBusy] = "Core2 is updating", + [UpdateTaskStageFlashValidate] = "Validating flash", + [UpdateTaskStageRadioImageValidate] = "Checking radio FW", + [UpdateTaskStageRadioErase] = "Uninstalling radio FW", + [UpdateTaskStageRadioWrite] = "Writing radio FW", + [UpdateTaskStageRadioInstall] = "Installing radio FW", + [UpdateTaskStageRadioBusy] = "Radio is updating", [UpdateTaskStageOBValidation] = "Validating opt. bytes", [UpdateTaskStageLfsBackup] = "Backing up LFS", [UpdateTaskStageLfsRestore] = "Restoring LFS", [UpdateTaskStageResourcesUpdate] = "Updating resources", - [UpdateTaskStageCompleted] = "Completed!", + [UpdateTaskStageCompleted] = "Restarting...", [UpdateTaskStageError] = "Error", - [UpdateTaskStageOBError] = "OB error, pls report", + [UpdateTaskStageOBError] = "OB Err, report", }; -static void update_task_set_status(UpdateTask* update_task, const char* status) { - if(!status) { - if(update_task->state.stage >= COUNT_OF(update_task_stage_descr)) { - status = "..."; - } else { - status = update_task_stage_descr[update_task->state.stage]; - } +typedef struct { + UpdateTaskStageGroup group; + uint8_t weight; +} UpdateTaskStageGroupMap; + +#define STAGE_DEF(GROUP, WEIGHT) \ + { .group = (GROUP), .weight = (WEIGHT), } + +static const UpdateTaskStageGroupMap update_task_stage_progress[] = { + [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), + + [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5), + [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 30), + + [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 30), + [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 50), + [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 100), + [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 5), + [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 70), + + [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10), + + [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 100), + [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200), + [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50), + + [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30), + + [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255), + + [UpdateTaskStageCompleted] = STAGE_DEF(UpdateTaskStageGroupMisc, 1), + [UpdateTaskStageError] = STAGE_DEF(UpdateTaskStageGroupMisc, 1), + [UpdateTaskStageOBError] = STAGE_DEF(UpdateTaskStageGroupMisc, 1), +}; + +static UpdateTaskStageGroup update_task_get_task_groups(UpdateTask* update_task) { + UpdateTaskStageGroup ret = UpdateTaskStageGroupPreUpdate | UpdateTaskStageGroupPostUpdate; + UpdateManifest* manifest = update_task->manifest; + if(!string_empty_p(manifest->radio_image)) { + ret |= UpdateTaskStageGroupRadio; } - string_set_str(update_task->state.status, status); + if(update_manifest_has_obdata(manifest)) { + ret |= UpdateTaskStageGroupOptionBytes; + } + if(!string_empty_p(manifest->firmware_dfu_image)) { + ret |= UpdateTaskStageGroupFirmware; + } + if(!string_empty_p(manifest->resource_bundle)) { + ret |= UpdateTaskStageGroupResources; + } + return ret; +} + +static void update_task_calc_completed_stages(UpdateTask* update_task) { + uint32_t completed_stages_points = 0; + for(UpdateTaskStage past_stage = UpdateTaskStageProgress; + past_stage < update_task->state.stage; + ++past_stage) { + const UpdateTaskStageGroupMap* grp_descr = &update_task_stage_progress[past_stage]; + if((grp_descr->group & update_task->state.groups) == 0) { + continue; + } + completed_stages_points += grp_descr->weight; + } + update_task->state.completed_stages_points = completed_stages_points; } void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, uint8_t progress) { if(stage != UpdateTaskStageProgress) { - // do not override more specific error states - if((update_task->state.stage < UpdateTaskStageError) || (stage < UpdateTaskStageError)) { - update_task->state.stage = stage; + /* do not override more specific error states */ + if((stage >= UpdateTaskStageError) && (update_task->state.stage >= UpdateTaskStageError)) { + return; + } + /* Build error message with code "[stage_idx-stage_percent]" */ + if(stage >= UpdateTaskStageError) { + string_printf( + update_task->state.status, + "%s #[%d-%d]", + update_task_stage_descr[stage], + update_task->state.stage, + update_task->state.stage_progress); + } else { + string_set_str(update_task->state.status, update_task_stage_descr[stage]); + } + /* Store stage update */ + update_task->state.stage = stage; + /* If we are still alive, sum completed stages weights */ + if((stage > UpdateTaskStageProgress) && (stage < UpdateTaskStageCompleted)) { + update_task_calc_completed_stages(update_task); } - update_task->state.current_stage_idx++; - update_task_set_status(update_task, NULL); } - if(progress > 100) { - progress = 100; + /* Store stage progress for all non-error updates - to provide details on error state */ + if(!update_stage_is_error(stage)) { + update_task->state.stage_progress = progress; } - update_task->state.progress = progress; + /* Calculate "overall" progress, based on stage weights */ + uint32_t adapted_progress = 1; + if(update_task->state.total_progress_points != 0) { + if(stage < UpdateTaskStageCompleted) { + adapted_progress = MIN( + (update_task->state.completed_stages_points + + (update_task_stage_progress[update_task->state.stage].weight * progress / 100)) * + 100 / (update_task->state.total_progress_points), + 100u); + + } else { + adapted_progress = update_task->state.overall_progress; + } + } + update_task->state.overall_progress = adapted_progress; + if(update_task->status_change_cb) { (update_task->status_change_cb)( string_get_cstr(update_task->state.status), - progress, - update_task->state.current_stage_idx, - update_task->state.total_stages, - update_task->state.stage >= UpdateTaskStageError, + adapted_progress, + update_stage_is_error(update_task->state.stage), update_task->status_change_cb_state); } } @@ -106,8 +191,7 @@ static void update_task_worker_thread_cb(FuriThreadState state, void* context) { return; } - int32_t op_result = furi_thread_get_return_code(update_task->thread); - if(op_result == UPDATE_TASK_NOERR) { + if(furi_thread_get_return_code(update_task->thread) == UPDATE_TASK_NOERR) { osDelay(UPDATE_DELAY_OPERATION_OK); furi_hal_power_reset(); } @@ -117,7 +201,8 @@ UpdateTask* update_task_alloc() { UpdateTask* update_task = malloc(sizeof(UpdateTask)); update_task->state.stage = UpdateTaskStageProgress; - update_task->state.progress = 0; + update_task->state.stage_progress = 0; + update_task->state.overall_progress = 0; string_init(update_task->state.status); update_task->manifest = update_manifest_alloc(); @@ -163,36 +248,66 @@ void update_task_free(UpdateTask* update_task) { bool update_task_parse_manifest(UpdateTask* update_task) { furi_assert(update_task); + update_task->state.stage_progress = 0; + update_task->state.overall_progress = 0; + update_task->state.total_progress_points = 0; + update_task->state.completed_stages_points = 0; + update_task->state.groups = 0; + update_task_set_progress(update_task, UpdateTaskStageReadManifest, 0); bool result = false; string_t manifest_path; string_init(manifest_path); do { - update_task_set_progress(update_task, UpdateTaskStageProgress, 10); - if(!update_operation_get_current_package_path( - update_task->storage, update_task->update_path)) { + update_task_set_progress(update_task, UpdateTaskStageProgress, 13); + if(!furi_hal_version_do_i_belong_here()) { break; } - path_concat( - string_get_cstr(update_task->update_path), - UPDATE_MANIFEST_DEFAULT_NAME, - manifest_path); + update_task_set_progress(update_task, UpdateTaskStageProgress, 20); + if(!update_operation_get_current_package_manifest_path( + update_task->storage, manifest_path)) { + break; + } + + path_extract_dirname(string_get_cstr(manifest_path), update_task->update_path); update_task_set_progress(update_task, UpdateTaskStageProgress, 30); - if(!update_manifest_init(update_task->manifest, string_get_cstr(manifest_path))) { + + UpdateManifest* manifest = update_task->manifest; + if(!update_manifest_init(manifest, string_get_cstr(manifest_path))) { + break; + } + + update_task_set_progress(update_task, UpdateTaskStageProgress, 40); + if(manifest->manifest_version < UPDATE_OPERATION_MIN_MANIFEST_VERSION) { break; } update_task_set_progress(update_task, UpdateTaskStageProgress, 50); - if(!string_empty_p(update_task->manifest->firmware_dfu_image) && - !update_task_check_file_exists(update_task, update_task->manifest->firmware_dfu_image)) { + if(manifest->target != furi_hal_version_get_hw_target()) { break; } - update_task_set_progress(update_task, UpdateTaskStageProgress, 70); - if(!string_empty_p(update_task->manifest->radio_image) && - !update_task_check_file_exists(update_task, update_task->manifest->radio_image)) { + update_task->state.groups = update_task_get_task_groups(update_task); + for(size_t stage_counter = 0; stage_counter < COUNT_OF(update_task_stage_progress); + ++stage_counter) { + const UpdateTaskStageGroupMap* grp_descr = &update_task_stage_progress[stage_counter]; + if((grp_descr->group & update_task->state.groups) != 0) { + update_task->state.total_progress_points += grp_descr->weight; + } + } + + update_task_set_progress(update_task, UpdateTaskStageProgress, 60); + if((update_task->state.groups & UpdateTaskStageGroupFirmware) && + !update_task_check_file_exists(update_task, manifest->firmware_dfu_image)) { + break; + } + + update_task_set_progress(update_task, UpdateTaskStageProgress, 80); + if((update_task->state.groups & UpdateTaskStageGroupRadio) && + (!update_task_check_file_exists(update_task, manifest->radio_image) || + (manifest->radio_version.version.type == 0))) { break; } @@ -227,4 +342,4 @@ UpdateTaskState const* update_task_get_state(UpdateTask* update_task) { UpdateManifest const* update_task_get_manifest(UpdateTask* update_task) { furi_assert(update_task); return update_task->manifest; -} \ No newline at end of file +} diff --git a/applications/updater/util/update_task.h b/applications/updater/util/update_task.h index 8afc3121..cfbbb850 100644 --- a/applications/updater/util/update_task.h +++ b/applications/updater/util/update_task.h @@ -10,46 +10,63 @@ extern "C" { #include #include -#define UPDATE_DELAY_OPERATION_OK 600 +#define UPDATE_DELAY_OPERATION_OK 300 #define UPDATE_DELAY_OPERATION_ERROR INT_MAX typedef enum { - UpdateTaskStageProgress, + UpdateTaskStageProgress = 0, + UpdateTaskStageReadManifest, - UpdateTaskStageValidateDFUImage, - UpdateTaskStageFlashWrite, - UpdateTaskStageFlashValidate, + UpdateTaskStageLfsBackup, + UpdateTaskStageRadioImageValidate, UpdateTaskStageRadioErase, UpdateTaskStageRadioWrite, UpdateTaskStageRadioInstall, UpdateTaskStageRadioBusy, + UpdateTaskStageOBValidation, - UpdateTaskStageLfsBackup, + + UpdateTaskStageValidateDFUImage, + UpdateTaskStageFlashWrite, + UpdateTaskStageFlashValidate, + UpdateTaskStageLfsRestore, UpdateTaskStageResourcesUpdate, + UpdateTaskStageCompleted, UpdateTaskStageError, - UpdateTaskStageOBError + UpdateTaskStageOBError, + UpdateTaskStageMAX } UpdateTaskStage; +inline bool update_stage_is_error(const UpdateTaskStage stage) { + return stage >= UpdateTaskStageError; +} + +typedef enum { + UpdateTaskStageGroupMisc = 0, + UpdateTaskStageGroupPreUpdate = 1 << 1, + UpdateTaskStageGroupFirmware = 1 << 2, + UpdateTaskStageGroupOptionBytes = 1 << 3, + UpdateTaskStageGroupRadio = 1 << 4, + UpdateTaskStageGroupPostUpdate = 1 << 5, + UpdateTaskStageGroupResources = 1 << 6, +} UpdateTaskStageGroup; + typedef struct { UpdateTaskStage stage; - uint8_t progress; - uint8_t current_stage_idx; - uint8_t total_stages; + uint8_t overall_progress, stage_progress; string_t status; + UpdateTaskStageGroup groups; + uint32_t total_progress_points; + uint32_t completed_stages_points; } UpdateTaskState; typedef struct UpdateTask UpdateTask; -typedef void (*updateProgressCb)( - const char* status, - const uint8_t stage_pct, - const uint8_t idx_stage, - const uint8_t total_stages, - bool failed, - void* state); +typedef void ( + *updateProgressCb)(const char* status, const uint8_t stage_pct, bool failed, void* state); UpdateTask* update_task_alloc(); @@ -67,4 +84,4 @@ UpdateManifest const* update_task_get_manifest(UpdateTask* update_task); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/updater/util/update_task_worker_backup.c b/applications/updater/util/update_task_worker_backup.c index 38d71dfd..011510ed 100644 --- a/applications/updater/util/update_task_worker_backup.c +++ b/applications/updater/util/update_task_worker_backup.c @@ -27,7 +27,6 @@ static bool update_task_pre_update(UpdateTask* update_task) { path_concat( string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, backup_file_path); - update_task->state.total_stages = 1; update_task_set_progress(update_task, UpdateTaskStageLfsBackup, 0); /* to avoid bootloops */ furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); @@ -62,22 +61,17 @@ static bool update_task_post_update(UpdateTask* update_task) { string_t file_path; string_init(file_path); - /* status text is too long, too few stages to bother with a counter */ - update_task->state.total_stages = 0; - + TarArchive* archive = tar_archive_alloc(update_task->storage); do { - CHECK_RESULT(update_task_parse_manifest(update_task)); path_concat( string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, file_path); - bool unpack_resources = !string_empty_p(update_task->manifest->resource_bundle); - update_task_set_progress(update_task, UpdateTaskStageLfsRestore, 0); - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); + update_operation_disarm(); CHECK_RESULT(lfs_backup_unpack(update_task->storage, string_get_cstr(file_path))); - if(unpack_resources) { + if(update_task->state.groups & UpdateTaskStageGroupResources) { TarUnpackProgress progress = { .update_task = update_task, .total_files = 0, @@ -90,20 +84,19 @@ static bool update_task_post_update(UpdateTask* update_task) { string_get_cstr(update_task->manifest->resource_bundle), file_path); - TarArchive* archive = tar_archive_alloc(update_task->storage); tar_archive_set_file_callback(archive, update_task_resource_unpack_cb, &progress); - success = tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ); - if(success) { - progress.total_files = tar_archive_get_entries_count(archive); - if(progress.total_files > 0) { - tar_archive_unpack_to(archive, EXT_PATH); - } + CHECK_RESULT( + tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ)); + + progress.total_files = tar_archive_get_entries_count(archive); + if(progress.total_files > 0) { + CHECK_RESULT(tar_archive_unpack_to(archive, EXT_PATH)); } - tar_archive_free(archive); } success = true; } while(false); + tar_archive_free(archive); string_clear(file_path); return success; } @@ -116,18 +109,17 @@ int32_t update_task_worker_backup_restore(void* context) { FuriHalRtcBootMode boot_mode = furi_hal_rtc_get_boot_mode(); if((boot_mode != FuriHalRtcBootModePreUpdate) && (boot_mode != FuriHalRtcBootModePostUpdate)) { /* no idea how we got here. Clear to normal boot */ - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); + update_operation_disarm(); return UPDATE_TASK_NOERR; } - update_task->state.current_stage_idx = 0; - - if(!update_operation_get_current_package_path(update_task->storage, update_task->update_path)) { + if(!update_task_parse_manifest(update_task)) { return UPDATE_TASK_FAILED; } - /* Waiting for BT service to 'start', so we don't race for boot mode */ + /* Waiting for BT service to 'start', so we don't race for boot mode flag */ furi_record_open("bt"); + furi_record_close("bt"); if(boot_mode == FuriHalRtcBootModePreUpdate) { success = update_task_pre_update(update_task); @@ -135,13 +127,11 @@ int32_t update_task_worker_backup_restore(void* context) { success = update_task_post_update(update_task); } - furi_record_close("bt"); - - if(success) { - update_task_set_progress(update_task, UpdateTaskStageCompleted, 100); - } else { - update_task_set_progress(update_task, UpdateTaskStageError, update_task->state.progress); + if(!success) { + update_task_set_progress(update_task, UpdateTaskStageError, 0); + return UPDATE_TASK_FAILED; } - return success ? UPDATE_TASK_NOERR : UPDATE_TASK_FAILED; + update_task_set_progress(update_task, UpdateTaskStageCompleted, 100); + return UPDATE_TASK_NOERR; } diff --git a/applications/updater/util/update_task_worker_flasher.c b/applications/updater/util/update_task_worker_flasher.c index 22e94fd0..1f22e2f7 100644 --- a/applications/updater/util/update_task_worker_flasher.c +++ b/applications/updater/util/update_task_worker_flasher.c @@ -111,19 +111,13 @@ static bool update_task_write_stack_data(UpdateTask* update_task) { } bytes_read = storage_file_read(update_task->file, fw_block, n_bytes_to_read); - if(bytes_read == 0) { - break; - } + CHECK_RESULT(bytes_read != 0); int16_t i_page = furi_hal_flash_get_page_number(update_task->manifest->radio_address + element_offs); - if(i_page < 0) { - break; - } + CHECK_RESULT(i_page >= 0); - if(!furi_hal_flash_program_page(i_page, fw_block, bytes_read)) { - break; - } + CHECK_RESULT(furi_hal_flash_program_page(i_page, fw_block, bytes_read)); element_offs += bytes_read; update_task_set_progress( @@ -142,19 +136,19 @@ static void update_task_wait_for_restart(UpdateTask* update_task) { static bool update_task_write_stack(UpdateTask* update_task) { bool success = false; + UpdateManifest* manifest = update_task->manifest; do { FURI_LOG_W(TAG, "Writing stack"); update_task_set_progress(update_task, UpdateTaskStageRadioImageValidate, 0); - CHECK_RESULT(update_task_open_file(update_task, update_task->manifest->radio_image)); + CHECK_RESULT(update_task_open_file(update_task, manifest->radio_image)); CHECK_RESULT( crc32_calc_file(update_task->file, &update_task_file_progress, update_task) == - update_task->manifest->radio_crc); + manifest->radio_crc); CHECK_RESULT(update_task_write_stack_data(update_task)); update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 0); CHECK_RESULT( - ble_glue_fus_stack_install(update_task->manifest->radio_address, 0) != - BleGlueCommandResultError); + ble_glue_fus_stack_install(manifest->radio_address, 0) != BleGlueCommandResultError); update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 80); CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK); update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 100); @@ -280,7 +274,6 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { manifest->ob_write_mask.obs[idx].values.base) != 0; if(can_patch) { - /* patch & restart loop */ const uint32_t patched_value = /* take all non-writable bits from real value */ (device_ob_value & ~(manifest->ob_write_mask.obs[idx].values.base)) | @@ -297,8 +290,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { if(!is_fixed) { /* Things are so bad that fixing what we are allowed to still doesn't match - * reference value - */ + * reference value */ FURI_LOG_W( TAG, "OB #%d is FUBAR (fixed&masked %08X, not %08X)", @@ -317,11 +309,11 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { } } if(!match) { - update_task_set_progress(update_task, UpdateTaskStageOBError, 95); + update_task_set_progress(update_task, UpdateTaskStageOBError, 0); } if(ob_dirty) { - FURI_LOG_W(TAG, "OB were changed, applying"); + FURI_LOG_W(TAG, "OBs were changed, applying"); furi_hal_flash_ob_apply(); } return match; @@ -332,24 +324,18 @@ int32_t update_task_worker_flash_writer(void* context) { UpdateTask* update_task = context; bool success = false; - update_task->state.current_stage_idx = 0; - update_task->state.total_stages = 0; - do { CHECK_RESULT(update_task_parse_manifest(update_task)); - if(!string_empty_p(update_task->manifest->radio_image)) { + if(update_task->state.groups & UpdateTaskStageGroupRadio) { CHECK_RESULT(update_task_manage_radiostack(update_task)); } - bool check_ob = update_manifest_has_obdata(update_task->manifest); - if(check_ob) { - update_task->state.total_stages++; + if(update_task->state.groups & UpdateTaskStageGroupOptionBytes) { CHECK_RESULT(update_task_validate_optionbytes(update_task)); } - if(!string_empty_p(update_task->manifest->firmware_dfu_image)) { - update_task->state.total_stages += 4; + if(update_task->state.groups & UpdateTaskStageGroupFirmware) { CHECK_RESULT(update_task_write_dfu(update_task)); } @@ -359,5 +345,10 @@ int32_t update_task_worker_flash_writer(void* context) { success = true; } while(false); - return success ? UPDATE_TASK_NOERR : UPDATE_TASK_FAILED; -} \ No newline at end of file + if(!success) { + update_task_set_progress(update_task, UpdateTaskStageError, 0); + return UPDATE_TASK_FAILED; + } + + return UPDATE_TASK_NOERR; +} diff --git a/applications/updater/views/updater_main.c b/applications/updater/views/updater_main.c index 8d9b3e95..72541b9a 100644 --- a/applications/updater/views/updater_main.c +++ b/applications/updater/views/updater_main.c @@ -15,12 +15,11 @@ struct UpdaterMainView { void* context; }; -static const uint8_t PROGRESS_RENDER_STEP = 3; /* percent, to limit rendering rate */ +static const uint8_t PROGRESS_RENDER_STEP = 1; /* percent, to limit rendering rate */ typedef struct { string_t status; uint8_t progress, rendered_progress; - uint8_t idx_stage, total_stages; bool failed; } UpdaterProgressModel; @@ -28,14 +27,10 @@ void updater_main_model_set_state( UpdaterMainView* main_view, const char* message, uint8_t progress, - uint8_t idx_stage, - uint8_t total_stages, bool failed) { with_view_model( main_view->view, (UpdaterProgressModel * model) { model->failed = failed; - model->idx_stage = idx_stage; - model->total_stages = total_stages; model->progress = progress; if(string_cmp_str(model->status, message)) { string_set(model->status, message); @@ -65,14 +60,10 @@ bool updater_main_input(InputEvent* event, void* context) { return true; } - if(event->type != InputTypeShort) { - return true; - } - - if(event->key == InputKeyOk) { + if((event->type == InputTypeShort) && (event->key == InputKeyOk)) { view_dispatcher_send_custom_event( main_view->view_dispatcher, UpdaterCustomEventRetryUpdate); - } else if(event->key == InputKeyBack) { + } else if((event->type == InputTypeLong) && (event->key == InputKeyBack)) { view_dispatcher_send_custom_event( main_view->view_dispatcher, UpdaterCustomEventCancelUpdate); } @@ -85,27 +76,25 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontPrimary); - uint16_t y_offset = model->failed ? 5 : 13; - string_t status_text; - if(!model->failed && (model->idx_stage != 0) && (model->idx_stage <= model->total_stages)) { - string_init_printf( - status_text, - "[%d/%d] %s", - model->idx_stage, - model->total_stages, - string_get_cstr(model->status)); - } else { - string_init_set(status_text, model->status); - } - canvas_draw_str_aligned( - canvas, 128 / 2, y_offset, AlignCenter, AlignTop, string_get_cstr(status_text)); - string_clear(status_text); if(model->failed) { + canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!"); canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned( - canvas, 128 / 2, 20, AlignCenter, AlignTop, "[OK] to retry, [Back] to abort"); + canvas, 42, 32, AlignLeft, AlignTop, string_get_cstr(model->status)); + + canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23); + canvas_draw_str_aligned( + canvas, 18, 51, AlignLeft, AlignTop, "to retry, hold to abort"); + canvas_draw_icon(canvas, 7, 50, &I_Ok_btn_9x9); + canvas_draw_icon(canvas, 75, 51, &I_Pin_back_arrow_10x8); + } else { + canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING"); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 51, AlignCenter, AlignTop, string_get_cstr(model->status)); + canvas_draw_icon(canvas, 4, 5, &I_Updating_32x40); + elements_progress_bar(canvas, 42, 29, 80, (float)model->progress / 100); } - elements_progress_bar(canvas, 14, 35, 100, (float)model->progress / 100); } UpdaterMainView* updater_main_alloc() { @@ -116,7 +105,7 @@ UpdaterMainView* updater_main_alloc() { with_view_model( main_view->view, (UpdaterProgressModel * model) { - string_init_set(model->status, "Waiting for storage"); + string_init_set(model->status, "Waiting for SD card"); return true; }); diff --git a/applications/updater/views/updater_main.h b/applications/updater/views/updater_main.h index 3c55a8c2..81a0e86c 100644 --- a/applications/updater/views/updater_main.h +++ b/applications/updater/views/updater_main.h @@ -17,12 +17,10 @@ void updater_main_model_set_state( UpdaterMainView* main_view, const char* message, uint8_t progress, - uint8_t idx_stage, - uint8_t total_stages, bool failed); void updater_main_set_storage_pubsub(UpdaterMainView* main_view, FuriPubSubSubscription* sub); FuriPubSubSubscription* updater_main_get_storage_pubsub(UpdaterMainView* main_view); -void updater_main_set_view_dispatcher(UpdaterMainView* main_view, ViewDispatcher* view_dispatcher); \ No newline at end of file +void updater_main_set_view_dispatcher(UpdaterMainView* main_view, ViewDispatcher* view_dispatcher); diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index 8b17d078..709fab45 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -642,6 +642,9 @@ const uint8_t* const _I_Drive_112x35[] = {_I_Drive_112x35_0}; const uint8_t _I_Error_62x31_0[] = {0x01,0x00,0x9e,0x00,0x00,0x47,0xc2,0xfe,0x07,0x58,0x66,0x02,0x02,0x07,0x48,0x1c,0x02,0x0c,0x06,0x3c,0x00,0x08,0x61,0x00,0x73,0xa0,0x00,0x86,0x20,0x07,0x39,0x00,0x09,0x01,0x88,0x07,0x70,0xd1,0x09,0x0b,0xe0,0x07,0x38,0x1c,0x62,0x11,0x08,0x80,0x8c,0x8a,0x0f,0x1c,0x82,0x7d,0x20,0x58,0x0b,0xe4,0x02,0x1d,0x0e,0x82,0x6e,0xa0,0xb8,0x0c,0x1c,0x02,0x39,0x07,0x82,0x4e,0xa0,0xb7,0x08,0x04,0x07,0x71,0x03,0x82,0x7e,0xa0,0xb0,0xe8,0x04,0x0b,0xe1,0x01,0x81,0x01,0xc6,0x01,0xc0,0x81,0xf8,0x01,0x42,0x27,0x18,0x04,0xc0,0x1e,0x63,0x71,0x3d,0x0c,0x08,0x3e,0x20,0xa1,0x22,0x94,0x08,0x5e,0x21,0x51,0x0f,0x08,0xbc,0x47,0xe2,0x07,0x29,0x81,0x40,0x49,0xe2,0x07,0x28,0x61,0x80,0x4b,0xe2,0x07,0x28,0x19,0xe0,0xc0,0xe2,0x0d,0x18,0xc0,0x1d,0x00,0x02,0xa8,0x30,0x39,0x2e,0x10,0x0e,0x5e,0x00,0x3b,0x7e,0x00,0xec,0x46,0x10,0x3f,0x80,0xc8,}; const uint8_t* const _I_Error_62x31[] = {_I_Error_62x31_0}; +const uint8_t _I_Updating_32x40_0[] = {0x01,0x00,0x56,0x00,0xc0,0x7f,0xc0,0x03,0xc0,0x01,0x97,0x82,0x07,0x00,0xe0,0x5c,0x00,0x65,0x38,0x01,0x94,0x70,0x06,0x50,0xe0,0x19,0x41,0xc0,0x65,0xff,0x01,0xb4,0x0c,0x02,0x7e,0x08,0x38,0x0c,0x7c,0xd6,0x70,0x18,0xfb,0xfe,0xfc,0x0c,0x18,0xc8,0x78,0x20,0x33,0x81,0x8f,0x8a,0x07,0x3e,0xbe,0x70,0x38,0x71,0xff,0xc7,0x0f,0xc7,0x0f,0xf8,0x71,0xc0,0x76,0x13,0x30,0xd9,0x88,0xcc,0x5f,0x03,0xb2,0x21,0xa1,0x2c,0xc0,0x26,0x82,0x10,0x1f,0x80,0xd1,0x24,0x40,0x04,}; +const uint8_t* const _I_Updating_32x40[] = {_I_Updating_32x40_0}; + const uint8_t _I_DolphinExcited_64x63_0[] = {0x01,0x00,0x36,0x01,0x00,0x25,0x00,0x0f,0xd2,0x00,0x3b,0xe0,0x00,0xeb,0x10,0x0c,0x34,0x40,0x30,0xd0,0x88,0x80,0x1d,0xa1,0x00,0x42,0xfc,0x7f,0xc0,0x63,0x04,0x01,0x0e,0x02,0x0f,0x00,0x00,0x8c,0x08,0x0e,0x37,0x00,0x10,0xc6,0x20,0x10,0x10,0xd9,0x11,0x92,0x1c,0x1a,0x3e,0x00,0x04,0x42,0x02,0x1a,0x20,0xb0,0xce,0x00,0x64,0x07,0x20,0x59,0x16,0x50,0x36,0x45,0x94,0x84,0x78,0x20,0x60,0x75,0x8e,0x43,0x06,0x63,0x3c,0x33,0x94,0x0c,0xd2,0x5c,0x30,0x38,0xe4,0x08,0x43,0x10,0xc0,0x5e,0x06,0x22,0x53,0x1a,0x02,0x08,0x7f,0xd0,0x32,0xc1,0x50,0x21,0x14,0x0e,0x70,0x1c,0x46,0xe2,0x07,0x19,0x06,0x3c,0xdc,0x20,0x91,0xae,0x01,0xcc,0xbe,0x30,0x09,0xfc,0x12,0x41,0xff,0x83,0xcc,0x0a,0xa3,0x1f,0x03,0x99,0xe8,0x7c,0x10,0xf8,0x25,0xa0,0x5e,0x50,0x0f,0x84,0x1e,0x09,0x54,0x03,0x9f,0xf2,0x07,0x02,0xd5,0x11,0xca,0x01,0xfe,0x80,0xc0,0xaa,0x9f,0xf0,0x39,0x5f,0xd0,0x43,0xaa,0x83,0x41,0x92,0xc3,0x1f,0x03,0x8d,0x52,0x02,0x2e,0x25,0xc9,0x6a,0x99,0x46,0xa6,0x2a,0xa0,0x1c,0xaf,0xca,0x62,0x94,0x28,0xcb,0x7e,0x0f,0x15,0x71,0xf8,0x3c,0x22,0x71,0x03,0x8a,0x84,0x67,0x18,0x0f,0xac,0x1c,0x0e,0x38,0x08,0x0c,0x3e,0x01,0xae,0xbd,0x13,0x0c,0x0e,0x35,0x8e,0xa8,0x1c,0xb0,0x1f,0xf8,0x06,0x83,0xf4,0x27,0x38,0x07,0xff,0xff,0x8f,0x03,0xa0,0x4c,0x80,0xed,0x60,0x03,0xb4,0x60,0x0e,0xd0,0x60,0x3a,0x87,0x84,0x0e,0xb7,0xc2,0xfa,0x18,0x05,0x44,0x20,0x73,0xff,0xf7,0xce,0xe4,0x07,0x2d,0x52,0x2c,0x80,0xe7,0x54,0xea,0x81,0xd7,0x50,0x0f,0x7a,0xaa,0x3d,0x41,0xe2,0x07,0x5a,0x80,0x3c,0xa0,0x40,0x72,0xd0,0x6a,0x80,0xa2,0x07,0x3a,0x05,0x54,0x8e,0x20,0x73,0xc0,0x03,0xd8,0x60,0x30,0x40,0x3a,0xc0,0x00,0xee,0xea,0x10,0x3b,0x80,}; const uint8_t* const _I_DolphinExcited_64x63[] = {_I_DolphinExcited_64x63_0}; @@ -835,6 +838,7 @@ const Icon I_Connect_me_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate const Icon I_Connected_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Connected_62x31}; const Icon I_Drive_112x35 = {.width=112,.height=35,.frame_count=1,.frame_rate=0,.frames=_I_Drive_112x35}; const Icon I_Error_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Error_62x31}; +const Icon I_Updating_32x40 = {.width=32,.height=40,.frame_count=1,.frame_rate=0,.frames=_I_Updating_32x40}; const Icon I_DolphinExcited_64x63 = {.width=64,.height=63,.frame_count=1,.frame_rate=0,.frames=_I_DolphinExcited_64x63}; const Icon I_DolphinMafia_115x62 = {.width=115,.height=62,.frame_count=1,.frame_rate=0,.frames=_I_DolphinMafia_115x62}; const Icon I_DolphinNice_96x59 = {.width=96,.height=59,.frame_count=1,.frame_rate=0,.frames=_I_DolphinNice_96x59}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index be1023f6..12ddb78e 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -173,6 +173,7 @@ extern const Icon I_Connect_me_62x31; extern const Icon I_Connected_62x31; extern const Icon I_Drive_112x35; extern const Icon I_Error_62x31; +extern const Icon I_Updating_32x40; extern const Icon I_DolphinExcited_64x63; extern const Icon I_DolphinMafia_115x62; extern const Icon I_DolphinNice_96x59; diff --git a/assets/compiled/flipper.pb.h b/assets/compiled/flipper.pb.h index 88548bea..3199090d 100644 --- a/assets/compiled/flipper.pb.h +++ b/assets/compiled/flipper.pb.h @@ -103,6 +103,7 @@ typedef struct _PB_Main { PB_Storage_BackupRestoreRequest storage_backup_restore_request; PB_System_PowerInfoRequest system_power_info_request; PB_System_PowerInfoResponse system_power_info_response; + PB_System_UpdateResponse system_update_response; } content; } PB_Main; @@ -171,6 +172,7 @@ extern "C" { #define PB_Main_storage_backup_restore_request_tag 43 #define PB_Main_system_power_info_request_tag 44 #define PB_Main_system_power_info_response_tag 45 +#define PB_Main_system_update_response_tag 46 /* Struct field encoding specification for nanopb */ #define PB_Empty_FIELDLIST(X, a) \ @@ -228,7 +230,8 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_request,content.system X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_create_request,content.storage_backup_create_request), 42) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_restore_request,content.storage_backup_restore_request), 43) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_request,content.system_power_info_request), 44) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.system_power_info_response), 45) +X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.system_power_info_response), 45) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_response,content.system_update_response), 46) #define PB_Main_CALLBACK NULL #define PB_Main_DEFAULT NULL #define PB_Main_content_empty_MSGTYPE PB_Empty @@ -273,6 +276,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.s #define PB_Main_content_storage_backup_restore_request_MSGTYPE PB_Storage_BackupRestoreRequest #define PB_Main_content_system_power_info_request_MSGTYPE PB_System_PowerInfoRequest #define PB_Main_content_system_power_info_response_MSGTYPE PB_System_PowerInfoResponse +#define PB_Main_content_system_update_response_MSGTYPE PB_System_UpdateResponse extern const pb_msgdesc_t PB_Empty_msg; extern const pb_msgdesc_t PB_StopSession_msg; diff --git a/assets/compiled/protobuf_version.h b/assets/compiled/protobuf_version.h index 0459d120..6b401411 100644 --- a/assets/compiled/protobuf_version.h +++ b/assets/compiled/protobuf_version.h @@ -1,3 +1,3 @@ #pragma once #define PROTOBUF_MAJOR_VERSION 0 -#define PROTOBUF_MINOR_VERSION 6 +#define PROTOBUF_MINOR_VERSION 7 diff --git a/assets/compiled/system.pb.c b/assets/compiled/system.pb.c index 45ab3a01..e05ff90e 100644 --- a/assets/compiled/system.pb.c +++ b/assets/compiled/system.pb.c @@ -48,6 +48,9 @@ PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AU PB_BIND(PB_System_UpdateRequest, PB_System_UpdateRequest, AUTO) +PB_BIND(PB_System_UpdateResponse, PB_System_UpdateResponse, AUTO) + + PB_BIND(PB_System_PowerInfoRequest, PB_System_PowerInfoRequest, AUTO) @@ -56,3 +59,4 @@ PB_BIND(PB_System_PowerInfoResponse, PB_System_PowerInfoResponse, AUTO) + diff --git a/assets/compiled/system.pb.h b/assets/compiled/system.pb.h index 978219ae..aef2c75b 100644 --- a/assets/compiled/system.pb.h +++ b/assets/compiled/system.pb.h @@ -16,6 +16,17 @@ typedef enum _PB_System_RebootRequest_RebootMode { PB_System_RebootRequest_RebootMode_UPDATE = 2 } PB_System_RebootRequest_RebootMode; +typedef enum _PB_System_UpdateResponse_UpdateResultCode { + PB_System_UpdateResponse_UpdateResultCode_OK = 0, + PB_System_UpdateResponse_UpdateResultCode_ManifestPathInvalid = 1, + PB_System_UpdateResponse_UpdateResultCode_ManifestFolderNotFound = 2, + PB_System_UpdateResponse_UpdateResultCode_ManifestInvalid = 3, + PB_System_UpdateResponse_UpdateResultCode_StageMissing = 4, + PB_System_UpdateResponse_UpdateResultCode_StageIntegrityError = 5, + PB_System_UpdateResponse_UpdateResultCode_ManifestPointerError = 6, + PB_System_UpdateResponse_UpdateResultCode_TargetMismatch = 7 +} PB_System_UpdateResponse_UpdateResultCode; + /* Struct definitions */ typedef struct _PB_System_DeviceInfoRequest { char dummy_field; @@ -84,6 +95,10 @@ typedef struct _PB_System_RebootRequest { PB_System_RebootRequest_RebootMode mode; } PB_System_RebootRequest; +typedef struct _PB_System_UpdateResponse { + PB_System_UpdateResponse_UpdateResultCode code; +} PB_System_UpdateResponse; + typedef struct _PB_System_GetDateTimeResponse { bool has_datetime; PB_System_DateTime datetime; @@ -100,6 +115,10 @@ typedef struct _PB_System_SetDateTimeRequest { #define _PB_System_RebootRequest_RebootMode_MAX PB_System_RebootRequest_RebootMode_UPDATE #define _PB_System_RebootRequest_RebootMode_ARRAYSIZE ((PB_System_RebootRequest_RebootMode)(PB_System_RebootRequest_RebootMode_UPDATE+1)) +#define _PB_System_UpdateResponse_UpdateResultCode_MIN PB_System_UpdateResponse_UpdateResultCode_OK +#define _PB_System_UpdateResponse_UpdateResultCode_MAX PB_System_UpdateResponse_UpdateResultCode_TargetMismatch +#define _PB_System_UpdateResponse_UpdateResultCode_ARRAYSIZE ((PB_System_UpdateResponse_UpdateResultCode)(PB_System_UpdateResponse_UpdateResultCode_TargetMismatch+1)) + #ifdef __cplusplus extern "C" { @@ -120,6 +139,7 @@ extern "C" { #define PB_System_ProtobufVersionRequest_init_default {0} #define PB_System_ProtobufVersionResponse_init_default {0, 0} #define PB_System_UpdateRequest_init_default {NULL} +#define PB_System_UpdateResponse_init_default {_PB_System_UpdateResponse_UpdateResultCode_MIN} #define PB_System_PowerInfoRequest_init_default {0} #define PB_System_PowerInfoResponse_init_default {NULL, NULL} #define PB_System_PingRequest_init_zero {NULL} @@ -136,6 +156,7 @@ extern "C" { #define PB_System_ProtobufVersionRequest_init_zero {0} #define PB_System_ProtobufVersionResponse_init_zero {0, 0} #define PB_System_UpdateRequest_init_zero {NULL} +#define PB_System_UpdateResponse_init_zero {_PB_System_UpdateResponse_UpdateResultCode_MIN} #define PB_System_PowerInfoRequest_init_zero {0} #define PB_System_PowerInfoResponse_init_zero {NULL, NULL} @@ -157,6 +178,7 @@ extern "C" { #define PB_System_ProtobufVersionResponse_major_tag 1 #define PB_System_ProtobufVersionResponse_minor_tag 2 #define PB_System_RebootRequest_mode_tag 1 +#define PB_System_UpdateResponse_code_tag 1 #define PB_System_GetDateTimeResponse_datetime_tag 1 #define PB_System_SetDateTimeRequest_datetime_tag 1 @@ -241,6 +263,11 @@ X(a, POINTER, SINGULAR, STRING, update_manifest, 1) #define PB_System_UpdateRequest_CALLBACK NULL #define PB_System_UpdateRequest_DEFAULT NULL +#define PB_System_UpdateResponse_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, code, 1) +#define PB_System_UpdateResponse_CALLBACK NULL +#define PB_System_UpdateResponse_DEFAULT NULL + #define PB_System_PowerInfoRequest_FIELDLIST(X, a) \ #define PB_System_PowerInfoRequest_CALLBACK NULL @@ -266,6 +293,7 @@ extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg; extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg; extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg; extern const pb_msgdesc_t PB_System_UpdateRequest_msg; +extern const pb_msgdesc_t PB_System_UpdateResponse_msg; extern const pb_msgdesc_t PB_System_PowerInfoRequest_msg; extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; @@ -284,6 +312,7 @@ extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; #define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg #define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg #define PB_System_UpdateRequest_fields &PB_System_UpdateRequest_msg +#define PB_System_UpdateResponse_fields &PB_System_UpdateResponse_msg #define PB_System_PowerInfoRequest_fields &PB_System_PowerInfoRequest_msg #define PB_System_PowerInfoResponse_fields &PB_System_PowerInfoResponse_msg @@ -304,6 +333,7 @@ extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; #define PB_System_ProtobufVersionResponse_size 12 #define PB_System_RebootRequest_size 2 #define PB_System_SetDateTimeRequest_size 24 +#define PB_System_UpdateResponse_size 2 #ifdef __cplusplus } /* extern "C" */ diff --git a/assets/icons/Update/Updating_32x40.png b/assets/icons/Update/Updating_32x40.png new file mode 100644 index 00000000..d8f7654b Binary files /dev/null and b/assets/icons/Update/Updating_32x40.png differ diff --git a/assets/protobuf b/assets/protobuf index 0ad90705..ffa62429 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 0ad90705b9434b6f8fb2c4b605069f0d56d8cc70 +Subproject commit ffa62429f3c678537e0e883a3a8c3ae5f1398ed4 diff --git a/assets/resources/Manifest b/assets/resources/Manifest index f19edd7d..08d95044 100644 --- a/assets/resources/Manifest +++ b/assets/resources/Manifest @@ -1,8 +1,9 @@ V:0 -T:1651076680 +T:1651524332 D:badusb D:dolphin D:infrared +D:music_player D:nfc D:subghz D:u2f @@ -223,6 +224,7 @@ F:f267f0654781049ca323b11bb4375519:581:dolphin/L3_Lab_research_128x54/frame_9.bm F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt D:infrared/assets F:d895fda2f48c6cc4c55e8a398ff52e43:74300:infrared/assets/tv.ir +F:a157a80f5a668700403d870c23b9567d:470:music_player/Marble_Machine.fmf D:nfc/assets F:c6826a621d081d68309e4be424d3d974:4715:nfc/assets/aid.nfc F:86efbebdf41bb6bf15cc51ef88f069d5:2565:nfc/assets/country_code.nfc diff --git a/assets/resources/music_player/Marble_Machine.fmf b/assets/resources/music_player/Marble_Machine.fmf new file mode 100644 index 00000000..7403c9a0 --- /dev/null +++ b/assets/resources/music_player/Marble_Machine.fmf @@ -0,0 +1,6 @@ +Filetype: Flipper Music Format +Version: 0 +BPM: 130 +Duration: 8 +Octave: 5 +Notes: E6, P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6, 4P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6 diff --git a/assets/unit_tests/subghz/firefly_raw.sub b/assets/unit_tests/subghz/firefly_raw.sub new file mode 100644 index 00000000..c143fa02 --- /dev/null +++ b/assets/unit_tests/subghz/firefly_raw.sub @@ -0,0 +1,11 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 300000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 361 -4326 2555 -28090 65 -302 65 -1890 131 -2062 2547 -95068 2565 -48020 67 -47036 2551 -30016 2561 -47778 67 -14884 2481 -95118 2537 -95132 2549 -48496 65 -21526 2571 -16342 97 -4142 65 -1938 2543 -95008 2551 -44030 1579 -548 1469 -588 433 -1568 469 -1540 479 -1550 1489 -538 473 -1574 1467 -538 1493 -566 443 -22130 693 -3742 321 -1702 341 -1690 1353 -628 391 -1666 1401 -584 1445 -596 391 -22192 1487 -554 1471 -550 447 -1584 453 -1568 445 -1578 1469 -550 459 -1598 1465 -540 1461 -576 445 -22164 1479 -546 1501 -544 453 -1568 447 -1580 445 -1584 1451 -560 443 -1594 1473 -548 1479 -556 441 -22160 1475 -548 1487 -554 449 -1578 451 -1586 451 -1572 1469 -552 449 -1578 1473 -558 1469 -552 449 -22142 1507 -546 1479 -548 457 -1574 447 -1580 447 -1584 1475 -554 441 -1592 1465 -546 1473 -546 483 -22132 1157 -1082 67 -166 65 -198 65 -1150 257 -1706 339 -1666 365 -1642 1409 -610 407 -1626 1417 -620 1435 -580 409 -22184 1495 -572 1463 -552 447 -1584 453 -1574 447 -1580 1473 -548 459 -1568 1501 -520 1501 -552 463 -22124 535 -7674 339 -1680 1345 -678 361 -1664 1395 -618 1411 -646 373 -22194 1511 -526 1477 -550 483 -1542 479 -1562 471 -1566 1483 -546 445 -1574 1471 -534 1497 -548 483 -169938 2539 -89172 167 -5768 2551 -93014 967 -252 1571 -5844 2503 -87590 65 -5948 2523 -64008 1605 -520 1473 -554 449 -1584 449 -1576 447 -1546 1505 -546 451 -1574 1469 -546 1475 -548 459 -22160 1525 -506 1501 -516 479 -1550 469 -1570 469 -1570 1471 -538 471 -1568 1489 -516 1501 -554 443 -22152 1507 -522 1511 -518 481 -1580 451 -1542 483 -1548 1505 -546 451 -1570 1471 -552 1473 -548 455 -22180 1505 -522 1501 -544 451 -1560 475 -1548 481 -1556 1477 -552 475 -1546 1505 -516 1517 -516 473 -22148 1515 -518 1499 -546 485 -1570 443 -1580 447 -1582 1475 -526 483 -1548 1507 -546 1479 -558 449 -22138 1495 -586 1437 -616 403 -1594 429 -1608 417 -1606 1465 -556 433 -1606 1465 -536 1499 -544 445 -22170 1401 -792 1245 -770 271 -1716 325 -1680 359 -1664 1397 -620 393 -1644 1407 -614 1433 -586 429 -22202 1477 -572 1469 -548 449 -1576 457 -1578 479 -1544 1473 -590 429 -1570 1491 -540 1509 -554 429 -22196 1481 -556 1467 -580 439 -1592 431 -1608 415 -1608 1441 -586 463 -1568 1467 -552 1489 -534 473 -22166 1485 -574 1469 -580 453 -1572 443 -1578 447 -1578 1477 -554 447 -1580 1479 -550 1481 -550 475 -22160 1525 -542 1467 -540 483 -1574 447 -1582 451 -1578 1481 -558 447 -1560 1493 -550 1505 -544 449 -22182 1435 -646 1391 -664 369 -1642 385 -1652 395 -1600 1463 -584 417 -1606 1467 -576 1443 -586 429 -148588 275 -106 847 -128 877 -100 281 -97826 2541 -92318 2505 -12474 2563 -73674 2555 -41600 2543 -76554 1601 -516 1471 -554 +RAW_Data: 487 -1556 453 -1570 441 -1590 1467 -556 469 -1538 1501 -522 1501 -552 463 -22124 1513 -514 1509 -548 445 -1582 461 -1568 443 -1574 1467 -536 465 -1574 1499 -516 1503 -556 441 -22150 1537 -484 1495 -544 479 -1558 459 -1574 447 -1580 1471 -548 459 -1576 1471 -554 1471 -550 459 -22160 1517 -516 1503 -546 447 -1574 473 -1546 481 -1576 1479 -520 467 -1572 1497 -550 1469 -556 441 -22156 1533 -528 1495 -530 469 -1568 445 -1566 485 -1548 1505 -544 451 -1572 1471 -554 1503 -516 495 -22160 1511 -520 1477 -546 483 -1542 485 -1546 481 -1542 1509 -526 455 -1578 1507 -544 1481 -524 485 -22146 1543 -510 1481 -552 475 -1546 473 -1568 481 -1540 1503 -522 473 -1556 1507 -558 1491 -518 479 -22164 1523 -520 1503 -544 453 -1566 479 -1550 469 -1572 1493 -546 447 -1576 1477 -552 1509 -544 451 -22178 639 -596 65 -926 63 -1954 237 -1680 355 -1670 383 -1636 1423 -596 439 -1578 1471 -574 1465 -576 445 -22182 1439 -676 1335 -702 339 -1648 387 -1648 409 -1608 1429 -618 419 -1612 1447 -578 1439 -614 425 -22186 1497 -530 1505 -556 471 -1540 479 -1582 431 -1570 1497 -546 481 -1536 1497 -554 1501 -556 463 -22178 1503 -566 1433 -586 433 -1604 445 -1576 441 -1580 1503 -548 453 -1572 1473 -578 1467 -558 469 -149080 311 -1034 895 -1084 939 -1006 337 -78790 97 -6890 2535 -28048 2511 -64482 2573 -88138 65 -6956 2515 -95140 2509 -61986 1589 -522 1475 -548 449 -1576 475 -1548 481 -1546 1475 -564 443 -1564 1477 -580 1477 -554 449 -22166 1503 -532 1481 -544 447 -1576 449 -1572 473 -1548 1473 -580 451 -1568 1463 -552 1477 -552 461 -22164 1521 -528 1493 -548 443 -1580 461 -1540 475 -1574 1473 -554 471 -1568 1489 -516 1497 -538 471 -22154 1385 -786 1245 -796 261 -1702 341 -1650 391 -1644 1411 -608 409 -1620 1415 -624 1409 -614 413 -22178 1533 -498 1519 -546 445 -1576 449 -1578 457 -1568 1503 -546 451 -1570 1467 -554 1503 -552 463 -22162 1401 -774 1257 -754 297 -1678 353 -1650 383 -1666 1397 -618 385 -1642 1437 -612 1433 -586 427 -22194 1483 -552 1477 -546 485 -1544 453 -1576 481 -1576 1479 -560 449 -1548 1507 -546 1479 -558 447 -22170 1413 -786 1245 -776 295 -1664 337 -1680 387 -1652 1385 -638 407 -1614 1441 -582 1451 -606 409 -22204 1503 -528 1507 -550 465 -1534 481 -1584 429 -1572 1497 -548 447 -1580 1481 -550 1503 -546 455 -22166 1519 -552 1469 -580 419 -1612 419 -1596 447 -1582 1479 -554 447 -1582 1479 -550 1519 -518 479 -134730 169 -172 559 -194 579 -676 257 -87040 99 -7384 2269 -488 313 -37888 65 -12084 2515 -33298 2247 -474 309 -42656 63 -51970 2233 -456 309 -94658 2233 -430 325 -90692 357 -186 2417 -518 1517 -514 475 -1550 467 -1570 471 -1538 1499 -556 443 -1564 1483 -552 1501 -524 +RAW_Data: 481 -22144 1433 -668 1373 -666 337 -1680 355 -1634 383 -1634 1431 -622 399 -1606 1443 -582 1443 -586 431 -22166 1521 -512 1497 -548 447 -1580 459 -1568 447 -1574 1473 -554 465 -1572 1497 -516 1507 -554 453 -22148 1503 -540 1489 -546 479 -1542 449 -1578 457 -1576 1475 -546 483 -1540 1507 -552 1473 -548 453 -22154 1539 -516 1469 -586 431 -1574 447 -1576 479 -1558 1485 -554 439 -1580 1501 -550 1457 -552 473 -22154 1521 -550 1485 -540 447 -1578 457 -1578 447 -1572 1471 -556 485 -1540 1483 -552 1501 -556 443 -22186 1437 -662 1345 -704 339 -1688 361 -1646 375 -1640 1399 -616 421 -1612 1441 -614 1435 -586 429 -22200 1513 -520 1503 -544 453 -1572 447 -1580 483 -1550 1475 -552 475 -1548 1501 -554 1491 -540 475 -22184 1499 -530 1485 -548 457 -1570 477 -1578 443 -1576 1501 -546 449 -1562 1499 -538 1493 -572 443 -22166 1471 -612 1429 -624 401 -1608 417 -1620 431 -1600 1461 -582 419 -1610 1441 -582 1473 -548 459 -205658 1761 -436 863 -68558 2597 -23434 1775 -438 519 -94592 1803 -422 829 -86706 1727 -434 527 -66 319 -94536 1753 -444 865 -238 1489 -652 1385 -656 357 -1668 365 -1628 403 -1612 1439 -614 403 -1626 1425 -588 1443 -584 409 -22168 1531 -528 1491 -530 469 -1568 443 -1564 483 -1538 1505 -546 455 -1570 1469 -556 1503 -518 491 -22128 1455 -660 1359 -686 355 -1632 385 -1632 411 -1640 1411 -596 423 -1606 1437 -580 1443 -596 423 -22188 1495 -550 1467 -534 473 -1566 481 -1540 483 -1572 1477 -552 449 -1582 1477 -558 1471 -552 449 -22174 543 -3692 235 -1680 357 -1668 353 -1698 1375 -636 371 -1644 1409 -610 1437 -578 449 -22180 1499 -542 1491 -542 479 -1540 481 -1566 449 -1562 1499 -554 465 -1568 1463 -554 1493 -536 473 -22168 1405 -774 1257 -788 267 -1676 355 -1672 369 -1660 1387 -624 417 -1606 1427 -624 1425 -586 415 -22208 1507 -552 1489 -548 443 -1562 483 -1550 481 -1546 1505 -558 447 -1586 1473 -548 1481 -554 479 -22166 1383 -786 1245 -776 295 -1664 373 -1646 387 -1644 1403 -642 411 -1624 1417 -594 1445 -612 409 -22210 1515 -516 1503 -554 453 -1564 457 -1572 447 -1580 1501 -554 465 -1570 1467 -554 1493 -570 443 -195814 1353 -442 1267 -37900 99 -53710 411 -142 2207 -8336 2487 -46990 1301 -452 1317 -86162 65 -8376 1289 -444 1327 -94552 1311 -488 1251 -1726 1531 -544 1467 -580 417 -1578 457 -1578 443 -1576 1475 -566 441 -1568 1503 -512 1509 -526 455 -22168 1473 -582 1469 -538 483 -1538 459 -1574 447 -1580 1471 -582 429 -1572 1469 -552 1473 -548 461 -22170 1437 -640 1401 -620 393 -1636 385 -1634 409 -1604 1457 -588 415 -1608 1431 -590 1459 -554 449 -22188 1483 -556 1487 -542 445 -1578 459 -1576 443 -1574 1473 -556 469 -1570 1459 -550 1503 -554 443 -22160 1469 -590 +RAW_Data: 1469 -582 409 -1620 429 -1608 415 -1602 1455 -568 441 -1578 1475 -552 1479 -560 467 -22166 1483 -572 1463 -546 451 -1580 453 -1580 481 -1542 1475 -588 451 -1570 1453 -550 1503 -540 469 -22158 1505 -554 1475 -554 487 -1556 453 -1562 477 -1546 1495 -546 479 -1544 1511 -554 1477 -532 471 -22180 1471 -602 1437 -602 407 -1610 421 -1614 421 -1606 1433 -582 457 -1578 1475 -550 1469 -586 465 -22164 1515 -546 1469 -546 483 -1572 447 -1558 471 -1580 1471 -578 451 -1568 1495 -542 1497 -530 471 -22194 1433 -644 1393 -662 371 -1640 385 -1642 413 -1628 1431 -584 431 -1602 1469 -540 1501 -576 443 -22180 1479 -592 1439 -608 407 -1620 427 -1610 415 -1606 1465 -570 441 -1612 1441 -586 1451 -576 445 -22196 1533 -522 1489 -540 477 -1574 481 -1544 455 -1568 1505 -546 459 -1572 1501 -556 1497 -530 471 -210202 685 -540 475 -138 839 -138 239 -9950 2501 -71112 761 -462 511 -66 1297 -85614 97 -8850 745 -466 1821 -94546 827 -468 481 -140 815 -164 237 -32934 1583 -540 1477 -554 441 -1582 447 -1580 453 -1568 1465 -554 479 -1556 1487 -558 1477 -550 453 -22174 1503 -516 1483 -584 429 -1572 449 -1576 447 -1588 1475 -558 449 -1580 1473 -546 1485 -556 449 -22168 1469 -586 1443 -614 401 -1624 401 -1608 415 -1608 1463 -570 441 -1574 1471 -586 1449 -572 445 -22164 1401 -772 1255 -756 301 -1674 353 -1708 329 -1662 1397 -650 387 -1632 1405 -614 1433 -584 431 -22200 1489 -566 1463 -582 419 -1580 457 -1596 447 -1576 1473 -554 443 -1580 1469 -582 1451 -550 479 -22174 1387 -786 1251 -792 257 -1704 331 -1690 337 -1706 1377 -632 395 -1632 1433 -586 1451 -584 413 -22198 1541 -512 1485 -554 481 -1574 445 -1560 461 -1568 1495 -556 469 -1568 1495 -518 1503 -554 469 -22160 1541 -516 1501 -556 443 -1564 495 -1536 479 -1550 1517 -544 445 -1576 1507 -556 1485 -542 445 -22202 1501 -530 1503 -554 465 -1574 445 -1582 461 -1574 1469 -546 479 -1568 1471 -556 1513 -550 463 -22170 1473 -614 1419 -602 439 -1614 417 -1610 415 -1590 1465 -588 429 -1606 1469 -586 1455 -570 441 -22200 1407 -760 1277 -772 267 -1692 363 -1678 355 -1668 1393 -660 369 -1642 1441 -584 1449 -574 445 -22206 1533 -528 1497 -530 471 -1572 449 -1576 455 -1578 1507 -544 455 -1572 1503 -556 1467 -560 469 -22188 1439 -678 1347 -672 375 -1648 393 -1646 387 -1636 1431 -588 431 -1610 1439 -618 1437 -596 437 -143610 67 -510 99 -66 223 -272 173 -70 273 -204 235 -64 483 -26542 2521 -65448 297 -348 2417 -76720 65 -8388 65 -9450 203 -332 587 -72 885 -92 899 -27534 67 -39500 221 -406 521 -72 885 -98 919 -29920 1581 -534 1491 -548 445 -1580 461 -1544 477 -1574 1465 -556 473 -1568 1455 -554 1501 -524 483 -22136 1529 -498 +RAW_Data: 1493 -576 441 -1568 469 -1574 447 -1576 1465 -548 481 -1544 1503 -542 1473 -554 449 -22176 1499 -530 1505 -554 463 -1540 479 -1546 479 -1558 1483 -556 449 -1580 1473 -548 1483 -552 447 -22198 1511 -508 1507 -554 441 -1580 453 -1586 453 -1576 1473 -548 451 -1586 1475 -554 1499 -554 445 -22180 1503 -526 1481 -550 481 -1544 485 -1574 449 -1566 1479 -548 461 -1572 1503 -540 1499 -530 471 -22192 1499 -530 1475 -584 433 -1572 475 -1586 429 -1570 1495 -548 449 -1578 1473 -552 1505 -546 455 -22202 1499 -544 1469 -562 471 -1570 447 -1580 457 -1568 1505 -544 451 -1574 1471 -554 1503 -554 465 -22160 1533 -530 1485 -548 459 -1600 443 -1576 441 -1580 1505 -544 455 -1568 1497 -556 1495 -530 473 -22200 1499 -544 1491 -544 479 -1572 451 -1572 447 -1578 1479 -550 493 -1564 1465 -590 1451 -576 445 -22198 1531 -532 1483 -548 479 -1542 483 -1576 449 -1562 1501 -554 465 -1574 1469 -556 1491 -572 445 -22196 1533 -528 1495 -532 473 -1574 449 -1580 457 -1576 1505 -546 453 -1572 1503 -556 1465 -558 471 -22200 1499 -530 1517 -552 463 -1568 445 -1580 457 -1578 1471 -578 451 -1574 1473 -554 1503 -556 469 -22188 1501 -554 1473 -544 479 -1592 461 -1568 447 -1576 1493 -552 453 -1584 1475 -554 1503 -554 471 -141048 233 -68 741 -68 133 -100 467 -49002 2539 -43448 2529 -91062 2557 -95072 2545 -89712 641 -300 1759 -3612 463 -9880 1221 -712 327 -1694 1367 -616 1445 -582 409 -22192 1505 -522 1497 -554 447 -1584 455 -1570 449 -1578 1473 -548 459 -1572 1475 -576 1465 -554 469 -22142 1507 -526 1509 -548 455 -1574 447 -1578 447 -1580 1479 -554 441 -1580 1467 -584 1457 -554 445 -22200 1513 -510 1509 -526 473 -1562 481 -1554 455 -1574 1473 -544 479 -1556 1481 -550 1497 -554 453 -22156 1529 -524 1497 -552 453 -1588 451 -1574 449 -1582 1475 -546 455 -1572 1505 -520 1503 -554 465 -22156 1537 -516 1485 -548 459 -1570 481 -1550 467 -1570 1495 -548 447 -1576 1493 -552 1481 -548 459 -22194 1513 -524 1481 -578 453 -1574 451 -1564 485 -1558 1477 -556 449 -1580 1471 -582 1491 -516 479 -22170 1535 -530 1499 -548 449 -1580 457 -1574 445 -1576 1511 -554 431 -1572 1497 -548 1507 -556 429 -22194 1523 -546 1473 -568 429 -1598 443 -1606 451 -1574 1471 -546 485 -1562 1481 -554 1503 -540 471 -22190 1387 -788 1277 -776 263 -1696 335 -1680 385 -1652 1385 -638 407 -1614 1445 -594 1445 -612 411 -22212 1541 -518 1499 -554 445 -1562 461 -1568 475 -1560 1495 -554 481 -1556 1487 -552 1507 -556 443 -22214 1521 -514 1507 -552 451 -1570 461 -1606 447 -1578 1483 -556 467 -1572 1471 -552 1491 -574 445 -22232 1507 -528 1481 -562 473 -1574 447 -1580 457 -1578 1505 -546 459 -1574 1471 -588 1461 -562 473 -22200 1431 -694 +RAW_Data: 1341 -740 305 -1690 361 -1644 387 -1670 1391 -626 403 -1644 1441 -598 1443 -608 411 -22244 1515 -518 1501 -552 439 -1598 469 -1572 447 -1576 1495 -554 453 -1586 1475 -552 1501 -554 467 -182986 65 -11040 2545 -94994 2537 -94978 2557 -10004 2527 -82554 2547 -84234 65 -10744 2497 -32446 1555 -544 1479 -558 421 -1608 447 -1582 451 -1542 1509 -552 449 -1548 1507 -528 1479 -550 481 -22134 1537 -518 1483 -548 457 -1566 477 -1574 441 -1572 1465 -552 481 -1576 1445 -586 1453 -552 477 -22154 1519 -522 1503 -546 449 -1570 441 -1578 485 -1558 1481 -558 449 -1550 1505 -544 1479 -558 449 -22154 1515 -542 1479 -556 447 -1594 459 -1544 475 -1570 1467 -558 469 -1566 1491 -548 1465 -558 487 -22132 1403 -776 1249 -800 271 -1678 357 -1648 393 -1634 1399 -650 389 -1610 1441 -610 1437 -584 429 -22204 1499 -528 1505 -552 463 -1574 447 -1578 443 -1558 1485 -552 479 -1548 1491 -574 1467 -546 483 -22168 1453 -632 1431 -614 389 -1614 419 -1634 411 -1584 1453 -616 391 -1636 1431 -582 1479 -554 443 -22204 887 -198 67 -950 65 -194 63 -200 65 -498 65 -910 261 -1696 339 -1646 387 -1650 1417 -640 377 -1614 1441 -612 1439 -618 401 -22186 1539 -516 1505 -556 437 -1596 463 -1572 447 -1582 1477 -546 481 -1540 1505 -552 1499 -554 453 -22184 1529 -500 1497 -586 431 -1570 471 -1576 447 -1576 1477 -552 481 -1580 1479 -558 1473 -554 481 -168716 2521 -95042 2539 -94986 2535 -25722 2535 -26624 2505 -18626 99 -76268 2541 -94974 2559 -17198 65 -6348 67 -42186 2539 -17892 131 -93800 99 -394 65 -7158 1331 -448 \ No newline at end of file diff --git a/assets/unit_tests/subghz/firely.sub b/assets/unit_tests/subghz/firely.sub new file mode 100644 index 00000000..a38c21df --- /dev/null +++ b/assets/unit_tests/subghz/firely.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 300000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Firefly +Bit: 10 +Key: 00 00 00 00 00 00 01 E4 diff --git a/assets/unit_tests/subghz/holtek.sub b/assets/unit_tests/subghz/holtek.sub new file mode 100644 index 00000000..b77a759d --- /dev/null +++ b/assets/unit_tests/subghz/holtek.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 418000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Holtek +Bit: 40 +Key: 00 00 00 50 00 00 AA BA diff --git a/assets/unit_tests/subghz/holtek_raw.sub b/assets/unit_tests/subghz/holtek_raw.sub new file mode 100644 index 00000000..8eac0a39 --- /dev/null +++ b/assets/unit_tests/subghz/holtek_raw.sub @@ -0,0 +1,19 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 418000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 2243 -98 331 -100 1129 -66 761 -100 1393 -100 165 -66 2883 -64 357 -66 4703 -68 927 -98 233 -134 461 -66 3855 -134 165 -98 1281 -100 2053 -66 3061 -98 331 -98 8981 -66 365 -66 631 -100 1027 -100 4521 -134 597 -66 3187 -66 2619 -100 3011 -98 1151 -66 953 -100 1423 -66 1755 -166 333 -98 1557 -66 761 -66 865 -66 4837 -132 357 -132 2419 -100 1023 -66 65 -66 2507 -66 131 -66 761 -66 997 -66 333 -100 2259 -68 431 -100 2523 -66 987 -100 363 -66 363 -66 1197 -68 1589 -164 951 -96 5351 -66 697 -100 163 -100 4683 -66 2265 -68 2051 -64 457 -64 3005 -132 1057 -66 2221 -100 1661 -98 695 -100 99 -66 861 -66 1957 -100 731 -132 1857 -100 3177 -98 1807 -98 463 -66 499 -134 1129 -100 3737 -100 1889 -66 263 -98 623 -66 2103 -98 3165 -66 131 -100 195 -66 691 -66 67 -132 531 -66 1857 -100 199 -68 97 -68 197 -68 697 -68 233 -100 3749 -134 1691 -68 3289 -66 3751 -68 65 -100 853 -66 531 -132 1299 -66 1585 -98 65 -98 1577 -66 785 -98 1151 -66 165 -68 397 -100 4255 -100 857 -100 1017 -66 1575 -130 1255 -234 1923 -66 199 -102 301 -66 231 -66 691 -64 227 -64 195 -66 1257 -100 2353 -100 235 -100 1163 -66 5423 -66 2049 -66 1807 -66 523 -198 693 -100 367 -100 597 -100 4013 -100 233 -166 365 -66 1827 -100 1491 -100 785 -64 885 -66 599 -134 2847 -100 667 -100 4943 -98 3319 -98 6729 -98 361 -96 391 -66 723 -132 503 -66 1583 -166 297 -234 2045 -66 1185 -134 661 -66 195 -66 291 -164 523 -98 1679 -134 233 -132 761 -394 855 -100 2003 -164 261 -66 229 -96 953 -66 3889 -66 929 -66 993 -68 3099 -132 1673 -66 1833 -100 563 -100 1131 -100 3219 -232 4411 -100 1095 -100 5315 -100 631 -198 461 -198 1907 -100 1743 -68 863 -132 4013 -64 295 -66 3883 -100 2707 -198 923 -100 2539 -166 629 -100 563 -100 3783 -68 893 -66 2987 -98 2357 -98 1665 -66 599 -66 1259 -232 165 -66 1361 -66 1645 -166 1543 -66 565 -66 401 -134 465 -100 831 -98 2405 -100 1055 -66 2109 -100 1161 -68 431 -100 265 -68 235 -66 463 -66 3453 -100 433 -66 2693 -132 263 -166 729 -134 763 -134 1327 -100 397 -234 795 -68 563 -66 1625 -98 267 -66 4835 -66 197 -66 589 -66 7575 -100 1959 -100 131 -68 297 -134 261 -98 433 -66 1427 -66 2421 -100 2925 -166 1921 -134 1645 -66 97 -132 5423 -100 2423 -98 1065 -66 1715 -132 963 -66 2403 -66 1117 -328 1981 -66 527 -100 427 -164 865 -66 2129 -232 165 -68 165 -66 131 -366 131 -100 2613 -450 +RAW_Data: 937 -900 447 -454 969 -884 479 -466 939 -452 935 -454 981 -454 943 -452 955 -458 945 -452 979 -444 943 -486 945 -448 951 -464 977 -440 967 -478 935 -480 951 -456 969 -460 975 -450 973 -450 979 -470 977 -450 981 -910 485 -466 939 -928 489 -448 971 -940 445 -484 951 -928 485 -484 945 -948 479 -456 973 -918 481 -944 451 -928 471 -478 995 -912 487 -472 977 -15948 479 -444 1021 -910 521 -444 995 -942 471 -480 991 -450 1013 -452 1023 -446 1001 -484 981 -486 1007 -458 1015 -470 1007 -450 1033 -452 1005 -480 1005 -458 1013 -470 1007 -482 1015 -450 1023 -482 1009 -462 1015 -468 1011 -484 983 -482 1021 -944 487 -484 1015 -942 471 -486 1003 -948 503 -478 991 -948 501 -478 1031 -914 521 -486 991 -946 519 -916 511 -944 485 -474 1009 -974 487 -482 1015 -16224 521 -468 1005 -970 503 -478 1001 -954 505 -458 1035 -484 1019 -482 1039 -482 1019 -486 1031 -490 1009 -478 1033 -486 1033 -486 1011 -494 1039 -478 1039 -450 1049 -486 1033 -488 1005 -476 1071 -448 1067 -486 1017 -468 1045 -482 1045 -484 1015 -952 515 -482 1043 -944 519 -482 1049 -950 519 -454 1039 -956 523 -484 1011 -960 505 -486 1065 -956 509 -926 539 -944 519 -480 1017 -984 521 -454 1037 -16440 553 -440 1043 -976 507 -460 1069 -940 513 -486 1041 -480 1067 -482 1033 -476 1061 -472 1043 -510 1049 -486 1041 -482 1043 -482 1065 -476 1037 -486 1069 -492 1037 -484 1047 -504 1047 -486 1041 -484 1041 -514 1015 -520 1049 -476 1053 -490 1041 -980 519 -486 1043 -962 507 -482 1049 -994 507 -500 1043 -946 507 -516 1033 -982 517 -478 1049 -984 509 -976 505 -950 527 -490 1039 -980 519 -486 1047 -111258 195 -428 263 -162 163 -362 97 -132 65 -98 163 -132 825 -100 795 -100 1795 -134 587 -66 229 -100 1349 -164 3261 -66 2305 -132 2219 -66 5549 -234 497 -132 201 -66 667 -298 2369 -68 4381 -66 3909 -134 923 -98 723 -100 1651 -168 1197 -100 65 -66 199 -68 195 -100 197 -134 1135 -66 2787 -66 3163 -68 231 -68 197 -100 6675 -100 667 -98 1125 -66 67 -98 2423 -66 2017 -332 2949 -100 1129 -68 1655 -100 1229 -66 1285 -130 163 -132 1315 -66 525 -98 295 -100 131 -64 427 -132 2207 -98 1153 -66 99 -100 697 -98 1397 -166 863 -66 1393 -132 5005 -66 497 -100 1753 -100 597 -66 1667 -66 397 -100 961 -66 763 -134 859 -64 689 -98 1917 -134 199 -234 167 -100 131 -166 2061 -66 1521 -98 759 -100 983 -66 825 -166 459 -66 2049 -166 1615 -100 829 -234 631 -66 465 -66 1493 -68 433 -66 1623 -132 65 -100 1133 -132 3083 -66 199 -132 199 -68 1257 -66 +RAW_Data: 265 -68 1061 -98 533 -100 1233 -68 1721 -68 995 -100 2535 -66 4193 -232 727 -100 727 -100 2773 -66 133 -98 399 -134 233 -232 67 -66 497 -100 267 -132 1127 -134 1063 -66 565 -132 97 -132 523 -132 919 -66 891 -66 855 -98 495 -66 3363 -296 3199 -98 563 -66 133 -100 495 -98 1165 -134 1161 -166 1849 -98 853 -132 5647 -134 563 -98 1827 -100 131 -100 1125 -132 1659 -132 265 -68 1121 -66 465 -232 431 -68 3589 -98 197 -68 97 -164 1717 -66 1645 -66 397 -66 97 -68 231 -166 631 -100 627 -66 1757 -66 131 -164 527 -98 1285 -328 1213 -134 2059 -100 1791 -68 931 -66 1611 -66 1511 -66 2211 -66 2597 -100 2545 -98 197 -162 1089 -98 589 -360 495 -132 1685 -202 1095 -100 729 -100 2825 -100 231 -100 567 -100 231 -66 1027 -66 131 -68 525 -132 1613 -232 461 -232 1597 -66 627 -198 231 -98 131 -98 65 -100 1229 -68 2507 -64 1349 -66 195 -134 97 -66 1321 -100 855 -132 163 -132 1151 -100 1025 -164 329 -66 891 -98 951 -132 163 -166 591 -98 1149 -132 955 -66 1329 -98 923 -66 331 -64 4269 -66 797 -134 399 -98 267 -170 197 -100 429 -198 1225 -100 331 -100 231 -132 1463 -100 597 -164 331 -66 1863 -134 659 -98 5507 -100 719 -100 131 -64 655 -164 1579 -98 1423 -130 1381 -98 1317 -132 467 -66 495 -132 361 -132 4417 -98 631 -364 299 -100 1499 -132 267 -68 663 -98 691 -100 2433 -66 953 -98 721 -66 1355 -232 897 -134 897 -134 365 -100 267 -132 2059 -132 199 -102 797 -68 695 -66 601 -66 265 -68 499 -66 1327 -164 1355 -64 1279 -66 3257 -66 1351 -66 131 -96 359 -132 499 -232 623 -96 427 -68 1909 -98 591 -98 4671 -100 4541 -66 1491 -66 3347 -98 1277 -100 1679 -198 295 -130 357 -98 697 -98 865 -100 2817 -66 329 -98 787 -64 1117 -66 3313 -202 1721 -100 199 -100 399 -66 199 -132 1891 -100 235 -100 201 -134 765 -166 761 -132 1529 -66 629 -202 861 -130 3501 -98 1377 -100 1741 -164 1509 -66 735 -68 733 -66 265 -166 2015 -134 131 -100 663 -100 2995 -132 1577 -98 1885 -66 2461 -100 1189 -66 1425 -100 201 -100 1691 -100 199 -98 499 -166 233 -100 233 -134 661 -68 1393 -100 295 -164 2079 -66 1289 -66 329 -198 599 -100 465 -98 3995 -98 199 -268 2045 -264 199 -66 1593 -66 165 -68 1561 -164 629 -66 635 -100 1251 -230 2733 -66 1727 -66 629 -100 1229 -132 731 -66 163 -198 131 -100 693 -66 3223 -68 565 -132 1091 -134 531 -100 3223 -68 729 -100 1527 -134 895 -166 1265 -66 527 -100 201 -200 1463 -66 1233 -132 +RAW_Data: 2397 -200 167 -234 1803 -66 821 -100 1351 -66 1687 -100 165 -66 233 -66 1125 -100 2203 -132 197 -98 97 -66 593 -164 4187 -102 529 -66 1161 -68 799 -66 427 -232 263 -66 589 -68 495 -68 197 -100 525 -66 327 -98 427 -130 1551 -66 727 -102 133 -234 265 -98 459 -66 2337 -64 585 -68 297 -68 691 -98 1857 -134 665 -132 365 -66 931 -166 495 -430 689 -196 1191 -98 465 -100 931 -366 1351 -102 3185 -164 1151 -98 2465 -66 2193 -100 331 -134 165 -98 267 -166 1985 -98 889 -132 765 -66 531 -100 1449 -166 457 -98 1715 -66 299 -166 3131 -130 197 -98 817 -294 793 -100 97 -66 3415 -164 1019 -98 1675 -132 197 -100 133 -68 199 -134 3319 -298 297 -66 791 -66 1029 -134 2153 -100 1629 -132 1391 -68 1229 -100 665 -66 2039 -164 461 -64 261 -66 395 -202 395 -166 3159 -134 2253 -166 265 -132 395 -66 887 -98 163 -66 589 -98 227 -130 1151 -230 293 -66 591 -68 527 -132 2883 -100 231 -66 99 -232 761 -134 499 -64 929 -100 167 -300 2259 -100 691 -164 459 -66 493 -132 163 -64 1283 -164 757 -132 295 -264 1023 -100 197 -198 6635 -198 2407 -100 2091 -132 1531 -66 1889 -100 199 -134 3567 -100 2981 -100 263 -198 425 -164 595 -100 231 -68 2691 -66 965 -100 2907 -98 367 -132 885 -198 1721 -100 659 -100 97 -296 495 -166 299 -134 397 -132 699 -66 1165 -66 465 -68 197 -66 659 -66 1543 -66 819 -164 2913 -98 1061 -66 5475 -132 167 -100 1035 -66 3427 -298 429 -166 2723 -66 831 -98 133 -66 133 -66 495 -98 701 -66 1063 -98 1991 -100 3319 -66 263 -66 233 -66 695 -66 593 -132 595 -66 553 -66 459 -66 197 -164 2241 -66 165 -68 959 -98 1587 -166 65 -102 233 -66 465 -134 1227 -100 2359 -66 1959 -198 331 -232 165 -102 531 -100 63 -66 1999 -68 265 -100 429 -66 657 -166 297 -132 823 -100 129 -132 4511 -164 659 -68 299 -66 593 -66 99 -134 65 -100 397 -66 1561 -66 697 -100 429 -66 265 -134 361 -132 195 -130 1319 -66 133 -66 265 -100 397 -268 895 -100 363 -134 433 -66 133 -100 2321 -68 +RAW_Data: -98 3573 -98 533 -68 961 -68 729 -132 559 -166 2189 -100 131 -68 657 -100 1387 -132 133 -68 2255 -68 429 -66 231 -134 793 -100 887 -98 361 -166 2141 -66 227 -130 663 -100 759 -100 1161 -134 1821 -66 327 -98 985 -130 757 -132 131 -132 1693 -66 361 -98 1411 -100 591 -132 1025 -66 663 -66 1065 -166 1059 -166 365 -66 723 -100 1659 -132 1883 -98 785 -132 1031 -66 261 -66 2501 -98 297 -66 1195 -100 691 -134 3009 -100 3921 -66 861 -66 363 -132 3361 -132 723 -66 459 -164 163 -164 333 -66 1291 -98 821 -230 591 -164 97 -262 361 -66 689 -66 733 -66 233 -134 1627 -66 533 -66 195 -100 521 -100 493 -98 493 -98 2173 -66 2037 -132 165 -100 429 -132 695 -100 67 -132 465 -68 1491 -100 1257 -66 965 -100 365 -68 929 -132 561 -66 899 -132 597 -132 861 -100 2627 -166 197 -98 2079 -66 2223 -100 1791 -364 895 -132 1027 -132 235 -68 599 -132 829 -66 197 -132 695 -66 133 -66 531 -68 333 -64 563 -66 265 -132 369 -134 2239 -164 4269 -100 793 -66 1495 -198 821 -164 133 -66 867 -66 797 -66 429 -66 365 -166 1729 -168 959 -100 1417 -66 233 -100 2579 -166 993 -164 461 -66 1529 -68 961 -66 1049 -98 1061 -132 2847 -66 229 -66 397 -134 263 -100 3285 -66 4115 -66 1547 -134 297 -132 431 -100 2895 -100 563 -66 1491 -66 399 -100 721 -66 395 -68 399 -66 1289 -66 293 -164 2307 -98 525 -66 3663 -64 927 -132 499 -134 1127 -264 397 -98 399 -198 131 -100 333 -100 663 -164 921 -166 1481 -262 691 -64 659 -64 2167 -98 3689 -100 833 -100 2085 -66 697 -100 595 -66 923 -134 893 -232 265 -98 367 -66 1157 -66 263 -130 1017 -66 623 -66 753 -100 2873 -132 395 -198 2787 -100 861 -132 3847 -100 297 -66 233 -98 1333 -100 495 -100 1325 -134 367 -66 595 -66 361 -230 4931 -66 1821 -98 329 -98 365 -168 333 -300 897 -100 2777 -66 1945 -132 2601 -66 951 -66 425 -98 789 -98 359 -64 1051 -66 1443 -132 851 -98 625 -100 97 -66 731 -232 263 -134 2757 -68 3021 -166 265 -100 1633 -132 427 -66 233 -98 799 -100 1059 -100 263 -98 557 -68 1063 -66 461 -100 1023 -98 163 -198 1481 -132 1227 -98 327 -100 327 -66 1317 -66 1853 -66 1061 -134 1287 -66 1315 -66 1345 -132 723 -66 1225 -68 1463 -166 3261 -98 2883 -66 563 -100 821 -100 2077 -166 3137 -66 565 -66 1355 -234 1415 -132 165 -66 397 -132 493 -132 563 -166 893 -66 1193 -66 1249 -100 333 -132 2083 -66 921 -100 1225 -262 861 -166 1321 -100 895 -100 591 -98 1249 +RAW_Data: -98 97 -66 6825 -66 231 -68 14077 -66 1787 -66 1547 -64 2617 -66 2925 -66 1723 -132 1529 -66 865 -166 827 -198 431 -66 495 -66 1121 -198 1327 -100 397 -130 557 -66 97 -100 261 -98 723 -98 557 -98 463 -98 463 -100 325 -66 3703 -100 465 -198 1123 -98 2545 -66 361 -66 857 -64 3455 -132 663 -98 1991 -200 825 -100 919 -98 893 -164 1749 -66 7759 -132 3321 -66 1807 -132 527 -66 393 -100 817 -130 657 -164 1485 -98 2367 -66 4171 -100 197 -130 3665 -134 1059 -132 597 -66 533 -66 1023 -98 1253 -134 2021 -100 231 -100 233 -66 197 -66 199 -66 1961 -168 729 -100 531 -100 461 -98 1361 -100 11161 -100 659 -166 229 -98 1675 -98 1027 -100 2063 -298 431 -100 99 -134 1059 -66 199 -100 763 -134 231 -66 233 -102 1761 -98 331 -68 757 -132 425 -64 457 -132 99 -66 2091 -66 567 -164 2121 -68 2125 -132 595 -200 759 -102 797 -132 1345 -66 429 -132 1019 -66 195 -66 791 -68 1227 -68 797 -132 1591 -200 199 -134 165 -66 1053 -66 559 -98 853 -164 825 -100 329 -98 891 -196 689 -132 657 -100 2341 -98 1119 -66 1883 -100 2607 -100 467 -100 1067 -164 6935 -66 2409 -132 855 -66 1809 -98 1119 -164 65 -66 199 -100 233 -132 931 -132 563 -66 1393 -132 567 -66 301 -68 1295 -66 529 -98 793 -66 131 -134 533 -132 827 -132 731 -332 1251 -98 921 -98 327 -198 361 -234 529 -66 1577 -132 97 -134 199 -100 1099 -68 1193 -132 991 -100 953 -98 2895 -166 1679 -98 161 -130 129 -66 1019 -100 261 -264 531 -100 263 -134 299 -68 495 -98 831 -100 531 -66 1357 -100 2051 -100 229 -98 829 -66 427 -66 859 -134 995 -68 665 -66 1793 -134 361 -100 2349 -66 331 -100 197 -66 1591 -66 959 -66 431 -234 2219 -332 661 -66 1487 -100 3381 -68 261 -164 463 -134 3377 -68 1127 -134 691 -66 529 -132 99 -66 6687 -98 889 -132 197 -164 725 -100 963 -66 2947 -132 327 -132 889 -66 393 -98 1581 -100 193 -130 97 -66 293 -66 1675 -100 1887 -98 2017 -100 597 -66 293 -98 557 -100 259 -98 985 -100 1727 -100 165 -100 301 -232 329 -100 533 -98 727 -100 761 -66 961 -68 2759 -100 2019 -66 855 -230 859 -98 1215 -98 1887 -98 131 -98 819 -166 227 -130 723 -132 625 -66 501 -66 429 -66 831 -66 1291 -66 331 -132 431 -132 1389 -100 265 -166 1461 -66 1907 -490 911 -962 409 -508 919 -944 419 -486 913 -526 915 -480 925 -488 911 -488 943 -476 925 -486 947 -462 945 -482 933 -484 951 -460 977 -440 967 -484 945 -468 945 -466 975 -450 983 +RAW_Data: -444 977 -458 975 -456 975 -444 965 -940 485 -430 967 -928 487 -448 981 -910 489 -446 963 -944 485 -430 975 -930 489 -912 485 -896 487 -452 977 -916 509 -454 977 -922 479 -448 985 -15898 487 -456 973 -926 493 -448 1001 -918 481 -484 981 -478 979 -450 1013 -476 977 -450 1017 -476 983 -448 999 -480 985 -484 983 -478 985 -484 981 -480 983 -476 1001 -474 979 -496 973 -486 1015 -476 977 -476 1005 -484 973 -486 1007 -920 505 -456 1011 -918 509 -458 1011 -950 497 -452 1011 -920 507 -458 1007 -950 477 -958 483 -942 481 -480 1003 -918 515 -446 1039 -922 505 -458 1007 -16154 501 -462 1013 -934 517 -474 999 -958 483 -478 993 -484 1037 -450 1027 -482 1027 -452 1037 -482 1025 -444 1035 -490 1009 -482 1013 -484 1001 -484 1039 -474 1003 -484 1045 -464 1011 -480 1049 -446 1037 -492 1007 -482 1013 -510 1005 -494 1005 -970 485 -482 1017 -974 473 -498 1007 -974 481 -486 1047 -948 479 -482 1051 -948 497 -952 519 -938 485 -482 1041 -946 517 -478 1013 -944 503 -472 415 -83640 97 -200 65 -632 131 -300 365 -364 231 -132 1061 -100 3047 -100 1393 -66 499 -66 1091 -66 333 -66 2353 -100 2273 -66 1427 -166 563 -132 1559 -132 427 -100 925 -98 13469 -100 2019 -98 821 -132 1097 -68 297 -100 897 -100 1129 -166 465 -166 961 -66 597 -100 165 -66 267 -100 201 -100 765 -134 297 -66 165 -66 3081 -100 1293 -100 1289 -136 233 -66 357 -66 1155 -166 295 -100 1197 -68 1089 -98 425 -132 1187 -100 523 -98 463 -98 197 -98 131 -98 493 -66 393 -98 2797 -164 359 -232 325 -66 229 -164 625 -98 1215 -164 425 -66 589 -98 195 -66 1083 -100 197 -68 1557 -66 1427 -66 525 -66 429 -132 863 -66 1129 -166 831 -98 265 -98 1183 -66 3157 -100 2735 -98 2819 -166 4645 -66 301 -68 1395 -132 1097 -100 897 -198 629 -200 1419 -132 493 -66 521 -132 697 -100 695 -66 459 -298 859 -66 559 -100 1029 -100 4113 -66 1167 -66 14017 -66 2123 -68 525 -132 861 -100 329 -66 399 -134 1523 -132 327 -64 691 -98 463 -132 1803 -132 853 -166 715 -66 953 -66 525 -98 723 -132 989 -132 461 -98 459 -164 2239 -66 1185 -66 589 -100 1945 -230 1483 -66 399 -66 265 -168 965 -66 197 -168 699 -68 1125 -68 529 -98 491 -66 987 -130 525 -168 397 -66 597 -100 561 -132 1353 -66 391 -132 393 -66 591 -98 557 -98 787 -66 463 -100 199 -134 395 -100 759 -66 295 -130 261 -98 229 -100 99 -100 1595 -66 699 -100 499 -66 595 -98 327 -132 957 -132 331 -100 493 -100 1313 -66 295 -132 197 -198 1279 +RAW_Data: -66 9461 -100 329 -68 27921 -66 24331 -68 13415 -66 6439 -98 133 -66 4193 -98 395 -66 653 -66 983 -66 163 -66 955 -132 1791 -66 861 -100 363 -132 1659 -132 667 -166 467 -134 429 -166 265 -66 4065 -98 293 -98 3183 -130 555 -98 163 -162 259 -100 661 -100 7057 -100 931 -100 1297 -66 2559 -98 1193 -100 333 -100 563 -132 65 -100 793 -66 855 -64 659 -100 929 -102 893 -132 689 -66 3475 -68 1361 -198 331 -134 691 -66 295 -66 425 -164 731 -266 921 -100 599 -100 165 -66 227 -98 1091 -66 263 -66 1215 -100 227 -164 657 -66 953 -132 359 -66 1845 -66 1779 -132 753 -164 393 -66 731 -66 1195 -66 533 -66 797 -132 1623 -98 1281 -100 493 -98 659 -98 2417 -166 799 -132 1259 -100 559 -134 595 -166 199 -66 1461 -198 865 -100 459 -66 463 -166 165 -100 497 -66 1097 -66 1579 -100 1449 -98 885 -98 263 -100 1097 -132 627 -68 329 -132 487 -132 427 -132 361 -66 525 -98 687 -66 1161 -100 263 -66 729 -100 229 -98 559 -66 1213 -100 1015 -66 795 -66 5475 -66 4043 -66 1683 -166 1151 -132 429 -98 1447 -68 261 -98 985 -100 429 -100 1289 -198 2269 -132 7999 -98 1591 -132 3233 -66 861 -66 2087 -98 557 -98 719 -66 981 -98 563 -100 199 -100 523 -100 2319 -134 833 -100 495 -132 197 -66 295 -64 989 -66 1059 -198 7343 -66 2023 -66 963 -66 593 -66 2401 -100 491 -100 959 -66 297 -134 999 -132 99 -68 3609 -230 97 -198 1911 -66 265 -100 1195 -132 633 -132 595 -66 1381 -66 491 -66 1681 -100 297 -100 1827 -132 2269 -100 1351 -132 1513 -66 1225 -134 231 -66 1523 -100 363 -200 1227 -66 2943 -66 923 -134 2249 -66 1809 -100 1121 -132 265 -66 827 -98 199 -66 201 -100 3279 -100 565 -132 1689 -66 395 -66 2979 -134 1065 -66 367 -168 3585 -200 463 -100 563 -66 97 -166 2293 -66 265 -134 1255 -132 2401 -66 1579 -166 365 -100 861 -298 261 -98 761 -66 363 -132 657 -130 63 -130 557 -66 131 -130 2041 -100 233 -66 1791 -100 925 -134 265 -100 1063 -100 301 -168 661 -66 657 -64 263 -64 197 -66 1853 -100 663 -98 231 -66 731 -100 5539 -166 197 -68 1423 -134 361 -68 1727 -68 929 -100 1397 -134 1885 -66 1661 -66 265 -66 1183 -66 295 -166 263 -166 165 -66 329 -66 465 -100 1159 -134 697 -100 2443 -100 393 -98 1093 -66 953 -296 787 -132 425 -66 2019 -66 461 -98 1201 -100 397 -132 3551 -100 1431 -264 725 -330 1455 -66 263 -100 531 -296 499 -100 265 -100 163 -66 1145 -132 1313 -98 2101 -98 261 -132 1083 -66 5403 +RAW_Data: -66 2223 -66 11583 -66 131 -66 5071 -66 3723 -132 1415 -132 6905 -64 9685 -102 4739 -66 3355 -66 5301 -98 29993 -508 897 -950 437 -490 909 -974 423 -510 935 -486 925 -508 943 -490 937 -494 947 -482 941 -484 979 -440 979 -456 1003 -462 975 -460 971 -458 977 -468 973 -484 975 -472 971 -450 1011 -452 1003 -446 983 -480 979 -450 1017 -908 487 -472 971 -944 471 -450 999 -944 485 -468 977 -918 493 -448 1011 -934 499 -920 487 -914 487 -452 1011 -912 521 -446 1009 -904 517 -468 1007 -16000 531 -444 1009 -908 519 -468 1009 -912 515 -466 1009 -452 1021 -466 1011 -450 1019 -480 1017 -448 1045 -448 1019 -460 1041 -450 1019 -480 1019 -450 1039 -474 1001 -480 1021 -484 1005 -476 1015 -480 1017 -484 1011 -486 1017 -464 1041 -446 1047 -922 503 -458 1037 -946 513 -442 1047 -938 503 -480 1023 -916 537 -450 1049 -926 521 -904 519 -942 519 -450 1055 -910 519 -486 1033 -916 519 -486 1029 -16258 533 -464 1015 -940 515 -456 1053 -946 511 -482 1051 -434 1075 -442 1075 -448 1065 -440 1065 -450 1049 -480 1067 -462 1041 -446 1075 -450 1063 -460 1053 -480 1047 -450 1075 -446 1079 -452 1055 -478 1051 -448 1067 -444 1065 -480 753 -66842 99 -1090 465 -332 131 -68 131 -134 99 -132 167 -200 429 -100 1809 -132 2385 -230 265 -102 597 -134 1025 -66 365 -100 361 -66 825 -168 1331 -100 797 -132 431 -132 299 -198 661 -168 501 -100 463 -164 329 -66 559 -98 391 -98 1085 -198 1939 -66 1871 -164 2251 -134 493 -66 719 -198 361 -98 361 -64 197 -132 391 -164 691 -300 489 -98 2139 -66 1413 -66 1875 -196 557 -66 263 -132 1359 -66 1397 -66 631 -100 793 -132 723 -100 65 -66 529 -134 463 -68 789 -100 227 -66 923 -100 2649 -166 363 -66 395 -200 295 -130 1757 -68 2057 -100 1023 -66 359 -66 391 -132 1679 -66 359 -66 1217 -98 663 -98 463 -100 821 -98 165 -98 1589 -132 2367 -98 559 -132 1079 -100 9617 -66 3669 -134 1787 -68 1679 -132 361 -66 555 -100 661 -66 1523 -100 2057 -198 1025 -66 4177 -100 165 -66 265 -132 465 -134 299 -232 265 -100 1125 -132 1461 -132 1295 -100 499 -132 367 -68 263 -66 331 -66 365 -100 1643 -130 197 -132 997 -98 867 -98 1191 -100 2945 -100 2339 -98 1779 -66 295 -132 597 -66 165 -100 665 -100 463 -66 331 -66 593 -100 459 -68 489 -164 855 -66 261 -64 163 -100 4449 -100 859 -100 699 -132 199 -100 1685 -66 301 -132 2317 -68 231 -100 827 -66 1749 -132 99 -64 1185 -100 329 -100 1253 -66 1127 -98 827 -198 363 -132 265 -134 365 -66 297 -66 1125 -66 261 +RAW_Data: -266 29863 -66 2443 -66 5113 -100 5947 -21026 99 -134 301 -132 199 -132 131 -266 163 -196 131 -66 365 -66 465 -98 13819 -98 525 -98 329 -100 893 -66 1259 -66 431 -98 427 -130 1051 -392 463 -200 795 -164 399 -66 1489 -66 1377 -100 1423 -132 597 -100 689 -68 1559 -100 2263 -100 1327 -98 1059 -98 497 -66 595 -132 265 -66 299 -66 199 -66 563 -134 627 -66 165 -134 889 -66 2751 -232 893 -264 231 -66 299 -132 467 -132 861 -68 1263 -164 795 -66 2601 -100 429 -66 1525 -66 961 -98 265 -98 997 -66 233 -68 695 -100 697 -66 795 -66 1195 -66 1223 -68 2173 -66 467 -66 827 -66 535 -68 697 -100 1221 -166 165 -100 365 -132 723 -66 829 -132 2091 -232 265 -66 195 -66 459 -262 499 -100 461 -68 759 -100 1087 -66 259 -164 2845 -66 1365 -98 561 -200 331 -168 201 -166 1397 -198 197 -66 697 -68 1713 -68 293 -134 1317 -66 593 -328 395 -100 499 -132 2251 -100 563 -134 333 -134 1921 -134 1187 -68 561 -132 933 -66 797 -100 631 -100 399 -132 929 -66 2769 -66 851 -130 2047 -66 265 -100 7219 -66 1987 -66 299 -98 2199 -134 1063 -98 2843 -98 655 -132 231 -66 1123 -198 2137 -64 327 -66 3183 -66 1127 -66 631 -100 263 -102 3173 -132 267 -68 1289 -98 1593 -66 2415 -66 1185 -66 359 -132 1051 -66 2169 -66 427 -98 395 -132 793 -98 293 -166 727 -134 131 -100 1287 -98 427 -98 687 -164 823 -64 853 -66 865 -100 763 -66 2025 -100 959 -66 1891 -64 793 -100 763 -66 729 -166 99 -98 399 -134 763 -100 4203 -66 1321 -230 4023 -98 1053 -66 985 -98 1383 -66 3559 -164 1515 -100 2899 -66 797 -134 1169 -100 3055 -134 1615 -66 429 -100 495 -64 1583 -134 923 -66 921 -66 723 -68 1359 -98 787 -98 425 -100 393 -64 1189 -98 263 -98 491 -100 1455 -98 +RAW_Data: -202 531 -66 531 -66 1093 -66 1389 -66 1551 -134 2699 -66 1291 -132 65 -64 657 -98 1083 -164 393 -98 1359 -134 1461 -66 393 -100 561 -130 2113 -132 597 -66 431 -102 1759 -302 985 -66 235 -100 1395 -66 901 -66 1061 -100 463 -66 5673 -66 227 -66 225 -66 855 -66 1581 -132 2503 -100 657 -66 2535 -98 259 -64 1015 -66 231 -132 1197 -66 827 -166 9641 -66 1823 -132 1565 -132 299 -66 797 -66 1631 -132 327 -132 2227 -232 433 -68 499 -100 1793 -66 1161 -132 525 -66 129 -100 361 -66 1765 -132 229 -66 491 -132 2255 -100 3043 -332 299 -100 499 -100 267 -68 2967 -66 991 -100 729 -100 633 -66 529 -98 825 -100 1033 -100 331 -66 723 -100 725 -264 2987 -68 825 -66 2601 -134 333 -100 3181 -134 1059 -100 299 -134 3279 -100 1221 -132 659 -66 3157 -98 1595 -132 1561 -98 201 -134 465 -66 1843 -130 589 -66 1413 -66 331 -100 333 -66 661 -100 265 -68 201 -234 1027 -166 297 -100 1161 -132 1561 -134 629 -66 431 -66 1025 -98 427 -198 1527 -66 793 -66 1903 -66 131 -130 1285 -66 299 -134 397 -98 229 -132 499 -132 4747 -100 2355 -100 263 -132 1915 -132 1749 -132 759 -66 2253 -100 4545 -66 391 -100 521 -100 1083 -100 929 -134 565 -66 2355 -66 1331 -66 167 -100 465 -100 1727 -132 633 -330 433 -66 897 -132 165 -134 331 -98 627 -66 231 -66 167 -66 1397 -66 729 -132 1397 -68 165 -66 1627 -134 2187 -66 231 -134 795 -200 6469 -232 829 -66 3929 -66 891 -98 1977 -100 525 -68 859 -66 921 -264 1029 -68 959 -134 1555 -66 259 -100 687 -66 429 -264 663 -66 1559 -100 1127 -100 2327 -132 1913 -64 4193 -132 293 -98 99 -100 5613 -132 1351 -66 1545 -66 1677 -66 295 -64 1943 -100 595 -132 1959 -166 765 -66 1389 -100 823 -66 1749 -66 1217 -100 597 -100 297 -66 2019 -98 165 -100 4165 -100 67 -100 2477 -262 295 -66 919 -200 3555 -66 229 -66 2531 -98 557 -66 2525 -66 1463 -100 1293 -68 197 -68 1391 -66 1421 -66 595 -164 327 -68 2285 -66 593 -98 99 -68 463 -98 1063 -100 165 -68 99 -100 631 -66 1085 -66 859 -98 6599 -66 1429 -66 233 -66 397 -98 231 -132 1975 -132 333 -66 131 -134 3373 -100 4277 -66 1363 -232 2893 -166 3133 -64 951 -66 2815 -100 425 -98 327 -66 599 -68 1031 -98 133 -68 633 -68 429 -100 1129 -66 327 -130 2679 -66 1321 -100 463 -200 367 -98 667 -66 493 -132 885 -98 2183 -166 559 -98 981 -66 3201 -164 593 -66 493 -130 1923 -166 565 -100 2421 -98 461 -66 1427 -130 1955 -64 197 -66 1643 +RAW_Data: -132 2291 -66 3057 -68 2521 -166 333 -134 503 -400 3235 -66 2329 -68 995 -100 333 -100 97 -166 1757 -100 397 -100 165 -66 2755 -132 297 -134 163 -100 565 -100 1793 -100 1813 -162 1293 -98 97 -66 999 -66 1763 -68 261 -68 2391 -100 765 -364 859 -100 1855 -98 1399 -230 463 -134 301 -198 397 -100 961 -68 431 -134 695 -202 133 -100 365 -66 925 -98 165 -66 365 -132 663 -98 4573 -134 1479 -66 1019 -66 629 -66 233 -68 201 -66 569 -66 295 -134 1755 -296 3199 -100 3261 -168 3373 -132 1425 -100 759 -66 895 -98 201 -100 265 -166 99 -66 695 -66 1091 -66 855 -168 299 -100 229 -164 589 -66 521 -66 655 -134 329 -98 493 -200 429 -66 929 -66 673 -100 953 -66 823 -66 1283 -66 1979 -68 233 -66 1547 -164 589 -132 597 -66 131 -66 265 -100 761 -200 759 -66 689 -332 263 -100 1227 -68 1067 -164 2945 -100 959 -100 995 -100 399 -100 1193 -100 625 -66 399 -66 3021 -134 393 -66 4805 -66 1095 -68 231 -332 399 -166 1663 -68 561 -66 927 -98 1085 -164 1155 -98 627 -66 265 -132 263 -130 2211 -66 2159 -66 1029 -264 2669 -66 295 -66 8747 -100 329 -232 625 -134 429 -68 1329 -168 1355 -98 987 -66 1545 -98 1015 -98 699 -134 133 -134 1263 -66 4687 -166 8299 -66 1349 -434 933 -906 443 -452 949 -894 441 -480 909 -486 907 -456 947 -448 949 -434 969 -454 931 -460 941 -448 933 -450 979 -450 945 -450 935 -458 935 -486 927 -456 947 -450 951 -482 945 -428 975 -446 967 -452 955 -458 945 -912 485 -434 971 -902 481 -450 949 -926 451 -478 941 -920 481 -450 949 -920 473 -450 955 -916 471 -452 981 -918 449 -486 945 -910 483 -924 473 -15780 479 -450 967 -948 449 -482 943 -944 485 -468 941 -484 979 -446 1001 -444 999 -446 967 -484 969 -482 979 -478 947 -484 985 -470 973 -458 983 -492 971 -458 979 -494 971 -458 983 -494 973 -458 981 -498 975 -458 1013 -466 973 -952 475 -458 973 -950 489 -450 1011 -916 481 -478 1001 -918 481 -478 1001 -916 481 -478 1001 -920 483 -480 983 -946 479 -458 1013 -932 485 -952 479 -16040 493 -476 1009 -912 515 -464 1007 -910 517 -464 1007 -450 1001 -488 1001 -484 1011 -450 1019 -458 1039 -450 1031 -454 1005 -484 1009 -458 1015 -476 1009 -478 1035 -462 1015 -468 1007 -480 1001 -486 1015 -460 1041 -450 1017 -484 1019 -482 1009 -952 477 -494 1003 -944 485 -478 1013 -944 519 -482 1013 -942 487 -482 1013 -946 487 -484 1015 -944 487 -484 1015 -946 519 -454 1019 -942 505 -952 487 -16238 517 -468 1007 -942 521 -482 1011 -944 519 +RAW_Data: -450 1019 -482 1035 -480 1033 -460 1047 -476 1017 -484 1007 -484 1051 -484 1027 -452 1039 -478 1035 -458 1049 -480 1017 -480 1035 -480 1035 -472 1047 -484 1027 -454 1039 -480 1033 -488 1031 -488 1009 -962 521 -486 1017 -966 485 -490 1015 -139210 229 -98 461 -364 165 -334 131 -168 2121 -66 1049 -66 1215 -166 297 -136 1449 -100 3877 -100 1495 -234 331 -64 1345 -262 393 -100 529 -132 2921 -164 1223 -132 1807 -66 765 -66 397 -98 3405 -132 2123 -230 231 -66 2541 -100 2489 -98 4397 -132 461 -98 293 -64 991 -66 1125 -166 401 -100 131 -100 99 -100 265 -100 2555 -100 499 -98 1361 -134 265 -166 895 -100 2253 -100 1057 -100 129 -296 1147 -198 197 -66 1163 -66 1935 -98 1675 -66 1103 -100 891 -100 989 -164 1019 -66 2967 -68 1293 -166 3161 -66 133 -264 1065 -100 731 -66 1693 -66 529 -100 165 -68 865 -66 825 -232 1117 -196 2401 -66 3051 -296 229 -132 1843 -132 1687 -68 1119 -68 299 -68 97 -66 4741 -66 197 -200 2319 -100 1097 -66 3765 -66 131 -100 695 -132 2753 -66 2287 -100 1129 -68 331 -98 1433 -132 893 -100 465 -100 801 -66 529 -66 1515 -264 393 -98 263 -66 1831 -166 3533 -100 633 -100 1051 -100 331 -98 795 -134 959 -132 1229 -100 627 -132 2517 -66 165 -98 131 -66 2301 -166 163 -134 465 -66 2767 -66 1019 -66 401 -134 397 -232 893 -66 397 -66 833 -66 199 -66 303 -66 2775 -66 2069 -98 1841 -100 399 -66 793 -98 2793 -68 3769 -100 867 -66 861 -100 399 -66 1859 -100 631 -132 755 -100 689 -66 163 -64 2045 -64 2191 -102 1127 -68 727 -68 625 -164 1381 -66 1153 -132 1115 -98 1017 -100 491 -100 593 -132 991 -98 1415 -98 4813 -66 331 -98 131 -102 1847 -98 197 -68 263 -100 3265 -66 431 -100 493 -98 435 -134 133 -68 1185 -134 395 -100 131 -66 399 -134 767 -134 1125 -66 429 -198 3185 -100 2261 -66 523 -230 2475 -168 1297 -66 3243 -66 1853 -100 1657 -66 459 -66 827 -100 263 -66 303 -234 197 -166 1167 -100 2299 -66 1329 -68 461 -100 763 -132 3819 -366 757 -66 591 -164 621 -98 1445 -100 2155 -100 231 -100 631 -68 1161 -66 131 -166 67 -98 1915 -166 1891 -66 1261 -68 999 -164 165 -132 133 -168 2695 -68 1055 -198 97 -98 229 -66 229 -66 1215 -66 885 -100 303 -132 297 -164 619 -198 459 -64 989 -66 229 -66 597 -134 693 -64 1255 -100 65 -132 331 -66 199 -98 529 -100 2831 -98 1259 -66 4855 -100 1163 -166 299 -66 395 -98 3141 -66 1319 -66 2139 -100 161 -132 261 -130 821 -200 263 -134 931 -330 65 -98 99 -134 793 +RAW_Data: -66 597 -100 231 -68 167 -66 1659 -100 733 -66 1631 -100 165 -66 199 -66 233 -166 165 -100 1925 -68 595 -198 1785 -134 2177 -134 131 -66 1049 -98 3087 -132 195 -64 589 -66 397 -134 329 -66 2565 -164 327 -100 689 -64 1775 -100 5183 -132 1187 -66 329 -66 395 -132 165 -98 261 -98 1247 -64 1217 -66 927 -66 997 -66 199 -98 1419 -66 531 -166 1231 -66 697 -100 97 -66 563 -66 161 -264 3205 -200 525 -98 293 -100 291 -100 133 -66 759 -66 659 -100 983 -64 523 -130 431 -166 919 -66 1097 -100 1757 -66 1119 -66 917 -98 2647 -166 1247 -66 165 -264 1189 -100 899 -134 597 -68 2323 -66 1893 -66 1095 -100 533 -64 965 -100 1817 -130 1215 -66 1879 -64 821 -164 1117 -132 263 -132 131 -66 557 -66 431 -132 661 -100 1183 -98 629 -100 1679 -132 259 -66 623 -98 431 -66 399 -164 923 -100 297 -66 165 -166 2521 -198 99 -66 431 -132 1225 -66 1063 -68 131 -136 631 -66 163 -100 99 -298 965 -68 465 -68 465 -298 2545 -134 2639 -230 1489 -66 299 -66 1991 -234 65 -132 693 -134 429 -102 101 -68 461 -66 3333 -64 1229 -68 333 -66 265 -66 885 -64 3163 -100 467 -66 2651 -164 1221 -100 1527 -66 1259 -134 431 -232 1259 -100 6029 -164 297 -98 1151 -66 1415 -100 5289 -66 2467 -100 493 -132 495 -200 1121 -66 129 -66 757 -166 327 -130 5477 -66 1227 -230 395 -100 265 -132 497 -132 1133 -132 361 -100 1051 -164 3089 -132 1583 -100 65 -68 2315 -100 529 -132 2157 -68 1257 -66 1975 -98 427 -98 1347 -66 719 -164 857 -66 165 -66 1029 -132 297 -132 467 -100 731 -130 1985 -98 199 -166 899 -100 1391 -166 3425 -100 261 -132 721 -66 4845 -98 1193 -68 1225 -66 721 -100 1015 -64 983 -66 557 -130 693 -98 99 -64 1091 -98 197 -100 2321 -66 431 -134 727 -66 467 -102 891 -98 167 -134 2619 -66 393 -64 97 -100 589 -98 1583 -164 301 -68 1481 -98 295 -98 959 -66 365 -98 1253 -66 231 -100 1255 -132 1813 -132 1645 -100 361 -132 395 -100 427 -164 1197 -98 1001 -100 861 -66 1161 -98 195 -100 197 -66 1429 -66 663 -66 1427 -98 665 -66 699 -100 663 -66 855 -196 161 -100 361 -98 823 -66 227 -66 621 -132 1853 -230 461 -230 623 -100 557 -98 229 -98 133 -134 1291 -66 533 -166 627 -134 195 -134 593 -64 591 -66 1019 -66 1049 -262 297 -100 2921 -66 133 -66 963 -134 165 -100 diff --git a/assets/unit_tests/subghz/megacode.sub b/assets/unit_tests/subghz/megacode.sub new file mode 100644 index 00000000..e968fd9b --- /dev/null +++ b/assets/unit_tests/subghz/megacode.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 318000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: MegaCode +Bit: 24 +Key: 00 00 00 00 00 8A E2 D2 diff --git a/assets/unit_tests/subghz/megacode_raw.sub b/assets/unit_tests/subghz/megacode_raw.sub new file mode 100644 index 00000000..c2235d8c --- /dev/null +++ b/assets/unit_tests/subghz/megacode_raw.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 318000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -754 361 -17246 131 -8734 65 -71908 65 -27774 65 -1230 65 -13826 99 -800 65 -634 67 -796 99 -47716 65 -18338 67 -18176 131 -7986 65 -1084 131 -2090 65 -48694 163 -40926 65 -4538 65 -10224 65 -9874 20955 -1970 1023 -4928 1007 -4946 1011 -7910 981 -1992 1021 -7898 1013 -1962 1007 -7896 1019 -4930 995 -4962 987 -1974 1029 -4924 1019 -4920 1025 -7896 1005 -1964 1027 -7894 1007 -4932 1033 -1948 1009 -7916 1009 -1982 1001 -4942 1011 -7880 1011 -2000 1003 -13820 1011 -1990 985 -4944 1021 -4932 995 -7916 1025 -1944 1025 -7892 1015 -1970 1025 -7892 1001 -4934 1031 -4926 1015 -1970 989 -4938 1007 -4954 1019 -7874 1013 -2000 985 -7896 1011 -4950 1001 -1968 1023 -7900 999 -1968 1007 -4968 973 -7936 985 -1970 1009 -13856 1013 -1968 981 -4962 1009 -4926 1005 -7924 1003 -1968 1013 -7892 1003 -1992 985 -7904 1011 -4936 1023 -4948 997 -1960 1015 -4950 987 -4970 993 -7896 1005 -1970 1009 -7928 1005 -4914 1023 -1984 1001 -7894 1011 -1970 999 -4962 1003 -7890 1007 -1992 1013 -13810 1011 -1994 987 -4938 1005 -4964 999 -7904 1013 -1974 987 -7910 1021 -1964 1015 -7894 1021 -4912 1019 -4948 1007 -1970 1017 -4916 1021 -4946 985 -7914 1003 -1972 1009 -7898 1041 -4912 1013 -1994 985 -7892 1027 -1964 1013 -4938 1003 -7904 1023 -1966 1017 -13824 1025 -1968 983 -4950 1007 -4944 999 -7900 1029 -1964 1015 -7914 981 -2000 981 -7932 979 -4936 1021 -4926 1013 -1998 979 -4946 1035 -4908 1031 -7896 999 -1964 1025 -7902 1021 -4914 1023 -1966 1015 -7908 1007 -1970 1003 -4952 981 -7910 1001 -1974 1003 -13832 1015 -1976 999 -4958 1019 -4938 985 -7900 1025 -1966 1011 -7914 1015 -1964 1009 -7906 1017 -4908 1027 -4916 1011 -2000 981 -4954 1007 -4926 1017 -7920 1011 -1958 1009 -7906 1019 -4912 1025 -1980 1009 -7900 1013 -1948 1027 -4916 1011 -7918 1005 -1976 1003 -13846 1013 -1970 1005 -4914 1041 -4916 1007 -7918 987 -2000 987 -7902 1013 -1970 1015 -7894 1007 -4936 1019 -4944 1009 -1970 1013 -4918 1019 -4954 977 -7914 1019 -1964 1007 -7906 1003 -4956 983 -1982 1027 -7896 1005 -1962 1027 -4930 1007 -7906 999 -1972 1009 -13850 1009 -1952 1027 -4944 983 -4954 1023 -7894 1007 -1952 1031 -7882 1035 -1970 1011 -7894 1007 -4936 1025 -4920 1023 -1968 1011 -4928 1009 -4920 1015 -7902 1015 -1966 1021 -7894 1011 -4948 997 -1970 1009 -7902 1027 -1978 1011 -4930 999 -7918 1007 -1966 1013 -13824 1015 -1966 1027 -4918 1027 -4912 1021 -7888 1009 -1998 989 -7918 1019 -1960 989 -7930 983 -4946 1025 -4920 1013 -1970 1015 -4950 1009 -4926 1005 -7892 1037 -1942 1011 -7926 1005 -4918 1007 -1996 985 -7928 1011 -1964 993 -4946 1025 -7880 1003 -1972 1009 -13854 1011 -1948 1019 -4956 983 -4946 1025 -7898 1003 -1966 1025 -7900 1019 -1964 1011 -7890 1021 -4912 1017 -4930 1013 -1968 1015 -4952 1009 -4932 1007 -7920 1009 -1972 979 -7924 1009 -4944 1003 -1970 1015 -7894 1017 +RAW_Data: -1968 997 -4952 1011 -7896 1013 -1954 1005 -13860 985 -2000 979 -4952 1005 -4946 993 -7930 979 -1990 1009 -7908 1017 -1968 1011 -7900 985 -4946 1027 -4920 1009 -1964 1015 -4942 1009 -263646 67 -9708 99 -68890 97 -48712 65 -62028 65 -4652 65 -108870 99 -71758 99 -3200 97 -47548 65 -7036 65 -104448 97 -38184 99 -6502 97 -17756 65 -10136 20983 -1968 999 -4950 1005 -4940 1001 -7898 1025 -1966 1011 -7876 1017 -1966 1023 -7918 981 -4936 1027 -4946 975 -2006 979 -4946 1017 -4954 977 -7930 983 -1980 1003 -7920 989 -4952 1007 -1970 1013 -7896 1007 -1970 1015 -4954 987 -7900 1007 -1970 1007 -13860 993 -1972 1007 -4956 1013 -4926 1005 -7908 995 -1972 1029 -7914 987 -1986 1009 -7906 981 -4956 1009 -4930 1005 -1966 1039 -4938 1007 -4916 1009 -7918 1019 -1968 989 -7892 1017 -4934 1027 -1956 1039 -7898 985 -1974 1007 -4960 981 -7930 985 -1996 989 -13824 1045 -1946 1025 -4928 1009 -4942 997 -7926 1011 -1968 1003 -7894 1023 -1962 993 -7902 1017 -4948 999 -4948 1007 -1968 1015 -4918 1045 -4926 999 -7888 1039 -1972 1013 -7888 1005 -4948 1001 -1970 1011 -7886 1013 -1974 1023 -4942 1005 -7890 1033 -1952 1021 -13806 1047 -1964 1001 -4936 1009 -4950 1001 -7882 1031 -1962 1007 -7906 1021 -1966 1011 -7908 985 -4946 1027 -4918 1011 -1968 1017 -4948 1009 -4932 1015 -7882 1009 -1964 1013 -7900 1017 -4950 1001 -1970 1013 -7916 1013 -1944 1031 -4916 1029 -7888 1007 -1976 1005 -13848 1013 -1968 995 -4952 1003 -4946 991 -7920 1019 -1968 983 -7904 1015 -1966 1019 -7894 1011 -4942 1027 -4924 1011 -1966 1015 -4944 1005 -4926 1007 -7914 1007 -1972 1013 -7884 1013 -4940 1027 -1968 1007 -7906 1001 -1980 999 -4944 1013 -7880 1009 -2000 1003 -13830 997 -1974 1009 -4930 1029 -4938 1013 -7880 1011 -1998 1001 -7908 997 -1966 1025 -7902 1013 -4938 983 -4962 979 -1998 1011 -4932 1005 -4924 1011 -7922 1009 -1970 1015 -7890 1011 -4946 1003 -1970 1013 -7892 1013 -1964 1027 -4928 1021 -7886 1007 -1980 1001 -13846 1013 -1968 999 -4948 1009 -4938 993 -7926 1011 -1964 991 -7926 1011 -1962 993 -7898 1041 -4906 1009 -4960 999 -1964 1023 -4932 1007 -4928 1013 -7898 1015 -1968 1013 -7894 1017 -4948 997 -1968 1031 -7892 1027 -1970 1005 -4914 1039 -7884 1023 -1964 1011 -13838 1013 -1948 1023 -4924 1015 -4942 1025 -7872 1029 -1964 1007 -7898 1025 -1960 1025 -7898 1021 -4912 1023 -4920 1011 -1970 1013 -4954 1011 -4926 1003 -7910 1011 -1968 1013 -7890 1009 -4938 1023 -1982 1007 -7902 1013 -1940 1023 -4926 1011 -7922 1007 -1980 997 -13816 1045 -1964 1001 -4948 1005 -4938 993 -7904 1005 -1966 1035 -7888 1027 -1964 1011 -7906 1015 -4916 1027 -4920 1011 -1968 1019 -4944 1009 -4928 1001 -7924 1009 -1972 979 -7914 1013 -4948 1001 -1970 1013 -7892 1015 -1966 1027 -4928 1021 -7872 1035 -1968 1011 -13832 1011 -1980 983 -4956 987 -4948 1025 -7892 1005 -1966 1007 -7914 1021 -1962 1007 +RAW_Data: -7912 985 -4942 1023 -4926 1007 -1992 981 -4944 1035 -4920 1007 -7904 1025 -1962 991 -7934 981 -4948 995 -2004 1007 -7880 1007 -1992 983 -4946 1027 -7890 1007 -1982 999 -13830 1011 -1968 1025 -4926 1013 -4942 997 -7898 1027 -1960 1023 -7910 983 -2000 979 -7906 1015 -4940 1025 -4920 1011 -1968 1013 -225644 65 -2082 65 -155560 133 -5172 65 -1102 131 -48576 99 -24714 67 -6858 65 -1314 67 -38246 65 -64888 65 -4564 67 -59374 99 -20160 99 -17606 65 -42096 97 -11950 131 -29302 65 -19034 99 -32020 97 -366 65 -4430 131 -14620 99 -17318 65 -5556 diff --git a/assets/unit_tests/subghz/security_pls_1_0_raw.sub b/assets/unit_tests/subghz/security_pls_1_0_raw.sub new file mode 100644 index 00000000..5542663d --- /dev/null +++ b/assets/unit_tests/subghz/security_pls_1_0_raw.sub @@ -0,0 +1,35 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 390000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 297 -1592 167 -1594 231 -366 65 -598 65 -600 197 -98 199 -1098 99 -98 65 -862 133 -628 165 -597 361 -6828 65 -1668 231 -632 65 -792 163 -1284 163 -5554 199 -1588 165 -5300 97 -992 65 -432 197 -2566 99 -2340 63 -5932 65 -1462 65 -1062 131 -2454 65 -1446 133 -1682 65 -1260 65 -368 131 -1482 65 -134 131 -1512 197 -1710 131 -824 99 -66 133 -464 131 -866 65 -698 65 -200 65 -894 99 -1692 233 -1130 97 -2160 265 -1392 99 -132 131 -166 65 -1318 327 -1548 163 -6980 165 -994 65 -698 131 -1580 129 -132 63 -758 97 -466 99 -1590 395 -1024 97 -600 99 -732 63 -228 129 -98 165 -292 99 -696 231 -232 197 -166 133 -132 131 -430 165 -664 199 -1596 197 -530 65 -1054 63 -3474 165 -4504 65 -2980 99 -268 133 -2356 131 -798 99 -132 99 -796 97 -1692 97 -3804 199 -166 67 -66 97 -132 99 -5058 129 -1512 163 -1290 65 -298 199 -398 65 -1034 65 -1332 167 -3448 65 -1750 65 -1186 131 -462 65 -920 65 -166 97 -362 131 -1704 131 -1748 65 -2124 65 -1064 133 -1694 197 -5148 99 -566 131 -1696 99 -598 65 -698 231 -692 267 -2490 99 -1618 165 -1760 197 -2152 165 -1226 195 -100 99 -66 131 -100 99 -400 65 -456 131 -198 165 -368 261 -826 365 -858 99 -132 163 -460 229 -264 65 -664 165 -234 231 -98 165 -100 99 -1986 99 -2526 65 -832 167 -1762 231 -728 67 -530 133 -2082 97 -960 67 -498 199 -1658 133 -1488 99 -2652 99 -1258 165 -5284 99 -1660 65 -1790 65 -432 65 -3804 197 -2170 131 -196 129 -66 97 -832 99 -2466 97 -1622 99 -1624 163 -394 163 -1018 133 -1856 99 -430 67 -826 197 -3156 65 -166 97 -558 65 -1690 131 -1498 99 -66 65 -2716 161 -658 99 -1054 65 -230 65 -2074 97 -2042 65 -3074 263 -1698 165 -492 65 -400 131 -196 131 -368 165 -134 203 -168 201 -134 165 -398 301 -628 99 -1032 99 -830 65 -66 65 -432 229 -230 161 -394 197 -228 197 -330 327 -66 197 -822 231 -392 131 -892 393 -1456 131 -64 163 -1418 65 -166 165 -1428 133 -1526 163 -954 65 -888 99 -1956 133 -1194 131 -3514 65 -1728 97 -662 67 -1590 167 -2714 65 -930 65 -166 65 -728 131 -2752 65 -434 133 -1828 99 -3704 129 -1912 133 -1544 227 -494 133 -202 97 -466 65 -200 131 -1580 263 -1708 65 -626 65 -626 199 -166 133 -3446 99 -3420 99 -398 131 -1164 131 -7018 131 -3468 63 -1658 199 -956 101 -598 99 -1790 97 -1192 65 -362 133 -630 65 -100 429 -794 65 -696 231 -1130 65 -268 395 -730 131 -466 431 -66 233 -168 197 -998 97 -264 65 -796 163 -236 +RAW_Data: 265 -100 133 -1464 99 -464 67 -592 229 -362 131 -262 163 -134 325 -164 163 -130 97 -164 65 -724 97 -132 97 -958 131 -594 131 -264 161 -98 229 -100 97 -890 131 -364 99 -198 97 -262 131 -234 2497 -134 65 -68 165 -400 563 -400 433 -496 99 -100 131 -266 99 -100 65 -200 231 -894 65 -166 463 -200 201 -1228 131 -266 65 -496 99 -300 97 -202 165 -896 365 -132 163 -1698 165 -132 99 -168 67 -166 67 -796 165 -400 131 -200 165 -796 165 -98 2161 -66 65 -166 293 -228 887 -66 395 -656 297 -100 97 -530 97 -66 97 -594 65 -428 97 -332 65 -400 131 -164 261 -66 299 -334 65 -596 97 -166 99 -1184 161 -460 131 -132 229 -398 299 -664 165 -722 165 -166 263 -300 99 -232 199 -266 267 -660 97 -758 133 -530 65 -632 99 -264 329 -1028 67 -166 2451 -562 427 -464 163 -198 229 -264 229 -790 295 -164 297 -132 263 -726 267 -66 99 -364 197 -564 99 -1162 67 -960 97 -198 163 -630 133 -66 163 -132 195 -1288 197 -430 197 -1546 65 -890 97 -394 231 -924 2173 -100 65 -594 165 -100 99 -528 99 -166 99 -298 497 -66 65 -100 131 -198 265 -362 131 -198 293 -294 129 -1150 263 -262 65 -100 131 -494 231 -166 231 -468 99 -66 165 -1262 197 -298 65 -298 397 -432 297 -498 361 -200 65 -466 131 -166 101 -496 231 -364 233 -64 197 -196 65 -426 265 -198 99 -1218 97 -200 67 -232 131 -200 167 -200 99 -66 165 -928 67 -1722 99 -764 65 -892 99 -232 133 -300 133 -1080 621 -1526 487 -1504 507 -506 1517 -1524 519 -1508 509 -1512 447 -546 1503 -1038 1035 -1482 547 -976 1007 -1208 823 -490 1503 -532 1481 -1048 989 -1534 499 -524 1507 -514 1499 -1014 1007 -524 1503 -1530 473 -60198 1533 -1516 481 -1040 985 -1044 981 -1554 479 -1530 479 -1044 1007 -1502 511 -1538 483 -516 1503 -1542 473 -1016 1033 -1510 483 -1542 505 -1002 1003 -508 1521 -1010 1015 -1512 507 -526 1515 -518 1505 -1016 1007 -59156 529 -1528 463 -1580 447 -542 1507 -1544 469 -1554 481 -1512 499 -518 1507 -1016 1007 -1512 511 -1012 1021 -1010 1007 -518 1529 -472 1555 -982 1023 -1502 505 -508 1537 -488 1545 -1012 1003 -480 1531 -1516 507 -60180 493 -12296 821 -1698 299 -1686 387 -590 1465 -1570 459 -1046 979 -1546 475 -1534 489 -1044 1009 -482 1529 -1032 973 -1538 513 -480 1537 -492 1523 -1012 1017 -59154 497 -11798 301 -704 1325 -1148 913 -1612 417 -1102 897 -1118 945 -586 1437 -568 1465 -1058 977 -1534 477 -550 1495 -502 1515 -1006 1037 -494 1527 -1510 489 -60174 531 -16794 355 -640 1399 -1608 449 -1050 989 -1540 461 -1546 477 -1068 973 -518 +RAW_Data: 1503 -1024 1009 -1536 473 -552 1503 -498 1517 -1010 1017 -59162 513 -9838 227 -1670 371 -604 1425 -1116 949 -1554 477 -1030 981 -1042 973 -550 1477 -532 1511 -1010 1003 -1544 511 -496 1515 -516 1509 -1018 1007 -488 1539 -1504 503 -60216 1525 -1530 485 -1018 999 -1012 1019 -1538 475 -1546 477 -1012 1025 -1506 517 -1530 505 -510 1507 -1512 513 -1010 999 -1516 507 -1520 513 -1012 1015 -506 1527 -1014 991 -1542 483 -524 1517 -482 1529 -1008 1005 -137640 165 -1660 165 -1362 231 -3114 67 -2286 131 -1652 197 -1448 195 -1648 97 -3534 163 -988 65 -556 65 -132 133 -2594 199 -2054 65 -1918 65 -1458 163 -690 65 -1134 131 -1194 67 -1158 131 -1656 199 -198 99 -298 199 -2676 67 -2122 231 -1762 263 -1560 131 -1228 99 -198 197 -830 99 -166 97 -6274 99 -1058 163 -1676 97 -1788 65 -5742 99 -3890 131 -2682 195 -166 65 -1394 265 -432 99 -368 99 -100 67 -198 163 -564 133 -992 131 -266 133 -962 233 -200 131 -196 231 -560 131 -66 65 -764 131 -1058 133 -564 99 -1792 133 -2820 65 -3480 165 -9536 99 -66 97 -626 97 -1828 199 -1860 99 -66 197 -1060 99 -1746 65 -1690 99 -198 99 -1660 165 -1764 65 -1558 199 -1456 99 -164 65 -1318 395 -5966 131 -928 165 -1026 99 -534 65 -434 99 -100 97 -100 97 -3272 65 -2168 131 -2904 231 -1564 67 -958 263 -3780 65 -166 99 -3506 99 -1594 165 -1492 197 -164 63 -1382 197 -1162 65 -364 133 -822 65 -498 495 -230 165 -366 65 -464 231 -666 231 -198 65 -332 163 -566 65 -164 67 -332 231 -232 265 -198 97 -1254 361 -200 65 -2056 129 -430 131 -100 65 -1588 263 -198 97 -2992 97 -528 297 -134 97 -368 427 -66 67 -132 65 -132 367 -330 65 -266 229 -66 65 -66 65 -198 231 -66 133 -528 363 -162 161 -230 525 -230 65 -230 461 -132 327 -330 295 -130 197 -230 165 -270 265 -464 65 -698 265 -264 229 -400 99 -3476 97 -1490 199 -134 99 -2970 165 -1618 167 -1598 65 -1162 99 -234 167 -1162 135 -464 65 -664 165 -1126 197 -362 97 -1222 65 -3496 65 -7024 131 -1592 131 -530 97 -6464 231 -998 263 -428 65 -698 131 -198 131 -1414 63 -1346 165 -1060 65 -1664 167 -566 263 -666 165 -566 331 -100 131 -1522 167 -368 199 -896 229 -232 99 -968 99 -168 231 -66 197 -68 131 -168 133 -400 131 -268 233 -596 233 -132 97 -494 131 -1710 197 -1616 67 -592 99 -1226 267 -268 65 -266 133 -1986 165 -332 99 -366 131 -2700 97 -1398 65 -130 269 -198 65 -1664 131 -3180 165 -992 65 -866 99 -166 163 -2782 65 -2354 265 -5176 65 -66 163 -1290 67 -164 99 -2584 67 -3084 +RAW_Data: 195 -364 65 -164 229 -958 63 -166 193 -130 65 -556 99 -332 199 -430 197 -996 297 -1426 235 -1160 2053 -166 1063 -100 501 -132 535 -198 67 -66 165 -98 165 -460 365 -366 97 -432 329 -264 133 -100 165 -328 197 -360 1087 -264 97 -166 63 -166 233 -98 195 -294 97 -264 163 -266 197 -100 359 -66 65 -1958 165 -694 99 -166 99 -596 299 -466 97 -66 99 -696 231 -1492 297 -1554 165 -1680 165 -368 99 -166 99 -168 65 -794 197 -194 2581 -98 1151 -592 99 -426 197 -328 295 -164 65 -232 163 -530 165 -264 129 -98 229 -294 493 -426 99 -66 163 -164 261 -264 129 -166 229 -68 65 -558 131 -132 65 -132 197 -1550 361 -98 67 -132 99 -132 131 -786 99 -198 301 -366 165 -530 99 -234 2159 -264 1691 -166 367 -132 231 -100 197 -166 97 -366 163 -68 131 -366 165 -268 133 -430 233 -100 133 -132 199 -932 561 -1416 231 -794 199 -1296 165 -564 165 -666 99 -490 97 -760 163 -1582 295 -464 267 -330 2561 -134 931 -66 65 -132 99 -264 63 -132 99 -198 97 -364 129 -460 65 -230 263 -164 163 -100 365 -100 131 -398 97 -530 65 -266 299 -1028 133 -100 97 -166 65 -296 65 -166 133 -498 331 -962 99 -98 199 -1328 165 -200 65 -234 99 -400 231 -632 65 -232 199 -530 65 -866 429 -958 197 -368 165 -668 65 -984 163 -100 129 -1088 259 -752 97 -522 131 -892 65 -298 67 -364 199 -132 65 -788 97 -396 363 -1052 99 -228 131 -98 99 -1526 463 -330 131 -898 263 -332 97 -996 163 -494 99 -2950 65 -798 131 -2490 165 -1424 65 -1694 65 -1822 65 -1756 67 -3820 65 -2536 97 -2410 65 -1030 131 -404 263 -732 165 -1566 197 -1554 199 -400 65 -100 99 -566 165 -3584 65 -764 101 -2630 65 -2896 163 -364 67 -100 65 -1228 263 -232 63 -884 65 -4092 133 -1622 325 -166 99 -2352 65 -500 65 -1324 99 -366 65 -1592 297 -5134 131 -1130 65 -1962 99 -66 99 -1454 67 -1130 99 -134 199 -134 165 -1222 229 -166 131 -464 197 -196 263 -234 99 -534 65 -132 131 -166 133 -134 199 -1590 231 -66 131 -1160 131 -300 65 -698 199 -462 133 -3446 99 -2876 65 -596 65 -1716 133 -2886 97 -134 199 -1628 131 -1790 67 -2556 615 -1510 453 -1584 443 -1566 485 -1014 977 -1054 1003 -516 1501 -1010 1007 -520 1495 -1034 1005 -1530 481 -514 1541 -492 1523 -1012 1001 -1508 521 -1016 999 -512 1527 -1506 509 -488 1521 -1040 989 -1538 473 -60194 1519 -1540 511 -1010 1001 -1020 1009 -1516 515 -1010 1001 -518 1507 -524 1503 -1534 493 -1510 501 -1022 1011 -516 1507 -522 1507 -1512 509 -1506 519 -516 +RAW_Data: 1499 -1542 485 -492 1535 -1508 491 -1046 1005 -1008 1001 -59158 547 -1508 515 -1510 505 -1510 523 -976 1033 -1000 1031 -472 1527 -1008 1039 -482 1541 -1010 1017 -1512 485 -514 1533 -482 1527 -1000 1019 -1534 479 -1044 1011 -488 1505 -1522 511 -512 1529 -984 1013 -1522 509 -60190 1543 -1522 477 -1038 999 -1002 1029 -1504 523 -1012 1009 -482 1541 -486 1543 -1510 481 -1544 505 -1008 997 -516 1507 -520 1513 -1508 517 -1510 519 -490 1521 -1540 485 -514 1503 -1540 487 -1016 1019 -1008 1003 -59184 521 -1536 511 -1506 489 -1548 475 -1026 1011 -1014 1019 -488 1513 -1014 1043 -484 1513 -1012 1023 -1506 519 -492 1525 -520 1507 -1008 1005 -1542 479 -1012 1023 -514 1507 -1508 521 -516 1523 -1008 1009 -1516 511 -60208 1513 -1524 477 -1042 1013 -984 1011 -1516 509 -1008 1015 -522 1505 -526 1509 -1504 503 -1526 513 -1008 1015 -512 1497 -522 1513 -1504 527 -1514 481 -516 1527 -1528 509 -494 1511 -1540 493 -1018 1005 -1014 1003 -59166 553 -1502 511 -1504 487 -1546 511 -992 1011 -1010 1015 -520 1517 -1016 1007 -480 1527 -1016 1009 -1512 509 -510 1529 -490 1525 -1018 999 -1542 481 -1014 1035 -488 1541 -1506 481 -520 1509 -1018 1035 -1510 481 -60216 1525 -1508 521 -1024 1005 -1008 1017 -1504 487 -1018 1009 -526 1517 -516 1509 -1532 475 -1518 511 -1008 1031 -506 1495 -520 1507 -1540 483 -1544 477 -514 1531 -1506 487 -520 1513 -1516 509 -1006 1037 -1016 1011 -139572 133 -1724 99 -1590 165 -1660 65 -168 67 -1000 529 -598 65 -296 131 -130 197 -566 99 -732 99 -832 65 -4560 131 -1156 161 -982 261 -788 65 -720 65 -1286 65 -100 131 -368 131 -298 65 -500 65 -2674 65 -758 197 -168 131 -294 63 -1744 163 -5304 131 -3408 199 -2122 65 -2626 131 -832 67 -166 65 -4384 163 -1608 65 -66 97 -262 65 -1418 65 -390 65 -230 65 -66 165 -1666 133 -1690 165 -1744 65 -2206 131 -392 165 -398 95 -594 97 -864 197 -632 99 -66 101 -364 331 -494 65 -1024 197 -762 165 -200 133 -298 229 -524 97 -560 97 -98 297 -522 65 -166 165 -360 195 -1514 229 -896 99 -562 261 -1552 195 -1422 263 -98 167 -396 99 -4540 165 -266 67 -398 97 -1660 263 -230 131 -1092 99 -134 65 -464 231 -98 99 -1458 97 -5494 99 -3342 65 -432 99 -2910 131 -1492 99 -3612 65 -1684 197 -1608 195 -996 65 -132 99 -1728 165 -1196 65 -862 131 -626 231 -796 65 -732 165 -1462 197 -2710 65 -790 97 -3198 165 -1778 65 -4158 165 -100 229 -5170 133 -2622 65 -3872 97 -754 165 -1260 365 -100 133 -98 133 -98 199 -562 131 -262 165 -1216 197 -230 131 -1612 165 -528 163 -228 63 -264 97 -328 99 -728 299 -758 163 -164 327 -228 65 -164 +RAW_Data: 197 -130 65 -264 163 -462 231 -100 65 -296 163 -196 97 -262 163 -728 299 -462 299 -1492 165 -200 99 -232 65 -1054 2385 -100 395 -132 99 -664 99 -132 365 -596 99 -794 329 -564 133 -298 165 -166 235 -366 229 -132 163 -590 197 -66 197 -1252 293 -262 129 -592 259 -232 163 -526 65 -230 165 -368 101 -1160 99 -826 97 -396 65 -198 3377 -66 791 -100 133 -168 99 -166 199 -100 465 -230 67 -400 197 -396 295 -1310 791 -1228 229 -560 65 -264 129 -326 199 -332 99 -264 65 -426 293 -132 197 -1316 99 -754 131 -822 197 -66 97 -460 65 -756 295 -166 3453 -198 65 -800 97 -100 199 -462 99 -198 67 -66 135 -298 299 -302 65 -300 99 -598 531 -466 233 -234 395 -200 133 -962 99 -100 199 -928 99 -628 97 -100 97 -730 99 -696 233 -528 67 -98 67 -694 365 -198 67 -896 295 -1484 97 -626 2563 -66 525 -100 561 -166 163 -232 265 -396 67 -234 99 -166 495 -166 97 -134 231 -132 133 -436 263 -298 97 -264 129 -230 65 -164 131 -164 393 -98 99 -294 65 -426 261 -264 131 -362 97 -196 65 -462 131 -1906 97 -260 65 -394 129 -660 133 -132 165 -264 231 -730 99 -560 197 -790 65 -896 65 -200 99 -764 261 -404 165 -164 165 -100 97 -164 395 -98 97 -164 99 -98 131 -132 163 -562 229 -532 99 -198 65 -332 99 -200 301 -330 165 -200 99 -928 2555 -362 731 -464 165 -492 165 -134 131 -732 131 -494 99 -164 99 -362 97 -166 97 -362 97 -134 97 -134 131 -166 99 -166 133 -468 329 -296 133 -1198 65 -2178 229 -3362 131 -1792 65 -7008 99 -164 65 -1448 65 -590 65 -134 67 -498 131 -1228 131 -532 131 -132 67 -364 65 -2128 165 -2358 99 -1526 265 -1154 65 -2240 97 -558 65 -2306 605 -1000 999 -1008 1035 -1510 513 -482 1531 -1496 543 -496 1507 -510 1529 -1514 511 -990 1007 -1002 1047 -984 1015 -492 1537 -512 1499 -1020 1011 -490 1539 -1000 1033 -988 1039 -476 1549 -474 1533 -1018 1001 -60188 1493 -1592 449 -1046 949 -1598 439 -564 1455 -552 1475 -548 1505 -1020 975 -544 1497 -1530 511 -1500 513 -1008 1003 -1540 507 -1512 501 -1022 1011 -1014 985 -1532 513 -500 1509 -1534 505 -522 1479 -528 1507 -59194 517 -1006 1017 -1006 1003 -1508 537 -482 1535 -1508 509 -512 1497 -520 1505 -1520 513 -1006 1033 -988 1039 -1006 1015 -480 1533 -490 1525 -1006 1035 -486 1539 -1014 987 -1018 1033 -484 1541 -484 1517 -1016 999 -60216 1481 -1620 387 -1118 923 -1602 431 -556 1481 -556 1447 -578 1467 -1048 977 -520 1505 -1542 499 -1516 481 -1048 989 -1544 493 -1516 515 -1010 1017 -986 1033 -1508 507 -514 +RAW_Data: 1495 -1514 509 -528 1509 -516 1503 -59178 493 -1064 983 -1050 983 -1534 479 -540 1487 -1544 481 -520 1501 -518 1511 -1544 487 -1012 1019 -1010 1013 -1016 1003 -514 1519 -478 1531 -1016 1001 -514 1533 -1012 1003 -1000 1035 -486 1517 -524 1513 -1012 1019 -60160 1525 -1580 443 -1070 929 -1580 451 -556 1505 -548 1467 -520 1511 -1020 999 -514 1527 -1502 505 -1512 511 -1012 1021 -1508 517 -1518 513 -1006 1017 -1006 1001 -1512 511 -514 1527 -1500 507 -524 1517 -486 1535 -59184 527 -1018 993 -1016 1013 -1516 511 -508 1495 -1538 491 -520 1511 -522 1507 -1534 473 -1016 1011 -1024 1007 -1008 1001 -518 1515 -524 1507 -1008 1001 -520 1501 -1026 1009 -1008 1031 -508 1495 -518 1507 -1046 975 -60196 1551 -1516 483 -1050 989 -1532 497 -522 1511 -484 1511 -518 1509 -1044 1007 -484 1517 -1544 495 -1508 509 -1010 1017 -1514 503 -1516 515 -1012 1017 -1018 1005 -1512 515 -482 1529 -1514 503 -524 1505 -512 1499 -135388 65 -928 99 -3478 197 -164 131 -558 65 -1120 131 -2416 265 -1562 99 -4088 133 -1460 165 -202 65 -1428 97 -1518 199 -332 133 -2388 197 -1590 67 -2016 133 -1624 97 -1094 65 -1692 99 -3458 163 -570 131 -4418 229 -296 97 -198 97 -164 297 -132 461 -164 163 -1284 299 -332 131 -1064 133 -796 67 -232 67 -264 201 -432 133 -330 133 -198 99 -166 99 -768 65 -462 133 -98 99 -100 397 -1228 133 -532 65 -5202 163 -2542 99 -766 263 -1686 65 -298 67 -1230 65 -266 197 -262 163 -1296 229 -1742 65 -1054 65 -2286 133 -366 165 -2936 229 -1158 167 -198 67 -3148 263 -3174 165 -1720 133 -1766 131 -5204 163 -1814 67 -1664 65 -4348 97 -364 131 -1532 267 -3838 163 -1348 65 -3364 231 -3336 65 -100 97 -466 65 -730 67 -3524 129 -296 163 -1118 97 -66 231 -786 131 -262 97 -428 429 -528 195 -68 165 -964 99 -366 295 -460 99 -930 197 -300 99 -598 63 -600 131 -430 131 -66 131 -762 363 -1554 99 -168 135 -1452 65 -466 165 -692 99 -296 131 -592 97 -726 131 -134 97 -3000 99 -1608 131 -492 65 -854 193 -1058 99 -498 99 -1694 65 -996 199 -530 97 -1582 165 -1718 131 -3418 131 -1592 267 -1622 99 -530 99 -466 197 -5108 131 -100 67 -1656 95 -1318 65 -3530 133 -1196 65 -1886 131 -490 165 -2222 197 -1694 97 -2076 65 -1022 65 -758 163 -98 97 -164 97 -198 63 -688 97 -1086 65 -1614 65 -1822 67 -1028 133 -398 99 -430 131 -2932 165 -1122 99 -334 297 -2028 65 -1392 97 -622 131 -296 99 -100 165 -100 199 -100 99 -300 497 -100 197 -302 265 -102 99 -1428 165 -168 297 -234 65 -798 131 -68 197 -466 165 -230 67 -132 99 -166 167 -598 231 -264 +RAW_Data: 265 -136 233 -764 165 -100 297 -232 67 -166 2513 -66 1745 -232 165 -436 99 -366 131 -466 99 -468 199 -466 131 -102 527 -764 99 -98 199 -166 133 -266 133 -166 99 -68 197 -434 65 -268 231 -132 131 -200 65 -330 65 -200 131 -232 165 -134 65 -1160 97 -134 99 -200 99 -1200 429 -920 97 -590 2475 -132 1095 -132 133 -66 233 -430 167 -168 429 -166 427 -164 423 -66 99 -230 229 -262 325 -164 65 -330 129 -132 231 -300 329 -332 133 -462 197 -564 99 -996 67 -264 233 -764 99 -98 299 -1462 363 -824 133 -132 99 -298 99 -100 197 -68 65 -132 4251 -132 67 -234 133 -166 199 -100 131 -200 131 -198 67 -330 199 -364 197 -298 99 -66 199 -268 197 -298 397 -430 131 -528 99 -266 231 -328 595 -402 65 -500 129 -298 229 -64 99 -1290 231 -822 229 -328 131 -1116 263 -228 361 -862 99 -66 133 -796 65 -698 3715 -166 463 -564 97 -198 97 -132 97 -230 295 -98 229 -330 393 -164 131 -230 297 -526 229 -98 97 -66 363 -722 295 -64 163 -400 167 -762 363 -66 165 -234 133 -864 97 -798 65 -332 431 -498 65 -928 197 -68 133 -266 165 -594 65 -200 99 -464 265 -230 2321 -196 1857 -98 297 -132 431 -266 431 -462 131 -100 397 -330 65 -364 65 -432 229 -166 297 -66 295 -954 163 -626 163 -526 495 -466 201 -660 327 -666 131 -998 197 -166 67 -468 97 -564 99 -1460 163 -926 299 -926 99 -598 133 -498 67 -232 199 -828 131 -1328 327 -166 99 -598 231 -402 65 -132 65 -566 97 -264 167 -1560 67 -1330 67 -858 65 -1366 131 -2754 99 -1786 131 -5130 195 -164 67 -134 131 -1984 65 -1286 97 -294 99 -228 65 -1062 65 -3418 131 -68 131 -1096 563 -1016 975 -1042 983 -1046 1005 -1516 485 -518 1531 -518 1507 -1514 515 -1014 989 -1516 523 -1016 1007 -1506 505 -1002 1011 -1520 511 -1012 1017 -1000 1005 -1532 513 -510 1499 -518 1497 -1018 1035 -1510 481 -60186 1543 -1514 513 -1014 987 -1518 527 -486 1537 -1008 999 -1018 1009 -1520 513 -1506 519 -1018 991 -516 1503 -520 1515 -1512 527 -1512 481 -1016 1019 -1008 1021 -1506 521 -992 1037 -510 1491 -1010 1017 -1512 507 -59178 481 -1116 879 -1138 897 -1118 915 -1614 409 -608 1423 -586 1441 -1580 441 -1070 957 -1580 455 -1044 1007 -1528 479 -1040 1003 -1518 481 -1034 1017 -1008 1015 -1520 481 -506 1521 -514 1507 -1016 1007 -1518 511 -60172 459 -4210 815 -1730 299 -658 1411 -1108 941 -1074 945 -1562 483 -1542 493 -1012 1005 -526 1507 -512 1497 -1520 513 -1524 511 -1004 1001 -1014 1029 -1494 515 -1002 1043 -478 1529 -1018 1001 -1538 495 -59140 529 -7690 365 -624 +RAW_Data: 1381 -658 1397 -1602 423 -1114 911 -1582 441 -1070 955 -1572 481 -1036 971 -1566 479 -1034 981 -1012 1015 -1514 505 -530 1513 -516 1511 -1018 1007 -1514 481 -60210 459 -7710 1381 -1140 903 -1126 915 -1602 415 -1588 443 -1060 983 -550 1475 -550 1469 -1558 479 -1540 493 -1018 1005 -1018 1009 -1506 503 -1006 1037 -484 1535 -1010 1017 -1518 497 -59168 525 -1008 997 -1046 1009 -1016 989 -1510 527 -486 1539 -480 1527 -1532 515 -1006 1011 -1506 519 -990 1019 -1534 479 -1042 1015 -1512 477 -1026 1009 -1010 1015 -1512 507 -526 1513 -484 1543 -1018 1003 -1510 509 -60172 1509 -1612 389 -1104 939 -1596 419 -582 1471 -1074 961 -1040 991 -1542 453 -1548 481 -1038 1017 -514 1505 -492 1543 -1502 515 -1506 515 -1002 1033 -986 1035 -1514 481 -1016 1027 -518 1503 -1014 1011 -1514 521 -133944 165 -1586 97 -294 63 -5014 99 -492 231 -1222 65 -396 131 -3086 99 -1920 65 -266 129 -1918 65 -922 195 -1908 65 -2080 97 -1894 99 -1558 165 -1424 165 -5468 99 -1694 65 -1756 65 -1812 99 -490 65 -1710 229 -98 99 -132 131 -992 99 -168 131 -68 65 -2322 199 -1888 133 -132 199 -800 97 -662 201 -666 97 -134 65 -132 65 -134 133 -166 199 -396 65 -558 231 -330 99 -692 199 -264 133 -332 99 -268 65 -366 231 -732 163 -264 327 -132 129 -132 99 -724 367 -234 133 -130 363 -598 331 -166 199 -1068 299 -466 99 -2822 65 -66 131 -1562 65 -1684 131 -556 99 -198 199 -1254 99 -1032 65 -1296 65 -100 133 -1330 65 -1058 65 -1096 65 -632 65 -1856 65 -134 163 -890 65 -1646 65 -664 65 -528 65 -392 99 -1624 165 -496 99 -1428 129 -2826 65 -466 65 -864 65 -4422 131 -1926 99 -1466 131 -6930 99 -894 131 -1754 97 -1640 65 -66 97 -396 99 -130 65 -1086 99 -756 65 -198 65 -2188 261 -1594 131 -1722 65 -130 97 -6642 97 -134 131 -2376 67 -1590 65 -66 65 -998 165 -930 165 -264 65 -132 65 -296 97 -558 65 -66 99 -1086 363 -230 131 -1194 165 -1490 231 -166 133 -636 229 -428 363 -826 261 -130 97 -132 97 -164 131 -66 131 -2902 359 -1518 165 -598 133 -990 161 -396 301 -5214 261 -2776 65 -2326 99 -1698 65 -1618 99 -1358 65 -3480 231 -1558 131 -4656 97 -1554 65 -166 199 -200 201 -926 99 -664 133 -1656 229 -98 99 -1030 99 -1656 131 -1294 67 -396 131 -3038 165 -332 427 -230 361 -266 1027 -166 329 -166 265 -100 67 -230 799 -166 135 -200 631 -298 99 -168 297 -464 497 -264 429 -66 597 -164 197 -200 67 -232 97 -300 595 -132 165 -234 163 -100 65 -432 65 -4370 65 -722 131 -1688 131 -398 65 -1162 199 -2120 263 -1098 133 -758 +RAW_Data: 99 -296 97 -300 231 -200 133 -364 163 -532 199 -536 265 -762 399 -66 131 -332 99 -466 97 -132 431 -198 131 -100 131 -234 465 -164 231 -564 131 -398 131 -334 301 -132 99 -132 131 -498 65 -462 99 -1094 65 -66 99 -266 99 -800 65 -432 65 -562 65 -792 65 -166 99 -1230 131 -1248 65 -770 197 -1260 1985 -134 747 -66 655 -198 99 -530 299 -198 65 -166 299 -134 131 -200 531 -328 131 -624 165 -98 97 -230 97 -560 97 -560 131 -1654 131 -200 65 -166 99 -666 297 -796 67 -132 297 -664 199 -100 65 -532 131 -168 65 -466 165 -728 131 -624 2073 -166 233 -168 863 -166 131 -464 463 -100 131 -266 165 -196 399 -330 563 -632 65 -232 97 -66 131 -166 129 -98 131 -1386 99 -462 131 -1254 131 -1548 231 -824 65 -198 265 -996 99 -1062 231 -862 329 -264 261 -658 2367 -66 631 -98 859 -230 231 -558 129 -396 129 -66 297 -98 201 -134 131 -166 231 -162 295 -432 263 -66 331 -1384 65 -198 197 -98 131 -228 65 -132 65 -692 261 -560 97 -262 163 -232 99 -132 99 -134 65 -200 133 -132 99 -798 231 -1624 131 -498 67 -630 99 -300 165 -1126 293 -694 65 -98 65 -100 2267 -98 393 -494 197 -426 131 -166 67 -198 199 -266 429 -166 65 -300 131 -66 65 -232 133 -102 365 -134 97 -332 67 -232 331 -66 363 -366 97 -796 65 -166 165 -1260 263 -164 99 -266 527 -758 65 -428 197 -564 65 -366 429 -166 267 -830 133 -598 333 -666 65 -134 197 -398 97 -132 65 -168 133 -502 65 -364 131 -98 65 -630 197 -166 129 -822 65 -230 295 -64 65 -164 65 -790 97 -230 129 -364 163 -330 131 -132 65 -230 67 -166 97 -66 165 -632 231 -264 97 -294 99 -856 229 -694 261 -1546 97 -2076 65 -462 133 -5548 199 -732 99 -4170 133 -1232 99 -164 165 -1656 65 -766 167 -2258 163 -1610 197 -2020 99 -2518 131 -1020 65 -364 97 -200 97 -1664 163 -526 65 -1096 165 -1684 65 -986 99 -4860 131 -966 131 -1622 65 -1658 65 -1266 97 -266 165 -200 99 -964 99 -330 65 -3440 131 -166 99 -68 65 -1164 65 -132 99 -200 67 -792 163 -496 99 -860 427 -492 195 -230 99 -466 163 -1364 295 -132 165 -364 67 -1026 231 -370 65 -566 65 -530 363 -196 97 -164 97 -594 63 -164 165 -228 163 -66 233 -862 97 -692 65 -1744 163 -1416 67 -132 99 -1718 65 -556 131 -496 99 -1328 99 -132 167 -466 131 -4690 165 -1654 65 -1114 263 -1620 65 -1796 97 -1426 99 -1922 99 -7098 97 -466 131 -1578 131 -2384 165 -298 133 -766 131 -330 295 -2348 +RAW_Data: 131 -534 99 -798 2211 -134 297 -66 361 -66 197 -198 97 -398 199 -100 163 -100 65 -464 133 -134 233 -68 229 -696 199 -200 265 -330 65 -1218 163 -166 97 -426 229 -698 165 -100 99 -134 165 -372 65 -1426 65 -266 99 -794 65 -832 199 -464 165 -698 99 -266 165 -794 99 -298 133 -734 165 -266 99 -864 131 -232 1893 -166 1465 -1484 263 -560 99 -230 65 -462 197 -66 97 -890 165 -130 97 -132 163 -232 97 -132 161 -162 263 -262 99 -362 65 -432 65 -830 97 -234 99 -628 199 -66 99 -166 101 -268 265 -594 131 -1030 97 -1156 595 -800 167 -1920 65 -464 165 -264 131 -66 167 -134 233 -632 329 -100 97 -166 199 -466 199 -98 267 -200 97 -266 199 -300 65 -496 563 -100 101 -166 165 -730 233 -166 131 -590 97 -232 131 -164 359 -428 3159 -792 65 -624 197 -98 229 -132 393 -398 199 -200 133 -366 99 -132 67 -528 265 -730 197 -166 65 -200 397 -1358 131 -1712 363 -1462 299 -132 67 -1792 65 -794 99 -368 131 -134 165 -134 67 -266 265 -430 2315 -98 1473 -100 129 -66 229 -198 261 -166 97 -426 97 -100 229 -496 197 -162 163 -392 231 -166 229 -660 131 -366 297 -166 299 -232 97 -332 301 -866 133 -596 267 -364 99 -502 99 -1988 131 -134 65 -66 165 -366 231 -266 165 -690 99 -234 65 -498 67 -166 133 -762 2459 -166 1019 -264 99 -200 265 -562 65 -328 295 -330 197 -360 131 -98 227 -232 65 -426 259 -166 99 -496 131 -500 399 -992 67 -432 133 -66 99 -1394 231 -1524 133 -430 65 -886 65 -1716 131 -2818 63 -430 229 -296 97 -1706 131 -164 65 -1478 131 -458 99 -1568 165 -756 197 -890 99 -1088 359 -660 97 -98 229 -166 65 -500 99 -266 65 -566 65 -432 365 -200 99 -798 99 -296 327 -1218 165 -132 99 -466 165 -168 133 -632 363 -1482 163 -802 131 -862 133 -1332 65 -100 431 -830 97 -596 165 -3422 99 -896 65 -766 97 -3766 65 -132 65 -1152 163 -1810 99 -230 97 -654 229 -458 165 -200 67 -166 297 -134 99 -4840 133 -762 67 -764 231 -1248 97 -1780 97 -3332 65 -100 261 -1186 99 -3360 99 -364 97 -1738 163 -294 97 -4918 129 -1550 295 -1028 199 -1264 99 -1560 99 -2156 167 -1556 231 -1852 167 -998 67 -1116 65 -562 167 -334 133 -266 165 -394 99 -166 97 -3082 99 -232 301 -5148 131 -502 67 -732 197 -434 199 -200 99 -432 65 -232 199 -464 133 -1060 97 -1582 97 -98 97 -924 129 -462 229 -560 65 -132 97 -166 161 -164 97 -166 229 -360 97 -132 63 -198 131 -162 525 -1714 67 -732 99 -958 +RAW_Data: 65 -1166 165 -200 199 -166 133 -100 65 -1294 99 -166 265 -992 297 -728 65 -332 431 -166 261 -132 65 -132 65 -98 363 -230 163 -430 165 -230 129 -660 129 -66 131 -398 2453 -132 1329 -166 1187 -232 1657 -166 499 -68 99 -132 233 -894 99 -232 99 -134 363 -628 67 -998 131 -234 99 -266 197 -398 97 -200 167 -334 197 -430 429 -168 263 -1160 99 -364 131 -264 97 -1318 131 -790 99 -432 131 -132 199 -100 131 -930 133 -1424 99 -398 165 -1486 299 -166 165 -334 2325 -66 795 -102 397 -100 533 -100 429 -98 131 -464 65 -532 329 -366 165 -332 99 -432 295 -132 99 -662 67 -332 331 -1226 131 -102 199 -562 469 -430 97 -232 63 -328 65 -1914 133 -466 131 -832 163 -1660 331 -464 199 -828 131 -696 65 -132 2139 -66 2051 -66 263 -790 99 -566 429 -428 99 -330 297 -698 65 -200 197 -68 461 -1292 131 -168 165 -634 131 -234 133 -594 163 -360 165 -700 99 -964 133 -1026 65 -532 197 -1520 263 -688 65 -888 295 -658 65 -824 67 -598 97 -426 65 -130 161 -132 63 -658 99 -64 165 -522 199 -298 65 -428 197 -560 65 -200 165 -100 167 -594 229 -100 297 -268 65 -100 459 -200 97 -334 2997 -200 597 -498 97 -626 97 -134 363 -166 333 -266 65 -664 331 -300 299 -568 529 -662 263 -626 67 -594 99 -266 165 -230 361 -462 67 -66 131 -694 397 -1490 167 -132 165 -768 165 -130 165 -466 99 -298 99 -952 163 -428 97 -296 97 -360 99 -196 65 -658 65 -4052 229 -6240 165 -228 65 -426 99 -994 99 -398 363 -1512 161 -2042 65 -592 131 -2866 65 -500 167 -5246 97 -462 67 -1156 99 -2428 99 -960 65 -132 99 -164 65 -166 329 -2484 263 -232 67 -1368 99 -996 267 -498 67 -4612 131 -4866 65 -100 363 -464 231 -264 231 -262 297 -1594 99 -1596 65 -136 133 -1662 67 -1694 429 -1290 197 -198 293 -858 99 -1976 165 -66 97 -460 131 -460 97 -328 163 -1624 397 -300 67 -166 97 -430 299 -300 299 -1792 65 -4438 131 -622 67 -500 131 -1064 65 -400 65 -426 261 -1644 131 -3468 165 -1684 99 -866 101 -66 231 -464 65 -498 133 -492 97 -1712 99 -98 197 -66 265 -1586 199 -1334 99 -1948 97 -200 99 -266 65 -666 131 -132 99 -264 195 -3066 99 -3512 99 -1746 65 -598 97 -6068 167 -600 99 -1262 65 -166 65 -134 65 -132 131 -1520 99 -1254 97 -1828 197 -1294 129 -66 65 -1248 97 -754 165 -6542 231 -662 197 -560 359 -98 97 -130 99 -3080 63 -952 129 -296 65 -230 63 -428 99 -1788 133 -100 65 -462 199 -66 165 -1094 99 -66 +RAW_Data: 167 -3190 265 -1128 195 -298 525 -166 65 -594 597 -664 131 -498 165 -232 65 -296 129 -296 65 -494 297 -498 297 -596 201 -332 2027 -132 593 -68 891 -66 893 -98 365 -396 97 -398 99 -300 199 -366 163 -598 99 -100 131 -234 65 -132 331 -532 165 -166 231 -1660 133 -532 265 -100 131 -100 131 -298 199 -396 199 -334 197 -166 67 -334 131 -1662 165 -298 97 -534 65 -628 65 -534 65 -266 97 -826 133 -696 65 -294 233 -198 165 -134 2081 -66 929 -198 167 -300 99 -232 297 -234 199 -662 67 -166 99 -66 233 -132 433 -232 265 -300 297 -132 65 -132 97 -496 199 -360 465 -132 65 -132 297 -460 293 -64 161 -262 97 -492 199 -200 233 -132 97 -396 99 -858 199 -864 65 -66 99 -532 131 -1608 297 -1550 163 -432 229 -66 163 -394 1953 -134 1491 -100 991 -66 165 -232 265 -130 299 -432 167 -724 363 -134 167 -200 231 -66 199 -98 395 -66 165 -266 99 -332 197 -268 265 -466 265 -166 493 -362 65 -132 99 -360 199 -200 133 -758 99 -330 165 -298 163 -428 199 -368 165 -334 131 -500 163 -986 97 -394 329 -196 97 -558 195 -230 97 -532 2373 -232 165 -232 795 -132 267 -168 363 -166 297 -298 131 -134 65 -466 131 -464 65 -232 67 -266 229 -364 231 -232 297 -464 65 -198 133 -398 529 -134 65 -364 163 -732 233 -298 299 -134 231 -66 129 -264 397 -132 131 -200 329 -430 131 -132 265 -1292 65 -362 131 -264 97 -1020 165 -398 131 -364 65 -300 265 -924 195 -396 331 -166 167 -132 433 -198 99 -464 297 -266 165 -396 131 -1226 165 -694 65 -230 197 -896 65 -594 2969 -164 461 -298 133 -330 133 -234 65 -134 131 -66 65 -68 97 -66 99 -132 231 -694 363 -298 267 -268 231 -368 131 -300 99 -134 65 -166 461 -396 263 -66 165 -298 131 -66 229 -1644 163 -1610 229 -658 97 -132 129 -162 97 -428 65 -66 129 -1912 65 -1194 233 -2218 133 -360 65 -132 229 -3428 65 -262 65 -3208 133 -1224 99 -296 65 -2212 65 -496 65 -200 199 -498 65 -1144 65 -1764 165 -1726 65 -434 65 -898 165 -2354 67 -134 99 -464 99 -792 263 -954 1161 -100 295 -296 131 -132 457 -462 363 -200 725 -298 131 -134 231 -68 531 -166 667 -298 99 -66 595 -794 165 -202 199 -68 99 -298 165 -68 231 -202 201 -200 97 -1360 197 -266 165 -334 99 -234 165 -200 165 -100 131 -664 65 -566 397 -100 165 -132 199 -132 165 -988 197 -394 99 -164 65 -294 99 -262 63 -1288 233 -132 199 -168 265 -64 99 -728 133 -1192 65 -334 165 -132 199 -200 +RAW_Data: 131 -400 65 -398 165 -866 131 -264 393 -1680 231 -1494 299 -894 265 -364 65 -132 131 -960 99 -296 165 -824 65 -1716 99 -664 97 -134 165 -1526 165 -634 131 -166 135 -466 231 -696 2331 -100 329 -100 961 -198 65 -164 199 -98 331 -132 65 -298 731 -66 163 -332 265 -894 65 -132 265 -300 97 -334 229 -100 65 -1026 233 -366 329 -922 99 -266 329 -428 97 -462 361 -758 163 -1886 65 -498 229 -558 65 -600 267 -68 65 -1592 133 -202 2299 -332 393 -132 329 -326 231 -232 97 -590 231 -136 201 -1226 265 -530 199 -134 65 -232 297 -398 65 -564 65 -1458 65 -500 99 -302 99 -1120 65 -66 131 -98 197 -66 133 -66 65 -730 99 -200 197 -730 165 -664 297 -1462 165 -664 133 -168 65 -168 133 -368 197 -466 1957 -66 1525 -266 131 -366 65 -394 65 -98 163 -296 99 -130 265 -696 65 -398 131 -1128 197 -134 67 -894 97 -296 231 -166 401 -98 131 -928 265 -398 131 -798 131 -298 165 -830 65 -230 231 -168 97 -1252 131 -590 65 -460 229 -692 97 -332 65 -366 265 -732 2297 -66 197 -66 131 -166 231 -100 99 -298 365 -168 361 -130 129 -66 161 -198 97 -626 593 -66 99 -98 99 -556 297 -132 65 -134 65 -526 295 -196 197 -68 163 -264 327 -130 855 -66 393 -132 131 -100 65 -98 227 -164 197 -758 131 -268 99 -430 65 -1686 131 -1652 197 -788 63 -726 165 -100 131 -264 197 -1026 197 -1250 131 -1650 65 -1980 97 -132 63 -1424 97 -198 99 -100 65 -1090 65 -398 99 -1686 99 -754 63 -1714 97 -1842 65 -2988 65 -4980 165 -1624 65 -232 67 -1464 65 -3048 65 -166 97 -1986 65 -1062 99 -862 131 -2732 99 -2360 97 -1620 65 -1326 65 -330 197 -3238 67 -266 131 -2968 67 -132 135 -1688 131 -1718 97 -1648 65 -166 65 -1292 65 -1908 99 -424 131 -1222 197 -798 99 -700 97 -1758 165 -1562 99 -396 165 -166 99 -98 65 -366 65 -762 131 -332 233 -498 133 -98 163 -562 65 -68 131 -858 65 -896 65 -366 233 -532 197 -168 65 -68 65 -630 195 -724 231 -296 361 -164 261 -2862 233 -232 99 -3186 67 -232 163 -496 165 -1620 97 -1622 131 -7022 267 -268 165 -466 63 -528 295 -200 197 -332 65 -1656 131 -5478 65 -1296 99 -130 161 -694 67 -1694 131 -734 99 -2590 99 -1056 65 -432 327 -66 165 -164 65 -1120 229 -1656 165 -1128 131 -1232 99 -1560 65 -568 131 -360 231 -1598 99 -3250 67 -1818 65 -1216 263 -3328 65 -1508 133 -2600 65 -528 65 -2418 65 -460 97 -100 97 -164 65 -1560 133 -1822 163 -296 165 -1090 165 -168 133 -1264 +RAW_Data: 229 -1458 165 -66 133 -1626 197 -132 65 -394 65 -724 229 -132 65 -200 263 -296 97 -264 131 -130 229 -132 161 -1230 431 -132 99 -234 233 -362 99 -698 67 -334 65 -366 299 -398 99 -328 131 -396 165 -1458 99 -926 2239 -66 763 -68 1727 -266 65 -364 65 -464 365 -366 97 -664 165 -200 265 -234 261 -264 395 -362 329 -690 261 -164 495 -232 131 -326 165 -264 99 -198 397 -928 299 -268 299 -166 99 -298 167 -436 65 -266 67 -498 231 -896 367 -428 97 -332 133 -628 165 -1394 231 -926 131 -232 3127 -132 921 -428 263 -66 97 -230 97 -1022 329 -430 97 -166 65 -198 63 -100 65 -66 97 -66 361 -132 67 -232 131 -268 99 -366 99 -98 331 -364 99 -428 97 -66 491 -164 99 -164 65 -428 131 -260 429 -1380 263 -1564 65 -300 65 -498 99 -364 167 -200 231 -264 67 -264 365 -266 231 -262 65 -724 65 -130 2213 -130 361 -166 2065 -166 165 -100 133 -264 299 -332 99 -98 229 -198 65 -328 131 -100 263 -628 131 -330 231 -98 65 -132 129 -264 65 -130 163 -692 131 -66 99 -532 133 -234 99 -232 367 -298 401 -702 165 -498 399 -166 65 -132 131 -400 165 -1232 165 -1296 65 -232 165 -300 97 -396 2033 -198 463 -230 67 -68 563 -262 295 -330 197 -1190 197 -66 167 -66 263 -430 263 -100 163 -198 167 -102 165 -100 99 -234 67 -66 267 -396 197 -296 131 -1190 331 -200 67 -234 231 -530 263 -1610 263 -264 329 -196 129 -98 131 -132 227 -132 425 -526 129 -694 299 -856 63 -132 165 -166 165 -436 297 -1430 65 -66 99 -198 167 -266 65 -864 267 -996 65 -500 265 -1456 297 -726 163 -66 579 -1508 523 -1504 509 -1006 1033 -486 1513 -1514 507 -510 1537 -982 1011 -528 1509 -512 1495 -1034 999 -1016 999 -516 1539 -1014 989 -1510 527 -486 1537 -1508 517 -1512 485 -1546 483 -524 1519 -484 1529 -60168 1539 -1506 507 -1006 1015 -1016 1007 -1512 509 -1006 1033 -506 1495 -1544 497 -1014 1007 -1008 1001 -1544 477 -1024 1011 -1538 485 -1512 525 -1010 1005 -482 1529 -1018 1005 -1020 1009 -1532 475 -540 1507 -512 1491 -59188 513 -1506 515 -1512 519 -1020 985 -506 1519 -1538 491 -504 1533 -998 1013 -516 1505 -522 1505 -1018 1005 -1002 1035 -494 1525 -1014 995 -1546 483 -524 1513 -1504 515 -1502 509 -1512 509 -514 1527 -514 1501 -60186 1539 -1506 509 -1008 1003 -1016 1009 -1520 515 -1014 989 -518 1509 -1544 485 -1016 999 -1016 1003 -1544 483 -1016 1017 -1506 515 -1534 475 -1036 987 -520 1507 -1012 1035 -1006 1017 -1502 503 -526 1503 -508 1533 -59160 523 -1508 507 -1502 537 -984 1013 -528 1505 -1504 503 -520 1537 -994 +RAW_Data: 1007 -508 1533 -474 1527 -1008 1037 -1012 1003 -510 1503 -1018 1009 -1518 513 -514 1495 -1546 477 -1520 509 -1528 505 -492 1527 -520 1505 -60188 1543 -1514 483 -1044 1001 -1000 1009 -1520 513 -1012 1019 -508 1505 -1516 515 -1008 999 -1016 1007 -1516 513 -1010 1017 -1514 503 -1520 513 -1008 1001 -530 1495 -1012 1021 -1010 1001 -1530 503 -518 1507 -516 1507 -59162 517 -1554 479 -1540 493 -1034 981 -538 1483 -1534 505 -506 1497 -1038 1007 -488 1537 -484 1539 -1020 1007 -1016 1009 -484 1539 -1000 1005 -1532 511 -480 1535 -1514 513 -1504 515 -1508 519 -494 1529 -486 1535 -60182 1515 -1556 479 -1044 983 -1016 1005 -1512 507 -1036 1001 -488 1529 -1536 495 -1020 1009 -1010 1017 -1510 487 -1014 1039 -1510 505 -1510 521 -980 1039 -484 1539 -986 1039 -1016 1007 -1504 503 -520 1507 -516 1507 -131494 295 -198 195 -98 99 -362 97 -196 165 -130 233 -1528 197 -1756 165 -1024 129 -326 97 -1794 131 -1562 65 -1692 99 -100 99 -532 99 -1728 231 -5256 65 -7488 133 -164 133 -100 97 -266 327 -166 99 -1294 131 -628 97 -502 163 -1122 131 -856 65 -1480 63 -3748 131 -1356 65 -1152 99 -2316 131 -2640 65 -798 131 -2520 99 -66 133 -5954 129 -1680 131 -3458 131 -1086 65 -532 67 -632 165 -3482 65 -1024 163 -2800 65 -362 197 -1880 97 -494 99 -100 65 -1120 131 -3212 299 -266 99 -698 329 -1328 165 -66 133 -534 131 -794 227 -990 65 -164 133 -130 131 -198 65 -196 63 -66 165 -196 131 -98 329 -298 99 -230 65 -164 425 -100 523 -266 65 -1686 65 -1182 163 -3614 131 -3386 133 -6578 65 -432 231 -1682 131 -1680 99 -588 99 -2222 97 -364 131 -5214 131 -698 133 -394 327 -296 295 -396 199 -1256 131 -1190 99 -234 65 -3596 163 -2036 163 -660 133 -430 199 -800 67 -2854 165 -3516 99 -1660 131 -1596 99 -1726 133 -2326 65 -168 65 -530 165 -166 67 -1384 229 -494 165 -1248 99 -1224 65 -1624 99 -468 233 -4386 165 -1264 133 -762 65 -296 229 -1678 165 -1518 163 -1580 65 -132 65 -530 261 -166 161 -428 199 -134 99 -730 99 -558 99 -266 65 -1164 499 -468 131 -462 229 -362 131 -1480 327 -230 65 -732 65 -928 395 -298 65 -568 99 -232 99 -200 99 -1098 65 -3106 97 -266 99 -2356 67 -494 65 -1816 163 -390 165 -1032 67 -2308 165 -134 99 -1284 97 -1550 99 -494 97 -1326 97 -3530 65 -3702 99 -1382 231 -1228 165 -496 97 -968 265 -1452 99 -4736 131 -3916 65 -1282 65 -364 65 -3530 97 -1352 97 -1742 133 -5274 99 -3490 65 -3418 65 -1850 97 -2782 99 -1720 133 -2258 65 -100 65 -1620 65 -1160 65 -1558 99 -662 65 -1458 99 -230 129 -98 163 -392 +RAW_Data: 129 -694 401 -1526 67 -298 65 -1258 231 -102 199 -298 99 -790 99 -100 97 -100 131 -100 97 -164 161 -266 65 -234 133 -132 299 -628 65 -702 197 -330 65 -962 231 -366 165 -330 133 -792 65 -628 2059 -196 633 -166 231 -264 97 -166 163 -336 231 -202 65 -266 65 -266 131 -134 99 -200 197 -330 165 -132 65 -200 99 -266 197 -264 97 -198 559 -66 163 -754 229 -98 65 -64 363 -164 229 -196 363 -426 231 -68 201 -1288 97 -634 331 -2022 99 -264 67 -166 197 -464 3065 -98 97 -132 97 -66 327 -132 853 -132 97 -164 99 -396 63 -100 393 -196 131 -1052 465 -1458 427 -198 97 -198 391 -262 65 -66 165 -494 131 -262 97 -264 97 -264 265 -168 197 -764 97 -232 163 -464 65 -66 131 -398 65 -896 133 -598 67 -430 165 -1230 165 -200 65 -1130 65 -198 263 -230 2753 -66 565 -100 1129 -132 99 -134 67 -532 99 -400 299 -166 131 -134 65 -464 231 -234 329 -132 231 -262 163 -132 65 -394 131 -98 131 -66 397 -100 65 -68 461 -198 99 -296 199 -500 231 -1552 195 -66 65 -1586 195 -1350 197 -1418 131 -488 2647 -396 229 -526 129 -262 97 -262 97 -328 165 -664 99 -166 99 -232 133 -234 131 -726 129 -130 65 -198 129 -132 161 -330 65 -426 97 -694 531 -364 99 -862 165 -694 301 -66 163 -302 65 -232 233 -700 65 -98 165 -628 65 -100 163 -1516 327 -362 65 -956 231 -626 131 -464 65 -232 99 -828 131 -164 99 -400 363 -1324 99 -264 97 -1560 101 -66 65 -464 65 -498 99 -300 297 -100 65 -200 65 -600 97 -166 2321 -100 603 -200 67 -468 299 -300 65 -100 133 -796 131 -66 67 -700 165 -432 97 -332 233 -534 197 -398 199 -166 297 -362 131 -1132 233 -562 165 -166 99 -530 197 -700 131 -856 133 -398 65 -892 97 -2990 65 -4596 99 -130 163 -1770 65 -2256 99 -860 65 -232 131 -1662 267 -232 101 -1166 165 -1160 99 -466 163 -100 97 -366 65 -2828 65 -1624 263 -1786 65 -164 131 -1214 131 -460 227 -2998 63 -494 67 -1658 97 -3456 65 -3618 99 -2554 99 -2484 231 -4088 97 -560 165 -296 129 -2144 197 -528 363 -166 231 -428 163 -296 197 -132 129 -1354 199 -664 163 -624 131 -98 131 -688 131 -590 263 -164 97 -494 197 -362 131 -298 133 -3478 65 -334 583 -1526 509 -1526 481 -514 1509 -1544 475 -1024 1011 -1012 1017 -506 1501 -528 1507 -1530 473 -538 1493 -520 1507 -1014 1011 -520 1515 -1512 491 -1046 1007 -482 1529 -1016 1007 -1512 507 -1004 1039 -990 1015 -60210 1503 -1524 513 -998 1015 -1542 483 -520 1505 -516 1507 -522 1519 -516 +RAW_Data: 1503 -1508 487 -554 1477 -1526 513 -514 1501 -1028 1005 -1526 481 -514 1541 -518 1503 -498 1515 -1506 501 -1544 499 -1020 1005 -1002 1001 -59198 529 -1518 481 -1544 507 -514 1497 -1536 473 -1044 1001 -1018 1009 -490 1539 -482 1529 -1512 507 -526 1507 -512 1503 -1016 1011 -524 1513 -1504 505 -1020 1005 -526 1507 -1008 1001 -1530 517 -1010 1013 -1012 1013 -60178 1557 -1508 489 -1016 1009 -1522 513 -514 1505 -520 1513 -524 1505 -512 1499 -1546 475 -526 1513 -1506 505 -506 1527 -1014 997 -1542 483 -522 1513 -518 1503 -516 1501 -1534 505 -1508 523 -1012 1007 -1014 987 -59186 515 -1578 419 -1608 449 -544 1471 -1546 485 -1050 977 -1042 991 -518 1507 -524 1487 -1538 489 -518 1503 -518 1529 -1002 1005 -524 1511 -1508 503 -1008 1035 -486 1541 -1014 987 -1538 495 -1018 1007 -1008 1001 -60188 453 -4246 817 -1716 295 -674 1393 -594 1449 -586 1447 -546 1467 -1578 447 -550 1497 -1530 511 -510 1489 -1038 1003 -1514 513 -512 1525 -478 1535 -492 1525 -1506 515 -1534 475 -1014 1031 -1000 1011 -59180 507 -11528 557 -686 1341 -674 1363 -1646 383 -620 1409 -610 1431 -1090 947 -554 1477 -1566 477 -1032 981 -516 1505 -1016 1005 -1522 511 -1012 1019 -1020 1005 -60176 1469 -1672 337 -1166 889 -1606 449 -578 1439 -566 1485 -518 1509 -516 1503 -1546 479 -514 1497 -1528 511 -512 1523 -1008 1003 -1514 513 -512 1525 -478 1541 -486 1517 -1522 511 -1508 521 -1010 995 -1010 1033 -133296 65 -1252 99 -332 65 -1220 131 -594 129 -394 99 -1546 131 -856 65 -1494 433 -132 99 -334 263 -164 199 -198 133 -3348 131 -626 65 -2598 65 -66 99 -1284 131 -1588 197 -1664 63 -694 65 -2206 197 -134 131 -300 65 -1146 67 -3524 197 -296 99 -1226 65 -1360 131 -1620 165 -260 231 -786 131 -1018 129 -1224 131 -302 65 -796 129 -396 97 -1744 67 -464 67 -166 131 -766 99 -398 65 -98 233 -66 97 -396 65 -1096 65 -298 99 -500 99 -3474 99 -996 97 -232 67 -2218 197 -1420 131 -1692 297 -6442 99 -368 99 -366 131 -164 65 -2038 65 -232 99 -1526 233 -5196 65 -298 65 -498 65 -1064 263 -232 627 -364 67 -132 129 -728 131 -166 65 -200 133 -596 197 -232 197 -390 97 -1088 331 -496 99 -300 65 -430 265 -402 197 -164 163 -596 165 -430 199 -1026 99 -1460 133 -1394 99 -1998 165 -300 65 -2360 165 -600 65 -3364 197 -658 131 -6356 99 -530 97 -166 165 -200 131 -132 133 -600 65 -5300 67 -762 131 -860 97 -1480 67 -1814 99 -1330 65 -266 99 -1918 99 -1360 165 -234 133 -5506 99 -468 65 -1894 131 -98 65 -1624 99 -98 67 -1808 65 -230 63 -786 99 -1970 131 -3506 99 -196 163 -1058 99 -164 67 -1730 165 -3516 +RAW_Data: 99 -666 99 -700 133 -98 133 -1086 163 -768 65 -1026 2523 -166 2747 -964 195 -362 265 -966 131 -198 197 -100 331 -330 65 -164 131 -528 163 -230 229 -68 97 -332 393 -134 197 -132 197 -330 165 -268 165 -198 133 -564 65 -232 233 -266 267 -432 199 -232 99 -66 131 -532 97 -132 299 -1252 133 -166 199 -796 99 -98 233 -398 197 -1590 163 -826 65 -764 165 -1658 163 -66 165 -698 165 -198 67 -164 99 -998 2029 -232 331 -100 691 -66 523 -98 561 -166 725 -560 65 -362 163 -132 395 -526 67 -166 67 -960 265 -298 131 -464 131 -200 329 -598 199 -132 163 -294 129 -754 99 -294 197 -432 165 -232 67 -202 99 -234 199 -326 163 -824 229 -132 259 -462 99 -266 65 -328 131 -326 229 -562 97 -230 97 -132 3077 -100 1031 -100 131 -100 165 -132 295 -68 97 -364 233 -264 65 -200 131 -562 331 -396 195 -228 197 -166 167 -266 165 -266 133 -662 165 -100 65 -466 531 -364 297 -526 65 -560 163 -364 99 -1678 131 -562 99 -268 65 -200 133 -1714 263 -986 2071 -624 99 -392 359 -296 99 -264 97 -230 295 -230 165 -766 165 -232 129 -302 97 -562 197 -66 97 -526 461 -166 131 -1146 131 -264 229 -788 65 -68 165 -66 97 -100 133 -100 99 -400 65 -198 97 -526 65 -360 195 -854 163 -362 97 -198 65 -362 97 -230 97 -690 99 -424 295 -200 197 -1052 2919 -134 565 -634 99 -498 331 -634 99 -300 65 -598 131 -330 131 -166 163 -132 65 -98 231 -130 65 -296 65 -166 259 -396 99 -362 65 -464 165 -232 131 -196 97 -526 97 -824 261 -330 229 -68 297 -560 397 -466 131 -796 329 -334 231 -166 133 -100 167 -236 335 -364 529 -762 199 -232 201 -1130 131 -866 99 -698 133 -1556 97 -664 99 -300 165 -598 131 -1688 199 -1062 97 -398 331 -164 65 -922 657 -198 393 -98 229 -428 555 -130 163 -394 397 -132 261 -264 65 -130 65 -262 493 -132 363 -134 165 -66 133 -402 265 -330 199 -132 565 -366 99 -134 163 -134 165 -200 99 -132 167 -332 431 -66 399 -200 199 -266 65 -830 133 -2050 97 -888 129 -2404 97 -2646 133 -2058 65 -1924 65 -530 97 -1646 65 -234 97 -3752 65 -1550 165 -2670 99 -328 97 -5326 97 -2246 65 -1094 165 -1672 97 -1582 97 -3722 65 -5080 65 -1676 197 -2936 665 -462 131 -264 65 -168 233 -298 65 -132 65 -600 67 -132 163 -296 99 -1318 131 -562 495 -396 263 -132 133 -200 131 -132 129 -264 263 -164 97 -132 131 -2308 99 -1956 167 -298 99 -592 163 -462 67 -3200 295 -620 65 -824 133 -64 131 -1552 +RAW_Data: 165 -1526 131 -690 65 -526 97 -132 129 -362 65 -198 97 -456 131 -262 575 -1010 1019 -1008 1003 -520 1513 -1016 999 -1012 1009 -522 1511 -1504 517 -1012 1011 -1514 511 -1010 1021 -514 1501 -1514 511 -1504 517 -1510 521 -492 1525 -1506 517 -514 1505 -522 1515 -484 1531 -1012 1011 -60190 1519 -1538 493 -1018 1005 -1514 515 -514 1495 -1528 513 -1502 515 -1010 1011 -1516 517 -514 1489 -1538 475 -1024 1003 -1534 515 -1498 505 -1036 987 -1018 1033 -1510 483 -1538 507 -1000 1009 -526 1505 -1534 491 -59172 529 -1018 1007 -1008 1001 -518 1507 -1024 1009 -1008 1035 -518 1499 -1526 481 -1044 979 -1546 475 -1026 1011 -516 1503 -1516 503 -1524 513 -1512 519 -482 1525 -1540 473 -510 1513 -518 1507 -518 1505 -1048 983 -60204 1495 -1594 439 -1062 983 -1542 461 -548 1503 -1548 449 -1540 507 -1034 1003 -1514 489 -516 1537 -1510 507 -1014 993 -1542 481 -1512 521 -1012 1015 -1006 1007 -1510 503 -1548 495 -1018 1007 -482 1531 -1514 505 -59196 507 -1042 979 -1048 973 -530 1515 -1012 1015 -1018 1005 -522 1505 -1508 519 -1014 993 -1542 483 -1018 997 -514 1529 -1508 517 -1528 473 -1546 495 -524 1505 -1504 501 -518 1505 -518 1505 -518 1513 -1016 997 -60198 495 -7704 1361 -1648 391 -1632 407 -1100 949 -1576 425 -566 1495 -1526 481 -1042 981 -1552 481 -1534 513 -1010 1013 -990 1007 -1536 511 -1506 487 -1020 1011 -526 1511 -1504 503 -59194 513 -1022 1013 -1016 989 -552 1465 -1046 1009 -1014 987 -518 1507 -1544 483 -1016 1017 -1508 515 -1010 1009 -488 1545 -1506 515 -1504 505 -1542 477 -516 1529 -1508 523 -486 1535 -500 1511 -516 1509 -1018 1011 -60166 1513 -1600 431 -1088 945 -1568 447 -580 1471 -1548 479 -1540 475 -1046 973 -1554 479 -510 1533 -1514 481 -1038 1017 -1506 487 -1548 509 -994 1013 -1008 1017 -1514 505 -1514 509 -1004 1015 -520 1517 -1516 513 -136452 65 -496 99 -796 131 -830 197 -168 99 -166 67 -2820 97 -134 65 -298 65 -168 99 -2792 97 -800 67 -3482 231 -166 99 -564 67 -266 99 -932 99 -68 397 -462 165 -66 165 -100 199 -68 497 -98 265 -498 593 -130 99 -360 561 -164 721 -66 131 -392 133 -198 201 -134 233 -66 99 -66 265 -558 163 -232 99 -66 729 -66 165 -164 99 -2250 65 -2340 131 -2166 99 -3386 63 -786 99 -426 197 -1022 197 -1564 131 -5336 99 -294 231 -166 65 -8582 133 -530 133 -234 131 -660 133 -1922 99 -3746 197 -402 65 -302 99 -1456 65 -954 65 -2616 197 -1694 165 -1584 261 -432 65 -986 65 -890 229 -132 97 -298 197 -266 67 -66 65 -200 229 -1018 99 -524 195 -228 165 -166 101 -398 99 -332 331 -1514 259 -164 97 -198 63 -198 95 -690 657 -232 233 -66 133 -68 +RAW_Data: 131 -298 99 -560 199 -984 227 -294 265 -462 97 -230 2307 -68 201 -100 99 -132 2079 -134 163 -234 399 -366 67 -366 131 -268 65 -202 165 -100 97 -364 99 -200 65 -234 199 -230 297 -132 199 -100 99 -696 133 -100 333 -534 165 -166 67 -498 331 -266 165 -696 459 -592 197 -330 131 -98 261 -1578 131 -1016 97 -66 97 -426 99 -630 263 -166 4367 -198 99 -166 99 -334 65 -400 299 -330 67 -926 265 -134 231 -134 197 -66 459 -200 265 -166 131 -132 67 -166 197 -400 165 -134 165 -664 197 -1196 99 -398 65 -564 167 -730 97 -266 165 -430 265 -634 133 -566 199 -66 2627 -366 297 -98 97 -100 131 -164 163 -628 197 -98 97 -428 397 -466 131 -68 99 -132 131 -1286 231 -98 165 -430 97 -364 129 -98 97 -562 65 -200 133 -996 131 -166 65 -234 67 -796 99 -630 297 -1058 165 -134 133 -1230 1931 -98 783 -196 99 -66 97 -532 65 -330 165 -400 333 -696 131 -398 65 -166 297 -198 65 -368 133 -366 199 -132 65 -134 197 -166 167 -266 99 -666 65 -458 197 -1418 229 -130 65 -562 131 -762 99 -564 97 -1064 65 -1158 99 -1364 2125 -132 231 -232 1221 -68 133 -200 165 -198 65 -664 231 -332 261 -494 97 -788 99 -166 131 -368 99 -762 197 -66 131 -134 331 -922 293 -200 165 -198 131 -132 163 -362 395 -64 263 -986 297 -724 163 -888 195 -164 65 -264 129 -196 493 -896 131 -332 165 -434 65 -232 101 -98 97 -598 99 -566 99 -398 165 -200 133 -100 267 -396 65 -332 131 -624 65 -558 63 -396 97 -596 261 -1120 99 -786 131 -130 131 -360 363 -462 233 -366 97 -166 265 -230 65 -756 131 -1646 195 -166 295 -1658 65 -66 195 -1684 65 -6928 99 -1488 65 -164 197 -556 99 -330 97 -528 195 -1352 197 -1590 99 -66 133 -1328 131 -366 97 -2218 65 -600 65 -66 265 -232 133 -1496 133 -462 97 -66 131 -2352 99 -196 67 -2794 99 -2374 97 -100 99 -198 63 -2074 65 -5114 65 -166 99 -3616 133 -1588 97 -1622 163 -98 97 -888 131 -328 195 -196 197 -362 99 -792 161 -164 131 -266 133 -100 65 -234 65 -500 97 -864 131 -132 99 -664 99 -300 99 -300 65 -98 99 -1296 165 -168 231 -796 99 -232 233 -1092 131 -264 361 -964 165 -100 99 -200 263 -2502 165 -630 65 -134 65 -3342 131 -436 199 -564 65 -466 131 -1458 131 -662 131 -936 65 -2260 99 -630 163 -132 65 -4312 197 -330 65 -1126 265 -1694 65 -166 97 -558 97 -694 97 -1754 65 -1656 65 -366 97 -1118 263 -1550 295 -1448 165 -1618 99 -132 163 -1622 165 -1198 +RAW_Data: 231 -730 99 -432 63 -1350 131 -226 197 -432 2459 -66 165 -64 493 -98 1215 -232 229 -494 131 -396 197 -726 165 -196 195 -330 197 -130 99 -134 399 -334 131 -532 99 -1018 99 -164 227 -230 97 -592 295 -66 131 -66 229 -132 559 -724 97 -164 297 -1396 65 -662 65 -1086 97 -1226 65 -166 133 -232 65 -1196 331 -234 67 -564 2619 -132 131 -164 1089 -68 97 -100 997 -66 165 -98 463 -198 133 -266 199 -100 333 -234 197 -198 199 -564 197 -564 163 -792 65 -230 329 -98 65 -234 99 -598 99 -330 327 -198 197 -166 163 -130 131 -1678 575 -1000 1041 -990 1009 -1532 503 -502 1527 -1516 499 -488 1541 -1506 505 -1014 1031 -482 1543 -1504 503 -504 1527 -480 1547 -476 1527 -1002 1021 -514 1527 -1010 1013 -1518 481 -1036 1015 -480 1537 -1516 485 -60180 1555 -994 1009 -512 1503 -506 1531 -518 1505 -1008 1009 -1016 997 -1544 487 -1546 483 -1512 519 -1012 1017 -1508 489 -1544 477 -530 1515 -1510 519 -1506 489 -1048 1005 -1010 1001 -1526 509 -992 1011 -1038 1005 -59156 527 -1090 885 -1112 909 -1604 439 -572 1457 -1580 457 -548 1463 -1562 481 -1046 981 -506 1527 -1510 523 -482 1539 -482 1529 -520 1503 -1018 1011 -514 1497 -1016 1011 -1520 511 -1014 1019 -488 1537 -1510 515 -60180 1501 -1080 947 -546 1493 -538 1485 -518 1505 -1044 973 -1058 983 -1538 465 -1542 501 -1512 509 -1006 1011 -1532 513 -1502 515 -514 1503 -1516 517 -1506 515 -1012 1009 -1018 1001 -1510 527 -1014 1009 -1014 987 -59196 515 -1014 1009 -1016 1015 -1538 483 -516 1507 -1542 479 -512 1531 -1506 489 -1018 1009 -530 1515 -1506 519 -488 1533 -514 1509 -488 1545 -1008 1015 -512 1497 -1016 999 -1548 497 -1014 1009 -482 1543 -1514 499 -60192 493 -7688 1397 -1156 881 -1120 891 -1632 397 -1618 417 -1580 479 -1042 967 -1548 483 -1542 475 -542 1505 -1516 515 -1504 505 -1018 1007 -1018 1009 -1504 537 -984 1013 -1022 1007 -59174 501 -11466 659 -1656 353 -1180 847 -632 1425 -1592 451 -550 1473 -548 1463 -570 1481 -1042 971 -540 1495 -1014 1001 -1544 479 -1034 1001 -518 1509 -1514 513 -60202 1527 -1042 963 -554 1471 -550 1499 -516 1503 -1018 1009 -1012 1019 -1512 501 -1518 513 -1508 501 -1038 1005 -1508 513 -1506 521 -488 1531 -1508 521 -1512 513 -990 1009 -1038 1003 -1514 515 -1008 1017 -1010 1011 -132210 97 -1712 231 -2272 97 -4094 65 -526 65 -2118 67 -432 99 -300 131 -364 165 -1226 199 -134 99 -100 465 -232 99 -726 133 -532 199 -266 133 -232 65 -234 265 -1586 131 -528 99 -696 99 -132 297 -398 67 -464 131 -166 267 -466 165 -764 197 -100 65 -1026 65 -3972 65 -1718 133 -630 99 -200 131 -68 65 -4004 163 -2078 65 -464 131 -496 +RAW_Data: 99 -134 131 -398 65 -1090 295 -132 65 -1646 65 -1396 233 -1296 199 -100 97 -134 65 -764 265 -760 197 -296 65 -526 197 -100 197 -198 63 -1414 163 -1316 195 -98 229 -200 97 -824 99 -100 131 -66 3137 -198 393 -164 131 -824 101 -66 399 -200 67 -232 133 -168 99 -198 65 -366 597 -898 197 -98 65 -330 131 -362 133 -864 97 -632 131 -654 195 -1260 231 -398 99 -626 65 -460 131 -722 99 -300 65 -464 165 -1060 165 -366 67 -132 2189 -66 299 -166 97 -464 99 -200 165 -596 231 -596 65 -134 65 -166 197 -232 265 -266 67 -232 133 -400 199 -232 333 -200 65 -466 65 -430 363 -230 97 -64 197 -758 131 -66 65 -592 131 -558 165 -266 133 -264 165 -1102 131 -134 97 -926 67 -496 197 -1252 2593 -66 229 -66 687 -98 1119 -66 659 -98 197 -960 297 -166 99 -524 429 -1022 99 -364 201 -200 65 -100 199 -498 99 -198 67 -132 399 -432 99 -492 295 -66 197 -66 131 -3066 395 -1156 131 -302 99 -792 161 -264 329 -66 163 -98 259 -762 131 -994 165 -1742 229 -830 165 -430 323 -98 295 -130 99 -368 65 -266 265 -1554 197 -492 2511 -68 795 -132 699 -132 99 -66 633 -562 197 -204 499 -364 99 -200 99 -794 231 -266 99 -564 65 -200 197 -68 429 -198 99 -830 165 -794 99 -166 133 -534 359 -298 99 -234 199 -492 67 -98 167 -528 65 -1858 97 -856 65 -64 131 -462 129 -592 131 -198 97 -396 131 -690 99 -232 2427 -68 2469 -396 467 -264 99 -532 133 -232 63 -362 229 -462 525 -264 97 -260 97 -230 165 -132 131 -992 133 -796 129 -1682 129 -362 99 -230 99 -132 99 -100 65 -1590 265 -1690 197 -1590 97 -392 231 -1454 133 -1298 65 -2296 65 -230 133 -300 99 -2750 65 -560 131 -2966 97 -230 129 -1054 133 -1296 65 -992 67 -5244 167 -200 65 -6756 229 -1608 229 -166 65 -66 97 -396 97 -130 197 -728 163 -2338 197 -132 131 -66 99 -100 97 -300 99 -664 265 -432 99 -696 133 -132 131 -866 233 -134 97 -266 199 -266 229 -1126 99 -100 131 -1424 199 -1594 131 -2186 99 -5780 67 -760 133 -1630 167 -832 99 -2854 65 -2846 65 -5308 231 -1616 97 -1684 131 -236 65 -3044 99 -1594 131 -2108 99 -1660 97 -3448 99 -3556 65 -2690 97 -1648 165 -1858 65 -1492 165 -2882 199 -402 99 -1196 131 -132 99 -66 65 -1728 67 -132 99 -1164 265 -398 99 -166 129 -132 131 -2468 65 -1658 201 -1688 99 -1712 131 -132 99 -992 65 -428 65 -100 165 -498 165 -666 199 -500 329 -732 99 -132 67 -692 65 -362 197 -132 97 -1314 325 -596 +RAW_Data: 165 -66 165 -666 165 -632 65 -198 263 -564 263 -198 99 -230 97 -228 263 -524 231 -98 133 -498 265 -166 99 -924 325 -328 65 -360 165 -196 129 -166 327 -822 99 -398 99 -266 131 -562 99 -460 97 -164 295 -200 197 -964 99 -796 99 -596 165 -1088 65 -200 129 -724 131 -662 295 -724 65 -398 131 -234 99 -430 3857 -66 163 -66 1023 -794 99 -198 363 -68 65 -198 99 -132 265 -296 65 -264 197 -66 167 -530 165 -462 131 -66 425 -428 131 -162 65 -594 493 -362 131 -394 165 -130 297 -394 557 -760 97 -1284 197 -1490 163 -1680 131 -392 231 -264 65 -624 229 -1090 2037 -134 457 -98 131 -164 1691 -100 65 -300 199 -798 99 -528 99 -198 97 -296 99 -262 131 -66 197 -292 133 -198 99 -166 197 -66 199 -1454 229 -396 131 -130 131 -690 99 -98 97 -66 65 -362 63 -98 163 -164 397 -1028 65 -232 99 -66 197 -264 67 -166 165 -202 65 -1134 99 -132 567 -364 197 -696 267 -628 133 -200 133 -166 2173 -296 561 -66 765 -164 97 -266 99 -366 263 -332 99 -566 231 -98 99 -100 265 -132 67 -398 65 -166 97 -230 163 -396 99 -164 97 -98 163 -260 99 -164 229 -1448 163 -298 723 -428 99 -366 65 -330 131 -400 97 -366 131 -596 65 -166 133 -332 99 -366 99 -628 65 -532 165 -66 133 -264 131 -2726 267 -270 131 -232 65 -66 67 -432 165 -200 67 -1030 167 -166 165 -630 231 -196 63 -428 65 -764 2901 -132 99 -198 131 -132 359 -198 63 -132 129 -692 65 -200 233 -98 165 -332 67 -330 133 -166 297 -532 497 -68 165 -168 331 -132 165 -230 333 -564 165 -100 65 -1258 165 -266 99 -760 65 -298 133 -532 163 -464 197 -592 165 -1678 97 -1086 99 -460 65 -2510 97 -66 165 -1428 131 -1280 65 -66 97 -2108 99 -394 129 -230 129 -298 97 -1446 97 -266 97 -230 577 -1538 475 -1542 485 -1018 1023 -514 1503 -490 1523 -1014 1021 -1510 519 -1512 513 -992 1011 -1012 1013 -1032 997 -514 1497 -518 1535 -1010 1001 -1530 481 -504 1521 -1534 473 -522 1539 -1492 513 -514 1511 -60178 1531 -1034 971 -518 1509 -518 1505 -518 1533 -488 1509 -516 1509 -1546 475 -1044 989 -1012 1007 -1544 475 -516 1531 -1008 1011 -490 1545 -1002 1017 -1506 487 -552 1501 -500 1517 -516 1511 -504 1501 -1026 1011 -59168 491 -7578 461 -670 1359 -1184 881 -1614 435 -1566 461 -1050 977 -1050 975 -1042 993 -518 1509 -524 1517 -1014 991 -1508 519 -490 1541 -1502 513 -514 1533 -1506 507 -484 1535 -60182 1535 -1060 949 -554 1483 -540 1467 -558 1475 -550 1469 -538 1499 -1554 481 -1008 1001 -1050 975 -1524 511 -516 +RAW_Data: 1503 -1018 1011 -526 1511 -1014 1017 -1518 495 -488 1537 -482 1527 -522 1503 -526 1505 -1006 1015 -59192 495 -1582 451 -1542 479 -1038 975 -568 1481 -514 1499 -1036 1003 -1512 493 -1544 483 -1012 1033 -1016 1003 -1016 1009 -514 1497 -520 1511 -1018 1011 -1506 519 -490 1533 -1508 519 -492 1525 -1508 515 -514 1501 -60200 1545 -1014 1011 -482 1543 -488 1541 -484 1531 -506 1497 -522 1509 -1520 513 -1012 1019 -986 1037 -1514 513 -486 1541 -1006 1009 -486 1539 -1014 987 -1534 501 -490 1545 -482 1539 -488 1545 -484 1533 -1006 1017 -59174 499 -7598 461 -644 1401 -1094 915 -1614 425 -1572 471 -1060 977 -1012 1019 -1012 1007 -524 1505 -514 1497 -1038 983 -1534 513 -478 1535 -1516 519 -480 1523 -1536 503 -504 1527 -60172 1523 -1078 949 -546 1465 -566 1449 -554 1477 -550 1501 -526 1507 -1508 507 -1014 1005 -1022 1011 -1504 505 -520 1511 -1022 1009 -516 1505 -1018 1007 -1516 511 -506 1529 -488 1517 -524 1507 -512 1529 -984 1011 -132432 263 -1692 97 -1216 65 -788 65 -1320 231 -6950 229 -1658 133 -3184 97 -166 131 -1296 99 -196 99 -2900 165 -1658 131 -1856 99 -1952 133 -632 133 -4016 131 -136 99 -166 99 -1352 95 -2420 99 -98 97 -856 129 -5964 99 -1588 163 -66 65 -1720 65 -2716 67 -398 67 -398 97 -1284 65 -100 65 -788 131 -1748 97 -1596 263 -66 163 -332 431 -130 1161 -198 165 -164 133 -100 199 -338 131 -432 163 -736 231 -660 101 -100 99 -266 99 -102 231 -966 99 -402 465 -464 65 -398 463 -492 231 -430 165 -3936 65 -6980 131 -1248 65 -428 133 -434 199 -728 65 -756 99 -198 97 -4038 133 -2028 65 -2102 65 -660 99 -2552 65 -1860 65 -466 131 -798 65 -1780 165 -1710 261 -132 65 -394 65 -1828 165 -730 65 -1394 97 -132 259 -296 63 -1674 97 -3318 133 -1658 133 -502 65 -2886 131 -1626 163 -196 97 -1414 65 -3520 99 -794 195 -2476 65 -1846 131 -2044 99 -1450 99 -922 99 -1908 65 -262 97 -1776 97 -996 233 -1460 231 -232 131 -702 99 -166 67 -166 165 -168 67 -500 131 -396 99 -298 199 -232 65 -934 299 -334 99 -100 65 -632 165 -168 65 -1226 163 -66 265 -202 233 -862 99 -166 233 -202 231 -762 99 -266 65 -300 65 -1390 67 -3772 131 -528 99 -1316 65 -694 63 -864 197 -1228 67 -430 97 -1712 163 -5212 165 -1624 165 -434 99 -1092 165 -3986 131 -5164 65 -496 65 -4734 163 -1648 97 -1710 199 -1714 99 -1460 359 -1578 165 -1096 67 -626 65 -2172 65 -1580 65 -164 65 -1450 131 -3556 163 -4194 165 -6992 233 -264 97 -464 131 -730 65 -366 65 -528 67 -66 197 -796 131 -298 163 -264 131 -262 131 -826 195 -166 127 -130 +RAW_Data: 293 -328 97 -460 197 -624 65 -262 63 -626 295 -100 131 -66 163 -132 163 -294 97 -164 165 -168 65 -400 299 -68 265 -198 331 -1494 97 -66 131 -1094 1955 -66 723 -132 593 -66 391 -132 1063 -264 2121 -100 1093 -66 165 -100 197 -264 233 -730 263 -166 99 -166 397 -234 165 -728 231 -132 261 -130 163 -194 99 -796 199 -668 131 -826 165 -1626 131 -198 99 -1360 131 -200 131 -132 67 -1058 99 -200 67 -200 67 -768 2605 -96 163 -130 691 -64 1149 -98 163 -132 97 -198 261 -98 131 -1258 297 -430 97 -500 65 -430 131 -398 65 -264 165 -298 165 -134 463 -366 131 -432 565 -166 197 -98 97 -198 133 -230 197 -132 261 -100 65 -592 65 -824 65 -3266 231 -68 65 -432 129 -392 2799 -100 1151 -64 883 -98 99 -562 131 -66 197 -430 195 -196 99 -200 463 -400 99 -1032 131 -330 231 -1092 163 -858 97 -164 97 -226 65 -394 163 -1050 261 -950 263 -230 199 -1786 65 -558 65 -168 65 -396 131 -196 197 -264 99 -588 97 -230 163 -692 97 -262 97 -164 2923 -100 131 -66 561 -162 163 -198 97 -732 133 -732 165 -930 67 -1228 361 -298 131 -928 65 -166 201 -1096 329 -134 299 -432 197 -166 133 -630 165 -896 133 -1126 97 -164 295 -266 265 -134 199 -564 129 -896 131 -600 131 -658 65 -166 499 -232 133 -332 195 -332 497 -100 65 -330 97 -230 129 -362 131 -330 199 -1256 65 -660 65 -790 165 -1358 199 -166 133 -1226 2239 -66 627 -100 595 -132 233 -166 99 -102 299 -66 99 -66 133 -198 167 -266 163 -98 197 -200 233 -466 331 -198 233 -98 99 -332 99 -132 629 -330 497 -466 65 -334 65 -166 131 -300 65 -564 165 -168 99 -1462 65 -134 131 -924 99 -266 233 -300 67 -494 129 -364 97 -662 357 -786 197 -1626 131 -200 65 -396 99 -666 131 -896 131 -600 163 -136 65 -1594 65 -2042 65 -1584 99 -1920 65 -3128 195 -3316 99 -890 195 -626 131 -722 161 -98 97 -626 527 -66 465 -100 295 -200 65 -66 233 -66 163 -166 423 -164 65 -458 295 -524 593 -64 197 -162 65 -98 97 -264 131 -100 327 -132 229 -98 131 -556 395 -66 197 -1060 131 -232 233 -134 65 -464 793 -1620 67 -4074 97 -1018 163 -328 97 -5922 65 -624 133 -668 97 -830 267 -166 133 -100 165 -694 99 -134 231 -230 97 -592 65 -100 229 -490 65 -790 229 -954 97 -198 163 -368 99 -664 65 -100 65 -168 199 -166 233 -600 101 -132 99 -68 65 -232 167 -268 199 -330 263 -496 65 -830 133 -892 99 -1450 129 -3654 63 -1680 99 -1384 97 -2114 97 -430 +RAW_Data: 199 -232 65 -530 131 -1814 65 -164 195 -66 97 -164 65 -232 97 -858 231 -296 163 -164 1939 -266 829 -200 1229 -132 167 -200 231 -230 133 -166 99 -300 331 -332 99 -132 167 -232 67 -864 131 -266 65 -266 131 -200 167 -334 99 -132 231 -134 65 -232 133 -500 65 -66 99 -66 165 -660 99 -198 367 -364 97 -396 131 -1158 63 -1312 131 -164 163 -858 99 -628 363 -330 99 -166 99 -430 97 -330 65 -558 165 -562 2495 -164 423 -66 1653 -166 199 -566 165 -134 97 -234 97 -234 265 -234 99 -232 67 -98 99 -98 131 -266 231 -66 67 -168 197 -996 133 -66 165 -132 133 -198 99 -830 295 -530 99 -166 297 -332 199 -296 129 -1284 165 -694 97 -732 263 -1554 65 -2058 231 -432 99 -264 2167 -164 99 -66 261 -98 719 -496 131 -564 231 -364 65 -466 201 -400 199 -200 67 -232 363 -630 99 -98 65 -500 333 -332 99 -200 397 -366 331 -560 99 -394 231 -130 195 -230 165 -1034 97 -66 131 -1060 97 -562 163 -488 131 -822 229 -500 197 -530 65 -796 197 -164 261 -756 163 -430 65 -530 131 -434 133 -168 133 -298 65 -530 427 -494 65 -628 261 -162 129 -196 131 -1624 65 -332 97 -498 231 -328 99 -166 101 -664 1211 -1510 491 -1542 485 -1020 1015 -510 1493 -1540 489 -534 1501 -1526 479 -1034 1001 -1508 507 -1016 1037 -484 1533 -1500 503 -1030 1007 -998 1009 -1038 1009 -1514 511 -496 1511 -512 1533 -486 1507 -1020 1007 -60200 1525 -1016 999 -514 1539 -484 1511 -520 1507 -514 1529 -474 1537 -522 1505 -1508 505 -1002 1033 -492 1531 -1506 523 -1012 1005 -480 1527 -1018 1011 -1024 1007 -1500 535 -1498 513 -1008 1023 -1008 1013 -492 1527 -59182 477 -1646 337 -1694 365 -1122 881 -618 1405 -1638 407 -600 1455 -1546 461 -1076 971 -1552 447 -1042 1015 -518 1503 -1512 515 -1008 1001 -1016 1011 -1024 1009 -1506 501 -512 1539 -484 1541 -484 1543 -1006 1005 -60182 535 -11720 1363 -658 1347 -1682 373 -1136 897 -590 1447 -1582 441 -1072 957 -550 1501 -1018 997 -1044 989 -1546 485 -1516 517 -1010 1011 -1010 1009 -492 1541 -59174 443 -11526 625 -1648 397 -1106 933 -1584 451 -1084 957 -546 1465 -1548 485 -1046 969 -1052 1001 -1018 977 -1540 507 -520 1505 -490 1535 -482 1531 -1018 1009 -60222 1533 -974 1047 -478 1537 -490 1527 -520 1505 -514 1507 -518 1527 -480 1543 -1506 507 -1008 1001 -522 1501 -1520 511 -1008 1033 -486 1515 -1020 1011 -1012 1013 -1532 511 -1488 513 -1006 1033 -1006 997 -516 1523 -59176 497 -1632 329 -1714 353 -1114 905 -608 1429 -1580 453 -580 1433 -1596 451 -1048 981 -1542 473 -1060 979 -518 1505 -1526 509 -996 1013 -1010 1015 -1016 1007 -1520 511 -516 +RAW_Data: 1505 -522 1509 -488 1537 -1014 1017 -60198 1533 -978 1025 -520 1503 -516 1503 -518 1527 -486 1543 -484 1533 -508 1495 -1548 475 -1026 1013 -516 1503 -1514 505 -1024 1009 -516 1503 -1018 1007 -1018 1009 -1504 501 -1544 497 -1020 1009 -1010 1017 -488 1539 -137350 65 -794 165 -166 65 -432 295 -428 329 -164 131 -324 97 -198 65 -230 165 -166 431 -532 263 -232 67 -430 197 -66 893 -1522 165 -3076 65 -328 163 -2006 65 -894 197 -1362 99 -132 99 -1660 231 -1580 263 -1126 99 -266 133 -864 65 -4456 163 -196 199 -3214 167 -398 67 -1322 63 -1148 197 -1698 197 -1014 65 -7018 133 -462 165 -1664 99 -894 65 -634 327 -1222 97 -6562 97 -2512 131 -758 65 -592 131 -1182 97 -1792 65 -230 129 -1284 65 -1020 65 -988 99 -5252 163 -1692 131 -1970 65 -198 197 -728 65 -366 363 -1592 131 -1216 165 -360 163 -526 99 -460 99 -332 201 -232 65 -200 67 -268 165 -532 197 -268 167 -566 265 -132 231 -194 129 -198 163 -198 195 -394 361 -762 99 -166 99 -536 99 -3384 65 -1684 99 -66 99 -790 133 -1716 97 -1710 165 -1624 231 -2062 99 -1362 299 -3378 65 -196 97 -854 65 -1120 99 -200 99 -268 133 -432 131 -1956 67 -664 65 -1556 65 -1050 97 -132 97 -4740 131 -132 99 -1660 199 -864 165 -1582 133 -1614 131 -590 63 -4394 263 -296 231 -3032 197 -1670 65 -756 131 -4392 131 -1654 167 -168 67 -368 65 -832 99 -100 133 -1532 133 -1690 99 -868 131 -662 131 -3508 97 -852 63 -1120 65 -3144 163 -662 97 -594 97 -98 229 -1126 67 -266 65 -132 195 -296 65 -196 129 -262 99 -462 199 -762 65 -396 65 -328 229 -530 231 -264 165 -200 301 -894 65 -264 195 -166 99 -852 195 -1186 97 -66 97 -166 63 -3368 65 -230 65 -1152 99 -1624 165 -1624 65 -1656 165 -1754 99 -430 131 -3440 65 -3044 99 -2126 199 -1190 233 -232 133 -1722 65 -1658 197 -3220 263 -1780 65 -1590 97 -134 133 -1386 97 -3256 165 -164 99 -1856 99 -232 133 -1298 231 -2322 65 -200 131 -3254 97 -2892 131 -534 231 -364 99 -862 99 -68 99 -1388 65 -2078 131 -632 97 -1850 65 -724 97 -166 197 -100 201 -534 99 -264 131 -100 133 -300 133 -334 99 -1158 163 -300 99 -364 99 -300 165 -1024 97 -66 131 -230 525 -298 131 -564 527 -432 65 -692 65 -2642 65 -568 133 -1884 65 -856 131 -922 65 -3040 99 -100 97 -1896 65 -300 165 -466 67 -98 233 -132 297 -5044 231 -2354 65 -3878 65 -626 99 -1746 99 -1850 131 -230 97 -2434 431 -200 199 -100 167 -298 65 -2452 133 -396 199 -1058 65 -624 131 -5426 129 -2438 229 -956 +RAW_Data: 197 -490 163 -662 163 -396 393 -66 163 -262 65 -328 65 -362 2243 -100 595 -100 1361 -334 299 -230 527 -594 199 -498 461 -798 265 -200 329 -166 267 -466 231 -132 197 -98 99 -264 163 -232 99 -364 99 -132 133 -200 131 -132 99 -68 99 -166 297 -66 297 -198 131 -324 67 -232 97 -166 99 -166 99 -830 99 -264 433 -66 133 -2620 65 -232 233 -556 197 -198 129 -428 197 -228 163 -630 265 -200 133 -200 133 -100 165 -264 131 -100 197 -832 97 -400 231 -300 67 -266 99 -232 67 -532 327 -662 65 -268 99 -332 265 -232 99 -498 3293 -98 67 -98 365 -134 97 -626 65 -166 129 -230 229 -798 165 -164 195 -98 65 -166 163 -298 233 -398 199 -232 163 -100 65 -196 261 -264 295 -328 99 -690 361 -264 195 -722 65 -132 261 -328 65 -822 129 -66 559 -624 97 -1390 99 -866 65 -630 163 -398 65 -200 65 -598 4821 -98 99 -360 561 -98 297 -428 197 -98 197 -690 427 -98 97 -66 99 -1128 297 -266 65 -364 165 -432 133 -366 65 -198 199 -166 97 -364 397 -964 67 -1560 165 -100 361 -630 129 -788 131 -818 67 -132 131 -556 99 -558 99 -722 99 -196 2437 -264 2337 -360 197 -166 65 -330 689 -166 395 -98 65 -396 131 -164 97 -66 593 -262 163 -398 331 -100 267 -266 231 -166 65 -232 231 -166 263 -394 97 -66 65 -730 133 -200 131 -100 429 -230 227 -560 65 -100 97 -132 131 -166 65 -662 131 -166 231 -986 99 -132 263 -200 265 -166 65 -164 163 -164 197 -1184 259 -294 2681 -100 1061 -134 133 -100 65 -530 199 -726 97 -566 497 -630 99 -300 199 -132 363 -168 97 -230 165 -100 263 -198 165 -330 99 -826 133 -1166 365 -1224 165 -1130 131 -134 165 -132 229 -828 99 -330 99 -694 67 -230 163 -558 231 -726 97 -132 129 -166 195 -560 65 -262 63 -396 165 -998 65 -134 99 -200 231 -66 131 -266 165 -362 229 -894 65 -3690 133 -132 131 -132 65 -828 67 -666 131 -1430 99 -200 99 -4978 67 -596 67 -132 99 -664 259 -3486 65 -794 63 -2578 165 -592 99 -236 197 -296 129 -2202 131 -892 197 -2080 263 -66 231 -200 131 -402 233 -896 65 -666 131 -4786 99 -3204 99 -2322 165 -2566 97 -1252 197 -1716 65 -198 97 -7054 99 -934 195 -1616 99 -3522 99 -3344 97 -66 131 -1652 299 -966 297 -1494 65 -3432 131 -1792 65 -1586 101 -1624 65 -66 65 -2622 65 -398 65 -852 165 -3880 99 -1660 197 -1592 129 -1386 131 -164 131 -394 97 -66 97 -824 195 -362 163 -66 131 -694 331 -300 65 -332 97 -296 163 -298 295 -464 +RAW_Data: 97 -764 329 -1064 233 -464 165 -64 129 -328 131 -330 229 -166 65 -332 65 -66 165 -162 163 -198 63 -98 63 -166 97 -298 63 -960 231 -394 99 -1128 133 -500 297 -764 97 -166 199 -334 97 -68 131 -330 99 -66 197 -200 65 -332 397 -1648 197 -526 97 -560 2903 -98 493 -98 99 -230 129 -756 231 -164 429 -362 133 -132 167 -432 263 -234 167 -166 265 -296 163 -98 361 -132 67 -164 67 -496 229 -296 193 -364 131 -1226 165 -164 99 -602 99 -132 231 -1394 65 -232 99 -166 165 -1254 165 -298 199 -330 99 -820 129 -928 65 -330 165 -66 133 -630 67 -166 197 -166 2079 -200 791 -98 1263 -564 363 -624 163 -230 131 -360 233 -130 63 -526 65 -528 363 -296 163 -270 131 -200 261 -166 531 -1434 297 -462 99 -100 131 -464 567 -402 67 -462 131 -494 131 -1196 67 -858 165 -230 97 -198 65 -196 197 -362 131 -2038 295 -166 2333 -66 165 -64 327 -98 65 -164 261 -432 165 -134 131 -100 233 -536 65 -266 631 -360 263 -66 97 -68 231 -396 133 -766 329 -230 65 -296 163 -294 65 -66 329 -230 301 -532 197 -334 133 -1160 199 -562 131 -332 131 -298 97 -928 199 -132 197 -664 197 -230 2811 -66 665 -134 165 -102 365 -166 267 -66 131 -198 201 -266 99 -166 131 -232 593 -264 131 -594 131 -100 263 -164 131 -198 97 -362 163 -164 131 -164 329 -262 295 -526 131 -66 197 -434 195 -66 195 -262 97 -98 525 -228 229 -890 429 -198 131 -268 67 -430 131 -1150 265 -198 99 -956 329 -1186 161 -262 163 -918 99 -332 65 -664 195 -262 295 -1480 297 -492 131 -494 231 -990 65 -198 65 -164 163 -1544 167 -868 65 -164 97 -98 97 diff --git a/assets/unit_tests/subghz/security_pls_2_0_raw.sub b/assets/unit_tests/subghz/security_pls_2_0_raw.sub new file mode 100644 index 00000000..4cd9822c --- /dev/null +++ b/assets/unit_tests/subghz/security_pls_2_0_raw.sub @@ -0,0 +1,32 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 390000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -130 1115 -68 55471 -1962 167 -1664 99 -364 427 -232 759 -132 199 -100 267 -134 527 -132 99 -1292 99 -266 65 -68 131 -762 327 -98 393 -298 37611 -730 131 -428 1487 -3910 327 -100 295 -98 491 -492 65 -98 197 -860 97 -98 131 -856 131 -134 231 -792 229 -66 919 -198 7527 -7444 131 -722 97 -230 65 -98 527 -100 267 -68 229 -262 361 -528 195 -624 131 -164 495 -66 1697 -66 1791 -132 3715 -8320 65 -394 165 -166 461 -1094 297 -532 131 -764 197 -98 261 -230 165 -100 6235 -12144 265 -600 131 -134 65 -298 233 -958 163 -196 97 -756 263 -98 465 -134 97 -164 3051 -16552 431 -68 131 -166 131 -264 331 -298 561 -166 689 -66 557 -264 3173 -8316 65 -166 531 -298 197 -234 233 -134 233 -892 163 -296 65 -890 161 -232 331 -100 397 -15072 199 -100 99 -394 165 -164 129 -132 197 -132 199 -798 99 -1032 67 -398 427 -100 391 -98 363 -166 297 -66 2869 -66 2299 -12300 97 -660 99 -662 263 -594 131 -662 133 -66 199 -332 97 -134 99 -132 65 -134 131 -100 431 -100 2143 -66 429 -8840 97 -6976 97 -66 397 -66 65 -166 131 -230 131 -294 99 -228 97 -230 129 -756 133 -1298 1293 -132 529 -100 2567 -15654 229 -328 97 -198 131 -66 195 -1492 131 -398 99 -134 99 -366 265 -168 99 -100 235 -100 131 -396 299 -200 1029 -66 6461 -6804 99 -1062 65 -960 65 -232 131 -98 195 -1708 63 -196 261 -164 331 -66 261 -12094 65 -298 265 -198 163 -592 131 -2402 63 -66 297 -198 97 -66 393 -264 4003 -15878 231 -98 261 -496 229 -264 65 -858 131 -994 133 -66 331 -66 429 -100 165 -132 297 -15004 99 -1466 97 -266 165 -198 463 -796 231 -66 131 -298 99 -100 133 -134 167 -430 99 -66 365 -100 297 -134 265 -132 563 -98 1217 -66 6399 -8742 99 -592 99 -426 397 -2338 199 -66 995 -134 229 -132 65 -164 3989 -66 3675 -6962 165 -466 65 -564 399 -66 199 -134 263 -396 97 -132 97 -100 97 -428 393 -624 131 -988 229 -66 363 -230 791 -164 7883 -8286 165 -134 99 -66 197 -100 99 -68 131 -164 163 -398 197 -2162 2005 -66 97 -100 4365 -98 1255 -12012 99 -132 165 -462 65 -166 97 -564 65 -100 331 -794 199 -364 261 -496 331 -132 823 -66 6233 -10976 165 -764 165 -200 195 -296 97 -19176 195 -230 129 -658 131 -132 293 -66 133 -860 65 -858 131 -64 229 -66 227 -66 161 -66 9051 -7316 65 -1494 131 -98 165 -198 65 -134 365 -398 297 -100 3969 -14874 99 -998 65 -564 67 -364 263 -132 163 -528 197 -132 65 -264 65 -264 431 -100 301 -66 297 +RAW_Data: -164 6323 -10770 65 -1420 227 -196 263 -198 197 -1086 99 -98 163 -164 163 -426 65 -362 97 -264 295 -132 197 -13586 65 -1808 131 -166 301 -66 465 -432 165 -330 65 -332 297 -962 99 -266 97 -166 265 -132 327 -198 329 -98 293 -14984 99 -862 131 -166 331 -68 165 -98 233 -132 201 -300 197 -364 133 -662 99 -398 99 -166 65 -432 133 -132 1447 -5882 197 -1082 65 -198 163 -1580 129 -264 67 -632 625 -134 165 -68 827 -100 165 -100 99 -164 3949 -9126 67 -164 131 -986 241 -534 309 -208 267 -226 247 -250 247 -248 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -504 257 -248 245 -246 247 -248 501 -258 247 -246 245 -248 247 -248 249 -248 249 -504 513 -226 243 -274 243 -500 513 -238 253 -256 253 -492 231 -262 485 -514 223 -244 527 -478 507 -274 255 -218 253 -498 261 -224 251 -250 503 -258 247 -246 243 -246 247 -504 515 -238 251 -472 277 -242 497 -246 289 -220 247 -498 513 -476 255 -68610 311 -208 235 -256 249 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 247 -248 503 -514 479 -274 253 -256 217 -254 247 -236 255 -250 247 -502 513 -240 251 -256 253 -254 249 -240 227 -252 249 -502 259 -246 245 -246 501 -514 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -246 501 -226 245 -276 245 -246 245 -248 247 -504 515 -478 255 -244 495 -274 253 -476 511 -240 241 -69142 321 -218 243 -230 251 -248 247 -248 247 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -506 257 -248 243 -246 247 -248 501 -258 247 -246 245 -246 247 -248 249 -248 249 -504 513 -238 251 -254 255 -490 499 -228 253 -250 249 -506 259 -248 499 -478 257 -244 495 -510 509 -238 255 -254 253 -494 227 -254 249 -248 505 -258 247 -246 245 -248 247 -504 513 -238 253 -472 279 -254 491 -226 253 -250 249 -504 513 -478 257 -68880 315 -216 241 -258 249 -248 247 -248 247 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 249 -504 257 -246 245 -246 247 -248 503 -516 477 -274 253 -256 217 -254 247 -236 255 -250 249 -502 481 -272 253 -254 255 -254 249 -238 227 -250 249 -504 257 -248 243 -246 501 -516 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -248 499 -228 245 -274 245 -246 245 -248 247 +RAW_Data: -504 513 -478 257 -244 495 -274 253 -500 483 -232 265 -69136 287 -256 249 -238 227 -250 249 -248 249 -248 249 -248 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -260 245 -246 245 -246 247 -248 249 -250 247 -504 513 -238 251 -256 253 -496 499 -228 249 -250 249 -504 257 -248 499 -478 257 -244 495 -510 509 -238 255 -254 255 -492 227 -256 249 -248 505 -258 247 -246 245 -248 245 -504 513 -238 253 -472 279 -254 491 -228 253 -250 249 -504 513 -478 257 -68886 309 -208 235 -256 249 -248 249 -248 249 -248 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 249 -504 257 -248 245 -246 245 -248 503 -514 477 -274 253 -254 217 -256 247 -238 255 -250 247 -504 513 -238 251 -256 253 -256 249 -240 227 -252 249 -504 257 -248 243 -246 501 -514 237 -252 473 -280 253 -250 241 -228 253 -248 249 -504 257 -246 499 -226 245 -276 245 -246 245 -248 247 -506 511 -478 257 -244 495 -272 255 -474 511 -240 241 -69150 323 -220 251 -242 229 -252 247 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -504 257 -248 243 -248 247 -248 503 -258 245 -246 245 -248 245 -250 247 -250 247 -504 515 -236 253 -254 253 -496 499 -228 251 -250 247 -504 257 -248 499 -478 257 -244 495 -510 509 -240 253 -256 253 -492 229 -254 249 -250 505 -258 247 -246 245 -246 247 -504 513 -238 253 -472 247 -272 501 -246 253 -254 243 -494 513 -476 255 -68934 287 -254 213 -240 257 -250 249 -248 247 -250 247 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -506 257 -248 245 -246 245 -248 503 -516 479 -272 255 -254 217 -256 245 -236 255 -250 247 -504 513 -238 253 -254 253 -256 249 -238 229 -252 249 -504 257 -246 245 -246 501 -514 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -248 499 -226 245 -276 245 -246 245 -248 247 -504 511 -478 255 -244 495 -256 243 -496 509 -274 253 -69130 309 -218 253 -256 249 -240 227 -252 249 -250 247 -248 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -504 259 -246 245 -246 247 -248 501 -258 247 -244 245 -248 247 -248 247 -250 249 -504 511 -226 245 -276 243 -500 477 -272 253 -254 255 -494 231 -262 481 -514 225 -246 527 -478 507 -256 241 -244 243 -494 257 -244 243 +RAW_Data: -246 527 -228 243 -276 245 -246 245 -500 513 -238 253 -474 279 -254 489 -228 251 -250 249 -506 513 -478 255 -68936 287 -218 249 -236 255 -248 247 -248 247 -248 249 -248 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -506 257 -246 245 -246 245 -248 503 -514 477 -272 255 -254 255 -218 247 -240 255 -250 247 -502 511 -226 273 -244 243 -244 247 -246 247 -250 247 -506 259 -246 245 -246 501 -512 225 -244 527 -238 251 -256 253 -254 251 -242 227 -508 257 -216 527 -226 275 -244 243 -246 245 -248 247 -504 513 -478 257 -242 527 -238 255 -472 511 -242 281 -119614 299 -200 65 -470 65 -466 297 -630 97 -1592 133 -166 299 -66 231 -100 131 -98 265 -134 165 -166 433 -100 2287 -9916 231 -166 65 -98 199 -166 133 -166 165 -756 65 -724 195 -428 231 -260 263 -98 229 -130 261 -66 163 -264 65 -132 1181 -66 6315 -6798 131 -296 559 -334 131 -166 233 -132 165 -66 133 -264 99 -66 65 -366 99 -630 301 -166 97 -100 167 -164 535 -202 7269 -8266 197 -1022 131 -756 99 -98 99 -164 163 -990 65 -530 163 -230 297 -136 635 -66 2113 -8426 67 -6674 97 -722 197 -362 263 -232 165 -134 99 -234 297 -362 129 -198 131 -556 297 -68 167 -98 331 -200 165 -66 295 -66 8689 -4994 65 -1750 165 -762 163 -864 135 -100 167 -694 1093 -66 695 -102 99 -100 9899 -1650 297 -1216 97 -66 99 -396 65 -198 165 -164 233 -1658 199 -98 465 -134 463 -166 1883 -98 6283 -7302 99 -932 133 -696 263 -298 97 -98 165 -1708 131 -820 229 -98 231 -130 163 -590 131 -130 99 -66 97 -16220 261 -1062 265 -998 197 -1290 97 -362 165 -494 895 -264 7839 -7804 99 -66 99 -364 231 -630 133 -166 427 -496 131 -1252 263 -100 233 -66 133 -132 165 -66 259 -98 3109 -10438 101 -5322 99 -100 65 -666 65 -166 331 -98 197 -132 233 -662 261 -1516 559 -66 263 -130 689 -132 229 -64 3613 -15976 231 -166 133 -66 399 -264 99 -132 295 -366 97 -1692 99 -398 529 -68 397 -130 899 -164 3559 -98 1197 -12106 199 -98 65 -166 99 -266 99 -134 231 -100 133 -132 297 -430 99 -1394 299 -64 397 -166 99 -100 465 -200 331 -132 599 -100 2333 -15214 65 -1230 231 -266 265 -432 165 -398 65 -532 333 -632 65 -232 957 -98 9785 -6320 97 -830 167 -166 133 -732 299 -958 327 -98 197 -66 229 -164 327 -98 653 -66 7993 -6418 65 -1284 97 -458 129 -196 197 -166 393 -134 99 -332 427 -132 131 -66 133 -98 233 -66 133 -364 163 -566 4873 -16030 97 +RAW_Data: -360 65 -364 65 -68 857 -98 65 -232 131 -264 63 -98 391 -396 65 -130 99 -98 65 -66 861 -166 265 -166 7611 -10336 65 -1822 165 -300 165 -166 295 -134 199 -100 67 -264 165 -166 99 -500 99 -198 97 -200 165 -268 197 -130 65 -300 629 -166 561 -132 333 -132 7459 -6294 131 -1096 165 -964 197 -332 65 -166 129 -132 99 -130 99 -100 97 -134 65 -164 131 -494 165 -396 97 -164 131 -198 99 -232 229 -66 821 -64 131 -14954 97 -788 65 -100 263 -66 99 -300 65 -400 131 -198 293 -294 163 -132 65 -692 99 -132 131 -200 1847 -132 8773 -5968 133 -330 65 -66 295 -430 197 -166 565 -132 467 -98 65 -430 165 -262 131 -528 131 -296 131 -100 131 -66 557 -166 787 -98 3221 -16236 299 -166 133 -562 199 -1692 99 -66 65 -364 65 -366 231 -168 367 -100 5541 -14968 297 -164 97 -132 163 -328 99 -532 99 -134 131 -370 397 -66 397 -98 293 -98 197 -98 1151 -66 7019 -6746 129 -296 163 -954 261 -230 229 -64 231 -264 431 -100 99 -466 165 -100 333 -166 133 -666 695 -200 67 -134 397 -100 1667 -7686 97 -426 195 -266 97 -330 63 -98 99 -594 97 -132 133 -270 131 -600 131 -362 833 -98 297 -166 199 -66 99 -200 65 -66 197 -100 2963 -98 1125 -2238 199 -554 275 -242 273 -212 271 -242 241 -242 271 -244 241 -244 273 -244 245 -246 247 -248 247 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -246 247 -248 249 -250 247 -504 513 -228 243 -244 273 -246 245 -500 513 -478 257 -242 241 -244 273 -244 499 -512 225 -244 525 -228 273 -496 475 -508 507 -240 253 -254 255 -494 261 -222 505 -258 245 -246 245 -246 245 -250 247 -506 513 -478 257 -242 241 -244 273 -244 499 -68858 319 -218 245 -230 251 -248 245 -248 247 -250 247 -250 249 -248 249 -248 249 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -250 247 -506 257 -246 245 -246 247 -248 503 -516 477 -274 253 -474 511 -478 527 -484 511 -240 253 -472 281 -254 489 -484 513 -478 513 -480 255 -242 523 -472 507 -276 253 -462 275 -240 491 -258 247 -244 245 -246 247 -502 515 -238 253 -254 253 -492 497 -230 253 -250 247 -250 247 -250 247 -250 247 -506 257 -68880 279 -248 241 -266 223 -252 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -506 225 -280 213 -278 245 -248 503 -260 215 -276 245 -246 247 -248 247 -250 247 -504 481 -272 251 +RAW_Data: -254 255 -254 213 -506 483 -514 271 -254 217 -292 217 -248 497 -516 237 -254 473 -278 251 -488 489 -516 477 -272 253 -254 219 -494 261 -260 481 -260 215 -278 247 -248 247 -248 247 -504 481 -514 235 -290 217 -256 253 -244 497 -69132 311 -212 235 -258 249 -248 247 -248 249 -248 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -512 479 -272 253 -474 513 -478 527 -482 513 -238 253 -472 281 -254 487 -486 515 -478 509 -480 255 -242 529 -480 509 -240 255 -496 271 -234 487 -260 247 -244 245 -248 247 -504 511 -226 243 -244 275 -498 479 -272 253 -254 255 -254 249 -238 225 -252 247 -504 257 -68882 319 -188 265 -280 235 -228 251 -250 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 245 -250 247 -250 249 -504 515 -238 251 -256 253 -256 249 -472 515 -480 271 -256 253 -218 255 -248 497 -482 271 -252 473 -280 253 -490 487 -516 477 -274 253 -256 217 -496 261 -224 507 -258 249 -246 245 -248 247 -248 249 -504 511 -478 255 -244 243 -244 275 -246 499 -69134 311 -208 231 -254 249 -246 247 -250 247 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -248 249 -506 259 -246 245 -246 247 -246 503 -516 479 -274 253 -464 519 -496 487 -516 477 -274 255 -498 249 -248 469 -514 479 -516 483 -488 277 -254 491 -498 487 -260 247 -498 227 -244 529 -228 243 -274 245 -246 245 -502 515 -238 251 -256 253 -496 497 -226 251 -248 249 -248 249 -248 249 -250 249 -504 257 -68898 247 -274 213 -312 185 -312 185 -312 185 -312 185 -312 185 -312 185 -310 185 -310 185 -310 215 -278 217 -278 215 -278 217 -278 217 -280 215 -532 237 -288 217 -290 215 -276 461 -260 219 -280 217 -280 217 -278 215 -280 247 -506 481 -270 251 -256 217 -290 213 -502 483 -514 271 -254 253 -218 255 -246 499 -482 271 -254 473 -282 253 -488 485 -516 477 -274 253 -256 217 -496 263 -224 507 -260 247 -246 245 -246 247 -248 249 -504 513 -478 255 -242 243 -244 275 -246 499 -69122 319 -220 243 -228 251 -248 247 -248 247 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -504 257 -248 245 -246 247 -246 505 -514 479 -274 253 -476 511 -476 493 -516 481 -270 253 -474 279 -254 487 -484 513 +RAW_Data: -478 507 -506 225 -272 495 -482 505 -254 241 -494 255 -242 525 -226 241 -274 243 -242 243 -496 509 -274 253 -254 219 -494 491 -258 249 -248 247 -248 249 -248 249 -248 249 -504 257 -68896 281 -214 241 -260 247 -248 247 -248 247 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -260 245 -246 245 -248 247 -248 247 -248 249 -504 513 -238 251 -254 255 -254 251 -474 515 -478 273 -254 255 -218 253 -248 499 -514 237 -254 473 -280 253 -490 485 -516 479 -274 253 -256 217 -496 263 -224 507 -258 247 -248 245 -246 247 -250 247 -504 513 -478 257 -244 241 -244 275 -246 499 -69128 321 -218 241 -230 249 -248 247 -246 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -504 257 -248 245 -246 245 -250 503 -514 477 -272 255 -474 515 -480 491 -518 479 -274 253 -474 281 -254 483 -486 479 -512 507 -506 223 -242 527 -482 509 -240 253 -496 273 -236 487 -260 247 -246 245 -246 247 -504 513 -238 251 -256 253 -492 495 -228 253 -250 249 -250 249 -250 249 -248 249 -504 257 -68860 273 -242 233 -256 249 -250 247 -248 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 247 -248 247 -248 249 -504 513 -238 253 -254 253 -256 249 -474 515 -480 273 -254 255 -218 253 -248 497 -516 237 -252 473 -280 253 -490 487 -514 479 -274 253 -254 219 -496 263 -224 507 -258 247 -246 245 -246 247 -248 249 -504 513 -476 257 -242 243 -244 273 -246 499 -68728 129 -604 249 -242 243 -276 213 -276 245 -244 245 -246 245 -278 215 -278 215 -278 247 -248 247 -248 247 -248 249 -248 247 -250 247 -250 247 -250 247 -504 259 -246 245 -246 247 -248 503 -514 477 -272 255 -474 511 -478 527 -484 481 -272 253 -472 281 -254 485 -486 511 -478 511 -480 255 -242 527 -482 505 -254 241 -494 253 -242 495 -254 241 -244 273 -244 243 -494 509 -238 255 -254 255 -492 489 -260 247 -248 245 -248 247 -248 249 -248 249 -504 257 -129658 99 -98 131 -132 97 -100 97 -132 131 -98 131 -496 297 -266 163 -198 99 -398 165 -626 133 -198 531 -166 67 -66 431 -132 331 -100 65 -132 99 -100 2725 -9960 65 -3686 295 -1552 99 -362 195 -100 887 -98 263 -100 1495 -8372 67 -298 99 -100 131 -332 133 -198 233 -398 65 -1060 99 -164 327 +RAW_Data: -460 129 -262 97 -100 755 -132 6515 -12306 229 -296 625 -198 131 -200 131 -398 165 -1634 231 -68 331 -166 133 -132 5259 -8900 67 -6298 99 -264 199 -66 133 -100 429 -200 131 -132 195 -266 163 -100 229 -462 165 -334 199 -132 63 -264 163 -264 231 -66 363 -68 331 -66 563 -100 6577 -10216 67 -962 99 -794 131 -198 133 -132 299 -66 133 -66 331 -630 163 -266 163 -132 99 -500 97 -232 195 -394 231 -66 133 -100 329 -400 7509 -12254 65 -166 65 -328 361 -266 65 -68 131 -100 65 -926 65 -758 99 -592 459 -66 557 -98 327 -66 1317 -100 3491 -16028 263 -132 227 -96 297 -68 165 -1160 133 -1030 97 -796 199 -134 65 -132 361 -100 389 -198 3891 -16112 131 -98 229 -1120 163 -1648 131 -392 429 -166 231 -926 2655 -16140 395 -230 227 -296 65 -98 199 -200 99 -1062 99 -134 695 -66 231 -100 97 -198 265 -198 67 -100 2705 -16076 99 -66 263 -398 229 -264 131 -132 63 -100 129 -1780 65 -362 229 -98 295 -132 555 -266 4985 -11336 65 -924 99 -200 263 -330 265 -298 133 -100 163 -628 97 -528 163 -228 459 -132 65 -66 297 -100 261 -100 131 -198 295 -98 229 -66 3967 -10946 131 -830 131 -102 663 -66 361 -396 165 -66 131 -1394 99 -98 131 -166 327 -66 559 -98 295 -134 65 -98 97 -132 427 -328 2763 -15960 131 -432 299 -798 131 -1030 295 -732 197 -132 231 -100 99 -98 199 -134 233 -134 331 -200 7663 -7818 163 -532 99 -264 267 -266 229 -1188 97 -98 99 -1492 463 -132 233 -168 97 -132 825 -66 6395 -13604 131 -430 133 -166 133 -864 65 -1162 397 -198 365 -134 165 -100 365 -66 8413 -8042 163 -164 131 -398 65 -1722 229 -428 97 -130 65 -596 395 -100 429 -100 131 -200 331 -98 433 -68 2937 -7902 65 -332 131 -7288 333 -396 65 -366 99 -232 99 -232 333 -1126 131 -594 99 -398 65 -100 893 -296 163 -66 525 -98 3767 -15992 265 -694 199 -366 231 -1000 65 -1358 97 -134 463 -100 231 -134 3623 -15876 129 -328 129 -132 65 -596 199 -566 231 -530 99 -596 595 -166 593 -200 97 -68 3353 -16312 131 -134 231 -202 133 -134 97 -234 131 -66 165 -628 101 -596 1027 -134 331 -198 3715 -66 195 -10652 229 -164 591 -362 97 -560 359 -464 97 -68 197 -266 165 -332 7019 -9984 199 -1166 363 -132 97 -100 131 -198 133 -232 229 -1058 67 -200 529 -198 65 -98 897 -66 265 -134 6685 -9926 297 -530 589 -66 97 -230 131 -98 99 -724 163 -164 163 -196 229 -164 267 -132 167 -68 333 -66 199 -100 131 -66 497 -66 4929 -9050 97 -5010 65 -1394 99 +RAW_Data: -562 165 -98 493 -66 65 -494 63 -132 397 -502 263 -1020 363 -68 8779 -5986 133 -1590 99 -894 165 -66 167 -136 99 -732 265 -66 133 -166 131 -266 267 -564 197 -68 941 -100 3631 -66 4059 -6506 263 -958 165 -568 167 -334 397 -530 231 -166 367 -364 133 -100 131 -134 133 -598 99 -200 2261 -8366 65 -6804 97 -262 263 -132 65 -98 231 -430 97 -164 97 -428 65 -134 99 -668 131 -296 233 -200 499 -98 889 -98 6325 -502 211 -558 271 -240 265 -224 249 -248 247 -248 249 -248 249 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -258 247 -246 245 -246 247 -248 249 -504 257 -246 499 -480 507 -256 241 -244 273 -496 509 -224 243 -526 477 -510 507 -240 253 -498 245 -244 497 -260 245 -246 243 -502 255 -248 243 -246 501 -258 247 -244 245 -500 511 -476 257 -242 527 -476 505 -254 241 -494 507 -480 255 -68596 289 -214 247 -250 249 -252 249 -250 249 -250 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -504 257 -248 245 -246 247 -248 503 -514 477 -272 255 -254 217 -496 491 -516 481 -512 255 -242 497 -274 253 -254 219 -496 263 -224 251 -250 505 -514 477 -256 243 -244 243 -276 243 -500 225 -278 497 -478 509 -512 473 -256 241 -244 273 -496 255 -242 243 -244 495 -274 251 -474 279 -254 487 -486 257 -248 243 -68886 271 -238 265 -226 251 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -504 257 -248 245 -248 245 -248 503 -260 245 -246 243 -248 247 -248 249 -504 257 -248 499 -480 507 -256 241 -244 243 -530 475 -256 243 -494 509 -482 507 -274 255 -484 237 -244 499 -260 247 -246 245 -504 257 -246 245 -244 501 -258 245 -246 245 -500 513 -480 273 -256 473 -484 509 -262 225 -508 513 -478 255 -68906 287 -254 211 -272 225 -252 247 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -248 249 -506 227 -278 245 -246 247 -246 505 -514 477 -272 253 -254 217 -496 491 -516 479 -510 257 -244 497 -272 253 -254 217 -498 261 -224 253 -250 505 -516 475 -256 243 -246 245 -244 245 -530 225 -246 529 -478 507 -510 483 -276 217 -292 217 -486 259 -248 247 -250 501 -258 215 -532 225 -244 529 -478 257 -242 243 -68922 239 -244 271 -226 251 -248 247 -250 247 -250 247 -250 247 -250 249 -248 249 +RAW_Data: -250 249 -250 249 -248 249 -248 249 -250 249 -250 247 -250 247 -506 257 -248 245 -246 245 -248 503 -258 245 -246 245 -248 247 -248 247 -506 257 -248 497 -480 509 -272 255 -254 255 -460 525 -226 249 -500 511 -478 507 -238 291 -476 245 -252 481 -260 247 -246 245 -502 255 -248 245 -246 501 -258 245 -246 245 -500 511 -476 255 -244 525 -478 505 -254 243 -492 507 -480 255 -68946 283 -250 241 -226 251 -248 247 -248 247 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -512 477 -274 253 -254 255 -460 493 -518 479 -510 255 -244 495 -274 253 -256 217 -496 261 -226 251 -250 503 -514 477 -274 253 -256 253 -218 249 -500 259 -246 499 -480 513 -482 505 -254 241 -244 243 -526 223 -272 243 -244 495 -272 255 -500 249 -246 473 -516 227 -244 243 -68908 317 -218 243 -258 247 -246 245 -248 247 -248 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -248 249 -250 249 -250 247 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 245 -250 247 -504 257 -248 499 -480 507 -274 253 -254 255 -460 527 -224 249 -502 511 -476 505 -256 241 -494 255 -242 527 -240 253 -254 255 -458 261 -262 223 -252 505 -260 245 -246 245 -500 511 -476 257 -242 525 -474 509 -238 289 -464 519 -496 225 -68914 283 -252 243 -266 223 -252 249 -252 249 -248 249 -250 249 -250 249 -250 247 -248 247 -250 247 -250 247 -250 249 -250 247 -250 247 -250 249 -506 225 -278 245 -246 247 -248 503 -516 479 -274 215 -292 217 -494 491 -516 477 -510 255 -244 497 -272 217 -290 219 -494 261 -258 221 -252 505 -514 479 -272 251 -256 217 -254 247 -500 227 -278 499 -480 509 -514 477 -276 253 -256 217 -520 225 -252 247 -248 503 -260 215 -530 225 -246 495 -510 257 -244 245 -68932 283 -218 247 -240 257 -250 247 -248 247 -248 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -506 259 -246 245 -246 245 -248 503 -260 245 -246 245 -246 247 -248 249 -504 259 -248 497 -482 509 -274 255 -218 253 -498 491 -258 247 -500 511 -478 507 -238 289 -466 283 -210 503 -258 247 -244 245 -500 257 -246 245 -244 501 -260 245 -244 245 -500 511 -476 257 -242 525 -474 509 -238 289 -464 519 -496 225 -68912 285 -250 243 -230 253 -250 247 -250 247 -250 247 -250 247 -250 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -248 249 +RAW_Data: -250 247 -504 227 -280 245 -246 247 -248 501 -514 477 -272 253 -254 219 -496 493 -514 481 -512 223 -276 495 -274 217 -290 217 -496 229 -256 253 -250 507 -516 477 -258 243 -244 245 -244 245 -530 225 -246 497 -512 511 -482 509 -240 253 -256 251 -482 257 -250 247 -248 505 -258 215 -532 235 -252 473 -518 243 -280 235 -68898 281 -248 239 -230 253 -250 247 -248 247 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -250 249 -248 249 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 505 -258 247 -244 245 -248 247 -248 247 -504 257 -246 501 -480 513 -238 289 -220 253 -494 489 -260 247 -502 479 -508 509 -238 253 -482 277 -248 479 -260 247 -248 247 -502 257 -246 245 -246 499 -258 247 -244 245 -502 515 -476 257 -242 495 -512 475 -272 255 -496 481 -492 259 -68570 131 -550 315 -218 253 -256 245 -236 255 -248 247 -250 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -250 249 -504 257 -248 243 -248 245 -248 503 -512 477 -274 253 -254 255 -458 525 -482 515 -478 255 -242 495 -274 253 -256 217 -496 261 -226 253 -250 505 -514 475 -256 243 -244 273 -244 245 -498 257 -246 499 -478 507 -506 507 -238 255 -254 255 -492 227 -254 249 -248 503 -258 247 -498 257 -214 527 -480 271 -256 253 -138338 231 -728 97 -596 199 -556 163 -262 427 -330 359 -164 727 -66 663 -396 4171 -7546 65 -864 131 -362 529 -326 131 -2650 231 -298 197 -66 335 -264 529 -66 2745 -16072 201 -132 133 -664 265 -2520 433 -132 465 -134 459 -364 267 -66 1303 -8330 297 -368 133 -890 197 -1992 131 -462 67 -66 265 -266 561 -296 197 -198 195 -132 459 -66 3345 -16118 99 -164 297 -66 229 -332 97 -234 65 -166 65 -764 97 -700 67 -232 465 -134 563 -200 363 -100 1487 -96 5715 -8386 195 -298 163 -130 295 -100 97 -494 99 -754 327 -164 295 -132 195 -66 425 -66 3351 -64 1925 -6840 231 -64 97 -66 131 -462 99 -98 131 -494 197 -2274 397 -68 163 -166 565 -166 197 -100 3691 -64 3991 -8380 65 -164 197 -194 327 -100 367 -860 233 -596 629 -100 231 -132 1957 -100 1993 -66 3287 -6542 97 -1854 331 -132 131 -662 297 -494 99 -100 201 -1730 365 -166 559 -100 199 -66 331 -198 2209 -130 3295 -13088 99 -332 131 -790 263 -98 163 -1252 165 -196 263 -130 99 -132 361 -132 291 -262 99 -196 6531 -12274 133 -630 65 -302 165 -334 99 -1590 165 -828 291 -98 691 -198 561 -132 133 -68 7049 -9118 331 -662 165 -66 65 -132 65 +RAW_Data: -364 129 -98 265 -98 97 -66 589 -5626 67 -2546 231 -230 197 -232 197 -262 261 -464 97 -594 229 -296 165 -130 65 -166 99 -166 97 -66 229 -100 99 -66 131 -132 3567 -7898 95 -6038 99 -802 163 -68 97 -232 131 -326 65 -298 97 -132 231 -302 99 -298 65 -132 231 -1024 97 -100 331 -100 397 -232 99 -66 263 -68 231 -298 7371 -8180 165 -100 261 -68 165 -430 229 -198 67 -132 131 -300 65 -266 165 -498 165 -66 531 -232 263 -68 593 -134 131 -13852 65 -198 133 -634 97 -1128 97 -264 131 -66 165 -198 293 -494 99 -428 99 -962 99 -132 133 -264 833 -98 233 -14108 65 -1496 131 -230 67 -100 133 -666 131 -132 133 -232 65 -268 99 -400 99 -1854 597 -132 263 -98 493 -230 893 -98 3963 -15854 197 -130 165 -98 195 -330 261 -330 97 -132 97 -664 65 -500 5941 -132 1485 -11064 97 -992 163 -132 65 -434 197 -532 97 -134 297 -922 329 -658 163 -132 421 -264 429 -100 265 -298 229 -134 3353 -15986 131 -362 131 -132 459 -230 199 -66 393 -1060 99 -1096 131 -134 263 -66 163 -132 259 -130 97 -328 331 -66 99 -166 2561 -14808 65 -762 65 -66 197 -100 299 -398 133 -134 131 -66 65 -98 297 -10702 97 -464 131 -1526 133 -198 129 -100 131 -164 99 -132 163 -1098 129 -962 163 -300 65 -66 963 -166 3181 -8734 363 -2112 163 -1062 297 -98 427 -100 165 -100 231 -100 7535 -6418 65 -1522 65 -196 97 -64 131 -166 97 -332 65 -166 197 -100 265 -1564 65 -132 67 -696 133 -198 535 -98 297 -164 263 -8472 97 -560 327 -100 129 -64 65 -228 165 -162 163 -2146 561 -100 827 -232 463 -66 731 -66 4783 -10516 131 -300 131 -832 99 -100 331 -198 133 -232 99 -234 165 -266 165 -362 231 -66 297 -134 495 -98 165 -266 99 -132 859 -66 163 -98 165 -98 5587 -12622 131 -200 165 -1460 99 -432 265 -860 65 -262 591 -66 195 -100 425 -166 259 -66 227 -100 9819 -556 65 -3310 295 -562 199 -98 267 -200 131 -66 131 -168 99 -962 131 -534 99 -1848 197 -100 365 -132 1031 -66 2057 -66 2023 -7754 97 -7222 263 -698 165 -264 131 -366 97 -464 65 -466 65 -298 231 -430 97 -98 263 -64 953 -66 4093 -100 4171 -6616 65 -1220 99 -268 99 -98 99 -200 201 -134 97 -98 165 -164 295 -132 357 -396 165 -98 65 -230 163 -164 423 -130 651 -64 3641 -130 859 -7392 165 -100 165 -166 99 -66 167 -132 101 -132 67 -166 165 -100 333 -660 99 -162 97 -162 63 -424 131 -98 129 -392 131 -68 395 -132 389 -66 161 -17386 261 -298 99 -134 131 +RAW_Data: -100 65 -366 131 -166 197 -68 97 -166 165 -788 131 -198 97 -132 129 -164 163 -132 199 -66 267 -232 165 -68 165 -98 199 -134 1197 -568 273 -256 253 -256 249 -240 225 -252 247 -248 247 -248 247 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 245 -250 247 -504 257 -248 499 -226 277 -496 255 -216 525 -480 257 -242 273 -242 497 -480 511 -274 253 -474 513 -478 263 -224 253 -250 247 -250 503 -260 245 -246 245 -500 257 -248 243 -248 499 -514 477 -272 255 -474 511 -478 263 -260 479 -514 477 -68856 257 -248 247 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 249 -250 249 -248 249 -248 249 -250 247 -250 249 -250 249 -250 247 -504 257 -248 245 -246 247 -248 503 -514 477 -274 253 -256 217 -494 523 -228 249 -502 513 -238 253 -254 253 -492 231 -264 227 -254 505 -258 247 -246 245 -248 245 -250 247 -504 257 -248 499 -478 509 -274 253 -500 249 -246 237 -228 509 -516 477 -516 483 -490 501 -518 479 -262 225 -512 257 -248 499 -69120 321 -218 245 -234 253 -250 247 -250 247 -250 247 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -260 245 -246 245 -246 247 -248 249 -504 257 -248 499 -228 243 -530 225 -244 529 -478 257 -242 243 -244 529 -476 509 -238 255 -512 479 -506 259 -226 251 -252 249 -250 505 -258 245 -246 245 -504 257 -246 245 -244 501 -516 479 -274 253 -476 479 -508 261 -226 511 -514 477 -69158 271 -240 263 -226 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -250 249 -504 257 -246 245 -246 247 -248 505 -514 475 -256 243 -244 243 -526 479 -272 255 -474 511 -240 243 -270 225 -508 257 -246 245 -246 501 -258 245 -244 245 -248 247 -248 247 -504 257 -248 499 -480 509 -274 253 -464 285 -246 239 -228 507 -482 509 -506 509 -482 507 -486 515 -240 241 -500 259 -248 499 -69138 283 -254 241 -230 251 -248 247 -248 249 -248 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -258 247 -246 243 -248 247 -248 247 -504 257 -248 499 -228 245 -530 237 -252 503 -486 279 -246 237 -230 507 -516 479 -274 253 -464 517 -496 227 -254 249 -250 247 -250 505 -258 247 -246 245 -502 257 -246 245 +RAW_Data: -244 501 -512 477 -272 255 -474 511 -478 263 -228 511 -514 475 -69198 287 -218 249 -238 255 -250 249 -248 247 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 247 -250 247 -250 249 -250 249 -504 257 -248 245 -246 247 -248 503 -514 477 -272 255 -254 217 -498 493 -258 249 -504 479 -272 253 -254 255 -490 231 -262 225 -252 507 -258 247 -246 245 -248 245 -250 247 -504 257 -248 499 -480 513 -238 255 -498 247 -280 237 -228 507 -514 479 -516 483 -490 503 -506 505 -248 253 -492 229 -254 505 -69150 317 -284 135 -324 159 -348 157 -346 157 -346 157 -314 189 -312 187 -314 187 -312 187 -312 187 -312 185 -312 187 -280 217 -280 215 -312 185 -566 195 -278 215 -278 215 -278 469 -306 213 -290 219 -288 207 -268 223 -510 225 -280 467 -272 249 -506 247 -254 489 -490 257 -248 245 -248 501 -516 477 -256 243 -494 509 -508 237 -256 253 -256 249 -240 487 -260 245 -246 245 -500 257 -248 243 -246 501 -512 475 -274 253 -476 511 -478 263 -260 477 -514 479 -69176 271 -240 265 -224 251 -250 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -506 257 -248 245 -246 245 -248 503 -514 477 -256 243 -244 243 -530 477 -274 253 -476 479 -272 239 -266 225 -508 259 -248 245 -246 501 -258 215 -276 245 -246 247 -248 247 -504 257 -248 501 -480 511 -256 243 -496 255 -242 243 -244 497 -512 475 -516 509 -520 477 -510 495 -226 251 -504 257 -248 499 -69162 285 -218 249 -240 257 -250 247 -248 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -246 247 -248 249 -504 257 -248 499 -226 277 -498 225 -244 527 -478 257 -244 243 -244 527 -476 507 -258 241 -494 507 -510 237 -256 253 -254 251 -242 491 -226 277 -244 245 -500 255 -248 243 -246 501 -512 477 -256 243 -494 507 -506 253 -244 495 -480 505 -69176 261 -258 221 -252 251 -250 249 -250 249 -250 249 -250 249 -250 249 -248 249 -250 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 247 -506 227 -280 245 -246 245 -248 503 -516 477 -256 243 -244 245 -496 509 -256 243 -496 509 -238 255 -254 255 -490 229 -254 251 -250 505 -258 215 -278 245 -246 247 -250 247 -504 227 -278 499 -480 511 -274 217 -514 243 -248 243 -266 483 -514 481 -512 475 -520 473 -506 507 -248 243 -500 249 -244 497 -69180 273 -256 217 +RAW_Data: -290 219 -246 235 -256 251 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -504 227 -278 245 -246 247 -246 505 -258 215 -278 245 -246 247 -248 247 -506 225 -278 499 -228 245 -530 225 -244 497 -508 257 -244 243 -246 497 -512 477 -272 255 -482 511 -500 229 -254 251 -250 249 -250 503 -260 215 -278 215 -534 225 -246 245 -276 499 -482 513 -238 253 -500 483 -528 227 -252 505 -514 479 -68732 173 -546 275 -240 233 -256 247 -250 247 -250 247 -250 247 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -504 257 -248 245 -246 247 -248 503 -514 477 -272 255 -254 217 -498 493 -260 249 -500 479 -272 253 -254 255 -494 233 -262 223 -252 505 -258 247 -246 245 -246 247 -250 247 -504 257 -248 499 -482 511 -238 255 -498 245 -280 237 -228 507 -516 479 -512 477 -518 475 -518 481 -270 237 -494 259 -250 501 -136574 65 -1160 65 -770 395 -198 199 -66 65 -330 231 -436 65 -1228 165 -664 727 -198 199 -166 229 -196 457 -64 493 -66 1987 -15790 99 -100 131 -234 231 -496 893 -234 297 -66 8071 -8244 99 -236 165 -134 199 -132 67 -198 165 -1094 65 -1782 195 -66 921 -66 229 -100 391 -132 7785 -7282 65 -402 65 -166 267 -266 165 -100 231 -166 461 -166 65 -696 65 -298 131 -166 99 -232 263 -100 397 -166 499 -66 165 -364 7435 -8394 331 -198 99 -198 99 -234 99 -1738 991 -198 333 -198 499 -132 891 -98 3239 -15978 165 -896 97 -100 131 -198 97 -532 65 -300 67 -1330 329 -66 859 -66 199 -232 397 -100 7707 -8162 363 -232 165 -98 231 -130 165 -294 131 -858 99 -932 65 -164 131 -264 565 -198 165 -132 233 -366 7109 -6100 65 -3046 165 -500 131 -232 67 -1028 99 -232 97 -300 65 -434 727 -166 363 -100 367 -64 263 -100 3147 -15114 65 -164 197 -296 97 -66 229 -264 497 -332 67 -98 99 -432 163 -132 65 -794 199 -166 297 -200 6509 -12574 199 -234 65 -132 99 -334 67 -264 131 -100 331 -168 65 -266 99 -166 397 -266 431 -98 565 -166 527 -100 3021 -68 3551 -12844 163 -294 165 -300 461 -856 331 -66 99 -1160 131 -132 293 -132 493 -166 261 -196 1149 -132 2177 -68 961 -15018 65 -992 99 -266 99 -200 229 -164 197 -956 231 -368 67 -100 99 -930 297 -360 623 -166 695 -134 1631 -66 957 -100 3451 -10430 65 -100 65 -1120 65 -198 65 -98 567 -200 199 -560 297 -792 65 -196 97 -690 197 -164 295 -66 295 -132 6963 -7554 131 -952 197 -228 131 +RAW_Data: -332 97 -264 295 -492 65 -1418 131 -396 363 -66 265 -134 731 -100 165 -68 133 -66 7537 -7378 65 -922 197 -164 229 -230 529 -66 165 -98 199 -132 65 -726 65 -164 97 -824 97 -230 427 -166 1363 -8016 97 -3030 65 -892 133 -164 99 -162 395 -230 163 -230 163 -230 197 -626 65 -166 97 -498 97 -700 495 -66 1215 -164 327 -10158 129 -1690 595 -198 163 -232 165 -164 365 -100 97 -732 99 -498 197 -364 365 -166 165 -134 797 -100 563 -100 3113 -9966 97 -426 165 -5434 393 -332 65 -98 99 -164 97 -232 65 -726 99 -266 265 -232 67 -298 461 -100 663 -68 9469 -8388 165 -396 231 -134 197 -166 67 -1556 97 -132 95 -230 65 -130 99 -98 657 -66 327 -68 527 -98 4249 -7974 97 -300 131 -264 397 -132 165 -562 99 -1060 65 -732 497 -134 531 -100 199 -66 203 -66 2987 -100 1657 -12228 97 -364 265 -200 165 -792 65 -396 129 -1312 623 -164 261 -98 165 -162 465 -66 3855 -8016 97 -6056 65 -1896 65 -366 99 -266 133 -132 99 -332 231 -864 133 -100 725 -98 261 -328 363 -98 293 -66 4765 -12278 99 -434 165 -64 65 -166 197 -498 65 -166 231 -500 99 -398 199 -398 695 -132 431 -100 131 -132 165 -66 199 -302 1463 -3364 241 -526 317 -212 235 -254 247 -248 245 -248 247 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -258 247 -246 245 -246 247 -248 249 -248 249 -248 249 -506 513 -238 251 -256 253 -490 499 -488 513 -476 509 -274 255 -474 479 -272 237 -266 225 -508 511 -226 245 -244 275 -500 225 -246 275 -244 501 -228 245 -528 225 -246 529 -478 257 -244 243 -244 245 -276 499 -226 245 -276 245 -246 245 -68834 321 -218 243 -232 253 -248 245 -248 247 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -504 257 -248 245 -246 247 -248 503 -512 477 -272 255 -500 483 -500 489 -514 479 -274 253 -254 219 -254 247 -236 255 -250 247 -504 257 -248 497 -226 245 -530 477 -274 253 -254 255 -458 525 -484 511 -476 509 -482 507 -274 255 -254 217 -488 259 -250 247 -248 245 -250 503 -260 245 -500 479 -272 255 -69110 309 -218 253 -256 253 -246 231 -254 247 -248 247 -248 247 -248 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 247 -506 257 -248 245 -246 245 -248 503 -260 245 -246 245 -248 245 -248 249 -248 249 -250 247 -506 513 -226 273 -244 243 -498 513 -476 509 +RAW_Data: -482 519 -240 255 -496 505 -228 253 -250 247 -504 513 -226 273 -244 243 -498 257 -246 245 -244 499 -258 245 -500 257 -214 527 -478 257 -242 273 -244 243 -246 501 -258 245 -246 245 -246 247 -69160 247 -274 213 -274 245 -242 245 -276 213 -276 245 -244 245 -246 245 -278 213 -278 245 -248 249 -248 247 -250 249 -248 249 -250 247 -248 249 -504 257 -246 245 -246 247 -248 503 -512 477 -274 251 -476 509 -512 461 -518 479 -258 243 -244 245 -276 245 -246 247 -248 247 -504 257 -248 501 -226 245 -530 477 -256 243 -244 245 -532 479 -480 509 -520 485 -488 509 -262 221 -252 249 -506 257 -248 245 -246 247 -248 503 -258 247 -498 477 -258 243 -69136 303 -236 227 -256 247 -250 247 -250 247 -250 249 -250 249 -248 249 -248 249 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -506 257 -248 243 -246 247 -248 505 -258 247 -244 245 -246 247 -250 247 -248 249 -250 247 -506 513 -226 243 -274 245 -498 511 -476 507 -482 507 -274 255 -484 475 -264 261 -222 251 -506 513 -238 251 -256 253 -496 233 -264 225 -252 505 -260 247 -498 225 -246 529 -478 257 -244 243 -244 275 -244 499 -258 245 -244 245 -246 247 -69174 321 -218 253 -242 231 -252 249 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 247 -504 259 -246 245 -248 245 -248 505 -514 479 -274 253 -476 511 -478 493 -516 481 -272 255 -254 253 -220 247 -240 257 -250 247 -502 257 -248 499 -228 245 -528 479 -272 255 -254 253 -460 525 -482 515 -476 509 -482 505 -254 241 -242 243 -526 225 -272 243 -242 243 -244 529 -238 253 -472 511 -276 247 -69140 309 -212 241 -244 273 -242 243 -242 243 -274 243 -244 241 -244 245 -276 245 -244 247 -248 247 -248 249 -250 247 -250 249 -250 247 -250 247 -506 257 -248 245 -246 245 -248 503 -258 245 -246 247 -246 247 -248 249 -248 249 -250 249 -504 513 -238 251 -254 255 -494 501 -484 513 -478 509 -238 253 -514 481 -270 235 -264 223 -506 513 -238 253 -254 255 -490 231 -266 225 -254 507 -258 247 -500 225 -246 529 -480 271 -256 253 -256 217 -248 501 -258 247 -244 245 -246 247 -69188 287 -218 247 -234 255 -250 247 -248 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -504 257 -248 245 -248 245 -250 503 -514 479 -274 253 -498 483 -500 487 -514 477 -258 241 -244 243 -246 275 -244 245 -248 245 -504 257 -248 499 -228 245 +RAW_Data: -528 477 -256 243 -244 245 -530 475 -508 509 -482 509 -492 505 -246 253 -254 243 -494 227 -278 245 -248 245 -248 503 -258 215 -530 479 -272 251 -69146 297 -230 225 -252 249 -250 249 -250 249 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 247 -506 259 -246 245 -246 247 -248 501 -258 247 -244 245 -248 247 -248 249 -248 249 -250 247 -506 513 -238 251 -254 255 -494 501 -484 513 -478 509 -238 253 -514 479 -270 237 -264 223 -508 513 -238 253 -254 255 -494 233 -262 225 -252 505 -258 247 -500 225 -246 529 -478 257 -242 243 -244 275 -246 499 -258 215 -276 245 -246 245 -69160 287 -254 251 -238 227 -252 249 -248 247 -250 247 -250 247 -250 249 -250 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -506 227 -280 215 -276 245 -248 505 -480 511 -272 253 -476 479 -506 493 -514 479 -260 243 -246 245 -276 245 -246 247 -248 247 -504 227 -278 499 -238 249 -504 473 -280 241 -244 243 -500 505 -520 485 -500 487 -518 479 -274 251 -256 217 -496 263 -224 251 -252 249 -250 503 -258 247 -500 479 -258 243 -131656 133 -100 133 -200 165 -100 97 -232 627 -1028 133 -992 163 -132 635 -264 197 -100 4009 -10800 163 -230 231 -168 65 -132 201 -400 395 -98 99 -296 393 -100 295 -66 1425 -6868 99 -1394 129 -164 65 -392 329 -1518 229 -198 163 -100 665 -66 199 -166 335 -166 165 -98 3141 -8982 65 -6896 163 -262 391 -230 195 -428 163 -526 131 -98 165 -196 65 -98 65 -724 131 -200 1585 -164 6977 -13106 131 -164 65 -692 97 -894 65 -998 297 -66 165 -166 401 -132 233 -66 561 -266 1987 -64 555 -13660 99 -430 131 -232 131 -398 99 -630 99 -100 267 -464 97 -924 99 -66 265 -526 561 -132 165 -68 199 -134 1951 -66 1643 -15920 231 -528 163 -162 65 -458 229 -98 65 -622 97 -68 97 -132 163 -134 631 -398 131 -198 883 -66 759 -64 1083 -16320 699 -464 163 -328 131 -232 231 -230 97 -690 263 -294 557 -100 729 -230 427 -98 65 -130 7841 -8604 131 -262 163 -200 199 -398 99 -98 263 -490 97 -132 97 -130 129 -626 229 -396 557 -66 229 -164 393 -262 395 -98 2347 -16232 297 -300 99 -68 297 -3186 461 -330 229 -68 131 -130 1389 -66 3247 -10450 131 -1522 229 -496 131 -100 195 -132 129 -66 327 -64 99 -196 133 -1794 67 -132 329 -100 197 -498 165 -132 165 -166 263 -132 7439 -7152 99 -502 131 -134 65 -200 199 -164 133 -100 401 -266 367 -1260 197 -366 297 -428 399 -198 897 +RAW_Data: -66 3765 -13986 497 -562 97 -732 297 -266 99 -232 429 -132 65 -298 197 -268 97 -1192 1259 -68 65 -132 97 -100 8047 -6842 97 -362 165 -130 131 -66 459 -164 197 -164 263 -164 359 -462 195 -262 65 -1122 229 -66 755 -100 465 -132 6211 -9870 99 -66 129 -100 163 -98 131 -264 131 -162 97 -198 97 -196 197 -262 229 -958 165 -266 65 -98 697 -200 5723 -12050 299 -66 231 -232 99 -528 99 -66 233 -134 65 -534 131 -1028 97 -300 63 -266 97 -100 133 -134 891 -100 4201 -100 3703 -8722 229 -360 263 -164 459 -66 819 -132 163 -1126 267 -66 231 -200 731 -232 229 -8678 131 -132 229 -198 295 -592 165 -820 65 -756 99 -66 65 -68 99 -200 199 -332 297 -100 565 -7800 65 -500 65 -7518 465 -368 99 -230 65 -832 99 -2356 627 -198 131 -100 361 -130 295 -132 3819 -96 5271 -6210 65 -266 393 -98 131 -64 329 -362 365 -66 133 -132 67 -632 65 -430 265 -166 65 -566 131 -132 461 -66 1429 -134 4601 -10498 65 -402 65 -430 229 -328 359 -98 263 -624 165 -168 199 -166 97 -494 197 -196 99 -98 261 -132 297 -166 99 -66 4183 -66 2927 -6458 99 -1894 427 -498 331 -562 131 -1458 229 -690 1785 -68 231 -100 731 -12140 165 -168 67 -134 131 -100 233 -198 99 -662 265 -730 299 -166 227 -328 97 -164 821 -66 2903 -66 1043 -7904 65 -3146 65 -4854 99 -98 133 -132 133 -760 99 -692 259 -1554 65 -98 495 -230 261 -64 491 -166 163 -98 227 -16058 97 -100 163 -294 197 -164 195 -100 129 -362 163 -626 65 -166 129 -526 65 -132 829 -100 597 -68 197 -366 1025 -66 497 -98 1387 -66 329 -12300 99 -232 99 -232 65 -532 99 -100 165 -402 131 -1326 395 -98 565 -232 131 -168 65 -166 1621 -66 2509 -13018 165 -362 99 -1982 99 -66 65 -764 593 -430 229 -132 329 -164 263 -100 2629 -15978 297 -68 131 -662 65 -98 99 -526 133 -132 133 -498 97 -560 229 -66 855 -98 593 -98 7597 -8606 427 -164 131 -822 65 -98 67 -296 97 -496 131 -198 97 -164 97 -394 1449 -230 397 -66 2897 -8398 165 -236 97 -1752 65 -330 65 -462 231 -134 131 -2680 1025 -132 633 -130 7803 -6500 65 -2808 67 -332 197 -164 97 -66 163 -2234 195 -132 425 -66 755 -98 2687 -66 5177 -6880 65 -1510 97 -232 195 -232 131 -234 197 -200 65 -166 65 -198 165 -134 67 -1262 395 -100 297 -98 165 -402 331 -134 5357 -12090 197 -232 99 -332 97 -2278 265 -66 563 -134 297 -66 3607 -10024 65 -4678 363 -166 201 -200 165 -100 163 -392 131 -98 129 -624 195 -332 65 -962 295 +RAW_Data: -132 165 -132 3857 -11128 241 -562 311 -208 235 -256 249 -250 247 -248 249 -248 247 -250 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 247 -504 259 -246 245 -246 247 -248 503 -258 247 -246 245 -248 245 -250 247 -250 247 -250 247 -506 513 -238 251 -256 253 -256 247 -474 259 -248 501 -480 509 -274 217 -514 477 -272 237 -266 223 -508 481 -512 509 -482 509 -490 505 -520 247 -246 241 -230 255 -250 249 -250 247 -250 505 -514 479 -512 475 -274 255 -68824 287 -218 273 -250 237 -230 251 -248 247 -248 247 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -514 477 -256 243 -494 509 -274 253 -476 245 -252 517 -226 249 -502 511 -224 243 -528 475 -508 505 -474 255 -242 273 -242 495 -274 253 -500 485 -498 227 -254 247 -250 503 -260 245 -498 513 -478 511 -472 507 -274 255 -254 255 -212 271 -480 511 -226 241 -69142 299 -230 225 -254 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 249 -504 257 -246 245 -246 247 -248 501 -258 247 -246 245 -248 247 -248 247 -250 247 -250 249 -504 513 -226 243 -276 243 -246 245 -502 257 -246 499 -478 509 -274 253 -500 485 -232 263 -226 251 -506 513 -476 509 -480 505 -508 489 -504 249 -242 241 -274 243 -242 241 -274 243 -242 495 -512 507 -482 509 -240 253 -69136 287 -254 249 -240 227 -252 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -516 477 -256 243 -496 509 -238 253 -514 243 -248 479 -260 249 -504 479 -258 243 -498 509 -514 475 -522 241 -254 255 -250 473 -260 249 -502 477 -510 255 -244 243 -246 497 -272 251 -474 509 -512 497 -486 483 -270 253 -254 255 -254 213 -506 481 -272 251 -69172 263 -226 285 -218 249 -250 249 -250 249 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -250 249 -248 249 -506 257 -246 245 -246 247 -248 503 -258 247 -244 245 -248 247 -248 247 -250 249 -250 247 -504 513 -228 243 -244 273 -244 245 -502 259 -246 499 -480 511 -274 255 -474 513 -240 239 -232 257 -506 513 -476 509 -478 505 -516 503 -472 279 -254 253 -252 239 -228 249 -248 247 -248 503 -514 477 -510 509 -238 253 -69168 273 -254 253 -220 253 -248 237 -256 249 -248 247 -250 247 +RAW_Data: -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 247 -250 249 -504 257 -248 245 -246 247 -248 501 -514 479 -272 255 -500 483 -234 263 -486 257 -248 501 -226 247 -528 479 -274 253 -474 511 -510 497 -482 259 -246 245 -244 501 -258 247 -498 477 -510 257 -242 243 -244 495 -272 251 -474 509 -512 497 -486 511 -226 245 -276 243 -246 245 -502 513 -240 251 -69164 295 -228 223 -252 249 -250 251 -250 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -506 257 -248 243 -246 247 -248 503 -258 245 -246 245 -248 247 -248 247 -250 249 -248 249 -504 513 -226 243 -246 275 -246 243 -502 257 -246 499 -478 509 -274 255 -474 479 -272 241 -266 223 -508 515 -478 509 -482 487 -520 481 -508 263 -228 253 -252 249 -250 249 -250 247 -250 503 -514 475 -508 507 -226 241 -69190 287 -218 249 -240 257 -250 247 -248 249 -248 247 -250 249 -250 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -514 477 -274 253 -474 511 -240 241 -500 259 -248 499 -258 245 -498 477 -274 253 -474 511 -512 495 -484 257 -246 245 -246 501 -258 245 -500 481 -512 253 -244 241 -244 495 -272 255 -474 517 -480 493 -516 511 -240 251 -256 253 -254 249 -470 515 -240 251 -69160 255 -244 243 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -506 257 -248 245 -246 247 -248 503 -258 215 -278 245 -246 247 -248 249 -248 249 -248 249 -506 481 -270 253 -254 253 -256 213 -506 257 -250 501 -482 513 -238 255 -514 477 -270 233 -262 223 -508 479 -514 509 -508 475 -520 475 -518 247 -248 243 -268 223 -250 249 -250 247 -250 505 -516 479 -514 475 -256 241 -69148 295 -226 223 -252 249 -250 249 -250 249 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -514 475 -256 243 -494 513 -238 289 -464 283 -210 505 -258 247 -498 513 -238 255 -474 509 -514 497 -484 257 -248 243 -246 499 -258 247 -498 509 -474 257 -242 243 -244 527 -238 251 -502 503 -490 515 -496 481 -258 245 -246 245 -246 247 -504 513 -238 253 -124420 65 -360 97 -98 129 -328 97 -426 99 -296 65 -232 231 -168 497 -232 163 -592 197 -392 131 -728 1593 -134 365 -66 97 -100 3173 -66 2309 -11768 163 -724 457 -100 197 +RAW_Data: -200 461 -66 165 -496 131 -134 99 -98 133 -98 97 -494 165 -230 97 -166 963 -266 3041 -15870 131 -98 231 -166 133 -68 199 -100 133 -132 633 -100 265 -198 65 -334 365 -198 131 -466 1129 -166 299 -234 3643 -16164 99 -364 231 -68 233 -598 133 -232 197 -100 133 -66 229 -66 297 -394 1219 -100 163 -166 3307 -7734 65 -4936 95 -1288 333 -232 233 -200 65 -364 333 -300 131 -100 165 -634 65 -564 131 -200 761 -232 563 -13840 133 -200 67 -464 65 -1318 231 -302 263 -100 199 -132 99 -166 99 -166 197 -328 163 -66 691 -262 497 -66 5665 -9958 99 -364 65 -1028 165 -398 265 -196 65 -132 561 -230 165 -66 461 -266 331 -364 131 -398 165 -166 595 -100 199 -102 729 -132 5765 -10908 65 -1388 129 -658 97 -98 295 -132 99 -132 131 -1152 265 -66 199 -98 731 -98 197 -66 751 -98 2631 -100 1691 -11754 263 -198 131 -132 133 -168 199 -132 99 -66 97 -1580 231 -100 4231 -14088 65 -1810 97 -690 65 -98 99 -164 397 -232 299 -2124 565 -64 267 -15924 99 -266 67 -132 565 -66 331 -266 165 -664 231 -1358 663 -264 297 -134 5749 -12972 197 -854 97 -1782 131 -100 63 -428 461 -66 891 -98 329 -64 1185 -15082 99 -468 97 -68 231 -396 165 -232 65 -134 65 -264 201 -430 231 -98 1097 -68 233 -132 5943 -12230 261 -756 99 -596 97 -132 97 -362 229 -198 163 -194 65 -64 395 -98 199 -100 133 -66 299 -11664 129 -658 97 -66 131 -98 263 -394 163 -132 129 -100 229 -1714 231 -166 99 -66 231 -132 599 -100 1127 -68 431 -100 1119 -14044 65 -1032 131 -826 99 -596 499 -266 199 -862 133 -1292 395 -100 921 -198 331 -132 363 -15244 97 -624 231 -134 163 -500 131 -530 201 -134 133 -132 67 -464 131 -998 965 -66 365 -100 3769 -9910 65 -6926 265 -264 133 -166 131 -166 233 -130 99 -132 65 -396 195 -196 65 -98 97 -98 557 -98 165 -66 397 -66 7539 -8488 199 -332 65 -200 199 -1458 65 -466 99 -66 65 -698 297 -68 361 -132 531 -134 165 -68 6531 -11410 65 -896 99 -264 67 -132 197 -98 165 -532 99 -100 165 -562 99 -100 297 -728 983 -98 131 -98 229 -230 63 -262 4137 -16250 427 -298 329 -430 99 -360 131 -724 131 -264 97 -796 825 -166 265 -134 3663 -14070 97 -1750 197 -68 163 -132 229 -530 165 -428 65 -132 65 -98 65 -1684 229 -100 229 -66 97 -330 131 -134 231 -100 3781 -8504 65 -7400 67 -164 131 -66 495 -164 133 -166 131 -202 65 -102 165 -568 65 -134 65 -498 229 -132 129 -394 197 -98 295 -66 427 -66 397 -68 2533 +RAW_Data: -16126 133 -268 131 -200 63 -196 229 -394 295 -758 131 -358 65 -164 263 -594 427 -66 131 -66 393 -5360 199 -132 165 -526 65 -230 165 -262 65 -66 97 -296 131 -556 65 -792 131 -402 331 -132 97 -168 429 -100 365 -66 401 -4724 65 -1924 99 -300 65 -1066 65 -266 65 -332 165 -366 65 -332 131 -166 233 -166 499 -264 65 -300 67 -132 99 -132 65 -432 397 -164 657 -64 263 -66 555 -66 2729 -10288 65 -5204 97 -100 591 -166 99 -496 97 -100 65 -98 99 -296 97 -428 265 -100 229 -164 263 -100 765 -100 263 -66 3453 -7586 133 -7046 99 -962 131 -98 131 -134 565 -66 131 -134 593 -66 131 -1384 97 -330 131 -402 5065 -15884 65 -664 297 -266 167 -134 101 -134 99 -596 165 -496 99 -564 2351 -66 6223 -11750 65 -330 365 -68 99 -132 99 -634 131 -860 163 -130 65 -1226 197 -98 861 -134 495 -266 2219 -11598 65 -1316 99 -758 229 -2510 131 -100 167 -68 303 -100 499 -164 131 -100 397 -7704 65 -7902 299 -100 131 -100 199 -166 531 -66 133 -298 199 -398 131 -100 65 -166 133 -66 199 -100 635 -132 599 -66 199 -134 361 -66 3253 -226 425 -15180 133 -568 297 -132 199 -132 793 -330 65 -526 97 -132 425 -526 331 -68 303 -548 297 -230 225 -254 249 -250 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -506 257 -248 245 -246 245 -248 503 -260 245 -246 243 -248 247 -502 515 -238 253 -472 277 -242 499 -508 481 -504 489 -516 477 -274 253 -256 253 -460 495 -260 249 -248 247 -250 247 -504 257 -248 245 -246 501 -512 475 -508 255 -242 243 -242 245 -274 499 -478 257 -244 243 -244 529 -476 509 -274 253 -218 255 -68836 285 -252 243 -228 249 -248 245 -248 247 -250 247 -250 249 -248 249 -248 249 -250 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 249 -504 259 -248 243 -246 247 -248 503 -514 475 -256 243 -494 509 -274 253 -218 255 -254 247 -496 257 -246 497 -226 275 -496 511 -474 507 -480 255 -242 273 -242 495 -274 253 -464 523 -498 225 -250 503 -258 245 -244 245 -502 511 -476 509 -510 473 -508 521 -488 249 -252 481 -516 225 -256 289 -68864 259 -224 249 -252 251 -250 251 -250 249 -248 249 -250 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 249 -248 249 -250 247 -504 257 -248 245 -246 247 -248 503 -258 245 -246 245 -248 247 -504 513 -240 251 -474 247 -272 499 -508 483 -506 489 -516 477 -274 253 -256 217 -496 491 -260 247 +RAW_Data: -248 249 -248 247 -504 257 -248 245 -246 501 -512 477 -512 253 -244 241 -244 243 -246 529 -478 257 -242 243 -244 529 -478 509 -238 253 -254 255 -69126 287 -254 251 -240 227 -252 247 -248 247 -250 247 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 249 -504 257 -248 245 -246 245 -248 503 -516 479 -272 255 -476 511 -238 241 -268 223 -252 249 -504 257 -248 499 -228 243 -530 477 -512 505 -474 255 -242 243 -274 495 -274 255 -474 485 -506 261 -222 507 -260 247 -246 245 -502 511 -478 509 -480 507 -488 499 -510 277 -246 471 -516 225 -256 253 -68936 271 -238 231 -256 249 -248 249 -248 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -260 245 -246 245 -246 247 -504 513 -238 251 -504 249 -254 489 -488 513 -476 509 -512 475 -274 255 -254 253 -488 483 -258 215 -276 245 -246 245 -504 255 -248 245 -246 503 -514 477 -512 225 -242 273 -242 243 -244 529 -476 255 -244 243 -244 529 -478 509 -238 253 -254 255 -69140 307 -220 253 -254 253 -246 231 -256 247 -248 247 -250 247 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -506 257 -248 245 -246 245 -248 503 -514 477 -272 255 -474 515 -242 239 -268 223 -252 247 -504 259 -246 501 -226 245 -530 479 -512 509 -482 253 -242 241 -244 529 -238 253 -498 481 -528 225 -250 503 -260 245 -244 245 -502 511 -478 509 -482 505 -506 505 -486 249 -252 487 -516 227 -256 251 -68924 311 -210 233 -258 247 -250 247 -250 247 -248 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -250 247 -250 249 -248 249 -250 249 -506 257 -248 245 -244 247 -246 505 -258 247 -244 245 -246 247 -504 515 -238 253 -472 281 -254 487 -486 513 -478 509 -512 475 -274 253 -256 253 -488 483 -228 255 -290 217 -254 255 -494 229 -254 249 -250 505 -514 477 -512 255 -242 243 -242 243 -244 529 -478 257 -242 243 -244 529 -480 513 -240 253 -254 255 -69136 321 -218 253 -246 229 -254 247 -246 247 -248 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -514 479 -272 255 -474 511 -240 241 -270 225 -252 247 -504 259 -246 499 -228 273 -498 511 -476 509 -480 253 -242 273 -242 491 -256 241 -494 507 -504 255 -242 491 -256 243 -242 243 -526 475 -506 505 -506 473 -504 505 +RAW_Data: -504 251 -242 495 -490 249 -242 271 -68916 273 -238 229 -256 249 -248 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -250 247 -506 257 -248 245 -246 245 -248 503 -258 245 -246 247 -246 247 -504 481 -258 243 -528 225 -244 495 -512 509 -482 507 -504 475 -276 255 -254 249 -474 515 -238 251 -254 255 -254 249 -474 257 -250 245 -248 501 -514 479 -512 225 -242 273 -244 243 -246 495 -508 255 -244 243 -246 497 -512 483 -272 255 -254 253 -69136 283 -254 241 -230 251 -248 245 -248 249 -248 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -250 247 -504 259 -246 245 -246 247 -248 503 -514 477 -274 253 -500 483 -232 265 -228 253 -250 249 -506 259 -248 499 -226 245 -528 477 -508 509 -484 253 -244 241 -244 497 -272 255 -496 479 -528 225 -252 505 -260 215 -276 245 -500 479 -510 509 -482 507 -510 491 -508 245 -246 479 -518 227 -292 215 -68942 321 -218 233 -274 235 -260 223 -250 249 -250 249 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -506 225 -280 213 -278 245 -248 503 -260 215 -276 215 -278 245 -504 479 -258 245 -496 257 -246 497 -514 475 -508 507 -508 461 -280 251 -252 241 -496 481 -272 251 -256 253 -254 249 -470 259 -248 245 -248 499 -512 475 -510 237 -256 253 -256 251 -244 493 -514 223 -244 245 -276 497 -480 509 -256 243 -244 243 -68750 131 -586 287 -220 253 -246 233 -254 249 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -250 247 -250 249 -504 259 -248 243 -248 245 -248 501 -514 477 -274 253 -474 513 -240 241 -268 227 -250 249 -504 257 -248 499 -226 245 -530 477 -510 507 -482 255 -242 241 -244 523 -256 241 -494 505 -474 257 -242 525 -224 273 -242 243 -494 507 -508 481 -506 505 -504 471 -506 249 -242 527 -472 251 -242 271 -119988 65 -164 163 -1380 229 -262 65 -1322 65 -564 99 -860 65 -566 501 -66 499 -164 395 -132 199 -100 895 -11996 131 -166 295 -132 165 -234 65 -164 231 -102 199 -134 97 -498 199 -164 265 -66 197 -132 65 -100 99 -664 1297 -98 8085 -7700 99 -634 365 -134 363 -954 99 -2236 261 -66 789 -98 425 -100 459 -12258 99 -198 267 -100 99 -102 97 -200 133 -300 67 -166 163 -464 133 -66 99 -828 927 -132 331 -166 9065 -7016 67 -98 67 -1290 131 -396 165 -134 131 -1026 97 -1118 65 -1048 919 -134 699 +RAW_Data: -100 3443 -13736 133 -1852 65 -232 363 -202 431 -100 133 -98 265 -166 197 -66 299 -526 131 -100 163 -832 727 -168 131 -200 65 -132 197 -102 331 -16028 99 -132 99 -198 99 -68 133 -364 163 -432 197 -464 131 -100 133 -298 97 -466 165 -200 133 -396 331 -66 823 -66 7065 -12144 97 -428 359 -164 65 -100 593 -198 163 -164 131 -132 99 -98 131 -1448 1193 -100 365 -132 10335 -1482 65 -364 63 -1844 97 -134 231 -630 131 -200 265 -232 65 -166 65 -368 197 -1126 297 -132 131 -66 1259 -134 129 -66 99 -66 8323 -6196 263 -298 97 -164 97 -492 231 -794 131 -166 67 -428 65 -954 755 -98 261 -66 261 -230 131 -230 1425 -11490 167 -562 197 -364 63 -428 65 -228 463 -166 65 -19728 165 -134 363 -100 131 -168 197 -198 101 -826 99 -1678 99 -66 561 -98 161 -66 229 -230 163 -398 265 -166 699 -9874 67 -2192 165 -200 67 -1096 131 -2282 227 -332 231 -98 165 -68 165 -364 3503 -7996 65 -430 99 -662 231 -266 165 -66 133 -134 199 -164 99 -168 65 -398 65 -730 231 -100 297 -198 67 -132 863 -134 231 -102 267 -68 871 -68 765 -66 823 -9234 99 -4694 231 -134 197 -166 99 -368 363 -100 233 -694 231 -400 65 -464 131 -234 99 -230 65 -400 297 -66 8683 -7160 233 -1030 129 -298 263 -100 299 -264 165 -100 229 -792 65 -164 131 -294 65 -264 459 -426 525 -132 229 -298 5509 -9856 131 -100 263 -232 163 -266 531 -232 99 -398 65 -332 165 -534 131 -68 293 -596 887 -232 4775 -16286 197 -364 65 -132 99 -98 163 -1350 131 -100 167 -398 99 -432 533 -100 929 -66 65 -228 3861 -3258 99 -434 65 -232 99 -332 133 -860 265 -66 233 -166 131 -100 197 -100 99 -66 99 -530 65 -564 65 -132 165 -232 265 -200 199 -100 165 -100 67 -98 531 -132 427 -10628 165 -232 199 -132 131 -366 199 -464 65 -2290 399 -198 333 -168 597 -166 533 -66 2453 -66 4151 -7656 99 -1062 131 -232 133 -98 131 -68 163 -198 133 -334 67 -596 923 -132 161 -98 327 -362 4939 -12358 195 -230 131 -528 65 -1744 65 -360 97 -396 63 -166 1047 -198 65 -196 231 -130 97 -12510 131 -198 99 -668 97 -166 199 -1224 99 -1128 65 -98 429 -132 365 -198 765 -132 1227 -9838 65 -5956 295 -266 297 -430 229 -1286 65 -392 197 -988 163 -132 625 -100 165 -66 525 -66 4229 -16222 129 -132 295 -66 163 -132 97 -66 97 -692 97 -462 65 -1026 265 -132 827 -166 163 -166 167 -234 6731 -12228 233 -166 99 -200 131 -632 133 -332 65 -498 263 -100 229 -262 463 -100 199 -100 733 +RAW_Data: -100 3989 -11100 131 -894 131 -464 65 -332 99 -132 133 -132 101 -236 99 -1328 165 -100 133 -198 1027 -360 3341 -9980 133 -1858 65 -166 133 -166 67 -134 395 -166 99 -930 97 -100 199 -234 99 -428 99 -164 1051 -66 657 -100 9339 -3804 197 -624 65 -2224 131 -900 529 -264 197 -296 231 -98 727 -132 199 -100 265 -66 99 -68 6671 -12588 165 -132 165 -132 233 -928 165 -934 99 -200 1557 -100 331 -166 7333 -8240 295 -164 263 -98 97 -132 97 -198 261 -230 197 -298 229 -692 197 -662 661 -200 231 -66 197 -15936 199 -960 65 -234 165 -466 231 -2022 431 -98 801 -232 463 -66 229 -164 3261 -8456 67 -5980 65 -1990 133 -364 97 -400 65 -132 99 -134 99 -132 99 -1292 429 -166 265 -68 3517 -8746 65 -862 165 -332 267 -198 67 -200 65 -166 299 -100 165 -2022 465 -430 165 -134 301 -136 297 -66 3287 -100 951 -132 3825 -8094 197 -132 129 -364 129 -66 163 -164 295 -428 131 -392 99 -394 459 -396 463 -164 4081 -10550 99 -266 67 -2688 203 -582 261 -260 223 -252 249 -250 249 -250 249 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -260 245 -246 245 -246 247 -504 511 -226 243 -528 225 -244 529 -238 253 -472 517 -244 279 -238 227 -252 247 -250 247 -504 513 -226 243 -528 477 -274 253 -256 217 -254 247 -500 259 -246 499 -226 245 -274 245 -246 245 -502 513 -476 255 -244 495 -274 253 -254 255 -218 247 -502 513 -476 257 -68588 311 -208 233 -256 249 -248 249 -248 247 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -514 477 -272 255 -254 217 -498 263 -226 509 -514 475 -274 253 -256 253 -460 525 -482 513 -478 507 -506 223 -244 271 -244 495 -274 253 -476 243 -252 247 -238 259 -248 503 -260 245 -246 245 -246 247 -248 249 -504 257 -248 245 -246 501 -514 479 -274 253 -218 255 -254 247 -234 255 -69132 319 -220 243 -232 251 -248 247 -248 247 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -258 247 -246 245 -246 247 -504 515 -238 251 -474 279 -254 489 -228 253 -506 513 -238 251 -256 253 -254 251 -240 227 -510 479 -258 243 -528 475 -274 253 -256 217 -254 247 -500 257 -248 499 -226 245 -276 243 -246 245 -502 513 -478 257 -242 495 -274 253 -256 217 -254 247 -500 513 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 77e81f23..9d1cdd67 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -63,3 +63,40 @@ RAW_Data: 231 -196 1265 -100 133 -68 933 -100 7293 -66 331 -132 295 -68 1157 -98 RAW_Data: 823 -420 417 -848 797 -472 381 -876 791 -428 413 -844 817 -426 379 -878 385 -848 403 -852 807 -452 379 -878 801 -452 801 -438 385 -838 419 -846 399 -852 379 -850 315 -110416 645 -1548 1691 -486 1667 -518 1695 -488 1671 -498 1697 -508 571 -1588 583 -1570 561 -1574 1689 -504 583 -1560 1679 -520 587 -1574 1677 -488 1701 -484 1697 -520 1677 -492 1693 -488 581 -1566 591 -1574 601 -1546 607 -1568 577 -1566 581 -1576 579 -16394 591 -1548 1679 -518 1671 -520 1679 -516 1663 -514 1689 -486 583 -1580 579 -1578 579 -1566 1701 -494 571 -1568 1697 -514 563 -1570 1693 -506 1669 -516 1695 -496 1681 -518 1667 -506 573 -1576 603 -1544 613 -1568 597 -1538 607 -1566 581 -1580 577 -16400 619 -1534 1703 -494 1677 -480 1697 -506 1675 -518 1669 -518 587 -1580 581 -1562 579 -1576 1683 -488 589 -1582 1677 -524 583 -1570 1653 -510 1703 -518 1641 -518 1693 -502 1677 -516 579 -1570 579 -1578 581 -1566 615 -1566 585 -1564 585 -1580 585 -16408 595 -1546 1685 -518 1673 -490 1669 -548 1665 -518 1675 -494 587 -1552 595 -1570 605 -1556 1673 -520 581 -1578 1665 -520 581 -1558 1701 -484 1681 -516 1667 -516 1697 -508 1675 -490 603 -1570 577 -1566 593 -1572 603 -1576 575 -1568 579 -1578 579 -16400 625 -1554 1667 -500 1699 -482 1691 -506 1679 -518 1673 -520 585 -1566 579 -1560 611 -1548 1697 -488 577 -1602 1651 -518 583 -1578 1667 -508 1691 -522 1675 -512 1665 -502 1699 -482 605 -1574 585 -1566 601 -1570 577 -1576 581 -1576 579 -1566 579 -16452 591 -1534 1693 -508 1683 -518 1673 -520 1673 -488 1711 -514 575 -1562 589 -1570 603 -1568 1667 -518 589 -1578 1677 -486 605 -1570 1701 -484 1701 -504 1697 -514 1667 -510 1717 -518 581 -1578 615 -91426 233 -298 197 -332 593 -162 261 -98 131 -68 163 -692 821 -132 227 -64 131 -66 197 -132 163 -66 263 -68 363 -134 461 -98 65 -66 229 -298 295 -66 3173 -64 987 -164 425 -98 193 -98 693 -66 723 -196 391 -496 431 -100 229 -68 499 -100 63 -66 165 -66 397 -98 133 -100 533 -166 1179 -166 361 -100 3973 -98 825 -100 131 -98 723 -66 1053 -66 131 -68 197 -100 199 -100 331 -66 165 -100 429 -68 231 -66 567 -66 533 -100 593 -68 1463 -66 2093 -100 599 -66 361 -66 361 -132 261 -462 263 -66 621 -98 555 -100 131 -68 4609 -200 199 -164 1033 -66 863 -132 131 -68 331 -100 4565 -98 229 -66 1313 -130 589 -166 3959 -100 531 -100 263 -132 361 -166 229 -64 165 -66 231 -328 261 -66 229 -66 165 -100 235 -100 299 -132 265 -266 165 -66 4417 -100 261 -68 1625 -64 165 -98 229 -160 259 -98 99 -332 593 -166 167 -102 RAW_Data: 199 -66 1063 -98 267 -100 263 -332 5513 -64 229 -232 685 -232 661 -98 431 -66 1021 -66 4085 -64 655 -66 2313 -66 531 -66 263 -100 197 -134 67 -132 901 -66 1591 -66 4217 -100 827 -100 165 -66 299 -166 1987 -166 4097 -66 365 -66 131 -332 131 -100 625 -66 361 -98 131 -196 1679 -66 163 -98 293 -100 2275 -98 1689 -66 825 -98 627 -164 297 -398 461 -66 4707 -66 795 -134 329 -132 597 -66 777 -6038 371 -1818 167 -668 693 -622 1573 -638 465 -1666 503 -1626 541 -1622 1635 -518 577 -1578 1669 -512 567 -1606 1667 -502 1677 -516 1693 -500 1673 -518 1675 -522 587 -1562 581 -1558 625 -1546 587 -1558 611 -1560 571 -1568 609 -16352 633 -1548 1689 -476 1707 -490 1687 -482 1709 -502 1675 -520 579 -1578 577 -1568 577 -1568 1705 -486 581 -1586 1695 -486 579 -1568 1679 -520 1673 -520 1669 -508 1707 -498 1677 -514 577 -1566 615 -1550 581 -1568 615 -1532 617 -1546 617 -1532 615 -16406 599 -1530 1691 -514 1695 -484 1679 -530 1659 -518 1669 -514 601 -1568 577 -1578 577 -1568 1699 -492 573 -1576 1707 -486 577 -1600 1655 -518 1669 -530 1691 -486 1673 -514 1691 -502 585 -1576 585 -1580 577 -1592 573 -1576 571 -1570 613 -1570 559 -16430 619 -1538 1703 -462 1723 -484 1697 -488 1691 -488 1715 -462 635 -1534 607 -1556 589 -1580 1685 -488 621 -1538 1711 -492 589 -1548 1717 -478 1693 -514 1687 -504 1693 -484 1705 -482 605 -1570 579 -1566 619 -1550 581 -1580 579 -1568 615 -1536 619 -16382 625 -1534 1709 -490 1683 -514 1673 -504 1677 -518 1671 -518 587 -1560 577 -1588 587 -1580 1681 -482 609 -1558 1677 -520 581 -1576 1663 -530 1659 -518 1673 -514 1691 -504 1697 -510 587 -1572 575 -1564 591 -1570 603 -1574 577 -1568 579 -1578 579 -16430 599 -1564 1693 -484 1695 -486 1675 -500 1713 -484 1709 -488 579 -1568 593 -1576 603 -1570 1665 -520 581 -1560 1699 -482 603 -1580 1677 -518 1667 -520 1671 -488 1711 -482 1699 -516 599 -1570 577 -1578 577 -1568 579 -1570 617 -1566 581 -1560 587 -16424 629 -1542 1677 -482 1695 -514 1687 -484 1711 -494 1675 -514 571 -1584 587 -1572 599 -1542 1695 -520 585 -1544 1701 -510 593 -1568 1665 -514 1689 -506 1669 -508 1679 -528 1669 -520 579 -1576 579 -1568 581 -1582 581 -1578 579 -1568 615 -1564 585 -16412 631 -1540 1683 -516 1671 -510 1653 -506 1691 -518 1671 -514 601 -1570 577 -1578 577 -1578 1665 -498 603 -1566 1693 -514 563 -1576 1699 -506 1663 -514 1701 -478 1687 -520 1669 -500 603 -1568 605 -1558 589 -1574 601 -1542 607 -1576 577 -1576 577 -16434 597 -1534 1695 -516 1687 -488 1707 -486 1683 -518 1693 -496 583 -1574 599 -1542 605 -1578 1665 -500 611 -1550 1711 -478 605 -1558 RAW_Data: 1679 -518 1675 -502 1699 -482 1693 -506 1679 -510 613 -1562 581 -1590 569 -1570 605 -1560 587 -1572 599 -1542 607 -16400 625 -1560 1669 -508 1677 -518 1667 -518 1695 -486 1709 -464 601 -1566 607 -1560 589 -1576 1691 -476 615 -1562 1677 -486 625 -1542 1709 -486 1703 -484 1697 -520 1673 -506 1695 -498 585 -1570 603 -1544 609 -1572 579 -1570 583 -1580 581 -1582 579 -16410 629 -1524 1715 -484 1679 -518 1673 -516 1663 -518 1697 -504 583 -1576 577 -1592 587 -1552 1681 -514 579 -1580 1681 -516 577 -1566 1705 -494 1689 -488 1705 -486 1695 -520 1675 -522 587 -1574 579 -1584 581 -1576 599 -1570 575 -1578 579 -1564 613 -89724 99 -1166 129 -1158 167 -532 163 -98 361 -198 299 -298 197 -66 2489 -66 3797 -66 1937 -66 1479 -98 557 -66 361 -66 1709 -66 6741 -98 1889 -132 5693 -68 7367 -100 8643 -100 2655 -100 3727 -66 1023 -66 865 -66 1161 -100 6287 -66 3987 -66 1961 -132 3307 -68 2183 -66 2429 -132 4179 -66 753 -66 461 -66 621 -64 5761 -100 331 -66 1683 -198 465 -66 629 -68 7341 -66 357 -198 261 -66 593 -234 331 -100 593 -64 293 -64 1611 -100 459 -100 297 -100 561 -134 1725 -66 6901 -100 1407 -68 8017 -200 1989 -66 5721 -100 199 -166 1251 -66 359 -130 9965 -66 4361 -100 819 -100 1051 -66 2187 -64 555 -66 861 -66 5889 -66 +RAW_Data: 361 -4326 2555 -28090 65 -302 65 -1890 131 -2062 2547 -95068 2565 -48020 67 -47036 2551 -30016 2561 -47778 67 -14884 2481 -95118 2537 -95132 2549 -48496 65 -21526 2571 -16342 97 -4142 65 -1938 2543 -95008 2551 -44030 1579 -548 1469 -588 433 -1568 469 -1540 479 -1550 1489 -538 473 -1574 1467 -538 1493 -566 443 -22130 693 -3742 321 -1702 341 -1690 1353 -628 391 -1666 1401 -584 1445 -596 391 -22192 1487 -554 1471 -550 447 -1584 453 -1568 445 -1578 1469 -550 459 -1598 1465 -540 1461 -576 445 -22164 1479 -546 1501 -544 453 -1568 447 -1580 445 -1584 1451 -560 443 -1594 1473 -548 1479 -556 441 -22160 1475 -548 1487 -554 449 -1578 451 -1586 451 -1572 1469 -552 449 -1578 1473 -558 1469 -552 449 -22142 1507 -546 1479 -548 457 -1574 447 -1580 447 -1584 1475 -554 441 -1592 1465 -546 1473 -546 483 -22132 1157 -1082 67 -166 65 -198 65 -1150 257 -1706 339 -1666 365 -1642 1409 -610 407 -1626 1417 -620 1435 -580 409 -22184 1495 -572 1463 -552 447 -1584 453 -1574 447 -1580 1473 -548 459 -1568 1501 -520 1501 -552 463 -22124 535 -7674 339 -1680 1345 -678 361 -1664 1395 -618 1411 -646 373 -22194 1511 -526 1477 -550 483 -1542 479 -1562 471 -1566 1483 -546 445 -1574 1471 -534 1497 -548 483 -169938 2539 -89172 167 -5768 2551 -93014 967 -252 1571 -5844 2503 -87590 65 -5948 2523 -64008 1605 -520 1473 -554 449 -1584 449 -1576 447 -1546 1505 -546 451 -1574 1469 -546 1475 -548 459 -22160 1525 -506 1501 -516 479 -1550 469 -1570 469 -1570 1471 -538 471 -1568 1489 -516 1501 -554 443 -22152 1507 -522 1511 -518 481 -1580 451 -1542 483 -1548 1505 -546 451 -1570 1471 -552 1473 -548 455 -22180 1505 -522 1501 -544 451 -1560 475 -1548 481 -1556 1477 -552 475 -1546 1505 -516 1517 -516 473 -22148 1515 -518 1499 -546 485 -1570 443 -1580 447 -1582 1475 -526 483 -1548 1507 -546 1479 -558 449 -22138 1495 -586 1437 -616 403 -1594 429 -1608 417 -1606 1465 -556 433 -1606 1465 -536 1499 -544 445 -22170 1401 -792 1245 -770 271 -1716 325 -1680 359 -1664 1397 -620 393 -1644 1407 -614 1433 -586 429 -22202 1477 -572 1469 -548 449 -1576 457 -1578 479 -1544 1473 -590 429 -1570 1491 -540 1509 -554 429 -22196 1481 -556 1467 -580 439 -1592 431 -1608 415 -1608 1441 -586 463 -1568 1467 -552 1489 -534 473 -22166 1485 -574 1469 -580 453 -1572 443 -1578 447 -1578 1477 -554 447 -1580 1479 -550 1481 -550 475 -22160 1525 -542 1467 -540 483 -1574 447 -1582 451 -1578 1481 -558 447 -1560 1493 -550 1505 -544 449 -22182 1435 -646 1391 -664 369 -1642 385 -1652 395 -1600 1463 -584 417 -1606 1467 -576 1443 -586 429 -148588 275 -106 847 -128 877 -100 281 -97826 2541 -92318 2505 -12474 2563 -73674 2555 -41600 2543 -76554 1601 -516 1471 -554 +RAW_Data: 487 -1556 453 -1570 441 -1590 1467 -556 469 -1538 1501 -522 1501 -552 463 -22124 1513 -514 1509 -548 445 -1582 461 -1568 443 -1574 1467 -536 465 -1574 1499 -516 1503 -556 441 -22150 1537 -484 1495 -544 479 -1558 459 -1574 447 -1580 1471 -548 459 -1576 1471 -554 1471 -550 459 -22160 1517 -516 1503 -546 447 -1574 473 -1546 481 -1576 1479 -520 467 -1572 1497 -550 1469 -556 441 -22156 1533 -528 1495 -530 469 -1568 445 -1566 485 -1548 1505 -544 451 -1572 1471 -554 1503 -516 495 -22160 1511 -520 1477 -546 483 -1542 485 -1546 481 -1542 1509 -526 455 -1578 1507 -544 1481 -524 485 -22146 1543 -510 1481 -552 475 -1546 473 -1568 481 -1540 1503 -522 473 -1556 1507 -558 1491 -518 479 -22164 1523 -520 1503 -544 453 -1566 479 -1550 469 -1572 1493 -546 447 -1576 1477 -552 1509 -544 451 -22178 639 -596 65 -926 63 -1954 237 -1680 355 -1670 383 -1636 1423 -596 439 -1578 1471 -574 1465 -576 445 -22182 1439 -676 1335 -702 339 -1648 387 -1648 409 -1608 1429 -618 419 -1612 1447 -578 1439 -614 425 -22186 1497 -530 1505 -556 471 -1540 479 -1582 431 -1570 1497 -546 481 -1536 1497 -554 1501 -556 463 -22178 1503 -566 1433 -586 433 -1604 445 -1576 441 -1580 1503 -548 453 -1572 1473 -578 1467 -558 469 -149080 311 -1034 895 -1084 939 -1006 337 -78790 97 -6890 2535 -28048 2511 -64482 2573 -88138 65 -6956 2515 -95140 2509 -61986 1589 -522 1475 -548 449 -1576 475 -1548 481 -1546 1475 -564 443 -1564 1477 -580 1477 -554 449 -22166 1503 -532 1481 -544 447 -1576 449 -1572 473 -1548 1473 -580 451 -1568 1463 -552 1477 -552 461 -22164 1521 -528 1493 -548 443 -1580 461 -1540 475 -1574 1473 -554 471 -1568 1489 -516 1497 -538 471 -22154 1385 -786 1245 -796 261 -1702 341 -1650 391 -1644 1411 -608 409 -1620 1415 -624 1409 -614 413 -22178 1533 -498 1519 -546 445 -1576 449 -1578 457 -1568 1503 -546 451 -1570 1467 -554 1503 -552 463 -22162 1401 -774 1257 -754 297 -1678 353 -1650 383 -1666 1397 -618 385 -1642 1437 -612 1433 -586 427 -22194 1483 -552 1477 -546 485 -1544 453 -1576 481 -1576 1479 -560 449 -1548 1507 -546 1479 -558 447 -22170 1413 -786 1245 -776 295 -1664 337 -1680 387 -1652 1385 -638 407 -1614 1441 -582 1451 -606 409 -22204 1503 -528 1507 -550 465 -1534 481 -1584 429 -1572 1497 -548 447 -1580 1481 -550 1503 -546 455 -22166 1519 -552 1469 -580 419 -1612 419 -1596 447 -1582 1479 -554 447 -1582 1479 -550 1519 -518 479 -134730 169 -172 559 -194 579 -676 257 -87040 99 -7384 2269 -488 313 -37888 65 -12084 2515 -33298 2247 -474 309 -42656 63 -51970 2233 -456 309 -94658 2233 -430 325 -90692 357 -186 2417 -518 1517 -514 475 -1550 467 -1570 471 -1538 1499 -556 443 -1564 1483 -552 1501 -524 +RAW_Data: 481 -22144 1433 -668 1373 -666 337 -1680 355 -1634 383 -1634 1431 -622 399 -1606 1443 -582 1443 -586 431 -22166 1521 -512 1497 -548 447 -1580 459 -1568 447 -1574 1473 -554 465 -1572 1497 -516 1507 -554 453 -22148 1503 -540 1489 -546 479 -1542 449 -1578 457 -1576 1475 -546 483 -1540 1507 -552 1473 -548 453 -22154 1539 -516 1469 -586 431 -1574 447 -1576 479 -1558 1485 -554 439 -1580 1501 -550 1457 -552 473 -22154 1521 -550 1485 -540 447 -1578 457 -1578 447 -1572 1471 -556 485 -1540 1483 -552 1501 -556 443 -22186 1437 -662 1345 -704 339 -1688 361 -1646 375 -1640 1399 -616 421 -1612 1441 -614 1435 -586 429 -22200 1513 -520 1503 -544 453 -1572 447 -1580 483 -1550 1475 -552 475 -1548 1501 -554 1491 -540 475 -22184 1499 -530 1485 -548 457 -1570 477 -1578 443 -1576 1501 -546 449 -1562 1499 -538 1493 -572 443 -22166 1471 -612 1429 -624 401 -1608 417 -1620 431 -1600 1461 -582 419 -1610 1441 -582 1473 -548 459 -205658 1761 -436 863 -68558 2597 -23434 1775 -438 519 -94592 1803 -422 829 -86706 1727 -434 527 -66 319 -94536 1753 -444 865 -238 1489 -652 1385 -656 357 -1668 365 -1628 403 -1612 1439 -614 403 -1626 1425 -588 1443 -584 409 -22168 1531 -528 1491 -530 469 -1568 443 -1564 483 -1538 1505 -546 455 -1570 1469 -556 1503 -518 491 -22128 1455 -660 1359 -686 355 -1632 385 -1632 411 -1640 1411 -596 423 -1606 1437 -580 1443 -596 423 -22188 1495 -550 1467 -534 473 -1566 481 -1540 483 -1572 1477 -552 449 -1582 1477 -558 1471 -552 449 -22174 543 -3692 235 -1680 357 -1668 353 -1698 1375 -636 371 -1644 1409 -610 1437 -578 449 -22180 1499 -542 1491 -542 479 -1540 481 -1566 449 -1562 1499 -554 465 -1568 1463 -554 1493 -536 473 -22168 1405 -774 1257 -788 267 -1676 355 -1672 369 -1660 1387 -624 417 -1606 1427 -624 1425 -586 415 -22208 1507 -552 1489 -548 443 -1562 483 -1550 481 -1546 1505 -558 447 -1586 1473 -548 1481 -554 479 -22166 1383 -786 1245 -776 295 -1664 373 -1646 387 -1644 1403 -642 411 -1624 1417 -594 1445 -612 409 -22210 1515 -516 1503 -554 453 -1564 457 -1572 447 -1580 1501 -554 465 -1570 1467 -554 1493 -570 443 -195814 1353 -442 1267 -37900 99 -53710 411 -142 2207 -8336 2487 -46990 1301 -452 1317 -86162 65 -8376 1289 -444 1327 -94552 1311 -488 1251 -1726 1531 -544 1467 -580 417 -1578 457 -1578 443 -1576 1475 -566 441 -1568 1503 -512 1509 -526 455 -22168 1473 -582 1469 -538 483 -1538 459 -1574 447 -1580 1471 -582 429 -1572 1469 -552 1473 -548 461 -22170 1437 -640 1401 -620 393 -1636 385 -1634 409 -1604 1457 -588 415 -1608 1431 -590 1459 -554 449 -22188 1483 -556 1487 -542 445 -1578 459 -1576 443 -1574 1473 -556 469 -1570 1459 -550 1503 -554 443 -22160 1469 -590 +RAW_Data: 1469 -582 409 -1620 429 -1608 415 -1602 1455 -568 441 -1578 1475 -552 1479 -560 467 -22166 1483 -572 1463 -546 451 -1580 453 -1580 481 -1542 1475 -588 451 -1570 1453 -550 1503 -540 469 -22158 1505 -554 1475 -554 487 -1556 453 -1562 477 -1546 1495 -546 479 -1544 1511 -554 1477 -532 471 -22180 1471 -602 1437 -602 407 -1610 421 -1614 421 -1606 1433 -582 457 -1578 1475 -550 1469 -586 465 -22164 1515 -546 1469 -546 483 -1572 447 -1558 471 -1580 1471 -578 451 -1568 1495 -542 1497 -530 471 -22194 1433 -644 1393 -662 371 -1640 385 -1642 413 -1628 1431 -584 431 -1602 1469 -540 1501 -576 443 -22180 1479 -592 1439 -608 407 -1620 427 -1610 415 -1606 1465 -570 441 -1612 1441 -586 1451 -576 445 -22196 1533 -522 1489 -540 477 -1574 481 -1544 455 -1568 1505 -546 459 -1572 1501 -556 1497 -530 471 -210202 685 -540 475 -138 839 -138 239 -9950 2501 -71112 761 -462 511 -66 1297 -85614 97 -8850 745 -466 1821 -94546 827 -468 481 -140 815 -164 237 -32934 1583 -540 1477 -554 441 -1582 447 -1580 453 -1568 1465 -554 479 -1556 1487 -558 1477 -550 453 -22174 1503 -516 1483 -584 429 -1572 449 -1576 447 -1588 1475 -558 449 -1580 1473 -546 1485 -556 449 -22168 1469 -586 1443 -614 401 -1624 401 -1608 415 -1608 1463 -570 441 -1574 1471 -586 1449 -572 445 -22164 1401 -772 1255 -756 301 -1674 353 -1708 329 -1662 1397 -650 387 -1632 1405 -614 1433 -584 431 -22200 1489 -566 1463 -582 419 -1580 457 -1596 447 -1576 1473 -554 443 -1580 1469 -582 1451 -550 479 -22174 1387 -786 1251 -792 257 -1704 331 -1690 337 -1706 1377 -632 395 -1632 1433 -586 1451 -584 413 -22198 1541 -512 1485 -554 481 -1574 445 -1560 461 -1568 1495 -556 469 -1568 1495 -518 1503 -554 469 -22160 1541 -516 1501 -556 443 -1564 495 -1536 479 -1550 1517 -544 445 -1576 1507 -556 1485 -542 445 -22202 1501 -530 1503 -554 465 -1574 445 -1582 461 -1574 1469 -546 479 -1568 1471 -556 1513 -550 463 -22170 1473 -614 1419 -602 439 -1614 417 -1610 415 -1590 1465 -588 429 -1606 1469 -586 1455 -570 441 -22200 1407 -760 1277 -772 267 -1692 363 -1678 355 -1668 1393 -660 369 -1642 1441 -584 1449 -574 445 -22206 1533 -528 1497 -530 471 -1572 449 -1576 455 -1578 1507 -544 455 -1572 1503 -556 1467 -560 469 -22188 1439 -678 1347 -672 375 -1648 393 -1646 387 -1636 1431 -588 431 -1610 1439 -618 1437 -596 437 -143610 67 -510 99 -66 223 -272 173 -70 273 -204 235 -64 483 -26542 2521 -65448 297 -348 2417 -76720 65 -8388 65 -9450 203 -332 587 -72 885 -92 899 -27534 67 -39500 221 -406 521 -72 885 -98 919 -29920 1581 -534 1491 -548 445 -1580 461 -1544 477 -1574 1465 -556 473 -1568 1455 -554 1501 -524 483 -22136 1529 -498 +RAW_Data: -754 361 -17246 131 -8734 65 -71908 65 -27774 65 -1230 65 -13826 99 -800 65 -634 67 -796 99 -47716 65 -18338 67 -18176 131 -7986 65 -1084 131 -2090 65 -48694 163 -40926 65 -4538 65 -10224 65 -9874 20955 -1970 1023 -4928 1007 -4946 1011 -7910 981 -1992 1021 -7898 1013 -1962 1007 -7896 1019 -4930 995 -4962 987 -1974 1029 -4924 1019 -4920 1025 -7896 1005 -1964 1027 -7894 1007 -4932 1033 -1948 1009 -7916 1009 -1982 1001 -4942 1011 -7880 1011 -2000 1003 -13820 1011 -1990 985 -4944 1021 -4932 995 -7916 1025 -1944 1025 -7892 1015 -1970 1025 -7892 1001 -4934 1031 -4926 1015 -1970 989 -4938 1007 -4954 1019 -7874 1013 -2000 985 -7896 1011 -4950 1001 -1968 1023 -7900 999 -1968 1007 -4968 973 -7936 985 -1970 1009 -13856 1013 -1968 981 -4962 1009 -4926 1005 -7924 1003 -1968 1013 -7892 1003 -1992 985 -7904 1011 -4936 1023 -4948 997 -1960 1015 -4950 987 -4970 993 -7896 1005 -1970 1009 -7928 1005 -4914 1023 -1984 1001 -7894 1011 -1970 999 -4962 1003 -7890 1007 -1992 1013 -13810 1011 -1994 987 -4938 1005 -4964 999 -7904 1013 -1974 987 -7910 1021 -1964 1015 -7894 1021 -4912 1019 -4948 1007 -1970 1017 -4916 1021 -4946 985 -7914 1003 -1972 1009 -7898 1041 -4912 1013 -1994 985 -7892 1027 -1964 1013 -4938 1003 -7904 1023 -1966 1017 -13824 1025 -1968 983 -4950 1007 -4944 999 -7900 1029 -1964 1015 -7914 981 -2000 981 -7932 979 -4936 1021 -4926 1013 -1998 979 -4946 1035 -4908 1031 -7896 999 -1964 1025 -7902 1021 -4914 1023 -1966 1015 -7908 1007 -1970 1003 -4952 981 -7910 1001 -1974 1003 -13832 1015 -1976 999 -4958 1019 -4938 985 -7900 1025 -1966 1011 -7914 1015 -1964 1009 -7906 1017 -4908 1027 -4916 1011 -2000 981 -4954 1007 -4926 1017 -7920 1011 -1958 1009 -7906 1019 -4912 1025 -1980 1009 -7900 1013 -1948 1027 -4916 1011 -7918 1005 -1976 1003 -13846 1013 -1970 1005 -4914 1041 -4916 1007 -7918 987 -2000 987 -7902 1013 -1970 1015 -7894 1007 -4936 1019 -4944 1009 -1970 1013 -4918 1019 -4954 977 -7914 1019 -1964 1007 -7906 1003 -4956 983 -1982 1027 -7896 1005 -1962 1027 -4930 1007 -7906 999 -1972 1009 -13850 1009 -1952 1027 -4944 983 -4954 1023 -7894 1007 -1952 1031 -7882 1035 -1970 1011 -7894 1007 -4936 1025 -4920 1023 -1968 1011 -4928 1009 -4920 1015 -7902 1015 -1966 1021 -7894 1011 -4948 997 -1970 1009 -7902 1027 -1978 1011 -4930 999 -7918 1007 -1966 1013 -13824 1015 -1966 1027 -4918 1027 -4912 1021 -7888 1009 -1998 989 -7918 1019 -1960 989 -7930 983 -4946 1025 -4920 1013 -1970 1015 -4950 1009 -4926 1005 -7892 1037 -1942 1011 -7926 1005 -4918 1007 -1996 985 -7928 1011 -1964 993 -4946 1025 -7880 1003 -1972 1009 -13854 1011 -1948 1019 -4956 983 -4946 1025 -7898 1003 -1966 1025 -7900 1019 -1964 1011 -7890 1021 -4912 1017 -4930 1013 -1968 1015 -4952 1009 -4932 1007 -7920 1009 -1972 979 -7924 1009 -4944 1003 -1970 1015 -7894 1017 +RAW_Data: 131 -534 99 -798 2211 -134 297 -66 361 -66 197 -198 97 -398 199 -100 163 -100 65 -464 133 -134 233 -68 229 -696 199 -200 265 -330 65 -1218 163 -166 97 -426 229 -698 165 -100 99 -134 165 -372 65 -1426 65 -266 99 -794 65 -832 199 -464 165 -698 99 -266 165 -794 99 -298 133 -734 165 -266 99 -864 131 -232 1893 -166 1465 -1484 263 -560 99 -230 65 -462 197 -66 97 -890 165 -130 97 -132 163 -232 97 -132 161 -162 263 -262 99 -362 65 -432 65 -830 97 -234 99 -628 199 -66 99 -166 101 -268 265 -594 131 -1030 97 -1156 595 -800 167 -1920 65 -464 165 -264 131 -66 167 -134 233 -632 329 -100 97 -166 199 -466 199 -98 267 -200 97 -266 199 -300 65 -496 563 -100 101 -166 165 -730 233 -166 131 -590 97 -232 131 -164 359 -428 3159 -792 65 -624 197 -98 229 -132 393 -398 199 -200 133 -366 99 -132 67 -528 265 -730 197 -166 65 -200 397 -1358 131 -1712 363 -1462 299 -132 67 -1792 65 -794 99 -368 131 -134 165 -134 67 -266 265 -430 2315 -98 1473 -100 129 -66 229 -198 261 -166 97 -426 97 -100 229 -496 197 -162 163 -392 231 -166 229 -660 131 -366 297 -166 299 -232 97 -332 301 -866 133 -596 267 -364 99 -502 99 -1988 131 -134 65 -66 165 -366 231 -266 165 -690 99 -234 65 -498 67 -166 133 -762 2459 -166 1019 -264 99 -200 265 -562 65 -328 295 -330 197 -360 131 -98 227 -232 65 -426 259 -166 99 -496 131 -500 399 -992 67 -432 133 -66 99 -1394 231 -1524 133 -430 65 -886 65 -1716 131 -2818 63 -430 229 -296 97 -1706 131 -164 65 -1478 131 -458 99 -1568 165 -756 197 -890 99 -1088 359 -660 97 -98 229 -166 65 -500 99 -266 65 -566 65 -432 365 -200 99 -798 99 -296 327 -1218 165 -132 99 -466 165 -168 133 -632 363 -1482 163 -802 131 -862 133 -1332 65 -100 431 -830 97 -596 165 -3422 99 -896 65 -766 97 -3766 65 -132 65 -1152 163 -1810 99 -230 97 -654 229 -458 165 -200 67 -166 297 -134 99 -4840 133 -762 67 -764 231 -1248 97 -1780 97 -3332 65 -100 261 -1186 99 -3360 99 -364 97 -1738 163 -294 97 -4918 129 -1550 295 -1028 199 -1264 99 -1560 99 -2156 167 -1556 231 -1852 167 -998 67 -1116 65 -562 167 -334 133 -266 165 -394 99 -166 97 -3082 99 -232 301 -5148 131 -502 67 -732 197 -434 199 -200 99 -432 65 -232 199 -464 133 -1060 97 -1582 97 -98 97 -924 129 -462 229 -560 65 -132 97 -166 161 -164 97 -166 229 -360 97 -132 63 -198 131 -162 525 -1714 67 -732 99 -958 +RAW_Data: 65 -1166 165 -200 199 -166 133 -100 65 -1294 99 -166 265 -992 297 -728 65 -332 431 -166 261 -132 65 -132 65 -98 363 -230 163 -430 165 -230 129 -660 129 -66 131 -398 2453 -132 1329 -166 1187 -232 1657 -166 499 -68 99 -132 233 -894 99 -232 99 -134 363 -628 67 -998 131 -234 99 -266 197 -398 97 -200 167 -334 197 -430 429 -168 263 -1160 99 -364 131 -264 97 -1318 131 -790 99 -432 131 -132 199 -100 131 -930 133 -1424 99 -398 165 -1486 299 -166 165 -334 2325 -66 795 -102 397 -100 533 -100 429 -98 131 -464 65 -532 329 -366 165 -332 99 -432 295 -132 99 -662 67 -332 331 -1226 131 -102 199 -562 469 -430 97 -232 63 -328 65 -1914 133 -466 131 -832 163 -1660 331 -464 199 -828 131 -696 65 -132 2139 -66 2051 -66 263 -790 99 -566 429 -428 99 -330 297 -698 65 -200 197 -68 461 -1292 131 -168 165 -634 131 -234 133 -594 163 -360 165 -700 99 -964 133 -1026 65 -532 197 -1520 263 -688 65 -888 295 -658 65 -824 67 -598 97 -426 65 -130 161 -132 63 -658 99 -64 165 -522 199 -298 65 -428 197 -560 65 -200 165 -100 167 -594 229 -100 297 -268 65 -100 459 -200 97 -334 2997 -200 597 -498 97 -626 97 -134 363 -166 333 -266 65 -664 331 -300 299 -568 529 -662 263 -626 67 -594 99 -266 165 -230 361 -462 67 -66 131 -694 397 -1490 167 -132 165 -768 165 -130 165 -466 99 -298 99 -952 163 -428 97 -296 97 -360 99 -196 65 -658 65 -4052 229 -6240 165 -228 65 -426 99 -994 99 -398 363 -1512 161 -2042 65 -592 131 -2866 65 -500 167 -5246 97 -462 67 -1156 99 -2428 99 -960 65 -132 99 -164 65 -166 329 -2484 263 -232 67 -1368 99 -996 267 -498 67 -4612 131 -4866 65 -100 363 -464 231 -264 231 -262 297 -1594 99 -1596 65 -136 133 -1662 67 -1694 429 -1290 197 -198 293 -858 99 -1976 165 -66 97 -460 131 -460 97 -328 163 -1624 397 -300 67 -166 97 -430 299 -300 299 -1792 65 -4438 131 -622 67 -500 131 -1064 65 -400 65 -426 261 -1644 131 -3468 165 -1684 99 -866 101 -66 231 -464 65 -498 133 -492 97 -1712 99 -98 197 -66 265 -1586 199 -1334 99 -1948 97 -200 99 -266 65 -666 131 -132 99 -264 195 -3066 99 -3512 99 -1746 65 -598 97 -6068 167 -600 99 -1262 65 -166 65 -134 65 -132 131 -1520 99 -1254 97 -1828 197 -1294 129 -66 65 -1248 97 -754 165 -6542 231 -662 197 -560 359 -98 97 -130 99 -3080 63 -952 129 -296 65 -230 63 -428 99 -1788 133 -100 65 -462 199 -66 165 -1094 99 -66 +RAW_Data: 167 -3190 265 -1128 195 -298 525 -166 65 -594 597 -664 131 -498 165 -232 65 -296 129 -296 65 -494 297 -498 297 -596 201 -332 2027 -132 593 -68 891 -66 893 -98 365 -396 97 -398 99 -300 199 -366 163 -598 99 -100 131 -234 65 -132 331 -532 165 -166 231 -1660 133 -532 265 -100 131 -100 131 -298 199 -396 199 -334 197 -166 67 -334 131 -1662 165 -298 97 -534 65 -628 65 -534 65 -266 97 -826 133 -696 65 -294 233 -198 165 -134 2081 -66 929 -198 167 -300 99 -232 297 -234 199 -662 67 -166 99 -66 233 -132 433 -232 265 -300 297 -132 65 -132 97 -496 199 -360 465 -132 65 -132 297 -460 293 -64 161 -262 97 -492 199 -200 233 -132 97 -396 99 -858 199 -864 65 -66 99 -532 131 -1608 297 -1550 163 -432 229 -66 163 -394 1953 -134 1491 -100 991 -66 165 -232 265 -130 299 -432 167 -724 363 -134 167 -200 231 -66 199 -98 395 -66 165 -266 99 -332 197 -268 265 -466 265 -166 493 -362 65 -132 99 -360 199 -200 133 -758 99 -330 165 -298 163 -428 199 -368 165 -334 131 -500 163 -986 97 -394 329 -196 97 -558 195 -230 97 -532 2373 -232 165 -232 795 -132 267 -168 363 -166 297 -298 131 -134 65 -466 131 -464 65 -232 67 -266 229 -364 231 -232 297 -464 65 -198 133 -398 529 -134 65 -364 163 -732 233 -298 299 -134 231 -66 129 -264 397 -132 131 -200 329 -430 131 -132 265 -1292 65 -362 131 -264 97 -1020 165 -398 131 -364 65 -300 265 -924 195 -396 331 -166 167 -132 433 -198 99 -464 297 -266 165 -396 131 -1226 165 -694 65 -230 197 -896 65 -594 2969 -164 461 -298 133 -330 133 -234 65 -134 131 -66 65 -68 97 -66 99 -132 231 -694 363 -298 267 -268 231 -368 131 -300 99 -134 65 -166 461 -396 263 -66 165 -298 131 -66 229 -1644 163 -1610 229 -658 97 -132 129 -162 97 -428 65 -66 129 -1912 65 -1194 233 -2218 133 -360 65 -132 229 -3428 65 -262 65 -3208 133 -1224 99 -296 65 -2212 65 -496 65 -200 199 -498 65 -1144 65 -1764 165 -1726 65 -434 65 -898 165 -2354 67 -134 99 -464 99 -792 263 -954 1161 -100 295 -296 131 -132 457 -462 363 -200 725 -298 131 -134 231 -68 531 -166 667 -298 99 -66 595 -794 165 -202 199 -68 99 -298 165 -68 231 -202 201 -200 97 -1360 197 -266 165 -334 99 -234 165 -200 165 -100 131 -664 65 -566 397 -100 165 -132 199 -132 165 -988 197 -394 99 -164 65 -294 99 -262 63 -1288 233 -132 199 -168 265 -64 99 -728 133 -1192 65 -334 165 -132 199 -200 +RAW_Data: 131 -400 65 -398 165 -866 131 -264 393 -1680 231 -1494 299 -894 265 -364 65 -132 131 -960 99 -296 165 -824 65 -1716 99 -664 97 -134 165 -1526 165 -634 131 -166 135 -466 231 -696 2331 -100 329 -100 961 -198 65 -164 199 -98 331 -132 65 -298 731 -66 163 -332 265 -894 65 -132 265 -300 97 -334 229 -100 65 -1026 233 -366 329 -922 99 -266 329 -428 97 -462 361 -758 163 -1886 65 -498 229 -558 65 -600 267 -68 65 -1592 133 -202 2299 -332 393 -132 329 -326 231 -232 97 -590 231 -136 201 -1226 265 -530 199 -134 65 -232 297 -398 65 -564 65 -1458 65 -500 99 -302 99 -1120 65 -66 131 -98 197 -66 133 -66 65 -730 99 -200 197 -730 165 -664 297 -1462 165 -664 133 -168 65 -168 133 -368 197 -466 1957 -66 1525 -266 131 -366 65 -394 65 -98 163 -296 99 -130 265 -696 65 -398 131 -1128 197 -134 67 -894 97 -296 231 -166 401 -98 131 -928 265 -398 131 -798 131 -298 165 -830 65 -230 231 -168 97 -1252 131 -590 65 -460 229 -692 97 -332 65 -366 265 -732 2297 -66 197 -66 131 -166 231 -100 99 -298 365 -168 361 -130 129 -66 161 -198 97 -626 593 -66 99 -98 99 -556 297 -132 65 -134 65 -526 295 -196 197 -68 163 -264 327 -130 855 -66 393 -132 131 -100 65 -98 227 -164 197 -758 131 -268 99 -430 65 -1686 131 -1652 197 -788 63 -726 165 -100 131 -264 197 -1026 197 -1250 131 -1650 65 -1980 97 -132 63 -1424 97 -198 99 -100 65 -1090 65 -398 99 -1686 99 -754 63 -1714 97 -1842 65 -2988 65 -4980 165 -1624 65 -232 67 -1464 65 -3048 65 -166 97 -1986 65 -1062 99 -862 131 -2732 99 -2360 97 -1620 65 -1326 65 -330 197 -3238 67 -266 131 -2968 67 -132 135 -1688 131 -1718 97 -1648 65 -166 65 -1292 65 -1908 99 -424 131 -1222 197 -798 99 -700 97 -1758 165 -1562 99 -396 165 -166 99 -98 65 -366 65 -762 131 -332 233 -498 133 -98 163 -562 65 -68 131 -858 65 -896 65 -366 233 -532 197 -168 65 -68 65 -630 195 -724 231 -296 361 -164 261 -2862 233 -232 99 -3186 67 -232 163 -496 165 -1620 97 -1622 131 -7022 267 -268 165 -466 63 -528 295 -200 197 -332 65 -1656 131 -5478 65 -1296 99 -130 161 -694 67 -1694 131 -734 99 -2590 99 -1056 65 -432 327 -66 165 -164 65 -1120 229 -1656 165 -1128 131 -1232 99 -1560 65 -568 131 -360 231 -1598 99 -3250 67 -1818 65 -1216 263 -3328 65 -1508 133 -2600 65 -528 65 -2418 65 -460 97 -100 97 -164 65 -1560 133 -1822 163 -296 165 -1090 165 -168 133 -1264 +RAW_Data: 229 -1458 165 -66 133 -1626 197 -132 65 -394 65 -724 229 -132 65 -200 263 -296 97 -264 131 -130 229 -132 161 -1230 431 -132 99 -234 233 -362 99 -698 67 -334 65 -366 299 -398 99 -328 131 -396 165 -1458 99 -926 2239 -66 763 -68 1727 -266 65 -364 65 -464 365 -366 97 -664 165 -200 265 -234 261 -264 395 -362 329 -690 261 -164 495 -232 131 -326 165 -264 99 -198 397 -928 299 -268 299 -166 99 -298 167 -436 65 -266 67 -498 231 -896 367 -428 97 -332 133 -628 165 -1394 231 -926 131 -232 3127 -132 921 -428 263 -66 97 -230 97 -1022 329 -430 97 -166 65 -198 63 -100 65 -66 97 -66 361 -132 67 -232 131 -268 99 -366 99 -98 331 -364 99 -428 97 -66 491 -164 99 -164 65 -428 131 -260 429 -1380 263 -1564 65 -300 65 -498 99 -364 167 -200 231 -264 67 -264 365 -266 231 -262 65 -724 65 -130 2213 -130 361 -166 2065 -166 165 -100 133 -264 299 -332 99 -98 229 -198 65 -328 131 -100 263 -628 131 -330 231 -98 65 -132 129 -264 65 -130 163 -692 131 -66 99 -532 133 -234 99 -232 367 -298 401 -702 165 -498 399 -166 65 -132 131 -400 165 -1232 165 -1296 65 -232 165 -300 97 -396 2033 -198 463 -230 67 -68 563 -262 295 -330 197 -1190 197 -66 167 -66 263 -430 263 -100 163 -198 167 -102 165 -100 99 -234 67 -66 267 -396 197 -296 131 -1190 331 -200 67 -234 231 -530 263 -1610 263 -264 329 -196 129 -98 131 -132 227 -132 425 -526 129 -694 299 -856 63 -132 165 -166 165 -436 297 -1430 65 -66 99 -198 167 -266 65 -864 267 -996 65 -500 265 -1456 297 -726 163 -66 579 -1508 523 -1504 509 -1006 1033 -486 1513 -1514 507 -510 1537 -982 1011 -528 1509 -512 1495 -1034 999 -1016 999 -516 1539 -1014 989 -1510 527 -486 1537 -1508 517 -1512 485 -1546 483 -524 1519 -484 1529 -60168 1539 -1506 507 -1006 1015 -1016 1007 -1512 509 -1006 1033 -506 1495 -1544 497 -1014 1007 -1008 1001 -1544 477 -1024 1011 -1538 485 -1512 525 -1010 1005 -482 1529 -1018 1005 -1020 1009 -1532 475 -540 1507 -512 1491 -59188 513 -1506 515 -1512 519 -1020 985 -506 1519 -1538 491 -504 1533 -998 1013 -516 1505 -522 1505 -1018 1005 -1002 1035 -494 1525 -1014 995 -1546 483 -524 1513 -1504 515 -1502 509 -1512 509 -514 1527 -514 1501 -60186 1539 -1506 509 -1008 1003 -1016 1009 -1520 515 -1014 989 -518 1509 -1544 485 -1016 999 -1016 1003 -1544 483 -1016 1017 -1506 515 -1534 475 -1036 987 -520 1507 -1012 1035 -1006 1017 -1502 503 -526 1503 -508 1533 -59160 523 -1508 507 -1502 537 -984 1013 -528 1505 -1504 503 -520 1537 -994 +RAW_Data: -1968 997 -4952 1011 -7896 1013 -1954 1005 -13860 985 -2000 979 -4952 1005 -4946 993 -7930 979 -1990 1009 -7908 1017 -1968 1011 -7900 985 -4946 1027 -4920 1009 -1964 1015 -4942 1009 -263646 67 -9708 99 -68890 97 -48712 65 -62028 65 -4652 65 -108870 99 -71758 99 -3200 97 -47548 65 -7036 65 -104448 97 -38184 99 -6502 97 -17756 65 -10136 20983 -1968 999 -4950 1005 -4940 1001 -7898 1025 -1966 1011 -7876 1017 -1966 1023 -7918 981 -4936 1027 -4946 975 -2006 979 -4946 1017 -4954 977 -7930 983 -1980 1003 -7920 989 -4952 1007 -1970 1013 -7896 1007 -1970 1015 -4954 987 -7900 1007 -1970 1007 -13860 993 -1972 1007 -4956 1013 -4926 1005 -7908 995 -1972 1029 -7914 987 -1986 1009 -7906 981 -4956 1009 -4930 1005 -1966 1039 -4938 1007 -4916 1009 -7918 1019 -1968 989 -7892 1017 -4934 1027 -1956 1039 -7898 985 -1974 1007 -4960 981 -7930 985 -1996 989 -13824 1045 -1946 1025 -4928 1009 -4942 997 -7926 1011 -1968 1003 -7894 1023 -1962 993 -7902 1017 -4948 999 -4948 1007 -1968 1015 -4918 1045 -4926 999 -7888 1039 -1972 1013 -7888 1005 -4948 1001 -1970 1011 -7886 1013 -1974 1023 -4942 1005 -7890 1033 -1952 1021 -13806 1047 -1964 1001 -4936 1009 -4950 1001 -7882 1031 -1962 1007 -7906 1021 -1966 1011 -7908 985 -4946 1027 -4918 1011 -1968 1017 -4948 1009 -4932 1015 -7882 1009 -1964 1013 -7900 1017 -4950 1001 -1970 1013 -7916 1013 -1944 1031 -4916 1029 -7888 1007 -1976 1005 -13848 1013 -1968 995 -4952 1003 -4946 991 -7920 1019 -1968 983 -7904 1015 -1966 1019 -7894 1011 -4942 1027 -4924 1011 -1966 1015 -4944 1005 -4926 1007 -7914 1007 -1972 1013 -7884 1013 -4940 1027 -1968 1007 -7906 1001 -1980 999 -4944 1013 -7880 1009 -2000 1003 -13830 997 -1974 1009 -4930 1029 -4938 1013 -7880 1011 -1998 1001 -7908 997 -1966 1025 -7902 1013 -4938 983 -4962 979 -1998 1011 -4932 1005 -4924 1011 -7922 1009 -1970 1015 -7890 1011 -4946 1003 -1970 1013 -7892 1013 -1964 1027 -4928 1021 -7886 1007 -1980 1001 -13846 1013 -1968 999 -4948 1009 -4938 993 -7926 1011 -1964 991 -7926 1011 -1962 993 -7898 1041 -4906 1009 -4960 999 -1964 1023 -4932 1007 -4928 1013 -7898 1015 -1968 1013 -7894 1017 -4948 997 -1968 1031 -7892 1027 -1970 1005 -4914 1039 -7884 1023 -1964 1011 -13838 1013 -1948 1023 -4924 1015 -4942 1025 -7872 1029 -1964 1007 -7898 1025 -1960 1025 -7898 1021 -4912 1023 -4920 1011 -1970 1013 -4954 1011 -4926 1003 -7910 1011 -1968 1013 -7890 1009 -4938 1023 -1982 1007 -7902 1013 -1940 1023 -4926 1011 -7922 1007 -1980 997 -13816 1045 -1964 1001 -4948 1005 -4938 993 -7904 1005 -1966 1035 -7888 1027 -1964 1011 -7906 1015 -4916 1027 -4920 1011 -1968 1019 -4944 1009 -4928 1001 -7924 1009 -1972 979 -7914 1013 -4948 1001 -1970 1013 -7892 1015 -1966 1027 -4928 1021 -7872 1035 -1968 1011 -13832 1011 -1980 983 -4956 987 -4948 1025 -7892 1005 -1966 1007 -7914 1021 -1962 1007 +RAW_Data: -7912 985 -4942 1023 -4926 1007 -1992 981 -4944 1035 -4920 1007 -7904 1025 -1962 991 -7934 981 -4948 995 -2004 1007 -7880 1007 -1992 983 -4946 1027 -7890 1007 -1982 999 -13830 1011 -1968 1025 -4926 1013 -4942 997 -7898 1027 -1960 1023 -7910 983 -2000 979 -7906 1015 -4940 1025 -4920 1011 -1968 1013 -225644 65 -2082 65 -155560 133 -5172 65 -1102 131 -48576 99 -24714 67 -6858 65 -1314 67 -38246 65 -64888 65 -4564 67 -59374 99 -20160 99 -17606 65 -42096 97 -11950 131 -29302 65 -19034 99 -32020 97 -366 65 -4430 131 -14620 99 -17318 65 -5556 +RAW_Data: 297 -1592 167 -1594 231 -366 65 -598 65 -600 197 -98 199 -1098 99 -98 65 -862 133 -628 165 -597 361 -6828 65 -1668 231 -632 65 -792 163 -1284 163 -5554 199 -1588 165 -5300 97 -992 65 -432 197 -2566 99 -2340 63 -5932 65 -1462 65 -1062 131 -2454 65 -1446 133 -1682 65 -1260 65 -368 131 -1482 65 -134 131 -1512 197 -1710 131 -824 99 -66 133 -464 131 -866 65 -698 65 -200 65 -894 99 -1692 233 -1130 97 -2160 265 -1392 99 -132 131 -166 65 -1318 327 -1548 163 -6980 165 -994 65 -698 131 -1580 129 -132 63 -758 97 -466 99 -1590 395 -1024 97 -600 99 -732 63 -228 129 -98 165 -292 99 -696 231 -232 197 -166 133 -132 131 -430 165 -664 199 -1596 197 -530 65 -1054 63 -3474 165 -4504 65 -2980 99 -268 133 -2356 131 -798 99 -132 99 -796 97 -1692 97 -3804 199 -166 67 -66 97 -132 99 -5058 129 -1512 163 -1290 65 -298 199 -398 65 -1034 65 -1332 167 -3448 65 -1750 65 -1186 131 -462 65 -920 65 -166 97 -362 131 -1704 131 -1748 65 -2124 65 -1064 133 -1694 197 -5148 99 -566 131 -1696 99 -598 65 -698 231 -692 267 -2490 99 -1618 165 -1760 197 -2152 165 -1226 195 -100 99 -66 131 -100 99 -400 65 -456 131 -198 165 -368 261 -826 365 -858 99 -132 163 -460 229 -264 65 -664 165 -234 231 -98 165 -100 99 -1986 99 -2526 65 -832 167 -1762 231 -728 67 -530 133 -2082 97 -960 67 -498 199 -1658 133 -1488 99 -2652 99 -1258 165 -5284 99 -1660 65 -1790 65 -432 65 -3804 197 -2170 131 -196 129 -66 97 -832 99 -2466 97 -1622 99 -1624 163 -394 163 -1018 133 -1856 99 -430 67 -826 197 -3156 65 -166 97 -558 65 -1690 131 -1498 99 -66 65 -2716 161 -658 99 -1054 65 -230 65 -2074 97 -2042 65 -3074 263 -1698 165 -492 65 -400 131 -196 131 -368 165 -134 203 -168 201 -134 165 -398 301 -628 99 -1032 99 -830 65 -66 65 -432 229 -230 161 -394 197 -228 197 -330 327 -66 197 -822 231 -392 131 -892 393 -1456 131 -64 163 -1418 65 -166 165 -1428 133 -1526 163 -954 65 -888 99 -1956 133 -1194 131 -3514 65 -1728 97 -662 67 -1590 167 -2714 65 -930 65 -166 65 -728 131 -2752 65 -434 133 -1828 99 -3704 129 -1912 133 -1544 227 -494 133 -202 97 -466 65 -200 131 -1580 263 -1708 65 -626 65 -626 199 -166 133 -3446 99 -3420 99 -398 131 -1164 131 -7018 131 -3468 63 -1658 199 -956 101 -598 99 -1790 97 -1192 65 -362 133 -630 65 -100 429 -794 65 -696 231 -1130 65 -268 395 -730 131 -466 431 -66 233 -168 197 -998 97 -264 65 -796 163 -236 +RAW_Data: 265 -100 133 -1464 99 -464 67 -592 229 -362 131 -262 163 -134 325 -164 163 -130 97 -164 65 -724 97 -132 97 -958 131 -594 131 -264 161 -98 229 -100 97 -890 131 -364 99 -198 97 -262 131 -234 2497 -134 65 -68 165 -400 563 -400 433 -496 99 -100 131 -266 99 -100 65 -200 231 -894 65 -166 463 -200 201 -1228 131 -266 65 -496 99 -300 97 -202 165 -896 365 -132 163 -1698 165 -132 99 -168 67 -166 67 -796 165 -400 131 -200 165 -796 165 -98 2161 -66 65 -166 293 -228 887 -66 395 -656 297 -100 97 -530 97 -66 97 -594 65 -428 97 -332 65 -400 131 -164 261 -66 299 -334 65 -596 97 -166 99 -1184 161 -460 131 -132 229 -398 299 -664 165 -722 165 -166 263 -300 99 -232 199 -266 267 -660 97 -758 133 -530 65 -632 99 -264 329 -1028 67 -166 2451 -562 427 -464 163 -198 229 -264 229 -790 295 -164 297 -132 263 -726 267 -66 99 -364 197 -564 99 -1162 67 -960 97 -198 163 -630 133 -66 163 -132 195 -1288 197 -430 197 -1546 65 -890 97 -394 231 -924 2173 -100 65 -594 165 -100 99 -528 99 -166 99 -298 497 -66 65 -100 131 -198 265 -362 131 -198 293 -294 129 -1150 263 -262 65 -100 131 -494 231 -166 231 -468 99 -66 165 -1262 197 -298 65 -298 397 -432 297 -498 361 -200 65 -466 131 -166 101 -496 231 -364 233 -64 197 -196 65 -426 265 -198 99 -1218 97 -200 67 -232 131 -200 167 -200 99 -66 165 -928 67 -1722 99 -764 65 -892 99 -232 133 -300 133 -1080 621 -1526 487 -1504 507 -506 1517 -1524 519 -1508 509 -1512 447 -546 1503 -1038 1035 -1482 547 -976 1007 -1208 823 -490 1503 -532 1481 -1048 989 -1534 499 -524 1507 -514 1499 -1014 1007 -524 1503 -1530 473 -60198 1533 -1516 481 -1040 985 -1044 981 -1554 479 -1530 479 -1044 1007 -1502 511 -1538 483 -516 1503 -1542 473 -1016 1033 -1510 483 -1542 505 -1002 1003 -508 1521 -1010 1015 -1512 507 -526 1515 -518 1505 -1016 1007 -59156 529 -1528 463 -1580 447 -542 1507 -1544 469 -1554 481 -1512 499 -518 1507 -1016 1007 -1512 511 -1012 1021 -1010 1007 -518 1529 -472 1555 -982 1023 -1502 505 -508 1537 -488 1545 -1012 1003 -480 1531 -1516 507 -60180 493 -12296 821 -1698 299 -1686 387 -590 1465 -1570 459 -1046 979 -1546 475 -1534 489 -1044 1009 -482 1529 -1032 973 -1538 513 -480 1537 -492 1523 -1012 1017 -59154 497 -11798 301 -704 1325 -1148 913 -1612 417 -1102 897 -1118 945 -586 1437 -568 1465 -1058 977 -1534 477 -550 1495 -502 1515 -1006 1037 -494 1527 -1510 489 -60174 531 -16794 355 -640 1399 -1608 449 -1050 989 -1540 461 -1546 477 -1068 973 -518 +RAW_Data: 1503 -1024 1009 -1536 473 -552 1503 -498 1517 -1010 1017 -59162 513 -9838 227 -1670 371 -604 1425 -1116 949 -1554 477 -1030 981 -1042 973 -550 1477 -532 1511 -1010 1003 -1544 511 -496 1515 -516 1509 -1018 1007 -488 1539 -1504 503 -60216 1525 -1530 485 -1018 999 -1012 1019 -1538 475 -1546 477 -1012 1025 -1506 517 -1530 505 -510 1507 -1512 513 -1010 999 -1516 507 -1520 513 -1012 1015 -506 1527 -1014 991 -1542 483 -524 1517 -482 1529 -1008 1005 -137640 165 -1660 165 -1362 231 -3114 67 -2286 131 -1652 197 -1448 195 -1648 97 -3534 163 -988 65 -556 65 -132 133 -2594 199 -2054 65 -1918 65 -1458 163 -690 65 -1134 131 -1194 67 -1158 131 -1656 199 -198 99 -298 199 -2676 67 -2122 231 -1762 263 -1560 131 -1228 99 -198 197 -830 99 -166 97 -6274 99 -1058 163 -1676 97 -1788 65 -5742 99 -3890 131 -2682 195 -166 65 -1394 265 -432 99 -368 99 -100 67 -198 163 -564 133 -992 131 -266 133 -962 233 -200 131 -196 231 -560 131 -66 65 -764 131 -1058 133 -564 99 -1792 133 -2820 65 -3480 165 -9536 99 -66 97 -626 97 -1828 199 -1860 99 -66 197 -1060 99 -1746 65 -1690 99 -198 99 -1660 165 -1764 65 -1558 199 -1456 99 -164 65 -1318 395 -5966 131 -928 165 -1026 99 -534 65 -434 99 -100 97 -100 97 -3272 65 -2168 131 -2904 231 -1564 67 -958 263 -3780 65 -166 99 -3506 99 -1594 165 -1492 197 -164 63 -1382 197 -1162 65 -364 133 -822 65 -498 495 -230 165 -366 65 -464 231 -666 231 -198 65 -332 163 -566 65 -164 67 -332 231 -232 265 -198 97 -1254 361 -200 65 -2056 129 -430 131 -100 65 -1588 263 -198 97 -2992 97 -528 297 -134 97 -368 427 -66 67 -132 65 -132 367 -330 65 -266 229 -66 65 -66 65 -198 231 -66 133 -528 363 -162 161 -230 525 -230 65 -230 461 -132 327 -330 295 -130 197 -230 165 -270 265 -464 65 -698 265 -264 229 -400 99 -3476 97 -1490 199 -134 99 -2970 165 -1618 167 -1598 65 -1162 99 -234 167 -1162 135 -464 65 -664 165 -1126 197 -362 97 -1222 65 -3496 65 -7024 131 -1592 131 -530 97 -6464 231 -998 263 -428 65 -698 131 -198 131 -1414 63 -1346 165 -1060 65 -1664 167 -566 263 -666 165 -566 331 -100 131 -1522 167 -368 199 -896 229 -232 99 -968 99 -168 231 -66 197 -68 131 -168 133 -400 131 -268 233 -596 233 -132 97 -494 131 -1710 197 -1616 67 -592 99 -1226 267 -268 65 -266 133 -1986 165 -332 99 -366 131 -2700 97 -1398 65 -130 269 -198 65 -1664 131 -3180 165 -992 65 -866 99 -166 163 -2782 65 -2354 265 -5176 65 -66 163 -1290 67 -164 99 -2584 67 -3084 +RAW_Data: 195 -364 65 -164 229 -958 63 -166 193 -130 65 -556 99 -332 199 -430 197 -996 297 -1426 235 -1160 2053 -166 1063 -100 501 -132 535 -198 67 -66 165 -98 165 -460 365 -366 97 -432 329 -264 133 -100 165 -328 197 -360 1087 -264 97 -166 63 -166 233 -98 195 -294 97 -264 163 -266 197 -100 359 -66 65 -1958 165 -694 99 -166 99 -596 299 -466 97 -66 99 -696 231 -1492 297 -1554 165 -1680 165 -368 99 -166 99 -168 65 -794 197 -194 2581 -98 1151 -592 99 -426 197 -328 295 -164 65 -232 163 -530 165 -264 129 -98 229 -294 493 -426 99 -66 163 -164 261 -264 129 -166 229 -68 65 -558 131 -132 65 -132 197 -1550 361 -98 67 -132 99 -132 131 -786 99 -198 301 -366 165 -530 99 -234 2159 -264 1691 -166 367 -132 231 -100 197 -166 97 -366 163 -68 131 -366 165 -268 133 -430 233 -100 133 -132 199 -932 561 -1416 231 -794 199 -1296 165 -564 165 -666 99 -490 97 -760 163 -1582 295 -464 267 -330 2561 -134 931 -66 65 -132 99 -264 63 -132 99 -198 97 -364 129 -460 65 -230 263 -164 163 -100 365 -100 131 -398 97 -530 65 -266 299 -1028 133 -100 97 -166 65 -296 65 -166 133 -498 331 -962 99 -98 199 -1328 165 -200 65 -234 99 -400 231 -632 65 -232 199 -530 65 -866 429 -958 197 -368 165 -668 65 -984 163 -100 129 -1088 259 -752 97 -522 131 -892 65 -298 67 -364 199 -132 65 -788 97 -396 363 -1052 99 -228 131 -98 99 -1526 463 -330 131 -898 263 -332 97 -996 163 -494 99 -2950 65 -798 131 -2490 165 -1424 65 -1694 65 -1822 65 -1756 67 -3820 65 -2536 97 -2410 65 -1030 131 -404 263 -732 165 -1566 197 -1554 199 -400 65 -100 99 -566 165 -3584 65 -764 101 -2630 65 -2896 163 -364 67 -100 65 -1228 263 -232 63 -884 65 -4092 133 -1622 325 -166 99 -2352 65 -500 65 -1324 99 -366 65 -1592 297 -5134 131 -1130 65 -1962 99 -66 99 -1454 67 -1130 99 -134 199 -134 165 -1222 229 -166 131 -464 197 -196 263 -234 99 -534 65 -132 131 -166 133 -134 199 -1590 231 -66 131 -1160 131 -300 65 -698 199 -462 133 -3446 99 -2876 65 -596 65 -1716 133 -2886 97 -134 199 -1628 131 -1790 67 -2556 615 -1510 453 -1584 443 -1566 485 -1014 977 -1054 1003 -516 1501 -1010 1007 -520 1495 -1034 1005 -1530 481 -514 1541 -492 1523 -1012 1001 -1508 521 -1016 999 -512 1527 -1506 509 -488 1521 -1040 989 -1538 473 -60194 1519 -1540 511 -1010 1001 -1020 1009 -1516 515 -1010 1001 -518 1507 -524 1503 -1534 493 -1510 501 -1022 1011 -516 1507 -522 1507 -1512 509 -1506 519 -516 +RAW_Data: -130 1115 -68 55471 -1962 167 -1664 99 -364 427 -232 759 -132 199 -100 267 -134 527 -132 99 -1292 99 -266 65 -68 131 -762 327 -98 393 -298 37611 -730 131 -428 1487 -3910 327 -100 295 -98 491 -492 65 -98 197 -860 97 -98 131 -856 131 -134 231 -792 229 -66 919 -198 7527 -7444 131 -722 97 -230 65 -98 527 -100 267 -68 229 -262 361 -528 195 -624 131 -164 495 -66 1697 -66 1791 -132 3715 -8320 65 -394 165 -166 461 -1094 297 -532 131 -764 197 -98 261 -230 165 -100 6235 -12144 265 -600 131 -134 65 -298 233 -958 163 -196 97 -756 263 -98 465 -134 97 -164 3051 -16552 431 -68 131 -166 131 -264 331 -298 561 -166 689 -66 557 -264 3173 -8316 65 -166 531 -298 197 -234 233 -134 233 -892 163 -296 65 -890 161 -232 331 -100 397 -15072 199 -100 99 -394 165 -164 129 -132 197 -132 199 -798 99 -1032 67 -398 427 -100 391 -98 363 -166 297 -66 2869 -66 2299 -12300 97 -660 99 -662 263 -594 131 -662 133 -66 199 -332 97 -134 99 -132 65 -134 131 -100 431 -100 2143 -66 429 -8840 97 -6976 97 -66 397 -66 65 -166 131 -230 131 -294 99 -228 97 -230 129 -756 133 -1298 1293 -132 529 -100 2567 -15654 229 -328 97 -198 131 -66 195 -1492 131 -398 99 -134 99 -366 265 -168 99 -100 235 -100 131 -396 299 -200 1029 -66 6461 -6804 99 -1062 65 -960 65 -232 131 -98 195 -1708 63 -196 261 -164 331 -66 261 -12094 65 -298 265 -198 163 -592 131 -2402 63 -66 297 -198 97 -66 393 -264 4003 -15878 231 -98 261 -496 229 -264 65 -858 131 -994 133 -66 331 -66 429 -100 165 -132 297 -15004 99 -1466 97 -266 165 -198 463 -796 231 -66 131 -298 99 -100 133 -134 167 -430 99 -66 365 -100 297 -134 265 -132 563 -98 1217 -66 6399 -8742 99 -592 99 -426 397 -2338 199 -66 995 -134 229 -132 65 -164 3989 -66 3675 -6962 165 -466 65 -564 399 -66 199 -134 263 -396 97 -132 97 -100 97 -428 393 -624 131 -988 229 -66 363 -230 791 -164 7883 -8286 165 -134 99 -66 197 -100 99 -68 131 -164 163 -398 197 -2162 2005 -66 97 -100 4365 -98 1255 -12012 99 -132 165 -462 65 -166 97 -564 65 -100 331 -794 199 -364 261 -496 331 -132 823 -66 6233 -10976 165 -764 165 -200 195 -296 97 -19176 195 -230 129 -658 131 -132 293 -66 133 -860 65 -858 131 -64 229 -66 227 -66 161 -66 9051 -7316 65 -1494 131 -98 165 -198 65 -134 365 -398 297 -100 3969 -14874 99 -998 65 -564 67 -364 263 -132 163 -528 197 -132 65 -264 65 -264 431 -100 301 -66 297 +RAW_Data: -164 6323 -10770 65 -1420 227 -196 263 -198 197 -1086 99 -98 163 -164 163 -426 65 -362 97 -264 295 -132 197 -13586 65 -1808 131 -166 301 -66 465 -432 165 -330 65 -332 297 -962 99 -266 97 -166 265 -132 327 -198 329 -98 293 -14984 99 -862 131 -166 331 -68 165 -98 233 -132 201 -300 197 -364 133 -662 99 -398 99 -166 65 -432 133 -132 1447 -5882 197 -1082 65 -198 163 -1580 129 -264 67 -632 625 -134 165 -68 827 -100 165 -100 99 -164 3949 -9126 67 -164 131 -986 241 -534 309 -208 267 -226 247 -250 247 -248 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -504 257 -248 245 -246 247 -248 501 -258 247 -246 245 -248 247 -248 249 -248 249 -504 513 -226 243 -274 243 -500 513 -238 253 -256 253 -492 231 -262 485 -514 223 -244 527 -478 507 -274 255 -218 253 -498 261 -224 251 -250 503 -258 247 -246 243 -246 247 -504 515 -238 251 -472 277 -242 497 -246 289 -220 247 -498 513 -476 255 -68610 311 -208 235 -256 249 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 247 -248 503 -514 479 -274 253 -256 217 -254 247 -236 255 -250 247 -502 513 -240 251 -256 253 -254 249 -240 227 -252 249 -502 259 -246 245 -246 501 -514 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -246 501 -226 245 -276 245 -246 245 -248 247 -504 515 -478 255 -244 495 -274 253 -476 511 -240 241 -69142 321 -218 243 -230 251 -248 247 -248 247 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -506 257 -248 243 -246 247 -248 501 -258 247 -246 245 -246 247 -248 249 -248 249 -504 513 -238 251 -254 255 -490 499 -228 253 -250 249 -506 259 -248 499 -478 257 -244 495 -510 509 -238 255 -254 253 -494 227 -254 249 -248 505 -258 247 -246 245 -248 247 -504 513 -238 253 -472 279 -254 491 -226 253 -250 249 -504 513 -478 257 -68880 315 -216 241 -258 249 -248 247 -248 247 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 249 -504 257 -246 245 -246 247 -248 503 -516 477 -274 253 -256 217 -254 247 -236 255 -250 249 -502 481 -272 253 -254 255 -254 249 -238 227 -250 249 -504 257 -248 243 -246 501 -516 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -248 499 -228 245 -274 245 -246 245 -248 247 +RAW_Data: -504 513 -478 257 -244 495 -274 253 -500 483 -232 265 -69136 287 -256 249 -238 227 -250 249 -248 249 -248 249 -248 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -260 245 -246 245 -246 247 -248 249 -250 247 -504 513 -238 251 -256 253 -496 499 -228 249 -250 249 -504 257 -248 499 -478 257 -244 495 -510 509 -238 255 -254 255 -492 227 -256 249 -248 505 -258 247 -246 245 -248 245 -504 513 -238 253 -472 279 -254 491 -228 253 -250 249 -504 513 -478 257 -68886 309 -208 235 -256 249 -248 249 -248 249 -248 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 249 -504 257 -248 245 -246 245 -248 503 -514 477 -274 253 -254 217 -256 247 -238 255 -250 247 -504 513 -238 251 -256 253 -256 249 -240 227 -252 249 -504 257 -248 243 -246 501 -514 237 -252 473 -280 253 -250 241 -228 253 -248 249 -504 257 -246 499 -226 245 -276 245 -246 245 -248 247 -506 511 -478 257 -244 495 -272 255 -474 511 -240 241 -69150 323 -220 251 -242 229 -252 247 -248 247 -248 249 -248 249 -248 249 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -248 249 -250 249 -504 257 -248 243 -248 247 -248 503 -258 245 -246 245 -248 245 -250 247 -250 247 -504 515 -236 253 -254 253 -496 499 -228 251 -250 247 -504 257 -248 499 -478 257 -244 495 -510 509 -240 253 -256 253 -492 229 -254 249 -250 505 -258 247 -246 245 -246 247 -504 513 -238 253 -472 247 -272 501 -246 253 -254 243 -494 513 -476 255 -68934 287 -254 213 -240 257 -250 249 -248 247 -250 247 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -248 249 -250 247 -250 249 -250 247 -506 257 -248 245 -246 245 -248 503 -516 479 -272 255 -254 217 -256 245 -236 255 -250 247 -504 513 -238 253 -254 253 -256 249 -238 229 -252 249 -504 257 -246 245 -246 501 -514 237 -254 473 -280 253 -250 239 -230 251 -250 247 -504 257 -248 499 -226 245 -276 245 -246 245 -248 247 -504 511 -478 255 -244 495 -256 243 -496 509 -274 253 -69130 309 -218 253 -256 249 -240 227 -252 249 -250 247 -248 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 247 -250 249 -250 249 -504 259 -246 245 -246 247 -248 501 -258 247 -244 245 -248 247 -248 247 -250 249 -504 511 -226 245 -276 243 -500 477 -272 253 -254 255 -494 231 -262 481 -514 225 -246 527 -478 507 -256 241 -244 243 -494 257 -244 243 +RAW_Data: -246 527 -228 243 -276 245 -246 245 -500 513 -238 253 -474 279 -254 489 -228 251 -250 249 -506 513 -478 255 -68936 287 -218 249 -236 255 -248 247 -248 247 -248 249 -248 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -250 247 -250 249 -506 257 -246 245 -246 245 -248 503 -514 477 -272 255 -254 255 -218 247 -240 255 -250 247 -502 511 -226 273 -244 243 -244 247 -246 247 -250 247 -506 259 -246 245 -246 501 -512 225 -244 527 -238 251 -256 253 -254 251 -242 227 -508 257 -216 527 -226 275 -244 243 -246 245 -248 247 -504 513 -478 257 -242 527 -238 255 -472 511 -242 281 -119614 299 -200 65 -470 65 -466 297 -630 97 -1592 133 -166 299 -66 231 -100 131 -98 265 -134 165 -166 433 -100 2287 -9916 231 -166 65 -98 199 -166 133 -166 165 -756 65 -724 195 -428 231 -260 263 -98 229 -130 261 -66 163 -264 65 -132 1181 -66 6315 -6798 131 -296 559 -334 131 -166 233 -132 165 -66 133 -264 99 -66 65 -366 99 -630 301 -166 97 -100 167 -164 535 -202 7269 -8266 197 -1022 131 -756 99 -98 99 -164 163 -990 65 -530 163 -230 297 -136 635 -66 2113 -8426 67 -6674 97 -722 197 -362 263 -232 165 -134 99 -234 297 -362 129 -198 131 -556 297 -68 167 -98 331 -200 165 -66 295 -66 8689 -4994 65 -1750 165 -762 163 -864 135 -100 167 -694 1093 -66 695 -102 99 -100 9899 -1650 297 -1216 97 -66 99 -396 65 -198 165 -164 233 -1658 199 -98 465 -134 463 -166 1883 -98 6283 -7302 99 -932 133 -696 263 -298 97 -98 165 -1708 131 -820 229 -98 231 -130 163 -590 131 -130 99 -66 97 -16220 261 -1062 265 -998 197 -1290 97 -362 165 -494 895 -264 7839 -7804 99 -66 99 -364 231 -630 133 -166 427 -496 131 -1252 263 -100 233 -66 133 -132 165 -66 259 -98 3109 -10438 101 -5322 99 -100 65 -666 65 -166 331 -98 197 -132 233 -662 261 -1516 559 -66 263 -130 689 -132 229 -64 3613 -15976 231 -166 133 -66 399 -264 99 -132 295 -366 97 -1692 99 -398 529 -68 397 -130 899 -164 3559 -98 1197 -12106 199 -98 65 -166 99 -266 99 -134 231 -100 133 -132 297 -430 99 -1394 299 -64 397 -166 99 -100 465 -200 331 -132 599 -100 2333 -15214 65 -1230 231 -266 265 -432 165 -398 65 -532 333 -632 65 -232 957 -98 9785 -6320 97 -830 167 -166 133 -732 299 -958 327 -98 197 -66 229 -164 327 -98 653 -66 7993 -6418 65 -1284 97 -458 129 -196 197 -166 393 -134 99 -332 427 -132 131 -66 133 -98 233 -66 133 -364 163 -566 4873 -16030 97 +RAW_Data: -360 65 -364 65 -68 857 -98 65 -232 131 -264 63 -98 391 -396 65 -130 99 -98 65 -66 861 -166 265 -166 7611 -10336 65 -1822 165 -300 165 -166 295 -134 199 -100 67 -264 165 -166 99 -500 99 -198 97 -200 165 -268 197 -130 65 -300 629 -166 561 -132 333 -132 7459 -6294 131 -1096 165 -964 197 -332 65 -166 129 -132 99 -130 99 -100 97 -134 65 -164 131 -494 165 -396 97 -164 131 -198 99 -232 229 -66 821 -64 131 -14954 97 -788 65 -100 263 -66 99 -300 65 -400 131 -198 293 -294 163 -132 65 -692 99 -132 131 -200 1847 -132 8773 -5968 133 -330 65 -66 295 -430 197 -166 565 -132 467 -98 65 -430 165 -262 131 -528 131 -296 131 -100 131 -66 557 -166 787 -98 3221 -16236 299 -166 133 -562 199 -1692 99 -66 65 -364 65 -366 231 -168 367 -100 5541 -14968 297 -164 97 -132 163 -328 99 -532 99 -134 131 -370 397 -66 397 -98 293 -98 197 -98 1151 -66 7019 -6746 129 -296 163 -954 261 -230 229 -64 231 -264 431 -100 99 -466 165 -100 333 -166 133 -666 695 -200 67 -134 397 -100 1667 -7686 97 -426 195 -266 97 -330 63 -98 99 -594 97 -132 133 -270 131 -600 131 -362 833 -98 297 -166 199 -66 99 -200 65 -66 197 -100 2963 -98 1125 -2238 199 -554 275 -242 273 -212 271 -242 241 -242 271 -244 241 -244 273 -244 245 -246 247 -248 247 -250 247 -250 249 -250 249 -248 249 -248 249 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -246 247 -248 249 -250 247 -504 513 -228 243 -244 273 -246 245 -500 513 -478 257 -242 241 -244 273 -244 499 -512 225 -244 525 -228 273 -496 475 -508 507 -240 253 -254 255 -494 261 -222 505 -258 245 -246 245 -246 245 -250 247 -506 513 -478 257 -242 241 -244 273 -244 499 -68858 319 -218 245 -230 251 -248 245 -248 247 -250 247 -250 249 -248 249 -248 249 -250 249 -250 249 -248 249 -248 249 -250 249 -248 249 -250 247 -506 257 -246 245 -246 247 -248 503 -516 477 -274 253 -474 511 -478 527 -484 511 -240 253 -472 281 -254 489 -484 513 -478 513 -480 255 -242 523 -472 507 -276 253 -462 275 -240 491 -258 247 -244 245 -246 247 -502 515 -238 253 -254 253 -492 497 -230 253 -250 247 -250 247 -250 247 -250 247 -506 257 -68880 279 -248 241 -266 223 -252 249 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -506 225 -280 213 -278 245 -248 503 -260 215 -276 245 -246 247 -248 247 -250 247 -504 481 -272 251 +RAW_Data: -254 255 -254 213 -506 483 -514 271 -254 217 -292 217 -248 497 -516 237 -254 473 -278 251 -488 489 -516 477 -272 253 -254 219 -494 261 -260 481 -260 215 -278 247 -248 247 -248 247 -504 481 -514 235 -290 217 -256 253 -244 497 -69132 311 -212 235 -258 249 -248 247 -248 249 -248 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -506 257 -248 245 -246 245 -248 503 -512 479 -272 253 -474 513 -478 527 -482 513 -238 253 -472 281 -254 487 -486 515 -478 509 -480 255 -242 529 -480 509 -240 255 -496 271 -234 487 -260 247 -244 245 -248 247 -504 511 -226 243 -244 275 -498 479 -272 253 -254 255 -254 249 -238 225 -252 247 -504 257 -68882 319 -188 265 -280 235 -228 251 -250 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 247 -250 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 245 -250 247 -250 249 -504 515 -238 251 -256 253 -256 249 -472 515 -480 271 -256 253 -218 255 -248 497 -482 271 -252 473 -280 253 -490 487 -516 477 -274 253 -256 217 -496 261 -224 507 -258 249 -246 245 -248 247 -248 249 -504 511 -478 255 -244 243 -244 275 -246 499 -69134 311 -208 231 -254 249 -246 247 -250 247 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -248 249 -506 259 -246 245 -246 247 -246 503 -516 479 -274 253 -464 519 -496 487 -516 477 -274 255 -498 249 -248 469 -514 479 -516 483 -488 277 -254 491 -498 487 -260 247 -498 227 -244 529 -228 243 -274 245 -246 245 -502 515 -238 251 -256 253 -496 497 -226 251 -248 249 -248 249 -248 249 -250 249 -504 257 -68898 247 -274 213 -312 185 -312 185 -312 185 -312 185 -312 185 -312 185 -310 185 -310 185 -310 215 -278 217 -278 215 -278 217 -278 217 -280 215 -532 237 -288 217 -290 215 -276 461 -260 219 -280 217 -280 217 -278 215 -280 247 -506 481 -270 251 -256 217 -290 213 -502 483 -514 271 -254 253 -218 255 -246 499 -482 271 -254 473 -282 253 -488 485 -516 477 -274 253 -256 217 -496 263 -224 507 -260 247 -246 245 -246 247 -248 249 -504 513 -478 255 -242 243 -244 275 -246 499 -69122 319 -220 243 -228 251 -248 247 -248 247 -250 247 -250 249 -248 249 -250 249 -248 249 -248 249 -250 249 -250 247 -250 249 -250 247 -250 249 -504 257 -248 245 -246 247 -246 505 -514 479 -274 253 -476 511 -476 493 -516 481 -270 253 -474 279 -254 487 -484 513 +RAW_Data: -478 507 -506 225 -272 495 -482 505 -254 241 -494 255 -242 525 -226 241 -274 243 -242 243 -496 509 -274 253 -254 219 -494 491 -258 249 -248 247 -248 249 -248 249 -248 249 -504 257 -68896 281 -214 241 -260 247 -248 247 -248 247 -250 247 -250 249 -248 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -250 249 -504 257 -248 245 -246 245 -248 503 -260 245 -246 245 -248 247 -248 247 -248 249 -504 513 -238 251 -254 255 -254 251 -474 515 -478 273 -254 255 -218 253 -248 499 -514 237 -254 473 -280 253 -490 485 -516 479 -274 253 -256 217 -496 263 -224 507 -258 247 -248 245 -246 247 -250 247 -504 513 -478 257 -244 241 -244 275 -246 499 -69128 321 -218 241 -230 249 -248 247 -246 249 -248 249 -248 249 -248 249 -250 249 -250 247 -250 247 -250 249 -250 247 -250 249 -250 249 -248 249 -504 257 -248 245 -246 245 -250 503 -514 477 -272 255 -474 515 -480 491 -518 479 -274 253 -474 281 -254 483 -486 479 -512 507 -506 223 -242 527 -482 509 -240 253 -496 273 -236 487 -260 247 -246 245 -246 247 -504 513 -238 251 -256 253 -492 495 -228 253 -250 249 -250 249 -250 249 -248 249 -504 257 -68860 273 -242 233 -256 249 -250 247 -248 247 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -250 247 -250 249 -248 249 -250 249 -248 249 -504 257 -248 245 -246 247 -248 503 -258 247 -244 245 -248 247 -248 247 -248 249 -504 513 -238 253 -254 253 -256 249 -474 515 -480 273 -254 255 -218 253 -248 497 -516 237 -252 473 -280 253 -490 487 -514 479 -274 253 -254 219 -496 263 -224 507 -258 247 -246 245 -246 247 -248 249 -504 513 -476 257 -242 243 -244 273 -246 499 -68728 129 -604 249 -242 243 -276 213 -276 245 -244 245 -246 245 -278 215 -278 215 -278 247 -248 247 -248 247 -248 249 -248 247 -250 247 -250 247 -250 247 -504 259 -246 245 -246 247 -248 503 -514 477 -272 255 -474 511 -478 527 -484 481 -272 253 -472 281 -254 485 -486 511 -478 511 -480 255 -242 527 -482 505 -254 241 -494 253 -242 495 -254 241 -244 273 -244 243 -494 509 -238 255 -254 255 -492 489 -260 247 -248 245 -248 247 -248 249 -248 249 -504 257 -129658 99 -98 131 -132 97 -100 97 -132 131 -98 131 -496 297 -266 163 -198 99 -398 165 -626 133 -198 531 -166 67 -66 431 -132 331 -100 65 -132 99 -100 2725 -9960 65 -3686 295 -1552 99 -362 195 -100 887 -98 263 -100 1495 -8372 67 -298 99 -100 131 -332 133 -198 233 -398 65 -1060 99 -164 327 +RAW_Data: 2243 -98 331 -100 1129 -66 761 -100 1393 -100 165 -66 2883 -64 357 -66 4703 -68 927 -98 233 -134 461 -66 3855 -134 165 -98 1281 -100 2053 -66 3061 -98 331 -98 8981 -66 365 -66 631 -100 1027 -100 4521 -134 597 -66 3187 -66 2619 -100 3011 -98 1151 -66 953 -100 1423 -66 1755 -166 333 -98 1557 -66 761 -66 865 -66 4837 -132 357 -132 2419 -100 1023 -66 65 -66 2507 -66 131 -66 761 -66 997 -66 333 -100 2259 -68 431 -100 2523 -66 987 -100 363 -66 363 -66 1197 -68 1589 -164 951 -96 5351 -66 697 -100 163 -100 4683 -66 2265 -68 2051 -64 457 -64 3005 -132 1057 -66 2221 -100 1661 -98 695 -100 99 -66 861 -66 1957 -100 731 -132 1857 -100 3177 -98 1807 -98 463 -66 499 -134 1129 -100 3737 -100 1889 -66 263 -98 623 -66 2103 -98 3165 -66 131 -100 195 -66 691 -66 67 -132 531 -66 1857 -100 199 -68 97 -68 197 -68 697 -68 233 -100 3749 -134 1691 -68 3289 -66 3751 -68 65 -100 853 -66 531 -132 1299 -66 1585 -98 65 -98 1577 -66 785 -98 1151 -66 165 -68 397 -100 4255 -100 857 -100 1017 -66 1575 -130 1255 -234 1923 -66 199 -102 301 -66 231 -66 691 -64 227 -64 195 -66 1257 -100 2353 -100 235 -100 1163 -66 5423 -66 2049 -66 1807 -66 523 -198 693 -100 367 -100 597 -100 4013 -100 233 -166 365 -66 1827 -100 1491 -100 785 -64 885 -66 599 -134 2847 -100 667 -100 4943 -98 3319 -98 6729 -98 361 -96 391 -66 723 -132 503 -66 1583 -166 297 -234 2045 -66 1185 -134 661 -66 195 -66 291 -164 523 -98 1679 -134 233 -132 761 -394 855 -100 2003 -164 261 -66 229 -96 953 -66 3889 -66 929 -66 993 -68 3099 -132 1673 -66 1833 -100 563 -100 1131 -100 3219 -232 4411 -100 1095 -100 5315 -100 631 -198 461 -198 1907 -100 1743 -68 863 -132 4013 -64 295 -66 3883 -100 2707 -198 923 -100 2539 -166 629 -100 563 -100 3783 -68 893 -66 2987 -98 2357 -98 1665 -66 599 -66 1259 -232 165 -66 1361 -66 1645 -166 1543 -66 565 -66 401 -134 465 -100 831 -98 2405 -100 1055 -66 2109 -100 1161 -68 431 -100 265 -68 235 -66 463 -66 3453 -100 433 -66 2693 -132 263 -166 729 -134 763 -134 1327 -100 397 -234 795 -68 563 -66 1625 -98 267 -66 4835 -66 197 -66 589 -66 7575 -100 1959 -100 131 -68 297 -134 261 -98 433 -66 1427 -66 2421 -100 2925 -166 1921 -134 1645 -66 97 -132 5423 -100 2423 -98 1065 -66 1715 -132 963 -66 2403 -66 1117 -328 1981 -66 527 -100 427 -164 865 -66 2129 -232 165 -68 165 -66 131 -366 131 -100 2613 -450 +RAW_Data: 937 -900 447 -454 969 -884 479 -466 939 -452 935 -454 981 -454 943 -452 955 -458 945 -452 979 -444 943 -486 945 -448 951 -464 977 -440 967 -478 935 -480 951 -456 969 -460 975 -450 973 -450 979 -470 977 -450 981 -910 485 -466 939 -928 489 -448 971 -940 445 -484 951 -928 485 -484 945 -948 479 -456 973 -918 481 -944 451 -928 471 -478 995 -912 487 -472 977 -15948 479 -444 1021 -910 521 -444 995 -942 471 -480 991 -450 1013 -452 1023 -446 1001 -484 981 -486 1007 -458 1015 -470 1007 -450 1033 -452 1005 -480 1005 -458 1013 -470 1007 -482 1015 -450 1023 -482 1009 -462 1015 -468 1011 -484 983 -482 1021 -944 487 -484 1015 -942 471 -486 1003 -948 503 -478 991 -948 501 -478 1031 -914 521 -486 991 -946 519 -916 511 -944 485 -474 1009 -974 487 -482 1015 -16224 521 -468 1005 -970 503 -478 1001 -954 505 -458 1035 -484 1019 -482 1039 -482 1019 -486 1031 -490 1009 -478 1033 -486 1033 -486 1011 -494 1039 -478 1039 -450 1049 -486 1033 -488 1005 -476 1071 -448 1067 -486 1017 -468 1045 -482 1045 -484 1015 -952 515 -482 1043 -944 519 -482 1049 -950 519 -454 1039 -956 523 -484 1011 -960 505 -486 1065 -956 509 -926 539 -944 519 -480 1017 -984 521 -454 1037 -16440 553 -440 1043 -976 507 -460 1069 -940 513 -486 1041 -480 1067 -482 1033 -476 1061 -472 1043 -510 1049 -486 1041 -482 1043 -482 1065 -476 1037 -486 1069 -492 1037 -484 1047 -504 1047 -486 1041 -484 1041 -514 1015 -520 1049 -476 1053 -490 1041 -980 519 -486 1043 -962 507 -482 1049 -994 507 -500 1043 -946 507 -516 1033 -982 517 -478 1049 -984 509 -976 505 -950 527 -490 1039 -980 519 -486 1047 -111258 195 -428 263 -162 163 -362 97 -132 65 -98 163 -132 825 -100 795 -100 1795 -134 587 -66 229 -100 1349 -164 3261 -66 2305 -132 2219 -66 5549 -234 497 -132 201 -66 667 -298 2369 -68 4381 -66 3909 -134 923 -98 723 -100 1651 -168 1197 -100 65 -66 199 -68 195 -100 197 -134 1135 -66 2787 -66 3163 -68 231 -68 197 -100 6675 -100 667 -98 1125 -66 67 -98 2423 -66 2017 -332 2949 -100 1129 -68 1655 -100 1229 -66 1285 -130 163 -132 1315 -66 525 -98 295 -100 131 -64 427 -132 2207 -98 1153 -66 99 -100 697 -98 1397 -166 863 -66 1393 -132 5005 -66 497 -100 1753 -100 597 -66 1667 -66 397 -100 961 -66 763 -134 859 -64 689 -98 1917 -134 199 -234 167 -100 131 -166 2061 -66 1521 -98 759 -100 983 -66 825 -166 459 -66 2049 -166 1615 -100 829 -234 631 -66 465 -66 1493 -68 433 -66 1623 -132 65 -100 1133 -132 3083 -66 199 -132 199 -68 1257 -66 +RAW_Data: 265 -68 1061 -98 533 -100 1233 -68 1721 -68 995 -100 2535 -66 4193 -232 727 -100 727 -100 2773 -66 133 -98 399 -134 233 -232 67 -66 497 -100 267 -132 1127 -134 1063 -66 565 -132 97 -132 523 -132 919 -66 891 -66 855 -98 495 -66 3363 -296 3199 -98 563 -66 133 -100 495 -98 1165 -134 1161 -166 1849 -98 853 -132 5647 -134 563 -98 1827 -100 131 -100 1125 -132 1659 -132 265 -68 1121 -66 465 -232 431 -68 3589 -98 197 -68 97 -164 1717 -66 1645 -66 397 -66 97 -68 231 -166 631 -100 627 -66 1757 -66 131 -164 527 -98 1285 -328 1213 -134 2059 -100 1791 -68 931 -66 1611 -66 1511 -66 2211 -66 2597 -100 2545 -98 197 -162 1089 -98 589 -360 495 -132 1685 -202 1095 -100 729 -100 2825 -100 231 -100 567 -100 231 -66 1027 -66 131 -68 525 -132 1613 -232 461 -232 1597 -66 627 -198 231 -98 131 -98 65 -100 1229 -68 2507 -64 1349 -66 195 -134 97 -66 1321 -100 855 -132 163 -132 1151 -100 1025 -164 329 -66 891 -98 951 -132 163 -166 591 -98 1149 -132 955 -66 1329 -98 923 -66 331 -64 4269 -66 797 -134 399 -98 267 -170 197 -100 429 -198 1225 -100 331 -100 231 -132 1463 -100 597 -164 331 -66 1863 -134 659 -98 5507 -100 719 -100 131 -64 655 -164 1579 -98 1423 -130 1381 -98 1317 -132 467 -66 495 -132 361 -132 4417 -98 631 -364 299 -100 1499 -132 267 -68 663 -98 691 -100 2433 -66 953 -98 721 -66 1355 -232 897 -134 897 -134 365 -100 267 -132 2059 -132 199 -102 797 -68 695 -66 601 -66 265 -68 499 -66 1327 -164 1355 -64 1279 -66 3257 -66 1351 -66 131 -96 359 -132 499 -232 623 -96 427 -68 1909 -98 591 -98 4671 -100 4541 -66 1491 -66 3347 -98 1277 -100 1679 -198 295 -130 357 -98 697 -98 865 -100 2817 -66 329 -98 787 -64 1117 -66 3313 -202 1721 -100 199 -100 399 -66 199 -132 1891 -100 235 -100 201 -134 765 -166 761 -132 1529 -66 629 -202 861 -130 3501 -98 1377 -100 1741 -164 1509 -66 735 -68 733 -66 265 -166 2015 -134 131 -100 663 -100 2995 -132 1577 -98 1885 -66 2461 -100 1189 -66 1425 -100 201 -100 1691 -100 199 -98 499 -166 233 -100 233 -134 661 -68 1393 -100 295 -164 2079 -66 1289 -66 329 -198 599 -100 465 -98 3995 -98 199 -268 2045 -264 199 -66 1593 -66 165 -68 1561 -164 629 -66 635 -100 1251 -230 2733 -66 1727 -66 629 -100 1229 -132 731 -66 163 -198 131 -100 693 -66 3223 -68 565 -132 1091 -134 531 -100 3223 -68 729 -100 1527 -134 895 -166 1265 -66 527 -100 201 -200 1463 -66 1233 -132 +RAW_Data: 2397 -200 167 -234 1803 -66 821 -100 1351 -66 1687 -100 165 -66 233 -66 1125 -100 2203 -132 197 -98 97 -66 593 -164 4187 -102 529 -66 1161 -68 799 -66 427 -232 263 -66 589 -68 495 -68 197 -100 525 -66 327 -98 427 -130 1551 -66 727 -102 133 -234 265 -98 459 -66 2337 -64 585 -68 297 -68 691 -98 1857 -134 665 -132 365 -66 931 -166 495 -430 689 -196 1191 -98 465 -100 931 -366 1351 -102 3185 -164 1151 -98 2465 -66 2193 -100 331 -134 165 -98 267 -166 1985 -98 889 -132 765 -66 531 -100 1449 -166 457 -98 1715 -66 299 -166 3131 -130 197 -98 817 -294 793 -100 97 -66 3415 -164 1019 -98 1675 -132 197 -100 133 -68 199 -134 3319 -298 297 -66 791 -66 1029 -134 2153 -100 1629 -132 1391 -68 1229 -100 665 -66 2039 -164 461 -64 261 -66 395 -202 395 -166 3159 -134 2253 -166 265 -132 395 -66 887 -98 163 -66 589 -98 227 -130 1151 -230 293 -66 591 -68 527 -132 2883 -100 231 -66 99 -232 761 -134 499 -64 929 -100 167 -300 2259 -100 691 -164 459 -66 493 -132 163 -64 1283 -164 757 -132 295 -264 1023 -100 197 -198 6635 -198 2407 -100 2091 -132 1531 -66 1889 -100 199 -134 3567 -100 2981 -100 263 -198 425 -164 595 -100 231 -68 2691 -66 965 -100 2907 -98 367 -132 885 -198 1721 -100 659 -100 97 -296 495 -166 299 -134 397 -132 699 -66 1165 -66 465 -68 197 -66 659 -66 1543 -66 819 -164 2913 -98 1061 -66 5475 -132 167 -100 1035 -66 3427 -298 429 -166 2723 -66 831 -98 133 -66 133 -66 495 -98 701 -66 1063 -98 1991 -100 3319 -66 263 -66 233 -66 695 -66 593 -132 595 -66 553 -66 459 -66 197 -164 2241 -66 165 -68 959 -98 1587 -166 65 -102 233 -66 465 -134 1227 -100 2359 -66 1959 -198 331 -232 165 -102 531 -100 63 -66 1999 -68 265 -100 429 -66 657 -166 297 -132 823 -100 129 -132 4511 -164 659 -68 299 -66 593 -66 99 -134 65 -100 397 -66 1561 -66 697 -100 429 -66 265 -134 361 -132 195 -130 1319 -66 133 -66 265 -100 397 -268 895 -100 363 -134 433 -66 133 -100 2321 -68 +RAW_Data: -98 3573 -98 533 -68 961 -68 729 -132 559 -166 2189 -100 131 -68 657 -100 1387 -132 133 -68 2255 -68 429 -66 231 -134 793 -100 887 -98 361 -166 2141 -66 227 -130 663 -100 759 -100 1161 -134 1821 -66 327 -98 985 -130 757 -132 131 -132 1693 -66 361 -98 1411 -100 591 -132 1025 -66 663 -66 1065 -166 1059 -166 365 -66 723 -100 1659 -132 1883 -98 785 -132 1031 -66 261 -66 2501 -98 297 -66 1195 -100 691 -134 3009 -100 3921 -66 861 -66 363 -132 3361 -132 723 -66 459 -164 163 -164 333 -66 1291 -98 821 -230 591 -164 97 -262 361 -66 689 -66 733 -66 233 -134 1627 -66 533 -66 195 -100 521 -100 493 -98 493 -98 2173 -66 2037 -132 165 -100 429 -132 695 -100 67 -132 465 -68 1491 -100 1257 -66 965 -100 365 -68 929 -132 561 -66 899 -132 597 -132 861 -100 2627 -166 197 -98 2079 -66 2223 -100 1791 -364 895 -132 1027 -132 235 -68 599 -132 829 -66 197 -132 695 -66 133 -66 531 -68 333 -64 563 -66 265 -132 369 -134 2239 -164 4269 -100 793 -66 1495 -198 821 -164 133 -66 867 -66 797 -66 429 -66 365 -166 1729 -168 959 -100 1417 -66 233 -100 2579 -166 993 -164 461 -66 1529 -68 961 -66 1049 -98 1061 -132 2847 -66 229 -66 397 -134 263 -100 3285 -66 4115 -66 1547 -134 297 -132 431 -100 2895 -100 563 -66 1491 -66 399 -100 721 -66 395 -68 399 -66 1289 -66 293 -164 2307 -98 525 -66 3663 -64 927 -132 499 -134 1127 -264 397 -98 399 -198 131 -100 333 -100 663 -164 921 -166 1481 -262 691 -64 659 -64 2167 -98 3689 -100 833 -100 2085 -66 697 -100 595 -66 923 -134 893 -232 265 -98 367 -66 1157 -66 263 -130 1017 -66 623 -66 753 -100 2873 -132 395 -198 2787 -100 861 -132 3847 -100 297 -66 233 -98 1333 -100 495 -100 1325 -134 367 -66 595 -66 361 -230 4931 -66 1821 -98 329 -98 365 -168 333 -300 897 -100 2777 -66 1945 -132 2601 -66 951 -66 425 -98 789 -98 359 -64 1051 -66 1443 -132 851 -98 625 -100 97 -66 731 -232 263 -134 2757 -68 3021 -166 265 -100 1633 -132 427 -66 233 -98 799 -100 1059 -100 263 -98 557 -68 1063 -66 461 -100 1023 -98 163 -198 1481 -132 1227 -98 327 -100 327 -66 1317 -66 1853 -66 1061 -134 1287 -66 1315 -66 1345 -132 723 -66 1225 -68 1463 -166 3261 -98 2883 -66 563 -100 821 -100 2077 -166 3137 -66 565 -66 1355 -234 1415 -132 165 -66 397 -132 493 -132 563 -166 893 -66 1193 -66 1249 -100 333 -132 2083 -66 921 -100 1225 -262 861 -166 1321 -100 895 -100 591 -98 1249 +RAW_Data: -98 97 -66 6825 -66 231 -68 14077 -66 1787 -66 1547 -64 2617 -66 2925 -66 1723 -132 1529 -66 865 -166 827 -198 431 -66 495 -66 1121 -198 1327 -100 397 -130 557 -66 97 -100 261 -98 723 -98 557 -98 463 -98 463 -100 325 -66 3703 -100 465 -198 1123 -98 2545 -66 361 -66 857 -64 3455 -132 663 -98 1991 -200 825 -100 919 -98 893 -164 1749 -66 7759 -132 3321 -66 1807 -132 527 -66 393 -100 817 -130 657 -164 1485 -98 2367 -66 4171 -100 197 -130 3665 -134 1059 -132 597 -66 533 -66 1023 -98 1253 -134 2021 -100 231 -100 233 -66 197 -66 199 -66 1961 -168 729 -100 531 -100 461 -98 1361 -100 11161 -100 659 -166 229 -98 1675 -98 1027 -100 2063 -298 431 -100 99 -134 1059 -66 199 -100 763 -134 231 -66 233 -102 1761 -98 331 -68 757 -132 425 -64 457 -132 99 -66 2091 -66 567 -164 2121 -68 2125 -132 595 -200 759 -102 797 -132 1345 -66 429 -132 1019 -66 195 -66 791 -68 1227 -68 797 -132 1591 -200 199 -134 165 -66 1053 -66 559 -98 853 -164 825 -100 329 -98 891 -196 689 -132 657 -100 2341 -98 1119 -66 1883 -100 2607 -100 467 -100 1067 -164 6935 -66 2409 -132 855 -66 1809 -98 1119 -164 65 -66 199 -100 233 -132 931 -132 563 -66 1393 -132 567 -66 301 -68 1295 -66 529 -98 793 -66 131 -134 533 -132 827 -132 731 -332 1251 -98 921 -98 327 -198 361 -234 529 -66 1577 -132 97 -134 199 -100 1099 -68 1193 -132 991 -100 953 -98 2895 -166 1679 -98 161 -130 129 -66 1019 -100 261 -264 531 -100 263 -134 299 -68 495 -98 831 -100 531 -66 1357 -100 2051 -100 229 -98 829 -66 427 -66 859 -134 995 -68 665 -66 1793 -134 361 -100 2349 -66 331 -100 197 -66 1591 -66 959 -66 431 -234 2219 -332 661 -66 1487 -100 3381 -68 261 -164 463 -134 3377 -68 1127 -134 691 -66 529 -132 99 -66 6687 -98 889 -132 197 -164 725 -100 963 -66 2947 -132 327 -132 889 -66 393 -98 1581 -100 193 -130 97 -66 293 -66 1675 -100 1887 -98 2017 -100 597 -66 293 -98 557 -100 259 -98 985 -100 1727 -100 165 -100 301 -232 329 -100 533 -98 727 -100 761 -66 961 -68 2759 -100 2019 -66 855 -230 859 -98 1215 -98 1887 -98 131 -98 819 -166 227 -130 723 -132 625 -66 501 -66 429 -66 831 -66 1291 -66 331 -132 431 -132 1389 -100 265 -166 1461 -66 1907 -490 911 -962 409 -508 919 -944 419 -486 913 -526 915 -480 925 -488 911 -488 943 -476 925 -486 947 -462 945 -482 933 -484 951 -460 977 -440 967 -484 945 -468 945 -466 975 -450 983 +RAW_Data: -444 977 -458 975 -456 975 -444 965 -940 485 -430 967 -928 487 -448 981 -910 489 -446 963 -944 485 -430 975 -930 489 -912 485 -896 487 -452 977 -916 509 -454 977 -922 479 -448 985 -15898 487 -456 973 -926 493 -448 1001 -918 481 -484 981 -478 979 -450 1013 -476 977 -450 1017 -476 983 -448 999 -480 985 -484 983 -478 985 -484 981 -480 983 -476 1001 -474 979 -496 973 -486 1015 -476 977 -476 1005 -484 973 -486 1007 -920 505 -456 1011 -918 509 -458 1011 -950 497 -452 1011 -920 507 -458 1007 -950 477 -958 483 -942 481 -480 1003 -918 515 -446 1039 -922 505 -458 1007 -16154 501 -462 1013 -934 517 -474 999 -958 483 -478 993 -484 1037 -450 1027 -482 1027 -452 1037 -482 1025 -444 1035 -490 1009 -482 1013 -484 1001 -484 1039 -474 1003 -484 1045 -464 1011 -480 1049 -446 1037 -492 1007 -482 1013 -510 1005 -494 1005 -970 485 -482 1017 -974 473 -498 1007 -974 481 -486 1047 -948 479 -482 1051 -948 497 -952 519 -938 485 -482 1041 -946 517 -478 1013 -944 503 -472 415 -83640 97 -200 65 -632 131 -300 365 -364 231 -132 1061 -100 3047 -100 1393 -66 499 -66 1091 -66 333 -66 2353 -100 2273 -66 1427 -166 563 -132 1559 -132 427 -100 925 -98 13469 -100 2019 -98 821 -132 1097 -68 297 -100 897 -100 1129 -166 465 -166 961 -66 597 -100 165 -66 267 -100 201 -100 765 -134 297 -66 165 -66 3081 -100 1293 -100 1289 -136 233 -66 357 -66 1155 -166 295 -100 1197 -68 1089 -98 425 -132 1187 -100 523 -98 463 -98 197 -98 131 -98 493 -66 393 -98 2797 -164 359 -232 325 -66 229 -164 625 -98 1215 -164 425 -66 589 -98 195 -66 1083 -100 197 -68 1557 -66 1427 -66 525 -66 429 -132 863 -66 1129 -166 831 -98 265 -98 1183 -66 3157 -100 2735 -98 2819 -166 4645 -66 301 -68 1395 -132 1097 -100 897 -198 629 -200 1419 -132 493 -66 521 -132 697 -100 695 -66 459 -298 859 -66 559 -100 1029 -100 4113 -66 1167 -66 14017 -66 2123 -68 525 -132 861 -100 329 -66 399 -134 1523 -132 327 -64 691 -98 463 -132 1803 -132 853 -166 715 -66 953 -66 525 -98 723 -132 989 -132 461 -98 459 -164 2239 -66 1185 -66 589 -100 1945 -230 1483 -66 399 -66 265 -168 965 -66 197 -168 699 -68 1125 -68 529 -98 491 -66 987 -130 525 -168 397 -66 597 -100 561 -132 1353 -66 391 -132 393 -66 591 -98 557 -98 787 -66 463 -100 199 -134 395 -100 759 -66 295 -130 261 -98 229 -100 99 -100 1595 -66 699 -100 499 -66 595 -98 327 -132 957 -132 331 -100 493 -100 1313 -66 295 -132 197 -198 1279 +RAW_Data: -66 9461 -100 329 -68 27921 -66 24331 -68 13415 -66 6439 -98 133 -66 4193 -98 395 -66 653 -66 983 -66 163 -66 955 -132 1791 -66 861 -100 363 -132 1659 -132 667 -166 467 -134 429 -166 265 -66 4065 -98 293 -98 3183 -130 555 -98 163 -162 259 -100 661 -100 7057 -100 931 -100 1297 -66 2559 -98 1193 -100 333 -100 563 -132 65 -100 793 -66 855 -64 659 -100 929 -102 893 -132 689 -66 3475 -68 1361 -198 331 -134 691 -66 295 -66 425 -164 731 -266 921 -100 599 -100 165 -66 227 -98 1091 -66 263 -66 1215 -100 227 -164 657 -66 953 -132 359 -66 1845 -66 1779 -132 753 -164 393 -66 731 -66 1195 -66 533 -66 797 -132 1623 -98 1281 -100 493 -98 659 -98 2417 -166 799 -132 1259 -100 559 -134 595 -166 199 -66 1461 -198 865 -100 459 -66 463 -166 165 -100 497 -66 1097 -66 1579 -100 1449 -98 885 -98 263 -100 1097 -132 627 -68 329 -132 487 -132 427 -132 361 -66 525 -98 687 -66 1161 -100 263 -66 729 -100 229 -98 559 -66 1213 -100 1015 -66 795 -66 5475 -66 4043 -66 1683 -166 1151 -132 429 -98 1447 -68 261 -98 985 -100 429 -100 1289 -198 2269 -132 7999 -98 1591 -132 3233 -66 861 -66 2087 -98 557 -98 719 -66 981 -98 563 -100 199 -100 523 -100 2319 -134 833 -100 495 -132 197 -66 295 -64 989 -66 1059 -198 7343 -66 2023 -66 963 -66 593 -66 2401 -100 491 -100 959 -66 297 -134 999 -132 99 -68 3609 -230 97 -198 1911 -66 265 -100 1195 -132 633 -132 595 -66 1381 -66 491 -66 1681 -100 297 -100 1827 -132 2269 -100 1351 -132 1513 -66 1225 -134 231 -66 1523 -100 363 -200 1227 -66 2943 -66 923 -134 2249 -66 1809 -100 1121 -132 265 -66 827 -98 199 -66 201 -100 3279 -100 565 -132 1689 -66 395 -66 2979 -134 1065 -66 367 -168 3585 -200 463 -100 563 -66 97 -166 2293 -66 265 -134 1255 -132 2401 -66 1579 -166 365 -100 861 -298 261 -98 761 -66 363 -132 657 -130 63 -130 557 -66 131 -130 2041 -100 233 -66 1791 -100 925 -134 265 -100 1063 -100 301 -168 661 -66 657 -64 263 -64 197 -66 1853 -100 663 -98 231 -66 731 -100 5539 -166 197 -68 1423 -134 361 -68 1727 -68 929 -100 1397 -134 1885 -66 1661 -66 265 -66 1183 -66 295 -166 263 -166 165 -66 329 -66 465 -100 1159 -134 697 -100 2443 -100 393 -98 1093 -66 953 -296 787 -132 425 -66 2019 -66 461 -98 1201 -100 397 -132 3551 -100 1431 -264 725 -330 1455 -66 263 -100 531 -296 499 -100 265 -100 163 -66 1145 -132 1313 -98 2101 -98 261 -132 1083 -66 5403 +RAW_Data: -66 2223 -66 11583 -66 131 -66 5071 -66 3723 -132 1415 -132 6905 -64 9685 -102 4739 -66 3355 -66 5301 -98 29993 -508 897 -950 437 -490 909 -974 423 -510 935 -486 925 -508 943 -490 937 -494 947 -482 941 -484 979 -440 979 -456 1003 -462 975 -460 971 -458 977 -468 973 -484 975 -472 971 -450 1011 -452 1003 -446 983 -480 979 -450 1017 -908 487 -472 971 -944 471 -450 999 -944 485 -468 977 -918 493 -448 1011 -934 499 -920 487 -914 487 -452 1011 -912 521 -446 1009 -904 517 -468 1007 -16000 531 -444 1009 -908 519 -468 1009 -912 515 -466 1009 -452 1021 -466 1011 -450 1019 -480 1017 -448 1045 -448 1019 -460 1041 -450 1019 -480 1019 -450 1039 -474 1001 -480 1021 -484 1005 -476 1015 -480 1017 -484 1011 -486 1017 -464 1041 -446 1047 -922 503 -458 1037 -946 513 -442 1047 -938 503 -480 1023 -916 537 -450 1049 -926 521 -904 519 -942 519 -450 1055 -910 519 -486 1033 -916 519 -486 1029 -16258 533 -464 1015 -940 515 -456 1053 -946 511 -482 1051 -434 1075 -442 1075 -448 1065 -440 1065 -450 1049 -480 1067 -462 1041 -446 1075 -450 1063 -460 1053 -480 1047 -450 1075 -446 1079 -452 1055 -478 1051 -448 1067 -444 1065 -480 753 -66842 99 -1090 465 -332 131 -68 131 -134 99 -132 167 -200 429 -100 1809 -132 2385 -230 265 -102 597 -134 1025 -66 365 -100 361 -66 825 -168 1331 -100 797 -132 431 -132 299 -198 661 -168 501 -100 463 -164 329 -66 559 -98 391 -98 1085 -198 1939 -66 1871 -164 2251 -134 493 -66 719 -198 361 -98 361 -64 197 -132 391 -164 691 -300 489 -98 2139 -66 1413 -66 1875 -196 557 -66 263 -132 1359 -66 1397 -66 631 -100 793 -132 723 -100 65 -66 529 -134 463 -68 789 -100 227 -66 923 -100 2649 -166 363 -66 395 -200 295 -130 1757 -68 2057 -100 1023 -66 359 -66 391 -132 1679 -66 359 -66 1217 -98 663 -98 463 -100 821 -98 165 -98 1589 -132 2367 -98 559 -132 1079 -100 9617 -66 3669 -134 1787 -68 1679 -132 361 -66 555 -100 661 -66 1523 -100 2057 -198 1025 -66 4177 -100 165 -66 265 -132 465 -134 299 -232 265 -100 1125 -132 1461 -132 1295 -100 499 -132 367 -68 263 -66 331 -66 365 -100 1643 -130 197 -132 997 -98 867 -98 1191 -100 2945 -100 2339 -98 1779 -66 295 -132 597 -66 165 -100 665 -100 463 -66 331 -66 593 -100 459 -68 489 -164 855 -66 261 -64 163 -100 4449 -100 859 -100 699 -132 199 -100 1685 -66 301 -132 2317 -68 231 -100 827 -66 1749 -132 99 -64 1185 -100 329 -100 1253 -66 1127 -98 827 -198 363 -132 265 -134 365 -66 297 -66 1125 -66 261 +RAW_Data: -266 29863 -66 2443 -66 5113 -100 5947 -21026 99 -134 301 -132 199 -132 131 -266 163 -196 131 -66 365 -66 465 -98 13819 -98 525 -98 329 -100 893 -66 1259 -66 431 -98 427 -130 1051 -392 463 -200 795 -164 399 -66 1489 -66 1377 -100 1423 -132 597 -100 689 -68 1559 -100 2263 -100 1327 -98 1059 -98 497 -66 595 -132 265 -66 299 -66 199 -66 563 -134 627 -66 165 -134 889 -66 2751 -232 893 -264 231 -66 299 -132 467 -132 861 -68 1263 -164 795 -66 2601 -100 429 -66 1525 -66 961 -98 265 -98 997 -66 233 -68 695 -100 697 -66 795 -66 1195 -66 1223 -68 2173 -66 467 -66 827 -66 535 -68 697 -100 1221 -166 165 -100 365 -132 723 -66 829 -132 2091 -232 265 -66 195 -66 459 -262 499 -100 461 -68 759 -100 1087 -66 259 -164 2845 -66 1365 -98 561 -200 331 -168 201 -166 1397 -198 197 -66 697 -68 1713 -68 293 -134 1317 -66 593 -328 395 -100 499 -132 2251 -100 563 -134 333 -134 1921 -134 1187 -68 561 -132 933 -66 797 -100 631 -100 399 -132 929 -66 2769 -66 851 -130 2047 -66 265 -100 7219 -66 1987 -66 299 -98 2199 -134 1063 -98 2843 -98 655 -132 231 -66 1123 -198 2137 -64 327 -66 3183 -66 1127 -66 631 -100 263 -102 3173 -132 267 -68 1289 -98 1593 -66 2415 -66 1185 -66 359 -132 1051 -66 2169 -66 427 -98 395 -132 793 -98 293 -166 727 -134 131 -100 1287 -98 427 -98 687 -164 823 -64 853 -66 865 -100 763 -66 2025 -100 959 -66 1891 -64 793 -100 763 -66 729 -166 99 -98 399 -134 763 -100 4203 -66 1321 -230 4023 -98 1053 -66 985 -98 1383 -66 3559 -164 1515 -100 2899 -66 797 -134 1169 -100 3055 -134 1615 -66 429 -100 495 -64 1583 -134 923 -66 921 -66 723 -68 1359 -98 787 -98 425 -100 393 -64 1189 -98 263 -98 491 -100 1455 -98 +RAW_Data: -202 531 -66 531 -66 1093 -66 1389 -66 1551 -134 2699 -66 1291 -132 65 -64 657 -98 1083 -164 393 -98 1359 -134 1461 -66 393 -100 561 -130 2113 -132 597 -66 431 -102 1759 -302 985 -66 235 -100 1395 -66 901 -66 1061 -100 463 -66 5673 -66 227 -66 225 -66 855 -66 1581 -132 2503 -100 657 -66 2535 -98 259 -64 1015 -66 231 -132 1197 -66 827 -166 9641 -66 1823 -132 1565 -132 299 -66 797 -66 1631 -132 327 -132 2227 -232 433 -68 499 -100 1793 -66 1161 -132 525 -66 129 -100 361 -66 1765 -132 229 -66 491 -132 2255 -100 3043 -332 299 -100 499 -100 267 -68 2967 -66 991 -100 729 -100 633 -66 529 -98 825 -100 1033 -100 331 -66 723 -100 725 -264 2987 -68 825 -66 2601 -134 333 -100 3181 -134 1059 -100 299 -134 3279 -100 1221 -132 659 -66 3157 -98 1595 -132 1561 -98 201 -134 465 -66 1843 -130 589 -66 1413 -66 331 -100 333 -66 661 -100 265 -68 201 -234 1027 -166 297 -100 1161 -132 1561 -134 629 -66 431 -66 1025 -98 427 -198 1527 -66 793 -66 1903 -66 131 -130 1285 -66 299 -134 397 -98 229 -132 499 -132 4747 -100 2355 -100 263 -132 1915 -132 1749 -132 759 -66 2253 -100 4545 -66 391 -100 521 -100 1083 -100 929 -134 565 -66 2355 -66 1331 -66 167 -100 465 -100 1727 -132 633 -330 433 -66 897 -132 165 -134 331 -98 627 -66 231 -66 167 -66 1397 -66 729 -132 1397 -68 165 -66 1627 -134 2187 -66 231 -134 795 -200 6469 -232 829 -66 3929 -66 891 -98 1977 -100 525 -68 859 -66 921 -264 1029 -68 959 -134 1555 -66 259 -100 687 -66 429 -264 663 -66 1559 -100 1127 -100 2327 -132 1913 -64 4193 -132 293 -98 99 -100 5613 -132 1351 -66 1545 -66 1677 -66 295 -64 1943 -100 595 -132 1959 -166 765 -66 1389 -100 823 -66 1749 -66 1217 -100 597 -100 297 -66 2019 -98 165 -100 4165 -100 67 -100 2477 -262 295 -66 919 -200 3555 -66 229 -66 2531 -98 557 -66 2525 -66 1463 -100 1293 -68 197 -68 1391 -66 1421 -66 595 -164 327 -68 2285 -66 593 -98 99 -68 463 -98 1063 -100 165 -68 99 -100 631 -66 1085 -66 859 -98 6599 -66 1429 -66 233 -66 397 -98 231 -132 1975 -132 333 -66 131 -134 3373 -100 4277 -66 1363 -232 2893 -166 3133 -64 951 -66 2815 -100 425 -98 327 -66 599 -68 1031 -98 133 -68 633 -68 429 -100 1129 -66 327 -130 2679 -66 1321 -100 463 -200 367 -98 667 -66 493 -132 885 -98 2183 -166 559 -98 981 -66 3201 -164 593 -66 493 -130 1923 -166 565 -100 2421 -98 461 -66 1427 -130 1955 -64 197 -66 1643 +RAW_Data: -132 2291 -66 3057 -68 2521 -166 333 -134 503 -400 3235 -66 2329 -68 995 -100 333 -100 97 -166 1757 -100 397 -100 165 -66 2755 -132 297 -134 163 -100 565 -100 1793 -100 1813 -162 1293 -98 97 -66 999 -66 1763 -68 261 -68 2391 -100 765 -364 859 -100 1855 -98 1399 -230 463 -134 301 -198 397 -100 961 -68 431 -134 695 -202 133 -100 365 -66 925 -98 165 -66 365 -132 663 -98 4573 -134 1479 -66 1019 -66 629 -66 233 -68 201 -66 569 -66 295 -134 1755 -296 3199 -100 3261 -168 3373 -132 1425 -100 759 -66 895 -98 201 -100 265 -166 99 -66 695 -66 1091 -66 855 -168 299 -100 229 -164 589 -66 521 -66 655 -134 329 -98 493 -200 429 -66 929 -66 673 -100 953 -66 823 -66 1283 -66 1979 -68 233 -66 1547 -164 589 -132 597 -66 131 -66 265 -100 761 -200 759 -66 689 -332 263 -100 1227 -68 1067 -164 2945 -100 959 -100 995 -100 399 -100 1193 -100 625 -66 399 -66 3021 -134 393 -66 4805 -66 1095 -68 231 -332 399 -166 1663 -68 561 -66 927 -98 1085 -164 1155 -98 627 -66 265 -132 263 -130 2211 -66 2159 -66 1029 -264 2669 -66 295 -66 8747 -100 329 -232 625 -134 429 -68 1329 -168 1355 -98 987 -66 1545 -98 1015 -98 699 -134 133 -134 1263 -66 4687 -166 8299 -66 1349 -434 933 -906 443 -452 949 -894 441 -480 909 -486 907 -456 947 -448 949 -434 969 -454 931 -460 941 -448 933 -450 979 -450 945 -450 935 -458 935 -486 927 -456 947 -450 951 -482 945 -428 975 -446 967 -452 955 -458 945 -912 485 -434 971 -902 481 -450 949 -926 451 -478 941 -920 481 -450 949 -920 473 -450 955 -916 471 -452 981 -918 449 -486 945 -910 483 -924 473 -15780 479 -450 967 -948 449 -482 943 -944 485 -468 941 -484 979 -446 1001 -444 999 -446 967 -484 969 -482 979 -478 947 -484 985 -470 973 -458 983 -492 971 -458 979 -494 971 -458 983 -494 973 -458 981 -498 975 -458 1013 -466 973 -952 475 -458 973 -950 489 -450 1011 -916 481 -478 1001 -918 481 -478 1001 -916 481 -478 1001 -920 483 -480 983 -946 479 -458 1013 -932 485 -952 479 -16040 493 -476 1009 -912 515 -464 1007 -910 517 -464 1007 -450 1001 -488 1001 -484 1011 -450 1019 -458 1039 -450 1031 -454 1005 -484 1009 -458 1015 -476 1009 -478 1035 -462 1015 -468 1007 -480 1001 -486 1015 -460 1041 -450 1017 -484 1019 -482 1009 -952 477 -494 1003 -944 485 -478 1013 -944 519 -482 1013 -942 487 -482 1013 -946 487 -484 1015 -944 487 -484 1015 -946 519 -454 1019 -942 505 -952 487 -16238 517 -468 1007 -942 521 -482 1011 -944 519 +RAW_Data: -450 1019 -482 1035 -480 1033 -460 1047 -476 1017 -484 1007 -484 1051 -484 1027 -452 1039 -478 1035 -458 1049 -480 1017 -480 1035 -480 1035 -472 1047 -484 1027 -454 1039 -480 1033 -488 1031 -488 1009 -962 521 -486 1017 -966 485 -490 1015 -139210 229 -98 461 -364 165 -334 131 -168 2121 -66 1049 -66 1215 -166 297 -136 1449 -100 3877 -100 1495 -234 331 -64 1345 -262 393 -100 529 -132 2921 -164 1223 -132 1807 -66 765 -66 397 -98 3405 -132 2123 -230 231 -66 2541 -100 2489 -98 4397 -132 461 -98 293 -64 991 -66 1125 -166 401 -100 131 -100 99 -100 265 -100 2555 -100 499 -98 1361 -134 265 -166 895 -100 2253 -100 1057 -100 129 -296 1147 -198 197 -66 1163 -66 1935 -98 1675 -66 1103 -100 891 -100 989 -164 1019 -66 2967 -68 1293 -166 3161 -66 133 -264 1065 -100 731 -66 1693 -66 529 -100 165 -68 865 -66 825 -232 1117 -196 2401 -66 3051 -296 229 -132 1843 -132 1687 -68 1119 -68 299 -68 97 -66 4741 -66 197 -200 2319 -100 1097 -66 3765 -66 131 -100 695 -132 2753 -66 2287 -100 1129 -68 331 -98 1433 -132 893 -100 465 -100 801 -66 529 -66 1515 -264 393 -98 263 -66 1831 -166 3533 -100 633 -100 1051 -100 331 -98 795 -134 959 -132 1229 -100 627 -132 2517 -66 165 -98 131 -66 2301 -166 163 -134 465 -66 2767 -66 1019 -66 401 -134 397 -232 893 -66 397 -66 833 -66 199 -66 303 -66 2775 -66 2069 -98 1841 -100 399 -66 793 -98 2793 -68 3769 -100 867 -66 861 -100 399 -66 1859 -100 631 -132 755 -100 689 -66 163 -64 2045 -64 2191 -102 1127 -68 727 -68 625 -164 1381 -66 1153 -132 1115 -98 1017 -100 491 -100 593 -132 991 -98 1415 -98 4813 -66 331 -98 131 -102 1847 -98 197 -68 263 -100 3265 -66 431 -100 493 -98 435 -134 133 -68 1185 -134 395 -100 131 -66 399 -134 767 -134 1125 -66 429 -198 3185 -100 2261 -66 523 -230 2475 -168 1297 -66 3243 -66 1853 -100 1657 -66 459 -66 827 -100 263 -66 303 -234 197 -166 1167 -100 2299 -66 1329 -68 461 -100 763 -132 3819 -366 757 -66 591 -164 621 -98 1445 -100 2155 -100 231 -100 631 -68 1161 -66 131 -166 67 -98 1915 -166 1891 -66 1261 -68 999 -164 165 -132 133 -168 2695 -68 1055 -198 97 -98 229 -66 229 -66 1215 -66 885 -100 303 -132 297 -164 619 -198 459 -64 989 -66 229 -66 597 -134 693 -64 1255 -100 65 -132 331 -66 199 -98 529 -100 2831 -98 1259 -66 4855 -100 1163 -166 299 -66 395 -98 3141 -66 1319 -66 2139 -100 161 -132 261 -130 821 -200 263 -134 931 -330 65 -98 99 -134 793 +RAW_Data: -66 597 -100 231 -68 167 -66 1659 -100 733 -66 1631 -100 165 -66 199 -66 233 -166 165 -100 1925 -68 595 -198 1785 -134 2177 -134 131 -66 1049 -98 3087 -132 195 -64 589 -66 397 -134 329 -66 2565 -164 327 -100 689 -64 1775 -100 5183 -132 1187 -66 329 -66 395 -132 165 -98 261 -98 1247 -64 1217 -66 927 -66 997 -66 199 -98 1419 -66 531 -166 1231 -66 697 -100 97 -66 563 -66 161 -264 3205 -200 525 -98 293 -100 291 -100 133 -66 759 -66 659 -100 983 -64 523 -130 431 -166 919 -66 1097 -100 1757 -66 1119 -66 917 -98 2647 -166 1247 -66 165 -264 1189 -100 899 -134 597 -68 2323 -66 1893 -66 1095 -100 533 -64 965 -100 1817 -130 1215 -66 1879 -64 821 -164 1117 -132 263 -132 131 -66 557 -66 431 -132 661 -100 1183 -98 629 -100 1679 -132 259 -66 623 -98 431 -66 399 -164 923 -100 297 -66 165 -166 2521 -198 99 -66 431 -132 1225 -66 1063 -68 131 -136 631 -66 163 -100 99 -298 965 -68 465 -68 465 -298 2545 -134 2639 -230 1489 -66 299 -66 1991 -234 65 -132 693 -134 429 -102 101 -68 461 -66 3333 -64 1229 -68 333 -66 265 -66 885 -64 3163 -100 467 -66 2651 -164 1221 -100 1527 -66 1259 -134 431 -232 1259 -100 6029 -164 297 -98 1151 -66 1415 -100 5289 -66 2467 -100 493 -132 495 -200 1121 -66 129 -66 757 -166 327 -130 5477 -66 1227 -230 395 -100 265 -132 497 -132 1133 -132 361 -100 1051 -164 3089 -132 1583 -100 65 -68 2315 -100 529 -132 2157 -68 1257 -66 1975 -98 427 -98 1347 -66 719 -164 857 -66 165 -66 1029 -132 297 -132 467 -100 731 -130 1985 -98 199 -166 899 -100 1391 -166 3425 -100 261 -132 721 -66 4845 -98 1193 -68 1225 -66 721 -100 1015 -64 983 -66 557 -130 693 -98 99 -64 1091 -98 197 -100 2321 -66 431 -134 727 -66 467 -102 891 -98 167 -134 2619 -66 393 -64 97 -100 589 -98 1583 -164 301 -68 1481 -98 295 -98 959 -66 365 -98 1253 -66 231 -100 1255 -132 1813 -132 1645 -100 361 -132 395 -100 427 -164 1197 -98 1001 -100 861 -66 1161 -98 195 -100 197 -66 1429 -66 663 -66 1427 -98 665 -66 699 -100 663 -66 855 -196 161 -100 361 -98 823 -66 227 -66 621 -132 1853 -230 461 -230 623 -100 557 -98 229 -98 133 -134 1291 -66 533 -166 627 -134 195 -134 593 -64 591 -66 1019 -66 1049 -262 297 -100 2921 -66 133 -66 963 -134 165 -100 diff --git a/core/furi/check.c b/core/furi/check.c index 5ea76614..b59e490c 100644 --- a/core/furi/check.c +++ b/core/furi/check.c @@ -71,4 +71,4 @@ FURI_NORETURN void furi_halt(const char* message) { furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n"); furi_hal_console_puts("\033[0m\r\n"); __furi_halt(); -} \ No newline at end of file +} diff --git a/core/furi/check.h b/core/furi/check.h index adea4039..4165c3c2 100644 --- a/core/furi/check.h +++ b/core/furi/check.h @@ -14,7 +14,10 @@ extern "C" { #ifdef FURI_DEBUG #define furi_assert(__e) ((__e) ? (void)0 : furi_crash("furi_assert failed\r\n")) #else -#define furi_assert(__e) ((void)0) +#define furi_assert(__e) \ + do { \ + ((void)(__e)); \ + } while(0) #endif /** Crash system */ diff --git a/core/furi/common_defines.h b/core/furi/common_defines.h index 9c4f7b18..5b0e6971 100644 --- a/core/furi/common_defines.h +++ b/core/furi/common_defines.h @@ -40,11 +40,6 @@ extern "C" { #define CLAMP(x, upper, lower) (MIN(upper, MAX(x, lower))) #endif -// need some common semantics for those two -#ifndef SIZEOF_ARRAY -#define SIZEOF_ARRAY(arr) (sizeof(arr) / sizeof(arr[0])) -#endif - #ifndef COUNT_OF #define COUNT_OF(x) (sizeof(x) / sizeof(x[0])) #endif diff --git a/core/furi/memmgr.c b/core/furi/memmgr.c index 457520d9..01cf573e 100644 --- a/core/furi/memmgr.c +++ b/core/furi/memmgr.c @@ -1,4 +1,5 @@ #include "memmgr.h" +#include "common_defines.h" #include extern void* pvPortMalloc(size_t xSize); @@ -60,17 +61,21 @@ size_t memmgr_get_minimum_free_heap(void) { } void* __wrap__malloc_r(struct _reent* r, size_t size) { + UNUSED(r); return pvPortMalloc(size); } void __wrap__free_r(struct _reent* r, void* ptr) { + UNUSED(r); vPortFree(ptr); } void* __wrap__calloc_r(struct _reent* r, size_t count, size_t size) { + UNUSED(r); return calloc(count, size); } void* __wrap__realloc_r(struct _reent* r, void* ptr, size_t size) { + UNUSED(r); return realloc(ptr, size); } diff --git a/core/furi/memmgr_heap.c b/core/furi/memmgr_heap.c index 8544092e..618d7e74 100644 --- a/core/furi/memmgr_heap.c +++ b/core/furi/memmgr_heap.c @@ -37,6 +37,7 @@ #include "memmgr_heap.h" #include "check.h" #include +#include #include #include #include @@ -205,6 +206,7 @@ static inline void traceMALLOC(void* pointer, size_t size) { #undef traceFREE static inline void traceFREE(void* pointer, size_t size) { + UNUSED(size); osThreadId_t thread_id = osThreadGetId(); if(thread_id && memmgr_heap_thread_trace_depth == 0) { memmgr_heap_thread_trace_depth++; diff --git a/core/furi/stdglue.c b/core/furi/stdglue.c index 4e727202..1eccafc9 100644 --- a/core/furi/stdglue.c +++ b/core/furi/stdglue.c @@ -93,9 +93,11 @@ bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) } void __malloc_lock(struct _reent* REENT) { + UNUSED(REENT); vTaskSuspendAll(); } void __malloc_unlock(struct _reent* REENT) { + UNUSED(REENT); xTaskResumeAll(); } diff --git a/core/furi/thread.h b/core/furi/thread.h index ea1da27a..83e6bb93 100644 --- a/core/furi/thread.h +++ b/core/furi/thread.h @@ -160,4 +160,4 @@ int32_t furi_thread_get_return_code(FuriThread* thread); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/core/furi/valuemutex.c b/core/furi/valuemutex.c index 77a99937..6010c963 100644 --- a/core/furi/valuemutex.c +++ b/core/furi/valuemutex.c @@ -55,4 +55,4 @@ bool write_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeou if(!release_mutex(valuemutex, value)) return false; return true; -} \ No newline at end of file +} diff --git a/core/furi/valuemutex.h b/core/furi/valuemutex.h index 84a08093..63dfac61 100644 --- a/core/furi/valuemutex.h +++ b/core/furi/valuemutex.h @@ -146,4 +146,4 @@ void consumer_app(void* _p) { } } ``` -*/ \ No newline at end of file +*/ diff --git a/docker-compose.yml b/docker-compose.yml index 68aa14c1..39aca411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,4 +9,4 @@ services: volumes: - .:/project - /dev/bus/usb:/dev/bus/usb - working_dir: '/project' \ No newline at end of file + working_dir: '/project' diff --git a/documentation/OTA.md b/documentation/OTA.md new file mode 100644 index 00000000..472e81b6 --- /dev/null +++ b/documentation/OTA.md @@ -0,0 +1,105 @@ +# Executing code from RAM + +In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. System image executing in RAM has full write access to whole Flipper's flash memory — something that's not possible when running main code from same flash. + +We leverage that boot mode to perform OTA firmware updates, including operations on radio stack running on second MCU core. + + +# How does Flipper OTA work? + +Installation of OTA updates goes through 3 stages: + +## 1. Backing up internal storage (`/int/`) + +It is a special partition of Flipper's flash memory, taking up all available space not used by firmware code. Newer versions of firmware may be of different size, and simply installing them would cause flash repartitioning and data loss. + +So, before taking any action upon the firmware, we back up current configuration from `/int/` into a plain tar archive on SD card. + + +## 2. Performing device update + +For that, main firmware loads an updater image - a customized build of main Flipper firmware — into RAM and runs it. Updater performs operations on system flash that are described by an Update manifest file. + +First, if there's a Radio stack image bundled with the update, updater compares its version with currently installed one. If they don't match, updater performs stack deinstallation followed by writing and installing a new one. The installation itself is performed by proprietary software, FUS, running on Core2, and leads to a series of system restarts. + +Then updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU. + +After that, updater loads a `.dfu` file with firmware to be flashed, checks its integrity using CRC32, writes it to system flash and validates written data. + + +## 3. Restoring internal storage and updating resources + +After performing operations on flash memory, system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents. + +If update package contains an additional resources archive, it is extracted onto SD card. + + +# Update manifest + +Update packages come with a manifest that contains a description of its contents. The manifest is in Flipper File Format — a simple text file, comprised of key-value pairs. + +## Mandatory fields + +Update manifest must contain the following keys in given order: + +* __Filetype__: a constant string, "Flipper firmware upgrade configuration"; + +* __Version__: manifest version. Current value is 2; + +* __Info__: arbitraty string, describing package contents; + +* __Target__: hardware revision the package is built for; + +* __Loader__: file name of stage 2 loader that is executed from RAM; + +* __Loader CRC__: CRC32 of loader file. Note that it is represented in little-endian hex. + +## Optional fields + +Other fields may have empty values, is such case updater skips all operations related to such values. + +* __Radio__: file name of radio stack image, provided by STM; + +* __Radio address__: address to install the radio stack at. It is specified in Release Notes by STM; + +* __Radio version__: Radio major, minor and sub versions followed by branch, release, and stack type packed into 6 hex-encoded bytes; + +* __Radio CRC__: CRC32 of radio image; + +* __Resources__: file name of TAR acrhive with resources to be extracted on SD card; + +* __OB reference__, __OB mask__, __OB write mask__: reference values for validating and correcting option bytes. + + +# OTA update error codes + +We designed the OTA update process to be as fail-safe as possible. We don't start any risky operation before validating all related pieces of data to ensure we don't leave the device in partially updated, or bricked, state. + +Even if something goes wrong, Updater gives you an option to retry failed operations, and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes an operation that failed, and `YY` contains extra details on its progress where the error occured. + +| Stage description | Code | Progress | Description | +|:-----------------------:|-------:|------------|--------------------------------------------| +| Loading update manifest | **1** | **13** | Updater reported hardware version mismatch | +| | | **20** | Failed to get saved manifest path | +| | | **30** | Failed to load manifest | +| | | **40** | Unsupported update package version | +| | | **50** | Package has mismatching HW target | +| | | **60** | Missing DFU file | +| | | **80** | Missing radio firmware file | +| Checking DFU file | **2** | **0** | Error opening DFU file | +| | | **1-98** | Error reading DFU file | +| | | **99-100** | Corrupted DFU file | +| Writing flash | **3** | **0-100** | Block read/write error | +| Validating flash | **4** | **0-100** | Block read/write error | +| Checking radio FW | **5** | **0-99** | Error reading radio firmware file | +| | | **100** | CRC mismatch | +| Uninstalling radio FW | **6** | **0** | SHCI Install command error | +| | | **80** | Error awaiting command status | +| Writing radio FW | **7** | **0-100** | Block read/write error | +| Installing radio FW | **8** | **0** | SHCI Install command error | +| | | **80** | Error awaiting command status | +| Radio is updating | **9** | **10** | Error waiting for operation completion | +| Validating opt. bytes | **10** | **yy** | Option byte code | +| Backing up LFS | **11** | **0-100** | Block read/write error | +| Restoring LFS | **12** | **0-100** | Block read/write error | +| Updating resources | **13** | **0-100** | SD card read/write error | diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index c3b2117c..0204826a 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -2,6 +2,7 @@ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include +#pragma GCC diagnostic ignored "-Wredundant-decls" extern uint32_t SystemCoreClock; #endif diff --git a/firmware/targets/f7/Inc/stm32_assert.h b/firmware/targets/f7/Inc/stm32_assert.h new file mode 100644 index 00000000..3b0a543d --- /dev/null +++ b/firmware/targets/f7/Inc/stm32_assert.h @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * @file stm32_assert.h + * @author MCD Application Team + * @brief STM32 assert template file. + * This file should be copied to the application folder and renamed + * to stm32_assert.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32_ASSERT_H +#define STM32_ASSERT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ + +/* We're confident in the parameters we pass to LL functions, so we can skip asserts + * since they introduce significant bloat to debug builds */ + +#ifdef FURI_LL_DEBUG +#define assert_param furi_assert +#else +#define assert_param(__e) \ + do { \ + ((void)(__e)); \ + } while(0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ASSERT_H */ \ No newline at end of file diff --git a/firmware/targets/f7/Src/main.c b/firmware/targets/f7/Src/main.c index 1865f8d1..3de1c6ca 100644 --- a/firmware/targets/f7/Src/main.c +++ b/firmware/targets/f7/Src/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #define TAG "Main" @@ -68,16 +69,3 @@ void Error_Handler(void) { void abort() { furi_crash("AbortHandler"); } - -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t* file, uint32_t line) { - furi_crash("HAL assert failed"); -} -#endif /* USE_FULL_ASSERT */ diff --git a/firmware/targets/f7/Src/update.c b/firmware/targets/f7/Src/update.c index 4b3ee3ad..a91972e9 100644 --- a/firmware/targets/f7/Src/update.c +++ b/firmware/targets/f7/Src/update.c @@ -7,12 +7,14 @@ #include #include +#include #include #include -static FATFS* pfs = NULL; +#define FS_ROOT_PATH "/" +#define UPDATE_POINTER_FILE_PATH FS_ROOT_PATH UPDATE_MANIFEST_POINTER_FILE_NAME -static const char FS_ROOT_PATH[] = "/"; +static FATFS* pfs = NULL; #define CHECK_FRESULT(result) \ { \ @@ -99,41 +101,34 @@ static bool flipper_update_load_stage(const string_t work_dir, UpdateManifest* m return false; } -static bool flipper_update_get_work_directory(string_t out_dir) { - const uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); - if(update_index == 0) { - string_set(out_dir, UPDATE_DIR_DEFAULT_REL_PATH); - return true; - } - - DIR dir; - UINT entry_idx = 0; - FILINFO fno; - CHECK_FRESULT(f_opendir(&dir, UPDATE_DIR_DEFAULT_REL_PATH)); - string_set(out_dir, UPDATE_DIR_DEFAULT_REL_PATH); - - while(f_readdir(&dir, &fno) == FR_OK) { - entry_idx++; - if(fno.fname[0] == '\0') { - return false; - } - if(entry_idx == update_index) { - path_append(out_dir, fno.fname); - return true; - } - } - - string_reset(out_dir); - return false; -} - -static UpdateManifest* flipper_update_process_manifest(const string_t work_dir) { +static bool flipper_update_get_manifest_path(string_t out_path) { FIL file; FILINFO stat; + uint16_t size_read = 0; + char manifest_name_buf[UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN] = {0}; - string_t manifest_path; - string_init_set(manifest_path, work_dir); - path_append(manifest_path, UPDATE_MANIFEST_DEFAULT_NAME); + string_reset(out_path); + CHECK_FRESULT(f_stat(UPDATE_POINTER_FILE_PATH, &stat)); + CHECK_FRESULT(f_open(&file, UPDATE_POINTER_FILE_PATH, FA_OPEN_EXISTING | FA_READ)); + do { + if(f_read(&file, manifest_name_buf, UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN, &size_read) != + FR_OK) { + break; + } + + if((size_read == 0) || (size_read == UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) { + break; + } + string_set_str(out_path, manifest_name_buf); + string_right(out_path, strlen("/ext")); + } while(0); + f_close(&file); + return !string_empty_p(out_path); +} + +static UpdateManifest* flipper_update_process_manifest(const string_t manifest_path) { + FIL file; + FILINFO stat; CHECK_FRESULT(f_stat(string_get_cstr(manifest_path), &stat)); CHECK_FRESULT(f_open(&file, string_get_cstr(manifest_path), FA_OPEN_EXISTING | FA_READ)); @@ -163,7 +158,7 @@ static UpdateManifest* flipper_update_process_manifest(const string_t work_dir) } } while(false); - string_clear(manifest_path); + f_close(&file); free(manifest_data); return manifest; } @@ -173,22 +168,25 @@ void flipper_boot_update_exec() { return; } - string_t work_dir; + string_t work_dir, manifest_path; string_init(work_dir); + string_init(manifest_path); do { - if(!flipper_update_get_work_directory(work_dir)) { + if(!flipper_update_get_manifest_path(manifest_path)) { break; } - UpdateManifest* manifest = flipper_update_process_manifest(work_dir); + UpdateManifest* manifest = flipper_update_process_manifest(manifest_path); if(!manifest) { break; } + path_extract_dirname(string_get_cstr(manifest_path), work_dir); if(!flipper_update_load_stage(work_dir, manifest)) { update_manifest_free(manifest); } } while(false); + string_clear(manifest_path); string_clear(work_dir); free(pfs); } diff --git a/firmware/targets/f7/ble_glue/app_debug.h b/firmware/targets/f7/ble_glue/app_debug.h index e1bd65fc..92a54d75 100644 --- a/firmware/targets/f7/ble_glue/app_debug.h +++ b/firmware/targets/f7/ble_glue/app_debug.h @@ -35,4 +35,4 @@ void APPD_EnableCPU2(void); #endif /*__APP_DEBUG_H */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/ble_app.c b/firmware/targets/f7/ble_glue/ble_app.c index d76b4e7b..618e2b94 100644 --- a/firmware/targets/f7/ble_glue/ble_app.c +++ b/firmware/targets/f7/ble_glue/ble_app.c @@ -121,6 +121,7 @@ void ble_app_thread_stop() { } static int32_t ble_app_hci_thread(void* arg) { + UNUSED(arg); uint32_t flags = 0; while(1) { @@ -138,6 +139,7 @@ static int32_t ble_app_hci_thread(void* arg) { // Called by WPAN lib void hci_notify_asynch_evt(void* pdata) { + UNUSED(pdata); if(ble_app) { osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread); furi_assert(thread_id); @@ -146,12 +148,14 @@ void hci_notify_asynch_evt(void* pdata) { } void hci_cmd_resp_release(uint32_t flag) { + UNUSED(flag); if(ble_app) { osSemaphoreRelease(ble_app->hci_sem); } } void hci_cmd_resp_wait(uint32_t timeout) { + UNUSED(timeout); if(ble_app) { osSemaphoreAcquire(ble_app->hci_sem, osWaitForever); } diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index ec4a617b..6a100bea 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -349,6 +349,7 @@ void ble_glue_thread_stop() { // Wrap functions static int32_t ble_glue_shci_thread(void* context) { + UNUSED(context); uint32_t flags = 0; while(true) { diff --git a/firmware/targets/f7/ble_glue/ble_glue.h b/firmware/targets/f7/ble_glue/ble_glue.h index e5c2738d..fe43ae09 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.h +++ b/firmware/targets/f7/ble_glue/ble_glue.h @@ -121,4 +121,4 @@ BleGlueCommandResult ble_glue_fus_wait_operation(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c index 45191a5a..f2a1a96f 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -489,6 +489,7 @@ void gap_stop_advertising() { } static void gap_advetise_timer_callback(void* context) { + UNUSED(context); GapCommand command = GapCommandAdvLowPower; furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK); } @@ -587,6 +588,7 @@ void gap_thread_stop() { } static int32_t gap_app(void* context) { + UNUSED(context); GapCommand command; while(1) { osStatus_t status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever); diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c index 246eabf0..fc2924d4 100644 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c @@ -419,6 +419,7 @@ uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo) { */ uint8_t BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { + UNUSED(Timeout); // FIXME! uint32_t offset = 0; uint32_t addr; uint8_t retr = BSP_SD_ERROR; @@ -500,6 +501,7 @@ uint8_t BSP_SD_WriteBlocks( uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) { + UNUSED(Timeout); // FIXME! uint32_t offset = 0; uint32_t addr; uint8_t retr = BSP_SD_ERROR; diff --git a/firmware/targets/f7/fatfs/user_diskio.c b/firmware/targets/f7/fatfs/user_diskio.c index 94a7d4d3..b504fcd5 100644 --- a/firmware/targets/f7/fatfs/user_diskio.c +++ b/firmware/targets/f7/fatfs/user_diskio.c @@ -44,6 +44,7 @@ static volatile DSTATUS Stat = STA_NOINIT; static DSTATUS User_CheckStatus(BYTE lun) { + UNUSED(lun); Stat = STA_NOINIT; if(BSP_SD_GetCardState() == MSD_OK) { Stat &= ~STA_NOINIT; @@ -106,6 +107,7 @@ DSTATUS USER_initialize(BYTE pdrv) { */ DSTATUS USER_status(BYTE pdrv) { /* USER CODE BEGIN STATUS */ + UNUSED(pdrv); return Stat; /* USER CODE END STATUS */ } @@ -120,6 +122,7 @@ DSTATUS USER_status(BYTE pdrv) { */ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { /* USER CODE BEGIN READ */ + UNUSED(pdrv); DRESULT res = RES_ERROR; furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); @@ -151,6 +154,7 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { /* USER CODE BEGIN WRITE */ /* USER CODE HERE */ + UNUSED(pdrv); DRESULT res = RES_ERROR; furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); @@ -181,6 +185,7 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { #if _USE_IOCTL == 1 DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { /* USER CODE BEGIN IOCTL */ + UNUSED(pdrv); DRESULT res = RES_ERROR; BSP_SD_CardInfo CardInfo; @@ -228,4 +233,4 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { } #endif /* _USE_IOCTL == 1 */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/furi_hal/furi_hal_crc.h b/firmware/targets/f7/furi_hal/furi_hal_crc.h index 110e6c05..8abaaad1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_crc.h +++ b/firmware/targets/f7/furi_hal/furi_hal_crc.h @@ -32,4 +32,4 @@ uint32_t furi_hal_crc_feed(void* data, uint16_t length); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.h b/firmware/targets/f7/furi_hal/furi_hal_i2c_config.h index 03c0f1ca..a8fb9183 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.h +++ b/firmware/targets/f7/furi_hal/furi_hal_i2c_config.h @@ -28,4 +28,4 @@ extern FuriHalI2cBusHandle furi_hal_i2c_handle_external; #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_types.h b/firmware/targets/f7/furi_hal/furi_hal_i2c_types.h index 0f2b735e..13f36105 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_i2c_types.h +++ b/firmware/targets/f7/furi_hal/furi_hal_i2c_types.h @@ -48,4 +48,4 @@ struct FuriHalI2cBusHandle { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/firmware/targets/f7/furi_hal/furi_hal_info.c index bbb3907d..cf7140eb 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_info.c +++ b/firmware/targets/f7/furi_hal/furi_hal_info.c @@ -132,4 +132,4 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { out("protobuf_version_minor", string_get_cstr(value), true, context); string_clear(value); -} \ No newline at end of file +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index bf9ea18c..768a4bac 100755 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -240,6 +240,7 @@ void rfal_interrupt_callback_handler() { } void rfal_state_changed_callback(void* context) { + UNUSED(context); osEventFlagsSet(event, EVENT_FLAG_STATE_CHANGED); } @@ -289,7 +290,7 @@ bool furi_hal_nfc_emulate_nfca( buff_rx_len = 0; buff_tx_len = 0; uint32_t flag = osEventFlagsWait(event, EVENT_FLAG_ALL, osFlagsWaitAny, timeout); - if(flag == osErrorTimeout || flag == EVENT_FLAG_STOP) { + if(flag == osFlagsErrorTimeout || flag == EVENT_FLAG_STOP) { break; } bool data_received = false; diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index 8beb0d08..9dd7191f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -178,5 +179,9 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) { + UNUSED(xTask); + furi_hal_console_puts("\r\n\r\n stack overflow in "); + furi_hal_console_puts(pcTaskName); + furi_hal_console_puts("\r\n\r\n"); furi_crash("StackOverflow"); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/firmware/targets/f7/furi_hal/furi_hal_random.c index 5dfda2b2..cd019c0d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_random.c +++ b/firmware/targets/f7/furi_hal/furi_hal_random.c @@ -7,6 +7,8 @@ #include +#define TAG "FuriHalRandom" + uint32_t furi_hal_random_get() { while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID)) ; @@ -51,8 +53,13 @@ void furi_hal_random_fill_buf(uint8_t* buf, uint32_t len) { } void srand(unsigned seed) { + UNUSED(seed); } int rand() { return (furi_hal_random_get() & RAND_MAX); } + +long random() { + return (furi_hal_random_get() & RAND_MAX); +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index e548ffaf..4209e0cf 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -87,10 +88,19 @@ void furi_hal_resources_init_early() { SET_BIT(PWR->CR3, PWR_CR3_APC); // Hard reset USB + furi_hal_gpio_write(&gpio_usb_dm, 1); + furi_hal_gpio_write(&gpio_usb_dp, 1); furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain); furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain); furi_hal_gpio_write(&gpio_usb_dm, 0); furi_hal_gpio_write(&gpio_usb_dp, 0); + furi_hal_delay_us(5); // Device Driven disconnect: 2.5us + extra to compensate cables + furi_hal_gpio_write(&gpio_usb_dm, 1); + furi_hal_gpio_write(&gpio_usb_dp, 1); + furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeAnalog); + furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeAnalog); + furi_hal_gpio_write(&gpio_usb_dm, 0); + furi_hal_gpio_write(&gpio_usb_dp, 0); // External header pins furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index 69485307..f12edcb3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -10,7 +10,7 @@ extern "C" { #endif /* Input Related Constants */ -#define INPUT_DEBOUNCE_TICKS 20 +#define INPUT_DEBOUNCE_TICKS 30 /* Input Keys */ typedef enum { diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/firmware/targets/f7/furi_hal/furi_hal_rfid.c index 964bd12b..86fecc99 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.c @@ -152,6 +152,7 @@ void furi_hal_rfid_tim_read_stop() { } void furi_hal_rfid_tim_emulate(float freq) { + UNUSED(freq); // FIXME // basic PWM setup with needed freq and internal clock FURI_CRITICAL_ENTER(); LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); diff --git a/firmware/targets/f7/furi_hal/furi_hal_speaker.c b/firmware/targets/f7/furi_hal/furi_hal_speaker.c index 00186198..03a7f094 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_speaker.c +++ b/firmware/targets/f7/furi_hal/furi_hal_speaker.c @@ -20,15 +20,7 @@ void furi_hal_speaker_init() { &gpio_speaker, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16); } -void furi_hal_speaker_start(float frequency, float volume) { - if(volume == 0) { - return; - } - - if(volume < 0) volume = 0; - if(volume > 1) volume = 1; - volume = volume * volume * volume; - +static inline uint32_t furi_hal_speaker_calculate_autoreload(float frequency) { uint32_t autoreload = (SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER / frequency) - 1; if(autoreload < 2) { autoreload = 2; @@ -36,35 +28,65 @@ void furi_hal_speaker_start(float frequency, float volume) { autoreload = UINT16_MAX; } - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = FURI_HAL_SPEAKER_PRESCALER - 1; - TIM_InitStruct.Autoreload = autoreload; - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); + return autoreload; +} + +static inline uint32_t furi_hal_speaker_calculate_compare(float volume) { + if(volume < 0) volume = 0; + if(volume > 1) volume = 1; + volume = volume * volume * volume; #ifdef FURI_HAL_SPEAKER_NEW_VOLUME uint32_t compare_value = volume * FURI_HAL_SPEAKER_MAX_VOLUME; - uint32_t clip_value = volume * TIM_InitStruct.Autoreload / 2; + uint32_t clip_value = volume * LL_TIM_GetAutoReload(FURI_HAL_SPEAKER_TIMER) / 2; if(compare_value > clip_value) { compare_value = clip_value; } #else - uint32_t compare_value = volume * autoreload / 2; + uint32_t compare_value = volume * LL_TIM_GetAutoReload(FURI_HAL_SPEAKER_TIMER) / 2; #endif if(compare_value == 0) { compare_value = 1; } + return compare_value; +} + +void furi_hal_speaker_start(float frequency, float volume) { + if(volume <= 0) { + furi_hal_speaker_stop(); + return; + } + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + TIM_InitStruct.Prescaler = FURI_HAL_SPEAKER_PRESCALER - 1; + TIM_InitStruct.Autoreload = furi_hal_speaker_calculate_autoreload(frequency); + LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = compare_value; + TIM_OC_InitStruct.CompareValue = furi_hal_speaker_calculate_compare(volume); LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); } +void furi_hal_speaker_set_volume(float volume) { + if(volume <= 0) { + furi_hal_speaker_stop(); + return; + } + +#if FURI_HAL_SPEAKER_CHANNEL == LL_TIM_CHANNEL_CH1 + LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, furi_hal_speaker_calculate_compare(volume)); +#else +#error Invalid channel +#endif +} + void furi_hal_speaker_stop() { LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index 01cb3ae6..f8c5a2c7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -83,6 +83,7 @@ void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { } static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { + UNUSED(timeout); // FIXME while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY) ; while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)) diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_config.h b/firmware/targets/f7/furi_hal/furi_hal_spi_config.h index 3e4296a0..eab633a1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi_config.h +++ b/firmware/targets/f7/furi_hal/furi_hal_spi_config.h @@ -58,4 +58,4 @@ extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_types.h b/firmware/targets/f7/furi_hal/furi_hal_spi_types.h index 1fb1c02b..d2273f38 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi_types.h +++ b/firmware/targets/f7/furi_hal/furi_hal_spi_types.h @@ -61,4 +61,4 @@ struct FuriHalSpiBusHandle { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 956342ff..7f40a152 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -799,6 +799,9 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { } else { furi_hal_subghz_async_tx.duty_low += API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME; } + // This code must be invoked only once: when encoder starts with low level. + // Otherwise whole thing will crash. + furi_check(samples > 0); } uint32_t duration = level_duration_get_duration(ld); @@ -969,9 +972,9 @@ void furi_hal_subghz_stop_async_tx() { FURI_LOG_D( TAG, "Async TX Radio stats: on %0.0fus, off %0.0fus, DutyCycle: %0.0f%%", - (float)furi_hal_subghz_async_tx.duty_high, - (float)furi_hal_subghz_async_tx.duty_low, - duty_cycle); + (double)furi_hal_subghz_async_tx.duty_high, + (double)furi_hal_subghz_async_tx.duty_low, + (double)duty_cycle); furi_hal_subghz_state = SubGhzStateIdle; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index d41414f8..6a5e534e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -189,6 +189,9 @@ void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) { } static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); + UNUSED(ep); osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReset); if(usb.callback != NULL) { usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx); @@ -196,6 +199,9 @@ static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) { } static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); + UNUSED(ep); if((usb.if_cur != NULL) && (usb.connected == true)) { usb.connected = false; usb.if_cur->suspend(&udev); @@ -208,6 +214,9 @@ static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) { } static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); + UNUSED(ep); if((usb.if_cur != NULL) && (usb.connected == false)) { usb.connected = true; usb.if_cur->wakeup(&udev); @@ -220,6 +229,7 @@ static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) { } static int32_t furi_hal_usb_thread(void* context) { + UNUSED(context); bool usb_request_pending = false; uint8_t usb_wait_time = 0; FuriHalUsbInterface* if_new = NULL; diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c index 807f1634..69a7fb3c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c @@ -429,6 +429,7 @@ FuriHalUsbInterface usb_cdc_dual = { }; static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { + UNUSED(ctx); usb_dev = dev; cdc_if_cur = intf; @@ -515,6 +516,7 @@ int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { } static void cdc_on_wakeup(usbd_device* dev) { + UNUSED(dev); connected = true; for(uint8_t i = 0; i < IF_NUM_MAX; i++) { if(callbacks[i] != NULL) { @@ -524,6 +526,7 @@ static void cdc_on_wakeup(usbd_device* dev) { } static void cdc_on_suspend(usbd_device* dev) { + UNUSED(dev); connected = false; for(uint8_t i = 0; i < IF_NUM_MAX; i++) { cdc_ctrl_line_state[i] = 0; @@ -534,6 +537,8 @@ static void cdc_on_suspend(usbd_device* dev) { } static void cdc_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); uint8_t if_num = 0; if(ep == CDC0_RXD_EP) if_num = 0; @@ -547,6 +552,8 @@ static void cdc_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { } static void cdc_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); uint8_t if_num = 0; if(ep == CDC0_TXD_EP) if_num = 0; @@ -629,6 +636,7 @@ static usbd_respond cdc_ep_config(usbd_device* dev, uint8_t cfg) { /* Control requests handler */ static usbd_respond cdc_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) { + UNUSED(callback); /* CDC control requests */ uint8_t if_num = 0; if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c index 55825dd9..aae4dd4f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c @@ -375,6 +375,7 @@ static void* hid_set_string_descr(char* str) { } static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { + UNUSED(intf); FuriHalUsbHidConfig* cfg = (FuriHalUsbHidConfig*)ctx; if(hid_semaphore == NULL) hid_semaphore = osSemaphoreNew(1, 1, NULL); usb_dev = dev; @@ -419,17 +420,23 @@ static void hid_deinit(usbd_device* dev) { } static void hid_on_wakeup(usbd_device* dev) { - if(hid_connected == false) { + UNUSED(dev); + if(!hid_connected) { hid_connected = true; - if(callback != NULL) callback(true, cb_ctx); + if(callback != NULL) { + callback(true, cb_ctx); + } } } static void hid_on_suspend(usbd_device* dev) { - if(hid_connected == true) { + UNUSED(dev); + if(hid_connected) { hid_connected = false; osSemaphoreRelease(hid_semaphore); - if(callback != NULL) callback(false, cb_ctx); + if(callback != NULL) { + callback(false, cb_ctx); + } } } @@ -450,6 +457,7 @@ static bool hid_send_report(uint8_t report_id) { } static void hid_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); if(event == usbd_evt_eptx) { osSemaphoreRelease(hid_semaphore); } else { @@ -484,6 +492,7 @@ static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) { /* Control requests handler */ static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) { + UNUSED(callback); /* HID control requests */ if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) && diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c b/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c index 37d879ed..a8041086 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c @@ -159,14 +159,18 @@ bool furi_hal_hid_u2f_is_connected() { void furi_hal_hid_u2f_set_callback(HidU2fCallback cb, void* ctx) { if(callback != NULL) { - if(hid_u2f_connected == true) callback(HidU2fDisconnected, cb_ctx); + if(hid_u2f_connected == true) { + callback(HidU2fDisconnected, cb_ctx); + } } callback = cb; cb_ctx = ctx; if(callback != NULL) { - if(hid_u2f_connected == true) callback(HidU2fConnected, cb_ctx); + if(hid_u2f_connected == true) { + callback(HidU2fConnected, cb_ctx); + } } } @@ -186,7 +190,11 @@ FuriHalUsbInterface usb_hid_u2f = { }; static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { - if(hid_u2f_semaphore == NULL) hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL); + UNUSED(intf); + UNUSED(ctx); + if(hid_u2f_semaphore == NULL) { + hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL); + } usb_dev = dev; usbd_reg_config(dev, hid_u2f_ep_config); @@ -201,15 +209,21 @@ static void hid_u2f_deinit(usbd_device* dev) { } static void hid_u2f_on_wakeup(usbd_device* dev) { + UNUSED(dev); hid_u2f_connected = true; - if(callback != NULL) callback(HidU2fConnected, cb_ctx); + if(callback != NULL) { + callback(HidU2fConnected, cb_ctx); + } } static void hid_u2f_on_suspend(usbd_device* dev) { - if(hid_u2f_connected == true) { + UNUSED(dev); + if(hid_u2f_connected) { hid_u2f_connected = false; osSemaphoreRelease(hid_u2f_semaphore); - if(callback != NULL) callback(HidU2fDisconnected, cb_ctx); + if(callback != NULL) { + callback(HidU2fDisconnected, cb_ctx); + } } } @@ -227,10 +241,18 @@ uint32_t furi_hal_hid_u2f_get_request(uint8_t* data) { } static void hid_u2f_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { - if(callback != NULL) callback(HidU2fRequest, cb_ctx); + UNUSED(dev); + UNUSED(event); + UNUSED(ep); + if(callback != NULL) { + callback(HidU2fRequest, cb_ctx); + } } static void hid_u2f_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { + UNUSED(dev); + UNUSED(event); + UNUSED(ep); osSemaphoreRelease(hid_u2f_semaphore); } @@ -268,6 +290,7 @@ static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg) { /* Control requests handler */ static usbd_respond hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) { + UNUSED(callback); /* HID control requests */ if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) && diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index e580c978..7abee281 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -205,7 +205,7 @@ const char* furi_hal_version_get_model_name() { return "Flipper Zero"; } -const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { +FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { if(*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) { return FuriHalVersionOtpVersionEmpty; } else { @@ -228,27 +228,27 @@ const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { } } -const uint8_t furi_hal_version_get_hw_version() { +uint8_t furi_hal_version_get_hw_version() { return furi_hal_version.board_version; } -const uint8_t furi_hal_version_get_hw_target() { +uint8_t furi_hal_version_get_hw_target() { return furi_hal_version.board_target; } -const uint8_t furi_hal_version_get_hw_body() { +uint8_t furi_hal_version_get_hw_body() { return furi_hal_version.board_body; } -const FuriHalVersionColor furi_hal_version_get_hw_color() { +FuriHalVersionColor furi_hal_version_get_hw_color() { return furi_hal_version.board_color; } -const uint8_t furi_hal_version_get_hw_connect() { +uint8_t furi_hal_version_get_hw_connect() { return furi_hal_version.board_connect; } -const FuriHalVersionRegion furi_hal_version_get_hw_region() { +FuriHalVersionRegion furi_hal_version_get_hw_region() { return furi_hal_version.board_region; } @@ -266,11 +266,11 @@ const char* furi_hal_version_get_hw_region_name() { return "R??"; } -const FuriHalVersionDisplay furi_hal_version_get_hw_display() { +FuriHalVersionDisplay furi_hal_version_get_hw_display() { return furi_hal_version.board_display; } -const uint32_t furi_hal_version_get_hw_timestamp() { +uint32_t furi_hal_version_get_hw_timestamp() { return furi_hal_version.timestamp; } diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/firmware/targets/f7/stm32wb55xx_flash.ld index f742ecc1..1d0e916b 100644 --- a/firmware/targets/f7/stm32wb55xx_flash.ld +++ b/firmware/targets/f7/stm32wb55xx_flash.ld @@ -135,6 +135,7 @@ SECTIONS _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ + *(*_DRIVER_CONTEXT) . = ALIGN(4); _edata = .; /* define a global symbol at data end */ @@ -158,7 +159,7 @@ SECTIONS } >RAM1 /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : + ._user_heap_stack(NOLOAD): { . = ALIGN(8); __heap_start__ = .; @@ -173,7 +174,7 @@ SECTIONS { __free_flash_start__ = .; . = ORIGIN(FLASH) + LENGTH(FLASH); - } >FLASH + } >FLASH /* Remove information from the standard libraries */ /DISCARD/ : diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 6410ba13..8e58a71c 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -18,7 +18,10 @@ endif MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections +# Warnings configuration +CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion + +CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions @@ -35,6 +38,7 @@ ASM_SOURCES += $(MXPROJECT_DIR)/startup_stm32wb55xx_cm4.s CUBE_DIR = ../lib/STM32CubeWB CFLAGS += \ -DUSE_FULL_LL_DRIVER \ + -DUSE_FULL_ASSERT \ -DHAVE_FREERTOS CFLAGS += \ -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ diff --git a/firmware/targets/furi_hal_include/furi_hal_random.h b/firmware/targets/furi_hal_include/furi_hal_random.h index fa549d23..ee69326f 100644 --- a/firmware/targets/furi_hal_include/furi_hal_random.h +++ b/firmware/targets/furi_hal_include/furi_hal_random.h @@ -21,4 +21,4 @@ void furi_hal_random_fill_buf(uint8_t* buf, uint32_t len); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_sd.h b/firmware/targets/furi_hal_include/furi_hal_sd.h index 307a8721..e1c08a35 100644 --- a/firmware/targets/furi_hal_include/furi_hal_sd.h +++ b/firmware/targets/furi_hal_include/furi_hal_sd.h @@ -1,3 +1,4 @@ +#pragma once /** * @file furi_hal_sd.h * SD Card HAL API diff --git a/firmware/targets/furi_hal_include/furi_hal_speaker.h b/firmware/targets/furi_hal_include/furi_hal_speaker.h index 35c89fb6..67de41d9 100644 --- a/firmware/targets/furi_hal_include/furi_hal_speaker.h +++ b/firmware/targets/furi_hal_include/furi_hal_speaker.h @@ -12,6 +12,8 @@ void furi_hal_speaker_init(); void furi_hal_speaker_start(float frequency, float volume); +void furi_hal_speaker_set_volume(float volume); + void furi_hal_speaker_stop(); #ifdef __cplusplus diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h index 4819e82e..20c76223 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h @@ -347,4 +347,4 @@ bool furi_hal_hid_consumer_key_press(uint16_t button); * * @param button key code */ -bool furi_hal_hid_consumer_key_release(uint16_t button); \ No newline at end of file +bool furi_hal_hid_consumer_key_release(uint16_t button); diff --git a/lib/ST25RFAL002/platform.c b/lib/ST25RFAL002/platform.c index 2c624f6e..52ac843e 100644 --- a/lib/ST25RFAL002/platform.c +++ b/lib/ST25RFAL002/platform.c @@ -14,6 +14,7 @@ static volatile PlatformIrqCallback platform_irq_callback = NULL; static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; void nfc_isr(void* _ctx) { + UNUSED(_ctx); if(platform_irq_callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { osThreadFlagsSet(platform_irq_thread_id, 0x1); } diff --git a/lib/ST25RFAL002/source/rfal_t4t.c b/lib/ST25RFAL002/source/rfal_t4t.c index bcc5b8de..8592daf8 100644 --- a/lib/ST25RFAL002/source/rfal_t4t.c +++ b/lib/ST25RFAL002/source/rfal_t4t.c @@ -118,6 +118,7 @@ ReturnCode rfalT4TPollerComposeCAPDU(const rfalT4tCApduParam* apduParam) { } /* Check whether requested Lc fits */ +#pragma GCC diagnostic ignored "-Wtype-limits" if((uint16_t)apduParam->Lc > (uint16_t)(RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN - RFAL_T4T_LE_LEN)) { return ERR_PARAM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ diff --git a/lib/ST25RFAL002/source/st25r3916/st25r3916_com.c b/lib/ST25RFAL002/source/st25r3916/st25r3916_com.c index 71ded38f..40d65807 100644 --- a/lib/ST25RFAL002/source/st25r3916/st25r3916_com.c +++ b/lib/ST25RFAL002/source/st25r3916/st25r3916_com.c @@ -609,7 +609,8 @@ bool st25r3916CheckReg(uint8_t reg, uint8_t mask, uint8_t val) { /*******************************************************************************/ bool st25r3916IsRegValid(uint8_t reg) { - if(!(((int16_t)reg >= (int16_t)ST25R3916_REG_IO_CONF1) && +#pragma GCC diagnostic ignored "-Wtype-limits" + if(!(((int16_t)reg >= (int32_t)ST25R3916_REG_IO_CONF1) && (reg <= (ST25R3916_SPACE_B | ST25R3916_REG_IC_IDENTITY)))) { return false; } diff --git a/lib/ST25RFAL002/timer.h b/lib/ST25RFAL002/timer.h index c6719410..b5f5eb32 100644 --- a/lib/ST25RFAL002/timer.h +++ b/lib/ST25RFAL002/timer.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * @attention * @@ -38,7 +39,8 @@ * INCLUDES ****************************************************************************** */ -#include "platform.h" +#include +#include /* ****************************************************************************** diff --git a/lib/app-scened-template/file_worker.c b/lib/app-scened-template/file_worker.c index f32d10d7..3a742ff9 100644 --- a/lib/app-scened-template/file_worker.c +++ b/lib/app-scened-template/file_worker.c @@ -232,6 +232,7 @@ bool file_worker_write_hex(FileWorker* file_worker, const uint8_t* buffer, uint1 } void file_worker_show_error(FileWorker* file_worker, const char* error_text) { + UNUSED(file_worker); DialogsApp* dialogs = furi_record_open("dialogs"); DialogMessage* message = dialog_message_alloc(); @@ -251,6 +252,7 @@ bool file_worker_file_select( char* result, uint8_t result_size, const char* selected_filename) { + UNUSED(file_worker); DialogsApp* dialogs = furi_record_open("dialogs"); bool ret = dialog_file_select_show(dialogs, path, extension, result, result_size, selected_filename); @@ -259,6 +261,7 @@ bool file_worker_file_select( } bool file_worker_check_common_errors(FileWorker* file_worker) { + UNUSED(file_worker); //TODO remove /* TODO: [FL-1431] Add return value to file_parser.get_sd_api().check_error() and replace get_fs_info(). */ return true; diff --git a/lib/app-scened-template/generic_scene.hpp b/lib/app-scened-template/generic_scene.hpp index c9e823b2..979e9747 100644 --- a/lib/app-scened-template/generic_scene.hpp +++ b/lib/app-scened-template/generic_scene.hpp @@ -6,4 +6,4 @@ public: virtual ~GenericScene(){}; private: -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/record_controller.hpp b/lib/app-scened-template/record_controller.hpp index af8db58c..9dfa9657 100644 --- a/lib/app-scened-template/record_controller.hpp +++ b/lib/app-scened-template/record_controller.hpp @@ -43,4 +43,4 @@ public: private: const char* name; TRecordClass* value; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/scene_controller.hpp b/lib/app-scened-template/scene_controller.hpp index 7e4c5ec0..678f6c0d 100644 --- a/lib/app-scened-template/scene_controller.hpp +++ b/lib/app-scened-template/scene_controller.hpp @@ -141,7 +141,7 @@ public: * @param tick_length_ms tick event length in milliseconds */ void process( - uint32_t tick_length_ms = 100, + uint32_t /* tick_length_ms */ = 100, typename TApp::SceneType start_scene_index = TApp::SceneType::Start) { typename TApp::Event event; bool consumed; @@ -240,4 +240,4 @@ private: return scene_index; } -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/text_store.h b/lib/app-scened-template/text_store.h index 95329f6d..a01784fd 100644 --- a/lib/app-scened-template/text_store.h +++ b/lib/app-scened-template/text_store.h @@ -9,4 +9,4 @@ public: void set(const char* text...); const uint8_t text_size; char* text; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/typeindex_no_rtti.hpp b/lib/app-scened-template/typeindex_no_rtti.hpp index be350cc9..4ac52725 100644 --- a/lib/app-scened-template/typeindex_no_rtti.hpp +++ b/lib/app-scened-template/typeindex_no_rtti.hpp @@ -118,4 +118,4 @@ template <> struct std::hash { result_type operator()(argument_type const& t) const noexcept { return t.hash_code(); } -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/byte_input_vm.h b/lib/app-scened-template/view_modules/byte_input_vm.h index 8217b213..9a161012 100644 --- a/lib/app-scened-template/view_modules/byte_input_vm.h +++ b/lib/app-scened-template/view_modules/byte_input_vm.h @@ -34,4 +34,4 @@ public: private: ByteInput* byte_input; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/dialog_ex_vm.h b/lib/app-scened-template/view_modules/dialog_ex_vm.h index 5c3cf124..66c2b760 100644 --- a/lib/app-scened-template/view_modules/dialog_ex_vm.h +++ b/lib/app-scened-template/view_modules/dialog_ex_vm.h @@ -70,4 +70,4 @@ public: private: DialogEx* dialog_ex; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/generic_view_module.h b/lib/app-scened-template/view_modules/generic_view_module.h index 10f04dc3..8b74ea3a 100644 --- a/lib/app-scened-template/view_modules/generic_view_module.h +++ b/lib/app-scened-template/view_modules/generic_view_module.h @@ -7,4 +7,4 @@ public: virtual ~GenericViewModule(){}; virtual View* get_view() = 0; virtual void clean() = 0; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/popup_vm.h b/lib/app-scened-template/view_modules/popup_vm.h index 483f33a2..26650563 100644 --- a/lib/app-scened-template/view_modules/popup_vm.h +++ b/lib/app-scened-template/view_modules/popup_vm.h @@ -65,4 +65,4 @@ public: private: Popup* popup; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/submenu_vm.h b/lib/app-scened-template/view_modules/submenu_vm.h index 6dba936f..06541527 100644 --- a/lib/app-scened-template/view_modules/submenu_vm.h +++ b/lib/app-scened-template/view_modules/submenu_vm.h @@ -39,4 +39,4 @@ public: private: Submenu* submenu; -}; \ No newline at end of file +}; diff --git a/lib/app-scened-template/view_modules/text_input_vm.h b/lib/app-scened-template/view_modules/text_input_vm.h index 8fafe861..81799e48 100644 --- a/lib/app-scened-template/view_modules/text_input_vm.h +++ b/lib/app-scened-template/view_modules/text_input_vm.h @@ -38,4 +38,4 @@ public: private: TextInput* text_input; -}; \ No newline at end of file +}; diff --git a/lib/app-template/app_template.h b/lib/app-template/app_template.h index 3af491ef..7adcf2bf 100644 --- a/lib/app-template/app_template.h +++ b/lib/app-template/app_template.h @@ -110,4 +110,4 @@ template uint8_t AppTemplate::exit( template void AppTemplate::update_gui(void) { view_port_update(view_port); -} \ No newline at end of file +} diff --git a/lib/callback-connector/callback-connector.h b/lib/callback-connector/callback-connector.h index e98ee914..10fec3e2 100644 --- a/lib/callback-connector/callback-connector.h +++ b/lib/callback-connector/callback-connector.h @@ -96,4 +96,4 @@ template auto obtain_connector(Functor functor) { } } //end of cbc scope -#endif // CALLBACKCONNECTOR_H \ No newline at end of file +#endif // CALLBACKCONNECTOR_H diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index bf654b5d..18f3f028 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -47,7 +47,7 @@ bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, ui uint8_t checksum = bq27220_get_checksum(buffer, 4); buffer[0] = checksum; buffer[1] = 6; - ret = furi_hal_i2c_write_mem( + ret &= furi_hal_i2c_write_mem( handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT); furi_hal_delay_us(10000); @@ -62,13 +62,13 @@ bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv) { return true; } FURI_LOG_I(TAG, "Start updating battery profile"); - OperationStatus status = {}; + OperationStatus status = {0}; if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) { FURI_LOG_E(TAG, "Can't configure update"); return false; }; - while((status.CFGUPDATE != 1) && (timeout-- > 0)) { + while((status.CFGUPDATE != true) && (timeout-- > 0)) { bq27220_get_operation_status(handle, &status); } bq27220_set_parameter_u16(handle, AddressGaugingConfig, cedv->cedv_conf.gauge_conf_raw); diff --git a/lib/drivers/cc1101.h b/lib/drivers/cc1101.h index c35c823c..af1f1556 100644 --- a/lib/drivers/cc1101.h +++ b/lib/drivers/cc1101.h @@ -148,13 +148,6 @@ uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t */ void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]); -/** Set Power Amplifier level table, ramp - * - * @param handle - pointer to FuriHalSpiHandle - * @param value - array of power level values - */ -void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]); - /** Write FIFO * * @param handle - pointer to FuriHalSpiHandle @@ -177,4 +170,4 @@ uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* si #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/drivers/cc1101_regs.h b/lib/drivers/cc1101_regs.h index 30a680be..a326dc92 100644 --- a/lib/drivers/cc1101_regs.h +++ b/lib/drivers/cc1101_regs.h @@ -209,4 +209,4 @@ typedef struct { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/fatfs/ff.c b/lib/fatfs/ff.c index b0bd4366..85ab9736 100644 --- a/lib/fatfs/ff.c +++ b/lib/fatfs/ff.c @@ -1059,7 +1059,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluste break; } } - /* go to default */ + __attribute__ ((fallthrough)); #endif default: val = 1; /* Internal error */ @@ -5430,7 +5430,7 @@ FRESULT f_mkfs ( ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ } st = 1; /* Do not compress short run */ - /* go to next case */ + __attribute__ ((fallthrough)); case 1: ch = si++; /* Fill the short run */ if (--j == 0) st = 0; diff --git a/lib/fatfs/ff_gen_drv.c b/lib/fatfs/ff_gen_drv.c index ccd595bb..9fb51efa 100644 --- a/lib/fatfs/ff_gen_drv.c +++ b/lib/fatfs/ff_gen_drv.c @@ -79,6 +79,7 @@ uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path) */ uint8_t FATFS_UnLinkDriverEx(char *path, uint8_t lun) { + (void)lun; uint8_t DiskNum = 0; uint8_t ret = 1; diff --git a/lib/flipper_format/flipper_format.c b/lib/flipper_format/flipper_format.c index 01f54632..cee76701 100644 --- a/lib/flipper_format/flipper_format.c +++ b/lib/flipper_format/flipper_format.c @@ -584,4 +584,4 @@ bool flipper_format_insert_or_update_hex( } return result; -} \ No newline at end of file +} diff --git a/lib/flipper_format/flipper_format.h b/lib/flipper_format/flipper_format.h index 0f3c299d..49e3f936 100644 --- a/lib/flipper_format/flipper_format.h +++ b/lib/flipper_format/flipper_format.h @@ -622,4 +622,4 @@ bool flipper_format_insert_or_update_hex( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/flipper_format/flipper_format_i.h b/lib/flipper_format/flipper_format_i.h index a47d4131..55b06f9f 100644 --- a/lib/flipper_format/flipper_format_i.h +++ b/lib/flipper_format/flipper_format_i.h @@ -16,4 +16,4 @@ Stream* flipper_format_get_raw_stream(FlipperFormat* flipper_format); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/flipper_format/flipper_format_stream.c b/lib/flipper_format/flipper_format_stream.c index b3a08590..bd700849 100644 --- a/lib/flipper_format/flipper_format_stream.c +++ b/lib/flipper_format/flipper_format_stream.c @@ -276,7 +276,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa #ifndef FLIPPER_STREAM_LITE case FlipperStreamValueFloat: { const float* data = write_data->data; - string_printf(value, "%f", data[i]); + string_printf(value, "%f", (double)data[i]); }; break; #endif case FlipperStreamValueInt32: { @@ -295,7 +295,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa furi_crash("Unknown FF type"); } - if((i + 1) < write_data->data_size) { + if((size_t)(i + 1) < write_data->data_size) { string_cat(value, " "); } @@ -340,7 +340,7 @@ bool flipper_format_stream_read_value_line( string_t value; string_init(value); - for(uint16_t i = 0; i < data_size; i++) { + for(size_t i = 0; i < data_size; i++) { bool last = false; result = flipper_format_stream_read_value(stream, value, &last); if(result) { @@ -507,4 +507,4 @@ bool flipper_format_stream_write_comment_cstr(Stream* stream, const char* data) } while(false); return result; -} \ No newline at end of file +} diff --git a/lib/flipper_format/flipper_format_stream.h b/lib/flipper_format/flipper_format_stream.h index dc9fb5b3..6ac17322 100644 --- a/lib/flipper_format/flipper_format_stream.h +++ b/lib/flipper_format/flipper_format_stream.h @@ -92,4 +92,4 @@ bool flipper_format_stream_write_comment_cstr(Stream* stream, const char* data); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/flipper_format/flipper_format_stream_i.h b/lib/flipper_format/flipper_format_stream_i.h index 74cf8f1a..f3614900 100644 --- a/lib/flipper_format/flipper_format_stream_i.h +++ b/lib/flipper_format/flipper_format_stream_i.h @@ -31,4 +31,4 @@ bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool str #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/fnv1a-hash/fnv1a-hash.c b/lib/fnv1a-hash/fnv1a-hash.c index a5bfa206..69c675f3 100644 --- a/lib/fnv1a-hash/fnv1a-hash.c +++ b/lib/fnv1a-hash/fnv1a-hash.c @@ -7,4 +7,4 @@ uint32_t fnv1a_buffer_hash(const uint8_t* buffer, uint32_t length, uint32_t hash hash = (hash ^ buffer[i]) * 16777619ULL; } return hash; -} \ No newline at end of file +} diff --git a/lib/fnv1a-hash/fnv1a-hash.h b/lib/fnv1a-hash/fnv1a-hash.h index fbbdb5b8..3218cc27 100644 --- a/lib/fnv1a-hash/fnv1a-hash.h +++ b/lib/fnv1a-hash/fnv1a-hash.h @@ -36,4 +36,4 @@ inline uint32_t fnv1a_string_hash(const char* str) { } return hash; } -#endif \ No newline at end of file +#endif diff --git a/lib/heatshrink/heatshrink_encoder.c b/lib/heatshrink/heatshrink_encoder.c index 9cd2594c..98f27dff 100644 --- a/lib/heatshrink/heatshrink_encoder.c +++ b/lib/heatshrink/heatshrink_encoder.c @@ -232,6 +232,7 @@ HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse, break; case HSES_FLUSH_BITS: hse->state = st_flush_bit_buffer(hse, &oi); + /* fall through */ case HSES_DONE: return HSER_POLL_EMPTY; default: diff --git a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c index c39de09e..1d944285 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c @@ -12,7 +12,9 @@ static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder); static inline size_t consume_samples(uint32_t* array, size_t len, size_t shift) { furi_assert(len >= shift); len -= shift; - for(int i = 0; i < len; ++i) array[i] = array[i + shift]; + for(size_t i = 0; i < len; ++i) { + array[i] = array[i + shift]; + } return len; } @@ -83,8 +85,8 @@ static InfraredStatus infrared_common_decode_bits(InfraredCommonDecoder* decoder if(timings->min_split_time && !level) { if(timing > timings->min_split_time) { /* long low timing - check if we're ready for any of protocol modification */ - for(int i = 0; decoder->protocol->databit_len[i] && - (i < COUNT_OF(decoder->protocol->databit_len)); + for(size_t i = 0; decoder->protocol->databit_len[i] && + (i < COUNT_OF(decoder->protocol->databit_len)); ++i) { if(decoder->protocol->databit_len[i] == decoder->databit_cnt) { return InfraredStatusReady; @@ -153,8 +155,8 @@ InfraredStatus InfraredStatus infrared_common_decode_manchester(InfraredCommonDecoder* decoder, bool level, uint32_t timing) { furi_assert(decoder); - uint16_t bit = decoder->protocol->timings.bit1_mark; - uint16_t tolerance = decoder->protocol->timings.bit_tolerance; + uint32_t bit = decoder->protocol->timings.bit1_mark; + uint32_t tolerance = decoder->protocol->timings.bit_tolerance; bool* switch_detect = &decoder->switch_detect; furi_assert((*switch_detect == true) || (*switch_detect == false)); @@ -196,7 +198,7 @@ InfraredMessage* infrared_common_decoder_check_ready(InfraredCommonDecoder* deco InfraredMessage* message = NULL; bool found_length = false; - for(int i = 0; + for(size_t i = 0; decoder->protocol->databit_len[i] && (i < COUNT_OF(decoder->protocol->databit_len)); ++i) { if(decoder->protocol->databit_len[i] == decoder->databit_cnt) { @@ -280,7 +282,7 @@ void* infrared_common_decoder_alloc(const InfraredCommonProtocolSpec* protocol) furi_assert(protocol); /* protocol->databit_len[0] has to contain biggest value of bits that can be decoded */ - for(int i = 1; i < COUNT_OF(protocol->databit_len); ++i) { + for(size_t i = 1; i < COUNT_OF(protocol->databit_len); ++i) { furi_assert(protocol->databit_len[i] <= protocol->databit_len[0]); } diff --git a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c index 563c1e64..f755222d 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c @@ -146,7 +146,7 @@ void* infrared_common_encoder_alloc(const InfraredCommonProtocolSpec* protocol) } /* protocol->databit_len[0] has to contain biggest value of bits that can be decoded */ - for(int i = 1; i < COUNT_OF(protocol->databit_len); ++i) { + for(size_t i = 1; i < COUNT_OF(protocol->databit_len); ++i) { furi_assert(protocol->databit_len[i] <= protocol->databit_len[0]); } @@ -174,7 +174,7 @@ void infrared_common_encoder_reset(InfraredCommonEncoder* encoder) { uint8_t max_databit_len = 0; - for(int i = 0; i < COUNT_OF(encoder->protocol->databit_len); ++i) { + for(size_t i = 0; i < COUNT_OF(encoder->protocol->databit_len); ++i) { max_databit_len = MAX(max_databit_len, encoder->protocol->databit_len[i]); } diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index 5dfa9281..59b11d5c 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -123,7 +123,7 @@ const InfraredMessage* InfraredMessage* message = NULL; InfraredMessage* result = NULL; - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { if(infrared_encoder_decoder[i].decoder.decode) { message = infrared_encoder_decoder[i].decoder.decode(handler->ctx[i], level, duration); if(!result && message) { @@ -139,7 +139,7 @@ InfraredDecoderHandler* infrared_alloc_decoder(void) { InfraredDecoderHandler* handler = malloc(sizeof(InfraredDecoderHandler)); handler->ctx = malloc(sizeof(void*) * COUNT_OF(infrared_encoder_decoder)); - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { handler->ctx[i] = 0; if(infrared_encoder_decoder[i].decoder.alloc) handler->ctx[i] = infrared_encoder_decoder[i].decoder.alloc(); @@ -153,7 +153,7 @@ void infrared_free_decoder(InfraredDecoderHandler* handler) { furi_assert(handler); furi_assert(handler->ctx); - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { if(infrared_encoder_decoder[i].decoder.free) infrared_encoder_decoder[i].decoder.free(handler->ctx[i]); } @@ -163,7 +163,7 @@ void infrared_free_decoder(InfraredDecoderHandler* handler) { } void infrared_reset_decoder(InfraredDecoderHandler* handler) { - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { if(infrared_encoder_decoder[i].decoder.reset) infrared_encoder_decoder[i].decoder.reset(handler->ctx[i]); } @@ -175,7 +175,7 @@ const InfraredMessage* infrared_check_decoder_ready(InfraredDecoderHandler* hand InfraredMessage* message = NULL; InfraredMessage* result = NULL; - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { if(infrared_encoder_decoder[i].decoder.check_ready) { message = infrared_encoder_decoder[i].decoder.check_ready(handler->ctx[i]); if(!result && message) { @@ -209,7 +209,7 @@ void infrared_free_encoder(InfraredEncoderHandler* handler) { } static int infrared_find_index_by_protocol(InfraredProtocol protocol) { - for(int i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { + for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { if(infrared_encoder_decoder[i].get_protocol_spec(protocol)) { return i; } diff --git a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c index 10ff56da..3ad14a7a 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c @@ -20,7 +20,9 @@ bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder) { uint8_t address_inverse = decoder->data[1]; uint8_t command = decoder->data[2]; uint8_t command_inverse = decoder->data[3]; - if((command == (uint8_t)~command_inverse) && (address == (uint8_t)~address_inverse)) { + uint8_t inverse_command_inverse = (uint8_t)~command_inverse; + uint8_t inverse_address_inverse = (uint8_t)~address_inverse; + if((command == inverse_command_inverse) && (address == inverse_address_inverse)) { decoder->message.protocol = InfraredProtocolNEC; decoder->message.address = address; decoder->message.command = command; diff --git a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c index 9101cac1..13d3e536 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c @@ -60,8 +60,8 @@ InfraredStatus infrared_decoder_rc6_decode_manchester( uint32_t timing) { // 4th bit lasts 2x times more InfraredStatus status = InfraredStatusError; - uint16_t bit = decoder->protocol->timings.bit1_mark; - uint16_t tolerance = decoder->protocol->timings.bit_tolerance; + uint32_t bit = decoder->protocol->timings.bit1_mark; + uint32_t tolerance = decoder->protocol->timings.bit_tolerance; bool single_timing = MATCH_TIMING(timing, bit, tolerance); bool double_timing = MATCH_TIMING(timing, 2 * bit, tolerance); diff --git a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c index 4450ffd1..e8cd3b05 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c @@ -17,8 +17,9 @@ bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder) { uint8_t address2 = decoder->data[1]; uint8_t command = decoder->data[2]; uint8_t command_inverse = decoder->data[3]; + uint8_t inverse_command_inverse = (uint8_t)~command_inverse; - if((address1 == address2) && (command == (uint8_t)~command_inverse)) { + if((address1 == address2) && (command == inverse_command_inverse)) { decoder->message.command = command; decoder->message.address = address1; decoder->message.protocol = InfraredProtocolSamsung32; diff --git a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c index a6918cee..8ae9e371 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c @@ -38,7 +38,7 @@ InfraredStatus infrared_encoder_sirc_encode_repeat( bool* level) { furi_assert(encoder); - furi_assert(encoder->timings_encoded == (1 + 2 + encoder->bits_to_encode * 2 - 1)); + furi_assert(encoder->timings_encoded == (1u + 2 + encoder->bits_to_encode * 2 - 1)); furi_assert(encoder->timings_sum < INFRARED_SIRC_REPEAT_PERIOD); *duration = INFRARED_SIRC_REPEAT_PERIOD - encoder->timings_sum; diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 5711d2c0..71126c86 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -597,6 +597,7 @@ void infrared_worker_set_raw_signal( InfraredWorkerGetSignalResponse infrared_worker_tx_get_signal_steady_callback(void* context, InfraredWorker* instance) { + UNUSED(context); InfraredWorkerGetSignalResponse response = instance->tx.steady_signal_sent ? InfraredWorkerGetSignalResponseSame : InfraredWorkerGetSignalResponseNew; diff --git a/lib/lfs_config.h b/lib/lfs_config.h index a545551c..59b3c486 100644 --- a/lib/lfs_config.h +++ b/lib/lfs_config.h @@ -4,6 +4,9 @@ #ifdef FURI_NDEBUG #define LFS_NO_ASSERT +#define LFS_ASSERT(x) +#else +#define LFS_ASSERT furi_assert #endif #define LFS_TAG "Lfs" @@ -16,7 +19,6 @@ #define LFS_ERROR(...) FURI_LOG_E(LFS_TAG, __VA_ARGS__); -#define LFS_ASSERT furi_assert // Because crc #undef LFS_CONFIG diff --git a/lib/lib.mk b/lib/lib.mk index 1470c89f..cb58fade 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -4,7 +4,7 @@ LIB_DIR = $(PROJECT_ROOT)/lib CFLAGS += -I$(LIB_DIR) # Mlib containers -CFLAGS += -I$(LIB_DIR)/mlib +CFLAGS += -I$(LIB_DIR)/mlib -D'M_MEMORY_FULL(x)=abort()' # U8G2 display library U8G2_DIR = $(LIB_DIR)/u8g2 diff --git a/lib/libusb_stm32 b/lib/libusb_stm32 index fd58c2b0..6a88ec4d 160000 --- a/lib/libusb_stm32 +++ b/lib/libusb_stm32 @@ -1 +1 @@ -Subproject commit fd58c2b04710554626ac69d9fb5fa1211d1bcaf0 +Subproject commit 6a88ec4d7709ca8605b5ec3e609057c330ca2a70 diff --git a/lib/micro-ecc/asm_arm.inc b/lib/micro-ecc/asm_arm.inc index 688fdc75..43844da6 100644 --- a/lib/micro-ecc/asm_arm.inc +++ b/lib/micro-ecc/asm_arm.inc @@ -97,6 +97,7 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, } #define asm_add 1 +#pragma GCC diagnostic ignored "-Wredundant-decls" uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, diff --git a/lib/micro-ecc/curve-specific.inc b/lib/micro-ecc/curve-specific.inc index 0453b212..f5d3da84 100644 --- a/lib/micro-ecc/curve-specific.inc +++ b/lib/micro-ecc/curve-specific.inc @@ -542,6 +542,7 @@ static void mod_sqrt_secp224r1_rp(uECC_word_t *d1, /* Compute a = sqrt(a) (mod curve_p). */ /* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) { + (void)curve; bitcount_t i; uECC_word_t e1[num_words_secp224r1]; uECC_word_t f1[num_words_secp224r1]; diff --git a/lib/nfc_protocols/emv.c b/lib/nfc_protocols/emv.c index 81a05e35..8e14cf48 100644 --- a/lib/nfc_protocols/emv.c +++ b/lib/nfc_protocols/emv.c @@ -292,7 +292,7 @@ static bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplicati i += 2; } else if(emv_decode_search_tag_u16_r(EMV_TAG_COUNTRY_CODE, buff, &i)) { app->country_code = (buff[i] << 8) | buff[i + 1]; - i += 2; + i += 1; } } diff --git a/lib/nfc_protocols/mifare_classic.c b/lib/nfc_protocols/mifare_classic.c index c738accc..ace37bff 100644 --- a/lib/nfc_protocols/mifare_classic.c +++ b/lib/nfc_protocols/mifare_classic.c @@ -36,6 +36,7 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicReader* reader) { } bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { + UNUSED(ATQA1); if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08)) { return true; } else if((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) { @@ -52,6 +53,7 @@ bool mf_classic_get_type( uint8_t ATQA1, uint8_t SAK, MfClassicReader* reader) { + UNUSED(ATQA1); furi_assert(uid); furi_assert(reader); memset(reader, 0, sizeof(MfClassicReader)); @@ -204,7 +206,6 @@ bool mf_classic_read_block( MfClassicBlock* block) { furi_assert(tx_rx); furi_assert(crypto); - furi_assert(block_num < MF_CLASSIC_TOTAL_BLOCKS_MAX); furi_assert(block); bool read_block_success = false; diff --git a/lib/nfc_protocols/mifare_desfire.c b/lib/nfc_protocols/mifare_desfire.c index 6a9c13b6..4f02e839 100644 --- a/lib/nfc_protocols/mifare_desfire.c +++ b/lib/nfc_protocols/mifare_desfire.c @@ -444,4 +444,4 @@ bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFil out->contents = malloc(len); memcpy(out->contents, buf, len); return true; -} \ No newline at end of file +} diff --git a/lib/nfc_protocols/mifare_ultralight.h b/lib/nfc_protocols/mifare_ultralight.h index 1947f10a..858fc3ec 100644 --- a/lib/nfc_protocols/mifare_ultralight.h +++ b/lib/nfc_protocols/mifare_ultralight.h @@ -123,4 +123,4 @@ bool mf_ul_prepare_emulation_response( uint8_t* buff_tx, uint16_t* buff_tx_len, uint32_t* data_type, - void* context); \ No newline at end of file + void* context); diff --git a/lib/nfc_protocols/nfc_util.c b/lib/nfc_protocols/nfc_util.c index 69c13ed4..9de6f982 100644 --- a/lib/nfc_protocols/nfc_util.c +++ b/lib/nfc_protocols/nfc_util.c @@ -45,19 +45,3 @@ uint8_t nfc_util_even_parity32(uint32_t data) { uint8_t nfc_util_odd_parity8(uint8_t data) { return nfc_util_odd_byte_parity[data]; } - -void nfc_util_merge_data_and_parity( - uint8_t* data, - uint16_t data_len, - uint8_t* parity, - uint16_t parity_len, - uint8_t* res, - uint16_t* res_len); - -void nfc_util_split_data_and_parity( - uint8_t* data, - uint16_t data_len, - uint8_t* parity, - uint16_t parity_len, - uint8_t* res, - uint16_t* res_len); \ No newline at end of file diff --git a/lib/nfc_protocols/nfc_util.h b/lib/nfc_protocols/nfc_util.h index caeb20c9..d530badc 100644 --- a/lib/nfc_protocols/nfc_util.h +++ b/lib/nfc_protocols/nfc_util.h @@ -9,19 +9,3 @@ uint64_t nfc_util_bytes2num(uint8_t* src, uint8_t len); uint8_t nfc_util_even_parity32(uint32_t data); uint8_t nfc_util_odd_parity8(uint8_t data); - -void nfc_util_merge_data_and_parity( - uint8_t* data, - uint16_t data_len, - uint8_t* parity, - uint16_t parity_len, - uint8_t* res, - uint16_t* res_len); - -void nfc_util_split_data_and_parity( - uint8_t* data, - uint16_t data_len, - uint8_t* parity, - uint16_t parity_len, - uint8_t* res, - uint16_t* res_len); diff --git a/lib/nfc_protocols/nfca.c b/lib/nfc_protocols/nfca.c index fe001f88..81a6ddfc 100755 --- a/lib/nfc_protocols/nfca.c +++ b/lib/nfc_protocols/nfca.c @@ -52,4 +52,4 @@ bool nfca_emulation_handler( } return sleep; -} \ No newline at end of file +} diff --git a/lib/one_wire/ibutton/encoder/encoder_cyfral.h b/lib/one_wire/ibutton/encoder/encoder_cyfral.h index 1b0c3e12..4fc7be5e 100644 --- a/lib/one_wire/ibutton/encoder/encoder_cyfral.h +++ b/lib/one_wire/ibutton/encoder/encoder_cyfral.h @@ -51,4 +51,4 @@ void encoder_cyfral_get_pulse(EncoderCyfral* cyfral, bool* polarity, uint32_t* l #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/encoder/encoder_metakom.h b/lib/one_wire/ibutton/encoder/encoder_metakom.h index 2812dc12..50ff11a2 100644 --- a/lib/one_wire/ibutton/encoder/encoder_metakom.h +++ b/lib/one_wire/ibutton/encoder/encoder_metakom.h @@ -51,4 +51,4 @@ void encoder_metakom_get_pulse(EncoderMetakom* metakom, bool* polarity, uint32_t #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/ibutton_key.c b/lib/one_wire/ibutton/ibutton_key.c index c90d5f4a..c6d4466f 100644 --- a/lib/one_wire/ibutton/ibutton_key.c +++ b/lib/one_wire/ibutton/ibutton_key.c @@ -118,4 +118,4 @@ bool ibutton_key_dallas_crc_is_valid(iButtonKey* key) { bool ibutton_key_dallas_is_1990_key(iButtonKey* key) { return (key->data[0] == 0x01); -} \ No newline at end of file +} diff --git a/lib/one_wire/ibutton/ibutton_key.h b/lib/one_wire/ibutton/ibutton_key.h index f8286103..8d6732bc 100644 --- a/lib/one_wire/ibutton/ibutton_key.h +++ b/lib/one_wire/ibutton/ibutton_key.h @@ -142,4 +142,4 @@ bool ibutton_key_dallas_is_1990_key(iButtonKey* key); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/ibutton_key_command.h b/lib/one_wire/ibutton/ibutton_key_command.h index 3978ea51..88049d06 100644 --- a/lib/one_wire/ibutton/ibutton_key_command.h +++ b/lib/one_wire/ibutton/ibutton_key_command.h @@ -25,4 +25,4 @@ #define TM01_CMD_SWITCH_TO_CYFRAL 0xCA #define TM01_CMD_SWITCH_TO_METAKOM 0xCB -#define DS1990_CMD_READ_ROM 0x33 \ No newline at end of file +#define DS1990_CMD_READ_ROM 0x33 diff --git a/lib/one_wire/ibutton/ibutton_worker.c b/lib/one_wire/ibutton/ibutton_worker.c index 74734e75..82c3d688 100644 --- a/lib/one_wire/ibutton/ibutton_worker.c +++ b/lib/one_wire/ibutton/ibutton_worker.c @@ -9,6 +9,7 @@ typedef enum { iButtonMessageRead, iButtonMessageWrite, iButtonMessageEmulate, + iButtonMessageNotifyEmulate, } iButtonMessageType; typedef struct { @@ -145,6 +146,11 @@ void ibutton_worker_switch_mode(iButtonWorker* worker, iButtonWorkerMode mode) { ibutton_worker_modes[worker->mode_index].start(worker); } +void ibutton_worker_notify_emulate(iButtonWorker* worker) { + iButtonMessage message = {.type = iButtonMessageNotifyEmulate}; + furi_check(osMessageQueuePut(worker->messages, &message, 0, 0) == osOK); +} + void ibutton_worker_set_key_p(iButtonWorker* worker, iButtonKey* key) { worker->key_p = key; } @@ -183,6 +189,11 @@ static int32_t ibutton_worker_thread(void* thread_context) { ibutton_worker_set_key_p(worker, message.data.key); ibutton_worker_switch_mode(worker, iButtonWorkerEmulate); break; + case iButtonMessageNotifyEmulate: + if(worker->emulate_cb) { + worker->emulate_cb(worker->cb_ctx, true); + } + break; } } else if(status == osErrorTimeout) { ibutton_worker_modes[worker->mode_index].tick(worker); diff --git a/lib/one_wire/ibutton/ibutton_worker.h b/lib/one_wire/ibutton/ibutton_worker.h index 3350e05f..5c8b1fc3 100644 --- a/lib/one_wire/ibutton/ibutton_worker.h +++ b/lib/one_wire/ibutton/ibutton_worker.h @@ -110,4 +110,4 @@ void ibutton_worker_stop(iButtonWorker* worker); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/ibutton_worker_i.h b/lib/one_wire/ibutton/ibutton_worker_i.h index 14e5d39d..93755481 100644 --- a/lib/one_wire/ibutton/ibutton_worker_i.h +++ b/lib/one_wire/ibutton/ibutton_worker_i.h @@ -27,9 +27,9 @@ typedef enum { typedef struct { const uint32_t quant; - const void (*start)(iButtonWorker* worker); - const void (*tick)(iButtonWorker* worker); - const void (*stop)(iButtonWorker* worker); + void (*const start) (iButtonWorker* worker); + void (*const tick) (iButtonWorker* worker); + void (*const stop) (iButtonWorker* worker); } iButtonWorkerModeType; typedef enum { @@ -73,7 +73,8 @@ struct iButtonWorker { extern const iButtonWorkerModeType ibutton_worker_modes[]; void ibutton_worker_switch_mode(iButtonWorker* worker, iButtonWorkerMode mode); +void ibutton_worker_notify_emulate(iButtonWorker* worker); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/ibutton_worker_modes.c b/lib/one_wire/ibutton/ibutton_worker_modes.c index 7ee3a005..5ee76862 100644 --- a/lib/one_wire/ibutton/ibutton_worker_modes.c +++ b/lib/one_wire/ibutton/ibutton_worker_modes.c @@ -49,12 +49,15 @@ const iButtonWorkerModeType ibutton_worker_modes[] = { /*********************** IDLE ***********************/ void ibutton_worker_mode_idle_start(iButtonWorker* worker) { + UNUSED(worker); } void ibutton_worker_mode_idle_tick(iButtonWorker* worker) { + UNUSED(worker); } void ibutton_worker_mode_idle_stop(iButtonWorker* worker) { + UNUSED(worker); } /*********************** READ ***********************/ @@ -151,6 +154,7 @@ bool ibutton_worker_read_dallas(iButtonWorker* worker) { } void ibutton_worker_mode_read_start(iButtonWorker* worker) { + UNUSED(worker); furi_hal_power_enable_otg(); } @@ -172,6 +176,7 @@ void ibutton_worker_mode_read_tick(iButtonWorker* worker) { } void ibutton_worker_mode_read_stop(iButtonWorker* worker) { + UNUSED(worker); furi_hal_power_disable_otg(); } @@ -179,9 +184,7 @@ void ibutton_worker_mode_read_stop(iButtonWorker* worker) { static void onewire_slave_callback(void* context) { furi_assert(context); iButtonWorker* worker = context; - if(worker->emulate_cb != NULL) { - worker->emulate_cb(worker->cb_ctx, true); - } + ibutton_worker_notify_emulate(worker); } void ibutton_worker_emulate_dallas_start(iButtonWorker* worker) { @@ -251,6 +254,7 @@ void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { } void ibutton_worker_emulate_timer_stop(iButtonWorker* worker) { + UNUSED(worker); furi_hal_ibutton_emulate_stop(); } @@ -272,6 +276,7 @@ void ibutton_worker_mode_emulate_start(iButtonWorker* worker) { } void ibutton_worker_mode_emulate_tick(iButtonWorker* worker) { + UNUSED(worker); } void ibutton_worker_mode_emulate_stop(iButtonWorker* worker) { @@ -327,4 +332,4 @@ void ibutton_worker_mode_write_tick(iButtonWorker* worker) { void ibutton_worker_mode_write_stop(iButtonWorker* worker) { furi_hal_power_disable_otg(); onewire_host_stop(worker->host); -} \ No newline at end of file +} diff --git a/lib/one_wire/ibutton/ibutton_writer.h b/lib/one_wire/ibutton/ibutton_writer.h index 8e81cfd1..6dbdbb27 100644 --- a/lib/one_wire/ibutton/ibutton_writer.h +++ b/lib/one_wire/ibutton/ibutton_writer.h @@ -57,4 +57,4 @@ void ibutton_writer_stop(iButtonWriter* writer); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/pulse_protocols/protocol_cyfral.h b/lib/one_wire/ibutton/pulse_protocols/protocol_cyfral.h index 4a7c00e4..10305da1 100644 --- a/lib/one_wire/ibutton/pulse_protocols/protocol_cyfral.h +++ b/lib/one_wire/ibutton/pulse_protocols/protocol_cyfral.h @@ -35,4 +35,4 @@ PulseProtocol* protocol_cyfral_get_protocol(ProtocolCyfral* cyfral); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/ibutton/pulse_protocols/protocol_metakom.h b/lib/one_wire/ibutton/pulse_protocols/protocol_metakom.h index fbafc235..fdc45769 100644 --- a/lib/one_wire/ibutton/pulse_protocols/protocol_metakom.h +++ b/lib/one_wire/ibutton/pulse_protocols/protocol_metakom.h @@ -35,4 +35,4 @@ PulseProtocol* protocol_metakom_get_protocol(ProtocolMetakom* metakom); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/maxim_crc.c b/lib/one_wire/maxim_crc.c index bd89d3ad..a5d099b1 100644 --- a/lib/one_wire/maxim_crc.c +++ b/lib/one_wire/maxim_crc.c @@ -13,4 +13,4 @@ uint8_t maxim_crc8(const uint8_t* data, const uint8_t data_size, const uint8_t c } } return crc; -} \ No newline at end of file +} diff --git a/lib/one_wire/maxim_crc.h b/lib/one_wire/maxim_crc.h index 1b7e8498..4bab5714 100644 --- a/lib/one_wire/maxim_crc.h +++ b/lib/one_wire/maxim_crc.h @@ -11,4 +11,4 @@ uint8_t maxim_crc8(const uint8_t* data, const uint8_t data_size, const uint8_t c #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/one_wire_device.h b/lib/one_wire/one_wire_device.h index 4ff16790..fc687c7b 100644 --- a/lib/one_wire/one_wire_device.h +++ b/lib/one_wire/one_wire_device.h @@ -71,4 +71,4 @@ uint8_t* onewire_device_get_id_p(OneWireDevice* device); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/one_wire_host.c b/lib/one_wire/one_wire_host.c index fd8deaf8..1bb0a1cc 100644 --- a/lib/one_wire/one_wire_host.c +++ b/lib/one_wire/one_wire_host.c @@ -23,6 +23,7 @@ void onewire_host_free(OneWireHost* host) { } bool onewire_host_reset(OneWireHost* host) { + UNUSED(host); uint8_t r; uint8_t retries = 125; @@ -52,6 +53,7 @@ bool onewire_host_reset(OneWireHost* host) { } bool onewire_host_read_bit(OneWireHost* host) { + UNUSED(host); bool result; // drive low @@ -88,6 +90,7 @@ void onewire_host_read_bytes(OneWireHost* host, uint8_t* buffer, uint16_t count) } void onewire_host_write_bit(OneWireHost* host, bool value) { + UNUSED(host); if(value) { // drive low furi_hal_ibutton_pin_low(); @@ -120,10 +123,12 @@ void onewire_host_skip(OneWireHost* host) { } void onewire_host_start(OneWireHost* host) { + UNUSED(host); furi_hal_ibutton_start_drive(); } void onewire_host_stop(OneWireHost* host) { + UNUSED(host); furi_hal_ibutton_stop(); } diff --git a/lib/one_wire/one_wire_host.h b/lib/one_wire/one_wire_host.h index 21530640..5b55ee8d 100644 --- a/lib/one_wire/one_wire_host.h +++ b/lib/one_wire/one_wire_host.h @@ -118,4 +118,4 @@ uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSear #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/one_wire_slave.c b/lib/one_wire/one_wire_slave.c index e8cc5ac1..3c9a796d 100644 --- a/lib/one_wire/one_wire_slave.c +++ b/lib/one_wire/one_wire_slave.c @@ -37,6 +37,7 @@ struct OneWireSlave { /*********************** PRIVATE ***********************/ uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) { + UNUSED(bus); uint32_t start = DWT->CYCCNT; uint32_t time_ticks = time * furi_hal_delay_instructions_per_microsecond(); uint32_t time_captured; @@ -253,6 +254,7 @@ void onewire_slave_start(OneWireSlave* bus) { } void onewire_slave_stop(OneWireSlave* bus) { + UNUSED(bus); furi_hal_ibutton_stop(); furi_hal_ibutton_remove_interrupt(); } diff --git a/lib/one_wire/pulse_protocols/pulse_decoder.h b/lib/one_wire/pulse_protocols/pulse_decoder.h index 4e9f9d22..dbaef52b 100644 --- a/lib/one_wire/pulse_protocols/pulse_decoder.h +++ b/lib/one_wire/pulse_protocols/pulse_decoder.h @@ -67,4 +67,4 @@ void pulse_decoder_get_data(PulseDecoder* decoder, int32_t index, uint8_t* data, #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/pulse_protocols/pulse_glue.h b/lib/one_wire/pulse_protocols/pulse_glue.h index aa58f239..4954e271 100644 --- a/lib/one_wire/pulse_protocols/pulse_glue.h +++ b/lib/one_wire/pulse_protocols/pulse_glue.h @@ -23,4 +23,4 @@ void pulse_glue_pop(PulseGlue* pulse_glue, uint32_t* length, uint32_t* period); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/one_wire/pulse_protocols/pulse_protocol.c b/lib/one_wire/pulse_protocols/pulse_protocol.c index ac01ea92..76feba11 100644 --- a/lib/one_wire/pulse_protocols/pulse_protocol.c +++ b/lib/one_wire/pulse_protocols/pulse_protocol.c @@ -64,4 +64,4 @@ void pulse_protocol_get_data(PulseProtocol* protocol, uint8_t* data, size_t leng if(protocol->get_data_cb != NULL) { protocol->get_data_cb(protocol->context, data, length); } -} \ No newline at end of file +} diff --git a/lib/one_wire/pulse_protocols/pulse_protocol.h b/lib/one_wire/pulse_protocols/pulse_protocol.h index 01bc14a1..bfce0e76 100644 --- a/lib/one_wire/pulse_protocols/pulse_protocol.h +++ b/lib/one_wire/pulse_protocols/pulse_protocol.h @@ -119,4 +119,4 @@ void pulse_protocol_reset(PulseProtocol* protocol); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/qrcode/qrcode.c b/lib/qrcode/qrcode.c index cbbf4a47..fb5bd8a6 100644 --- a/lib/qrcode/qrcode.c +++ b/lib/qrcode/qrcode.c @@ -972,4 +972,4 @@ bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y) { uint32_t offset = y * qrcode->size + x; return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; -} \ No newline at end of file +} diff --git a/lib/qrcode/qrcode.h b/lib/qrcode/qrcode.h index bc3ccb59..6d637ba0 100644 --- a/lib/qrcode/qrcode.h +++ b/lib/qrcode/qrcode.h @@ -96,4 +96,4 @@ bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y); } #endif /* __cplusplus */ -#endif /* __QRCODE_H_ */ \ No newline at end of file +#endif /* __QRCODE_H_ */ diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index 0d8fe0a2..1a7bca83 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -16,7 +16,7 @@ struct SubGhzBlockGeneric { uint32_t serial; uint8_t data_count_bit; uint8_t btn; - uint16_t cnt; + uint32_t cnt; }; /** diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 467e3154..8817b380 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -76,6 +76,7 @@ const SubGhzProtocol subghz_protocol_came = { }; void* subghz_protocol_encoder_came_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderCame* instance = malloc(sizeof(SubGhzProtocolEncoderCame)); instance->base.protocol = &subghz_protocol_came; @@ -182,6 +183,7 @@ LevelDuration subghz_protocol_encoder_came_yield(void* context) { } void* subghz_protocol_decoder_came_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderCame* instance = malloc(sizeof(SubGhzProtocolDecoderCame)); instance->base.protocol = &subghz_protocol_came; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 67d5398f..51e7fe0b 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -136,7 +136,7 @@ void subghz_protocol_decoder_came_atomo_feed(void* context, bool level, uint32_t subghz_protocol_came_atomo_const.te_delta) { event = ManchesterEventLongLow; } else if( - duration >= (subghz_protocol_came_atomo_const.te_long * 2 + + duration >= ((uint32_t)subghz_protocol_came_atomo_const.te_long * 2 + subghz_protocol_came_atomo_const.te_delta)) { if(instance->decoder.decode_count_bit == subghz_protocol_came_atomo_const.min_count_bit_for_found) { diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index fe5f7877..4ca11623 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -103,6 +103,7 @@ const SubGhzProtocol subghz_protocol_came_twee = { }; void* subghz_protocol_encoder_came_twee_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderCameTwee* instance = malloc(sizeof(SubGhzProtocolEncoderCameTwee)); instance->base.protocol = &subghz_protocol_came_twee; @@ -289,6 +290,7 @@ LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) { } void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee)); instance->base.protocol = &subghz_protocol_came_twee; instance->generic.protocol_name = instance->base.protocol->name; @@ -351,7 +353,7 @@ void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t subghz_protocol_came_twee_const.te_delta) { event = ManchesterEventLongLow; } else if( - duration >= (subghz_protocol_came_twee_const.te_long * 2 + + duration >= ((uint32_t)subghz_protocol_came_twee_const.te_long * 2 + subghz_protocol_came_twee_const.te_delta)) { if(instance->decoder.decode_count_bit >= subghz_protocol_came_twee_const.min_count_bit_for_found) { diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index d5006ae6..d5761831 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -69,6 +69,7 @@ const SubGhzProtocol subghz_protocol_faac_slh = { }; void* subghz_protocol_decoder_faac_slh_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderFaacSLH* instance = malloc(sizeof(SubGhzProtocolDecoderFaacSLH)); instance->base.protocol = &subghz_protocol_faac_slh; instance->generic.protocol_name = instance->base.protocol->name; @@ -111,7 +112,7 @@ void subghz_protocol_decoder_faac_slh_feed(void* context, bool level, uint32_t d break; case FaacSLHDecoderStepSaveDuration: if(level) { - if(duration >= (subghz_protocol_faac_slh_const.te_short * 3 + + if(duration >= ((uint32_t)subghz_protocol_faac_slh_const.te_short * 3 + subghz_protocol_faac_slh_const.te_delta)) { instance->decoder.parser_step = FaacSLHDecoderStepFoundPreambula; if(instance->decoder.decode_count_bit >= diff --git a/lib/subghz/protocols/firefly.c b/lib/subghz/protocols/firefly.c index e872d558..21047a30 100644 --- a/lib/subghz/protocols/firefly.c +++ b/lib/subghz/protocols/firefly.c @@ -6,12 +6,6 @@ #include "../blocks/generic.h" #include "../blocks/math.h" -/* - * Help - * https://phreakerclub.com/447 - * - */ - #define TAG "SubGhzProtocolFirefly" #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c" @@ -81,6 +75,7 @@ const SubGhzProtocol subghz_protocol_firefly = { }; void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderFirefly* instance = malloc(sizeof(SubGhzProtocolEncoderFirefly)); instance->base.protocol = &subghz_protocol_firefly; @@ -199,6 +194,7 @@ LevelDuration subghz_protocol_encoder_firefly_yield(void* context) { } void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderFirefly* instance = malloc(sizeof(SubGhzProtocolDecoderFirefly)); instance->base.protocol = &subghz_protocol_firefly; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index dd6548a2..5f124c37 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -69,6 +69,7 @@ const SubGhzProtocol subghz_protocol_gate_tx = { }; void* subghz_protocol_encoder_gate_tx_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderGateTx* instance = malloc(sizeof(SubGhzProtocolEncoderGateTx)); instance->base.protocol = &subghz_protocol_gate_tx; @@ -175,6 +176,7 @@ LevelDuration subghz_protocol_encoder_gate_tx_yield(void* context) { } void* subghz_protocol_decoder_gate_tx_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderGateTx* instance = malloc(sizeof(SubGhzProtocolDecoderGateTx)); instance->base.protocol = &subghz_protocol_gate_tx; instance->generic.protocol_name = instance->base.protocol->name; @@ -218,7 +220,7 @@ void subghz_protocol_decoder_gate_tx_feed(void* context, bool level, uint32_t du break; case GateTXDecoderStepSaveDuration: if(!level) { - if(duration >= (subghz_protocol_gate_tx_const.te_short * 10 + + if(duration >= ((uint32_t)subghz_protocol_gate_tx_const.te_short * 10 + subghz_protocol_gate_tx_const.te_delta)) { instance->decoder.parser_step = GateTXDecoderStepFoundStartBit; if(instance->decoder.decode_count_bit >= diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c new file mode 100644 index 00000000..174d023e --- /dev/null +++ b/lib/subghz/protocols/holtek.c @@ -0,0 +1,360 @@ +#include "holtek.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://pdf1.alldatasheet.com/datasheet-pdf/view/82103/HOLTEK/HT640.html + * https://fccid.io/OJM-CMD-HHLR-XXXA + * + */ + +#define TAG "SubGhzProtocolHoltek" + +#define HOLTEK_HEADER_MASK 0xF000000000 +#define HOLTEK_HEADER 0x5000000000 + +static const SubGhzBlockConst subghz_protocol_holtek_const = { + .te_short = 430, + .te_long = 870, + .te_delta = 100, + .min_count_bit_for_found = 40, +}; + +struct SubGhzProtocolDecoderHoltek { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderHoltek { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + HoltekDecoderStepReset = 0, + HoltekDecoderStepFoundStartBit, + HoltekDecoderStepSaveDuration, + HoltekDecoderStepCheckDuration, +} HoltekDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_holtek_decoder = { + .alloc = subghz_protocol_decoder_holtek_alloc, + .free = subghz_protocol_decoder_holtek_free, + + .feed = subghz_protocol_decoder_holtek_feed, + .reset = subghz_protocol_decoder_holtek_reset, + + .get_hash_data = subghz_protocol_decoder_holtek_get_hash_data, + .serialize = subghz_protocol_decoder_holtek_serialize, + .deserialize = subghz_protocol_decoder_holtek_deserialize, + .get_string = subghz_protocol_decoder_holtek_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_holtek_encoder = { + .alloc = subghz_protocol_encoder_holtek_alloc, + .free = subghz_protocol_encoder_holtek_free, + + .deserialize = subghz_protocol_encoder_holtek_deserialize, + .stop = subghz_protocol_encoder_holtek_stop, + .yield = subghz_protocol_encoder_holtek_yield, +}; + +const SubGhzProtocol subghz_protocol_holtek = { + .name = SUBGHZ_PROTOCOL_HOLTEK_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_315 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | + SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_holtek_decoder, + .encoder = &subghz_protocol_holtek_encoder, +}; + +void* subghz_protocol_encoder_holtek_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderHoltek* instance = malloc(sizeof(SubGhzProtocolEncoderHoltek)); + + instance->base.protocol = &subghz_protocol_holtek; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_holtek_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderHoltek* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderHoltek instance + * @return true On success + */ +static bool subghz_protocol_encoder_holtek_get_upload(SubGhzProtocolEncoderHoltek* instance) { + furi_assert(instance); + + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send header + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_holtek_const.te_short * 36); + //Send start bit + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_holtek_const.te_short); + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_holtek_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_holtek_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_holtek_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_holtek_const.te_long); + } + } + return true; +} + +bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderHoltek* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_holtek_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_holtek_stop(void* context) { + SubGhzProtocolEncoderHoltek* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_holtek_yield(void* context) { + SubGhzProtocolEncoderHoltek* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_holtek_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderHoltek* instance = malloc(sizeof(SubGhzProtocolDecoderHoltek)); + instance->base.protocol = &subghz_protocol_holtek; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_holtek_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + free(instance); +} + +void subghz_protocol_decoder_holtek_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + instance->decoder.parser_step = HoltekDecoderStepReset; +} + +void subghz_protocol_decoder_holtek_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + + switch(instance->decoder.parser_step) { + case HoltekDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_holtek_const.te_short * 36) < + subghz_protocol_holtek_const.te_delta * 36)) { + //Found Preambula + instance->decoder.parser_step = HoltekDecoderStepFoundStartBit; + } + break; + case HoltekDecoderStepFoundStartBit: + if((level) && (DURATION_DIFF(duration, subghz_protocol_holtek_const.te_short) < + subghz_protocol_holtek_const.te_delta)) { + //Found StartBit + instance->decoder.parser_step = HoltekDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = HoltekDecoderStepReset; + } + break; + case HoltekDecoderStepSaveDuration: + //save duration + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_holtek_const.te_short * 10 + + subghz_protocol_holtek_const.te_delta)) { + instance->decoder.parser_step = HoltekDecoderStepSaveDuration; + if(instance->decoder.decode_count_bit == + subghz_protocol_holtek_const.min_count_bit_for_found) { + if((instance->decoder.decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = HoltekDecoderStepFoundStartBit; + break; + } else { + instance->decoder.te_last = duration; + + instance->decoder.parser_step = HoltekDecoderStepCheckDuration; + } + } else { + instance->decoder.parser_step = HoltekDecoderStepReset; + } + break; + case HoltekDecoderStepCheckDuration: + if(level) { + if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_holtek_const.te_short) < + subghz_protocol_holtek_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_holtek_const.te_long) < + subghz_protocol_holtek_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = HoltekDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_holtek_const.te_long) < + subghz_protocol_holtek_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_holtek_const.te_short) < + subghz_protocol_holtek_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = HoltekDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = HoltekDecoderStepReset; + } + } else { + instance->decoder.parser_step = HoltekDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_holtek_check_remote_controller(SubGhzBlockGeneric* instance) { + if((instance->data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) { + instance->serial = + subghz_protocol_blocks_reverse_key((instance->data >> 16) & 0xFFFFF, 20); + uint16_t btn = instance->data & 0xFFFF; + if((btn & 0xf) != 0xA) { + instance->btn = 0x1 << 4 | (btn & 0xF); + } else if(((btn >> 4) & 0xF) != 0xA) { + instance->btn = 0x2 << 4 | ((btn >> 4) & 0xF); + } else if(((btn >> 8) & 0xF) != 0xA) { + instance->btn = 0x3 << 4 | ((btn >> 8) & 0xF); + } else if(((btn >> 12) & 0xF) != 0xA) { + instance->btn = 0x4 << 4 | ((btn >> 12) & 0xF); + } else { + instance->btn = 0; + } + } else { + instance->serial = 0; + instance->btn = 0; + instance->cnt = 0; + } +} + +uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_holtek_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_holtek_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderHoltek* instance = context; + subghz_protocol_holtek_check_remote_controller(&instance->generic); + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%05lX BTN:%X ", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)((instance->generic.data >> 32) & 0xFFFFFFFF), + (uint32_t)(instance->generic.data & 0xFFFFFFFF), + instance->generic.serial, + instance->generic.btn >> 4); + + if((instance->generic.btn & 0xF) == 0xE) { + string_cat_printf(output, "ON\r\n"); + } else if(((instance->generic.btn & 0xF) == 0xB)) { + string_cat_printf(output, "OFF\r\n"); + } +} diff --git a/lib/subghz/protocols/holtek.h b/lib/subghz/protocols/holtek.h new file mode 100644 index 00000000..0110fdd3 --- /dev/null +++ b/lib/subghz/protocols/holtek.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_HOLTEK_NAME "Holtek" + +typedef struct SubGhzProtocolDecoderHoltek SubGhzProtocolDecoderHoltek; +typedef struct SubGhzProtocolEncoderHoltek SubGhzProtocolEncoderHoltek; + +extern const SubGhzProtocolDecoder subghz_protocol_holtek_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_holtek_encoder; +extern const SubGhzProtocol subghz_protocol_holtek; + +/** + * Allocate SubGhzProtocolEncoderHoltek. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderHoltek* pointer to a SubGhzProtocolEncoderHoltek instance + */ +void* subghz_protocol_encoder_holtek_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderHoltek. + * @param context Pointer to a SubGhzProtocolEncoderHoltek instance + */ +void subghz_protocol_encoder_holtek_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderHoltek instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderHoltek instance + */ +void subghz_protocol_encoder_holtek_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderHoltek instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_holtek_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderHoltek. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderHoltek* pointer to a SubGhzProtocolDecoderHoltek instance + */ +void* subghz_protocol_decoder_holtek_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderHoltek. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + */ +void subghz_protocol_decoder_holtek_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderHoltek. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + */ +void subghz_protocol_decoder_holtek_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_holtek_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderHoltek. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_holtek_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderHoltek. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderHoltek instance + * @param output Resulting text + */ +void subghz_protocol_decoder_holtek_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index 7a3fd233..20ff50fc 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -72,6 +72,7 @@ const SubGhzProtocol subghz_protocol_hormann = { }; void* subghz_protocol_encoder_hormann_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderHormann* instance = malloc(sizeof(SubGhzProtocolEncoderHormann)); instance->base.protocol = &subghz_protocol_hormann; @@ -191,6 +192,7 @@ LevelDuration subghz_protocol_encoder_hormann_yield(void* context) { } void* subghz_protocol_decoder_hormann_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderHormann* instance = malloc(sizeof(SubGhzProtocolDecoderHormann)); instance->base.protocol = &subghz_protocol_hormann; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index d2962435..93693b68 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -68,6 +68,7 @@ const SubGhzProtocol subghz_protocol_ido = { }; void* subghz_protocol_decoder_ido_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderIDo* instance = malloc(sizeof(SubGhzProtocolDecoderIDo)); instance->base.protocol = &subghz_protocol_ido; instance->generic.protocol_name = instance->base.protocol->name; @@ -111,8 +112,8 @@ void subghz_protocol_decoder_ido_feed(void* context, bool level, uint32_t durati break; case IDoDecoderStepSaveDuration: if(level) { - if(duration >= - (subghz_protocol_ido_const.te_short * 5 + subghz_protocol_ido_const.te_delta)) { + if(duration >= ((uint32_t)subghz_protocol_ido_const.te_short * 5 + + subghz_protocol_ido_const.te_delta)) { instance->decoder.parser_step = IDoDecoderStepFoundPreambula; if(instance->decoder.decode_count_bit >= subghz_protocol_ido_const.min_count_bit_for_found) { diff --git a/lib/subghz/protocols/ido.h b/lib/subghz/protocols/ido.h index c53a1593..266529e1 100644 --- a/lib/subghz/protocols/ido.h +++ b/lib/subghz/protocols/ido.h @@ -72,4 +72,4 @@ bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipp * @param context Pointer to a SubGhzProtocolDecoderIDo instance * @param output Resulting text */ -void subghz_protocol_decoder_ido_get_string(void* context, string_t output); \ No newline at end of file +void subghz_protocol_decoder_ido_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 975cd29c..566ae576 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -11,7 +11,7 @@ #include "../blocks/generic.h" #include "../blocks/math.h" -#define TAG "SubGhzProtocolkeeloq" +#define TAG "SubGhzProtocolKeeloq" static const SubGhzBlockConst subghz_protocol_keeloq_const = { .te_short = 400, @@ -384,7 +384,7 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur break; case KeeloqDecoderStepCheckDuration: if(!level) { - if(duration >= (subghz_protocol_keeloq_const.te_short * 2 + + if(duration >= ((uint32_t)subghz_protocol_keeloq_const.te_short * 2 + subghz_protocol_keeloq_const.te_delta)) { // Found end TX instance->decoder.parser_step = KeeloqDecoderStepReset; diff --git a/lib/subghz/protocols/keeloq_common.c b/lib/subghz/protocols/keeloq_common.c index 9dfc0934..7e864a32 100644 --- a/lib/subghz/protocols/keeloq_common.c +++ b/lib/subghz/protocols/keeloq_common.c @@ -81,4 +81,4 @@ inline uint64_t subghz_protocol_keeloq_common_magic_xor_type1_learning(uint32_t data, uint64_t xor) { data &= 0x0FFFFFFF; return (((uint64_t)data << 32) | data) ^ xor; -} \ No newline at end of file +} diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index f623a61d..5a89934b 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -70,6 +70,7 @@ const SubGhzProtocol subghz_protocol_kia = { }; void* subghz_protocol_decoder_kia_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderKIA* instance = malloc(sizeof(SubGhzProtocolDecoderKIA)); instance->base.protocol = &subghz_protocol_kia; instance->generic.protocol_name = instance->base.protocol->name; @@ -141,7 +142,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati case KIADecoderStepSaveDuration: if(level) { if(duration >= - (subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) { + (uint32_t)(subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) { //Found stop bit instance->decoder.parser_step = KIADecoderStepReset; if(instance->decoder.decode_count_bit >= diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c new file mode 100644 index 00000000..48a6908e --- /dev/null +++ b/lib/subghz/protocols/megacode.c @@ -0,0 +1,413 @@ +#include "megacode.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://wiki.cuvoodoo.info/doku.php?id=megacode + * https://wiki.cuvoodoo.info/lib/exe/fetch.php?media=megacode:megacode_1.pdf + * https://fccid.io/EF4ACP00872/Test-Report/Megacode-2-112615.pdf + * https://github.com/aaronsp777/megadecoder + * https://github.com/rjmendez/Linear_keyfob + * https://github.com/j07rdi/Linear_MegaCode_Garage_Remote + * + */ + +#define TAG "SubGhzProtocolMegaCode" + +static const SubGhzBlockConst subghz_protocol_megacode_const = { + .te_short = 1000, + .te_long = 1000, + .te_delta = 200, + .min_count_bit_for_found = 24, +}; + +struct SubGhzProtocolDecoderMegaCode { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + uint8_t last_bit; +}; + +struct SubGhzProtocolEncoderMegaCode { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + MegaCodeDecoderStepReset = 0, + MegaCodeDecoderStepFoundStartBit, + MegaCodeDecoderStepSaveDuration, + MegaCodeDecoderStepCheckDuration, +} MegaCodeDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_megacode_decoder = { + .alloc = subghz_protocol_decoder_megacode_alloc, + .free = subghz_protocol_decoder_megacode_free, + + .feed = subghz_protocol_decoder_megacode_feed, + .reset = subghz_protocol_decoder_megacode_reset, + + .get_hash_data = subghz_protocol_decoder_megacode_get_hash_data, + .serialize = subghz_protocol_decoder_megacode_serialize, + .deserialize = subghz_protocol_decoder_megacode_deserialize, + .get_string = subghz_protocol_decoder_megacode_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_megacode_encoder = { + .alloc = subghz_protocol_encoder_megacode_alloc, + .free = subghz_protocol_encoder_megacode_free, + + .deserialize = subghz_protocol_encoder_megacode_deserialize, + .stop = subghz_protocol_encoder_megacode_stop, + .yield = subghz_protocol_encoder_megacode_yield, +}; + +const SubGhzProtocol subghz_protocol_megacode = { + .name = SUBGHZ_PROTOCOL_MEGACODE_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_megacode_decoder, + .encoder = &subghz_protocol_megacode_encoder, +}; + +void* subghz_protocol_encoder_megacode_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderMegaCode* instance = malloc(sizeof(SubGhzProtocolEncoderMegaCode)); + + instance->base.protocol = &subghz_protocol_megacode; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 52; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_megacode_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderMegaCode* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderMegaCode instance + * @return true On success + */ +static bool subghz_protocol_encoder_megacode_get_upload(SubGhzProtocolEncoderMegaCode* instance) { + furi_assert(instance); + uint8_t last_bit = 0; + size_t size_upload = (instance->generic.data_count_bit * 2); + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + /* + * Due to the nature of the protocol + * + * 00000 1 + * _____|-| = 1 becomes + * + * 00 1 000 + * __|-|___ = 0 becomes + * + * it's easier for us to generate an upload backwards + */ + + size_t index = size_upload - 1; + + // Send end level + instance->encoder.upload[index--] = + level_duration_make(true, (uint32_t)subghz_protocol_megacode_const.te_short); + if(bit_read(instance->generic.data, 0)) { + last_bit = 1; + } else { + last_bit = 0; + } + + //Send key data + for(uint8_t i = 1; i < instance->generic.data_count_bit; i++) { + if(bit_read(instance->generic.data, i)) { + //if bit 1 + instance->encoder.upload[index--] = level_duration_make( + false, + last_bit ? (uint32_t)subghz_protocol_megacode_const.te_short * 5 : + (uint32_t)subghz_protocol_megacode_const.te_short * 2); + last_bit = 1; + } else { + //if bit 0 + instance->encoder.upload[index--] = level_duration_make( + false, + last_bit ? (uint32_t)subghz_protocol_megacode_const.te_short * 8 : + (uint32_t)subghz_protocol_megacode_const.te_short * 5); + last_bit = 0; + } + instance->encoder.upload[index--] = + level_duration_make(true, (uint32_t)subghz_protocol_megacode_const.te_short); + } + + //Send PT_GUARD + if(bit_read(instance->generic.data, 0)) { + //if end bit 1 + instance->encoder.upload[index] = + level_duration_make(false, (uint32_t)subghz_protocol_megacode_const.te_short * 11); + } else { + //if end bit 1 + instance->encoder.upload[index] = + level_duration_make(false, (uint32_t)subghz_protocol_megacode_const.te_short * 14); + } + + return true; +} + +bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderMegaCode* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_megacode_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_megacode_stop(void* context) { + SubGhzProtocolEncoderMegaCode* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_megacode_yield(void* context) { + SubGhzProtocolEncoderMegaCode* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_megacode_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderMegaCode* instance = malloc(sizeof(SubGhzProtocolDecoderMegaCode)); + instance->base.protocol = &subghz_protocol_megacode; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_megacode_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + free(instance); +} + +void subghz_protocol_decoder_megacode_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + instance->decoder.parser_step = MegaCodeDecoderStepReset; +} + +void subghz_protocol_decoder_megacode_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + switch(instance->decoder.parser_step) { + case MegaCodeDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short * 13) < + subghz_protocol_megacode_const.te_delta * 15)) { //10..16ms + //Found header MegaCode + instance->decoder.parser_step = MegaCodeDecoderStepFoundStartBit; + } + break; + case MegaCodeDecoderStepFoundStartBit: + if(level && (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short) < + subghz_protocol_megacode_const.te_delta)) { + //Found start bit MegaCode + instance->decoder.parser_step = MegaCodeDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->last_bit = 1; + + } else { + instance->decoder.parser_step = MegaCodeDecoderStepReset; + } + break; + case MegaCodeDecoderStepSaveDuration: + if(!level) { //save interval + if(duration >= (subghz_protocol_megacode_const.te_short * 10)) { + instance->decoder.parser_step = MegaCodeDecoderStepReset; + if(instance->decoder.decode_count_bit >= + subghz_protocol_megacode_const.min_count_bit_for_found) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } + + if(!instance->last_bit) { + instance->decoder.te_last = duration - subghz_protocol_megacode_const.te_short * 3; + } else { + instance->decoder.te_last = duration; + } + instance->decoder.parser_step = MegaCodeDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = MegaCodeDecoderStepReset; + } + break; + case MegaCodeDecoderStepCheckDuration: + if(level) { + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_megacode_const.te_short * 5) < + subghz_protocol_megacode_const.te_delta * 5) && + (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short) < + subghz_protocol_megacode_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->last_bit = 1; + instance->decoder.parser_step = MegaCodeDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_megacode_const.te_short * 2) < + subghz_protocol_megacode_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short) < + subghz_protocol_megacode_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->last_bit = 0; + instance->decoder.parser_step = MegaCodeDecoderStepSaveDuration; + } else + instance->decoder.parser_step = MegaCodeDecoderStepReset; + } else { + instance->decoder.parser_step = MegaCodeDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_megacode_check_remote_controller(SubGhzBlockGeneric* instance) { + /* + * Short: 1000 µs + * Long: 1000 µs + * Gap: 11000 .. 14000 µs + * A Linear Megacode transmission consists of 24 bit frames starting with + * the most significant bit and ending with the least. Each of the 24 bit + * frames is 6 milliseconds wide and always contains a single 1 millisecond + * pulse. A frame with more than 1 pulse or a frame with no pulse is invalid + * and a receiver should reset and begin watching for another start bit. + * Start bit is always 1. + * + * + * Example (I created with my own remote): + * Remote “A” has the code “17316”, a Facility Code of “3”, and a single button. + * Start bit (S) = 1 + * Facility Code 3 (F) = 0011 + * Remote Code (Key) 17316 = 43A4 = 0100001110100100 + * Button (Btn) 1 = 001 + * S F Key Btn + * Result = 1|0011|0100001110100100|001 + * + * 00000 1 + * _____|-| = 1 becomes + * + * 00 1 000 + * __|-|___ = 0 becomes + * + * The device needs to transmit with a 9000 µs gap between retransmissions: + * 000001 001000 001000 000001 000001 001000 000001 001000 001000 001000 001000 000001 + * 000001 000001 001000 000001 001000 001000 000001 001000 001000 001000 001000 000001 + * wait 9000 µs + * 000001 001000 001000 000001 000001 001000 000001 001000 001000 001000 001000 000001 + * 000001 000001 001000 000001 001000 001000 000001 001000 001000 001000 001000 000001 + * + */ + if((instance->data >> 23) == 1) { + instance->serial = (instance->data >> 3) & 0xFFFF; + instance->btn = instance->data & 0b111; + instance->cnt = (instance->data >> 19) & 0b1111; + } else { + instance->serial = 0; + instance->btn = 0; + instance->cnt = 0; + } +} + +uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_megacode_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_megacode_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderMegaCode* instance = context; + subghz_protocol_megacode_check_remote_controller(&instance->generic); + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%06lX\r\n" + "Sn:%04lX Btn:%X\r\n" + "Facility:%X\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)instance->generic.data, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/megacode.h b/lib/subghz/protocols/megacode.h new file mode 100644 index 00000000..1a3cfd5d --- /dev/null +++ b/lib/subghz/protocols/megacode.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_MEGACODE_NAME "MegaCode" + +typedef struct SubGhzProtocolDecoderMegaCode SubGhzProtocolDecoderMegaCode; +typedef struct SubGhzProtocolEncoderMegaCode SubGhzProtocolEncoderMegaCode; + +extern const SubGhzProtocolDecoder subghz_protocol_megacode_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_megacode_encoder; +extern const SubGhzProtocol subghz_protocol_megacode; + +/** + * Allocate SubGhzProtocolEncoderMegaCode. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderMegaCode* pointer to a SubGhzProtocolEncoderMegaCode instance + */ +void* subghz_protocol_encoder_megacode_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderMegaCode. + * @param context Pointer to a SubGhzProtocolEncoderMegaCode instance + */ +void subghz_protocol_encoder_megacode_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderMegaCode instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderMegaCode instance + */ +void subghz_protocol_encoder_megacode_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderMegaCode instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_megacode_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderMegaCode. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderMegaCode* pointer to a SubGhzProtocolDecoderMegaCode instance + */ +void* subghz_protocol_decoder_megacode_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderMegaCode. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + */ +void subghz_protocol_decoder_megacode_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderMegaCode. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + */ +void subghz_protocol_decoder_megacode_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_megacode_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderMegaCode. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_megacode_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderMegaCode. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance + * @param output Resulting text + */ +void subghz_protocol_decoder_megacode_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index d25c377a..6797843f 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -71,6 +71,7 @@ const SubGhzProtocol subghz_protocol_nero_radio = { }; void* subghz_protocol_encoder_nero_radio_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderNeroRadio* instance = malloc(sizeof(SubGhzProtocolEncoderNeroRadio)); instance->base.protocol = &subghz_protocol_nero_radio; @@ -200,6 +201,7 @@ LevelDuration subghz_protocol_encoder_nero_radio_yield(void* context) { } void* subghz_protocol_decoder_nero_radio_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderNeroRadio* instance = malloc(sizeof(SubGhzProtocolDecoderNeroRadio)); instance->base.protocol = &subghz_protocol_nero_radio; instance->generic.protocol_name = instance->base.protocol->name; @@ -278,7 +280,7 @@ void subghz_protocol_decoder_nero_radio_feed(void* context, bool level, uint32_t break; case NeroRadioDecoderStepCheckDuration: if(!level) { - if(duration >= (subghz_protocol_nero_radio_const.te_short * 10 + + if(duration >= ((uint32_t)subghz_protocol_nero_radio_const.te_short * 10 + subghz_protocol_nero_radio_const.te_delta * 2)) { //Found stop bit if(DURATION_DIFF( diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 12a1a547..1ba0cf86 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -6,12 +6,6 @@ #include "../blocks/generic.h" #include "../blocks/math.h" -/* - * Help - * https://phreakerclub.com/447 - * - */ - #define TAG "SubGhzProtocolNeroSketch" static const SubGhzBlockConst subghz_protocol_nero_sketch_const = { @@ -76,6 +70,7 @@ const SubGhzProtocol subghz_protocol_nero_sketch = { }; void* subghz_protocol_encoder_nero_sketch_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderNeroSketch* instance = malloc(sizeof(SubGhzProtocolEncoderNeroSketch)); instance->base.protocol = &subghz_protocol_nero_sketch; @@ -200,6 +195,7 @@ LevelDuration subghz_protocol_encoder_nero_sketch_yield(void* context) { } void* subghz_protocol_decoder_nero_sketch_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderNeroSketch* instance = malloc(sizeof(SubGhzProtocolDecoderNeroSketch)); instance->base.protocol = &subghz_protocol_nero_sketch; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 01371b73..d2844dcd 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -5,12 +5,6 @@ #include "../blocks/generic.h" #include "../blocks/math.h" -/* - * Help - * https://phreakerclub.com/447 - * - */ - #define TAG "SubGhzProtocolNiceFLO" static const SubGhzBlockConst subghz_protocol_nice_flo_const = { @@ -75,6 +69,7 @@ const SubGhzProtocol subghz_protocol_nice_flo = { }; void* subghz_protocol_encoder_nice_flo_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderNiceFlo* instance = malloc(sizeof(SubGhzProtocolEncoderNiceFlo)); instance->base.protocol = &subghz_protocol_nice_flo; @@ -181,6 +176,7 @@ LevelDuration subghz_protocol_encoder_nice_flo_yield(void* context) { } void* subghz_protocol_decoder_nice_flo_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderNiceFlo* instance = malloc(sizeof(SubGhzProtocolDecoderNiceFlo)); instance->base.protocol = &subghz_protocol_nice_flo; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/nice_flo.h b/lib/subghz/protocols/nice_flo.h index ca5cfe3f..430b111d 100644 --- a/lib/subghz/protocols/nice_flo.h +++ b/lib/subghz/protocols/nice_flo.h @@ -106,4 +106,4 @@ bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance * @param output Resulting text */ -void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output); \ No newline at end of file +void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 8a3e26a8..1fe5876d 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -5,6 +5,7 @@ #include "../blocks/encoder.h" #include "../blocks/generic.h" #include "../blocks/math.h" + /* * https://phreakerclub.com/1615 * https://phreakerclub.com/forum/showthread.php?t=2360 diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 4fa2b481..046484c7 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -12,7 +12,7 @@ * */ -#define TAG "SubGhzProtocolCAME" +#define TAG "SubGhzProtocolPrinceton" static const SubGhzBlockConst subghz_protocol_princeton_const = { .te_short = 400, @@ -28,6 +28,7 @@ struct SubGhzProtocolDecoderPrinceton { SubGhzBlockGeneric generic; uint32_t te; + uint32_t last_data; }; struct SubGhzProtocolEncoderPrinceton { @@ -79,6 +80,7 @@ const SubGhzProtocol subghz_protocol_princeton = { }; void* subghz_protocol_encoder_princeton_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderPrinceton* instance = malloc(sizeof(SubGhzProtocolEncoderPrinceton)); instance->base.protocol = &subghz_protocol_princeton; @@ -193,6 +195,7 @@ LevelDuration subghz_protocol_encoder_princeton_yield(void* context) { } void* subghz_protocol_decoder_princeton_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderPrinceton* instance = malloc(sizeof(SubGhzProtocolDecoderPrinceton)); instance->base.protocol = &subghz_protocol_princeton; instance->generic.protocol_name = instance->base.protocol->name; @@ -209,6 +212,7 @@ void subghz_protocol_decoder_princeton_reset(void* context) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; instance->decoder.parser_step = PrincetonDecoderStepReset; + instance->last_data = 0; } void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t duration) { @@ -236,20 +240,24 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t break; case PrincetonDecoderStepCheckDuration: if(!level) { - if(duration >= (subghz_protocol_princeton_const.te_short * 10 + + if(duration >= ((uint32_t)subghz_protocol_princeton_const.te_short * 10 + subghz_protocol_princeton_const.te_delta)) { instance->decoder.parser_step = PrincetonDecoderStepSaveDuration; if(instance->decoder.decode_count_bit == subghz_protocol_princeton_const.min_count_bit_for_found) { - instance->te /= (instance->decoder.decode_count_bit * 4 + 1); + if((instance->last_data == instance->decoder.decode_data) && + instance->last_data) { + instance->te /= (instance->decoder.decode_count_bit * 4 + 1); - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - instance->generic.serial = instance->decoder.decode_data >> 4; - instance->generic.btn = (uint8_t)instance->decoder.decode_data & 0x00000F; + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->generic.serial = instance->decoder.decode_data >> 4; + instance->generic.btn = (uint8_t)instance->decoder.decode_data & 0x00000F; - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->last_data = instance->decoder.decode_data; } instance->decoder.decode_data = 0; instance->decoder.decode_count_bit = 0; diff --git a/lib/subghz/protocols/princeton_for_testing.c b/lib/subghz/protocols/princeton_for_testing.c index 1c4552f4..5c3f7151 100644 --- a/lib/subghz/protocols/princeton_for_testing.c +++ b/lib/subghz/protocols/princeton_for_testing.c @@ -2,6 +2,7 @@ #include "furi_hal.h" #include "../blocks/math.h" + /* * Help * https://phreakerclub.com/447 @@ -248,7 +249,7 @@ void subghz_decoder_princeton_for_testing_parse( break; case PrincetonDecoderStepCheckDuration: if(!level) { - if(duration >= (instance->te_short * 10 + instance->te_delta)) { + if(duration >= ((uint32_t)instance->te_short * 10 + instance->te_delta)) { instance->parser_step = PrincetonDecoderStepSaveDuration; if(instance->code_count_bit == instance->code_min_count_bit_for_found) { instance->te /= (instance->code_count_bit * 4 + 1); diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 111f4536..516aa633 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -192,6 +192,7 @@ size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolDecoderRAW* instance) } void* subghz_protocol_decoder_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderRAW* instance = malloc(sizeof(SubGhzProtocolDecoderRAW)); instance->base.protocol = &subghz_protocol_raw; instance->upload_raw = NULL; @@ -243,6 +244,7 @@ void subghz_protocol_decoder_raw_get_string(void* context, string_t output) { } void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolEncoderRAW* instance = malloc(sizeof(SubGhzProtocolEncoderRAW)); instance->base.protocol = &subghz_protocol_raw; diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index c384eda1..b90e535c 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -1,13 +1,14 @@ #include "registry.h" const SubGhzProtocol* subghz_protocol_registry[] = { - &subghz_protocol_princeton, &subghz_protocol_keeloq, &subghz_protocol_star_line, + &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_gate_tx, - &subghz_protocol_raw, &subghz_protocol_firefly, + &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, + &subghz_protocol_raw, &subghz_protocol_firefly, &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, }; diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index 531caee2..a8bc9af4 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -22,6 +22,10 @@ #include "gate_tx.h" #include "raw.h" #include "firefly.h" +#include "secplus_v2.h" +#include "secplus_v1.h" +#include "megacode.h" +#include "holtek.h" /** * Registration by name SubGhzProtocol. diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index c352b4ae..a9a7c040 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -76,6 +76,7 @@ const SubGhzProtocol subghz_protocol_scher_khan = { }; void* subghz_protocol_decoder_scher_khan_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderScherKhan* instance = malloc(sizeof(SubGhzProtocolDecoderScherKhan)); instance->base.protocol = &subghz_protocol_scher_khan; instance->generic.protocol_name = instance->base.protocol->name; @@ -150,7 +151,7 @@ void subghz_protocol_decoder_scher_khan_feed(void* context, bool level, uint32_t break; case ScherKhanDecoderStepSaveDuration: if(level) { - if(duration >= (subghz_protocol_scher_khan_const.te_long + + if(duration >= (uint32_t)(subghz_protocol_scher_khan_const.te_long + subghz_protocol_scher_khan_const.te_delta * 2)) { //Found stop bit instance->decoder.parser_step = ScherKhanDecoderStepReset; diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c new file mode 100644 index 00000000..ff43e2a4 --- /dev/null +++ b/lib/subghz/protocols/secplus_v1.c @@ -0,0 +1,370 @@ +#include "secplus_v1.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* +* Help +* https://github.com/argilo/secplus +* https://github.com/merbanan/rtl_433/blob/master/src/devices/secplus_v1.c +*/ + +#define TAG "SubGhzProtocoSecPlus_v1" + +#define SECPLUS_V1_BIT_ERR -1 //0b0000 +#define SECPLUS_V1_BIT_0 0 //0b0001 +#define SECPLUS_V1_BIT_1 1 //0b0011 +#define SECPLUS_V1_BIT_2 2 //0b0111 + +#define SECPLUS_V1_PACKET_1_HEADER 0x00 +#define SECPLUS_V1_PACKET_2_HEADER 0x02 +#define SECPLUS_V1_PACKET_1_INDEX_BASE 0 +#define SECPLUS_V1_PACKET_2_INDEX_BASE 21 +#define SECPLUS_V1_PACKET_1_ACCEPTED (1 << 0) +#define SECPLUS_V1_PACKET_2_ACCEPTED (1 << 1) + +static const SubGhzBlockConst subghz_protocol_secplus_v1_const = { + .te_short = 500, + .te_long = 1500, + .te_delta = 100, + .min_count_bit_for_found = 21, +}; + +struct SubGhzProtocolDecoderSecPlus_v1 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint8_t packet_accepted; + uint8_t base_packet_index; + uint8_t data_array[44]; +}; + +struct SubGhzProtocolEncoderSecPlus_v1 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + SecPlus_v1DecoderStepReset = 0, + SecPlus_v1DecoderStepSearchStartBit, + SecPlus_v1DecoderStepSaveDuration, + SecPlus_v1DecoderStepDecoderData, +} SecPlus_v1DecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_secplus_v1_decoder = { + .alloc = subghz_protocol_decoder_secplus_v1_alloc, + .free = subghz_protocol_decoder_secplus_v1_free, + + .feed = subghz_protocol_decoder_secplus_v1_feed, + .reset = subghz_protocol_decoder_secplus_v1_reset, + + .get_hash_data = subghz_protocol_decoder_secplus_v1_get_hash_data, + .serialize = subghz_protocol_decoder_secplus_v1_serialize, + .deserialize = subghz_protocol_decoder_secplus_v1_deserialize, + .get_string = subghz_protocol_decoder_secplus_v1_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_secplus_v1_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_secplus_v1 = { + .name = SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_secplus_v1_decoder, + .encoder = &subghz_protocol_secplus_v1_encoder, +}; + +void* subghz_protocol_decoder_secplus_v1_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderSecPlus_v1* instance = malloc(sizeof(SubGhzProtocolDecoderSecPlus_v1)); + instance->base.protocol = &subghz_protocol_secplus_v1; + instance->generic.protocol_name = instance->base.protocol->name; + + return instance; +} + +void subghz_protocol_decoder_secplus_v1_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + free(instance); +} + +void subghz_protocol_decoder_secplus_v1_reset(void* context) { + furi_assert(context); + // SubGhzProtocolDecoderSecPlus_v1* instance = context; + // does not reset the decoder because you need to get 2 parts of the package +} + +/** + * Security+ 1.0 half-message decoding + * @param instance SubGhzProtocolDecoderSecPlus_v1* + */ + +static void subghz_protocol_secplus_v1_decode(SubGhzProtocolDecoderSecPlus_v1* instance) { + uint32_t rolling = 0; + uint32_t fixed = 0; + uint32_t acc = 0; + uint8_t digit = 0; + + //decode packet 1 + for(uint8_t i = 1; i < 21; i += 2) { + digit = instance->data_array[i]; + rolling = (rolling * 3) + digit; + acc += digit; + + digit = (60 + instance->data_array[i + 1] - acc) % 3; + fixed = (fixed * 3) + digit; + acc += digit; + } + + acc = 0; + //decode packet 2 + for(uint8_t i = 22; i < 42; i += 2) { + digit = instance->data_array[i]; + rolling = (rolling * 3) + digit; + acc += digit; + + digit = (60 + instance->data_array[i + 1] - acc) % 3; + fixed = (fixed * 3) + digit; + acc += digit; + } + + rolling = subghz_protocol_blocks_reverse_key(rolling, 32); + instance->generic.data = (uint64_t)fixed << 32 | rolling; + + instance->generic.data_count_bit = + subghz_protocol_secplus_v1_const.min_count_bit_for_found * 2; +} + +void subghz_protocol_decoder_secplus_v1_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + + switch(instance->decoder.parser_step) { + case SecPlus_v1DecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) < + subghz_protocol_secplus_v1_const.te_delta * 120)) { + //Found header Security+ 1.0 + instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->packet_accepted = 0; + memset(instance->data_array, 0, sizeof(instance->data_array)); + } + break; + case SecPlus_v1DecoderStepSearchStartBit: + if(level) { + if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) < + subghz_protocol_secplus_v1_const.te_delta) { + instance->base_packet_index = SECPLUS_V1_PACKET_1_INDEX_BASE; + instance + ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] = + SECPLUS_V1_BIT_0; + instance->decoder.decode_count_bit++; + instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration; + } else if( + DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_long) < + subghz_protocol_secplus_v1_const.te_delta) { + instance->base_packet_index = SECPLUS_V1_PACKET_2_INDEX_BASE; + instance + ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] = + SECPLUS_V1_BIT_2; + instance->decoder.decode_count_bit++; + instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration; + } else { + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + } else { + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + break; + case SecPlus_v1DecoderStepSaveDuration: + if(!level) { //save interval + if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) < + subghz_protocol_secplus_v1_const.te_delta * 120) { + if(instance->decoder.decode_count_bit == + subghz_protocol_secplus_v1_const.min_count_bit_for_found) { + if(instance->base_packet_index == SECPLUS_V1_PACKET_1_INDEX_BASE) + instance->packet_accepted |= SECPLUS_V1_PACKET_1_ACCEPTED; + if(instance->base_packet_index == SECPLUS_V1_PACKET_2_INDEX_BASE) + instance->packet_accepted |= SECPLUS_V1_PACKET_2_ACCEPTED; + + if(instance->packet_accepted == + (SECPLUS_V1_PACKET_1_ACCEPTED | SECPLUS_V1_PACKET_2_ACCEPTED)) { + subghz_protocol_secplus_v1_decode(instance); + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + } + instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.te_last = duration; + instance->decoder.parser_step = SecPlus_v1DecoderStepDecoderData; + } + } else { + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + break; + case SecPlus_v1DecoderStepDecoderData: + if(level && (instance->decoder.decode_count_bit <= + subghz_protocol_secplus_v1_const.min_count_bit_for_found)) { + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 3) < + subghz_protocol_secplus_v1_const.te_delta * 3) && + (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) < + subghz_protocol_secplus_v1_const.te_delta)) { + instance + ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] = + SECPLUS_V1_BIT_0; + instance->decoder.decode_count_bit++; + instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 2) < + subghz_protocol_secplus_v1_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 2) < + subghz_protocol_secplus_v1_const.te_delta * 2)) { + instance + ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] = + SECPLUS_V1_BIT_1; + instance->decoder.decode_count_bit++; + instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short) < + subghz_protocol_secplus_v1_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 3) < + subghz_protocol_secplus_v1_const.te_delta * 3)) { + instance + ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] = + SECPLUS_V1_BIT_2; + instance->decoder.decode_count_bit++; + instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration; + } else { + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + } else { + instance->decoder.parser_step = SecPlus_v1DecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_secplus_v1_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v1* instance = context; + + uint32_t fixed = (instance->generic.data >> 32) & 0xFFFFFFFF; + instance->generic.cnt = instance->generic.data & 0xFFFFFFFF; + + instance->generic.btn = fixed % 3; + uint8_t id0 = (fixed / 3) % 3; + uint8_t id1 = (fixed / 9) % 3; + uint16_t pin = 0; + + string_cat_printf( + output, + "%s %db\r\n" + "Key:0x%lX%08lX\r\n" + "id1:%d id0:%d", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)instance->generic.data, + id1, + id0); + + if(id1 == 0) { + // (fixed // 3**3) % (3**7) 3^3=27 3^73=72187 + + instance->generic.serial = (fixed / 27) % 2187; + // pin = (fixed // 3**10) % (3**9) 3^10=59049 3^9=19683 + pin = (fixed / 59049) % 19683; + + if(pin <= 9999) { + string_cat_printf(output, " pin:%d", pin); + } else if(10000 <= pin && pin <= 11029) { + string_cat_printf(output, " pin:enter"); + } + + int pin_suffix = 0; + // pin_suffix = (fixed // 3**19) % 3 3^19=1162261467 + pin_suffix = (fixed / 1162261467) % 3; + + if(pin_suffix == 1) { + string_cat_printf(output, " #\r\n"); + } else if(pin_suffix == 2) { + string_cat_printf(output, " *\r\n"); + } else { + string_cat_printf(output, "\r\n"); + } + string_cat_printf( + output, + "Sn:0x%08lX\r\n" + "Cnt:0x%03X\r\n" + "Sw_id:0x%X\r\n", + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } else { + //id = fixed / 27; + instance->generic.serial = fixed / 27; + if(instance->generic.btn == 1) { + string_cat_printf(output, " Btn:left\r\n"); + } else if(instance->generic.btn == 0) { + string_cat_printf(output, " Btn:middle\r\n"); + } else if(instance->generic.btn == 2) { + string_cat_printf(output, " Btn:right\r\n"); + } + + string_cat_printf( + output, + "Sn:0x%08lX\r\n" + "Cnt:0x%03X\r\n" + "Sw_id:0x%X\r\n", + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } +} diff --git a/lib/subghz/protocols/secplus_v1.h b/lib/subghz/protocols/secplus_v1.h new file mode 100644 index 00000000..891f751c --- /dev/null +++ b/lib/subghz/protocols/secplus_v1.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_SECPLUS_V1_NAME "Security+ 1.0" + +typedef struct SubGhzProtocolDecoderSecPlus_v1 SubGhzProtocolDecoderSecPlus_v1; +typedef struct SubGhzProtocolEncoderSecPlus_v1 SubGhzProtocolEncoderSecPlus_v1; + +extern const SubGhzProtocolDecoder subghz_protocol_secplus_v1_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_secplus_v1_encoder; +extern const SubGhzProtocol subghz_protocol_secplus_v1; + +/** + * Allocate SubGhzProtocolDecoderSecPlus_v1. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderSecPlus_v1* pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + */ +void* subghz_protocol_decoder_secplus_v1_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderSecPlus_v1. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + */ +void subghz_protocol_decoder_secplus_v1_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderSecPlus_v1. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + */ +void subghz_protocol_decoder_secplus_v1_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_secplus_v1_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderSecPlus_v1. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_secplus_v1_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderSecPlus_v1. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c new file mode 100644 index 00000000..936eb0a6 --- /dev/null +++ b/lib/subghz/protocols/secplus_v2.c @@ -0,0 +1,476 @@ +#include "secplus_v2.h" +#include +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* +* Help +* https://github.com/argilo/secplus +* https://github.com/merbanan/rtl_433/blob/master/src/devices/secplus_v2.c +*/ + +#define TAG "SubGhzProtocoSecPlus_v2" + +#define SECPLUS_V2_HEADER 0x3C0000000000 +#define SECPLUS_V2_HEADER_MASK 0xFFFF3C0000000000 +#define SECPLUS_V2_PACKET_1 0x000000000000 +#define SECPLUS_V2_PACKET_2 0x010000000000 +#define SECPLUS_V2_PACKET_MASK 0x30000000000 + +static const SubGhzBlockConst subghz_protocol_secplus_v2_const = { + .te_short = 250, + .te_long = 500, + .te_delta = 110, + .min_count_bit_for_found = 62, +}; + +struct SubGhzProtocolDecoderSecPlus_v2 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + ManchesterState manchester_saved_state; + uint64_t secplus_packet_1; +}; + +struct SubGhzProtocolEncoderSecPlus_v2 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + SecPlus_v2DecoderStepReset = 0, + SecPlus_v2DecoderStepDecoderData, +} SecPlus_v2DecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_secplus_v2_decoder = { + .alloc = subghz_protocol_decoder_secplus_v2_alloc, + .free = subghz_protocol_decoder_secplus_v2_free, + + .feed = subghz_protocol_decoder_secplus_v2_feed, + .reset = subghz_protocol_decoder_secplus_v2_reset, + + .get_hash_data = subghz_protocol_decoder_secplus_v2_get_hash_data, + .serialize = subghz_protocol_decoder_secplus_v2_serialize, + .deserialize = subghz_protocol_decoder_secplus_v2_deserialize, + .get_string = subghz_protocol_decoder_secplus_v2_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_secplus_v2_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_secplus_v2 = { + .name = SUBGHZ_PROTOCOL_SECPLUS_V2_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_secplus_v2_decoder, + .encoder = &subghz_protocol_secplus_v2_encoder, +}; + +void* subghz_protocol_decoder_secplus_v2_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderSecPlus_v2* instance = malloc(sizeof(SubGhzProtocolDecoderSecPlus_v2)); + instance->base.protocol = &subghz_protocol_secplus_v2; + instance->generic.protocol_name = instance->base.protocol->name; + + return instance; +} + +void subghz_protocol_decoder_secplus_v2_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + free(instance); +} + +void subghz_protocol_decoder_secplus_v2_reset(void* context) { + furi_assert(context); + // SubGhzProtocolDecoderSecPlus_v2* instance = context; + // does not reset the decoder because you need to get 2 parts of the package +} + +static bool subghz_protocol_secplus_v2_check_packet(SubGhzProtocolDecoderSecPlus_v2* instance) { + if((instance->decoder.decode_data & SECPLUS_V2_HEADER_MASK) == SECPLUS_V2_HEADER) { + if((instance->decoder.decode_data & SECPLUS_V2_PACKET_MASK) == SECPLUS_V2_PACKET_1) { + instance->secplus_packet_1 = instance->decoder.decode_data; + } else if( + ((instance->decoder.decode_data & SECPLUS_V2_PACKET_MASK) == SECPLUS_V2_PACKET_2) && + (instance->secplus_packet_1)) { + return true; + } + } + return false; +} + +void subghz_protocol_decoder_secplus_v2_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + + ManchesterEvent event = ManchesterEventReset; + switch(instance->decoder.parser_step) { + case SecPlus_v2DecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_secplus_v2_const.te_long * 130) < + subghz_protocol_secplus_v2_const.te_delta * 100)) { + //Found header Security+ 2.0 + instance->decoder.parser_step = SecPlus_v2DecoderStepDecoderData; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->secplus_packet_1 = 0; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); + manchester_advance( + instance->manchester_saved_state, + ManchesterEventLongHigh, + &instance->manchester_saved_state, + NULL); + manchester_advance( + instance->manchester_saved_state, + ManchesterEventShortLow, + &instance->manchester_saved_state, + NULL); + } + break; + case SecPlus_v2DecoderStepDecoderData: + if(!level) { + if(DURATION_DIFF(duration, subghz_protocol_secplus_v2_const.te_short) < + subghz_protocol_secplus_v2_const.te_delta) { + event = ManchesterEventShortLow; + } else if( + DURATION_DIFF(duration, subghz_protocol_secplus_v2_const.te_long) < + subghz_protocol_secplus_v2_const.te_delta) { + event = ManchesterEventLongLow; + } else if( + duration >= (uint32_t)(subghz_protocol_secplus_v2_const.te_long * 2 + + subghz_protocol_secplus_v2_const.te_delta)) { + if(instance->decoder.decode_count_bit >= + subghz_protocol_secplus_v2_const.min_count_bit_for_found) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + if(subghz_protocol_secplus_v2_check_packet(instance)) { + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + instance->decoder.parser_step = SecPlus_v2DecoderStepReset; + } + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); + manchester_advance( + instance->manchester_saved_state, + ManchesterEventLongHigh, + &instance->manchester_saved_state, + NULL); + manchester_advance( + instance->manchester_saved_state, + ManchesterEventShortLow, + &instance->manchester_saved_state, + NULL); + } else { + instance->decoder.parser_step = SecPlus_v2DecoderStepReset; + } + } else { + if(DURATION_DIFF(duration, subghz_protocol_secplus_v2_const.te_short) < + subghz_protocol_secplus_v2_const.te_delta) { + event = ManchesterEventShortHigh; + } else if( + DURATION_DIFF(duration, subghz_protocol_secplus_v2_const.te_long) < + subghz_protocol_secplus_v2_const.te_delta) { + event = ManchesterEventLongHigh; + } else { + instance->decoder.parser_step = SecPlus_v2DecoderStepReset; + } + } + if(event != ManchesterEventReset) { + bool data; + bool data_ok = manchester_advance( + instance->manchester_saved_state, event, &instance->manchester_saved_state, &data); + + if(data_ok) { + instance->decoder.decode_data = (instance->decoder.decode_data << 1) | data; + instance->decoder.decode_count_bit++; + } + } + break; + } +} + +/** + * Security+ 2.0 half-message decoding + * @param data data + * @param roll_array[] return roll_array part + * @param fixed[] return fixed part + * @return true On success + */ + +static bool + subghz_protocol_secplus_v2_decode_half(uint64_t data, uint8_t roll_array[], uint32_t* fixed) { + uint8_t order = (data >> 34) & 0x0f; + uint8_t invert = (data >> 30) & 0x0f; + uint16_t p[3] = {0}; + + for(int i = 29; i >= 0; i -= 3) { + p[0] = p[0] << 1 | bit_read(data, i); + p[1] = p[1] << 1 | bit_read(data, i - 1); + p[2] = p[2] << 1 | bit_read(data, i - 2); + } + + // selectively invert buffers + switch(invert) { + case 0x00: // 0b0000 (True, True, False), + p[0] = ~p[0] & 0x03FF; + p[1] = ~p[1] & 0x03FF; + break; + case 0x01: // 0b0001 (False, True, False), + p[1] = ~p[1] & 0x03FF; + break; + case 0x02: // 0b0010 (False, False, True), + p[2] = ~p[2] & 0x03FF; + break; + case 0x04: // 0b0100 (True, True, True), + p[0] = ~p[0] & 0x03FF; + p[1] = ~p[1] & 0x03FF; + p[2] = ~p[2] & 0x03FF; + break; + case 0x05: // 0b0101 (True, False, True), + case 0x0a: // 0b1010 (True, False, True), + p[0] = ~p[0] & 0x03FF; + p[2] = ~p[2] & 0x03FF; + break; + case 0x06: // 0b0110 (False, True, True), + p[1] = ~p[1] & 0x03FF; + p[2] = ~p[2] & 0x03FF; + break; + case 0x08: // 0b1000 (True, False, False), + p[0] = ~p[0] & 0x03FF; + break; + case 0x09: // 0b1001 (False, False, False), + break; + default: + FURI_LOG_E(TAG, "Invert FAIL"); + return false; + } + + uint16_t a = p[0], b = p[1], c = p[2]; + + // selectively reorder buffers + switch(order) { + case 0x06: // 0b0110 2, 1, 0], + case 0x09: // 0b1001 2, 1, 0], + p[2] = a; + p[1] = b; + p[0] = c; + break; + case 0x08: // 0b1000 1, 2, 0], + case 0x04: // 0b0100 1, 2, 0], + p[1] = a; + p[2] = b; + p[0] = c; + break; + case 0x01: // 0b0001 2, 0, 1], + p[2] = a; + p[0] = b; + p[1] = c; + break; + case 0x00: // 0b0000 0, 2, 1], + p[0] = a; + p[2] = b; + p[1] = c; + break; + case 0x05: // 0b0101 1, 0, 2], + p[1] = a; + p[0] = b; + p[2] = c; + break; + case 0x02: // 0b0010 0, 1, 2], + case 0x0A: // 0b1010 0, 1, 2], + p[0] = a; + p[1] = b; + p[2] = c; + break; + default: + FURI_LOG_E(TAG, "Order FAIL"); + return false; + } + + data = order << 4 | invert; + int k = 0; + for(int i = 6; i >= 0; i -= 2) { + roll_array[k++] = (data >> i) & 0x03; + if(roll_array[k] == 3) { + FURI_LOG_E(TAG, "Roll_Array FAIL"); + return false; + } + } + + for(int i = 8; i >= 0; i -= 2) { + roll_array[k++] = (p[2] >> i) & 0x03; + if(roll_array[k] == 3) { + FURI_LOG_E(TAG, "Roll_Array FAIL"); + return false; + } + } + + fixed[0] = p[0] << 10 | p[1]; + return true; +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + * @param packet_1 first part of the message + */ +static void + subghz_protocol_secplus_v2_remote_controller(SubGhzBlockGeneric* instance, uint64_t packet_1) { + uint32_t fixed_1[1]; + uint8_t roll_1[9] = {0}; + uint32_t fixed_2[1]; + uint8_t roll_2[9] = {0}; + uint8_t rolling_digits[18] = {0}; + + if(subghz_protocol_secplus_v2_decode_half(packet_1, roll_1, fixed_1) && + subghz_protocol_secplus_v2_decode_half(instance->data, roll_2, fixed_2)) { + rolling_digits[0] = roll_2[8]; + rolling_digits[1] = roll_1[8]; + + rolling_digits[2] = roll_2[4]; + rolling_digits[3] = roll_2[5]; + rolling_digits[4] = roll_2[6]; + rolling_digits[5] = roll_2[7]; + + rolling_digits[6] = roll_1[4]; + rolling_digits[7] = roll_1[5]; + rolling_digits[8] = roll_1[6]; + rolling_digits[9] = roll_1[7]; + + rolling_digits[10] = roll_2[0]; + rolling_digits[11] = roll_2[1]; + rolling_digits[12] = roll_2[2]; + rolling_digits[13] = roll_2[3]; + + rolling_digits[14] = roll_1[0]; + rolling_digits[15] = roll_1[1]; + rolling_digits[16] = roll_1[2]; + rolling_digits[17] = roll_1[3]; + + uint32_t rolling = 0; + for(int i = 0; i < 18; i++) { + rolling = (rolling * 3) + rolling_digits[i]; + } + // Max value = 2^28 (268435456) + if(rolling >= 0x10000000) { + FURI_LOG_E(TAG, "Rolling FAIL"); + instance->cnt = 0; + instance->btn = 0; + instance->serial = 0; + } else { + instance->cnt = subghz_protocol_blocks_reverse_key(rolling, 28); + instance->btn = fixed_1[0] >> 12; + instance->serial = fixed_1[0] << 20 | fixed_2[0]; + } + } else { + instance->cnt = 0; + instance->btn = 0; + instance->serial = 0; + } +} + +uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_secplus_v2_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + bool res = + subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> i * 8) & 0xFF; + } + + if(res && + !flipper_format_write_hex(flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Secplus_packet_1"); + res = false; + } + return res; +} + +bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_format_read_hex( + flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Missing Secplus_packet_1"); + break; + } + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + instance->secplus_packet_1 = instance->secplus_packet_1 << 8 | key_data[i]; + } + res = true; + } while(false); + + return res; +} + +void subghz_protocol_decoder_secplus_v2_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderSecPlus_v2* instance = context; + subghz_protocol_secplus_v2_remote_controller(&instance->generic, instance->secplus_packet_1); + + string_cat_printf( + output, + "%s %db\r\n" + "Pk1:0x%lX%08lX\r\n" + "Pk2:0x%lX%08lX\r\n" + "Sn:0x%08lX Btn:0x%01X\r\n" + "Cnt:0x%03X\r\n", + + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->secplus_packet_1 >> 32), + (uint32_t)instance->secplus_packet_1, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)instance->generic.data, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h new file mode 100644 index 00000000..dbb1e1bd --- /dev/null +++ b/lib/subghz/protocols/secplus_v2.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_SECPLUS_V2_NAME "Security+ 2.0" + +typedef struct SubGhzProtocolDecoderSecPlus_v2 SubGhzProtocolDecoderSecPlus_v2; +typedef struct SubGhzProtocolEncoderSecPlus_v2 SubGhzProtocolEncoderSecPlus_v2; + +extern const SubGhzProtocolDecoder subghz_protocol_secplus_v2_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_secplus_v2_encoder; +extern const SubGhzProtocol subghz_protocol_secplus_v2; + +/** + * Allocate SubGhzProtocolDecoderSecPlus_v2. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderSecPlus_v2* pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + */ +void* subghz_protocol_decoder_secplus_v2_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderSecPlus_v2. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + */ +void subghz_protocol_decoder_secplus_v2_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderSecPlus_v2. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + */ +void subghz_protocol_decoder_secplus_v2_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_secplus_v2_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderSecPlus_v2. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_secplus_v2_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderSecPlus_v2. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_secplus_v2_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index 9f58d734..764e8147 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -75,6 +75,7 @@ const SubGhzProtocol subghz_protocol_somfy_keytis = { }; void* subghz_protocol_decoder_somfy_keytis_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderSomfyKeytis* instance = malloc(sizeof(SubGhzProtocolDecoderSomfyKeytis)); instance->base.protocol = &subghz_protocol_somfy_keytis; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 4f1212bc..63407427 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -74,6 +74,7 @@ const SubGhzProtocol subghz_protocol_somfy_telis = { }; void* subghz_protocol_decoder_somfy_telis_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); SubGhzProtocolDecoderSomfyTelis* instance = malloc(sizeof(SubGhzProtocolDecoderSomfyTelis)); instance->base.protocol = &subghz_protocol_somfy_telis; instance->generic.protocol_name = instance->base.protocol->name; diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index 91538e1f..83cf90b7 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -19,7 +19,6 @@ struct SubGhzFileEncoderWorker { volatile bool worker_running; volatile bool worker_stoping; bool level; - int32_t duration; string_t str_data; string_t file_path; @@ -37,50 +36,43 @@ void subghz_file_encoder_worker_callback_end( instance->context_end = context_end; } -void subghz_file_encoder_worker_add_livel_duration( +void subghz_file_encoder_worker_add_level_duration( SubGhzFileEncoderWorker* instance, int32_t duration) { bool res = true; if(duration < 0 && !instance->level) { - instance->duration += duration; res = false; } else if(duration > 0 && instance->level) { - instance->duration += duration; res = false; - } else if(duration == 0) { - instance->duration = 0; } if(res) { instance->level = !instance->level; - instance->duration += duration; - xStreamBufferSend(instance->stream, &instance->duration, sizeof(int32_t), 10); - instance->duration = 0; + xStreamBufferSend(instance->stream, &duration, sizeof(int32_t), 100); + } else { + FURI_LOG_E(TAG, "Invalid level in the stream"); } } -bool subghz_file_encoder_worker_data_parse( - SubGhzFileEncoderWorker* instance, - const char* strStart, - size_t len) { +bool subghz_file_encoder_worker_data_parse(SubGhzFileEncoderWorker* instance, const char* strStart) { char* str1; - size_t ind_start = (size_t)strStart; //store the start address of the beginning of the line bool res = false; + // Line sample: "RAW_Data: -1, 2, -2..." + + // Look for a key in the line + str1 = strstr(strStart, "RAW_Data: "); - str1 = strstr( - strStart, "RAW_Data: "); //looking for the beginning of the desired title in the line if(str1 != NULL) { - str1 = strchr( - str1, - ' '); //if found, shift the pointer by 1 element per line "RAW_Data: -1, 2, -2..." - while( - strchr(str1, ' ') != NULL && - ((size_t)str1 < - (len + - ind_start))) { //check that there is still an element in the line and that it has not gone beyond the line + // Skip key + str1 = strchr(str1, ' '); + + // Check that there is still an element in the line + while(strchr(str1, ' ') != NULL) { str1 = strchr(str1, ' '); - str1 += 1; //if found, shift the pointer by next element per line - subghz_file_encoder_worker_add_livel_duration(instance, atoi(str1)); + + // Skip space + str1 += 1; + subghz_file_encoder_worker_add_level_duration(instance, atoi(str1)); } res = true; } @@ -148,18 +140,16 @@ static int32_t subghz_file_encoder_worker_thread(void* context) { if(stream_read_line(stream, instance->str_data)) { string_strim(instance->str_data); if(!subghz_file_encoder_worker_data_parse( - instance, - string_get_cstr(instance->str_data), - strlen(string_get_cstr(instance->str_data)))) { + instance, string_get_cstr(instance->str_data))) { //to stop DMA correctly - subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); - subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); + subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); + subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); break; } } else { - subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); - subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); + subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); + subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); break; } } diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index 1acb6ba5..d3903bc5 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -303,7 +303,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 } // HEX Encode encrypted line const char xx[] = "0123456789ABCDEF"; - for(size_t i = 0; i < len; i++) { + for(int i = 0; i < len; i++) { size_t cursor = len - i - 1; size_t hex_cursor = len * 2 - i * 2 - 1; encrypted_line[hex_cursor] = xx[encrypted_line[cursor] & 0xF]; @@ -601,4 +601,4 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* string_clear(str_temp); return result; -} \ No newline at end of file +} diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index aad28b88..863aaa31 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -83,7 +83,10 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* if(furi_hal_subghz_rx_pipe_not_empty()) { FURI_LOG_I( - TAG, "RSSI: %03.1fdbm LQI: %d", furi_hal_subghz_get_rssi(), furi_hal_subghz_get_lqi()); + TAG, + "RSSI: %03.1fdbm LQI: %d", + (double)furi_hal_subghz_get_rssi(), + furi_hal_subghz_get_lqi()); if(furi_hal_subghz_is_rx_data_crc_valid()) { furi_hal_subghz_read_packet(data, size); ret = true; diff --git a/lib/subghz/transmitter.c b/lib/subghz/transmitter.c index c74c38ea..0dc2bacd 100644 --- a/lib/subghz/transmitter.c +++ b/lib/subghz/transmitter.c @@ -3,6 +3,11 @@ #include "protocols/base.h" #include "protocols/registry.h" +struct SubGhzTransmitter { + const SubGhzProtocol* protocol; + SubGhzProtocolEncoderBase* protocol_instance; +}; + SubGhzTransmitter* subghz_transmitter_alloc_init(SubGhzEnvironment* environment, const char* protocol_name) { SubGhzTransmitter* instance = NULL; @@ -23,6 +28,11 @@ void subghz_transmitter_free(SubGhzTransmitter* instance) { free(instance); } +SubGhzProtocolEncoderBase* subghz_transmitter_get_protocol_instance(SubGhzTransmitter* instance) { + furi_assert(instance); + return instance->protocol_instance; +} + bool subghz_transmitter_stop(SubGhzTransmitter* instance) { furi_assert(instance); bool ret = false; @@ -46,6 +56,5 @@ bool subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* LevelDuration subghz_transmitter_yield(void* context) { SubGhzTransmitter* instance = context; - return instance->protocol->encoder->yield(instance->protocol_instance); } diff --git a/lib/subghz/transmitter.h b/lib/subghz/transmitter.h index 205a3eee..53f10b07 100644 --- a/lib/subghz/transmitter.h +++ b/lib/subghz/transmitter.h @@ -6,11 +6,6 @@ typedef struct SubGhzTransmitter SubGhzTransmitter; -struct SubGhzTransmitter { - const SubGhzProtocol* protocol; - SubGhzProtocolEncoderBase* protocol_instance; -}; - /** * Allocate and init SubGhzTransmitter. * @param environment Pointer to a SubGhzEnvironment instance @@ -25,6 +20,11 @@ SubGhzTransmitter* */ void subghz_transmitter_free(SubGhzTransmitter* instance); +/** Get protocol instance. + * @param instance Pointer to a SubGhzTransmitter instance + */ +SubGhzProtocolEncoderBase* subghz_transmitter_get_protocol_instance(SubGhzTransmitter* instance); + /** * Forced transmission stop. * @param instance Pointer to a SubGhzTransmitter instance diff --git a/lib/toolbox/args.c b/lib/toolbox/args.c index 8d6295dd..287ca7ef 100644 --- a/lib/toolbox/args.c +++ b/lib/toolbox/args.c @@ -92,4 +92,4 @@ bool args_read_hex_bytes(string_t args, uint8_t* bytes, size_t bytes_count) { } return result; -} \ No newline at end of file +} diff --git a/lib/toolbox/args.h b/lib/toolbox/args.h index 4ae1e1db..dc72bdaf 100644 --- a/lib/toolbox/args.h +++ b/lib/toolbox/args.h @@ -78,4 +78,4 @@ bool args_char_to_hex(char hi_nibble, char low_nibble, uint8_t* byte); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/dir_walk.c b/lib/toolbox/dir_walk.c new file mode 100644 index 00000000..2efbc0f1 --- /dev/null +++ b/lib/toolbox/dir_walk.c @@ -0,0 +1,152 @@ +#include "dir_walk.h" +#include + +LIST_DEF(DirIndexList, uint32_t); + +struct DirWalk { + File* file; + string_t path; + DirIndexList_t index_list; + uint32_t current_index; + bool recursive; + DirWalkFilterCb filter_cb; + void* filter_context; +}; + +DirWalk* dir_walk_alloc(Storage* storage) { + DirWalk* dir_walk = malloc(sizeof(DirWalk)); + string_init(dir_walk->path); + dir_walk->file = storage_file_alloc(storage); + DirIndexList_init(dir_walk->index_list); + dir_walk->recursive = true; + dir_walk->filter_cb = NULL; + return dir_walk; +} + +void dir_walk_free(DirWalk* dir_walk) { + storage_file_free(dir_walk->file); + string_clear(dir_walk->path); + DirIndexList_clear(dir_walk->index_list); + free(dir_walk); +} + +void dir_walk_set_recursive(DirWalk* dir_walk, bool recursive) { + dir_walk->recursive = recursive; +} + +void dir_walk_set_filter_cb(DirWalk* dir_walk, DirWalkFilterCb cb, void* context) { + dir_walk->filter_cb = cb; + dir_walk->filter_context = context; +} + +bool dir_walk_open(DirWalk* dir_walk, const char* path) { + string_set(dir_walk->path, path); + dir_walk->current_index = 0; + return storage_dir_open(dir_walk->file, path); +} + +static bool dir_walk_filter(DirWalk* dir_walk, const char* name, FileInfo* fileinfo) { + if(dir_walk->filter_cb) { + return dir_walk->filter_cb(name, fileinfo, dir_walk->filter_context); + } else { + return true; + } +} + +static DirWalkResult dir_walk_iter(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo) { + DirWalkResult result = DirWalkError; + char* name = malloc(256); + FileInfo info; + bool end = false; + + while(!end) { + storage_dir_read(dir_walk->file, &info, name, 255); + + if(storage_file_get_error(dir_walk->file) == FSE_OK) { + result = DirWalkOK; + dir_walk->current_index++; + + if(dir_walk_filter(dir_walk, name, &info)) { + if(return_path != NULL) { + string_printf(return_path, "%s/%s", string_get_cstr(dir_walk->path), name); + } + + if(fileinfo != NULL) { + memcpy(fileinfo, &info, sizeof(FileInfo)); + } + + end = true; + } + + if((info.flags & FSF_DIRECTORY) && dir_walk->recursive) { + // step into + DirIndexList_push_back(dir_walk->index_list, dir_walk->current_index); + dir_walk->current_index = 0; + storage_dir_close(dir_walk->file); + + string_cat_printf(dir_walk->path, "/%s", name); + storage_dir_open(dir_walk->file, string_get_cstr(dir_walk->path)); + } + } else if(storage_file_get_error(dir_walk->file) == FSE_NOT_EXIST) { + if(DirIndexList_size(dir_walk->index_list) == 0) { + // last + result = DirWalkLast; + end = true; + } else { + // step out + uint32_t index; + DirIndexList_pop_back(&index, dir_walk->index_list); + dir_walk->current_index = 0; + + storage_dir_close(dir_walk->file); + + size_t last_char = string_search_rchar(dir_walk->path, '/'); + if(last_char != STRING_FAILURE) { + string_left(dir_walk->path, last_char); + } + + storage_dir_open(dir_walk->file, string_get_cstr(dir_walk->path)); + + // rewind + while(true) { + if(index == dir_walk->current_index) { + result = DirWalkOK; + break; + } + + if(!storage_dir_read(dir_walk->file, &info, name, 255)) { + result = DirWalkError; + end = true; + break; + } + + dir_walk->current_index++; + } + } + } else { + result = DirWalkError; + end = true; + } + } + + free(name); + return result; +} + +FS_Error dir_walk_get_error(DirWalk* dir_walk) { + return storage_file_get_error(dir_walk->file); +} + +DirWalkResult dir_walk_read(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo) { + return dir_walk_iter(dir_walk, return_path, fileinfo); +} + +void dir_walk_close(DirWalk* dir_walk) { + if(storage_file_is_open(dir_walk->file)) { + storage_dir_close(dir_walk->file); + } + + DirIndexList_reset(dir_walk->index_list); + string_reset(dir_walk->path); + dir_walk->current_index = 0; +} diff --git a/lib/toolbox/dir_walk.h b/lib/toolbox/dir_walk.h new file mode 100644 index 00000000..fc651042 --- /dev/null +++ b/lib/toolbox/dir_walk.h @@ -0,0 +1,79 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DirWalk DirWalk; + +typedef enum { + DirWalkOK, /**< OK */ + DirWalkError, /**< Error */ + DirWalkLast, /**< Last element */ +} DirWalkResult; + +typedef bool (*DirWalkFilterCb)(const char* name, FileInfo* fileinfo, void* ctx); + +/** + * Allocate DirWalk + * @param storage + * @return DirWalk* + */ +DirWalk* dir_walk_alloc(Storage* storage); + +/** + * Free DirWalk + * @param dir_walk + */ +void dir_walk_free(DirWalk* dir_walk); + +/** + * Set recursive mode (true by default) + * @param dir_walk + * @param recursive + */ +void dir_walk_set_recursive(DirWalk* dir_walk, bool recursive); + +/** + * Set filter callback (Should return true if the data is valid) + * @param dir_walk + * @param cb + * @param context + */ +void dir_walk_set_filter_cb(DirWalk* dir_walk, DirWalkFilterCb cb, void* context); + +/** + * Open directory + * @param dir_walk + * @param path + * @return true + * @return false + */ +bool dir_walk_open(DirWalk* dir_walk, const char* path); + +/** + * Get error id + * @param dir_walk + * @return FS_Error + */ +FS_Error dir_walk_get_error(DirWalk* dir_walk); + +/** + * Read next element from directory + * @param dir_walk + * @param return_path + * @param fileinfo + * @return DirWalkResult + */ +DirWalkResult dir_walk_read(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo); + +/** + * Close directory + * @param dir_walk + */ +void dir_walk_close(DirWalk* dir_walk); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/toolbox/hex.c b/lib/toolbox/hex.c index 8b443e12..739eb30b 100644 --- a/lib/toolbox/hex.c +++ b/lib/toolbox/hex.c @@ -25,4 +25,4 @@ bool hex_chars_to_uint8(char hi, char low, uint8_t* value) { } else { return false; } -} \ No newline at end of file +} diff --git a/lib/toolbox/hex.h b/lib/toolbox/hex.h index ac67549a..ca10f2be 100644 --- a/lib/toolbox/hex.h +++ b/lib/toolbox/hex.h @@ -25,4 +25,4 @@ bool hex_chars_to_uint8(char hi, char low, uint8_t* value); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/level_duration.h b/lib/toolbox/level_duration.h index bef0b6ec..9406cef3 100644 --- a/lib/toolbox/level_duration.h +++ b/lib/toolbox/level_duration.h @@ -79,4 +79,4 @@ static inline uint32_t level_duration_get_duration(LevelDuration level_duration) return (level_duration >= 0) ? level_duration : -level_duration; } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/manchester_decoder.h b/lib/toolbox/manchester_decoder.h index 580d88e2..4fb6dbc6 100644 --- a/lib/toolbox/manchester_decoder.h +++ b/lib/toolbox/manchester_decoder.h @@ -28,4 +28,4 @@ bool manchester_advance( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/manchester_encoder.c b/lib/toolbox/manchester_encoder.c index c0fc4ca9..c22e4a17 100644 --- a/lib/toolbox/manchester_encoder.c +++ b/lib/toolbox/manchester_encoder.c @@ -51,4 +51,4 @@ bool manchester_encoder_advance( ManchesterEncoderResult manchester_encoder_finish(ManchesterEncoderState* state) { state->step = 0; return (state->prev_bit << 1) + state->prev_bit; -} \ No newline at end of file +} diff --git a/lib/toolbox/manchester_encoder.h b/lib/toolbox/manchester_encoder.h index 639d9b81..57ea8fb4 100644 --- a/lib/toolbox/manchester_encoder.h +++ b/lib/toolbox/manchester_encoder.h @@ -29,4 +29,4 @@ ManchesterEncoderResult manchester_encoder_finish(ManchesterEncoderState* state) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/md5.c b/lib/toolbox/md5.c index b873ee0f..3cf7cf05 100644 --- a/lib/toolbox/md5.c +++ b/lib/toolbox/md5.c @@ -296,4 +296,4 @@ void md5(const unsigned char* input, size_t ilen, unsigned char output[16]) { md5_finish(&ctx, output); memset(&ctx, 0, sizeof(md5_context)); -} \ No newline at end of file +} diff --git a/lib/toolbox/md5.h b/lib/toolbox/md5.h index 7878881e..fe53db8d 100644 --- a/lib/toolbox/md5.h +++ b/lib/toolbox/md5.h @@ -80,4 +80,4 @@ void md5(const unsigned char* input, size_t ilen, unsigned char output[16]); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/random_name.c b/lib/toolbox/random_name.c index 34a53867..b581bb97 100644 --- a/lib/toolbox/random_name.c +++ b/lib/toolbox/random_name.c @@ -33,8 +33,8 @@ void set_random_name(char* name, uint8_t max_name_size) { "opening", "crack", }; - uint8_t prefix_i = rand() % SIZEOF_ARRAY(prefix); - uint8_t suffix_i = rand() % SIZEOF_ARRAY(suffix); + uint8_t prefix_i = rand() % COUNT_OF(prefix); + uint8_t suffix_i = rand() % COUNT_OF(suffix); sniprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]); // Set first symbol to upper case diff --git a/lib/toolbox/stream/file_stream.c b/lib/toolbox/stream/file_stream.c index 340cb61a..70db8af9 100644 --- a/lib/toolbox/stream/file_stream.c +++ b/lib/toolbox/stream/file_stream.c @@ -228,4 +228,4 @@ static bool file_stream_delete_and_insert( string_clear(scratch_name); return result; -} \ No newline at end of file +} diff --git a/lib/toolbox/stream/file_stream.h b/lib/toolbox/stream/file_stream.h index ec371a53..4531b3e7 100644 --- a/lib/toolbox/stream/file_stream.h +++ b/lib/toolbox/stream/file_stream.h @@ -44,4 +44,4 @@ FS_Error file_stream_get_error(Stream* stream); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/stream/stream.c b/lib/toolbox/stream/stream.c index 4aee8acd..982c4983 100644 --- a/lib/toolbox/stream/stream.c +++ b/lib/toolbox/stream/stream.c @@ -217,7 +217,7 @@ bool stream_delete_and_insert_vaformat( string_init_vprintf(data, format, args); StreamWriteData write_data = { .data = (uint8_t*)string_get_cstr(data), .size = string_size(data)}; - bool result = stream_delete_and_insert(stream, 0, stream_write_struct, &write_data); + bool result = stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data); string_clear(data); return result; @@ -333,4 +333,4 @@ void stream_dump_data(Stream* stream) { printf("\r\n"); printf("DATA END\r\n"); stream_seek(stream, tell, StreamOffsetFromStart); -} \ No newline at end of file +} diff --git a/lib/toolbox/stream/stream.h b/lib/toolbox/stream/stream.h index 97ded8bd..c10e9f5e 100644 --- a/lib/toolbox/stream/stream.h +++ b/lib/toolbox/stream/stream.h @@ -333,4 +333,4 @@ void stream_dump_data(Stream* stream); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/stream/stream_i.h b/lib/toolbox/stream/stream_i.h index a62e174c..178d3fee 100644 --- a/lib/toolbox/stream/stream_i.h +++ b/lib/toolbox/stream/stream_i.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define STREAM_CACHE_SIZE 512 +#define STREAM_CACHE_SIZE 512u typedef struct StreamVTable StreamVTable; diff --git a/lib/toolbox/stream/string_stream.c b/lib/toolbox/stream/string_stream.c index 5fec06c3..3244b7ba 100644 --- a/lib/toolbox/stream/string_stream.c +++ b/lib/toolbox/stream/string_stream.c @@ -176,4 +176,4 @@ static size_t string_stream_write_char(StringStream* stream, char c) { stream->index++; return 1; -} \ No newline at end of file +} diff --git a/lib/toolbox/stream/string_stream.h b/lib/toolbox/stream/string_stream.h index 1827258d..6cccfa6c 100644 --- a/lib/toolbox/stream/string_stream.h +++ b/lib/toolbox/stream/string_stream.h @@ -15,4 +15,4 @@ Stream* string_stream_alloc(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 315497e1..91d2c812 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -345,4 +345,4 @@ bool tar_archive_add_dir(TarArchive* archive, const char* fs_full_path, const ch free(name); storage_file_free(directory); return success; -} \ No newline at end of file +} diff --git a/lib/toolbox/tar/tar_archive.h b/lib/toolbox/tar/tar_archive.h index a8976181..d9b0f321 100644 --- a/lib/toolbox/tar/tar_archive.h +++ b/lib/toolbox/tar/tar_archive.h @@ -63,4 +63,4 @@ bool tar_archive_finalize(TarArchive* archive); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/toolbox/version.c b/lib/toolbox/version.c index 902be876..40c48370 100644 --- a/lib/toolbox/version.c +++ b/lib/toolbox/version.c @@ -55,4 +55,4 @@ uint8_t version_get_target(const Version* v) { bool version_get_dirty_flag(const Version* v) { return v ? v->build_is_dirty : version.build_is_dirty; -} \ No newline at end of file +} diff --git a/lib/toolbox/version.h b/lib/toolbox/version.h index 7e82e45d..652ff3fe 100644 --- a/lib/toolbox/version.h +++ b/lib/toolbox/version.h @@ -84,4 +84,4 @@ bool version_get_dirty_flag(const Version* v); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/u8g2/u8g2_glue.c b/lib/u8g2/u8g2_glue.c index cc186663..33d30f29 100644 --- a/lib/u8g2/u8g2_glue.c +++ b/lib/u8g2/u8g2_glue.c @@ -3,6 +3,8 @@ #include uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { + UNUSED(u8x8); + UNUSED(arg_ptr); switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: /* HAL initialization contains all what we need so we can skip this part. */ @@ -27,6 +29,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo } uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { + UNUSED(u8x8); switch(msg) { case U8X8_MSG_BYTE_SEND: furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_display, (uint8_t*)arg_ptr, arg_int, 10000); diff --git a/lib/u8g2/u8x8_display.c b/lib/u8g2/u8x8_display.c index 76a099b1..83b0ca41 100644 --- a/lib/u8g2/u8x8_display.c +++ b/lib/u8g2/u8x8_display.c @@ -147,4 +147,4 @@ void u8x8_ClearLine(u8x8_t* u8x8, uint8_t line) { u8x8->display_cb( u8x8, U8X8_MSG_DISPLAY_DRAW_TILE, u8x8->display_info->tile_width, (void*)&tile); } -} \ No newline at end of file +} diff --git a/lib/u8g2/u8x8_gpio.c b/lib/u8g2/u8x8_gpio.c index bb1470d3..1fcc0a39 100644 --- a/lib/u8g2/u8x8_gpio.c +++ b/lib/u8g2/u8x8_gpio.c @@ -44,4 +44,4 @@ void u8x8_gpio_Delay(u8x8_t *u8x8, uint8_t msg, uint8_t dly) { u8x8->gpio_and_delay_cb(u8x8, msg, dly, NULL); } -*/ \ No newline at end of file +*/ diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 3d05d0ba..2fe0a1ef 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -26,6 +26,7 @@ UpdateManifest* update_manifest_alloc() { string_init(update_manifest->staged_loader_file); string_init(update_manifest->resource_bundle); update_manifest->target = 0; + update_manifest->manifest_version = 0; memset(update_manifest->ob_reference.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); memset(update_manifest->ob_compare_mask.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); memset(update_manifest->ob_write_mask.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); @@ -49,12 +50,11 @@ static bool furi_assert(flipper_file); string_t filetype; - uint32_t version = 0; // TODO: compare filetype? string_init(filetype); update_manifest->valid = - flipper_format_read_header(flipper_file, filetype, &version) && + flipper_format_read_header(flipper_file, filetype, &update_manifest->manifest_version) && flipper_format_read_string(flipper_file, MANIFEST_KEY_INFO, update_manifest->version) && flipper_format_read_uint32( flipper_file, MANIFEST_KEY_TARGET, &update_manifest->target, 1) && @@ -68,7 +68,7 @@ static bool string_clear(filetype); if(update_manifest->valid) { - /* Optional fields - we can have dfu, radio, or both */ + /* Optional fields - we can have dfu, radio, resources, or any combination */ flipper_format_read_string( flipper_file, MANIFEST_KEY_DFU_FILE, update_manifest->firmware_dfu_image); flipper_format_read_string( @@ -131,8 +131,7 @@ static bool ob_data_check_masked_values_valid( const FuriHalFlashRawOptionByteData* mask) { bool valid = true; for(size_t idx = 0; valid && (idx < FURI_HAL_FLASH_OB_TOTAL_VALUES); ++idx) { - valid &= (data->obs[idx]. dword & mask->obs[idx].dword) == - data->obs[idx].dword; + valid &= (data->obs[idx].dword & mask->obs[idx].dword) == data->obs[idx].dword; } return valid; } @@ -179,4 +178,4 @@ bool update_manifest_init_mem( flipper_format_free(flipper_file); return update_manifest->valid; -} \ No newline at end of file +} diff --git a/lib/update_util/update_manifest.h b/lib/update_util/update_manifest.h index d03c71d2..2b1e6857 100644 --- a/lib/update_util/update_manifest.h +++ b/lib/update_util/update_manifest.h @@ -12,7 +12,7 @@ extern "C" { /* Paths don't include /ext -- because at startup SD card is mounted as root */ #define UPDATE_DIR_DEFAULT_REL_PATH "/update" #define UPDATE_MANIFEST_DEFAULT_NAME "update.fuf" -#define UPDATE_MAINFEST_DEFAULT_PATH UPDATE_DIR_DEFAULT_REL_PATH "/" UPDATE_MANIFEST_DEFAULT_NAME +#define UPDATE_MANIFEST_POINTER_FILE_NAME ".fupdate" typedef union { uint8_t raw[6]; @@ -28,6 +28,7 @@ typedef union { _Static_assert(sizeof(UpdateManifestRadioVersion) == 6, "UpdateManifestRadioVersion size error"); typedef struct { + uint32_t manifest_version; string_t version; uint32_t target; string_t staged_loader_file; @@ -59,4 +60,4 @@ bool update_manifest_has_obdata(UpdateManifest* update_manifest); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index beea98d2..142dcaaa 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -9,10 +9,9 @@ #include #include -static const char* UPDATE_ROOT_DIR = "/ext" UPDATE_DIR_DEFAULT_REL_PATH; -static const char* UPDATE_PREFIX = "/ext" UPDATE_DIR_DEFAULT_REL_PATH "/"; -static const char* UPDATE_SUFFIX = "/" UPDATE_MANIFEST_DEFAULT_NAME; -static const uint32_t MAX_DIR_NAME_LEN = 250; +#define UPDATE_ROOT_DIR "/ext" UPDATE_DIR_DEFAULT_REL_PATH +#define UPDATE_PREFIX "/ext" UPDATE_DIR_DEFAULT_REL_PATH "/" +#define UPDATE_SUFFIX "/" UPDATE_MANIFEST_DEFAULT_NAME static const char* update_prepare_result_descr[] = { [UpdatePrepareResultOK] = "OK", @@ -21,6 +20,8 @@ static const char* update_prepare_result_descr[] = { [UpdatePrepareResultManifestInvalid] = "Invalid manifest data", [UpdatePrepareResultStageMissing] = "Missing Stage2 loader", [UpdatePrepareResultStageIntegrityError] = "Corrupted Stage2 loader", + [UpdatePrepareResultManifestPointerError] = "Failed to create update pointer file", + [UpdatePrepareResultOutdatedManifestVersion] = "Update package is too old", }; const char* update_operation_describe_preparation_result(const UpdatePrepareResult value) { @@ -31,68 +32,10 @@ const char* update_operation_describe_preparation_result(const UpdatePrepareResu } } -bool update_operation_get_package_dir_name(const char* full_path, string_t out_manifest_dir) { - bool path_ok = false; - string_t full_path_str; - string_init_set(full_path_str, full_path); - string_reset(out_manifest_dir); - bool start_end_ok = string_start_with_str_p(full_path_str, UPDATE_PREFIX) && - string_end_with_str_p(full_path_str, UPDATE_SUFFIX); - int16_t dir_name_len = - strlen(full_path) - strlen(UPDATE_PREFIX) - strlen(UPDATE_MANIFEST_DEFAULT_NAME) - 1; - if(dir_name_len == -1) { - path_ok = true; - } else if(start_end_ok && (dir_name_len > 0)) { - string_set_n(out_manifest_dir, full_path_str, strlen(UPDATE_PREFIX), dir_name_len); - path_ok = true; - if(string_search_char(out_manifest_dir, '/') != STRING_FAILURE) { - string_reset(out_manifest_dir); - path_ok = false; - } - } - string_clear(full_path_str); - return path_ok; -} - -int32_t update_operation_get_package_index(Storage* storage, const char* update_package_dir) { - furi_assert(storage); - furi_assert(update_package_dir); - - if(strlen(update_package_dir) == 0) { - return 0; - } - - bool found = false; - int32_t index = 0; - File* dir = storage_file_alloc(storage); - FileInfo fi = {0}; - char* name_buffer = malloc(MAX_DIR_NAME_LEN); - do { - if(!storage_dir_open(dir, UPDATE_ROOT_DIR)) { - break; - } - - while(storage_dir_read(dir, &fi, name_buffer, MAX_DIR_NAME_LEN)) { - index++; - if(strcmp(name_buffer, update_package_dir)) { - continue; - } else { - found = true; - break; - } - } - } while(false); - - free(name_buffer); - storage_file_free(dir); - - return found ? index : -1; -} - -bool update_operation_get_current_package_path(Storage* storage, string_t out_path) { - uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); +static bool update_operation_get_current_package_path_rtc(Storage* storage, string_t out_path) { + const uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); string_set_str(out_path, UPDATE_ROOT_DIR); - if(update_index == 0) { + if(update_index == UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC) { return true; } @@ -100,13 +43,13 @@ bool update_operation_get_current_package_path(Storage* storage, string_t out_pa uint32_t iter_index = 0; File* dir = storage_file_alloc(storage); FileInfo fi = {0}; - char* name_buffer = malloc(MAX_DIR_NAME_LEN); + char* name_buffer = malloc(UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN); do { if(!storage_dir_open(dir, UPDATE_ROOT_DIR)) { break; } - while(storage_dir_read(dir, &fi, name_buffer, MAX_DIR_NAME_LEN)) { + while(storage_dir_read(dir, &fi, name_buffer, UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) { if(++iter_index == update_index) { found = true; path_append(out_path, name_buffer); @@ -124,74 +67,148 @@ bool update_operation_get_current_package_path(Storage* storage, string_t out_pa return found; } +#define UPDATE_FILE_POINTER_FN "/ext/" UPDATE_MANIFEST_POINTER_FILE_NAME +#define UPDATE_MANIFEST_MAX_PATH_LEN 256u + +bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path) { + string_reset(out_path); + if(storage_common_stat(storage, UPDATE_FILE_POINTER_FN, NULL) == FSE_OK) { + char* manifest_name_buffer = malloc(UPDATE_MANIFEST_MAX_PATH_LEN); + File* upd_file = NULL; + do { + upd_file = storage_file_alloc(storage); + if(!storage_file_open( + upd_file, UPDATE_FILE_POINTER_FN, FSAM_READ, FSOM_OPEN_EXISTING)) { + break; + } + uint16_t bytes_read = + storage_file_read(upd_file, manifest_name_buffer, UPDATE_MANIFEST_MAX_PATH_LEN); + if((bytes_read == 0) || (bytes_read == UPDATE_MANIFEST_MAX_PATH_LEN)) { + break; + } + if(storage_common_stat(storage, manifest_name_buffer, NULL) != FSE_OK) { + break; + } + string_set_str(out_path, manifest_name_buffer); + } while(0); + free(manifest_name_buffer); + storage_file_free(upd_file); + } else { + /* legacy, will be deprecated */ + string_t rtcpath; + string_init(rtcpath); + do { + if(!update_operation_get_current_package_path_rtc(storage, rtcpath)) { + break; + } + path_concat(string_get_cstr(rtcpath), UPDATE_MANIFEST_DEFAULT_NAME, out_path); + } while(0); + string_clear(rtcpath); + } + return !string_empty_p(out_path); +} + +static bool update_operation_persist_manifest_path(Storage* storage, const char* manifest_path) { + const uint16_t manifest_path_len = strlen(manifest_path); + furi_check(manifest_path && manifest_path_len); + bool success = false; + File* file = storage_file_alloc(storage); + do { + if(manifest_path_len >= UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN) { + break; + } + + if(!storage_file_open(file, UPDATE_FILE_POINTER_FN, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + break; + } + + if(storage_file_write(file, manifest_path, manifest_path_len) != manifest_path_len) { + break; + } + + success = true; + } while(0); + storage_file_free(file); + return success; +} + UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { - string_t update_folder; - string_init(update_folder); - if(!update_operation_get_package_dir_name(manifest_file_path, update_folder)) { - string_clear(update_folder); - return UpdatePrepareResultManifestPathInvalid; - } - + UpdatePrepareResult result = UpdatePrepareResultManifestFolderNotFound; Storage* storage = furi_record_open("storage"); - int32_t update_index = - update_operation_get_package_index(storage, string_get_cstr(update_folder)); - string_clear(update_folder); - - if(update_index < 0) { - furi_record_close("storage"); - return UpdatePrepareResultManifestFolderNotFound; - } - - string_t update_dir_path; - string_init(update_dir_path); - path_extract_dirname(manifest_file_path, update_dir_path); - - UpdatePrepareResult result = UpdatePrepareResultManifestInvalid; UpdateManifest* manifest = update_manifest_alloc(); - if(update_manifest_init(manifest, manifest_file_path)) { - result = UpdatePrepareResultStageMissing; - File* file = storage_file_alloc(storage); + File* file = storage_file_alloc(storage); + + string_t stage_path; + string_init(stage_path); + do { + if(storage_common_stat(storage, manifest_file_path, NULL) != FSE_OK) { + break; + } + + if(!update_manifest_init(manifest, manifest_file_path)) { + result = UpdatePrepareResultManifestInvalid; + break; + } + + if(manifest->manifest_version < UPDATE_OPERATION_MIN_MANIFEST_VERSION) { + result = UpdatePrepareResultOutdatedManifestVersion; + break; + } + + if(furi_hal_version_get_hw_target() != manifest->target) { + result = UpdatePrepareResultTargetMismatch; + break; + } - string_t stage_path; - string_init(stage_path); path_extract_dirname(manifest_file_path, stage_path); path_append(stage_path, string_get_cstr(manifest->staged_loader_file)); - uint32_t crc = 0; - do { - if(!storage_file_open( - file, string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { - break; - } - - result = UpdatePrepareResultStageIntegrityError; - crc = crc32_calc_file(file, NULL, NULL); - } while(false); - - string_clear(stage_path); - storage_file_free(file); - - if(crc == manifest->staged_loader_crc) { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); - update_operation_persist_package_index(update_index); - result = UpdatePrepareResultOK; + if(!storage_file_open(file, string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { + result = UpdatePrepareResultStageMissing; + break; } - } - furi_record_close("storage"); + + uint32_t crc = crc32_calc_file(file, NULL, NULL); + if(crc != manifest->staged_loader_crc) { + result = UpdatePrepareResultStageIntegrityError; + break; + } + + if(!update_operation_persist_manifest_path(storage, manifest_file_path)) { + result = UpdatePrepareResultManifestPointerError; + break; + } + + result = UpdatePrepareResultOK; + furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); + } while(false); + + string_clear(stage_path); + storage_file_free(file); + update_manifest_free(manifest); + furi_record_close("storage"); return result; } bool update_operation_is_armed() { - return furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModePreUpdate; + FuriHalRtcBootMode boot_mode = furi_hal_rtc_get_boot_mode(); + const uint32_t rtc_upd_index = + furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); + Storage* storage = furi_record_open("storage"); + const bool upd_fn_ptr_exists = + (storage_common_stat(storage, UPDATE_FILE_POINTER_FN, NULL) == FSE_OK); + furi_record_close("storage"); + return (boot_mode >= FuriHalRtcBootModePreUpdate) && + (boot_mode <= FuriHalRtcBootModePostUpdate) && + ((rtc_upd_index != INT_MAX) || upd_fn_ptr_exists); } void update_operation_disarm() { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); - furi_hal_rtc_set_register(FuriHalRtcRegisterUpdateFolderFSIndex, 0); -} - -void update_operation_persist_package_index(uint32_t index) { - furi_hal_rtc_set_register(FuriHalRtcRegisterUpdateFolderFSIndex, index); + furi_hal_rtc_set_register(FuriHalRtcRegisterUpdateFolderFSIndex, INT_MAX); + Storage* storage = furi_record_open("storage"); + storage_simply_remove(storage, UPDATE_FILE_POINTER_FN); + furi_record_close("storage"); } \ No newline at end of file diff --git a/lib/update_util/update_operation.h b/lib/update_util/update_operation.h index 6b6ab730..39d58028 100644 --- a/lib/update_util/update_operation.h +++ b/lib/update_util/update_operation.h @@ -8,6 +8,10 @@ extern "C" { #endif +#define UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC 0 +#define UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN 255u +#define UPDATE_OPERATION_MIN_MANIFEST_VERSION 2 + /* * Checks if supplied full manifest path is valid * @param full_path Full path to manifest file. Must be named UPDATE_MANIFEST_DEFAULT_NAME @@ -17,6 +21,7 @@ extern "C" { */ bool update_operation_get_package_dir_name(const char* full_path, string_t out_manifest_dir); +/* When updating this enum, also update assets/protobuf/system.proto */ typedef enum { UpdatePrepareResultOK, UpdatePrepareResultManifestPathInvalid, @@ -24,6 +29,9 @@ typedef enum { UpdatePrepareResultManifestInvalid, UpdatePrepareResultStageMissing, UpdatePrepareResultStageIntegrityError, + UpdatePrepareResultManifestPointerError, + UpdatePrepareResultTargetMismatch, + UpdatePrepareResultOutdatedManifestVersion, } UpdatePrepareResult; const char* update_operation_describe_preparation_result(const UpdatePrepareResult value); @@ -35,30 +43,16 @@ const char* update_operation_describe_preparation_result(const UpdatePrepareResu */ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path); -/* - * Gets update package index to pass in RTC registers - * @param storage Storage API - * @param update_package_dir Package directory name - * @return int32_t <0 - error, >= 0 - update index value - */ -int32_t update_operation_get_package_index(Storage* storage, const char* update_package_dir); - /* * Gets filesystem path for current update package * @param storage Storage API - * @param out_path Path to directory with manifest & related files. Must be initialized + * @param out_path Path to manifest. Must be initialized * @return true if path was restored successfully */ -bool update_operation_get_current_package_path(Storage* storage, string_t out_path); +bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path); /* - * Stores given update index in RTC registers - * @param index Value to store - */ -void update_operation_persist_package_index(uint32_t index); - -/* - * Sets up update operation to be performed on reset + * Checks if an update operation step is pending after reset */ bool update_operation_is_armed(); @@ -69,4 +63,4 @@ void update_operation_disarm(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/make/base.mk b/make/base.mk index 696c4294..281419e9 100644 --- a/make/base.mk +++ b/make/base.mk @@ -8,4 +8,4 @@ OPENOCD_OPTS = CFLAGS = CPPFLAGS = LDFLAGS = -SVD_FILE = \ No newline at end of file +SVD_FILE = diff --git a/make/defaults.mk b/make/defaults.mk index 86e4f03d..ade34a6b 100644 --- a/make/defaults.mk +++ b/make/defaults.mk @@ -1,2 +1,2 @@ TARGET ?= f7 -export TARGET \ No newline at end of file +export TARGET diff --git a/make/freertos-heap.mk b/make/freertos-heap.mk index e839e61c..93992900 100644 --- a/make/freertos-heap.mk +++ b/make/freertos-heap.mk @@ -1 +1 @@ -LDFLAGS += -Wl,--wrap,_malloc_r -Wl,--wrap,_free_r -Wl,--wrap,_calloc_r -Wl,--wrap,_realloc_r \ No newline at end of file +LDFLAGS += -Wl,--wrap,_malloc_r -Wl,--wrap,_free_r -Wl,--wrap,_calloc_r -Wl,--wrap,_realloc_r diff --git a/scripts/ReadMe.md b/scripts/ReadMe.md index b04ed0d1..86b5b8af 100644 --- a/scripts/ReadMe.md +++ b/scripts/ReadMe.md @@ -57,4 +57,4 @@ Run in the root folder of the repo: ```bash python scripts/storage.py -p send assets/resources /ext -``` \ No newline at end of file +``` diff --git a/scripts/update.py b/scripts/update.py index 3e8daab0..4769565c 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -13,6 +13,7 @@ import math class Main(App): + UPDATE_MANIFEST_VERSION = 2 UPDATE_MANIFEST_NAME = "update.fuf" # No compression, plain tar @@ -93,7 +94,9 @@ class Main(App): ) file = FlipperFormatFile() - file.setHeader("Flipper firmware upgrade configuration", 1) + file.setHeader( + "Flipper firmware upgrade configuration", self.UPDATE_MANIFEST_VERSION + ) file.writeKey("Info", self.args.version) file.writeKey("Target", self.args.target[1:]) # dirty 'f' strip file.writeKey("Loader", stage_basename) @@ -102,7 +105,7 @@ class Main(App): file.writeKey("Firmware", dfu_basename) file.writeKey("Radio", radiobin_basename or "") file.writeKey("Radio address", self.int2ffhex(radio_addr)) - file.writeKey("Radio version", self.int2ffhex(radio_version)) + file.writeKey("Radio version", self.int2ffhex(radio_version, 12)) if radiobin_basename: file.writeKey("Radio CRC", self.int2ffhex(self.crc(self.args.radiobin))) else: @@ -149,11 +152,10 @@ class Main(App): return " ".join(f"{b:02X}" for b in value) @staticmethod - def int2ffhex(value: int): - n_hex_bytes = 4 + def int2ffhex(value: int, n_hex_syms=8): if value: - n_hex_bytes = math.ceil(math.ceil(math.log2(value)) / 8) * 2 - fmtstr = f"%0{n_hex_bytes}X" + n_hex_syms = math.ceil(math.ceil(math.log2(value)) / 8) * 2 + fmtstr = f"%0{n_hex_syms}X" hexstr = fmtstr % value return " ".join(list(Main.batch(hexstr, 2))[::-1])