Merge branch 'dev' into shutdown_idle

This commit is contained in:
あく
2022-10-29 02:36:31 +09:00
committed by GitHub
470 changed files with 4355 additions and 2385 deletions

View File

@@ -127,7 +127,7 @@ jobs:
**Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:** **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:**
- [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz) - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz)
- [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu) - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu)
- [☁️ Web/App updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}}) - [☁️ Web/App updater](https://lab.flipper.net/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}})
edit-mode: replace edit-mode: replace
compact: compact:

View File

@@ -65,7 +65,6 @@ jobs:
pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }}
pvs-studio-analyzer analyze \ pvs-studio-analyzer analyze \
@.pvsoptions \ @.pvsoptions \
--disableLicenseExpirationCheck \
-j$(grep -c processor /proc/cpuinfo) \ -j$(grep -c processor /proc/cpuinfo) \
-f build/f7-firmware-DC/compile_commands.json \ -f build/f7-firmware-DC/compile_commands.json \
-o PVS-Studio.log -o PVS-Studio.log

52
.github/workflows/unit_tests.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: 'Unit tests'
on:
pull_request:
env:
TARGETS: f7
DEFAULT_TARGET: f7
jobs:
main:
runs-on: [self-hosted, FlipperZeroTest]
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Get flipper from device manager (mock)'
id: device
run: |
echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT
- name: 'Compile unit tests firmware'
id: compile
run: |
FBT_TOOLCHAIN_PATH=/opt ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1
- name: 'Wait for flipper to finish updating'
id: connect
if: steps.compile.outcome == 'success'
run: |
python3 ./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}}
- name: 'Format flipper SD card'
id: format
if: steps.connect.outcome == 'success'
run: |
./scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext
- name: 'Copy assets and unit tests data to flipper'
id: copy
if: steps.format.outcome == 'success'
run: |
./scripts/storage.py -p ${{steps.device.outputs.flipper}} send assets/resources /ext
./scripts/storage.py -p ${{steps.device.outputs.flipper}} send assets/unit_tests /ext/unit_tests
- name: 'Run units and validate results'
if: steps.copy.outcome == 'success'
run: |
python3 ./scripts/testing/units.py ${{steps.device.outputs.flipper}}

3
.gitmodules vendored
View File

@@ -22,9 +22,6 @@
[submodule "lib/microtar"] [submodule "lib/microtar"]
path = lib/microtar path = lib/microtar
url = https://github.com/amachronic/microtar.git url = https://github.com/amachronic/microtar.git
[submodule "lib/scons"]
path = lib/scons
url = https://github.com/SCons/scons.git
[submodule "lib/mbedtls"] [submodule "lib/mbedtls"]
path = lib/mbedtls path = lib/mbedtls
url = https://github.com/Mbed-TLS/mbedtls.git url = https://github.com/Mbed-TLS/mbedtls.git

View File

@@ -2,7 +2,7 @@
"configurations": [ "configurations": [
{ {
"name": "Win32", "name": "Win32",
"compilerPath": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gcc.exe", "compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
"intelliSenseMode": "gcc-arm", "intelliSenseMode": "gcc-arm",
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json", "compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
"configurationProvider": "ms-vscode.cpptools", "configurationProvider": "ms-vscode.cpptools",

View File

@@ -79,6 +79,25 @@
] ]
// "showDevDebugOutput": "raw", // "showDevDebugOutput": "raw",
}, },
{
"name": "Attach FW (DAP)",
"cwd": "${workspaceFolder}",
"executable": "./build/latest/firmware.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "openocd",
"device": "cmsis-dap",
"svdFile": "./debug/STM32WB55_CM4.svd",
"rtos": "FreeRTOS",
"configFiles": [
"interface/cmsis-dap.cfg",
"./debug/stm32wbx.cfg",
],
"postAttachCommands": [
"source debug/flipperapps.py",
],
// "showDevDebugOutput": "raw",
},
{ {
"name": "fbt debug", "name": "fbt debug",
"type": "python", "type": "python",

View File

@@ -6,13 +6,13 @@
"cortex-debug.enableTelemetry": false, "cortex-debug.enableTelemetry": false,
"cortex-debug.variableUseNaturalFormat": true, "cortex-debug.variableUseNaturalFormat": true,
"cortex-debug.showRTOS": true, "cortex-debug.showRTOS": true,
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin", "cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin",
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin", "cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/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.windows": "${workspaceFolder}/toolchain/x86_64-windows/openocd/bin/openocd.exe",
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd", "cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd", "cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gdb-py.bat", "cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py", "cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py", "cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
"editor.formatOnSave": true, "editor.formatOnSave": true,

View File

@@ -109,13 +109,13 @@
"label": "[Debug] Build FAPs", "label": "[Debug] Build FAPs",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt plugin_dist" "command": "./fbt fap_dist"
}, },
{ {
"label": "[Release] Build FAPs", "label": "[Release] Build FAPs",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 plugin_dist" "command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
}, },
{ {
"label": "[Debug] Launch App on Flipper", "label": "[Debug] Launch App on Flipper",

View File

@@ -156,11 +156,9 @@ Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
Alias("fap_dist", fap_dist) Alias("fap_dist", fap_dist)
# distenv.Default(fap_dist) # distenv.Default(fap_dist)
plugin_resources_dist = list( distenv.Depends(
distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1]) firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"]["resources_dist"]
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
) )
distenv.Depends(firmware_env["FW_RESOURCES"], plugin_resources_dist)
# Target for bundling core2 package for qFlipper # Target for bundling core2 package for qFlipper
@@ -291,6 +289,16 @@ distenv.PhonyTarget(
"@echo $( ${BLACKMAGIC_ADDR} $)", "@echo $( ${BLACKMAGIC_ADDR} $)",
) )
# Find STLink probe ids
distenv.PhonyTarget(
"get_stlink",
distenv.Action(
lambda **kw: distenv.GetDevices(),
None,
),
)
# Prepare vscode environment # Prepare vscode environment
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*")) vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
distenv.Precious(vscode_dist) distenv.Precious(vscode_dist)

View File

@@ -8,4 +8,5 @@ App(
stack_size=2 * 1024, stack_size=2 * 1024,
order=150, order=150,
fap_category="Debug", fap_category="Debug",
fap_icon_assets="icons",
) )

View File

@@ -1,4 +1,4 @@
#include "assets_icons.h" #include <file_browser_test_icons.h>
#include "file_browser_app_i.h" #include "file_browser_app_i.h"
#include "gui/modules/file_browser.h" #include "gui/modules/file_browser.h"
#include <furi.h> #include <furi.h>

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

View File

@@ -13,7 +13,7 @@
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 233 #define TEST_RANDOM_COUNT_PARSE 232
#define TEST_TIMEOUT 10000 #define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler; static SubGhzEnvironment* environment_handler;
@@ -437,13 +437,6 @@ MU_TEST(subghz_decoder_clemsa_test) {
"Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n"); "Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
} }
MU_TEST(subghz_decoder_oregon2_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/oregon2_raw.sub"), SUBGHZ_PROTOCOL_OREGON2_NAME),
"Test decoder " SUBGHZ_PROTOCOL_OREGON2_NAME " error\r\n");
}
//test encoders //test encoders
MU_TEST(subghz_encoder_princeton_test) { MU_TEST(subghz_encoder_princeton_test) {
mu_assert( mu_assert(
@@ -605,7 +598,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_magellan_test); MU_RUN_TEST(subghz_decoder_magellan_test);
MU_RUN_TEST(subghz_decoder_intertechno_v3_test); MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
MU_RUN_TEST(subghz_decoder_clemsa_test); MU_RUN_TEST(subghz_decoder_clemsa_test);
MU_RUN_TEST(subghz_decoder_oregon2_test);
MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_princeton_test);
MU_RUN_TEST(subghz_encoder_came_test); MU_RUN_TEST(subghz_encoder_came_test);

View File

@@ -0,0 +1,24 @@
# Application icons
To use icons, do the following:
* add a line to the application manifest: `fap_icon_assets="folder"`, where `folder` points to the folder where your icons are located
* add `#include "application_id_icons.h"` to the application code, where `application_id` is the appid from the manifest
* every icon in the folder will be available as a `I_icon_name` variable, where `icon_name` is the name of the icon file without the extension
## Example
We have an application with the following manifest:
```
App(
appid="example_images",
...
fap_icon_assets="images",
)
```
So the icons are in the `images` folder and will be available in the generated `example_images_icons.h` file.
The example code is located in `example_images_main.c` and contains the following line:
```
#include "example_images_icons.h"
```
Image `dolphin_71x25.png` is available as `I_dolphin_71x25`.

View File

@@ -5,6 +5,7 @@
#include "bad_usb_script.h" #include "bad_usb_script.h"
#include <gui/gui.h> #include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <gui/modules/submenu.h> #include <gui/modules/submenu.h>

View File

@@ -1,6 +1,7 @@
#include "bad_usb_view.h" #include "bad_usb_view.h"
#include "../bad_usb_script.h" #include "../bad_usb_script.h"
#include <gui/elements.h> #include <gui/elements.h>
#include <assets_icons.h>
#define MAX_NAME_LEN 64 #define MAX_NAME_LEN 64

View File

@@ -1,5 +1,6 @@
#include <furi.h> #include <furi.h>
#include <gui/gui.h> #include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <storage/storage.h> #include <storage/storage.h>
#include <gui/modules/loading.h> #include <gui/modules/loading.h>

View File

@@ -15,6 +15,7 @@
#include <gui/modules/widget.h> #include <gui/modules/widget.h>
#include "views/gpio_test.h" #include "views/gpio_test.h"
#include "views/gpio_usb_uart.h" #include "views/gpio_usb_uart.h"
#include <assets_icons.h>
struct GpioApp { struct GpioApp {
Gui* gui; Gui* gui;

View File

@@ -5,6 +5,7 @@
#include <toolbox/path.h> #include <toolbox/path.h>
#include <flipper_format/flipper_format.h> #include <flipper_format/flipper_format.h>
#include <rpc/rpc_app.h> #include <rpc/rpc_app.h>
#include <dolphin/dolphin.h>
#define TAG "iButtonApp" #define TAG "iButtonApp"
@@ -337,11 +338,13 @@ int32_t ibutton_app(void* p) {
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop); ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc);
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
} else { } else {
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen);
if(key_loaded) { if(key_loaded) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
} else { } else {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart);
} }

View File

@@ -4,6 +4,7 @@
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view.h> #include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <notification/notification_messages.h> #include <notification/notification_messages.h>

View File

@@ -1,7 +1,5 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <dolphin/dolphin.h>
void ibutton_scene_add_type_byte_input_callback(void* context) { void ibutton_scene_add_type_byte_input_callback(void* context) {
iButton* ibutton = context; iButton* ibutton = context;
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult); view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult);
@@ -38,7 +36,6 @@ bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
if(event.event == iButtonCustomEventByteEditResult) { if(event.event == iButtonCustomEventByteEditResult) {
ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE); ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE);
DOLPHIN_DEED(DolphinDeedIbuttonAdd);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
} }
} }

