Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
commit
f785ce1f91
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -113,7 +113,7 @@ jobs:
|
||||
run: |
|
||||
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
|
||||
chmod 600 ./deploy_key;
|
||||
rsync -avzP --mkpath \
|
||||
rsync -avzP --delete --mkpath \
|
||||
-e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
|
||||
artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/";
|
||||
rm ./deploy_key;
|
||||
|
||||
4
.vscode/.gitignore
vendored
Normal file
4
.vscode/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
./c_cpp_properties.json
|
||||
./launch.json
|
||||
./settings.json
|
||||
./tasks.json
|
||||
17
.vscode/ReadMe.md
vendored
Normal file
17
.vscode/ReadMe.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Visual Studio Code workspace for Flipper Zero
|
||||
|
||||
## Setup
|
||||
|
||||
* To start developing with VSCode, run `./fbt vscode_dist` in project root. _That should only be done once_
|
||||
* After that, open firmware folder in VSCode: "File" > "Open folder"
|
||||
|
||||
For more details on fbt, see [fbt docs](../documentation/fbt.md).
|
||||
|
||||
|
||||
## Workflow
|
||||
|
||||
Commands for building firmware are invoked through Build menu: Ctrl+Shift+B.
|
||||
|
||||
To attach a debugging session, first build and flash firmware, then choose your debug probe in Debug menu (Ctrl+Shift+D).
|
||||
|
||||
Note that you have to detach debugging session before rebuilding and re-flashing firmware.
|
||||
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Mac",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
87
.vscode/example/launch.json
vendored
Normal file
87
.vscode/example/launch.json
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"inputs": [
|
||||
{
|
||||
"id": "BLACKMAGIC",
|
||||
"type": "command",
|
||||
"command": "shellCommand.execute",
|
||||
"args": {
|
||||
"command": "./fbt get_blackmagic",
|
||||
"description": "Get Blackmagic device",
|
||||
}
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach FW (ST-Link)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/latest/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "stlink",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/stlink.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
// "attach 1",
|
||||
"compare-sections",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "Attach FW (blackmagic)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/latest/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "external",
|
||||
"gdbTarget": "${input:BLACKMAGIC}",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"monitor swdp_scan",
|
||||
"attach 1",
|
||||
"set confirm off",
|
||||
"set mem inaccessible-by-default off",
|
||||
"compare-sections",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "Attach FW (JLink)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/latest/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "jlink",
|
||||
"interface": "swd",
|
||||
"device": "STM32WB55RG",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "fbt debug",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "./lib/scons/scripts/scons.py",
|
||||
"args": [
|
||||
"sdk"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python debug",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
22
.vscode/example/settings.json
vendored
Normal file
22
.vscode/example/settings.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"C_Cpp.default.cStandard": "gnu17",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"python.formatting.provider": "black",
|
||||
"workbench.tree.indent": 12,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.showRTOS": true,
|
||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin",
|
||||
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
|
||||
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
|
||||
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/i686-windows/openocd/bin/openocd.exe",
|
||||
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
|
||||
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"*.scons": "python",
|
||||
"SConscript": "python",
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python",
|
||||
}
|
||||
}
|
||||
103
.vscode/example/tasks.json
vendored
Normal file
103
.vscode/example/tasks.json
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "[Release] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (JLink)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 jflash"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (JLink)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 jflash"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build update bundle",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt updater_package COMPACT=1 DEBUG=0"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build update bundle",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt updater_package"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build updater",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt updater_all COMPACT=1 DEBUG=0"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build updater",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt updater_all"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (USB, w/o resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, w/o resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Debug:unit_tests] Flash (USB)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, with resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
|
||||
},
|
||||
]
|
||||
}
|
||||
15
.vscode/extensions.json
vendored
Normal file
15
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"ms-vscode.cpptools",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
@ -274,8 +274,13 @@ distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"get_blackmagic",
|
||||
"@echo $( ${BLACKMAGIC_ADDR} $)",
|
||||
)
|
||||
|
||||
# Prepare vscode environment
|
||||
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
||||
distenv.Precious(vscode_dist)
|
||||
distenv.NoClean(vscode_dist)
|
||||
distenv.Alias("vscode_dist", vscode_dist)
|
||||
|
||||
@ -45,7 +45,7 @@ static DialogMessageButton compliance_screen(DialogsApp* dialogs, DialogMessage*
|
||||
DialogMessageButton result;
|
||||
|
||||
const char* screen_text = "For all compliance\n"
|
||||
"certificates please visit\n"
|
||||
"certificates please visit:\n"
|
||||
"www.flipp.dev/compliance";
|
||||
|
||||
dialog_message_set_text(message, screen_text, 0, 0, AlignLeft, AlignTop);
|
||||
@ -91,13 +91,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage*
|
||||
furi_hal_version_get_hw_region_name(),
|
||||
my_name ? my_name : "Unknown");
|
||||
|
||||
string_cat_printf(buffer, "Serial number:\n");
|
||||
string_cat_printf(buffer, "Serial Number:\n");
|
||||
const uint8_t* uid = furi_hal_version_uid();
|
||||
for(size_t i = 0; i < furi_hal_version_uid_size(); i++) {
|
||||
string_cat_printf(buffer, "%02X", uid[i]);
|
||||
}
|
||||
|
||||
dialog_message_set_header(message, "HW Version info:", 0, 0, AlignLeft, AlignTop);
|
||||
dialog_message_set_header(message, "HW Version Info:", 0, 0, AlignLeft, AlignTop);
|
||||
dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop);
|
||||
result = dialog_message_show(dialogs, message);
|
||||
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
|
||||
@ -133,7 +133,7 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage*
|
||||
version_get_gitbranch(ver));
|
||||
}
|
||||
|
||||
dialog_message_set_header(message, "FW Version info:", 0, 0, AlignLeft, AlignTop);
|
||||
dialog_message_set_header(message, "FW Version Info:", 0, 0, AlignLeft, AlignTop);
|
||||
dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop);
|
||||
result = dialog_message_show(dialogs, message);
|
||||
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
|
||||
|
||||
@ -32,14 +32,14 @@ void AccessorApp::run(void) {
|
||||
}
|
||||
|
||||
AccessorApp::AccessorApp() {
|
||||
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||
onewire_host = onewire_host_alloc();
|
||||
furi_hal_power_enable_otg();
|
||||
}
|
||||
|
||||
AccessorApp::~AccessorApp() {
|
||||
furi_hal_power_disable_otg();
|
||||
furi_record_close("notification");
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
onewire_host_free(onewire_host);
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ AccessorAppViewManager::AccessorAppViewManager() {
|
||||
popup = popup_alloc();
|
||||
add_view(ViewType::Popup, popup_get_view(popup));
|
||||
|
||||
gui = static_cast<Gui*>(furi_record_open("gui"));
|
||||
gui = static_cast<Gui*>(furi_record_open(RECORD_GUI));
|
||||
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// set previous view callback for all views
|
||||
@ -31,6 +31,7 @@ AccessorAppViewManager::~AccessorAppViewManager() {
|
||||
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup));
|
||||
|
||||
// free view modules
|
||||
furi_record_close(RECORD_GUI);
|
||||
submenu_free(submenu);
|
||||
popup_free(popup);
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ uint16_t archive_favorites_count(void* context) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue; // Skip empty lines
|
||||
}
|
||||
++lines;
|
||||
}
|
||||
@ -93,7 +93,7 @@ static bool archive_favourites_rescan() {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, "/app:") == 0) {
|
||||
@ -152,7 +152,7 @@ bool archive_favorites_read(void* context) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, "/app:") == 0) {
|
||||
@ -215,7 +215,7 @@ bool archive_favorites_delete(const char* format, ...) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, filename)) {
|
||||
@ -259,7 +259,7 @@ bool archive_is_favorite(const char* format, ...) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(!string_search(buffer, filename)) {
|
||||
found = true;
|
||||
@ -299,7 +299,7 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
archive_file_append(
|
||||
|
||||
@ -92,8 +92,6 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
ArchiveBrowserView* browser = archive->browser;
|
||||
ArchiveFile_t* selected = archive_get_current_file(browser);
|
||||
|
||||
const char* name = archive_get_name(browser);
|
||||
bool known_app = archive_is_known_app(selected->type);
|
||||
bool favorites = archive_get_tab(browser) == ArchiveTabFavorites;
|
||||
bool consumed = false;
|
||||
|
||||
@ -108,18 +106,19 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
break;
|
||||
case ArchiveBrowserEventFileMenuRun:
|
||||
if(known_app) {
|
||||
if(archive_is_known_app(selected->type)) {
|
||||
archive_run_in_app(browser, selected);
|
||||
archive_show_file_menu(browser, false);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
case ArchiveBrowserEventFileMenuPin:
|
||||
case ArchiveBrowserEventFileMenuPin: {
|
||||
const char* name = archive_get_name(browser);
|
||||
if(favorites) {
|
||||
archive_favorites_delete(name);
|
||||
archive_file_array_rm_selected(browser);
|
||||
archive_show_file_menu(browser, false);
|
||||
} else if(known_app) {
|
||||
} else if(archive_is_known_app(selected->type)) {
|
||||
if(archive_is_favorite("%s", name)) {
|
||||
archive_favorites_delete("%s", name);
|
||||
} else {
|
||||
@ -128,12 +127,12 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
archive_show_file_menu(browser, false);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ArchiveBrowserEventFileMenuRename:
|
||||
if(favorites) {
|
||||
browser->callback(ArchiveBrowserEventEnterFavMove, browser->context);
|
||||
} else if((known_app) && (selected->is_app == false)) {
|
||||
} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
|
||||
archive_show_file_menu(browser, false);
|
||||
scene_manager_set_scene_state(
|
||||
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH);
|
||||
|
||||
@ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) {
|
||||
false);
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
string_get_cstr(archive->browser->path), archive->file_extension, NULL);
|
||||
string_get_cstr(archive->browser->path), archive->file_extension, "");
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
string_clear(filename);
|
||||
|
||||
@ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
|
||||
|
||||
string_init(app->file_path);
|
||||
|
||||
if(arg != NULL) {
|
||||
if(arg && strlen(arg)) {
|
||||
string_set_str(app->file_path, arg);
|
||||
}
|
||||
|
||||
@ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
|
||||
bad_usb_free(app->bad_usb_view);
|
||||
|
||||
|
||||
@ -38,6 +38,5 @@ struct BadUsbApp {
|
||||
|
||||
typedef enum {
|
||||
BadUsbAppViewError,
|
||||
BadUsbAppViewFileSelect,
|
||||
BadUsbAppViewWork,
|
||||
} BadUsbAppView;
|
||||
|
||||
@ -90,7 +90,7 @@ BtHid* bt_hid_app_alloc() {
|
||||
submenu_add_item(
|
||||
app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Media player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app);
|
||||
app->submenu, "Media Player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app);
|
||||
submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app);
|
||||
view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit);
|
||||
view_dispatcher_add_view(
|
||||
@ -103,7 +103,7 @@ BtHid* bt_hid_app_alloc() {
|
||||
dialog_ex_set_left_button_text(app->dialog, "Exit");
|
||||
dialog_ex_set_right_button_text(app->dialog, "Stay");
|
||||
dialog_ex_set_center_button_text(app->dialog, "Menu");
|
||||
dialog_ex_set_header(app->dialog, "Close current app?", 16, 12, AlignLeft, AlignTop);
|
||||
dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BtHidViewExitConfirm, dialog_ex_get_view(app->dialog));
|
||||
|
||||
|
||||
@ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) {
|
||||
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
|
||||
}
|
||||
|
||||
int32_t bt_srv() {
|
||||
int32_t bt_srv(void* p) {
|
||||
UNUSED(p);
|
||||
Bt* bt = bt_alloc();
|
||||
|
||||
if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
||||
|
||||
@ -10,9 +10,9 @@ void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result,
|
||||
void bt_settings_scene_forget_dev_confirm_on_enter(void* context) {
|
||||
BtSettingsApp* app = context;
|
||||
DialogEx* dialog = app->dialog;
|
||||
dialog_ex_set_header(dialog, "Unpair all devices?", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog, "Unpair All Devices?", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog, "All previous pairings\nwill be lost.", 64, 22, AlignCenter, AlignTop);
|
||||
dialog, "All previous pairings\nwill be lost!", 64, 22, AlignCenter, AlignTop);
|
||||
dialog_ex_set_left_button_text(dialog, "Back");
|
||||
dialog_ex_set_right_button_text(dialog, "Unpair");
|
||||
dialog_ex_set_context(dialog, app);
|
||||
|
||||
@ -439,9 +439,9 @@ void cli_session_open(Cli* cli, void* session) {
|
||||
cli->session = session;
|
||||
if(cli->session != NULL) {
|
||||
cli->session->init();
|
||||
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
|
||||
furi_thread_set_stdout_callback(cli->session->tx_stdout);
|
||||
} else {
|
||||
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||
furi_thread_set_stdout_callback(NULL);
|
||||
}
|
||||
furi_semaphore_release(cli->idle_sem);
|
||||
furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk);
|
||||
@ -455,7 +455,7 @@ void cli_session_close(Cli* cli) {
|
||||
cli->session->deinit();
|
||||
}
|
||||
cli->session = NULL;
|
||||
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||
furi_thread_set_stdout_callback(NULL);
|
||||
furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk);
|
||||
}
|
||||
|
||||
@ -469,9 +469,9 @@ int32_t cli_srv(void* p) {
|
||||
furi_record_create(RECORD_CLI, cli);
|
||||
|
||||
if(cli->session != NULL) {
|
||||
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
|
||||
furi_thread_set_stdout_callback(cli->session->tx_stdout);
|
||||
} else {
|
||||
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||
furi_thread_set_stdout_callback(NULL);
|
||||
}
|
||||
|
||||
if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(last);
|
||||
printf("%-24s: %s\r\n", key, value);
|
||||
printf("%-30s: %s\r\n", key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -25,7 +25,7 @@ struct CliSession {
|
||||
void (*deinit)(void);
|
||||
size_t (*rx)(uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
void (*tx)(const uint8_t* buffer, size_t size);
|
||||
void (*tx_stdout)(void* _cookie, const char* data, size_t size);
|
||||
void (*tx_stdout)(const char* data, size_t size);
|
||||
bool (*is_connected)(void);
|
||||
};
|
||||
|
||||
|
||||
@ -277,8 +277,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) {
|
||||
UNUSED(_cookie);
|
||||
static void cli_vcp_tx_stdout(const char* data, size_t size) {
|
||||
cli_vcp_tx((const uint8_t*)data, size);
|
||||
}
|
||||
|
||||
|
||||
@ -26,11 +26,11 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
canvas_clear(canvas);
|
||||
char strings[5][20];
|
||||
|
||||
sprintf(strings[0], "Ok: %d", state->ok);
|
||||
sprintf(strings[1], "L: %d", state->left);
|
||||
sprintf(strings[2], "R: %d", state->right);
|
||||
sprintf(strings[3], "U: %d", state->up);
|
||||
sprintf(strings[4], "D: %d", state->down);
|
||||
snprintf(strings[0], 20, "Ok: %d", state->ok);
|
||||
snprintf(strings[1], 20, "L: %d", state->left);
|
||||
snprintf(strings[2], 20, "R: %d", state->right);
|
||||
snprintf(strings[3], 20, "U: %d", state->up);
|
||||
snprintf(strings[4], 20, "D: %d", state->down);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 0, 10, "Keypad test");
|
||||
|
||||
@ -143,7 +143,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
|
||||
furi_assert(view);
|
||||
bool activate = true;
|
||||
BubbleAnimationViewModel* model = view_get_model(view->view);
|
||||
if(!model->current) {
|
||||
if(model->current == NULL) {
|
||||
activate = false;
|
||||
} else if(model->freeze_frame) {
|
||||
activate = false;
|
||||
@ -151,14 +151,16 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
|
||||
activate = false;
|
||||
}
|
||||
|
||||
if(!force) {
|
||||
if((model->active_ended_at + model->current->active_cooldown * 1000) >
|
||||
xTaskGetTickCount()) {
|
||||
activate = false;
|
||||
} else if(model->active_shift) {
|
||||
activate = false;
|
||||
} else if(model->current_frame >= model->current->passive_frames) {
|
||||
activate = false;
|
||||
if(model->current != NULL) {
|
||||
if(!force) {
|
||||
if((model->active_ended_at + model->current->active_cooldown * 1000) >
|
||||
xTaskGetTickCount()) {
|
||||
activate = false;
|
||||
} else if(model->active_shift) {
|
||||
activate = false;
|
||||
} else if(model->current_frame >= model->current->passive_frames) {
|
||||
activate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
view_commit_model(view->view, false);
|
||||
@ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) {
|
||||
bubble_animation_activate(view, false);
|
||||
|
||||
BubbleAnimationViewModel* model = view_get_model(view->view);
|
||||
uint8_t frame_rate = model->current->icon_animation.frame_rate;
|
||||
uint8_t frame_rate = 0;
|
||||
if(model->current != NULL) {
|
||||
frame_rate = model->current->icon_animation.frame_rate;
|
||||
}
|
||||
view_commit_model(view->view, false);
|
||||
|
||||
if(frame_rate) {
|
||||
|
||||
@ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
|
||||
extern int32_t desktop_settings_app(void* p) {
|
||||
DesktopSettingsApp* app = desktop_settings_app_alloc();
|
||||
LOAD_DESKTOP_SETTINGS(&app->settings);
|
||||
if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) {
|
||||
if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
|
||||
|
||||
@ -23,7 +23,7 @@ void desktop_debug_render(Canvas* canvas, void* model) {
|
||||
const Version* ver;
|
||||
char buffer[64];
|
||||
|
||||
static const char* headers[] = {"FW Version info:", "Dolphin info:"};
|
||||
static const char* headers[] = {"FW Version Info:", "Dolphin Info:"};
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
@ -78,7 +78,6 @@ void desktop_debug_render(Canvas* canvas, void* model) {
|
||||
canvas_draw_str(canvas, 5, 50 + STATUS_BAR_Y_SHIFT, buffer);
|
||||
|
||||
} else {
|
||||
char buffer[64];
|
||||
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
|
||||
DolphinStats stats = dolphin_stats(dolphin);
|
||||
furi_record_close(RECORD_DOLPHIN);
|
||||
@ -87,18 +86,20 @@ void desktop_debug_render(Canvas* canvas, void* model) {
|
||||
uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(buffer, 64, "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt);
|
||||
snprintf(buffer, sizeof(buffer), "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt);
|
||||
canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer);
|
||||
|
||||
snprintf(
|
||||
buffer,
|
||||
64,
|
||||
sizeof(buffer),
|
||||
"Level: %ld To level up: %ld",
|
||||
current_lvl,
|
||||
(remaining == (uint32_t)(-1) ? remaining : 0));
|
||||
canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, buffer);
|
||||
|
||||
snprintf(buffer, 64, "%s", asctime(localtime((const time_t*)&m->timestamp)));
|
||||
// even if timestamp is uint64_t, it's safe to cast it to uint32_t, because furi_hal_rtc_datetime_to_timestamp only returns uint32_t
|
||||
snprintf(buffer, sizeof(buffer), "%ld", (uint32_t)m->timestamp);
|
||||
|
||||
canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer);
|
||||
canvas_draw_str(canvas, 0, 49 + STATUS_BAR_Y_SHIFT, "[< >] icounter value [ok] save");
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) {
|
||||
const char* str = Lockmenu_Items[i];
|
||||
|
||||
if(i == 1 && !m->pin_set) str = "Set PIN";
|
||||
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented";
|
||||
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not Implemented";
|
||||
|
||||
if(str != NULL)
|
||||
canvas_draw_str_aligned(
|
||||
|
||||
@ -20,7 +20,7 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event);
|
||||
static void gpio_test_draw_callback(Canvas* canvas, void* _model) {
|
||||
GpioTestModel* model = _model;
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Gpio Output mode test");
|
||||
elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "GPIO Output Mode Test");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
|
||||
|
||||
@ -185,17 +185,19 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
|
||||
return false;
|
||||
});
|
||||
|
||||
if(item->type == ButtonMenuItemTypeControl) {
|
||||
if(type == InputTypeShort) {
|
||||
if(item && item->callback) {
|
||||
item->callback(item->callback_context, item->index, type);
|
||||
if(item) {
|
||||
if(item->type == ButtonMenuItemTypeControl) {
|
||||
if(type == InputTypeShort) {
|
||||
if(item && item->callback) {
|
||||
item->callback(item->callback_context, item->index, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(item->type == ButtonMenuItemTypeCommon) {
|
||||
if((type == InputTypePress) || (type == InputTypeRelease)) {
|
||||
if(item && item->callback) {
|
||||
item->callback(item->callback_context, item->index, type);
|
||||
if(item->type == ButtonMenuItemTypeCommon) {
|
||||
if((type == InputTypePress) || (type == InputTypeRelease)) {
|
||||
if(item && item->callback) {
|
||||
item->callback(item->callback_context, item->index, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +131,9 @@ static bool char_is_lowercase(char letter) {
|
||||
}
|
||||
|
||||
static char char_to_uppercase(const char letter) {
|
||||
if(isalpha(letter)) {
|
||||
if(letter == '_') {
|
||||
return 0x20;
|
||||
} else if(isalpha(letter)) {
|
||||
return (letter - 0x20);
|
||||
} else {
|
||||
return letter;
|
||||
@ -147,7 +149,7 @@ static void text_input_backspace_cb(TextInputModel* model) {
|
||||
|
||||
static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
TextInputModel* model = _model;
|
||||
uint8_t text_length = strlen(model->text_buffer);
|
||||
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
|
||||
uint8_t needed_string_width = canvas_width(canvas) - 8;
|
||||
uint8_t start_pos = 4;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// #include <gui/view.h>
|
||||
#include <m-string.h>
|
||||
#include <core/common_defines.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@ -9,20 +9,6 @@
|
||||
|
||||
#define TAG "iButtonApp"
|
||||
|
||||
static const NotificationSequence sequence_blink_start_cyan = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_cyan,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_start_magenta = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_magenta,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_set_yellow = {
|
||||
&message_blink_set_color_yellow,
|
||||
NULL,
|
||||
@ -33,11 +19,6 @@ static const NotificationSequence sequence_blink_set_magenta = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence* ibutton_notification_sequences[] = {
|
||||
&sequence_error,
|
||||
&sequence_success,
|
||||
@ -106,6 +87,8 @@ static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context)
|
||||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(
|
||||
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||
ibutton->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
||||
} else if(event == RpcAppEventLoadFile) {
|
||||
@ -324,22 +307,6 @@ void ibutton_text_store_clear(iButton* ibutton) {
|
||||
memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE);
|
||||
}
|
||||
|
||||
void ibutton_switch_to_previous_scene_one_of(
|
||||
iButton* ibutton,
|
||||
const uint32_t* scene_ids,
|
||||
size_t scene_ids_size) {
|
||||
furi_assert(scene_ids_size);
|
||||
SceneManager* scene_manager = ibutton->scene_manager;
|
||||
|
||||
for(size_t i = 0; i < scene_ids_size; ++i) {
|
||||
const uint32_t scene_id = scene_ids[i];
|
||||
if(scene_manager_has_previous_scene(scene_manager, scene_id)) {
|
||||
scene_manager_search_and_switch_to_previous_scene(scene_manager, scene_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibutton_notification_message(iButton* ibutton, uint32_t message) {
|
||||
furi_assert(message < sizeof(ibutton_notification_sequences) / sizeof(NotificationSequence*));
|
||||
notification_message(ibutton->notifications, ibutton_notification_sequences[message]);
|
||||
@ -353,7 +320,7 @@ int32_t ibutton_app(void* p) {
|
||||
bool key_loaded = false;
|
||||
bool rpc_mode = false;
|
||||
|
||||
if(p) {
|
||||
if(p && strlen(p)) {
|
||||
uint32_t rpc_ctx = 0;
|
||||
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
|
||||
FURI_LOG_D(TAG, "Running in RPC mode");
|
||||
|
||||
@ -83,8 +83,4 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name);
|
||||
bool ibutton_delete_key(iButton* ibutton);
|
||||
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
|
||||
void ibutton_text_store_clear(iButton* ibutton);
|
||||
void ibutton_switch_to_previous_scene_one_of(
|
||||
iButton* ibutton,
|
||||
const uint32_t* scene_ids,
|
||||
size_t scene_ids_size);
|
||||
void ibutton_notification_message(iButton* ibutton, uint32_t message);
|
||||
|
||||
@ -21,7 +21,7 @@ void ibutton_scene_exit_confirm_on_enter(void* context) {
|
||||
widget_add_string_element(
|
||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu?");
|
||||
widget_add_string_element(
|
||||
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost.");
|
||||
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
|
||||
|
||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ void ibutton_scene_read_on_enter(void* context) {
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
||||
|
||||
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59);
|
||||
|
||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||
|
||||
@ -21,7 +21,7 @@ void ibutton_scene_retry_confirm_on_enter(void* context) {
|
||||
widget_add_string_element(
|
||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
|
||||
widget_add_string_element(
|
||||
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost.");
|
||||
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
|
||||
|
||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == iButtonCustomEventRpcLoad) {
|
||||
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
|
||||
bool result = false;
|
||||
if(arg) {
|
||||
if(arg && (string_empty_p(ibutton->file_path))) {
|
||||
string_set_str(ibutton->file_path, arg);
|
||||
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
||||
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
|
||||
@ -51,17 +51,17 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
string_clear(key_name);
|
||||
result = true;
|
||||
} else {
|
||||
string_reset(ibutton->file_path);
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
} else if(event.event == iButtonCustomEventRpcExit) {
|
||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true);
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||
scene_manager_stop(ibutton->scene_manager);
|
||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||
ibutton->rpc_ctx = NULL;
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||
scene_manager_stop(ibutton->scene_manager);
|
||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
} else {
|
||||
const uint32_t possible_scenes[] = {
|
||||
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||
ibutton_switch_to_previous_scene_one_of(
|
||||
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
ibutton->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,8 +31,8 @@ bool ibutton_scene_save_success_on_event(void* context, SceneManagerEvent event)
|
||||
if(event.event == iButtonCustomEventBack) {
|
||||
const uint32_t possible_scenes[] = {
|
||||
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||
ibutton_switch_to_previous_scene_one_of(
|
||||
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
ibutton->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,8 +31,8 @@ bool ibutton_scene_write_success_on_event(void* context, SceneManagerEvent event
|
||||
consumed = true;
|
||||
if(event.event == iButtonCustomEventBack) {
|
||||
const uint32_t possible_scenes[] = {iButtonSceneReadKeyMenu, iButtonSceneStart};
|
||||
ibutton_switch_to_previous_scene_one_of(
|
||||
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
ibutton->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,10 +7,12 @@ static const NotificationSequence* infrared_notification_sequences[] = {
|
||||
&sequence_success,
|
||||
&sequence_set_only_green_255,
|
||||
&sequence_reset_green,
|
||||
&sequence_blink_cyan_10,
|
||||
&sequence_blink_magenta_10,
|
||||
&sequence_solid_yellow,
|
||||
&sequence_reset_rgb};
|
||||
&sequence_reset_rgb,
|
||||
&sequence_blink_start_cyan,
|
||||
&sequence_blink_start_magenta,
|
||||
&sequence_blink_stop,
|
||||
};
|
||||
|
||||
static void infrared_make_app_folder(Infrared* infrared) {
|
||||
if(!storage_simply_mkdir(infrared->storage, INFRARED_APP_FOLDER)) {
|
||||
@ -44,6 +46,8 @@ static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context
|
||||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
|
||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||
infrared->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
|
||||
@ -301,6 +305,7 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedIrSend);
|
||||
infrared_worker_tx_start(infrared->worker);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
|
||||
void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
|
||||
@ -310,14 +315,17 @@ void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
|
||||
InfraredSignal* signal = infrared_remote_button_get_signal(button);
|
||||
|
||||
infrared_tx_start_signal(infrared, signal);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
|
||||
void infrared_tx_start_received(Infrared* infrared) {
|
||||
infrared_tx_start_signal(infrared, infrared->received_signal);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
|
||||
void infrared_tx_stop(Infrared* infrared) {
|
||||
infrared_worker_tx_stop(infrared->worker);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
}
|
||||
|
||||
void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...) {
|
||||
@ -354,12 +362,6 @@ void infrared_show_loading_popup(Infrared* infrared, bool show) {
|
||||
}
|
||||
}
|
||||
|
||||
void infrared_signal_sent_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Infrared* infrared = context;
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend);
|
||||
}
|
||||
|
||||
void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) {
|
||||
furi_assert(context);
|
||||
Infrared* infrared = context;
|
||||
@ -405,7 +407,7 @@ int32_t infrared_app(void* p) {
|
||||
bool is_remote_loaded = false;
|
||||
bool is_rpc_mode = false;
|
||||
|
||||
if(p) {
|
||||
if(p && strlen(p)) {
|
||||
uint32_t rpc_ctx = 0;
|
||||
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
|
||||
infrared->rpc_ctx = (void*)rpc_ctx;
|
||||
|
||||
@ -27,7 +27,7 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv
|
||||
|
||||
if(infrared_worker_signal_is_decoded(received_signal)) {
|
||||
const InfraredMessage* message = infrared_worker_get_decoded_signal(received_signal);
|
||||
buf_cnt = sniprintf(
|
||||
buf_cnt = snprintf(
|
||||
buf,
|
||||
sizeof(buf),
|
||||
"%s, A:0x%0*lX, C:0x%0*lX%s\r\n",
|
||||
@ -43,13 +43,13 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv
|
||||
size_t timings_cnt;
|
||||
infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt);
|
||||
|
||||
buf_cnt = sniprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt);
|
||||
buf_cnt = snprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt);
|
||||
cli_write(cli, (uint8_t*)buf, buf_cnt);
|
||||
for(size_t i = 0; i < timings_cnt; ++i) {
|
||||
buf_cnt = sniprintf(buf, sizeof(buf), "%lu ", timings[i]);
|
||||
buf_cnt = snprintf(buf, sizeof(buf), "%lu ", timings[i]);
|
||||
cli_write(cli, (uint8_t*)buf, buf_cnt);
|
||||
}
|
||||
buf_cnt = sniprintf(buf, sizeof(buf), "\r\n");
|
||||
buf_cnt = snprintf(buf, sizeof(buf), "\r\n");
|
||||
cli_write(cli, (uint8_t*)buf, buf_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,10 +115,11 @@ typedef enum {
|
||||
InfraredNotificationMessageSuccess,
|
||||
InfraredNotificationMessageGreenOn,
|
||||
InfraredNotificationMessageGreenOff,
|
||||
InfraredNotificationMessageBlinkRead,
|
||||
InfraredNotificationMessageBlinkSend,
|
||||
InfraredNotificationMessageYellowOn,
|
||||
InfraredNotificationMessageYellowOff,
|
||||
InfraredNotificationMessageBlinkStartRead,
|
||||
InfraredNotificationMessageBlinkStartSend,
|
||||
InfraredNotificationMessageBlinkStop,
|
||||
} InfraredNotificationMessage;
|
||||
|
||||
bool infrared_add_remote_with_button(Infrared* infrared, const char* name, InfraredSignal* signal);
|
||||
@ -132,7 +133,6 @@ void infrared_text_store_clear(Infrared* infrared, uint32_t bank);
|
||||
void infrared_play_notification_message(Infrared* infrared, uint32_t message);
|
||||
void infrared_show_loading_popup(Infrared* infrared, bool show);
|
||||
|
||||
void infrared_signal_sent_callback(void* context);
|
||||
void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal);
|
||||
void infrared_text_input_callback(void* context);
|
||||
void infrared_popup_closed_callback(void* context);
|
||||
|
||||
@ -21,12 +21,14 @@ static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint3
|
||||
infrared_progress_view_set_back_callback(
|
||||
progress, infrared_scene_universal_common_progress_back_callback, infrared);
|
||||
view_stack_add_view(view_stack, infrared_progress_view_get_view(progress));
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
|
||||
static void infrared_scene_universal_common_hide_popup(Infrared* infrared) {
|
||||
ViewStack* view_stack = infrared->view_stack;
|
||||
InfraredProgressView* progress = infrared->progress;
|
||||
view_stack_remove_view(view_stack, infrared_progress_view_get_view(progress));
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
}
|
||||
|
||||
void infrared_scene_universal_common_on_enter(void* context) {
|
||||
@ -42,7 +44,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
|
||||
|
||||
if(infrared_brute_force_is_started(brute_force)) {
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend);
|
||||
bool success = infrared_brute_force_send_next(brute_force);
|
||||
if(success) {
|
||||
success = infrared_progress_view_increase_progress(infrared->progress);
|
||||
@ -71,8 +72,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
|
||||
brute_force, infrared_custom_event_get_value(event.event), &record_count)) {
|
||||
DOLPHIN_DEED(DolphinDeedIrBruteForce);
|
||||
infrared_scene_universal_common_show_popup(infrared, record_count);
|
||||
infrared_play_notification_message(
|
||||
infrared, InfraredNotificationMessageBlinkSend);
|
||||
} else {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases);
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ void infrared_scene_ask_back_on_enter(void* context) {
|
||||
DialogEx* dialog_ex = infrared->dialog_ex;
|
||||
|
||||
if(infrared->app_state.is_learning_new_remote) {
|
||||
dialog_ex_set_header(dialog_ex, "Exit to Infrared menu?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Exit to Infrared Menu?", 64, 0, AlignCenter, AlignTop);
|
||||
} else {
|
||||
dialog_ex_set_header(dialog_ex, "Exit to remote menu?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Exit to Remote Menu?", 64, 0, AlignCenter, AlignTop);
|
||||
}
|
||||
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Exit");
|
||||
dialog_ex_set_center_button_text(dialog_ex, NULL);
|
||||
|
||||
@ -9,9 +9,9 @@ void infrared_scene_ask_retry_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
DialogEx* dialog_ex = infrared->dialog_ex;
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Return to reading?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Return to Reading?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Exit");
|
||||
dialog_ex_set_center_button_text(dialog_ex, NULL);
|
||||
|
||||
@ -65,4 +65,5 @@ void infrared_scene_debug_on_exit(void* context) {
|
||||
InfraredWorker* worker = infrared->worker;
|
||||
infrared_worker_rx_stop(worker);
|
||||
infrared_worker_rx_enable_blink_on_receiving(worker, false);
|
||||
infrared_worker_rx_set_received_signal_callback(worker, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ void infrared_scene_edit_delete_on_enter(void* context) {
|
||||
int32_t current_button_index = infrared->app_state.current_button_index;
|
||||
furi_assert(current_button_index != InfraredButtonIndexNone);
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Delete button?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Delete Button?", 64, 0, AlignCenter, AlignTop);
|
||||
InfraredRemoteButton* current_button =
|
||||
infrared_remote_get_button(remote, current_button_index);
|
||||
InfraredSignal* signal = infrared_remote_button_get_signal(current_button);
|
||||
@ -45,7 +45,7 @@ void infrared_scene_edit_delete_on_enter(void* context) {
|
||||
}
|
||||
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Delete Remote?", 64, 0, AlignCenter, AlignTop);
|
||||
infrared_text_store_set(
|
||||
infrared,
|
||||
0,
|
||||
@ -97,7 +97,7 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event)
|
||||
} else {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@ -28,8 +28,10 @@ bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent e
|
||||
scene_manager, InfraredSceneRemote);
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneStart, InfraredSceneRemoteList};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
if(!scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes))) {
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
}
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
@ -21,7 +21,10 @@ bool infrared_scene_edit_rename_done_on_event(void* context, SceneManagerEvent e
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote);
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
infrared->scene_manager, InfraredSceneRemote)) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ void infrared_scene_learn_on_enter(void* context) {
|
||||
infrared_worker_rx_set_received_signal_callback(
|
||||
worker, infrared_signal_received_callback, context);
|
||||
infrared_worker_rx_start(worker);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartRead);
|
||||
|
||||
popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31);
|
||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter);
|
||||
@ -22,10 +23,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkRead);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypeSignalReceived) {
|
||||
infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess);
|
||||
@ -41,6 +39,7 @@ void infrared_scene_learn_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
infrared_worker_rx_stop(infrared->worker);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
popup_set_icon(popup, 0, 0, NULL);
|
||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignCenter);
|
||||
}
|
||||
|
||||
@ -29,7 +29,10 @@ bool infrared_scene_learn_done_on_event(void* context, SceneManagerEvent event)
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote);
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
infrared->scene_manager, InfraredSceneRemote)) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
|
||||
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, context);
|
||||
infrared_worker_tx_set_signal_sent_callback(
|
||||
infrared->worker, infrared_signal_sent_callback, context);
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
@ -104,6 +102,8 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
|
||||
InfraredSceneLearnSuccess,
|
||||
InfraredSceneLearnSuccessStateSending);
|
||||
infrared_tx_start_received(infrared);
|
||||
infrared_play_notification_message(
|
||||
infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExReleaseCenter) {
|
||||
@ -111,6 +111,7 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
|
||||
scene_manager_set_scene_state(
|
||||
scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
|
||||
infrared_tx_stop(infrared);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||
}
|
||||
consumed = true;
|
||||
@ -124,7 +125,7 @@ void infrared_scene_learn_success_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
InfraredWorker* worker = infrared->worker;
|
||||
dialog_ex_reset(infrared->dialog_ex);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||
infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL);
|
||||
infrared_worker_tx_set_signal_sent_callback(worker, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -33,8 +33,6 @@ void infrared_scene_remote_on_enter(void* context) {
|
||||
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||
infrared_worker_tx_set_signal_sent_callback(
|
||||
infrared->worker, infrared_signal_sent_callback, infrared);
|
||||
|
||||
size_t button_count = infrared_remote_get_button_count(remote);
|
||||
for(size_t i = 0; i < button_count; ++i) {
|
||||
@ -80,7 +78,7 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
const uint16_t custom_type = infrared_custom_event_get_type(event.event);
|
||||
const int16_t button_index = infrared_custom_event_get_value(event.event);
|
||||
@ -112,7 +110,7 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
void infrared_scene_remote_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
infrared_tx_stop(infrared);
|
||||
infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
|
||||
infrared_worker_tx_set_signal_sent_callback(infrared->worker, NULL, NULL);
|
||||
button_menu_reset(infrared->button_menu);
|
||||
}
|
||||
|
||||
@ -1,20 +1,28 @@
|
||||
#include "../infrared_i.h"
|
||||
#include "gui/canvas.h"
|
||||
|
||||
typedef enum {
|
||||
InfraredRpcStateIdle,
|
||||
InfraredRpcStateLoaded,
|
||||
InfraredRpcStateSending,
|
||||
} InfraredRpcState;
|
||||
|
||||
void infrared_scene_rpc_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
|
||||
popup_set_header(popup, "Infrared", 82, 28, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_header(popup, "Infrared", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
popup_set_context(popup, context);
|
||||
popup_set_callback(popup, infrared_popup_closed_callback);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
|
||||
|
||||
scene_manager_set_scene_state(infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateIdle);
|
||||
|
||||
notification_message(infrared->notifications, &sequence_display_backlight_on);
|
||||
}
|
||||
|
||||
@ -24,6 +32,8 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
InfraredRpcState state =
|
||||
scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc);
|
||||
if(event.event == InfraredCustomEventTypeBackPressed) {
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
@ -31,41 +41,51 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.event == InfraredCustomEventTypeRpcLoad) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||
if(arg) {
|
||||
if(arg && (state == InfraredRpcStateIdle)) {
|
||||
string_set_str(infrared->file_path, arg);
|
||||
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||
infrared_worker_tx_set_signal_sent_callback(
|
||||
infrared->worker, infrared_signal_sent_callback, infrared);
|
||||
if(result) {
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||
}
|
||||
}
|
||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||
|
||||
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
||||
popup_set_text(
|
||||
infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop);
|
||||
infrared->popup, infrared->text_store[0], 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||
if(arg) {
|
||||
if(arg && (state == InfraredRpcStateLoaded)) {
|
||||
size_t button_index = 0;
|
||||
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
||||
infrared_tx_start_button_index(infrared, button_index);
|
||||
result = true;
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending);
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
|
||||
infrared_tx_stop(infrared);
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true);
|
||||
bool result = false;
|
||||
if(state == InfraredRpcStateSending) {
|
||||
infrared_tx_stop(infrared);
|
||||
result = true;
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||
}
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcExit) {
|
||||
scene_manager_stop(infrared->scene_manager);
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
|
||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||
infrared->rpc_ctx = NULL;
|
||||
scene_manager_stop(infrared->scene_manager);
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
}
|
||||
}
|
||||
@ -74,5 +94,9 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
void infrared_scene_rpc_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
if(scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc) ==
|
||||
InfraredRpcStateSending) {
|
||||
infrared_tx_stop(infrared);
|
||||
}
|
||||
popup_reset(infrared->popup);
|
||||
}
|
||||
|
||||
@ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
int32_t input_srv() {
|
||||
int32_t input_srv(void* p) {
|
||||
UNUSED(p);
|
||||
input = malloc(sizeof(Input));
|
||||
input->thread_id = furi_thread_get_current_id();
|
||||
input->event_pubsub = furi_pubsub_alloc();
|
||||
|
||||
@ -56,6 +56,9 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::RpcSessionClose;
|
||||
app->view_controller.send_event(&event);
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
} else if(rpc_event == RpcAppEventAppExit) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Exit;
|
||||
@ -74,22 +77,25 @@ void LfRfidApp::run(void* _args) {
|
||||
|
||||
make_app_folder();
|
||||
|
||||
if(strlen(args)) {
|
||||
if(args && strlen(args)) {
|
||||
uint32_t rpc_ctx_ptr = 0;
|
||||
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
|
||||
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
||||
rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
|
||||
rpc_system_app_send_started(rpc_ctx);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeDesktop);
|
||||
scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
|
||||
scene_controller.process(100, SceneType::Rpc);
|
||||
} else {
|
||||
string_set_str(file_path, args);
|
||||
load_key_data(file_path, &worker.key, true);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||
scene_controller.process(100, SceneType::Emulate);
|
||||
}
|
||||
|
||||
} else {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
||||
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
|
||||
|
||||
@ -101,5 +101,4 @@ public:
|
||||
bool save_key_data(string_t path, RfidKey* key);
|
||||
|
||||
void make_app_folder();
|
||||
//bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context);
|
||||
};
|
||||
|
||||
@ -107,7 +107,7 @@ static void lfrfid_cli_write(Cli* cli, string_t args) {
|
||||
UNUSED(cli);
|
||||
UNUSED(args);
|
||||
// TODO implement rfid write
|
||||
printf("Not implemented :(\r\n");
|
||||
printf("Not Implemented :(\r\n");
|
||||
}
|
||||
|
||||
static void lfrfid_cli_emulate(Cli* cli, string_t args) {
|
||||
|
||||
@ -2,18 +2,6 @@
|
||||
#include <core/common_defines.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static const NotificationSequence sequence_blink_start_magenta = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_magenta,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(data_string);
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@ void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
|
||||
line_1->set_text("Exit to RFID menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_2->set_text(
|
||||
"All unsaved data will be lost.", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
"All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
@ -17,9 +17,9 @@ void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore *
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
|
||||
line_1->set_text("Return to reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_2->set_text(
|
||||
"All unsaved data will be lost.", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
"All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
@ -3,24 +3,12 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
static const NotificationSequence sequence_blink_start_magenta = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_magenta,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("LF RFID", 89, 30, AlignCenter, AlignTop);
|
||||
popup->set_text("RPC mode", 89, 43, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom);
|
||||
popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
|
||||
@ -39,33 +27,25 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
app->view_controller.send_event(&view_event);
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
|
||||
consumed = true;
|
||||
LfRfidApp::Event view_event;
|
||||
view_event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&view_event);
|
||||
} else if(event->type == LfRfidApp::EventType::EmulateStart) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
consumed = true;
|
||||
emulating = true;
|
||||
|
||||
app->text_store.set("emulating\n%s", app->worker.key.get_name());
|
||||
popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
|
||||
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||
consumed = true;
|
||||
bool result = false;
|
||||
if(arg) {
|
||||
if(arg && !emulating) {
|
||||
string_set_str(app->file_path, arg);
|
||||
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::EmulateStart;
|
||||
app->view_controller.send_event(&event);
|
||||
app->worker.start_emulate();
|
||||
emulating = true;
|
||||
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
app->text_store.set("emulating\n%s", app->worker.key.get_name());
|
||||
popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ LfRfidDebugApp::~LfRfidDebugApp() {
|
||||
}
|
||||
|
||||
void LfRfidDebugApp::run() {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
|
||||
scene_controller.process(100);
|
||||
|
||||
@ -5,6 +5,6 @@ App(
|
||||
entry_point="loader_srv",
|
||||
cdefines=["SRV_LOADER"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
stack_size=2 * 1024,
|
||||
order=90,
|
||||
)
|
||||
|
||||
@ -300,7 +300,7 @@ int32_t music_player_app(void* p) {
|
||||
string_init(file_path);
|
||||
|
||||
do {
|
||||
if(p) {
|
||||
if(p && strlen(p)) {
|
||||
string_cat_str(file_path, p);
|
||||
} else {
|
||||
string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
|
||||
|
||||
@ -10,7 +10,7 @@ App(
|
||||
],
|
||||
provides=["nfc_start"],
|
||||
icon="A_NFC_14",
|
||||
stack_size=4 * 1024,
|
||||
stack_size=5 * 1024,
|
||||
order=30,
|
||||
)
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ static void nfc_generate_mf_ul_orig(NfcDeviceData* data) {
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUnknown;
|
||||
mful->data_size = 16 * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
// TODO: what's internal byte on page 2?
|
||||
memset(&mful->data[4 * 4], 0xFF, 4);
|
||||
@ -67,6 +68,7 @@ static void nfc_generate_mf_ul_ntag203(NfcDeviceData* data) {
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeNTAG203;
|
||||
mful->data_size = 42 * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
mful->data[9] = 0x48; // Internal byte
|
||||
memcpy(&mful->data[3 * 4], default_data_ntag203, sizeof(default_data_ntag203));
|
||||
@ -78,6 +80,7 @@ static void nfc_generate_mf_ul_with_config_common(NfcDeviceData* data, uint8_t n
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->data_size = num_pages * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
uint16_t config_index = (num_pages - 4) * 4;
|
||||
mful->data[config_index] = 0x04; // STRG_MOD_EN
|
||||
@ -180,6 +183,7 @@ static void
|
||||
mful->type = type;
|
||||
memcpy(&mful->version, version_bytes_ntag_i2c, sizeof(version_bytes_ntag_i2c));
|
||||
mful->data_size = num_pages * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
memcpy(mful->data, data->nfc_data.uid, data->nfc_data.uid_len);
|
||||
mful->data[7] = data->nfc_data.sak;
|
||||
mful->data[8] = data->nfc_data.atqa[0];
|
||||
|
||||
@ -21,6 +21,8 @@ static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||
|
||||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
|
||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||
nfc->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
} else if(event == RpcAppEventLoadFile) {
|
||||
@ -199,18 +201,6 @@ void nfc_text_store_clear(Nfc* nfc) {
|
||||
memset(nfc->text_store, 0, sizeof(nfc->text_store));
|
||||
}
|
||||
|
||||
static const NotificationSequence sequence_blink_start_blue = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_blue,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void nfc_blink_start(Nfc* nfc) {
|
||||
notification_message(nfc->notifications, &sequence_blink_start_blue);
|
||||
}
|
||||
@ -238,7 +228,7 @@ int32_t nfc_app(void* p) {
|
||||
char* args = p;
|
||||
|
||||
// Check argument and run corresponding scene
|
||||
if((*args != '\0')) {
|
||||
if(args && strlen(args)) {
|
||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
||||
uint32_t rpc_ctx = 0;
|
||||
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
|
||||
|
||||
0
applications/nfc/nfc_i.h
Executable file → Normal file
0
applications/nfc/nfc_i.h
Executable file → Normal file
@ -15,11 +15,17 @@ ADD_SCENE(nfc, emulate_uid, EmulateUid)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
|
||||
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_auth_result, MfUltralightReadAuthResult)
|
||||
ADD_SCENE(nfc, mf_ultralight_key_input, MfUltralightKeyInput)
|
||||
ADD_SCENE(nfc, mf_ultralight_unlock_menu, MfUltralightUnlockMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_unlock_warn, MfUltralightUnlockWarn)
|
||||
ADD_SCENE(nfc, mf_desfire_read_success, MfDesfireReadSuccess)
|
||||
ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu)
|
||||
ADD_SCENE(nfc, mf_desfire_data, MfDesfireData)
|
||||
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
||||
ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess)
|
||||
ADD_SCENE(nfc, mf_classic_info, MfClassicInfo)
|
||||
ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
|
||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||
|
||||
@ -37,7 +37,7 @@ static void nfc_scene_detect_reader_widget_config(Nfc* nfc, bool data_received)
|
||||
|
||||
widget_add_icon_element(widget, 0, 14, &I_Reader_detect);
|
||||
widget_add_string_element(
|
||||
widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold near reader");
|
||||
widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold Near Reader");
|
||||
widget_add_string_element(widget, 55, 22, AlignLeft, AlignTop, FontPrimary, "Emulating...");
|
||||
|
||||
if(data_received) {
|
||||
|
||||
@ -12,9 +12,9 @@ void nfc_scene_exit_confirm_on_enter(void* context) {
|
||||
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Exit");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Stay");
|
||||
dialog_ex_set_header(dialog_ex, "Exit to NFC menu?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Exit to NFC Menu?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data\nwill be lost.", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_exit_confirm_dialog_callback);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexMfClassicKeys,
|
||||
SubmenuIndexMfUltralightUnlock,
|
||||
};
|
||||
|
||||
void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
|
||||
@ -20,6 +21,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
||||
SubmenuIndexMfClassicKeys,
|
||||
nfc_scene_extra_actions_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Unlock NTAG/Ultralight",
|
||||
SubmenuIndexMfUltralightUnlock,
|
||||
nfc_scene_extra_actions_submenu_callback,
|
||||
nfc);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
@ -35,6 +42,8 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexMfUltralightUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
#define TAG "NfcMfClassicDictAttack"
|
||||
|
||||
typedef enum {
|
||||
DictAttackStateIdle,
|
||||
DictAttackStateUserDictInProgress,
|
||||
@ -32,7 +34,9 @@ static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) {
|
||||
|
||||
static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) {
|
||||
MfClassicData* data = &nfc->dev->dev_data.mf_classic_data;
|
||||
NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data;
|
||||
NfcWorkerState worker_state = NfcWorkerStateReady;
|
||||
MfClassicDict* dict = NULL;
|
||||
|
||||
// Identify scene state
|
||||
if(state == DictAttackStateIdle) {
|
||||
@ -47,16 +51,36 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt
|
||||
|
||||
// Setup view
|
||||
if(state == DictAttackStateUserDictInProgress) {
|
||||
worker_state = NfcWorkerStateMfClassicUserDictAttack;
|
||||
worker_state = NfcWorkerStateMfClassicDictAttack;
|
||||
dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict.");
|
||||
} else if(state == DictAttackStateFlipperDictInProgress) {
|
||||
worker_state = NfcWorkerStateMfClassicFlipperDictAttack;
|
||||
dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict.");
|
||||
dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||
|
||||
// If failed to load user dictionary - try flipper dictionary
|
||||
if(!dict) {
|
||||
FURI_LOG_E(TAG, "User dictionary not found");
|
||||
state = DictAttackStateFlipperDictInProgress;
|
||||
}
|
||||
}
|
||||
if(state == DictAttackStateFlipperDictInProgress) {
|
||||
worker_state = NfcWorkerStateMfClassicDictAttack;
|
||||
dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict.");
|
||||
dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper);
|
||||
if(!dict) {
|
||||
FURI_LOG_E(TAG, "Flipper dictionary not found");
|
||||
// Pass through to let worker handle the failure
|
||||
}
|
||||
}
|
||||
// Free previous dictionary
|
||||
if(dict_attack_data->dict) {
|
||||
mf_classic_dict_free(dict_attack_data->dict);
|
||||
}
|
||||
dict_attack_data->dict = dict;
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state);
|
||||
dict_attack_set_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc);
|
||||
dict_attack_set_current_sector(nfc->dict_attack, 0);
|
||||
dict_attack_set_card_detected(nfc->dict_attack, data->type);
|
||||
dict_attack_set_total_dict_keys(
|
||||
nfc->dict_attack, dict ? mf_classic_dict_get_total_keys(dict) : 0);
|
||||
nfc_scene_mf_classic_dict_attack_update_view(nfc);
|
||||
nfc_worker_start(
|
||||
nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc);
|
||||
@ -112,6 +136,10 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
nfc_scene_mf_classic_dict_attack_update_view(nfc);
|
||||
dict_attack_inc_current_sector(nfc->dict_attack);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventNewDictKeyBatch) {
|
||||
nfc_scene_mf_classic_dict_attack_update_view(nfc);
|
||||
dict_attack_inc_current_dict_key(nfc->dict_attack, NFC_DICT_KEY_BATCH_SIZE);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventDictAttackSkip) {
|
||||
if(state == DictAttackStateUserDictInProgress) {
|
||||
nfc_worker_stop(nfc->worker);
|
||||
@ -130,8 +158,13 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
|
||||
void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data;
|
||||
// Stop worker
|
||||
nfc_worker_stop(nfc->worker);
|
||||
if(dict_attack_data->dict) {
|
||||
mf_classic_dict_free(dict_attack_data->dict);
|
||||
dict_attack_data->dict = NULL;
|
||||
}
|
||||
dict_attack_reset(nfc->dict_attack);
|
||||
nfc_blink_stop(nfc);
|
||||
}
|
||||
|
||||
72
applications/nfc/scenes/nfc_scene_mf_classic_info.c
Normal file
72
applications/nfc/scenes/nfc_scene_mf_classic_info.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_classic_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
Nfc* nfc = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
string_t str_tmp;
|
||||
string_init(str_tmp);
|
||||
|
||||
// Setup view
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, mf_classic_get_type_str(mf_data->type));
|
||||
widget_add_string_element(
|
||||
widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)");
|
||||
string_printf(str_tmp, "UID:");
|
||||
for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) {
|
||||
string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(
|
||||
str_tmp,
|
||||
"ATQA: %02X %02X SAK: %02X",
|
||||
dev_data->nfc_data.atqa[0],
|
||||
dev_data->nfc_data.atqa[1],
|
||||
dev_data->nfc_data.sak);
|
||||
widget_add_string_element(
|
||||
widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
||||
string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 55, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
|
||||
string_clear(str_tmp);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_info_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(nfc->widget);
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_classic_menu_submenu_callback(void* context, uint32_t index) {
|
||||
@ -19,6 +20,9 @@ void nfc_scene_mf_classic_menu_on_enter(void* context) {
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_classic_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mf_classic_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_classic_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicMenu));
|
||||
|
||||
@ -43,6 +47,11 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexEmulate);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
|
||||
44
applications/nfc/scenes/nfc_scene_mf_ultralight_key_input.c
Normal file
44
applications/nfc/scenes/nfc_scene_mf_ultralight_key_input.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_key_input_byte_input_callback(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_key_input_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_scene_mf_ultralight_key_input_byte_input_callback,
|
||||
NULL,
|
||||
nfc,
|
||||
nfc->byte_input_store,
|
||||
4);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_key_input_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventByteInputDone) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockWarn);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_key_input_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(nfc->byte_input, "");
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexUnlock,
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulate,
|
||||
};
|
||||
@ -14,7 +15,16 @@ void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index
|
||||
void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data;
|
||||
|
||||
if(data->data_read != data->data_size) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Unlock With Password",
|
||||
SubmenuIndexUnlock,
|
||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||
nfc);
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
@ -35,19 +45,20 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightMenu, SubmenuIndexSave);
|
||||
nfc->dev->format = NfcDeviceSaveFormatMifareUl;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightMenu, SubmenuIndexEmulate);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, event.event);
|
||||
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
107
applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c
Normal file
107
applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c
Normal file
@ -0,0 +1,107 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
NfcSceneMfUlReadStateIdle,
|
||||
NfcSceneMfUlReadStateDetecting,
|
||||
NfcSceneMfUlReadStateReading,
|
||||
NfcSceneMfUlReadStateNotSupportedCard,
|
||||
} NfcSceneMfUlReadState;
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_auth_worker_callback(NfcWorkerEvent event, void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
if(event == NfcWorkerEventMfUltralightPassKey) {
|
||||
memcpy(nfc->dev->dev_data.mf_ul_data.auth_key, nfc->byte_input_store, 4);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState state) {
|
||||
uint32_t curr_state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth);
|
||||
if(curr_state != state) {
|
||||
if(state == NfcSceneMfUlReadStateDetecting) {
|
||||
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);
|
||||
} else if(state == NfcSceneMfUlReadStateReading) {
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_header(
|
||||
nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop);
|
||||
popup_set_icon(nfc->popup, 12, 23, &A_Loading_24);
|
||||
} else if(state == NfcSceneMfUlReadStateNotSupportedCard) {
|
||||
popup_reset(nfc->popup);
|
||||
popup_set_header(nfc->popup, "Wrong type of card!", 64, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
nfc->popup,
|
||||
"Only MIFARE\nUltralight & NTAG\n are supported",
|
||||
4,
|
||||
22,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
popup_set_icon(nfc->popup, 73, 17, &I_DolphinFirstStart8_56x51);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth, state);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||
|
||||
nfc_device_clear(nfc->dev);
|
||||
// Setup view
|
||||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateDetecting);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
// Start worker
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateReadMfUltralightReadAuth,
|
||||
&nfc->dev->dev_data,
|
||||
nfc_scene_mf_ultralight_read_auth_worker_callback,
|
||||
nfc);
|
||||
|
||||
nfc_blink_start(nfc);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_auth_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if((event.event == NfcWorkerEventSuccess) || (event.event == NfcWorkerEventFail)) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuthResult);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventCardDetected) {
|
||||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateReading);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventNoCardDetected) {
|
||||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateDetecting);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventWrongCardDetected) {
|
||||
nfc_scene_mf_ultralight_read_auth_set_state(
|
||||
nfc, NfcSceneMfUlReadStateNotSupportedCard);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Stop worker
|
||||
nfc_worker_stop(nfc->worker);
|
||||
// Clear view
|
||||
popup_reset(nfc->popup);
|
||||
nfc_blink_stop(nfc);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadAuth, NfcSceneMfUlReadStateIdle);
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_result_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_ultralight_read_auth_result_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup dialog view
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(mf_ul_data);
|
||||
Widget* widget = nfc->widget;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
if((mf_ul_data->data_read == mf_ul_data->data_size) && (mf_ul_data->data_read > 0)) {
|
||||
widget_add_string_element(
|
||||
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "All pages are unlocked!");
|
||||
} else {
|
||||
widget_add_string_element(
|
||||
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Not all pages unlocked!");
|
||||
}
|
||||
string_set_str(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 17, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
if(mf_ul_data->auth_success) {
|
||||
string_printf(
|
||||
temp_str,
|
||||
"Password: %02X %02X %02X %02X",
|
||||
config_pages->auth_data.pwd.raw[0],
|
||||
config_pages->auth_data.pwd.raw[1],
|
||||
config_pages->auth_data.pwd.raw[2],
|
||||
config_pages->auth_data.pwd.raw[3]);
|
||||
widget_add_string_element(
|
||||
widget, 0, 28, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
string_printf(
|
||||
temp_str,
|
||||
"PACK: %02X %02X",
|
||||
config_pages->auth_data.pack.raw[0],
|
||||
config_pages->auth_data.pack.raw[1]);
|
||||
widget_add_string_element(
|
||||
widget, 0, 39, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
}
|
||||
string_printf(
|
||||
temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
widget_add_string_element(
|
||||
widget, 0, 50, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
"Save",
|
||||
nfc_scene_mf_ultralight_read_auth_result_widget_callback,
|
||||
nfc);
|
||||
|
||||
string_clear(temp_str);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_auth_result_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatMifareUl;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_result_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean views
|
||||
widget_reset(nfc->widget);
|
||||
}
|
||||
94
applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c
Executable file → Normal file
94
applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c
Executable file → Normal file
@ -1,51 +1,67 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
|
||||
|
||||
enum {
|
||||
ReadMifareUlStateShowUID,
|
||||
ReadMifareUlStateShowInfo,
|
||||
ReadMifareUlStateShowData,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_read_success_dialog_callback(DialogExResult result, void* context) {
|
||||
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup dialog view
|
||||
// Setup widget view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||
dialog_ex_set_center_button_text(dialog_ex, "Data");
|
||||
dialog_ex_set_header(
|
||||
dialog_ex, nfc_mf_ul_type(mf_ul_data->type, true), 64, 8, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
|
||||
// Display UID
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
NFC_SCENE_READ_SUCCESS_SHIFT "ATQA: %02X%02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
|
||||
"SAK: %02X\nUID: %02X %02X %02X %02X %02X %02X %02X",
|
||||
data->atqa[0],
|
||||
data->atqa[1],
|
||||
data->sak,
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 16, AlignLeft, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_ultralight_read_success_dialog_callback);
|
||||
Widget* widget = nfc->widget;
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeCenter,
|
||||
"Data",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
"More",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_t data_str;
|
||||
string_init_printf(data_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(data_str, " %02X", data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
string_printf(
|
||||
data_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
widget_add_string_element(
|
||||
widget, 0, 24, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||
widget_add_string_element(
|
||||
widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-protected pages!");
|
||||
}
|
||||
string_clear(data_str);
|
||||
|
||||
// Setup TextBox view
|
||||
TextBox* text_box = nfc->text_box;
|
||||
@ -60,8 +76,8 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowUID);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
@ -71,13 +87,13 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(state == ReadMifareUlStateShowUID && event.event == DialogExResultLeft) {
|
||||
if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultRight) {
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultCenter) {
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeCenter) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData);
|
||||
@ -85,9 +101,9 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == ReadMifareUlStateShowData) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowUID);
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
@ -102,7 +118,7 @@ void nfc_scene_mf_ultralight_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean views
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
widget_reset(nfc->widget);
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
}
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexMfUlUnlockMenuManual,
|
||||
SubmenuIndexMfUlUnlockMenuAmeebo,
|
||||
SubmenuIndexMfUlUnlockMenuXiaomi,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_menu_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Enter Password Manually",
|
||||
SubmenuIndexMfUlUnlockMenuManual,
|
||||
nfc_scene_mf_ultralight_unlock_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Auth As Ameebo",
|
||||
SubmenuIndexMfUlUnlockMenuAmeebo,
|
||||
nfc_scene_mf_ultralight_unlock_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Auth As Xiaomi",
|
||||
SubmenuIndexMfUlUnlockMenuXiaomi,
|
||||
nfc_scene_mf_ultralight_unlock_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_set_selected_item(submenu, state);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_unlock_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexMfUlUnlockMenuManual) {
|
||||
nfc->dev->dev_data.mf_ul_data.auth_method = MfUltralightAuthMethodManual;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightKeyInput);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexMfUlUnlockMenuAmeebo) {
|
||||
nfc->dev->dev_data.mf_ul_data.auth_method = MfUltralightAuthMethodAmeebo;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockWarn);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexMfUlUnlockMenuXiaomi) {
|
||||
nfc->dev->dev_data.mf_ul_data.auth_method = MfUltralightAuthMethodXiaomi;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockWarn);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_menu_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_warn_dialog_callback(DialogExResult result, void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_warn_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_ultralight_unlock_warn_dialog_callback);
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Risky function!", 64, 4, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Wrong password\ncan block your\ncard.", 4, 18, AlignLeft, AlignTop);
|
||||
dialog_ex_set_icon(dialog_ex, 73, 17, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_unlock_warn_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultCenter) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuth);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_warn_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
||||
@ -10,7 +10,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Restore card data?", 64, 0, AlignCenter, AlignTop);
|
||||
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_text(
|
||||
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
|
||||
|
||||
@ -12,9 +12,9 @@ void nfc_scene_retry_confirm_on_enter(void* context) {
|
||||
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Stay");
|
||||
dialog_ex_set_header(dialog_ex, "Retry reading?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data will be\nlost.", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex, "All unsaved data will be\nlost!", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback);
|
||||
|
||||
|
||||
@ -4,10 +4,10 @@ void nfc_scene_rpc_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Popup* popup = nfc->popup;
|
||||
|
||||
popup_set_header(popup, "NFC", 82, 28, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
|
||||
@ -31,13 +31,11 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
|
||||
scene_manager_stop(nfc->scene_manager);
|
||||
view_dispatcher_stop(nfc->view_dispatcher);
|
||||
nfc_blink_stop(nfc);
|
||||
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||
nfc->rpc_ctx = NULL;
|
||||
scene_manager_stop(nfc->scene_manager);
|
||||
view_dispatcher_stop(nfc->view_dispatcher);
|
||||
nfc_blink_stop(nfc);
|
||||
} else if(event.event == NfcCustomEventRpcLoad) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(nfc->rpc_ctx);
|
||||
@ -66,7 +64,7 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
nfc_blink_start(nfc);
|
||||
nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
|
||||
popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, nfc->text_store, 89, 44, AlignCenter, AlignTop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexEditUid,
|
||||
SubmenuIndexRename,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
@ -27,6 +28,14 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
SubmenuIndexEmulate,
|
||||
nfc_scene_saved_menu_submenu_callback,
|
||||
nfc);
|
||||
if(nfc->dev->dev_data.protocol == NfcDeviceProtocolUnknown) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Edit UID",
|
||||
SubmenuIndexEditUid,
|
||||
nfc_scene_saved_menu_submenu_callback,
|
||||
nfc);
|
||||
}
|
||||
} else if(
|
||||
nfc->dev->format == NfcDeviceSaveFormatMifareUl ||
|
||||
nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
@ -71,6 +80,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.event == SubmenuIndexRename) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEditUid) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
|
||||
consumed = true;
|
||||
|
||||
@ -31,8 +31,16 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventByteInputDone) {
|
||||
DOLPHIN_DEED(DolphinDeedNfcAdd);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
||||
@ -23,6 +23,8 @@ typedef struct {
|
||||
uint8_t sector_current;
|
||||
uint8_t keys_total;
|
||||
uint8_t keys_found;
|
||||
uint16_t dict_keys_total;
|
||||
uint16_t dict_keys_current;
|
||||
} DictAttackViewModel;
|
||||
|
||||
static void dict_attack_draw_callback(Canvas* canvas, void* model) {
|
||||
@ -38,8 +40,15 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header));
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
float progress =
|
||||
m->sectors_total == 0 ? 0 : (float)(m->sector_current) / (float)(m->sectors_total);
|
||||
float dict_progress = m->dict_keys_total == 0 ?
|
||||
0 :
|
||||
(float)(m->dict_keys_current) / (float)(m->dict_keys_total);
|
||||
float progress = m->sectors_total == 0 ? 0 :
|
||||
((float)(m->sector_current) + dict_progress) /
|
||||
(float)(m->sectors_total);
|
||||
if(progress > 1.0) {
|
||||
progress = 1.0;
|
||||
}
|
||||
elements_progress_bar(canvas, 5, 15, 120, progress);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total);
|
||||
@ -100,6 +109,8 @@ void dict_attack_reset(DictAttack* dict_attack) {
|
||||
model->sector_current = 0;
|
||||
model->keys_total = 0;
|
||||
model->keys_found = 0;
|
||||
model->dict_keys_total = 0;
|
||||
model->dict_keys_current = 0;
|
||||
string_reset(model->header);
|
||||
return false;
|
||||
});
|
||||
@ -171,6 +182,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) {
|
||||
with_view_model(
|
||||
dict_attack->view, (DictAttackViewModel * model) {
|
||||
model->sector_current = curr_sec;
|
||||
model->dict_keys_current = 0;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -181,6 +193,7 @@ void dict_attack_inc_current_sector(DictAttack* dict_attack) {
|
||||
dict_attack->view, (DictAttackViewModel * model) {
|
||||
if(model->sector_current < model->sectors_total) {
|
||||
model->sector_current++;
|
||||
model->dict_keys_current = 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@ -196,3 +209,23 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack) {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) {
|
||||
furi_assert(dict_attack);
|
||||
with_view_model(
|
||||
dict_attack->view, (DictAttackViewModel * model) {
|
||||
model->dict_keys_total = dict_keys_total;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) {
|
||||
furi_assert(dict_attack);
|
||||
with_view_model(
|
||||
dict_attack->view, (DictAttackViewModel * model) {
|
||||
if(model->dict_keys_current + keys_tried < model->dict_keys_total) {
|
||||
model->dict_keys_current += keys_tried;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@ -34,3 +34,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec);
|
||||
void dict_attack_inc_current_sector(DictAttack* dict_attack);
|
||||
|
||||
void dict_attack_inc_keys_found(DictAttack* dict_attack);
|
||||
|
||||
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total);
|
||||
|
||||
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried);
|
||||
|
||||
@ -431,6 +431,54 @@ const NotificationSequence sequence_blink_white_100 = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
// Hardware blink
|
||||
const NotificationSequence sequence_blink_start_blue = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_blue,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_start_red = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_red,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_start_green = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_green,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_start_yellow = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_yellow,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_start_cyan = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_cyan,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_start_magenta = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_magenta,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
//General
|
||||
const NotificationSequence sequence_single_vibro = {
|
||||
&message_vibro_on,
|
||||
|
||||
@ -122,6 +122,15 @@ extern const NotificationSequence sequence_blink_cyan_100;
|
||||
extern const NotificationSequence sequence_blink_magenta_100;
|
||||
extern const NotificationSequence sequence_blink_white_100;
|
||||
|
||||
// Hardware blink
|
||||
extern const NotificationSequence sequence_blink_start_blue;
|
||||
extern const NotificationSequence sequence_blink_start_red;
|
||||
extern const NotificationSequence sequence_blink_start_green;
|
||||
extern const NotificationSequence sequence_blink_start_yellow;
|
||||
extern const NotificationSequence sequence_blink_start_cyan;
|
||||
extern const NotificationSequence sequence_blink_start_magenta;
|
||||
extern const NotificationSequence sequence_blink_stop;
|
||||
|
||||
// General
|
||||
extern const NotificationSequence sequence_single_vibro;
|
||||
extern const NotificationSequence sequence_double_vibro;
|
||||
|
||||
@ -13,7 +13,7 @@ void picopass_scene_read_card_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = picopass->popup;
|
||||
popup_set_header(popup, "Detecting\npicopass card", 70, 34, AlignLeft, AlignTop);
|
||||
popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop);
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
|
||||
// Start worker
|
||||
|
||||
@ -57,7 +57,7 @@ BatteryTestApp* battery_test_alloc() {
|
||||
battery_info_get_view(app->batery_info));
|
||||
|
||||
app->dialog = dialog_ex_alloc();
|
||||
dialog_ex_set_header(app->dialog, "Close battery test?", 64, 12, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop);
|
||||
dialog_ex_set_left_button_text(app->dialog, "Exit");
|
||||
dialog_ex_set_right_button_text(app->dialog, "Stay");
|
||||
dialog_ex_set_result_callback(app->dialog, battery_test_dialog_callback);
|
||||
|
||||
@ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) {
|
||||
}
|
||||
|
||||
int32_t power_srv(void* p) {
|
||||
(void)p;
|
||||
UNUSED(p);
|
||||
Power* power = power_alloc();
|
||||
power_update_info(power);
|
||||
furi_record_create(RECORD_POWER, power);
|
||||
|
||||
@ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) {
|
||||
|
||||
int32_t power_settings_app(void* p) {
|
||||
uint32_t first_scene = PowerSettingsAppSceneStart;
|
||||
if(p && !strcmp(p, "off")) {
|
||||
if(p && strlen(p) && !strcmp(p, "off")) {
|
||||
first_scene = PowerSettingsAppScenePowerOff;
|
||||
}
|
||||
PowerSettingsApp* app = power_settings_app_alloc(first_scene);
|
||||
|
||||
@ -10,7 +10,7 @@ void power_settings_scene_power_off_on_enter(void* context) {
|
||||
PowerSettingsApp* app = context;
|
||||
DialogEx* dialog = app->dialog;
|
||||
|
||||
dialog_ex_set_header(dialog, "Turn off Device?", 64, 2, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog, "Turn Off Device?", 64, 2, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog, " I will be\nwaiting for\n you here...", 78, 16, AlignLeft, AlignTop);
|
||||
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user