Merge remote-tracking branch 'origin/subbrute-deep-refactor' into subbrute-deep-refactor
1
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1 @@
|
||||
* @xMasterX
|
4
.vscode/example/launch.json
vendored
@ -9,6 +9,10 @@
|
||||
"type": "command",
|
||||
"command": "shellCommand.execute",
|
||||
"args": {
|
||||
"useSingleResult": true,
|
||||
"env": {
|
||||
"PATH": "${workspaceFolder};${env:PATH}"
|
||||
},
|
||||
"command": "./fbt get_blackmagic",
|
||||
"description": "Get Blackmagic device",
|
||||
}
|
||||
|
2
.vscode/example/settings.json
vendored
@ -22,4 +22,4 @@
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
CHANGELOG.md
@ -1,16 +1,20 @@
|
||||
### New changes
|
||||
* Picopass plugin fixed (bug with mbedtls lib fixed by hedger in OFW PR 1742)
|
||||
* PR: Fix SubGHz last used settings (PR 70 by derskythe)
|
||||
* PR: Random UID for detect reader mode - changes each time when you exit NFC app and launch it (PR 69 by h4sh5)
|
||||
* OFW PR: Dummy mode (aka dumb mode) (OFW PR 1739 by nminaylov)
|
||||
* OFW PR: picopass se identify (OFW PR 1701 by pcunning)
|
||||
* OFW PR: faploader api extension and lib fixes (OFW PR 1742 by hedger)
|
||||
* Infrared: Updated universal remote assets (by @Amec0e)
|
||||
* OFW PR: SubGHz: Read RAW - datetime in default names (+ format changed) (OFW PR 1772 by Skorpionm)
|
||||
* OFW: Text input overwrite max size template
|
||||
* OFW: Remove unused headers
|
||||
* OFW: ELF-Loader: C++ plugin support, loader overhaul.
|
||||
* OFW: Core: simplify record container
|
||||
|
||||
#### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use web updater or microSD update package**
|
||||
#### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use .tgz file with qFlipper, or install automatically via web updater or use microSD update package**
|
||||
|
||||
**Note: To avoid issues prefer installing using web updater or by self update package, all needed assets will be installed**
|
||||
[- How to install](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or `.tgz` for iOS mobile app
|
||||
[- Download qFlipper 1.2.0 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0/)
|
||||
|
||||
DFU for update using qFlipper is no longer included in releases to avoid issues with assets - Use Web Updater or self-update package!
|
||||
**Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed**
|
||||
|
||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for iOS mobile app / qFlipper
|
||||
|
||||
Update using qFlipper (1.2.0) is now possible with `.tgz` update package! Also you can use Web Updater or self-update package.
|
||||
|
||||
|
@ -49,7 +49,7 @@ See changelog in releases for latest updates!
|
||||
- Keeloq [Not ALL systems supported yet!]
|
||||
- Nice Flor S
|
||||
- Security+ v1 & v2
|
||||
- Star Line
|
||||
- Star Line (saving only)
|
||||
|
||||
## Support us so we can buy equipment and develop new features
|
||||
* ETH/BSC/ERC20-Tokens: `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`
|
||||
@ -87,7 +87,6 @@ Games:
|
||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||
- SubGHz -> New frequency analyzer - [(by ClusterM)](https://github.com/ClusterM)
|
||||
- SubGHz -> Detect RAW feature - [(by perspecdev)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/152)
|
||||
- SubGHz -> Save last used config settings - [(by derskythe)](https://github.com/Eng1n33r/flipperzero-firmware/pull/67)
|
||||
|
||||
# Instructions
|
||||
## [- How to install firmware](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
@ -167,4 +166,4 @@ Games:
|
||||
- `site_scons` - Build helpers
|
||||
- `scripts` - Supplementary scripts and python libraries home
|
||||
|
||||
Also pay attention to `ReadMe.md` files inside of those directories.
|
||||
Also pay attention to `ReadMe.md` files inside those directories.
|
||||
|
13
SConstruct
@ -44,6 +44,8 @@ distenv = coreenv.Clone(
|
||||
"target extended-remote ${GDBREMOTE}",
|
||||
"-ex",
|
||||
"set confirm off",
|
||||
"-ex",
|
||||
"set pagination off",
|
||||
],
|
||||
GDBOPTS_BLACKMAGIC=[
|
||||
"-ex",
|
||||
@ -234,10 +236,19 @@ distenv.PhonyTarget(
|
||||
distenv.PhonyTarget(
|
||||
"debug_other",
|
||||
"${GDBPYCOM}",
|
||||
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"debug_other_blackmagic",
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="$${BLACKMAGIC_ADDR}",
|
||||
)
|
||||
|
||||
|
||||
# Just start OpenOCD
|
||||
distenv.PhonyTarget(
|
||||
"openocd",
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <storage/storage.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
#include <lib/nfc/protocols/nfca.h>
|
||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||
#include <lib/digital_signal/digital_signal.h>
|
||||
|
||||
#include <lib/flipper_format/flipper_format_i.h>
|
||||
@ -170,10 +171,59 @@ MU_TEST(nfc_digital_signal_test) {
|
||||
"NFC long digital signal test failed\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_dict_test) {
|
||||
MfClassicDict* instance = NULL;
|
||||
uint64_t key = 0;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
|
||||
mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
|
||||
|
||||
mu_assert(
|
||||
mf_classic_dict_get_total_keys(instance) == 0,
|
||||
"mf_classic_dict_get_total_keys == 0 assert failed\r\n");
|
||||
|
||||
string_set(temp_str, "2196FAD8115B");
|
||||
mu_assert(
|
||||
mf_classic_dict_add_key_str(instance, temp_str),
|
||||
"mf_classic_dict_add_key == true assert failed\r\n");
|
||||
|
||||
mu_assert(
|
||||
mf_classic_dict_get_total_keys(instance) == 1,
|
||||
"mf_classic_dict_get_total_keys == 1 assert failed\r\n");
|
||||
|
||||
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||
|
||||
mu_assert(
|
||||
mf_classic_dict_get_key_at_index_str(instance, temp_str, 0),
|
||||
"mf_classic_dict_get_key_at_index_str == true assert failed\r\n");
|
||||
mu_assert(
|
||||
string_cmp(temp_str, "2196FAD8115B") == 0,
|
||||
"string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n");
|
||||
|
||||
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||
|
||||
mu_assert(
|
||||
mf_classic_dict_get_key_at_index(instance, &key, 0),
|
||||
"mf_classic_dict_get_key_at_index == true assert failed\r\n");
|
||||
mu_assert(key == 0x2196FAD8115B, "key == 0x2196FAD8115B assert failed\r\n");
|
||||
|
||||
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||
|
||||
mu_assert(
|
||||
mf_classic_dict_delete_index(instance, 0),
|
||||
"mf_classic_dict_delete_index == true assert failed\r\n");
|
||||
|
||||
mf_classic_dict_free(instance);
|
||||
string_clear(temp_str);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(nfc) {
|
||||
nfc_test_alloc();
|
||||
|
||||
MU_RUN_TEST(nfc_digital_signal_test);
|
||||
MU_RUN_TEST(mf_classic_dict_test);
|
||||
|
||||
nfc_test_free();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
#define TEST_RANDOM_COUNT_PARSE 232
|
||||
#define TEST_RANDOM_COUNT_PARSE 233
|
||||
#define TEST_TIMEOUT 10000
|
||||
|
||||
static SubGhzEnvironment* environment_handler;
|
||||
@ -434,6 +434,13 @@ MU_TEST(subghz_decoder_clemsa_test) {
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_oregon2_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/oregon2_raw.sub"), SUBGHZ_PROTOCOL_OREGON2_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_OREGON2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
//test encoders
|
||||
MU_TEST(subghz_encoder_princeton_test) {
|
||||
mu_assert(
|
||||
@ -595,6 +602,7 @@ MU_TEST_SUITE(subghz) {
|
||||
MU_RUN_TEST(subghz_decoder_magellen_test);
|
||||
MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
|
||||
MU_RUN_TEST(subghz_decoder_clemsa_test);
|
||||
MU_RUN_TEST(subghz_decoder_oregon2_test);
|
||||
|
||||
MU_RUN_TEST(subghz_encoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_test);
|
||||
|
@ -15,6 +15,23 @@ App(
|
||||
"archive",
|
||||
"clock",
|
||||
"unirfremix",
|
||||
"spectrum_analyzer",
|
||||
],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="main_apps_default",
|
||||
name="Basic applications for main menu",
|
||||
apptype=FlipperAppType.METAPACKAGE,
|
||||
provides=[
|
||||
"gpio",
|
||||
#"ibutton",
|
||||
"infrared",
|
||||
"lfrfid",
|
||||
"nfc",
|
||||
"subghz",
|
||||
#"bad_usb",
|
||||
#"u2f",
|
||||
"fap_loader",
|
||||
"archive",
|
||||
],
|
||||
)
|
||||
|
@ -16,6 +16,7 @@ static const char* tab_default_paths[] = {
|
||||
[ArchiveTabInfrared] = ANY_PATH("infrared"),
|
||||
[ArchiveTabBadUsb] = ANY_PATH("badusb"),
|
||||
[ArchiveTabU2f] = "/app:u2f",
|
||||
[ArchiveTabApps] = ANY_PATH("apps"),
|
||||
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
|
||||
};
|
||||
|
||||
@ -27,6 +28,7 @@ static const char* known_ext[] = {
|
||||
[ArchiveFileTypeInfrared] = ".ir",
|
||||
[ArchiveFileTypeBadUsb] = ".txt",
|
||||
[ArchiveFileTypeU2f] = "?",
|
||||
[ArchiveFileTypeApps] = ".fap",
|
||||
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
||||
[ArchiveFileTypeFolder] = "?",
|
||||
[ArchiveFileTypeUnknown] = "*",
|
||||
@ -41,6 +43,7 @@ static const ArchiveFileTypeEnum known_type[] = {
|
||||
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
||||
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||
[ArchiveTabApps] = ArchiveFileTypeApps,
|
||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@ typedef enum {
|
||||
ArchiveFileTypeInfrared,
|
||||
ArchiveFileTypeBadUsb,
|
||||
ArchiveFileTypeU2f,
|
||||
ArchiveFileTypeApps,
|
||||
ArchiveFileTypeUpdateManifest,
|
||||
ArchiveFileTypeFolder,
|
||||
ArchiveFileTypeUnknown,
|
||||
|
@ -42,10 +42,7 @@ ARRAY_DEF(
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
// Using in applications/archive/views/archive_browser_view.c
|
||||
static void archive_menu_add_item(
|
||||
ArchiveContextMenuItem_t* obj,
|
||||
string_t text,
|
||||
uint32_t event) {
|
||||
static void archive_menu_add_item(ArchiveContextMenuItem_t* obj, string_t text, uint32_t event) {
|
||||
string_init_move(obj->text, text);
|
||||
obj->event = event;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ static const char* flipper_app_name[] = {
|
||||
[ArchiveFileTypeInfrared] = "Infrared",
|
||||
[ArchiveFileTypeBadUsb] = "Bad USB",
|
||||
[ArchiveFileTypeU2f] = "U2F",
|
||||
[ArchiveFileTypeApps] = "Applications",
|
||||
[ArchiveFileTypeUpdateManifest] = "UpdaterApp",
|
||||
};
|
||||
|
||||
@ -132,7 +133,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
case ArchiveBrowserEventFileMenuRename:
|
||||
if(favorites) {
|
||||
browser->callback(ArchiveBrowserEventEnterFavMove, browser->context);
|
||||
//} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
|
||||
//} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
|
||||
} else {
|
||||
// Added ability to rename files and folders
|
||||
archive_show_file_menu(browser, false);
|
||||
|
@ -37,7 +37,11 @@ void archive_scene_info_on_enter(void* context) {
|
||||
|
||||
// Directory path
|
||||
path_extract_dirname(string_get_cstr(current->path), dirname);
|
||||
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "");
|
||||
if(strcmp(string_get_cstr(dirname), "/any") == 0) {
|
||||
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "/");
|
||||
} else {
|
||||
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "");
|
||||
}
|
||||
|
||||
// File size
|
||||
FileInfo fileinfo;
|
||||
@ -60,7 +64,7 @@ void archive_scene_info_on_enter(void* context) {
|
||||
string_get_cstr(dirname));
|
||||
}
|
||||
widget_add_text_box_element(
|
||||
instance->widget, 0, 25, 128, 25, AlignLeft, AlignCenter, file_info_message, false);
|
||||
instance->widget, 0, 25, 128, 25, AlignLeft, AlignCenter, file_info_message, true);
|
||||
|
||||
// This one to return and cursor select this file
|
||||
path_extract_filename_no_ext(string_get_cstr(current->path), filename);
|
||||
|
@ -16,6 +16,7 @@ static const char* ArchiveTabNames[] = {
|
||||
[ArchiveTabInfrared] = "Infrared",
|
||||
[ArchiveTabBadUsb] = "Bad USB",
|
||||
[ArchiveTabU2f] = "U2F",
|
||||
[ArchiveTabApps] = "Apps",
|
||||
[ArchiveTabBrowser] = "Browser",
|
||||
};
|
||||
|
||||
@ -27,6 +28,7 @@ static const Icon* ArchiveItemIcons[] = {
|
||||
[ArchiveFileTypeInfrared] = &I_ir_10px,
|
||||
[ArchiveFileTypeBadUsb] = &I_badusb_10px,
|
||||
[ArchiveFileTypeU2f] = &I_u2f_10px,
|
||||
[ArchiveFileTypeApps] = &I_Apps_10px,
|
||||
[ArchiveFileTypeUpdateManifest] = &I_update_10px,
|
||||
[ArchiveFileTypeFolder] = &I_dir_10px,
|
||||
[ArchiveFileTypeUnknown] = &I_unknown_10px,
|
||||
|
@ -27,6 +27,7 @@ typedef enum {
|
||||
ArchiveTabIButton,
|
||||
ArchiveTabBadUsb,
|
||||
ArchiveTabU2f,
|
||||
ArchiveTabApps,
|
||||
ArchiveTabBrowser,
|
||||
ArchiveTabTotal,
|
||||
} ArchiveTabEnum;
|
||||
|
@ -33,5 +33,4 @@ typedef enum {
|
||||
typedef struct {
|
||||
TimeFormat time_format;
|
||||
DateFormat date_format;
|
||||
uint8_t increment_precision;
|
||||
} ClockSettings;
|
@ -25,7 +25,7 @@ static bool
|
||||
FlipperApplication* app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
|
||||
|
||||
FlipperApplicationPreloadStatus preload_res =
|
||||
flipper_application_preload(app, string_get_cstr(path));
|
||||
flipper_application_preload_manifest(app, string_get_cstr(path));
|
||||
|
||||
bool load_success = false;
|
||||
|
||||
|
@ -33,8 +33,6 @@ static void infrared_scene_universal_common_hide_popup(Infrared* infrared) {
|
||||
|
||||
void infrared_scene_universal_common_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
infrared_brute_force_clear_records(infrared->brute_force);
|
||||
button_panel_reset_selection(infrared->button_panel);
|
||||
view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel));
|
||||
}
|
||||
|
||||
@ -89,5 +87,6 @@ void infrared_scene_universal_common_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
ButtonPanel* button_panel = infrared->button_panel;
|
||||
view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel));
|
||||
infrared_brute_force_clear_records(infrared->brute_force);
|
||||
button_panel_reset(button_panel);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
||||
LfRfidReadViewModel* model = _model;
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual);
|
||||
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual_60x50);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
|
@ -231,7 +231,30 @@ void nfc_show_loading_popup(void* context, bool show) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool nfc_is_hal_ready() {
|
||||
if(!furi_hal_nfc_is_init()) {
|
||||
// No connection to the chip, show an error screen
|
||||
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
dialog_message_set_text(
|
||||
message,
|
||||
"Error!\nNFC chip failed to start\n\n\nSend a photo of this to:\nsupport@flipperzero.one",
|
||||
0,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
dialog_message_show(dialogs, message);
|
||||
dialog_message_free(message);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t nfc_app(void* p) {
|
||||
if(!nfc_is_hal_ready()) return 0;
|
||||
|
||||
Nfc* nfc = nfc_alloc();
|
||||
char* args = p;
|
||||
|
||||
|
@ -33,8 +33,14 @@
|
||||
#include <nfc/scenes/nfc_scene.h>
|
||||
#include <nfc/helpers/nfc_custom_event.h>
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include "rpc/rpc_app.h"
|
||||
|
||||
#include <m-array.h>
|
||||
|
||||
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
|
||||
|
||||
#define NFC_TEXT_STORE_SIZE 128
|
||||
|
||||
typedef enum {
|
||||
@ -58,6 +64,7 @@ struct Nfc {
|
||||
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
||||
string_t text_box_store;
|
||||
uint8_t byte_input_store[6];
|
||||
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
|
||||
|
||||
void* rpc_ctx;
|
||||
NfcRpcState rpc_state;
|
||||
|
@ -32,6 +32,9 @@ ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
|
||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
||||
ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
|
||||
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
|
||||
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
|
||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
||||
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
||||
|
@ -25,8 +25,13 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneFileSelect);
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
} else {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
@ -47,7 +47,9 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
} else if(
|
||||
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
|
||||
string_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,10 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneExtraActions);
|
||||
} else {
|
||||
|
@ -17,7 +17,7 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Mf Classic Keys",
|
||||
"Mifare Classic Keys",
|
||||
SubmenuIndexMfClassicKeys,
|
||||
nfc_scene_extra_actions_submenu_callback,
|
||||
nfc);
|
||||
|
@ -26,15 +26,25 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
||||
}
|
||||
|
||||
widget_add_string_element(
|
||||
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys");
|
||||
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys");
|
||||
char temp_str[32];
|
||||
snprintf(temp_str, sizeof(temp_str), "Flipper dict: %ld", flipper_dict_keys_total);
|
||||
snprintf(temp_str, sizeof(temp_str), "Flipper list: %ld", flipper_dict_keys_total);
|
||||
widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
snprintf(temp_str, sizeof(temp_str), "User dict: %ld", user_dict_keys_total);
|
||||
snprintf(temp_str, sizeof(temp_str), "User list: %ld", user_dict_keys_total);
|
||||
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
||||
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
||||
widget_add_icon_element(nfc->widget, 87, 13, &I_Keychain_39x36);
|
||||
if(user_dict_keys_total > 0) {
|
||||
widget_add_button_element(
|
||||
nfc->widget,
|
||||
GuiButtonTypeRight,
|
||||
"List",
|
||||
nfc_scene_mf_classic_keys_widget_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
@ -47,6 +57,12 @@ bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event)
|
||||
if(event.event == GuiButtonTypeCenter) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd);
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_previous_scene(nfc->scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysList);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,16 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventByteInputDone) {
|
||||
// Add key to dict
|
||||
bool key_added = false;
|
||||
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||
if(dict) {
|
||||
if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
|
||||
key_added = true;
|
||||
if(mf_classic_dict_is_key_present(dict, nfc->byte_input_store)) {
|
||||
scene_manager_next_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
|
||||
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||
}
|
||||
}
|
||||
if(key_added) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_classic_keys_delete_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_delete_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||
uint32_t key_index =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||
// Setup Custom Widget view
|
||||
string_t key_str;
|
||||
string_init(key_str);
|
||||
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?");
|
||||
widget_add_button_element(
|
||||
nfc->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Cancel",
|
||||
nfc_scene_mf_classic_keys_delete_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Delete",
|
||||
nfc_scene_mf_classic_keys_delete_widget_callback,
|
||||
nfc);
|
||||
|
||||
mf_classic_dict_get_key_at_index_str(dict, key_str, key_index);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str));
|
||||
|
||||
string_clear(key_str);
|
||||
mf_classic_dict_free(dict);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_keys_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t key_index =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||
if(mf_classic_dict_delete_index(dict, key_index)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
}
|
||||
mf_classic_dict_free(dict);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_delete_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
widget_reset(nfc->widget);
|
||||
}
|
100
applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100)
|
||||
|
||||
void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_list_popup_callback(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) {
|
||||
Submenu* submenu = nfc->submenu;
|
||||
uint32_t index = 0;
|
||||
string_t temp_key;
|
||||
string_init(temp_key);
|
||||
|
||||
submenu_set_header(submenu, "Select key to delete:");
|
||||
while(mf_classic_dict_get_next_key_str(dict, temp_key)) {
|
||||
char* current_key = (char*)malloc(sizeof(char) * 13);
|
||||
strncpy(current_key, string_get_cstr(temp_key), 12);
|
||||
MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
|
||||
FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
|
||||
submenu_add_item(
|
||||
submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc);
|
||||
}
|
||||
string_clear(temp_key);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_list_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||
MfClassicUserKeys_init(nfc->mfc_key_strs);
|
||||
if(dict) {
|
||||
uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict);
|
||||
if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) {
|
||||
nfc_scene_mf_classic_keys_list_prepare(nfc, dict);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
} else {
|
||||
popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
nfc->popup,
|
||||
"Edit user dictionary\nwith file browser",
|
||||
64,
|
||||
12,
|
||||
AlignCenter,
|
||||
AlignTop);
|
||||
popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
|
||||
popup_set_context(nfc->popup, nfc);
|
||||
popup_set_timeout(nfc->popup, 3000);
|
||||
popup_enable_timeout(nfc->popup);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
mf_classic_dict_free(dict);
|
||||
} else {
|
||||
popup_set_header(
|
||||
nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter);
|
||||
popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
|
||||
popup_set_context(nfc->popup, nfc);
|
||||
popup_set_timeout(nfc->popup, 3000);
|
||||
popup_enable_timeout(nfc->popup);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_list_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
MfClassicUserKeys_it_t it;
|
||||
for(MfClassicUserKeys_it(it, nfc->mfc_key_strs); !MfClassicUserKeys_end_p(it);
|
||||
MfClassicUserKeys_next(it)) {
|
||||
free(*MfClassicUserKeys_ref(it));
|
||||
}
|
||||
MfClassicUserKeys_clear(nfc->mfc_key_strs);
|
||||
submenu_reset(nfc->submenu);
|
||||
popup_reset(nfc->popup);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_classic_keys_warn_duplicate_popup_callback(void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48);
|
||||
popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
popup,
|
||||
"Please enter a\n"
|
||||
"different key.",
|
||||
4,
|
||||
24,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
popup_set_timeout(popup, 5000);
|
||||
popup_set_context(popup, nfc);
|
||||
popup_set_callback(popup, nfc_scene_mf_classic_keys_warn_duplicate_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_keys_warn_duplicate_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeysAdd);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_keys_warn_duplicate_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
popup_reset(nfc->popup);
|
||||
}
|
@ -7,6 +7,13 @@ enum SubmenuIndex {
|
||||
SubmenuIndexDynamic, // dynamic indexes start here
|
||||
};
|
||||
|
||||
void nfc_scene_mf_desfire_popup_callback(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
|
||||
MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) {
|
||||
uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >>
|
||||
1;
|
||||
@ -25,46 +32,45 @@ void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) {
|
||||
|
||||
void nfc_scene_mf_desfire_app_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
|
||||
if(!app) {
|
||||
popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42);
|
||||
popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom);
|
||||
popup_set_text(
|
||||
nfc->popup,
|
||||
"No app selected.\nThis should\nnever happen,\nplease file a bug.",
|
||||
55,
|
||||
15,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom);
|
||||
popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback);
|
||||
popup_set_context(nfc->popup, nfc);
|
||||
popup_set_timeout(nfc->popup, 3000);
|
||||
popup_enable_timeout(nfc->popup);
|
||||
popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
FURI_LOG_E(TAG, "Bad state. No app selected?");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
text_box_set_font(nfc->text_box, TextBoxFontHex);
|
||||
submenu_add_item(
|
||||
nfc->submenu,
|
||||
"App info",
|
||||
SubmenuIndexAppInfo,
|
||||
nfc_scene_mf_desfire_app_submenu_callback,
|
||||
nfc);
|
||||
|
||||
text_box_set_font(nfc->text_box, TextBoxFontHex);
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc);
|
||||
|
||||
uint16_t cap = NFC_TEXT_STORE_SIZE;
|
||||
char* buf = nfc->text_store;
|
||||
int idx = SubmenuIndexDynamic;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
int size = snprintf(buf, cap, "File %d", file->id);
|
||||
if(size < 0 || size >= cap) {
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
|
||||
break;
|
||||
uint16_t cap = NFC_TEXT_STORE_SIZE;
|
||||
char* buf = nfc->text_store;
|
||||
int idx = SubmenuIndexDynamic;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
int size = snprintf(buf, cap, "File %d", file->id);
|
||||
if(size < 0 || size >= cap) {
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
|
||||
break;
|
||||
}
|
||||
char* label = buf;
|
||||
cap -= size + 1;
|
||||
buf += size + 1;
|
||||
submenu_add_item(
|
||||
nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
|
||||
}
|
||||
char* label = buf;
|
||||
cap -= size + 1;
|
||||
buf += size + 1;
|
||||
submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
|
||||
@ -73,26 +79,30 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
|
||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
|
||||
TextBox* text_box = nfc->text_box;
|
||||
string_reset(nfc->text_box_store);
|
||||
if(event.event == SubmenuIndexAppInfo) {
|
||||
mf_df_cat_application_info(app, nfc->text_box_store);
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else {
|
||||
uint16_t index = event.event - SubmenuIndexDynamic;
|
||||
MifareDesfireFile* file = app->file_head;
|
||||
for(int i = 0; file && i < index; i++) {
|
||||
file = file->next;
|
||||
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
|
||||
TextBox* text_box = nfc->text_box;
|
||||
string_reset(nfc->text_box_store);
|
||||
if(event.event == SubmenuIndexAppInfo) {
|
||||
mf_df_cat_application_info(app, nfc->text_box_store);
|
||||
} else {
|
||||
uint16_t index = event.event - SubmenuIndexDynamic;
|
||||
MifareDesfireFile* file = app->file_head;
|
||||
for(int i = 0; file && i < index; i++) {
|
||||
file = file->next;
|
||||
}
|
||||
if(!file) {
|
||||
return false;
|
||||
}
|
||||
mf_df_cat_file(file, nfc->text_box_store);
|
||||
}
|
||||
if(!file) {
|
||||
return false;
|
||||
}
|
||||
mf_df_cat_file(file, nfc->text_box_store);
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
consumed = true;
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state & 1) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
@ -108,6 +118,7 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear views
|
||||
popup_reset(nfc->popup);
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
submenu_reset(nfc->submenu);
|
||||
|
@ -27,7 +27,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_text(
|
||||
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
|
||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
|
||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else if(state == NfcSceneMfUlReadStateReading) {
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_header(
|
||||
|
@ -34,15 +34,19 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
nfc);
|
||||
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||
string_cat_printf(temp_str, "\nPassword-protected pages!");
|
||||
if(string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
string_init_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||
string_cat_printf(temp_str, "\nPassword-protected pages!");
|
||||
}
|
||||
}
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
@ -20,7 +20,7 @@ void nfc_scene_mf_ultralight_unlock_menu_on_enter(void* context) {
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Enter Password Manually",
|
||||
"Enter PWD Manually",
|
||||
SubmenuIndexMfUlUnlockMenuManual,
|
||||
nfc_scene_mf_ultralight_unlock_menu_submenu_callback,
|
||||
nfc);
|
||||
|
@ -26,7 +26,7 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_text(
|
||||
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
|
||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
|
||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else if(state == NfcSceneReadStateReading) {
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_header(
|
||||
|
@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
|
||||
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
||||
|
@ -27,7 +27,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneSavedMenu);
|
||||
} else {
|
||||
|
@ -91,7 +91,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
bool application_info_present = false;
|
||||
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
application_info_present = true;
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
} else if(
|
||||
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
|
||||
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ void subghz_scene_decode_raw_on_enter(void* context) {
|
||||
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
|
||||
false);
|
||||
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
|
||||
|
||||
|
||||
if(decode_raw_state == SubGhzDecodeRawStateStart) {
|
||||
//Decode RAW to history
|
||||
subghz_history_reset(subghz->txrx->history);
|
||||
@ -225,6 +225,8 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz_file_encoder_worker_free(file_worker_encoder);
|
||||
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneMoreRAW);
|
||||
consumed = true;
|
||||
|
@ -50,8 +50,8 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
string_get_cstr(subghz->last_setting->preset_name),
|
||||
subghz->last_setting->frequency,
|
||||
"AM650",
|
||||
subghz_setting_get_default_frequency(subghz->setting),
|
||||
NULL,
|
||||
0);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
|
@ -113,12 +113,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SubGhzCustomEventViewReadRAWBack:
|
||||
// Check if return from config save values
|
||||
if(subghz->current_scene == SubGhzSceneReceiverConfig) {
|
||||
//FURI_LOG_I(TAG, "Raw value: %d", subghz->last_setting->detect_raw);
|
||||
subghz_last_setting_save(
|
||||
subghz->last_setting, EXT_PATH("subghz/assets/last_used.txt"));
|
||||
}
|
||||
//Stop TX
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
@ -137,14 +131,13 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
if((subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) ||
|
||||
(subghz->txrx->rx_key_state == SubGhzRxKeyStateBack)) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateExit;
|
||||
subghz->current_scene = SubGhzSceneNeedSaving;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
||||
} else {
|
||||
//Restore default setting
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
string_get_cstr(subghz->last_setting->preset_name),
|
||||
subghz->last_setting->frequency,
|
||||
"AM650",
|
||||
subghz_setting_get_default_frequency(subghz->setting),
|
||||
NULL,
|
||||
0);
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
@ -153,11 +146,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->scene_manager, SubGhzSceneStart)) {
|
||||
scene_manager_stop(subghz->scene_manager);
|
||||
view_dispatcher_stop(subghz->view_dispatcher);
|
||||
} else {
|
||||
subghz->current_scene = SubGhzSceneStart;
|
||||
}
|
||||
} else {
|
||||
subghz->current_scene = SubGhzSceneSaved;
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
@ -181,8 +170,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
case SubGhzCustomEventViewReadRAWConfig:
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
|
||||
subghz->current_scene = SubGhzSceneReceiverConfig;
|
||||
//FURI_LOG_I(TAG, "Raw value: %d", subghz->last_setting->detect_raw);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
consumed = true;
|
||||
break;
|
||||
@ -204,7 +191,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad;
|
||||
subghz->current_scene = SubGhzSceneMoreRAW;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW);
|
||||
consumed = true;
|
||||
} else {
|
||||
@ -224,7 +210,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
if(!subghz_tx_start(subghz, subghz->txrx->fff_data)) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
|
||||
subghz->current_scene = SubGhzSceneShowOnlyRx;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
|
||||
} else {
|
||||
DOLPHIN_DEED(DolphinDeedSubGhzSend);
|
||||
@ -284,7 +269,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
case SubGhzCustomEventViewReadRAWREC:
|
||||
if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) {
|
||||
subghz->current_scene = SubGhzSceneNeedSaving;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
||||
} else {
|
||||
//subghz_get_preset_name(subghz, subghz->error_str);
|
||||
@ -305,7 +289,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
|
||||
} else {
|
||||
string_set_str(subghz->error_str, "Function requires\nan SD card.");
|
||||
subghz->current_scene = SubGhzSceneShowError;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
}
|
||||
@ -317,7 +300,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSetRAW);
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
|
||||
subghz->current_scene = SubGhzSceneSaveName;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
}
|
||||
consumed = true;
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include "../subghz_i.h"
|
||||
#include "../views/receiver.h"
|
||||
|
||||
#define TAG "SubGhzSceneReceiver"
|
||||
|
||||
const NotificationSequence subghz_sequence_rx = {
|
||||
&message_green_255,
|
||||
|
||||
@ -100,18 +98,12 @@ static void subghz_scene_add_to_history_callback(
|
||||
void subghz_scene_receiver_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
subghz_last_setting_set_receiver_values(subghz->last_setting, subghz->txrx->receiver);
|
||||
|
||||
string_t str_buff;
|
||||
string_init(str_buff);
|
||||
|
||||
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) {
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
string_get_cstr(subghz->last_setting->preset_name),
|
||||
subghz->last_setting->frequency,
|
||||
NULL,
|
||||
0);
|
||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
||||
subghz_history_reset(subghz->txrx->history);
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateStart;
|
||||
}
|
||||
@ -143,8 +135,6 @@ void subghz_scene_receiver_on_enter(void* context) {
|
||||
}
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
// Set values that can be reset after using DetectRAW Scene
|
||||
subghz_last_setting_set_receiver_values(subghz->last_setting, subghz->txrx->receiver);
|
||||
subghz_begin(
|
||||
subghz,
|
||||
subghz_setting_get_preset_data_by_name(
|
||||
@ -162,12 +152,6 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SubGhzCustomEventViewReceiverBack:
|
||||
// Check if return from config save values
|
||||
if(subghz->current_scene == SubGhzSceneReceiverConfig) {
|
||||
//FURI_LOG_I(TAG, "Raw value: %d", subghz->last_setting->detect_raw);
|
||||
subghz_last_setting_save(
|
||||
subghz->last_setting, EXT_PATH("subghz/assets/last_used.txt"));
|
||||
}
|
||||
// Stop CC1101 Rx
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
@ -180,17 +164,15 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateExit;
|
||||
subghz->current_scene = SubGhzSceneNeedSaving;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
||||
} else {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
string_get_cstr(subghz->last_setting->preset_name),
|
||||
subghz->last_setting->frequency,
|
||||
"AM650",
|
||||
subghz_setting_get_default_frequency(subghz->setting),
|
||||
NULL,
|
||||
0);
|
||||
subghz->current_scene = SubGhzSceneStart;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
}
|
||||
@ -199,7 +181,6 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
case SubGhzCustomEventViewReceiverOK:
|
||||
subghz->txrx->idx_menu_chosen =
|
||||
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
subghz->current_scene = SubGhzSceneReceiverInfo;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
|
||||
consumed = true;
|
||||
break;
|
||||
@ -207,10 +188,6 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
subghz->txrx->idx_menu_chosen =
|
||||
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzViewIdReceiver, SubGhzCustomEventManagerSet);
|
||||
subghz->current_scene = SubGhzSceneReceiverConfig;
|
||||
//FURI_LOG_I(TAG, "Raw value: %d", subghz->last_setting->detect_raw);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
consumed = true;
|
||||
break;
|
||||
@ -250,8 +227,5 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void subghz_scene_receiver_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
//filter restoration
|
||||
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
|
||||
UNUSED(context);
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <lib/subghz/protocols/raw.h>
|
||||
|
||||
#define TAG "SubGhzSceneReceiverConfig"
|
||||
|
||||
enum SubGhzSettingIndex {
|
||||
SubGhzSettingIndexFrequency,
|
||||
SubGhzSettingIndexHopping,
|
||||
@ -147,8 +145,6 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
|
||||
(subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000);
|
||||
variable_item_set_current_value_text(item, text_buf);
|
||||
subghz->txrx->preset->frequency = subghz_setting_get_frequency(subghz->setting, index);
|
||||
subghz->last_setting->frequency = subghz->txrx->preset->frequency;
|
||||
subghz_setting_set_default_frequency(subghz->setting, subghz->txrx->preset->frequency);
|
||||
} else {
|
||||
variable_item_set_current_value_index(
|
||||
item, subghz_setting_get_frequency_default_index(subghz->setting));
|
||||
@ -158,13 +154,11 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
|
||||
static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
const char* preset_name = subghz_setting_get_preset_name(subghz->setting, index);
|
||||
variable_item_set_current_value_text(item, preset_name);
|
||||
string_set_str(subghz->last_setting->preset_name, preset_name);
|
||||
|
||||
variable_item_set_current_value_text(
|
||||
item, subghz_setting_get_preset_name(subghz->setting, index));
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
preset_name,
|
||||
subghz_setting_get_preset_name(subghz->setting, index),
|
||||
subghz->txrx->preset->frequency,
|
||||
subghz_setting_get_preset_data(subghz->setting, index),
|
||||
subghz_setting_get_preset_data_size(subghz->setting, index));
|
||||
@ -179,7 +173,6 @@ static void subghz_scene_receiver_config_set_rssi_threshold(VariableItem* item)
|
||||
subghz_receiver_search_decoder_base_by_name(
|
||||
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
|
||||
rssi_threshold_value[index]);
|
||||
subghz->last_setting->rssi_threshold = rssi_threshold_value[index];
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
|
||||
@ -188,7 +181,6 @@ static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
|
||||
|
||||
variable_item_set_current_value_text(item, detect_raw_text[index]);
|
||||
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
|
||||
subghz->last_setting->detect_raw = detect_raw_value[index];
|
||||
|
||||
subghz_protocol_decoder_raw_set_auto_mode(
|
||||
subghz_receiver_search_decoder_base_by_name(
|
||||
@ -230,7 +222,6 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
|
||||
}
|
||||
|
||||
subghz->txrx->hopper_state = hopping_value[index];
|
||||
subghz->last_setting->hopping = hopping_value[index];
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
|
||||
@ -244,9 +235,6 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context,
|
||||
|
||||
void subghz_scene_receiver_config_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
subghz_last_setting_set_receiver_values(subghz->last_setting, subghz->txrx->receiver);
|
||||
|
||||
VariableItem* item;
|
||||
uint8_t value_index;
|
||||
|
||||
@ -270,6 +258,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
||||
(subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000);
|
||||
variable_item_set_current_value_text(item, text_buf);
|
||||
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||
SubGhzCustomEventManagerSet) {
|
||||
item = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Hopping:",
|
||||
HOPPING_COUNT,
|
||||
subghz_scene_receiver_config_set_hopping_running,
|
||||
subghz);
|
||||
value_index = subghz_scene_receiver_config_hopper_value_index(
|
||||
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, hopping_text[value_index]);
|
||||
}
|
||||
|
||||
item = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Modulation:",
|
||||
@ -284,17 +286,6 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
||||
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||
SubGhzCustomEventManagerSet) {
|
||||
item = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Hopping:",
|
||||
HOPPING_COUNT,
|
||||
subghz_scene_receiver_config_set_hopping_running,
|
||||
subghz);
|
||||
value_index = subghz_scene_receiver_config_hopper_value_index(
|
||||
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, hopping_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Detect Raw:",
|
||||
@ -307,7 +298,10 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
||||
DETECT_RAW_COUNT);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
|
||||
}
|
||||
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||
SubGhzCustomEventManagerSet) {
|
||||
item = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"RSSI for Raw:",
|
||||
@ -321,7 +315,10 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
||||
RSSI_THRESHOLD_COUNT);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, rssi_threshold_text[value_index]);
|
||||
}
|
||||
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||
SubGhzCustomEventManagerSet) {
|
||||
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
|
||||
variable_item_list_set_enter_callback(
|
||||
subghz->variable_item_list,
|
||||
@ -348,6 +345,7 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
void subghz_scene_receiver_config_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
variable_item_list_set_selected_item(subghz->variable_item_list, 0);
|
||||
variable_item_list_reset(subghz->variable_item_list);
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);
|
||||
|
@ -14,6 +14,22 @@ void subghz_scene_save_name_text_input_callback(void* context) {
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneSaveName);
|
||||
}
|
||||
|
||||
void subghz_scene_save_name_get_timefilename(string_t name, uint32_t frequency) {
|
||||
FuriHalRtcDateTime datetime = {0};
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
string_printf(
|
||||
name,
|
||||
"RAW_%.4d.%.2d.%.2d-%.2d.%.2d.%.2d-%d.%.2dMHz",
|
||||
datetime.year,
|
||||
datetime.month,
|
||||
datetime.day,
|
||||
datetime.hour,
|
||||
datetime.minute,
|
||||
datetime.second,
|
||||
frequency / 1000000,
|
||||
(frequency / 10000) % 100);
|
||||
}
|
||||
|
||||
void subghz_scene_save_name_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
@ -42,9 +58,9 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
|
||||
SubGhzCustomEventManagerSetRAW) {
|
||||
dev_name_empty = true;
|
||||
subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME);
|
||||
subghz_scene_save_name_get_timefilename(
|
||||
file_name, subghz->txrx->preset->frequency);
|
||||
}
|
||||
path_extract_filename(subghz->file_path, file_name, true);
|
||||
}
|
||||
string_set(subghz->file_path, dir_name);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <lib/subghz/protocols/raw.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexRead = 10,
|
||||
SubmenuIndexSaved,
|
||||
@ -19,6 +21,12 @@ void subghz_scene_start_on_enter(void* context) {
|
||||
if(subghz->state_notifications == SubGhzNotificationStateStarting) {
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
}
|
||||
subghz_protocol_decoder_raw_set_auto_mode(
|
||||
subghz_receiver_search_decoder_base_by_name(
|
||||
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
|
||||
false);
|
||||
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
|
||||
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
|
||||
submenu_add_item(
|
||||
|
@ -174,25 +174,16 @@ SubGhz* subghz_alloc() {
|
||||
subghz->setting = subghz_setting_alloc();
|
||||
subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"));
|
||||
|
||||
// Load last used values for Read, Read RAW, etc. or default
|
||||
subghz->last_setting = subghz_last_setting_alloc();
|
||||
subghz_last_setting_load(subghz->last_setting, EXT_PATH("subghz/assets/last_used.txt"));
|
||||
subghz_setting_set_default_frequency(subghz->setting, subghz->last_setting->frequency);
|
||||
|
||||
//init Worker & Protocol & History & KeyBoard
|
||||
subghz->lock = SubGhzLockOff;
|
||||
subghz->txrx = malloc(sizeof(SubGhzTxRx));
|
||||
subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition));
|
||||
string_init(subghz->txrx->preset->name);
|
||||
subghz_preset_init(
|
||||
subghz,
|
||||
string_get_cstr(subghz->last_setting->preset_name),
|
||||
subghz->last_setting->frequency,
|
||||
NULL,
|
||||
0);
|
||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
||||
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||
subghz->txrx->hopper_state = subghz->last_setting->hopping;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
|
||||
subghz->txrx->history = subghz_history_alloc();
|
||||
subghz->txrx->worker = subghz_worker_alloc();
|
||||
@ -205,8 +196,6 @@ SubGhz* subghz_alloc() {
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s"));
|
||||
subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment);
|
||||
|
||||
// Setup values
|
||||
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
|
||||
|
||||
subghz_worker_set_overrun_callback(
|
||||
@ -299,9 +288,6 @@ void subghz_free(SubGhz* subghz) {
|
||||
//setting
|
||||
subghz_setting_free(subghz->setting);
|
||||
|
||||
// Last setting
|
||||
subghz_last_setting_free(subghz->last_setting);
|
||||
|
||||
//Worker & Protocol & History
|
||||
subghz_receiver_free(subghz->txrx->receiver);
|
||||
subghz_environment_free(subghz->txrx->environment);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "subghz_history.h"
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <furi.h>
|
||||
#include <m-string.h>
|
||||
|
||||
#define SUBGHZ_HISTORY_MAX 65
|
||||
#define TAG "SubGhzHistory"
|
||||
@ -37,9 +39,15 @@ SubGhzHistory* subghz_history_alloc(void) {
|
||||
|
||||
void subghz_history_free(SubGhzHistory* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// Call method instead of code duplicate
|
||||
subghz_history_reset(instance);
|
||||
string_clear(instance->tmp_string);
|
||||
for
|
||||
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
|
||||
string_clear(item->item_str);
|
||||
string_clear(item->preset->name);
|
||||
free(item->preset);
|
||||
flipper_format_free(item->flipper_string);
|
||||
item->type = 0;
|
||||
}
|
||||
SubGhzHistoryItemArray_clear(instance->history->data);
|
||||
free(instance->history);
|
||||
free(instance);
|
||||
@ -133,22 +141,16 @@ bool subghz_history_add_to_history(
|
||||
furi_assert(instance);
|
||||
furi_assert(context);
|
||||
|
||||
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) {
|
||||
FURI_LOG_W(TAG, "Out of history slots!");
|
||||
return false;
|
||||
}
|
||||
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false;
|
||||
|
||||
SubGhzProtocolDecoderBase* decoder_base = context;
|
||||
if((instance->code_last_hash_data ==
|
||||
subghz_protocol_decoder_base_get_hash_data(decoder_base)) &&
|
||||
((furi_get_tick() - instance->last_update_timestamp) < 500)) {
|
||||
//FURI_LOG_W(TAG, "Too short period for add");
|
||||
instance->last_update_timestamp = furi_get_tick();
|
||||
return false;
|
||||
}
|
||||
|
||||
//FURI_LOG_I(TAG, "Add to history. Total: %d", instance->last_index_write + 1);
|
||||
|
||||
instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base);
|
||||
instance->last_update_timestamp = furi_get_tick();
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
|
||||
#include "subghz_history.h"
|
||||
#include "subghz_setting.h"
|
||||
#include "subghz_last_setting.h"
|
||||
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
@ -101,11 +100,10 @@ struct SubGhz {
|
||||
SubGhzTestPacket* subghz_test_packet;
|
||||
string_t error_str;
|
||||
SubGhzSetting* setting;
|
||||
SubGhzLastSetting* last_setting;
|
||||
SubGhzLock lock;
|
||||
|
||||
bool in_decoder_scene;
|
||||
SubGhzScene current_scene;
|
||||
|
||||
void* rpc_ctx;
|
||||
};
|
||||
|
||||
|
@ -1,140 +0,0 @@
|
||||
#include "subghz_setting.h"
|
||||
#include "subghz_i.h"
|
||||
#include "subghz_last_setting.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <m-list.h>
|
||||
#include <furi_hal_subghz.h>
|
||||
#include <furi_hal_subghz_configs.h>
|
||||
#include <lib/subghz/protocols/raw.h>
|
||||
|
||||
#define TAG "SubGhzLastSetting"
|
||||
|
||||
#define SUBGHZ_LAST_SETTING_FILE_TYPE "Flipper SubGhz Last Setting File"
|
||||
#define SUBGHZ_LAST_SETTING_FILE_VERSION 1
|
||||
#define SUBGHZ_LAST_SETTING_DEFAULT_PRESET "AM650"
|
||||
#define SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY 433920000
|
||||
|
||||
SubGhzLastSetting* subghz_last_setting_alloc(void) {
|
||||
SubGhzLastSetting* instance = malloc(sizeof(SubGhzLastSetting));
|
||||
string_init(instance->preset_name);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_last_setting_free(SubGhzLastSetting* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
string_clear(instance->preset_name);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_last_setting_load(SubGhzLastSetting* instance, const char* file_path) {
|
||||
furi_assert(instance);
|
||||
string_init(instance->preset_name);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
|
||||
string_t temp_preset;
|
||||
string_init(temp_preset);
|
||||
uint32_t temp_frequency = 0; // Default 433920000
|
||||
uint32_t temp_hopping = 0; // Default 0
|
||||
uint32_t temp_detect_raw = 0; // Default 2
|
||||
int32_t temp_rssi_threshold = 0; // Default -72
|
||||
|
||||
if(FSE_OK == storage_sd_status(storage) && file_path &&
|
||||
flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
flipper_format_read_string(fff_data_file, "Preset", temp_preset);
|
||||
flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&temp_frequency, 1);
|
||||
flipper_format_read_uint32(fff_data_file, "Hopping", (uint32_t*)&temp_hopping, 1);
|
||||
flipper_format_read_uint32(fff_data_file, "DetectRaw", (uint32_t*)&temp_detect_raw, 1);
|
||||
flipper_format_read_int32(fff_data_file, "Rssi", (int32_t*)&temp_rssi_threshold, 1);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||
}
|
||||
|
||||
if(string_empty_p(temp_preset)) {
|
||||
FURI_LOG_D(TAG, "Last used preset not found");
|
||||
string_set(instance->preset_name, SUBGHZ_LAST_SETTING_DEFAULT_PRESET);
|
||||
} else {
|
||||
string_set(instance->preset_name, temp_preset);
|
||||
}
|
||||
|
||||
if(temp_frequency == 0 || !furi_hal_subghz_is_tx_allowed(temp_frequency)) {
|
||||
FURI_LOG_D(TAG, "Last used frequency not found or can't be used!");
|
||||
instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY;
|
||||
} else {
|
||||
instance->frequency = temp_frequency;
|
||||
}
|
||||
|
||||
if(temp_detect_raw == 0) {
|
||||
instance->detect_raw = SubGhzProtocolFlag_Decodable;
|
||||
} else {
|
||||
instance->detect_raw = temp_detect_raw;
|
||||
}
|
||||
|
||||
if(temp_rssi_threshold == 0) {
|
||||
instance->rssi_threshold = -72;
|
||||
} else {
|
||||
instance->rssi_threshold = temp_rssi_threshold;
|
||||
}
|
||||
instance->hopping = temp_hopping;
|
||||
|
||||
string_clear(temp_preset);
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
bool subghz_last_setting_save(SubGhzLastSetting* instance, const char* file_path) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool saved = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(FSE_OK != storage_sd_status(storage)) break;
|
||||
|
||||
// Open file
|
||||
if(!flipper_format_file_open_always(file, file_path)) break;
|
||||
|
||||
// Write header
|
||||
if(!flipper_format_write_header_cstr(
|
||||
file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION))
|
||||
break;
|
||||
|
||||
//FURI_LOG_D(TAG, "Preset %s", string_get_cstr(instance->preset_name));
|
||||
if(!flipper_format_insert_or_update_string_cstr(
|
||||
file, "Preset", string_get_cstr(instance->preset_name)))
|
||||
break;
|
||||
if(!flipper_format_insert_or_update_uint32(file, "Frequency", &instance->frequency, 1))
|
||||
break;
|
||||
if(!flipper_format_insert_or_update_uint32(file, "Hopping", &instance->hopping, 1)) break;
|
||||
if(!flipper_format_insert_or_update_uint32(file, "DetectRaw", &instance->detect_raw, 1))
|
||||
break;
|
||||
if(!flipper_format_insert_or_update_int32(file, "Rssi", &instance->rssi_threshold, 1))
|
||||
break;
|
||||
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
if(!saved) {
|
||||
FURI_LOG_E(TAG, "Error save file %s", file_path);
|
||||
}
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
void subghz_last_setting_set_receiver_values(SubGhzLastSetting* instance, SubGhzReceiver* receiver) {
|
||||
SubGhzProtocolDecoderBase* protocolDecoderBase =
|
||||
subghz_receiver_search_decoder_base_by_name(receiver, SUBGHZ_PROTOCOL_RAW_NAME);
|
||||
|
||||
subghz_receiver_set_filter(receiver, instance->detect_raw);
|
||||
subghz_protocol_decoder_raw_set_auto_mode(
|
||||
protocolDecoderBase, (instance->detect_raw != SubGhzProtocolFlag_Decodable));
|
||||
subghz_protocol_decoder_raw_set_rssi_threshold(protocolDecoderBase, instance->rssi_threshold);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
|
||||
typedef struct {
|
||||
string_t preset_name;
|
||||
uint32_t frequency;
|
||||
uint32_t hopping;
|
||||
uint32_t detect_raw;
|
||||
int32_t rssi_threshold;
|
||||
} SubGhzLastSetting;
|
||||
|
||||
SubGhzLastSetting* subghz_last_setting_alloc(void);
|
||||
|
||||
void subghz_last_setting_free(SubGhzLastSetting* instance);
|
||||
|
||||
void subghz_last_setting_load(SubGhzLastSetting* instance, const char* file_path);
|
||||
|
||||
bool subghz_last_setting_save(SubGhzLastSetting* instance, const char* file_path);
|
||||
|
||||
void subghz_last_setting_set_receiver_values(SubGhzLastSetting* instance, SubGhzReceiver* receiver);
|
@ -260,7 +260,13 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
|
||||
break;
|
||||
}
|
||||
if(flipper_format_read_uint32(fff_data_file, "Default_frequency", &temp_data32, 1)) {
|
||||
subghz_setting_set_default_frequency(instance, temp_data32);
|
||||
for
|
||||
M_EACH(frequency, instance->frequencies, FrequencyList_t) {
|
||||
*frequency &= FREQUENCY_MASK;
|
||||
if(*frequency == temp_data32) {
|
||||
*frequency |= FREQUENCY_FLAG_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// custom preset (optional)
|
||||
@ -288,16 +294,6 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup) {
|
||||
for
|
||||
M_EACH(frequency, instance->frequencies, FrequencyList_t) {
|
||||
*frequency &= FREQUENCY_MASK;
|
||||
if(*frequency == frequency_to_setup) {
|
||||
*frequency |= FREQUENCY_FLAG_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) {
|
||||
furi_assert(instance);
|
||||
return FrequencyList_size(instance->frequencies);
|
||||
|
@ -46,5 +46,3 @@ uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx
|
||||
uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance);
|
||||
|
||||
uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance);
|
||||
|
||||
void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup);
|
@ -340,7 +340,6 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
|
||||
return true;
|
||||
});
|
||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||
//Config receiver
|
||||
subghz_receiver->callback(SubGhzCustomEventViewReceiverConfig, subghz_receiver->context);
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
|
@ -45,7 +45,7 @@ void subghz_view_transmitter_add_data_to_show(
|
||||
}
|
||||
|
||||
static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) {
|
||||
const uint8_t button_height = 13;
|
||||
const uint8_t button_height = 12;
|
||||
const uint8_t vertical_offset = 3;
|
||||
const uint8_t horizontal_offset = 1;
|
||||
const uint8_t string_width = canvas_string_width(canvas, str);
|
||||
@ -69,7 +69,10 @@ static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str
|
||||
|
||||
canvas_invert_color(canvas);
|
||||
canvas_draw_icon(
|
||||
canvas, x + horizontal_offset, y - button_height + vertical_offset, &I_ButtonCenter_7x7);
|
||||
canvas,
|
||||
x + horizontal_offset,
|
||||
y - button_height + vertical_offset - 1,
|
||||
&I_ButtonCenter_7x7);
|
||||
canvas_draw_str(
|
||||
canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str);
|
||||
canvas_invert_color(canvas);
|
||||
|
@ -790,7 +790,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
break;
|
||||
case 1:
|
||||
canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13);
|
||||
canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up7x9);
|
||||
canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9);
|
||||
break;
|
||||
case 2:
|
||||
canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13);
|
||||
@ -845,6 +845,8 @@ void unirfremix_subghz_alloc(UniRFRemix* app) {
|
||||
UniRFRemix* unirfremix_alloc(void) {
|
||||
UniRFRemix* app = malloc(sizeof(UniRFRemix));
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
app->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
app->input_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||
@ -862,7 +864,9 @@ UniRFRemix* unirfremix_alloc(void) {
|
||||
return app;
|
||||
}
|
||||
|
||||
void unirfremix_free(UniRFRemix* app) {
|
||||
void unirfremix_free(UniRFRemix* app, bool with_subghz) {
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
|
||||
string_clear(app->up_file);
|
||||
string_clear(app->down_file);
|
||||
string_clear(app->left_file);
|
||||
@ -888,10 +892,12 @@ void unirfremix_free(UniRFRemix* app) {
|
||||
|
||||
furi_mutex_free(app->model_mutex);
|
||||
|
||||
furi_hal_subghz_sleep();
|
||||
subghz_setting_free(app->setting);
|
||||
subghz_receiver_free(app->subghz_receiver);
|
||||
subghz_environment_free(app->environment);
|
||||
if(with_subghz) {
|
||||
furi_hal_subghz_sleep();
|
||||
subghz_setting_free(app->setting);
|
||||
subghz_receiver_free(app->subghz_receiver);
|
||||
subghz_environment_free(app->environment);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
app->notification = NULL;
|
||||
@ -939,6 +945,8 @@ int32_t unirfremix_app(void* p) {
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
if(!res) {
|
||||
FURI_LOG_E(TAG, "No file selected");
|
||||
unirfremix_free(app, false);
|
||||
return 255;
|
||||
} else {
|
||||
//check map and population variables
|
||||
unirfremix_cfg_set_check(app, app->file_path);
|
||||
@ -970,8 +978,6 @@ int32_t unirfremix_app(void* p) {
|
||||
furi_mutex_release(app->model_mutex);
|
||||
view_port_update(app->view_port);
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
//input detect loop start
|
||||
InputEvent input;
|
||||
while(1) {
|
||||
@ -1164,9 +1170,7 @@ int32_t unirfremix_app(void* p) {
|
||||
}
|
||||
|
||||
// remove & free all stuff created by app
|
||||
unirfremix_free(app);
|
||||
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
unirfremix_free(app, true);
|
||||
|
||||
return 0;
|
||||
}
|
@ -109,7 +109,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
|
||||
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
|
||||
},
|
||||
{
|
||||
{.width = 1, .icon = &I_Pin_arrow_up7x9, .value = HID_KEYBOARD_L_SHIFT},
|
||||
{.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT},
|
||||
{.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA},
|
||||
{.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT},
|
||||
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},
|
||||
|
@ -53,7 +53,7 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up7x9);
|
||||
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Down
|
||||
|
@ -1,21 +1,35 @@
|
||||
# Flipfrid
|
||||
|
||||
Basic EM4100 Fuzzer
|
||||
Basic EM4100 and HIDProx Fuzzer.
|
||||
|
||||
## Why
|
||||
|
||||
Flipfrid is a simple Rfid fuzzer using EM4100 protocol (125khz).
|
||||
Objective is to provide a simple to use fuzzer to test readers by emulating various cards.
|
||||
|
||||
EM4100 cards use a 1 byte customer id and 4 bytes card id.
|
||||
- EM4100 cards use a 1 byte customer id and 4 bytes card id.
|
||||
- HIDProx cards use a 2 byte customer id and 3 byte card id.
|
||||
|
||||
## How
|
||||
|
||||
There is 4 modes :
|
||||
- Default key loop over 16 factory/default keys and emulate each one after one ;
|
||||
- BF customer id. just an iteration from 0X00 to 0XFF on the first byte ;
|
||||
- Load Dump file : Load an existing EM4100 dump generated by Flipperzero, select an index and bruteforce from 0X00 to 0XFF;
|
||||
- Uids list: loop over a text file (one uid per line)
|
||||
1) Select the Protocol with the left and right arrows
|
||||
2) Select the Mode with the up and down arrows
|
||||
|
||||
### Info
|
||||
|
||||
There are 2 Protocols:
|
||||
- EM4100
|
||||
- HIDProx
|
||||
|
||||
There are 4 modes:
|
||||
- Default Values: Try factory/default keys and emulate one after the other.
|
||||
- BF customer id: An iteration from 0X00 to 0XFF on the first byte.
|
||||
- Load Dump file: Load an existing dump (.rfid) generated by Flipperzero, select an index and bruteforce from 0X00 to 0XFF;
|
||||
- Uids list: Iterate over an input text file (one uid per line) and emulate one after the other.
|
||||
|
||||
|
||||
|
||||
|
||||
TODO :
|
||||
- blank screen on back press
|
||||
- Add second byte test to `BF customer id`
|
||||
|
@ -64,6 +64,7 @@ FlipFridState* flipfrid_alloc() {
|
||||
flipfrid->is_attacking = false;
|
||||
flipfrid->key_index = 0;
|
||||
flipfrid->menu_index = 0;
|
||||
flipfrid->menu_proto_index = 0;
|
||||
|
||||
flipfrid->attack = FlipFridAttackDefaultValues;
|
||||
flipfrid->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||
@ -73,12 +74,14 @@ FlipFridState* flipfrid_alloc() {
|
||||
flipfrid->data[2] = 0x00;
|
||||
flipfrid->data[3] = 0x00;
|
||||
flipfrid->data[4] = 0x00;
|
||||
flipfrid->data[5] = 0x00;
|
||||
|
||||
flipfrid->payload[0] = 0x00;
|
||||
flipfrid->payload[1] = 0x00;
|
||||
flipfrid->payload[2] = 0x00;
|
||||
flipfrid->payload[3] = 0x00;
|
||||
flipfrid->payload[4] = 0x00;
|
||||
flipfrid->payload[5] = 0x00;
|
||||
|
||||
//Dialog
|
||||
flipfrid->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
@ -28,6 +28,11 @@ typedef enum {
|
||||
FlipFridAttackLoadFileCustomUids,
|
||||
} FlipFridAttacks;
|
||||
|
||||
typedef enum {
|
||||
EM4100,
|
||||
HIDProx,
|
||||
} FlipFridProtos;
|
||||
|
||||
typedef enum {
|
||||
NoneScene,
|
||||
SceneEntryPoint,
|
||||
@ -56,13 +61,16 @@ typedef struct {
|
||||
FlipFridScene previous_scene;
|
||||
NotificationApp* notify;
|
||||
u_int8_t menu_index;
|
||||
u_int8_t menu_proto_index;
|
||||
|
||||
string_t data_str;
|
||||
uint8_t data[5];
|
||||
uint8_t payload[5];
|
||||
uint8_t data[6];
|
||||
uint8_t payload[6];
|
||||
uint8_t attack_step;
|
||||
FlipFridAttacks attack;
|
||||
FlipFridProtos proto;
|
||||
string_t attack_name;
|
||||
string_t proto_name;
|
||||
|
||||
DialogsApp* dialogs;
|
||||
string_t notification_msg;
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include "flipfrid_scene_entrypoint.h"
|
||||
|
||||
string_t menu_items[4];
|
||||
string_t menu_proto_items[2];
|
||||
|
||||
void flipfrid_scene_entrypoint_menu_callback(FlipFridState* context, uint32_t index) {
|
||||
void flipfrid_scene_entrypoint_menu_callback(
|
||||
FlipFridState* context,
|
||||
uint32_t index,
|
||||
uint32_t proto_index) {
|
||||
switch(index) {
|
||||
case FlipFridAttackDefaultValues:
|
||||
context->attack = FlipFridAttackDefaultValues;
|
||||
@ -27,6 +31,19 @@ void flipfrid_scene_entrypoint_menu_callback(FlipFridState* context, uint32_t in
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(proto_index) {
|
||||
case EM4100:
|
||||
context->proto = EM4100;
|
||||
string_set_str(context->proto_name, "EM4100");
|
||||
break;
|
||||
case HIDProx:
|
||||
context->proto = HIDProx;
|
||||
string_set_str(context->proto_name, "HIDProx");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||
@ -36,6 +53,7 @@ void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
context->payload[5] = 0x00;
|
||||
|
||||
context->menu_index = 0;
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
@ -46,6 +64,14 @@ void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||
string_set(menu_items[1], "BF Customer ID");
|
||||
string_set(menu_items[2], "Load File");
|
||||
string_set(menu_items[3], "Load uids from file");
|
||||
|
||||
context->menu_proto_index = 0;
|
||||
for(uint32_t i = 0; i < 2; i++) {
|
||||
string_init(menu_proto_items[i]);
|
||||
}
|
||||
|
||||
string_set(menu_proto_items[0], "EM4100");
|
||||
string_set(menu_proto_items[1], "HIDProx");
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||
@ -53,6 +79,10 @@ void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
string_clear(menu_items[i]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < 2; i++) {
|
||||
string_clear(menu_proto_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_tick(FlipFridState* context) {
|
||||
@ -74,10 +104,18 @@ void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* cont
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->menu_proto_index > EM4100) {
|
||||
context->menu_proto_index--;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->menu_proto_index < HIDProx) {
|
||||
context->menu_proto_index++;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
flipfrid_scene_entrypoint_menu_callback(context, context->menu_index);
|
||||
flipfrid_scene_entrypoint_menu_callback(
|
||||
context, context->menu_index, context->menu_proto_index);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->is_running = false;
|
||||
@ -91,10 +129,6 @@ void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Title
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "RFID Fuzzer");
|
||||
|
||||
if(context->menu_index > FlipFridAttackDefaultValues) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
@ -120,4 +154,41 @@ void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
AlignTop,
|
||||
string_get_cstr(menu_items[context->menu_index + 1]));
|
||||
}
|
||||
|
||||
if(context->menu_proto_index > EM4100) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
string_get_cstr(menu_proto_items[context->menu_proto_index - 1]));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 34, 4, AlignCenter, AlignTop, "<");
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
4,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
string_get_cstr(menu_proto_items[context->menu_proto_index]));
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 94, 4, AlignCenter, AlignTop, ">");
|
||||
|
||||
if(context->menu_proto_index < HIDProx) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
string_get_cstr(menu_proto_items[context->menu_proto_index + 1]));
|
||||
}
|
||||
}
|
@ -36,11 +36,21 @@ bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key type: %s", string_get_cstr(temp_str));
|
||||
if(strcmp(string_get_cstr(temp_str), "EM4100") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
|
||||
if(context->proto == EM4100) {
|
||||
if(strcmp(string_get_cstr(temp_str), "EM4100") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(strcmp(string_get_cstr(temp_str), "HIDProx") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,15 +63,24 @@ bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", string_get_cstr(context->data_str));
|
||||
|
||||
// Check data size
|
||||
if(string_size(context->data_str) != 14) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
if(context->proto == EM4100) {
|
||||
if(string_size(context->data_str) != 14) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(string_size(context->data_str) != 17) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include <gui/elements.h>
|
||||
|
||||
uint8_t counter = 0;
|
||||
#define TIME_BETWEEN_CARDS 5
|
||||
uint8_t id_list[16][5] = {
|
||||
#define TIME_BETWEEN_CARDS 6
|
||||
uint8_t id_list[17][5] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
@ -16,17 +16,39 @@ uint8_t id_list[16][5] = {
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_hid[14][6] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, // Incremental UID
|
||||
{0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
void flipfrid_scene_run_attack_on_enter(FlipFridState* context) {
|
||||
context->attack_step = 0;
|
||||
context->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
context->worker = lfrfid_worker_alloc(context->dict);
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
|
||||
if(context->proto == HIDProx) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "HIDProx");
|
||||
} else {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_run_attack_on_exit(FlipFridState* context) {
|
||||
@ -40,7 +62,7 @@ void flipfrid_scene_run_attack_on_exit(FlipFridState* context) {
|
||||
void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
if(context->is_attacking) {
|
||||
if(1 == counter) {
|
||||
protocol_dict_set_data(context->dict, context->protocol, context->payload, 5);
|
||||
protocol_dict_set_data(context->dict, context->protocol, context->payload, 6);
|
||||
lfrfid_worker_free(context->worker);
|
||||
context->worker = lfrfid_worker_alloc(context->dict);
|
||||
lfrfid_worker_start_thread(context->worker);
|
||||
@ -50,87 +72,180 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
lfrfid_worker_stop_thread(context->worker);
|
||||
switch(context->attack) {
|
||||
case FlipFridAttackDefaultValues:
|
||||
context->payload[0] = id_list[context->attack_step][0];
|
||||
context->payload[1] = id_list[context->attack_step][1];
|
||||
context->payload[2] = id_list[context->attack_step][2];
|
||||
context->payload[3] = id_list[context->attack_step][3];
|
||||
context->payload[4] = id_list[context->attack_step][4];
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = id_list[context->attack_step][0];
|
||||
context->payload[1] = id_list[context->attack_step][1];
|
||||
context->payload[2] = id_list[context->attack_step][2];
|
||||
context->payload[3] = id_list[context->attack_step][3];
|
||||
context->payload[4] = id_list[context->attack_step][4];
|
||||
|
||||
if(context->attack_step == 15) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FlipFridAttackBfCustomerId:
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
case FlipFridAttackLoadFile:
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
if(context->attack_step == 15) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
context->payload[0] = id_list_hid[context->attack_step][0];
|
||||
context->payload[1] = id_list_hid[context->attack_step][1];
|
||||
context->payload[2] = id_list_hid[context->attack_step][2];
|
||||
context->payload[3] = id_list_hid[context->attack_step][3];
|
||||
context->payload[4] = id_list_hid[context->attack_step][4];
|
||||
context->payload[5] = id_list_hid[context->attack_step][5];
|
||||
|
||||
if(context->attack_step == 15) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FlipFridAttackLoadFileCustomUids:
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
|
||||
case FlipFridAttackBfCustomerId:
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
context->payload[5] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FlipFridAttackLoadFile:
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 11) continue;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
context->payload[5] = context->data[5];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
case FlipFridAttackLoadFileCustomUids:
|
||||
if(context->proto == EM4100) {
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 11) continue;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 13) continue;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,16 +305,30 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 8, AlignCenter, AlignTop, string_get_cstr(context->attack_name));
|
||||
|
||||
char uid[16];
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4]);
|
||||
char uid[18];
|
||||
if(context->proto == HIDProx) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4],
|
||||
context->payload[5]);
|
||||
} else {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4]);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
@ -47,7 +47,8 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(!plugin_state->addr_err && !plugin_state->ducky_err && !plugin_state->is_thread_running) {
|
||||
if(!plugin_state->addr_err && !plugin_state->ducky_err && !plugin_state->is_thread_running &&
|
||||
!plugin_state->is_ducky_running) {
|
||||
snprintf(target_text, sizeof(target_text), target_fmt_text, target_address_str);
|
||||
canvas_draw_str_aligned(canvas, 7, 10, AlignLeft, AlignBottom, target_text);
|
||||
canvas_draw_str_aligned(canvas, 22, 20, AlignLeft, AlignBottom, "<- select address ->");
|
||||
@ -66,7 +67,10 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas, 3, 10, AlignLeft, AlignBottom, "Error: No mousejacker folder");
|
||||
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "or duckyscript file");
|
||||
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "loading error");
|
||||
} else if(plugin_state->is_thread_running) {
|
||||
} else if(plugin_state->is_thread_running && !plugin_state->is_ducky_running) {
|
||||
canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Loading...");
|
||||
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!");
|
||||
} else if(plugin_state->is_thread_running && plugin_state->is_ducky_running) {
|
||||
canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Running duckyscript");
|
||||
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!");
|
||||
canvas_draw_str_aligned(
|
||||
@ -97,7 +101,7 @@ static void hexlify(uint8_t* in, uint8_t size, char* out) {
|
||||
snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]);
|
||||
}
|
||||
|
||||
static bool open_ducky_script(Stream* stream) {
|
||||
static bool open_ducky_script(Stream* stream, PluginState* plugin_state) {
|
||||
DialogsApp* dialogs = furi_record_open("dialogs");
|
||||
bool result = false;
|
||||
string_t path;
|
||||
@ -120,6 +124,9 @@ static bool open_ducky_script(Stream* stream) {
|
||||
}
|
||||
}
|
||||
string_clear(path);
|
||||
|
||||
plugin_state->is_ducky_running = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -160,10 +167,11 @@ static bool process_ducky_file(
|
||||
uint8_t* file_buf;
|
||||
bool loaded = false;
|
||||
FURI_LOG_D(TAG, "opening ducky script");
|
||||
if(open_ducky_script(file_stream)) {
|
||||
if(open_ducky_script(file_stream, plugin_state)) {
|
||||
file_size = stream_size(file_stream);
|
||||
if(file_size == (size_t)0) {
|
||||
FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
|
||||
plugin_state->is_ducky_running = false;
|
||||
return loaded;
|
||||
}
|
||||
file_buf = malloc(file_size);
|
||||
@ -180,6 +188,7 @@ static bool process_ducky_file(
|
||||
}
|
||||
free(file_buf);
|
||||
}
|
||||
plugin_state->is_ducky_running = false;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ typedef struct {
|
||||
bool ducky_err;
|
||||
bool addr_err;
|
||||
bool is_thread_running;
|
||||
bool is_ducky_running;
|
||||
bool close_thread_please;
|
||||
Storage* storage;
|
||||
FuriThread* mjthread;
|
||||
|
@ -1,7 +1,7 @@
|
||||
App(
|
||||
appid="picopass",
|
||||
name="PicoPass Reader",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="picopass_app",
|
||||
requires=[
|
||||
"storage",
|
||||
|
@ -1,11 +1,12 @@
|
||||
App(
|
||||
appid="spectrum_analyzer",
|
||||
name="Spectrum Analyzer",
|
||||
apptype=FlipperAppType.APP,
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="spectrum_analyzer_app",
|
||||
cdefines=["APP_SPECTRUM_ANALYZER"],
|
||||
requires=["gui"],
|
||||
icon="A_SpectrumAnalyzer_14",
|
||||
stack_size=2 * 1024,
|
||||
order=12,
|
||||
fap_icon="spectrum_10px.png",
|
||||
fap_category="Tools",
|
||||
)
|
BIN
applications/plugins/spectrum_analyzer/spectrum_10px.png
Normal file
After Width: | Height: | Size: 135 B |
@ -22,15 +22,11 @@ void desktop_scene_slideshow_on_enter(void* context) {
|
||||
bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
Storage* storage = NULL;
|
||||
Power* power = NULL;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopSlideshowCompleted:
|
||||
storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_common_remove(storage, SLIDESHOW_FS_PATH);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
scene_manager_previous_scene(desktop->scene_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
@ -50,4 +46,8 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
void desktop_scene_slideshow_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_common_remove(storage, SLIDESHOW_FS_PATH);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu
|
||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9);
|
||||
break;
|
||||
case InputKeyUp:
|
||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9);
|
||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7);
|
||||
|
@ -142,6 +142,8 @@ void button_panel_reset(ButtonPanel* button_panel) {
|
||||
}
|
||||
model->reserve_x = 0;
|
||||
model->reserve_y = 0;
|
||||
model->selected_item_x = 0;
|
||||
model->selected_item_y = 0;
|
||||
LabelList_reset(model->labels);
|
||||
ButtonMatrix_reset(model->button_matrix);
|
||||
return true;
|
||||
|
@ -318,15 +318,17 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
|
||||
}
|
||||
} else if(selected == BACKSPACE_KEY) {
|
||||
text_input_backspace_cb(model);
|
||||
} else if(text_length < (model->text_buffer_size - 1)) {
|
||||
} else {
|
||||
if(model->clear_default_text) {
|
||||
text_length = 0;
|
||||
}
|
||||
if(text_length == 0 && char_is_lowercase(selected)) {
|
||||
selected = char_to_uppercase(selected);
|
||||
if(text_length < (model->text_buffer_size - 1)) {
|
||||
if(text_length == 0 && char_is_lowercase(selected)) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
model->text_buffer[text_length] = selected;
|
||||
model->text_buffer[text_length + 1] = 0;
|
||||
}
|
||||
model->text_buffer[text_length] = selected;
|
||||
model->text_buffer[text_length + 1] = 0;
|
||||
}
|
||||
model->clear_default_text = false;
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
#include "power_i.h"
|
||||
#include "views/power_off.h"
|
||||
#include "desktop/desktop_settings.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/view_port.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
#define POWER_OFF_TIMEOUT 90
|
||||
|
||||
|
@ -60,19 +60,8 @@ const char* const delay_text[DELAY_COUNT] = {
|
||||
"10min",
|
||||
"30min",
|
||||
};
|
||||
const uint32_t delay_value[DELAY_COUNT] = {
|
||||
1000,
|
||||
5000,
|
||||
10000,
|
||||
15000,
|
||||
30000,
|
||||
60000,
|
||||
90000,
|
||||
120000,
|
||||
300000,
|
||||
600000,
|
||||
1800000
|
||||
};
|
||||
const uint32_t delay_value[DELAY_COUNT] =
|
||||
{1000, 5000, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000, 1800000};
|
||||
|
||||
#define VIBRO_COUNT 2
|
||||
const char* const vibro_text[VIBRO_COUNT] = {
|
||||
|
@ -1,16 +1,5 @@
|
||||
Import("env")
|
||||
|
||||
from fbt.version import get_fast_git_version_id
|
||||
|
||||
# HACHHACK
|
||||
# Currently injected to CPPPATH by libs - since they are built earlier and depend on assets
|
||||
# env.Append(
|
||||
# CPPPATH=[
|
||||
# Dir("./compiled"),
|
||||
# ]
|
||||
# )
|
||||
version_value = Value(get_fast_git_version_id())
|
||||
|
||||
assetsenv = env.Clone(
|
||||
tools=["fbt_assets"],
|
||||
FW_LIB_NAME="assets",
|
||||
@ -77,7 +66,6 @@ assetsenv.Alias("proto_ver", proto_ver)
|
||||
|
||||
# Gather everything into a static lib
|
||||
assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver)
|
||||
assetsenv.Depends(assets_parts, version_value)
|
||||
|
||||
assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts)
|
||||
assetsenv.Install("${LIB_DIST_DIR}", assetslib)
|
||||
@ -113,6 +101,7 @@ if assetsenv["IS_BASE_FIRMWARE"]:
|
||||
)
|
||||
|
||||
# Exporting resources node to external environment
|
||||
env["FW_ASSETS_HEADERS"] = assets_parts
|
||||
env["FW_RESOURCES"] = resources
|
||||
assetsenv.Alias("resources", resources)
|
||||
|
||||
|
@ -7,7 +7,7 @@ Passive frames: 8
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7
|
||||
Active cycles: 0
|
||||
Frame rate: 4
|
||||
Frame rate: 3
|
||||
Duration: 3600
|
||||
Active cooldown: 0
|
||||
|
||||
|
BIN
assets/icons/Archive/Apps_10px.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
@ -1 +0,0 @@
|
||||
4
|
Before Width: | Height: | Size: 3.7 KiB |
BIN
assets/icons/NFC/Keychain_39x36.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@ -7,7 +7,7 @@ Passive frames: 8
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7
|
||||
Active cycles: 0
|
||||
Frame rate: 4
|
||||
Frame rate: 3
|
||||
Duration: 3600
|
||||
Active cooldown: 0
|
||||
|
||||
|
@ -1,332 +1,356 @@
|
||||
Filetype: IR library file
|
||||
Version: 1
|
||||
# Last Updated 8th Sep, 2022
|
||||
#
|
||||
# Last Updated 17th Sept, 2022
|
||||
#
|
||||
# ON
|
||||
name: POWER
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 529 7218 126 6585 219 703 180 5362 427 18618 177
|
||||
#
|
||||
name: VOL+
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9069 4362 622 486 621 487 621 491 622 1608 623 1603 622 487 621 487 621 491 622 1604 621 487 622 491 622 1604 621 491 622 1608 622 1609 621 1604 622 486 622 487 621 491 621 1605 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1604 622 491 621 1609 622 1604 621 491 621 1604 622 487 621 487 622 486 622 487 621 488 621 487 621 488 620 491 621 1609 622 1609 620 1609 621 1609 621 1609 621 1609 621 1609 621 1618 621 14330 9047 2137 620
|
||||
#
|
||||
name: VOL-
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9047 4362 621 486 622 463 645 490 622 1609 622 1604 622 487 620 487 621 491 622 1604 622 484 625 490 621 1605 649 463 621 1609 620 1611 621 1608 622 1605 621 486 622 491 622 1604 621 487 621 492 620 1604 621 488 621 492 620 1609 622 1604 621 492 622 1609 620 1605 621 491 622 1603 622 488 621 488 620 488 620 488 621 488 620 487 622 485 621 492 596 1635 621 1609 622 1585 643 1611 620 1608 621 1610 619 1611 620 1619 619 14332 9074 2109 647
|
||||
#
|
||||
name: MUTE
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9073 4336 648 461 647 484 624 489 623 1607 623 1603 622 486 622 486 622 491 622 1604 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1609 621 1608 622 1609 621 1604 621 486 622 486 622 491 622 1604 622 486 622 487 621 487 621 491 622 1608 622 1609 621 1604 622 491 621 1604 621 487 621 486 622 487 621 487 621 487 621 487 621 487 621 491 622 1608 622 1608 622 1609 621 1608 622 1608 622 1608 622 1609 621 1617 622 14330 9047 2137 620
|
||||
# ON
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 F4 00 00
|
||||
command: 4F B0 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 80 19 00 00
|
||||
command: 10 EF 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 80 19 00 00
|
||||
command: 1C E3 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 80 19 00 00
|
||||
command: 46 B9 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 80 00 00 00
|
||||
command: 51 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 40 40 00 00
|
||||
command: 0A F5 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 30 00 00
|
||||
command: 4E B1 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 30 00 00
|
||||
command: 0E F1 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 30 00 00
|
||||
command: 0D F2 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 30 00 00
|
||||
command: 4F B0 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 30 00 00
|
||||
command: 14 EB 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 08 16 00 00
|
||||
command: 87 78 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 08 16 00 00
|
||||
command: C8 37 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 01 00 00 00
|
||||
command: 01 00 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 01 00 00 00
|
||||
command: 02 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 01 00 00 00
|
||||
command: 28 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 01 00 00 00
|
||||
command: 29 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 84 F4 00 00
|
||||
command: 0B F4 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 33 00 00 00
|
||||
command: 00 FF 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 33 00 00 00
|
||||
command: 1E E1 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 33 00 00 00
|
||||
command: 1D E2 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 33 00 00 00
|
||||
command: 0B F4 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 55 00 00
|
||||
command: 90 6F 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 55 00 00
|
||||
command: 99 66 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 55 00 00
|
||||
command: 98 67 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 DF 00 00
|
||||
command: 1C E3 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 DF 00 00
|
||||
command: 4F B0 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 00 DF 00 00
|
||||
command: 4B B4 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 32 00 00 00
|
||||
command: 02 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 32 00 00 00
|
||||
command: 2E 00 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 32 00 00 00
|
||||
command: 52 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 20 00 00 00
|
||||
command: 41 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 20 00 00 00
|
||||
command: 51 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 20 00 00 00
|
||||
command: 56 00 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 20 00 00 00
|
||||
command: 5A 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: SIRC15
|
||||
address: 54 00 00 00
|
||||
command: 15 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 F4 00 00
|
||||
command: 82 7D 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 F4 00 00
|
||||
command: 83 7C 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 83 F4 00 00
|
||||
command: 14 EB 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 31 00 00 00
|
||||
command: 91 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 31 00 00 00
|
||||
command: 90 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 31 00 00 00
|
||||
command: D0 00 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 31 00 00 00
|
||||
command: 89 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 86 00 00 00
|
||||
command: 00 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 86 00 00 00
|
||||
command: 30 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 86 00 00 00
|
||||
command: 31 00 00 00
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 86 00 00 00
|
||||
command: 32 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 30 00 00 00
|
||||
command: 00 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 87 4E 00 00
|
||||
command: 0D 00 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9034 4482 593 563 569 561 571 559 563 1698 566 1694 570 559 563 568 564 566 566 1695 569 560 572 559 563 1671 593 563 569 1692 562 1671 593 1693 571 558 564 567 565 565 567 1693 571 532 590 567 565 1695 569 560 562 1698 566 1694 570 1663 591 539 593 1693 571 1688 566 564 568 1691 563 567 565 565 567 563 569 561 571 559 563 567 565 565 567 563 569 1690 564 1695 569 1691 563 1696 568 1691 563 1697 567 1692 562 1697 567 13988 9030 2223 597 96250 9035 2219 591 96245 9032 2221 589 96240 9038 2215 595 96235 9033 2220 590
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9028 4482 593 563 569 561 571 558 564 1696 568 1690 564 566 566 563 569 561 571 1688 566 563 569 561 571 1688 566 563 569 1690 564 1695 569 1689 565 1668 596 560 562 568 564 1695 569 560 562 568 564 1695 569 560 562 568 564 1695 569 1690 564 566 566 1692 572 1687 567 563 569 1690 564 566 566 564 568 562 570 559 563 567 565 565 567 562 570 560 562 1696 568 1665 589 1670 594 1665 589 1670 594 1664 590 1669 647 1612 590 13987 9031 2220 590 96223 9033 2217 593 96223 9034 2218 592 96225 9032 2219 591 96221 9087 2164 595
|
||||
#
|
||||
#
|
||||
name: MUTE
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9031 4479 596 560 572 558 564 566 566 1693 571 1688 566 563 569 561 571 559 563 1696 568 561 571 559 563 1697 567 562 570 1689 565 1694 570 1688 566 1693 571 1661 593 1693 571 558 564 566 566 564 568 1691 563 541 591 564 568 562 570 560 562 1697 567 1692 562 1696 568 562 570 1689 565 564 568 561 571 559 563 567 565 564 568 562 570 560 562 567 565 1694 570 1689 565 1694 570 1688 566 1693 571 1688 566 1693 571 1662 592 13987 9031 2220 590 96231 9034 2217 593 96234 9030 2222 588 96247 9037 2215 595
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 32 00 00 00
|
||||
command: 11 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
@ -338,22 +362,52 @@ type: parsed
|
||||
protocol: NECext
|
||||
address: 83 F4 00 00
|
||||
command: 4E B1 00 00
|
||||
#
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 03 00 00 00
|
||||
command: 1D 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 03 00 00 00
|
||||
command: 11 00 00 00
|
||||
#
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 03 00 00 00
|
||||
command: 15 00 00 00
|
||||
#
|
||||
# OFF
|
||||
name: POWER
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: Samsung32
|
||||
address: 07 00 00 00
|
||||
command: E6 00 00 00
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: Samsung32
|
||||
address: 07 00 00 00
|
||||
command: 07 00 00 00
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: Samsung32
|
||||
address: 07 00 00 00
|
||||
command: 0B 00 00 00
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: Samsung32
|
||||
address: 07 00 00 00
|
||||
command: 0F 00 00 00
|
||||
#
|
||||
|