View File

@@ -1,6 +1,5 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <core/log.h> #include <core/log.h>
#include <dolphin/dolphin.h>
#include <toolbox/path.h> #include <toolbox/path.h>
#define EMULATE_TIMEOUT_TICKS 10 #define EMULATE_TIMEOUT_TICKS 10
@@ -26,8 +25,6 @@ void ibutton_scene_emulate_on_enter(void* context) {
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
} }
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
// check that stored key has name // check that stored key has name
if(!furi_string_empty(key_name)) { if(!furi_string_empty(key_name)) {
ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));

View File

@@ -11,7 +11,6 @@ void ibutton_scene_read_on_enter(void* context) {
Popup* popup = ibutton->popup; Popup* popup = ibutton->popup;
iButtonKey* key = ibutton->key; iButtonKey* key = ibutton->key;
iButtonWorker* worker = ibutton->key_worker; iButtonWorker* worker = ibutton->key_worker;
DOLPHIN_DEED(DolphinDeedIbuttonRead);
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); 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);
@@ -54,8 +53,8 @@ bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) {
if(success) { if(success) {
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess); ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn); ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn);
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess); scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess);
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
} }
} }
} }

View File

@@ -1,4 +1,5 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
SubmenuIndexSave, SubmenuIndexSave,
@@ -49,6 +50,7 @@ bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
} else if(event.event == SubmenuIndexEmulate) { } else if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
} else if(event.event == SubmenuIndexWrite) { } else if(event.event == SubmenuIndexWrite) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
} }

View File

@@ -1,6 +1,7 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <lib/toolbox/random_name.h> #include <lib/toolbox/random_name.h>
#include <toolbox/path.h> #include <toolbox/path.h>
#include <dolphin/dolphin.h>
static void ibutton_scene_save_name_text_input_callback(void* context) { static void ibutton_scene_save_name_text_input_callback(void* context) {
iButton* ibutton = context; iButton* ibutton = context;
@@ -57,6 +58,15 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(event.event == iButtonCustomEventTextEditResult) { if(event.event == iButtonCustomEventTextEditResult) {
if(ibutton_save_key(ibutton, ibutton->text_store)) { if(ibutton_save_key(ibutton, ibutton->text_store)) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess);
if(scene_manager_has_previous_scene(
ibutton->scene_manager, iButtonSceneSavedKeyMenu)) {
// Nothing, do not count editing as saving
} else if(scene_manager_has_previous_scene(
ibutton->scene_manager, iButtonSceneAddType)) {
DOLPHIN_DEED(DolphinDeedIbuttonAdd);
} else {
DOLPHIN_DEED(DolphinDeedIbuttonSave);
}
} else { } else {
const uint32_t possible_scenes[] = { const uint32_t possible_scenes[] = {
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType}; iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};

View File

@@ -1,5 +1,4 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <dolphin/dolphin.h>
static void ibutton_scene_save_success_popup_callback(void* context) { static void ibutton_scene_save_success_popup_callback(void* context) {
iButton* ibutton = context; iButton* ibutton = context;
@@ -9,7 +8,6 @@ static void ibutton_scene_save_success_popup_callback(void* context) {
void ibutton_scene_save_success_on_enter(void* context) { void ibutton_scene_save_success_on_enter(void* context) {
iButton* ibutton = context; iButton* ibutton = context;
Popup* popup = ibutton->popup; Popup* popup = ibutton->popup;
DOLPHIN_DEED(DolphinDeedIbuttonSave);
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);

View File

@@ -1,4 +1,5 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexEmulate, SubmenuIndexEmulate,
@@ -58,6 +59,7 @@ bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent even
consumed = true; consumed = true;
if(event.event == SubmenuIndexEmulate) { if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
} else if(event.event == SubmenuIndexWrite) { } else if(event.event == SubmenuIndexWrite) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
} else if(event.event == SubmenuIndexEdit) { } else if(event.event == SubmenuIndexEdit) {

View File

@@ -1,5 +1,6 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include "ibutton/scenes/ibutton_scene.h" #include "ibutton/scenes/ibutton_scene.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexRead, SubmenuIndexRead,
@@ -38,6 +39,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
if(event.event == SubmenuIndexRead) { if(event.event == SubmenuIndexRead) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
DOLPHIN_DEED(DolphinDeedIbuttonRead);
} else if(event.event == SubmenuIndexSaved) { } else if(event.event == SubmenuIndexSaved) {
furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER); furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);

View File

@@ -5,25 +5,21 @@
#include <furi_hal_infrared.h> #include <furi_hal_infrared.h>
#include <flipper_format.h> #include <flipper_format.h>
#include <toolbox/args.h> #include <toolbox/args.h>
#include <m-dict.h>
#include "infrared_signal.h" #include "infrared_signal.h"
#include "infrared_brute_force.h" #include "infrared_brute_force.h"
#include <m-dict.h>
#define INFRARED_CLI_BUF_SIZE 10 #define INFRARED_CLI_BUF_SIZE 10
#define INFRARED_ASSETS_FOLDER "infrared/assets"
#define INFRARED_BRUTE_FORCE_DUMMY_INDEX 0
DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST) DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST)
enum RemoteTypes { TV = 0, AC = 1 };
static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args); static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args);
static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args); static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args);
static void infrared_cli_process_decode(Cli* cli, FuriString* args); static void infrared_cli_process_decode(Cli* cli, FuriString* args);
static void infrared_cli_process_universal(Cli* cli, FuriString* args); static void infrared_cli_process_universal(Cli* cli, FuriString* args);
static void infrared_cli_list_remote_signals(enum RemoteTypes remote_type);
static void
infrared_cli_brute_force_signals(Cli* cli, enum RemoteTypes remote_type, FuriString* signal);
static const struct { static const struct {
const char* cmd; const char* cmd;
@@ -87,8 +83,10 @@ static void infrared_cli_print_usage(void) {
INFRARED_MIN_FREQUENCY, INFRARED_MIN_FREQUENCY,
INFRARED_MAX_FREQUENCY); INFRARED_MAX_FREQUENCY);
printf("\tir decode <input_file> [<output_file>]\r\n"); printf("\tir decode <input_file> [<output_file>]\r\n");
printf("\tir universal <tv, ac> <signal name>\r\n"); printf("\tir universal <remote_name> <signal_name>\r\n");
printf("\tir universal list <tv, ac>\r\n"); printf("\tir universal list <remote_name>\r\n");
// TODO: Do not hardcode universal remote names
printf("\tAvailable universal remotes: tv audio ac\r\n");
} }
static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) { static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) {
@@ -356,89 +354,31 @@ static void infrared_cli_process_decode(Cli* cli, FuriString* args) {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void infrared_cli_process_universal(Cli* cli, FuriString* args) { static void infrared_cli_list_remote_signals(FuriString* remote_name) {
enum RemoteTypes Remote; if(furi_string_empty(remote_name)) {
printf("Missing remote name.\r\n");
FuriString* command; return;
FuriString* remote;
FuriString* signal;
command = furi_string_alloc();
remote = furi_string_alloc();
signal = furi_string_alloc();
do {
if(!args_read_string_and_trim(args, command)) {
infrared_cli_print_usage();
break;
}
if(furi_string_cmp_str(command, "list") == 0) {
args_read_string_and_trim(args, remote);
if(furi_string_cmp_str(remote, "tv") == 0) {
Remote = TV;
} else if(furi_string_cmp_str(remote, "ac") == 0) {
Remote = AC;
} else {
printf("Invalid remote type.\r\n");
break;
}
infrared_cli_list_remote_signals(Remote);
break;
}
if(furi_string_cmp_str(command, "tv") == 0) {
Remote = TV;
} else if(furi_string_cmp_str(command, "ac") == 0) {
Remote = AC;
} else {
printf("Invalid remote type.\r\n");
break;
}
args_read_string_and_trim(args, signal);
if(furi_string_empty(signal)) {
printf("Must supply a valid signal for type of remote selected.\r\n");
break;
}
infrared_cli_brute_force_signals(cli, Remote, signal);
break;
} while(false);
furi_string_free(command);
furi_string_free(remote);
furi_string_free(signal);
}
static void infrared_cli_list_remote_signals(enum RemoteTypes remote_type) {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
dict_signals_t signals_dict;
FuriString* key;
const char* remote_file = NULL;
bool success = false;
int max = 1;
switch(remote_type) {
case TV:
remote_file = EXT_PATH("infrared/assets/tv.ir");
break;
case AC:
remote_file = EXT_PATH("infrared/assets/ac.ir");
break;
default:
break;
} }
dict_signals_init(signals_dict); Storage* storage = furi_record_open(RECORD_STORAGE);
key = furi_string_alloc(); FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
FuriString* remote_path = furi_string_alloc_printf(
"%s/%s.ir", EXT_PATH(INFRARED_ASSETS_FOLDER), furi_string_get_cstr(remote_name));
do {
if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(remote_path))) {
printf("Invalid remote name.\r\n");
break;
}
dict_signals_t signals_dict;
dict_signals_init(signals_dict);
FuriString* key = furi_string_alloc();
FuriString* signal_name = furi_string_alloc();
success = flipper_format_buffered_file_open_existing(ff, remote_file);
if(success) {
FuriString* signal_name;
signal_name = furi_string_alloc();
printf("Valid signals:\r\n"); printf("Valid signals:\r\n");
int max = 1;
while(flipper_format_read_string(ff, "name", signal_name)) { while(flipper_format_read_string(ff, "name", signal_name)) {
furi_string_set_str(key, furi_string_get_cstr(signal_name)); furi_string_set_str(key, furi_string_get_cstr(signal_name));
int* v = dict_signals_get(signals_dict, key); int* v = dict_signals_get(signals_dict, key);
@@ -449,57 +389,57 @@ static void infrared_cli_list_remote_signals(enum RemoteTypes remote_type) {
dict_signals_set_at(signals_dict, key, 1); dict_signals_set_at(signals_dict, key, 1);
} }
} }
dict_signals_it_t it; dict_signals_it_t it;
for(dict_signals_it(it, signals_dict); !dict_signals_end_p(it); dict_signals_next(it)) { for(dict_signals_it(it, signals_dict); !dict_signals_end_p(it); dict_signals_next(it)) {
const struct dict_signals_pair_s* pair = dict_signals_cref(it); const struct dict_signals_pair_s* pair = dict_signals_cref(it);
printf("\t%s\r\n", furi_string_get_cstr(pair->key)); printf("\t%s\r\n", furi_string_get_cstr(pair->key));
} }
furi_string_free(signal_name);
}
furi_string_free(key); furi_string_free(key);
dict_signals_clear(signals_dict); furi_string_free(signal_name);
dict_signals_clear(signals_dict);
} while(false);
flipper_format_free(ff); flipper_format_free(ff);
furi_string_free(remote_path);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void static void
infrared_cli_brute_force_signals(Cli* cli, enum RemoteTypes remote_type, FuriString* signal) { infrared_cli_brute_force_signals(Cli* cli, FuriString* remote_name, FuriString* signal_name) {
InfraredBruteForce* brute_force = infrared_brute_force_alloc(); InfraredBruteForce* brute_force = infrared_brute_force_alloc();
const char* remote_file = NULL; FuriString* remote_path = furi_string_alloc_printf(
uint32_t i = 0; "%s/%s.ir", EXT_PATH(INFRARED_ASSETS_FOLDER), furi_string_get_cstr(remote_name));
bool success = false;
switch(remote_type) { infrared_brute_force_set_db_filename(brute_force, furi_string_get_cstr(remote_path));
case TV: infrared_brute_force_add_record(
remote_file = EXT_PATH("infrared/assets/tv.ir"); brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, furi_string_get_cstr(signal_name));
break;
case AC:
remote_file = EXT_PATH("infrared/assets/ac.ir");
break;
default:
break;
}
infrared_brute_force_set_db_filename(brute_force, remote_file); do {
infrared_brute_force_add_record(brute_force, i++, furi_string_get_cstr(signal)); if(furi_string_empty(signal_name)) {
printf("Missing signal name.\r\n");
success = infrared_brute_force_calculate_messages(brute_force); break;
if(success) { }
uint32_t record_count; if(!infrared_brute_force_calculate_messages(brute_force)) {
uint32_t index = 0; printf("Invalid remote name.\r\n");
int records_sent = 0; break;
bool running = false;
running = infrared_brute_force_start(brute_force, index, &record_count);
if(record_count <= 0) {
printf("Invalid signal.\n");
infrared_brute_force_reset(brute_force);
return;
} }
printf("Sending %ld codes to the tv.\r\n", record_count); uint32_t record_count;
bool running = infrared_brute_force_start(
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, &record_count);
if(record_count <= 0) {
printf("Invalid signal name.\r\n");
break;
}
printf("Sending %ld signal(s)...\r\n", record_count);
printf("Press Ctrl-C to stop.\r\n"); printf("Press Ctrl-C to stop.\r\n");
int records_sent = 0;
while(running) { while(running) {
running = infrared_brute_force_send_next(brute_force); running = infrared_brute_force_send_next(brute_force);
@@ -510,14 +450,35 @@ static void
} }
infrared_brute_force_stop(brute_force); infrared_brute_force_stop(brute_force);
} else { } while(false);
printf("Invalid signal.\r\n");
}
furi_string_free(remote_path);
infrared_brute_force_reset(brute_force); infrared_brute_force_reset(brute_force);
infrared_brute_force_free(brute_force); infrared_brute_force_free(brute_force);
} }
static void infrared_cli_process_universal(Cli* cli, FuriString* args) {
FuriString* arg1 = furi_string_alloc();
FuriString* arg2 = furi_string_alloc();
do {
if(!args_read_string_and_trim(args, arg1)) break;
if(!args_read_string_and_trim(args, arg2)) break;
} while(false);
if(furi_string_empty(arg1)) {
printf("Wrong arguments.\r\n");
infrared_cli_print_usage();
} else if(furi_string_equal_str(arg1, "list")) {
infrared_cli_list_remote_signals(arg2);
} else {
infrared_cli_brute_force_signals(cli, arg1, arg2);
}
furi_string_free(arg1);
furi_string_free(arg2);
}
static void infrared_cli_start_ir(Cli* cli, FuriString* args, void* context) { static void infrared_cli_start_ir(Cli* cli, FuriString* args, void* context) {
UNUSED(context); UNUSED(context);
if(furi_hal_infrared_is_busy()) { if(furi_hal_infrared_is_busy()) {

View File

@@ -2,6 +2,7 @@
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view.h> #include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_stack.h> #include <gui/view_stack.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>

View File

@@ -16,6 +16,7 @@ ADD_SCENE(infrared, remote_list, RemoteList)
ADD_SCENE(infrared, universal, Universal) ADD_SCENE(infrared, universal, Universal)
ADD_SCENE(infrared, universal_tv, UniversalTV) ADD_SCENE(infrared, universal_tv, UniversalTV)
ADD_SCENE(infrared, universal_ac, UniversalAC) ADD_SCENE(infrared, universal_ac, UniversalAC)
ADD_SCENE(infrared, universal_audio, UniversalAudio)
ADD_SCENE(infrared, debug, Debug) ADD_SCENE(infrared, debug, Debug)
ADD_SCENE(infrared, error_databases, ErrorDatabases) ADD_SCENE(infrared, error_databases, ErrorDatabases)
ADD_SCENE(infrared, rpc, Rpc) ADD_SCENE(infrared, rpc, Rpc)

View File

@@ -1,4 +1,5 @@
#include "../infrared_i.h" #include "../infrared_i.h"
#include <dolphin/dolphin.h>
void infrared_scene_learn_on_enter(void* context) { void infrared_scene_learn_on_enter(void* context) {
Infrared* infrared = context; Infrared* infrared = context;
@@ -27,6 +28,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
if(event.event == InfraredCustomEventTypeSignalReceived) { if(event.event == InfraredCustomEventTypeSignalReceived) {
infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess); infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess);
scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess); scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess);
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
consumed = true; consumed = true;
} }
} }

View File

@@ -1,13 +1,10 @@
#include "../infrared_i.h" #include "../infrared_i.h"
#include <dolphin/dolphin.h>
void infrared_scene_learn_done_on_enter(void* context) { void infrared_scene_learn_done_on_enter(void* context) {
Infrared* infrared = context; Infrared* infrared = context;
Popup* popup = infrared->popup; Popup* popup = infrared->popup;
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
DOLPHIN_DEED(DolphinDeedIrSave);
if(infrared->app_state.is_learning_new_remote) { if(infrared->app_state.is_learning_new_remote) {
popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop); popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop);

View File

@@ -1,4 +1,5 @@
#include "../infrared_i.h" #include "../infrared_i.h"
#include <dolphin/dolphin.h>
void infrared_scene_learn_enter_name_on_enter(void* context) { void infrared_scene_learn_enter_name_on_enter(void* context) {
Infrared* infrared = context; Infrared* infrared = context;
@@ -49,6 +50,7 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e
if(success) { if(success) {
scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); scene_manager_next_scene(scene_manager, InfraredSceneLearnDone);
DOLPHIN_DEED(DolphinDeedIrSave);
} else { } else {
dialog_message_show_storage_error(infrared->dialogs, "Failed to save file"); dialog_message_show_storage_error(infrared->dialogs, "Failed to save file");
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};

View File

@@ -1,7 +1,5 @@
#include "../infrared_i.h" #include "../infrared_i.h"
#include <dolphin/dolphin.h>
static void static void
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) { infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
Infrared* infrared = context; Infrared* infrared = context;
@@ -13,7 +11,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
DialogEx* dialog_ex = infrared->dialog_ex; DialogEx* dialog_ex = infrared->dialog_ex;
InfraredSignal* signal = infrared->received_signal; InfraredSignal* signal = infrared->received_signal;
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
if(infrared_signal_is_raw(signal)) { if(infrared_signal_is_raw(signal)) {

View File

@@ -21,6 +21,12 @@ void infrared_scene_universal_on_enter(void* context) {
SubmenuIndexUniversalTV, SubmenuIndexUniversalTV,
infrared_scene_universal_submenu_callback, infrared_scene_universal_submenu_callback,
context); context);
submenu_add_item(
submenu,
"Audio Players",
SubmenuIndexUniversalAudio,
infrared_scene_universal_submenu_callback,
context);
submenu_add_item( submenu_add_item(
submenu, submenu,
"Air Conditioners", "Air Conditioners",
@@ -45,7 +51,7 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC); scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexUniversalAudio) { } else if(event.event == SubmenuIndexUniversalAudio) {
//TODO Implement Audio universal remote scene_manager_next_scene(scene_manager, InfraredSceneUniversalAudio);
consumed = true; consumed = true;
} }
} }

View File

@@ -0,0 +1,133 @@
#include "../infrared_i.h"
#include "common/infrared_scene_universal_common.h"
void infrared_scene_universal_audio_on_enter(void* context) {
infrared_scene_universal_common_on_enter(context);
Infrared* infrared = context;
ButtonPanel* button_panel = infrared->button_panel;
InfraredBruteForce* brute_force = infrared->brute_force;
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/audio.ir"));
button_panel_reserve(button_panel, 2, 4);
uint32_t i = 0;
button_panel_add_item(
button_panel,
i,
0,
0,
3,
11,
&I_Power_25x27,
&I_Power_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
11,
&I_Mute_25x27,
&I_Mute_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
41,
&I_Play_25x27,
&I_Play_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Play");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
41,
&I_Pause_25x27,
&I_Pause_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Pause");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
71,
&I_TrackPrev_25x27,
&I_TrackPrev_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Prev");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
71,
&I_TrackNext_25x27,
&I_TrackNext_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Next");
button_panel_add_item(
button_panel,
i,
0,
3,
3,
101,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_item(
button_panel,
i,
1,
3,
36,
101,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_label(button_panel, 1, 8, FontPrimary, "Mus. remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
infrared_show_loading_popup(infrared, true);
bool success = infrared_brute_force_calculate_messages(brute_force);
infrared_show_loading_popup(infrared, false);
if(!success) {
scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases);
}
}
bool infrared_scene_universal_audio_on_event(void* context, SceneManagerEvent event) {
return infrared_scene_universal_common_on_event(context, event);
}
void infrared_scene_universal_audio_on_exit(void* context) {
infrared_scene_universal_common_on_exit(context);
}

View File

@@ -1,4 +1,5 @@
#include "lfrfid_i.h" #include "lfrfid_i.h"
#include <dolphin/dolphin.h>
static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) { static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
furi_assert(context); furi_assert(context);
@@ -182,12 +183,14 @@ int32_t lfrfid_app(void* p) {
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop); app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop);
scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc); scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc);
DOLPHIN_DEED(DolphinDeedRfidEmulate);
} else { } else {
furi_string_set(app->file_path, args); furi_string_set(app->file_path, args);
lfrfid_load_key_data(app, app->file_path, true); lfrfid_load_key_data(app, app->file_path, true);
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
DOLPHIN_DEED(DolphinDeedRfidEmulate);
} }
} else { } else {
@@ -311,4 +314,4 @@ void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context)
void lfrfid_text_input_callback(void* context) { void lfrfid_text_input_callback(void* context) {
LfRfid* app = context; LfRfid* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext); view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext);
} }

View File

@@ -5,6 +5,7 @@
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view.h> #include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <cli/cli.h> #include <cli/cli.h>

View File

@@ -1,12 +1,9 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
void lfrfid_scene_emulate_on_enter(void* context) { void lfrfid_scene_emulate_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
Popup* popup = app->popup; Popup* popup = app->popup;
DOLPHIN_DEED(DolphinDeedRfidEmulate);
popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop); popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop);
if(!furi_string_empty(app->file_name)) { if(!furi_string_empty(app->file_name)) {
popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);

View File

@@ -1,4 +1,5 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
SubmenuIndexASK, SubmenuIndexASK,
@@ -57,10 +58,12 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
if(event.event == SubmenuIndexASK) { if(event.event == SubmenuIndexASK) {
app->read_type = LFRFIDWorkerReadTypeASKOnly; app->read_type = LFRFIDWorkerReadTypeASKOnly;
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
DOLPHIN_DEED(DolphinDeedRfidRead);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexPSK) { } else if(event.event == SubmenuIndexPSK) {
app->read_type = LFRFIDWorkerReadTypePSKOnly; app->read_type = LFRFIDWorkerReadTypePSKOnly;
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
DOLPHIN_DEED(DolphinDeedRfidRead);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexRAW) { } else if(event.event == SubmenuIndexRAW) {
scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName); scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);

View File

@@ -46,7 +46,6 @@ static void
void lfrfid_scene_read_on_enter(void* context) { void lfrfid_scene_read_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
DOLPHIN_DEED(DolphinDeedRfidRead);
if(app->read_type == LFRFIDWorkerReadTypePSKOnly) { if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly); lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
} else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) { } else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
@@ -79,10 +78,10 @@ bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
} else if(event.event == LfRfidEventReadDone) { } else if(event.event == LfRfidEventReadDone) {
app->protocol_id = app->protocol_id_next; app->protocol_id = app->protocol_id_next;
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
notification_message(app->notifications, &sequence_success); notification_message(app->notifications, &sequence_success);
furi_string_reset(app->file_name); furi_string_reset(app->file_name);
scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess); scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess);
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
consumed = true; consumed = true;
} else if(event.event == LfRfidEventReadStartPSK) { } else if(event.event == LfRfidEventReadStartPSK) {
if(app->read_type == LFRFIDWorkerReadTypeAuto) { if(app->read_type == LFRFIDWorkerReadTypeAuto) {

View File

@@ -1,4 +1,5 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
SubmenuIndexSave, SubmenuIndexSave,
@@ -43,6 +44,7 @@ bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event)
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexEmulate) { } else if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
DOLPHIN_DEED(DolphinDeedRfidEmulate);
consumed = true; consumed = true;
} }
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event); scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event);

View File

@@ -1,5 +1,4 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
void lfrfid_scene_save_data_on_enter(void* context) { void lfrfid_scene_save_data_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
@@ -32,7 +31,6 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size); protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
DOLPHIN_DEED(DolphinDeedRfidAdd);
scene_manager_next_scene(scene_manager, LfRfidSceneSaveName); scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1); scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1);
} }

View File

@@ -1,5 +1,6 @@
#include <lib/toolbox/random_name.h> #include <lib/toolbox/random_name.h>
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
void lfrfid_scene_save_name_on_enter(void* context) { void lfrfid_scene_save_name_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
@@ -55,6 +56,13 @@ bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(lfrfid_save_key(app)) { if(lfrfid_save_key(app)) {
scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess); scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess);
if(scene_manager_has_previous_scene(scene_manager, LfRfidSceneSavedKeyMenu)) {
// Nothing, do not count editing as saving
} else if(scene_manager_has_previous_scene(scene_manager, LfRfidSceneSaveType)) {
DOLPHIN_DEED(DolphinDeedRfidAdd);
} else {
DOLPHIN_DEED(DolphinDeedRfidSave);
}
} else { } else {
scene_manager_search_and_switch_to_previous_scene( scene_manager_search_and_switch_to_previous_scene(
scene_manager, LfRfidSceneReadKeyMenu); scene_manager, LfRfidSceneReadKeyMenu);

View File

@@ -1,5 +1,4 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
void lfrfid_scene_save_success_on_enter(void* context) { void lfrfid_scene_save_success_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
@@ -8,7 +7,6 @@ void lfrfid_scene_save_success_on_enter(void* context) {
// Clear state of data enter scene // Clear state of data enter scene
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0); scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0);
DOLPHIN_DEED(DolphinDeedRfidSave);
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
popup_set_context(popup, app); popup_set_context(popup, app);

View File

@@ -1,4 +1,5 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
SubmenuIndexEmulate, SubmenuIndexEmulate,
@@ -42,6 +43,7 @@ bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexEmulate) { if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
DOLPHIN_DEED(DolphinDeedRfidEmulate);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexWrite) { } else if(event.event == SubmenuIndexWrite) {
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite); scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);

View File

@@ -1,4 +1,5 @@
#include "../lfrfid_i.h" #include "../lfrfid_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
SubmenuIndexRead, SubmenuIndexRead,
@@ -47,6 +48,7 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) { if(event.event == SubmenuIndexRead) {
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
DOLPHIN_DEED(DolphinDeedRfidRead);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexSaved) { } else if(event.event == SubmenuIndexSaved) {
furi_string_set(app->file_path, LFRFID_APP_FOLDER); furi_string_set(app->file_path, LFRFID_APP_FOLDER);

View File

@@ -1,5 +1,6 @@
#include "lfrfid_view_read.h" #include "lfrfid_view_read.h"
#include <gui/elements.h> #include <gui/elements.h>
#include <assets_icons.h>
#define TEMP_STR_LEN 128 #define TEMP_STR_LEN 128

View File

@@ -1,5 +1,6 @@
#include "nfc_i.h" #include "nfc_i.h"
#include "furi_hal_nfc.h" #include "furi_hal_nfc.h"
#include <dolphin/dolphin.h>
bool nfc_custom_event_callback(void* context, uint32_t event) { bool nfc_custom_event_callback(void* context, uint32_t event) {
furi_assert(context); furi_assert(context);
@@ -275,12 +276,15 @@ int32_t nfc_app(void* p) {
if(nfc_device_load(nfc->dev, p, true)) { if(nfc_device_load(nfc->dev, p, true)) {
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
DOLPHIN_DEED(DolphinDeedNfcEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
DOLPHIN_DEED(DolphinDeedNfcEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
} else { } else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
DOLPHIN_DEED(DolphinDeedNfcEmulate);
} }
} else { } else {
// Exit app // Exit app

View File

@@ -7,6 +7,7 @@
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view.h> #include <gui/view.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <cli/cli.h> #include <cli/cli.h>

View File

@@ -36,6 +36,12 @@ ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete) ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate) ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack) ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
ADD_SCENE(nfc, mf_classic_write, MfClassicWrite)
ADD_SCENE(nfc, mf_classic_write_success, MfClassicWriteSuccess)
ADD_SCENE(nfc, mf_classic_write_fail, MfClassicWriteFail)
ADD_SCENE(nfc, mf_classic_update, MfClassicUpdate)
ADD_SCENE(nfc, mf_classic_update_success, MfClassicUpdateSuccess)
ADD_SCENE(nfc, mf_classic_wrong_card, MfClassicWrongCard)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu) ADD_SCENE(nfc, emv_menu, EmvMenu)
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U) #define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U)
@@ -26,10 +25,14 @@ void nfc_scene_detect_reader_callback(void* context) {
void nfc_scene_detect_reader_on_enter(void* context) { void nfc_scene_detect_reader_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcDetectReader);
detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc); detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc);
detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX); detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX);
NfcDeviceData* dev_data = &nfc->dev->dev_data;
if(dev_data->nfc_data.uid_len) {
detect_reader_set_uid(
nfc->detect_reader, dev_data->nfc_data.uid, dev_data->nfc_data.uid_len);
}
// Store number of collected nonces in scene state // Store number of collected nonces in scene state
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0); scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX (200) #define NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX (200)
@@ -59,7 +58,6 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) {
void nfc_scene_emulate_uid_on_enter(void* context) { void nfc_scene_emulate_uid_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
// Setup Widget // Setup Widget
nfc_scene_emulate_uid_widget_config(nfc, false); nfc_scene_emulate_uid_widget_config(nfc, false);

View File

@@ -1,6 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include "../helpers/nfc_emv_parser.h" #include "../helpers/nfc_emv_parser.h"
#include <dolphin/dolphin.h>
void nfc_scene_emv_read_success_widget_callback( void nfc_scene_emv_read_success_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -15,7 +14,6 @@ void nfc_scene_emv_read_success_widget_callback(
void nfc_scene_emv_read_success_on_enter(void* context) { void nfc_scene_emv_read_success_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
EmvData* emv_data = &nfc->dev->dev_data.emv_data; EmvData* emv_data = &nfc->dev->dev_data.emv_data;
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
// Setup Custom Widget view // Setup Custom Widget view
widget_add_button_element( widget_add_button_element(

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define TAG "NfcMfClassicDictAttack" #define TAG "NfcMfClassicDictAttack"
@@ -110,6 +111,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
} else { } else {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} }
} else if(event.event == NfcWorkerEventAborted) { } else if(event.event == NfcWorkerEventAborted) {
@@ -119,6 +121,8 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
} else { } else {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
// Counting failed attempts too
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} }
} else if(event.event == NfcWorkerEventCardDetected) { } else if(event.event == NfcWorkerEventCardDetected) {

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL) #define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL)
#define NFC_MF_CLASSIC_DATA_CHANGED (1UL) #define NFC_MF_CLASSIC_DATA_CHANGED (1UL)
@@ -15,7 +14,6 @@ bool nfc_mf_classic_emulate_worker_callback(NfcWorkerEvent event, void* context)
void nfc_scene_mf_classic_emulate_on_enter(void* context) { void nfc_scene_mf_classic_emulate_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
// Setup view // Setup view
Popup* popup = nfc->popup; Popup* popup = nfc->popup;

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_classic_keys_add_byte_input_callback(void* context) { void nfc_scene_mf_classic_keys_add_byte_input_callback(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
@@ -36,6 +37,7 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate); nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) { } else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
DOLPHIN_DEED(DolphinDeedNfcMfcAdd);
} else { } else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
} }

View File

@@ -36,8 +36,6 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSave) { if(event.event == SubmenuIndexSave) {
DOLPHIN_DEED(DolphinDeedNfcMfcAdd);
scene_manager_set_scene_state( scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexSave); nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexSave);
nfc->dev->format = NfcDeviceSaveFormatMifareClassic; nfc->dev->format = NfcDeviceSaveFormatMifareClassic;
@@ -49,6 +47,11 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
scene_manager_set_scene_state( scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexEmulate); nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexEmulate);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
DOLPHIN_DEED(DolphinDeedNfcAddEmulate);
} else {
DOLPHIN_DEED(DolphinDeedNfcEmulate);
}
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexInfo) { } else if(event.event == SubmenuIndexInfo) {
scene_manager_set_scene_state( scene_manager_set_scene_state(

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_classic_read_success_widget_callback( void nfc_scene_mf_classic_read_success_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -18,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
NfcDeviceData* dev_data = &nfc->dev->dev_data; NfcDeviceData* dev_data = &nfc->dev->dev_data;
MfClassicData* mf_data = &dev_data->mf_classic_data; MfClassicData* mf_data = &dev_data->mf_classic_data;
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
// Setup view // Setup view
Widget* widget = nfc->widget; Widget* widget = nfc->widget;
widget_add_button_element( widget_add_button_element(

View File

@@ -0,0 +1,98 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum {
NfcSceneMfClassicUpdateStateCardSearch,
NfcSceneMfClassicUpdateStateCardFound,
};
bool nfc_mf_classic_update_worker_callback(NfcWorkerEvent event, void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
return true;
}
static void nfc_scene_mf_classic_update_setup_view(Nfc* nfc) {
Popup* popup = nfc->popup;
popup_reset(popup);
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicUpdate);
if(state == NfcSceneMfClassicUpdateStateCardSearch) {
popup_set_text(
nfc->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else {
popup_set_header(popup, "Updating\nDon't move...", 52, 32, AlignLeft, AlignCenter);
popup_set_icon(popup, 12, 23, &A_Loading_24);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
void nfc_scene_mf_classic_update_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicUpdate, NfcSceneMfClassicUpdateStateCardSearch);
nfc_scene_mf_classic_update_setup_view(nfc);
// Setup and start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateMfClassicUpdate,
&nfc->dev->dev_data,
nfc_mf_classic_update_worker_callback,
nfc);
nfc_blink_emulate_start(nfc);
}
bool nfc_scene_mf_classic_update_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcWorkerEventSuccess) {
nfc_worker_stop(nfc->worker);
if(nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicUpdateSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
}
consumed = true;
} else if(event.event == NfcWorkerEventWrongCard) {
nfc_worker_stop(nfc->worker);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
consumed = true;
} else if(event.event == NfcWorkerEventCardDetected) {
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneMfClassicUpdate,
NfcSceneMfClassicUpdateStateCardFound);
nfc_scene_mf_classic_update_setup_view(nfc);
consumed = true;
} else if(event.event == NfcWorkerEventNoCardDetected) {
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneMfClassicUpdate,
NfcSceneMfClassicUpdateStateCardSearch);
nfc_scene_mf_classic_update_setup_view(nfc);
consumed = true;
}
}
return consumed;
}
void nfc_scene_mf_classic_update_on_exit(void* context) {
Nfc* nfc = context;
nfc_worker_stop(nfc->worker);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicUpdate, NfcSceneMfClassicUpdateStateCardSearch);
// Clear view
popup_reset(nfc->popup);
nfc_blink_stop(nfc);
}

View File

@@ -0,0 +1,44 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_classic_update_success_popup_callback(void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_mf_classic_update_success_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcSave);
notification_message(nfc->notifications, &sequence_success);
Popup* popup = nfc->popup;
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Updated!", 11, 20, AlignLeft, AlignBottom);
popup_set_timeout(popup, 1500);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_mf_classic_update_success_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
bool nfc_scene_mf_classic_update_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
}
}
return consumed;
}
void nfc_scene_mf_classic_update_success_on_exit(void* context) {
Nfc* nfc = context;
// Clear view
popup_reset(nfc->popup);
}

View File

@@ -0,0 +1,92 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum {
NfcSceneMfClassicWriteStateCardSearch,
NfcSceneMfClassicWriteStateCardFound,
};
bool nfc_mf_classic_write_worker_callback(NfcWorkerEvent event, void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
return true;
}
static void nfc_scene_mf_classic_write_setup_view(Nfc* nfc) {
Popup* popup = nfc->popup;
popup_reset(popup);
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicWrite);
if(state == NfcSceneMfClassicWriteStateCardSearch) {
popup_set_text(
nfc->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else {
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
popup_set_icon(popup, 12, 23, &A_Loading_24);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
void nfc_scene_mf_classic_write_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicWrite, NfcSceneMfClassicWriteStateCardSearch);
nfc_scene_mf_classic_write_setup_view(nfc);
// Setup and start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateMfClassicWrite,
&nfc->dev->dev_data,
nfc_mf_classic_write_worker_callback,
nfc);
nfc_blink_emulate_start(nfc);
}
bool nfc_scene_mf_classic_write_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcWorkerEventSuccess) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWriteSuccess);
consumed = true;
} else if(event.event == NfcWorkerEventFail) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWriteFail);
consumed = true;
} else if(event.event == NfcWorkerEventWrongCard) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
consumed = true;
} else if(event.event == NfcWorkerEventCardDetected) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicWrite, NfcSceneMfClassicWriteStateCardFound);
nfc_scene_mf_classic_write_setup_view(nfc);
consumed = true;
} else if(event.event == NfcWorkerEventNoCardDetected) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicWrite, NfcSceneMfClassicWriteStateCardSearch);
nfc_scene_mf_classic_write_setup_view(nfc);
consumed = true;
}
}
return consumed;
}
void nfc_scene_mf_classic_write_on_exit(void* context) {
Nfc* nfc = context;
nfc_worker_stop(nfc->worker);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicWrite, NfcSceneMfClassicWriteStateCardSearch);
// Clear view
popup_reset(nfc->popup);
nfc_blink_stop(nfc);
}

View File

@@ -0,0 +1,58 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_write_fail_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
Nfc* nfc = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}
void nfc_scene_mf_classic_write_fail_on_enter(void* context) {
Nfc* nfc = context;
Widget* widget = nfc->widget;
notification_message(nfc->notifications, &sequence_error);
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
widget_add_string_multiline_element(
widget,
7,
17,
AlignLeft,
AlignTop,
FontSecondary,
"Not all sectors\nwere written\ncorrectly.");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Finish", nfc_scene_mf_classic_write_fail_widget_callback, nfc);
// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
bool nfc_scene_mf_classic_write_fail_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
}
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneSavedMenu);
}
return consumed;
}
void nfc_scene_mf_classic_write_fail_on_exit(void* context) {
Nfc* nfc = context;
widget_reset(nfc->widget);
}

View File

@@ -0,0 +1,44 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_classic_write_success_popup_callback(void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_mf_classic_write_success_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcSave);
notification_message(nfc->notifications, &sequence_success);
Popup* popup = nfc->popup;
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom);
popup_set_timeout(popup, 1500);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_mf_classic_write_success_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
bool nfc_scene_mf_classic_write_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
}
}
return consumed;
}
void nfc_scene_mf_classic_write_success_on_exit(void* context) {
Nfc* nfc = context;
// Clear view
popup_reset(nfc->popup);
}

View File

@@ -0,0 +1,53 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_wrong_card_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
Nfc* nfc = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}
void nfc_scene_mf_classic_wrong_card_on_enter(void* context) {
Nfc* nfc = context;
Widget* widget = nfc->widget;
notification_message(nfc->notifications, &sequence_error);
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
widget_add_string_multiline_element(
widget,
4,
17,
AlignLeft,
AlignTop,
FontSecondary,
"Data management\nis only possible\nwith initial card");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_classic_wrong_card_widget_callback, nfc);
// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
bool nfc_scene_mf_classic_wrong_card_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
}
}
return consumed;
}
void nfc_scene_mf_classic_wrong_card_on_exit(void* context) {
Nfc* nfc = context;
widget_reset(nfc->widget);
}

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexSave, SubmenuIndexSave,
@@ -48,6 +49,11 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event)
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexEmulateUid) { } else if(event.event == SubmenuIndexEmulateUid) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
DOLPHIN_DEED(DolphinDeedNfcAddEmulate);
} else {
DOLPHIN_DEED(DolphinDeedNfcEmulate);
}
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexInfo) { } else if(event.event == SubmenuIndexInfo) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_MF_UL_DATA_NOT_CHANGED (0UL) #define NFC_MF_UL_DATA_NOT_CHANGED (0UL)
#define NFC_MF_UL_DATA_CHANGED (1UL) #define NFC_MF_UL_DATA_CHANGED (1UL)
@@ -15,7 +14,6 @@ bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* conte
void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { void nfc_scene_mf_ultralight_emulate_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
// Setup view // Setup view
Popup* popup = nfc->popup; Popup* popup = nfc->popup;

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexUnlock, SubmenuIndexUnlock,
@@ -56,6 +57,11 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexEmulate) { } else if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
DOLPHIN_DEED(DolphinDeedNfcAddEmulate);
} else {
DOLPHIN_DEED(DolphinDeedNfcEmulate);
}
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexUnlock) { } else if(event.event == SubmenuIndexUnlock) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
typedef enum { typedef enum {
NfcSceneMfUlReadStateIdle, NfcSceneMfUlReadStateIdle,
@@ -51,7 +50,6 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
void nfc_scene_mf_ultralight_read_auth_on_enter(void* context) { void nfc_scene_mf_ultralight_read_auth_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcRead);
nfc_device_clear(nfc->dev); nfc_device_clear(nfc->dev);
// Setup view // Setup view

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_ultralight_read_auth_result_widget_callback( void nfc_scene_mf_ultralight_read_auth_result_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -37,7 +36,6 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) {
widget_add_string_element( widget_add_string_element(
widget, 0, 17, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); widget, 0, 17, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));
if(mf_ul_data->auth_success) { if(mf_ul_data->auth_success) {
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
furi_string_printf( furi_string_printf(
temp_str, temp_str,
"Password: %02X %02X %02X %02X", "Password: %02X %02X %02X %02X",
@@ -54,8 +52,6 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) {
config_pages->auth_data.pack.raw[1]); config_pages->auth_data.pack.raw[1]);
widget_add_string_element( widget_add_string_element(
widget, 0, 39, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); widget, 0, 39, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));
} else {
DOLPHIN_DEED(DolphinDeedNfcMfulError);
} }
furi_string_printf( furi_string_printf(
temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_ultralight_read_success_widget_callback( void nfc_scene_mf_ultralight_read_success_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -14,7 +13,6 @@ void nfc_scene_mf_ultralight_read_success_widget_callback(
void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
// Setup widget view // Setup widget view
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_mf_ultralight_unlock_warn_dialog_callback(DialogExResult result, void* context) { void nfc_scene_mf_ultralight_unlock_warn_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = context; Nfc* nfc = context;
@@ -30,6 +31,7 @@ bool nfc_scene_mf_ultralight_unlock_warn_on_event(void* context, SceneManagerEve
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DialogExResultCenter) { if(event.event == DialogExResultCenter) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuth); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuth);
DOLPHIN_DEED(DolphinDeedNfcRead);
consumed = true; consumed = true;
} }
} }

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexSaveUid, SubmenuIndexSaveUid,
@@ -41,6 +42,11 @@ bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexEmulateUid) { } else if(event.event == SubmenuIndexEmulateUid) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
DOLPHIN_DEED(DolphinDeedNfcAddEmulate);
} else {
DOLPHIN_DEED(DolphinDeedNfcEmulate);
}
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexInfo) { } else if(event.event == SubmenuIndexInfo) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_nfca_read_success_widget_callback( void nfc_scene_nfca_read_success_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -16,8 +15,6 @@ void nfc_scene_nfca_read_success_widget_callback(
void nfc_scene_nfca_read_success_on_enter(void* context) { void nfc_scene_nfca_read_success_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
// Setup view // Setup view
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
Widget* widget = nfc->widget; Widget* widget = nfc->widget;

View File

@@ -39,7 +39,6 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
void nfc_scene_read_on_enter(void* context) { void nfc_scene_read_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcRead);
nfc_device_clear(nfc->dev); nfc_device_clear(nfc->dev);
// Setup view // Setup view
@@ -62,26 +61,32 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
(event.event == NfcWorkerEventReadUidNfcV)) { (event.event == NfcWorkerEventReadUidNfcV)) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadUidNfcA) { } else if(event.event == NfcWorkerEventReadUidNfcA) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadMfUltralight) { } else if(event.event == NfcWorkerEventReadMfUltralight) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadMfClassicDone) { } else if(event.event == NfcWorkerEventReadMfClassicDone) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadMfDesfire) { } else if(event.event == NfcWorkerEventReadMfDesfire) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadBankCard) { } else if(event.event == NfcWorkerEventReadBankCard) {
notification_message(nfc->notifications, &sequence_success); notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
consumed = true; consumed = true;
} else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) {
if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) {

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_read_card_success_widget_callback( void nfc_scene_read_card_success_widget_callback(
GuiButtonType result, GuiButtonType result,
@@ -18,7 +17,6 @@ void nfc_scene_read_card_success_on_enter(void* context) {
FuriString* temp_str; FuriString* temp_str;
temp_str = furi_string_alloc(); temp_str = furi_string_alloc();
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
// Setup view // Setup view
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;

View File

@@ -2,6 +2,7 @@
#include <lib/toolbox/random_name.h> #include <lib/toolbox/random_name.h>
#include <gui/modules/validators.h> #include <gui/modules/validators.h>
#include <toolbox/path.h> #include <toolbox/path.h>
#include <dolphin/dolphin.h>
void nfc_scene_save_name_text_input_callback(void* context) { void nfc_scene_save_name_text_input_callback(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
@@ -63,6 +64,13 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1); strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
if(nfc_device_save(nfc->dev, nfc->text_store)) { if(nfc_device_save(nfc->dev, nfc->text_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
if(!scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
// Nothing, do not count editing as saving
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
DOLPHIN_DEED(DolphinDeedNfcAddSave);
} else {
DOLPHIN_DEED(DolphinDeedNfcSave);
}
consumed = true; consumed = true;
} else { } else {
consumed = scene_manager_search_and_switch_to_previous_scene( consumed = scene_manager_search_and_switch_to_previous_scene(

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_save_success_popup_callback(void* context) { void nfc_scene_save_success_popup_callback(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
@@ -8,7 +7,6 @@ void nfc_scene_save_success_popup_callback(void* context) {
void nfc_scene_save_success_on_enter(void* context) { void nfc_scene_save_success_on_enter(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcSave);
// Setup view // Setup view
Popup* popup = nfc->popup; Popup* popup = nfc->popup;

View File

@@ -1,8 +1,12 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexEmulate, SubmenuIndexEmulate,
SubmenuIndexEditUid, SubmenuIndexEditUid,
SubmenuIndexDetectReader,
SubmenuIndexWrite,
SubmenuIndexUpdate,
SubmenuIndexRename, SubmenuIndexRename,
SubmenuIndexDelete, SubmenuIndexDelete,
SubmenuIndexInfo, SubmenuIndexInfo,
@@ -41,6 +45,28 @@ void nfc_scene_saved_menu_on_enter(void* context) {
submenu_add_item( submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc); submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
} }
if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
if(!mf_classic_is_card_read(&nfc->dev->dev_data.mf_classic_data)) {
submenu_add_item(
submenu,
"Detect reader",
SubmenuIndexDetectReader,
nfc_scene_saved_menu_submenu_callback,
nfc);
}
submenu_add_item(
submenu,
"Write To Initial Card",
SubmenuIndexWrite,
nfc_scene_saved_menu_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Update From Initial Card",
SubmenuIndexUpdate,
nfc_scene_saved_menu_submenu_callback,
nfc);
}
submenu_add_item( submenu_add_item(
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
if(nfc->dev->shadow_file_exist) { if(nfc->dev->shadow_file_exist) {
@@ -76,6 +102,16 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
} else { } else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
} }
DOLPHIN_DEED(DolphinDeedNfcEmulate);
consumed = true;
} else if(event.event == SubmenuIndexDetectReader) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader);
consumed = true;
} else if(event.event == SubmenuIndexWrite) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrite);
consumed = true;
} else if(event.event == SubmenuIndexUpdate) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicUpdate);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexRename) { } else if(event.event == SubmenuIndexRename) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);

View File

@@ -1,5 +1,4 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_scene_set_uid_byte_input_callback(void* context) { void nfc_scene_set_uid_byte_input_callback(void* context) {
Nfc* nfc = context; Nfc* nfc = context;
@@ -30,7 +29,6 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) { if(event.event == NfcCustomEventByteInputDone) {
DOLPHIN_DEED(DolphinDeedNfcAddSave);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) { if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h" #include "../nfc_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexRead, SubmenuIndexRead,
@@ -47,11 +48,14 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) { if(event.event == SubmenuIndexRead) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
DOLPHIN_DEED(DolphinDeedNfcRead);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexDetectReader) { } else if(event.event == SubmenuIndexDetectReader) {
bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK; bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK;
if(sd_exist) { if(sd_exist) {
nfc_device_data_clear(&nfc->dev->dev_data);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader); scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader);
DOLPHIN_DEED(DolphinDeedNfcDetectReader);
} else { } else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
} }

View File

@@ -1,7 +1,9 @@
#include "detect_reader.h" #include "detect_reader.h"
#include <assets_icons.h>
#include <gui/elements.h> #include <gui/elements.h>
#define DETECT_READER_UID_MAX_LEN (10)
struct DetectReader { struct DetectReader {
View* view; View* view;
DetectReaderDoneCallback callback; DetectReaderDoneCallback callback;
@@ -12,6 +14,7 @@ typedef struct {
uint16_t nonces; uint16_t nonces;
uint16_t nonces_max; uint16_t nonces_max;
DetectReaderState state; DetectReaderState state;
FuriString* uid_str;
} DetectReaderViewModel; } DetectReaderViewModel;
static void detect_reader_draw_callback(Canvas* canvas, void* model) { static void detect_reader_draw_callback(Canvas* canvas, void* model) {
@@ -23,6 +26,10 @@ static void detect_reader_draw_callback(Canvas* canvas, void* model) {
if(m->state == DetectReaderStateStart) { if(m->state == DetectReaderStateStart) {
snprintf(text, sizeof(text), "Touch the reader"); snprintf(text, sizeof(text), "Touch the reader");
canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39);
if(furi_string_size(m->uid_str)) {
elements_multiline_text_aligned(
canvas, 64, 64, AlignCenter, AlignBottom, furi_string_get_cstr(m->uid_str));
}
} else if(m->state == DetectReaderStateReaderDetected) { } else if(m->state == DetectReaderStateReaderDetected) {
snprintf(text, sizeof(text), "Move the Flipper away"); snprintf(text, sizeof(text), "Move the Flipper away");
canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15); canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15);
@@ -86,12 +93,24 @@ DetectReader* detect_reader_alloc() {
view_set_input_callback(detect_reader->view, detect_reader_input_callback); view_set_input_callback(detect_reader->view, detect_reader_input_callback);
view_set_context(detect_reader->view, detect_reader); view_set_context(detect_reader->view, detect_reader);
with_view_model(
detect_reader->view,
DetectReaderViewModel * model,
{ model->uid_str = furi_string_alloc(); },
false);
return detect_reader; return detect_reader;
} }
void detect_reader_free(DetectReader* detect_reader) { void detect_reader_free(DetectReader* detect_reader) {
furi_assert(detect_reader); furi_assert(detect_reader);
with_view_model(
detect_reader->view,
DetectReaderViewModel * model,
{ furi_string_free(model->uid_str); },
false);
view_free(detect_reader->view); view_free(detect_reader->view);
free(detect_reader); free(detect_reader);
} }
@@ -106,6 +125,7 @@ void detect_reader_reset(DetectReader* detect_reader) {
model->nonces = 0; model->nonces = 0;
model->nonces_max = 0; model->nonces_max = 0;
model->state = DetectReaderStateStart; model->state = DetectReaderStateStart;
furi_string_reset(model->uid_str);
}, },
false); false);
} }
@@ -152,3 +172,19 @@ void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState stat
with_view_model( with_view_model(
detect_reader->view, DetectReaderViewModel * model, { model->state = state; }, true); detect_reader->view, DetectReaderViewModel * model, { model->state = state; }, true);
} }
void detect_reader_set_uid(DetectReader* detect_reader, uint8_t* uid, uint8_t uid_len) {
furi_assert(detect_reader);
furi_assert(uid);
furi_assert(uid_len < DETECT_READER_UID_MAX_LEN);
with_view_model(
detect_reader->view,
DetectReaderViewModel * model,
{
furi_string_set_str(model->uid_str, "UID:");
for(size_t i = 0; i < uid_len; i++) {
furi_string_cat_printf(model->uid_str, " %02X", uid[i]);
}
},
true);
}

View File

@@ -32,3 +32,5 @@ void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_m
void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected); void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected);
void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state); void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state);
void detect_reader_set_uid(DetectReader* detect_reader, uint8_t* uid, uint8_t uid_len);

View File

@@ -1,6 +1,5 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include "../views/subghz_frequency_analyzer.h" #include "../views/subghz_frequency_analyzer.h"
#include <dolphin/dolphin.h>
void subghz_scene_frequency_analyzer_callback(SubGhzCustomEvent event, void* context) { void subghz_scene_frequency_analyzer_callback(SubGhzCustomEvent event, void* context) {
furi_assert(context); furi_assert(context);
@@ -10,7 +9,6 @@ void subghz_scene_frequency_analyzer_callback(SubGhzCustomEvent event, void* con
void subghz_scene_frequency_analyzer_on_enter(void* context) { void subghz_scene_frequency_analyzer_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer);
subghz_frequency_analyzer_set_callback( subghz_frequency_analyzer_set_callback(
subghz->subghz_frequency_analyzer, subghz_scene_frequency_analyzer_callback, subghz); subghz->subghz_frequency_analyzer, subghz_scene_frequency_analyzer_callback, subghz);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer);

View File

@@ -6,6 +6,7 @@
#define RAW_FILE_NAME "Raw_signal_" #define RAW_FILE_NAME "Raw_signal_"
#define TAG "SubGhzSceneReadRAW" #define TAG "SubGhzSceneReadRAW"
#define RAW_THRESHOLD_RSSI_LOW_COUNT 10
bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { bool subghz_scene_read_raw_update_filename(SubGhz* subghz) {
bool ret = false; bool ret = false;
@@ -72,24 +73,33 @@ void subghz_scene_read_raw_on_enter(void* context) {
switch(subghz->txrx->rx_key_state) { switch(subghz->txrx->rx_key_state) {
case SubGhzRxKeyStateBack: case SubGhzRxKeyStateBack:
subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, ""); subghz_read_raw_set_status(
subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", subghz->txrx->raw_threshold_rssi);
break; break;
case SubGhzRxKeyStateRAWLoad: case SubGhzRxKeyStateRAWLoad:
path_extract_filename(subghz->file_path, file_name, true); path_extract_filename(subghz->file_path, file_name, true);
subghz_read_raw_set_status( subghz_read_raw_set_status(
subghz->subghz_read_raw, subghz->subghz_read_raw,
SubGhzReadRAWStatusLoadKeyTX, SubGhzReadRAWStatusLoadKeyTX,
furi_string_get_cstr(file_name)); furi_string_get_cstr(file_name),
subghz->txrx->raw_threshold_rssi);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
break; break;
case SubGhzRxKeyStateRAWSave: case SubGhzRxKeyStateRAWSave:
path_extract_filename(subghz->file_path, file_name, true); path_extract_filename(subghz->file_path, file_name, true);
subghz_read_raw_set_status( subghz_read_raw_set_status(
subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, furi_string_get_cstr(file_name)); subghz->subghz_read_raw,
SubGhzReadRAWStatusSaveKey,
furi_string_get_cstr(file_name),
subghz->txrx->raw_threshold_rssi);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
break; break;
default: default:
subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusStart, ""); subghz_read_raw_set_status(
subghz->subghz_read_raw,
SubGhzReadRAWStatusStart,
"",
subghz->txrx->raw_threshold_rssi);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
break; break;
} }
@@ -213,7 +223,12 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
} else { } else {
DOLPHIN_DEED(DolphinDeedSubGhzSend); if(scene_manager_has_previous_scene(
subghz->scene_manager, SubGhzSceneSaved) ||
!scene_manager_has_previous_scene(
subghz->scene_manager, SubGhzSceneStart)) {
DOLPHIN_DEED(DolphinDeedSubGhzSend);
}
// set callback end tx // set callback end tx
subghz_protocol_raw_file_encoder_worker_set_callback_end( subghz_protocol_raw_file_encoder_worker_set_callback_end(
(SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(
@@ -273,7 +288,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) { if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else { } else {
//subghz_get_preset_name(subghz, subghz->error_str); subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT;
if(subghz_protocol_raw_save_to_file_init( if(subghz_protocol_raw_save_to_file_init(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result,
RAW_FILE_NAME, RAW_FILE_NAME,
@@ -319,7 +334,35 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
subghz->subghz_read_raw, subghz->subghz_read_raw,
subghz_protocol_raw_get_sample_write( subghz_protocol_raw_get_sample_write(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result)); (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result));
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, furi_hal_subghz_get_rssi());
float rssi = furi_hal_subghz_get_rssi();
if(subghz->txrx->raw_threshold_rssi == SUBGHZ_RAW_TRESHOLD_MIN) {
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true);
subghz_protocol_raw_save_to_file_pause(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false);
} else {
if(rssi < subghz->txrx->raw_threshold_rssi) {
subghz->txrx->raw_threshold_rssi_low_count++;
if(subghz->txrx->raw_threshold_rssi_low_count > RAW_THRESHOLD_RSSI_LOW_COUNT) {
subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT;
}
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false);
} else {
subghz->txrx->raw_threshold_rssi_low_count = 0;
}
if(subghz->txrx->raw_threshold_rssi_low_count == RAW_THRESHOLD_RSSI_LOW_COUNT) {
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false);
subghz_protocol_raw_save_to_file_pause(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, true);
} else {
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true);
subghz_protocol_raw_save_to_file_pause(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false);
}
}
break; break;
case SubGhzNotificationStateTx: case SubGhzNotificationStateTx:
notification_message(subghz->notifications, &sequence_blink_magenta_10); notification_message(subghz->notifications, &sequence_blink_magenta_10);

View File

@@ -1,5 +1,6 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include "../views/receiver.h" #include "../views/receiver.h"
#include <dolphin/dolphin.h>
static const NotificationSequence subghs_sequence_rx = { static const NotificationSequence subghs_sequence_rx = {
&message_green_255, &message_green_255,
@@ -181,6 +182,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz->txrx->idx_menu_chosen = subghz->txrx->idx_menu_chosen =
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
DOLPHIN_DEED(DolphinDeedSubGhzReceiverInfo);
consumed = true; consumed = true;
break; break;
case SubGhzCustomEventViewReceiverConfig: case SubGhzCustomEventViewReceiverConfig:

View File

@@ -1,10 +1,41 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include <lib/toolbox/value_index.h>
enum SubGhzSettingIndex { enum SubGhzSettingIndex {
SubGhzSettingIndexFrequency, SubGhzSettingIndexFrequency,
SubGhzSettingIndexHopping, SubGhzSettingIndexHopping,
SubGhzSettingIndexModulation, SubGhzSettingIndexModulation,
SubGhzSettingIndexLock, SubGhzSettingIndexLock,
SubGhzSettingIndexRAWThesholdRSSI,
};
#define RAW_THRESHOLD_RSSI_COUNT 11
const char* const raw_theshold_rssi_text[RAW_THRESHOLD_RSSI_COUNT] = {
"-----",
"-85.0",
"-80.0",
"-75.0",
"-70.0",
"-65.0",
"-60.0",
"-55.0",
"-50.0",
"-45.0",
"-40.0",
};
const float raw_theshold_rssi_value[RAW_THRESHOLD_RSSI_COUNT] = {
-90.0f,
-85.0f,
-80.0f,
-75.0f,
-70.0f,
-65.0f,
-60.0f,
-55.0f,
-50.0f,
-45.0f,
-40.0f,
}; };
#define HOPPING_COUNT 2 #define HOPPING_COUNT 2
@@ -136,6 +167,14 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
subghz->txrx->hopper_state = hopping_value[index]; subghz->txrx->hopper_state = hopping_value[index];
} }
static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, raw_theshold_rssi_text[index]);
subghz->txrx->raw_threshold_rssi = raw_theshold_rssi_value[index];
}
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
furi_assert(context); furi_assert(context);
SubGhz* subghz = context; SubGhz* subghz = context;
@@ -204,6 +243,19 @@ void subghz_scene_receiver_config_on_enter(void* context) {
subghz_scene_receiver_config_var_list_enter_callback, subghz_scene_receiver_config_var_list_enter_callback,
subghz); subghz);
} }
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubGhzCustomEventManagerSet) {
item = variable_item_list_add(
subghz->variable_item_list,
"RSSI Threshold:",
RAW_THRESHOLD_RSSI_COUNT,
subghz_scene_receiver_config_set_raw_threshold_rssi,
subghz);
value_index = value_index_float(
subghz->txrx->raw_threshold_rssi, raw_theshold_rssi_value, RAW_THRESHOLD_RSSI_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, raw_theshold_rssi_text[value_index]);
}
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
} }

View File

@@ -1,6 +1,5 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include "../helpers/subghz_custom_event.h" #include "../helpers/subghz_custom_event.h"
#include <dolphin/dolphin.h>
void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) { void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) {
furi_assert(context); furi_assert(context);
@@ -45,7 +44,6 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
void subghz_scene_receiver_info_on_enter(void* context) { void subghz_scene_receiver_info_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
DOLPHIN_DEED(DolphinDeedSubGhzReceiverInfo);
if(subghz_scene_receiver_info_update_parser(subghz)) { if(subghz_scene_receiver_info_update_parser(subghz)) {
FuriString* frequency_str; FuriString* frequency_str;
FuriString* modulation_str; FuriString* modulation_str;

View File

@@ -4,6 +4,7 @@
#include "../helpers/subghz_custom_event.h" #include "../helpers/subghz_custom_event.h"
#include <lib/subghz/protocols/raw.h> #include <lib/subghz/protocols/raw.h>
#include <gui/modules/validators.h> #include <gui/modules/validators.h>
#include <dolphin/dolphin.h>
#define MAX_TEXT_INPUT_LEN 22 #define MAX_TEXT_INPUT_LEN 22
@@ -131,6 +132,17 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
} }
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneSavedMenu)) {
// Nothing, do not count editing as saving
} else if(scene_manager_has_previous_scene(
subghz->scene_manager, SubGhzSceneMoreRAW)) {
// Ditto, for RAW signals
} else if(scene_manager_has_previous_scene(
subghz->scene_manager, SubGhzSceneSetType)) {
DOLPHIN_DEED(DolphinDeedSubGhzAddManually);
} else {
DOLPHIN_DEED(DolphinDeedSubGhzSave);
}
return true; return true;
} else { } else {
furi_string_set(subghz->error_str, "No name file"); furi_string_set(subghz->error_str, "No name file");

View File

@@ -1,7 +1,5 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include "../helpers/subghz_custom_event.h" #include "../helpers/subghz_custom_event.h"
#include <dolphin/helpers/dolphin_deed.h>
#include <dolphin/dolphin.h>
void subghz_scene_save_success_popup_callback(void* context) { void subghz_scene_save_success_popup_callback(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
@@ -10,7 +8,6 @@ void subghz_scene_save_success_popup_callback(void* context) {
void subghz_scene_save_success_on_enter(void* context) { void subghz_scene_save_success_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
DOLPHIN_DEED(DolphinDeedSubGhzSave);
// Setup view // Setup view
Popup* popup = subghz->popup; Popup* popup = subghz->popup;

View File

@@ -3,7 +3,6 @@
#include <lib/subghz/protocols/secplus_v1.h> #include <lib/subghz/protocols/secplus_v1.h>
#include <lib/subghz/protocols/secplus_v2.h> #include <lib/subghz/protocols/secplus_v2.h>
#include <lib/subghz/blocks/math.h> #include <lib/subghz/blocks/math.h>
#include <dolphin/dolphin.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/stream.h> #include <lib/toolbox/stream/stream.h>
#include <lib/subghz/protocols/protocol_items.h> #include <lib/subghz/protocols/protocol_items.h>
@@ -381,7 +380,6 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
if(generated_protocol) { if(generated_protocol) {
subghz_file_name_clear(subghz); subghz_file_name_clear(subghz);
DOLPHIN_DEED(DolphinDeedSubGhzAddManually);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
return true; return true;
} }

View File

@@ -1,4 +1,5 @@
#include "../subghz_i.h" #include "../subghz_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexRead = 10, SubmenuIndexRead = 10,
@@ -84,6 +85,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer);
return true; return true;
} else if(event.event == SubmenuIndexTest) { } else if(event.event == SubmenuIndexTest) {
scene_manager_set_scene_state( scene_manager_set_scene_state(

View File

@@ -50,7 +50,6 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
void subghz_scene_transmitter_on_enter(void* context) { void subghz_scene_transmitter_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
DOLPHIN_DEED(DolphinDeedSubGhzSend);
if(!subghz_scene_transmitter_update_data_show(subghz)) { if(!subghz_scene_transmitter_update_data_show(subghz)) {
view_dispatcher_send_custom_event( view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewTransmitterError); subghz->view_dispatcher, SubGhzCustomEventViewTransmitterError);
@@ -78,6 +77,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
} else { } else {
subghz->state_notifications = SubGhzNotificationStateTx; subghz->state_notifications = SubGhzNotificationStateTx;
subghz_scene_transmitter_update_data_show(subghz); subghz_scene_transmitter_update_data_show(subghz);
DOLPHIN_DEED(DolphinDeedSubGhzSend);
} }
} }
return true; return true;

View File

@@ -178,6 +178,7 @@ SubGhz* subghz_alloc() {
subghz->txrx->txrx_state = SubGhzTxRxStateSleep; subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
subghz->txrx->hopper_state = SubGhzHopperStateOFF; subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz->txrx->raw_threshold_rssi = SUBGHZ_RAW_TRESHOLD_MIN;
subghz->txrx->history = subghz_history_alloc(); subghz->txrx->history = subghz_history_alloc();
subghz->txrx->worker = subghz_worker_alloc(); subghz->txrx->worker = subghz_worker_alloc();
subghz->txrx->fff_data = flipper_format_string_alloc(); subghz->txrx->fff_data = flipper_format_string_alloc();

View File

@@ -102,8 +102,8 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) {
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
furi_hal_subghz_idle(); furi_hal_subghz_idle();
furi_hal_subghz_set_frequency_and_path(frequency); furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_write(&gpio_cc1101_g0, false);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_cc1101_g0, true);
bool ret = furi_hal_subghz_tx(); bool ret = furi_hal_subghz_tx();
subghz->txrx->txrx_state = SubGhzTxRxStateTx; subghz->txrx->txrx_state = SubGhzTxRxStateTx;
return ret; return ret;

View File

@@ -13,6 +13,7 @@
#include "views/subghz_test_packet.h" #include "views/subghz_test_packet.h"
#include <gui/gui.h> #include <gui/gui.h>
#include <assets_icons.h>
#include <dialogs/dialogs.h> #include <dialogs/dialogs.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <notification/notification_messages.h> #include <notification/notification_messages.h>
@@ -54,6 +55,9 @@ struct SubGhzTxRx {
uint8_t hopper_timeout; uint8_t hopper_timeout;
uint8_t hopper_idx_frequency; uint8_t hopper_idx_frequency;
SubGhzRxKeyState rx_key_state; SubGhzRxKeyState rx_key_state;
float raw_threshold_rssi;
uint8_t raw_threshold_rssi_low_count;
}; };
typedef struct SubGhzTxRx SubGhzTxRx; typedef struct SubGhzTxRx SubGhzTxRx;

View File

@@ -23,10 +23,12 @@ typedef struct {
FuriString* sample_write; FuriString* sample_write;
FuriString* file_name; FuriString* file_name;
uint8_t* rssi_history; uint8_t* rssi_history;
uint8_t rssi_curret;
bool rssi_history_end; bool rssi_history_end;
uint8_t ind_write; uint8_t ind_write;
uint8_t ind_sin; uint8_t ind_sin;
SubGhzReadRAWStatus status; SubGhzReadRAWStatus status;
float raw_threshold_rssi;
} SubGhzReadRAWModel; } SubGhzReadRAWModel;
void subghz_read_raw_set_callback( void subghz_read_raw_set_callback(
@@ -54,21 +56,27 @@ void subghz_read_raw_add_data_statusbar(
true); true);
} }
void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) { void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace) {
furi_assert(instance); furi_assert(instance);
uint8_t u_rssi = 0; uint8_t u_rssi = 0;
if(rssi < -90) { if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
u_rssi = 0; u_rssi = 0;
} else { } else {
u_rssi = (uint8_t)((rssi + 90) / 2.7); u_rssi = (uint8_t)((rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7);
} }
with_view_model( with_view_model(
instance->view, instance->view,
SubGhzReadRAWModel * model, SubGhzReadRAWModel * model,
{ {
model->rssi_history[model->ind_write++] = u_rssi; model->rssi_curret = u_rssi;
if(trace) {
model->rssi_history[model->ind_write++] = u_rssi;
} else {
model->rssi_history[model->ind_write] = u_rssi;
}
if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) { if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
model->rssi_history_end = true; model->rssi_history_end = true;
model->ind_write = 0; model->ind_write = 0;
@@ -187,24 +195,53 @@ void subghz_read_raw_draw_scale(Canvas* canvas, SubGhzReadRAWModel* model) {
void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) { void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
int ind = 0; int ind = 0;
int base = 0; int base = 0;
uint8_t width = 2;
if(model->rssi_history_end == false) { if(model->rssi_history_end == false) {
for(int i = model->ind_write; i >= 0; i--) { for(int i = model->ind_write; i >= 0; i--) {
canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]); canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]);
} }
canvas_draw_line(
canvas, model->ind_write + 1, 47, model->ind_write + 1, 47 - model->rssi_curret);
if(model->ind_write > 3) { if(model->ind_write > 3) {
canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13); canvas_draw_line(
canvas, model->ind_write - 1, 47, model->ind_write - 1, 47 - model->rssi_curret);
for(uint8_t i = 13; i < 47; i += width * 2) {
canvas_draw_line(canvas, model->ind_write, i, model->ind_write, i + width);
}
canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12); canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12);
canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13); canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13);
} }
} else { } else {
int i = 0;
base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write; base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write;
for(int i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) { for(i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i > 0; i--) {
ind = i - base; ind = i - base;
if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE;
canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]); canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]);
} }
canvas_draw_line( canvas_draw_line(
canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 13); canvas,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
47,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
47 - model->rssi_curret);
canvas_draw_line(
canvas,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
47,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
47 - model->rssi_curret);
for(uint8_t i = 13; i < 47; i += width * 2) {
canvas_draw_line(
canvas,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE,
i,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE,
i + width);
}
canvas_draw_line( canvas_draw_line(
canvas, canvas,
SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2,
@@ -220,6 +257,24 @@ void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
} }
} }
void subghz_read_raw_draw_threshold_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
uint8_t x = 118;
uint8_t y = 48;
if(model->raw_threshold_rssi > SUBGHZ_RAW_TRESHOLD_MIN) {
uint8_t x = 118;
y -= (uint8_t)((model->raw_threshold_rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7);
uint8_t width = 3;
for(uint8_t i = 0; i < x; i += width * 2) {
canvas_draw_line(canvas, i, y, i + width, y);
}
}
canvas_draw_line(canvas, x, y - 2, x, y + 2);
canvas_draw_line(canvas, x - 1, y - 1, x - 1, y + 1);
canvas_draw_dot(canvas, x - 2, y);
}
void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
uint8_t graphics_mode = 1; uint8_t graphics_mode = 1;
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
@@ -278,8 +333,9 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
} else { } else {
subghz_read_raw_draw_rssi(canvas, model); subghz_read_raw_draw_rssi(canvas, model);
subghz_read_raw_draw_scale(canvas, model); subghz_read_raw_draw_scale(canvas, model);
subghz_read_raw_draw_threshold_rssi(canvas, model);
canvas_set_font_direction(canvas, CanvasDirectionBottomToTop); canvas_set_font_direction(canvas, CanvasDirectionBottomToTop);
canvas_draw_str(canvas, 126, 40, "RSSI"); canvas_draw_str(canvas, 128, 40, "RSSI");
canvas_set_font_direction(canvas, CanvasDirectionLeftToRight); canvas_set_font_direction(canvas, CanvasDirectionLeftToRight);
} }
} }
@@ -433,7 +489,8 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
void subghz_read_raw_set_status( void subghz_read_raw_set_status(
SubGhzReadRAW* instance, SubGhzReadRAW* instance,
SubGhzReadRAWStatus status, SubGhzReadRAWStatus status,
const char* file_name) { const char* file_name,
float raw_threshold_rssi) {
furi_assert(instance); furi_assert(instance);
switch(status) { switch(status) {
@@ -447,6 +504,7 @@ void subghz_read_raw_set_status(
model->ind_write = 0; model->ind_write = 0;
furi_string_reset(model->file_name); furi_string_reset(model->file_name);
furi_string_set(model->sample_write, "0 spl."); furi_string_set(model->sample_write, "0 spl.");
model->raw_threshold_rssi = raw_threshold_rssi;
}, },
true); true);
break; break;
@@ -536,6 +594,7 @@ SubGhzReadRAW* subghz_read_raw_alloc() {
model->sample_write = furi_string_alloc(); model->sample_write = furi_string_alloc();
model->file_name = furi_string_alloc(); model->file_name = furi_string_alloc();
model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t)); model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
model->raw_threshold_rssi = -127.0f;
}, },
true); true);

View File

@@ -3,6 +3,8 @@
#include <gui/view.h> #include <gui/view.h>
#include "../helpers/subghz_custom_event.h" #include "../helpers/subghz_custom_event.h"
#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
typedef struct SubGhzReadRAW SubGhzReadRAW; typedef struct SubGhzReadRAW SubGhzReadRAW;
typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context); typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context);
@@ -40,11 +42,12 @@ void subghz_read_raw_stop_send(SubGhzReadRAW* instance);
void subghz_read_raw_update_sin(SubGhzReadRAW* instance); void subghz_read_raw_update_sin(SubGhzReadRAW* instance);
void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi); void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace);
void subghz_read_raw_set_status( void subghz_read_raw_set_status(
SubGhzReadRAW* instance, SubGhzReadRAW* instance,
SubGhzReadRAWStatus status, SubGhzReadRAWStatus status,
const char* file_name); const char* file_name,
float raw_threshold_rssi);
View* subghz_read_raw_get_view(SubGhzReadRAW* subghz_static); View* subghz_read_raw_get_view(SubGhzReadRAW* subghz_static);

View File

@@ -4,6 +4,7 @@
#include "scenes/u2f_scene.h" #include "scenes/u2f_scene.h"
#include <gui/gui.h> #include <gui/gui.h>
#include <assets_icons.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <gui/modules/submenu.h> #include <gui/modules/submenu.h>

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