mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-11 19:33:30 -07:00
Merge branch 'dev' into ntag-auto-pwd-capture
This commit is contained in:
+7
-2
@@ -18,7 +18,7 @@
|
||||
/applications/main/gpio/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
/applications/main/ibutton/ @skotopes @DrZlo13 @hedger @gsurkov
|
||||
/applications/main/infrared/ @skotopes @DrZlo13 @hedger @gsurkov
|
||||
/applications/main/nfc/ @skotopes @DrZlo13 @hedger @gornekich
|
||||
/applications/main/nfc/ @skotopes @DrZlo13 @hedger @gornekich @Astrrra
|
||||
/applications/main/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm
|
||||
/applications/main/u2f/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
|
||||
/applications/system/storage_move_to_sd/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
|
||||
/applications/debug/unit_tests/ @skotopes @DrZlo13 @hedger @nminaylov @gornekich @Astrrra @gsurkov @Skorpionm
|
||||
|
||||
# Documentation
|
||||
/documentation/ @skotopes @DrZlo13 @hedger @drunkbatya
|
||||
/scripts/toolchain/ @skotopes @DrZlo13 @hedger @drunkbatya
|
||||
@@ -54,6 +56,9 @@
|
||||
/lib/mbedtls/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
/lib/micro-ecc/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
/lib/nanopb/ @skotopes @DrZlo13 @hedger @nminaylov
|
||||
/lib/nfc/ @skotopes @DrZlo13 @hedger @gornekich
|
||||
/lib/nfc/ @skotopes @DrZlo13 @hedger @gornekich @Astrrra
|
||||
/lib/one_wire/ @skotopes @DrZlo13 @hedger @gsurkov
|
||||
/lib/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm
|
||||
|
||||
# CI/CD
|
||||
/.github/workflows/ @skotopes @DrZlo13 @hedger @drunkbatya
|
||||
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
export RODATA_SIZE="$(get_size ".rodata")"
|
||||
export DATA_SIZE="$(get_size ".data")"
|
||||
export FREE_FLASH_SIZE="$(get_size ".free_flash")"
|
||||
python3 -m pip install mariadb
|
||||
python3 -m pip install mariadb==1.1.4
|
||||
python3 scripts/amap_mariadb_insert.py \
|
||||
${{ secrets.AMAP_MARIADB_USER }} \
|
||||
${{ secrets.AMAP_MARIADB_PASSWORD }} \
|
||||
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
|
||||
- name: 'Generate compile_comands.json'
|
||||
run: |
|
||||
FBT_TOOLCHAIN_PATH=/runner/_work ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking
|
||||
FBT_TOOLCHAIN_PATH=/runner/_work ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons
|
||||
|
||||
- name: 'Static code analysis'
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
name: 'Unit tests'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TARGETS: f7
|
||||
DEFAULT_TARGET: f7
|
||||
|
||||
jobs:
|
||||
run_units_on_test_bench:
|
||||
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: 'Flash unit tests firmware'
|
||||
id: flashing
|
||||
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.flashing.outcome == 'success'
|
||||
run: |
|
||||
. scripts/toolchain/fbtenv.sh
|
||||
./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}}
|
||||
|
||||
- name: 'Format flipper SD card'
|
||||
id: format
|
||||
if: steps.connect.outcome == 'success'
|
||||
run: |
|
||||
. scripts/toolchain/fbtenv.sh
|
||||
./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/toolchain/fbtenv.sh
|
||||
./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: |
|
||||
. scripts/toolchain/fbtenv.sh
|
||||
./scripts/testing/units.py ${{steps.device.outputs.flipper}}
|
||||
@@ -54,3 +54,5 @@ openocd.log
|
||||
# PVS Studio temporary files
|
||||
.PVS-Studio/
|
||||
PVS-Studio.log
|
||||
|
||||
.gdbinit
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//-V:BPTREE_DEF2:779,1086,557,773,512
|
||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685
|
||||
//-V:ALGO_DEF:1048,747,1044
|
||||
//-V:TUPLE_DEF2:524,590,1001,760
|
||||
|
||||
# Non-severe malloc/null pointer deref warnings
|
||||
//-V::522:2,3
|
||||
|
||||
Vendored
+4
@@ -38,6 +38,7 @@
|
||||
"postAttachCommands": [
|
||||
// "compare-sections",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "source debug/FreeRTOS/FreeRTOS.py",
|
||||
// "svd_load debug/STM32WB55_CM4.svd"
|
||||
]
|
||||
@@ -59,6 +60,7 @@
|
||||
"set confirm off",
|
||||
"set mem inaccessible-by-default off",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "compare-sections",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
@@ -76,6 +78,7 @@
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
@@ -95,6 +98,7 @@
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
],
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
|
||||
+26
-19
@@ -7,6 +7,7 @@
|
||||
# construction of certain targets behind command-line options.
|
||||
|
||||
import os
|
||||
from fbt.util import path_as_posix
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
|
||||
@@ -33,10 +34,6 @@ coreenv = SConscript(
|
||||
)
|
||||
SConscript("site_scons/cc.scons", exports={"ENV": coreenv})
|
||||
|
||||
# Store root dir in environment for certain tools
|
||||
coreenv["ROOT_DIR"] = Dir(".")
|
||||
|
||||
|
||||
# Create a separate "dist" environment and add construction envs to it
|
||||
distenv = coreenv.Clone(
|
||||
tools=[
|
||||
@@ -47,6 +44,7 @@ distenv = coreenv.Clone(
|
||||
"jflash",
|
||||
],
|
||||
ENV=os.environ,
|
||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||
)
|
||||
|
||||
firmware_env = distenv.AddFwProject(
|
||||
@@ -144,21 +142,28 @@ distenv.Default(basic_dist)
|
||||
dist_dir = distenv.GetProjetDirName()
|
||||
fap_dist = [
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps/debug_elf",
|
||||
firmware_env["FW_EXTAPPS"]["debug"].values(),
|
||||
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
|
||||
list(
|
||||
app_artifact.debug
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
),
|
||||
*(
|
||||
distenv.Install(f"#/dist/{dist_dir}/apps/{dist_entry[0]}", dist_entry[1])
|
||||
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps",
|
||||
"#/assets/resources/apps",
|
||||
),
|
||||
]
|
||||
Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
|
||||
Depends(
|
||||
fap_dist,
|
||||
list(
|
||||
app_artifact.validator
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
)
|
||||
Alias("fap_dist", fap_dist)
|
||||
# distenv.Default(fap_dist)
|
||||
|
||||
distenv.Depends(
|
||||
firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"]["resources_dist"]
|
||||
)
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
||||
|
||||
|
||||
# Target for bundling core2 package for qFlipper
|
||||
@@ -196,6 +201,7 @@ firmware_debug = distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
distenv.Depends(firmware_debug, firmware_flash)
|
||||
|
||||
@@ -205,6 +211,7 @@ distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
|
||||
# Debug alien elf
|
||||
@@ -213,7 +220,7 @@ distenv.PhonyTarget(
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
@@ -233,14 +240,14 @@ distenv.PhonyTarget(
|
||||
# Linter
|
||||
distenv.PhonyTarget(
|
||||
"lint",
|
||||
"${PYTHON3} scripts/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format",
|
||||
"${PYTHON3} scripts/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||
@@ -280,7 +287,7 @@ distenv.PhonyTarget(
|
||||
)
|
||||
|
||||
# Start Flipper CLI via PySerial's miniterm
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py")
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
|
||||
@@ -8,4 +8,5 @@ App(
|
||||
stack_size=2 * 1024,
|
||||
order=150,
|
||||
fap_category="Debug",
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "assets_icons.h"
|
||||
#include <file_browser_test_icons.h>
|
||||
#include "file_browser_app_i.h"
|
||||
#include "gui/modules/file_browser.h"
|
||||
#include <furi.h>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 576 B |
@@ -424,6 +424,7 @@ MU_TEST(infrared_test_decoder_mixed) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_nec) {
|
||||
@@ -489,6 +490,15 @@ MU_TEST(infrared_test_encoder_rc6) {
|
||||
infrared_test_run_encoder(InfraredProtocolRC6, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_kaseikyo) {
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
|
||||
@@ -498,6 +508,7 @@ MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC6, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(infrared_test) {
|
||||
@@ -515,6 +526,7 @@ MU_TEST_SUITE(infrared_test) {
|
||||
MU_RUN_TEST(infrared_test_decoder_nec);
|
||||
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
||||
MU_RUN_TEST(infrared_test_decoder_necext1);
|
||||
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
|
||||
MU_RUN_TEST(infrared_test_decoder_mixed);
|
||||
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <lib/nfc/protocols/nfca.h>
|
||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||
#include <lib/digital_signal/digital_signal.h>
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include <applications/main/nfc/helpers/nfc_generators.h>
|
||||
|
||||
#include <lib/flipper_format/flipper_format_i.h>
|
||||
#include <lib/toolbox/stream/file_stream.h>
|
||||
@@ -17,6 +19,7 @@
|
||||
#define NFC_TEST_SIGNAL_SHORT_FILE "nfc_nfca_signal_short.nfc"
|
||||
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.nfc"
|
||||
#define NFC_TEST_DICT_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
|
||||
#define NFC_TEST_NFC_DEV_PATH EXT_PATH("unit_tests/nfc/nfc_dev_test.nfc")
|
||||
|
||||
static const char* nfc_test_file_type = "Flipper NFC test";
|
||||
static const uint32_t nfc_test_file_version = 1;
|
||||
@@ -287,9 +290,203 @@ MU_TEST(mf_classic_dict_load_test) {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST(nfca_file_test) {
|
||||
NfcDevice* nfc = nfc_device_alloc();
|
||||
mu_assert(nfc != NULL, "nfc_device_data != NULL assert failed\r\n");
|
||||
nfc->format = NfcDeviceSaveFormatUid;
|
||||
|
||||
// Fill the UID, sak, ATQA and type
|
||||
uint8_t uid[7] = {0x04, 0x01, 0x23, 0x45, 0x67, 0x89, 0x00};
|
||||
memcpy(nfc->dev_data.nfc_data.uid, uid, 7);
|
||||
nfc->dev_data.nfc_data.uid_len = 7;
|
||||
|
||||
nfc->dev_data.nfc_data.sak = 0x08;
|
||||
nfc->dev_data.nfc_data.atqa[0] = 0x00;
|
||||
nfc->dev_data.nfc_data.atqa[1] = 0x04;
|
||||
nfc->dev_data.nfc_data.type = FuriHalNfcTypeA;
|
||||
|
||||
// Save the NFC device data to the file
|
||||
mu_assert(
|
||||
nfc_device_save(nfc, NFC_TEST_NFC_DEV_PATH), "nfc_device_save == true assert failed\r\n");
|
||||
nfc_device_free(nfc);
|
||||
|
||||
// Load the NFC device data from the file
|
||||
NfcDevice* nfc_validate = nfc_device_alloc();
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, true),
|
||||
"nfc_device_load == true assert failed\r\n");
|
||||
|
||||
// Check the UID, sak, ATQA and type
|
||||
mu_assert(memcmp(nfc_validate->dev_data.nfc_data.uid, uid, 7) == 0, "uid assert failed\r\n");
|
||||
mu_assert(nfc_validate->dev_data.nfc_data.sak == 0x08, "sak == 0x08 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.atqa[0] == 0x00, "atqa[0] == 0x00 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.atqa[1] == 0x04, "atqa[1] == 0x04 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
|
||||
"type == FuriHalNfcTypeA assert failed\r\n");
|
||||
nfc_device_free(nfc_validate);
|
||||
}
|
||||
|
||||
static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
|
||||
NfcDevice* nfc_dev = nfc_device_alloc();
|
||||
mu_assert(nfc_dev != NULL, "nfc_device_data != NULL assert failed\r\n");
|
||||
nfc_dev->format = NfcDeviceSaveFormatMifareClassic;
|
||||
|
||||
// Create a test file
|
||||
nfc_generate_mf_classic(&nfc_dev->dev_data, uid_len, type);
|
||||
|
||||
// Get the uid from generated MFC
|
||||
uint8_t uid[7] = {0};
|
||||
memcpy(uid, nfc_dev->dev_data.nfc_data.uid, uid_len);
|
||||
uint8_t sak = nfc_dev->dev_data.nfc_data.sak;
|
||||
uint8_t atqa[2] = {};
|
||||
memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2);
|
||||
|
||||
MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data;
|
||||
// Check the manufacturer block (should be uid[uid_len] + 0xFF[rest])
|
||||
uint8_t manufacturer_block[16] = {0};
|
||||
memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16);
|
||||
mu_assert(
|
||||
memcmp(manufacturer_block, uid, uid_len) == 0,
|
||||
"manufacturer_block uid doesn't match the file\r\n");
|
||||
for(uint8_t i = uid_len; i < 16; i++) {
|
||||
mu_assert(
|
||||
manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n");
|
||||
}
|
||||
|
||||
// Reference sector trailers (should be 0xFF[6] + 0xFF + 0x07 + 0x80 + 0x69 + 0xFF[6])
|
||||
uint8_t sector_trailer[16] = {
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0x07,
|
||||
0x80,
|
||||
0x69,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF};
|
||||
// Reference block data
|
||||
uint8_t block_data[16] = {};
|
||||
memset(block_data, 0xff, sizeof(block_data));
|
||||
uint16_t total_blocks = mf_classic_get_total_block_num(type);
|
||||
for(size_t i = 1; i < total_blocks; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
mu_assert(
|
||||
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
|
||||
"Failed sector trailer compare");
|
||||
} else {
|
||||
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
|
||||
}
|
||||
}
|
||||
// Save the NFC device data to the file
|
||||
mu_assert(
|
||||
nfc_device_save(nfc_dev, NFC_TEST_NFC_DEV_PATH),
|
||||
"nfc_device_save == true assert failed\r\n");
|
||||
// Verify that key cache is saved
|
||||
FuriString* key_cache_name = furi_string_alloc();
|
||||
furi_string_set_str(key_cache_name, "/ext/nfc/cache/");
|
||||
for(size_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(key_cache_name, "%02X", uid[i]);
|
||||
}
|
||||
furi_string_cat_printf(key_cache_name, ".keys");
|
||||
mu_assert(
|
||||
storage_common_stat(nfc_dev->storage, furi_string_get_cstr(key_cache_name), NULL) ==
|
||||
FSE_OK,
|
||||
"Key cache file save failed");
|
||||
nfc_device_free(nfc_dev);
|
||||
|
||||
// Load the NFC device data from the file
|
||||
NfcDevice* nfc_validate = nfc_device_alloc();
|
||||
mu_assert(nfc_validate, "Nfc device alloc assert");
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, false),
|
||||
"nfc_device_load == true assert failed\r\n");
|
||||
|
||||
// Check the UID, sak, ATQA and type
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.nfc_data.uid, uid, uid_len) == 0,
|
||||
"uid compare assert failed\r\n");
|
||||
mu_assert(nfc_validate->dev_data.nfc_data.sak == sak, "sak compare assert failed\r\n");
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.nfc_data.atqa, atqa, 2) == 0,
|
||||
"atqa compare assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
|
||||
"type == FuriHalNfcTypeA assert failed\r\n");
|
||||
|
||||
// Check the manufacturer block
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.mf_classic_data.block[0].value, manufacturer_block, 16) == 0,
|
||||
"manufacturer_block assert failed\r\n");
|
||||
// Check other blocks
|
||||
for(size_t i = 1; i < total_blocks; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
mu_assert(
|
||||
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
|
||||
"Failed sector trailer compare");
|
||||
} else {
|
||||
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
|
||||
}
|
||||
}
|
||||
nfc_device_free(nfc_validate);
|
||||
|
||||
// Check saved key cache
|
||||
NfcDevice* nfc_keys = nfc_device_alloc();
|
||||
mu_assert(nfc_validate, "Nfc device alloc assert");
|
||||
nfc_keys->dev_data.nfc_data.uid_len = uid_len;
|
||||
memcpy(nfc_keys->dev_data.nfc_data.uid, uid, uid_len);
|
||||
mu_assert(nfc_device_load_key_cache(nfc_keys), "Failed to load key cache");
|
||||
uint8_t total_sec = mf_classic_get_total_sectors_num(type);
|
||||
uint8_t default_key[6] = {};
|
||||
memset(default_key, 0xff, 6);
|
||||
for(size_t i = 0; i < total_sec; i++) {
|
||||
MfClassicSectorTrailer* sec_tr =
|
||||
mf_classic_get_sector_trailer_by_sector(&nfc_keys->dev_data.mf_classic_data, i);
|
||||
mu_assert(memcmp(sec_tr->key_a, default_key, 6) == 0, "Failed key compare");
|
||||
mu_assert(memcmp(sec_tr->key_b, default_key, 6) == 0, "Failed key compare");
|
||||
}
|
||||
|
||||
// Delete key cache file
|
||||
mu_assert(
|
||||
storage_common_remove(nfc_keys->storage, furi_string_get_cstr(key_cache_name)) == FSE_OK,
|
||||
"Failed to remove key cache file");
|
||||
furi_string_free(key_cache_name);
|
||||
nfc_device_free(nfc_keys);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_1k_4b_file_test) {
|
||||
mf_classic_generator_test(4, MfClassicType1k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_4k_4b_file_test) {
|
||||
mf_classic_generator_test(4, MfClassicType4k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_1k_7b_file_test) {
|
||||
mf_classic_generator_test(7, MfClassicType1k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_4k_7b_file_test) {
|
||||
mf_classic_generator_test(7, MfClassicType4k);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(nfc) {
|
||||
nfc_test_alloc();
|
||||
|
||||
MU_RUN_TEST(nfca_file_test);
|
||||
MU_RUN_TEST(mf_classic_1k_4b_file_test);
|
||||
MU_RUN_TEST(mf_classic_4k_4b_file_test);
|
||||
MU_RUN_TEST(mf_classic_1k_7b_file_test);
|
||||
MU_RUN_TEST(mf_classic_4k_7b_file_test);
|
||||
MU_RUN_TEST(nfc_digital_signal_test);
|
||||
MU_RUN_TEST(mf_classic_dict_test);
|
||||
MU_RUN_TEST(mf_classic_dict_load_test);
|
||||
|
||||
@@ -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`.
|
||||
@@ -133,7 +133,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
case ArchiveBrowserEventFileMenuRename:
|
||||
if(favorites) {
|
||||
browser->callback(ArchiveBrowserEventEnterFavMove, browser->context);
|
||||
} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
|
||||
} else if(selected->is_app == false) {
|
||||
archive_show_file_menu(browser, false);
|
||||
scene_manager_set_scene_state(
|
||||
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH);
|
||||
|
||||
@@ -57,9 +57,11 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) {
|
||||
ArchiveFile_t* file = archive_get_current_file(archive->browser);
|
||||
|
||||
FuriString* path_dst;
|
||||
|
||||
path_dst = furi_string_alloc();
|
||||
path_extract_dirname(path_src, path_dst);
|
||||
furi_string_cat_printf(path_dst, "/%s%s", archive->text_store, known_ext[file->type]);
|
||||
furi_string_cat_printf(
|
||||
path_dst, "/%s%s", archive->text_store, archive->file_extension);
|
||||
|
||||
storage_common_rename(fs_api, path_src, furi_string_get_cstr(path_dst));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
@@ -65,7 +65,6 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
if(!archive_is_known_app(selected->type)) {
|
||||
furi_string_set(menu[0], "---");
|
||||
furi_string_set(menu[1], "---");
|
||||
furi_string_set(menu[2], "---");
|
||||
} else {
|
||||
if(model->tab_idx == ArchiveTabFavorites) {
|
||||
furi_string_set(menu[2], "Move");
|
||||
|
||||
@@ -11,4 +11,5 @@ App(
|
||||
stack_size=2 * 1024,
|
||||
icon="A_BadUsb_14",
|
||||
order=70,
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "bad_usb_script.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
@@ -82,7 +82,7 @@ static const DuckyKey ducky_keys[] = {
|
||||
{"PAGEUP", HID_KEYBOARD_PAGE_UP},
|
||||
{"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN},
|
||||
{"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN},
|
||||
{"SCROLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SPACE", HID_KEYBOARD_SPACEBAR},
|
||||
{"TAB", HID_KEYBOARD_TAB},
|
||||
{"MENU", HID_KEYBOARD_APPLICATION},
|
||||
@@ -237,12 +237,8 @@ static int32_t
|
||||
const char* line_tmp = furi_string_get_cstr(line);
|
||||
bool state = false;
|
||||
|
||||
for(uint32_t i = 0; i < line_len; i++) {
|
||||
if((line_tmp[i] != ' ') && (line_tmp[i] != '\t') && (line_tmp[i] != '\n')) {
|
||||
line_tmp = &line_tmp[i];
|
||||
break; // Skip spaces and tabs
|
||||
}
|
||||
if(i == line_len - 1) return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
|
||||
if(line_len == 0) {
|
||||
return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
|
||||
}
|
||||
|
||||
FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp);
|
||||
@@ -338,10 +334,6 @@ static int32_t
|
||||
furi_hal_hid_kb_release(key);
|
||||
return (0);
|
||||
}
|
||||
if(error != NULL) {
|
||||
strncpy(error, "Unknown error", error_len);
|
||||
}
|
||||
return SCRIPT_STATE_ERROR;
|
||||
}
|
||||
|
||||
static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
|
||||
@@ -454,10 +446,12 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
||||
bad_usb->st.line_cur++;
|
||||
bad_usb->buf_len = bad_usb->buf_len + bad_usb->buf_start - (i + 1);
|
||||
bad_usb->buf_start = i + 1;
|
||||
furi_string_trim(bad_usb->line);
|
||||
delay_val = ducky_parse_line(
|
||||
bad_usb, bad_usb->line, bad_usb->st.error, sizeof(bad_usb->st.error));
|
||||
|
||||
if(delay_val < 0) {
|
||||
if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line
|
||||
return 0;
|
||||
} else if(delay_val < 0) {
|
||||
bad_usb->st.error_line = bad_usb->st.line_cur;
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur);
|
||||
return SCRIPT_STATE_ERROR;
|
||||
@@ -524,12 +518,16 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect, FuriFlagWaitAny, FuriWaitForever);
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) {
|
||||
worker_state = BadUsbStateIdle; // Ready to run
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
worker_state = BadUsbStateWillRun; // Will run when USB is connected
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
@@ -556,6 +554,31 @@ static int32_t bad_usb_worker(void* context) {
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateWillRun) { // State: start on connection
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) { // Start executing script
|
||||
DOLPHIN_DEED(DolphinDeedBadUsbPlayScript);
|
||||
delay_val = 0;
|
||||
bad_usb->buf_len = 0;
|
||||
bad_usb->st.line_cur = 0;
|
||||
bad_usb->defdelay = 0;
|
||||
bad_usb->repeat_cnt = 0;
|
||||
bad_usb->file_end = false;
|
||||
storage_file_seek(script_file, 0, true);
|
||||
// extra time for PC to recognize Flipper as keyboard
|
||||
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
|
||||
worker_state = BadUsbStateRunning;
|
||||
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
||||
worker_state = BadUsbStateNotConnected;
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateRunning) { // State: running
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
@@ -627,7 +650,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
furi_assert(file_path);
|
||||
|
||||
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
|
||||
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); //-V773
|
||||
bad_usb->file_path = furi_string_alloc();
|
||||
furi_string_set(bad_usb->file_path, file_path);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef enum {
|
||||
BadUsbStateInit,
|
||||
BadUsbStateNotConnected,
|
||||
BadUsbStateIdle,
|
||||
BadUsbStateWillRun,
|
||||
BadUsbStateRunning,
|
||||
BadUsbStateDelay,
|
||||
BadUsbStateDone,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "bad_usb_view.h"
|
||||
#include "../bad_usb_script.h"
|
||||
#include <gui/elements.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define MAX_NAME_LEN 64
|
||||
|
||||
@@ -28,10 +29,13 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_draw_icon(canvas, 22, 20, &I_UsbTree_48x22);
|
||||
|
||||
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone)) {
|
||||
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) ||
|
||||
(model->state.state == BadUsbStateNotConnected)) {
|
||||
elements_button_center(canvas, "Run");
|
||||
} else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
||||
if(model->state.state == BadUsbStateNotConnected) {
|
||||
@@ -39,6 +43,11 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Connect");
|
||||
canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "to USB");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Will run");
|
||||
canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "on connect");
|
||||
} else if(model->state.state == BadUsbStateFileError) {
|
||||
canvas_draw_icon(canvas, 4, 22, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <storage/storage.h>
|
||||
#include <gui/modules/loading.h>
|
||||
@@ -154,7 +155,7 @@ static bool fap_loader_select_app(FapLoader* loader) {
|
||||
}
|
||||
|
||||
static FapLoader* fap_loader_alloc(const char* path) {
|
||||
FapLoader* loader = malloc(sizeof(FapLoader));
|
||||
FapLoader* loader = malloc(sizeof(FapLoader)); //-V773
|
||||
loader->fap_path = furi_string_alloc_set(path);
|
||||
loader->storage = furi_record_open(RECORD_STORAGE);
|
||||
loader->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
@@ -8,4 +8,5 @@ App(
|
||||
stack_size=1 * 1024,
|
||||
icon="A_GPIO_14",
|
||||
order=50,
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <gui/modules/widget.h>
|
||||
#include "views/gpio_test.h"
|
||||
#include "views/gpio_usb_uart.h"
|
||||
#include <assets_icons.h>
|
||||
|
||||
struct GpioApp {
|
||||
Gui* gui;
|
||||
|
||||
@@ -184,7 +184,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
while(1) {
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
size_t len = furi_stream_buffer_receive(
|
||||
@@ -288,7 +288,7 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
while(1) {
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtTxStop) break;
|
||||
if(events & WorkerEvtCdcRx) {
|
||||
furi_check(furi_mutex_acquire(usb_uart->usb_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
@@ -12,6 +12,7 @@ App(
|
||||
icon="A_iButton_14",
|
||||
stack_size=2 * 1024,
|
||||
order=60,
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
App(
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <toolbox/path.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <rpc/rpc_app.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "iButtonApp"
|
||||
|
||||
@@ -337,11 +338,13 @@ int32_t ibutton_app(void* p) {
|
||||
view_dispatcher_attach_to_gui(
|
||||
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop);
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||
} else {
|
||||
view_dispatcher_attach_to_gui(
|
||||
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen);
|
||||
if(key_loaded) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||
} else {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "../ibutton_i.h"
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void ibutton_scene_add_type_byte_input_callback(void* context) {
|
||||
iButton* ibutton = context;
|
||||
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;
|
||||
if(event.event == iButtonCustomEventByteEditResult) {
|
||||
ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonAdd);
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,5 @@ void ibutton_scene_delete_success_on_exit(void* context) {
|
||||
iButton* ibutton = context;
|
||||
Popup* popup = ibutton->popup;
|
||||
|
||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 0, NULL);
|
||||
|
||||
popup_disable_timeout(popup);
|
||||
popup_set_context(popup, NULL);
|
||||
popup_set_callback(popup, NULL);
|
||||
popup_reset(popup);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <core/log.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <toolbox/path.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||
|
||||
// check that stored key has name
|
||||
if(!furi_string_empty(key_name)) {
|
||||
ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
|
||||
|
||||
@@ -11,7 +11,6 @@ void ibutton_scene_read_on_enter(void* context) {
|
||||
Popup* popup = ibutton->popup;
|
||||
iButtonKey* key = ibutton->key;
|
||||
iButtonWorker* worker = ibutton->key_worker;
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
||||
|
||||
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
|
||||
@@ -54,8 +53,8 @@ bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||
if(success) {
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
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);
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <toolbox/path.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static void ibutton_scene_save_name_text_input_callback(void* context) {
|
||||
iButton* ibutton = context;
|
||||
@@ -57,6 +58,15 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == iButtonCustomEventTextEditResult) {
|
||||
if(ibutton_save_key(ibutton, ibutton->text_store)) {
|
||||
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 {
|
||||
const uint32_t possible_scenes[] = {
|
||||
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static void ibutton_scene_save_success_popup_callback(void* 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) {
|
||||
iButton* ibutton = context;
|
||||
Popup* popup = ibutton->popup;
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
||||
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||
@@ -41,10 +39,5 @@ void ibutton_scene_save_success_on_exit(void* context) {
|
||||
iButton* ibutton = context;
|
||||
Popup* popup = ibutton->popup;
|
||||
|
||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 0, NULL);
|
||||
|
||||
popup_disable_timeout(popup);
|
||||
popup_set_context(popup, NULL);
|
||||
popup_set_callback(popup, NULL);
|
||||
popup_reset(popup);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexEmulate,
|
||||
@@ -58,6 +59,7 @@ bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent even
|
||||
consumed = true;
|
||||
if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include "ibutton/scenes/ibutton_scene.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexRead,
|
||||
@@ -38,6 +39,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
if(event.event == SubmenuIndexRead) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
|
||||
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
||||
} else if(event.event == SubmenuIndexSaved) {
|
||||
furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
|
||||
|
||||
@@ -43,10 +43,5 @@ void ibutton_scene_write_success_on_exit(void* context) {
|
||||
iButton* ibutton = context;
|
||||
Popup* popup = ibutton->popup;
|
||||
|
||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 0, NULL);
|
||||
|
||||
popup_disable_timeout(popup);
|
||||
popup_set_context(popup, NULL);
|
||||
popup_set_callback(popup, NULL);
|
||||
popup_reset(popup);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ App(
|
||||
icon="A_Infrared_14",
|
||||
stack_size=3 * 1024,
|
||||
order=40,
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
App(
|
||||
|
||||
@@ -5,25 +5,21 @@
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <flipper_format.h>
|
||||
#include <toolbox/args.h>
|
||||
#include <m-dict.h>
|
||||
|
||||
#include "infrared_signal.h"
|
||||
#include "infrared_brute_force.h"
|
||||
|
||||
#include <m-dict.h>
|
||||
|
||||
#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)
|
||||
|
||||
enum RemoteTypes { TV = 0, AC = 1 };
|
||||
|
||||
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_process_decode(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 {
|
||||
const char* cmd;
|
||||
@@ -87,8 +83,10 @@ static void infrared_cli_print_usage(void) {
|
||||
INFRARED_MIN_FREQUENCY,
|
||||
INFRARED_MAX_FREQUENCY);
|
||||
printf("\tir decode <input_file> [<output_file>]\r\n");
|
||||
printf("\tir universal <tv, ac> <signal name>\r\n");
|
||||
printf("\tir universal list <tv, ac>\r\n");
|
||||
printf("\tir universal <remote_name> <signal_name>\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) {
|
||||
@@ -356,89 +354,31 @@ static void infrared_cli_process_decode(Cli* cli, FuriString* args) {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void infrared_cli_process_universal(Cli* cli, FuriString* args) {
|
||||
enum RemoteTypes Remote;
|
||||
|
||||
FuriString* command;
|
||||
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;
|
||||
static void infrared_cli_list_remote_signals(FuriString* remote_name) {
|
||||
if(furi_string_empty(remote_name)) {
|
||||
printf("Missing remote name.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dict_signals_init(signals_dict);
|
||||
key = furi_string_alloc();
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
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");
|
||||
int max = 1;
|
||||
while(flipper_format_read_string(ff, "name", signal_name)) {
|
||||
furi_string_set_str(key, furi_string_get_cstr(signal_name));
|
||||
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_it_t 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);
|
||||
printf("\t%s\r\n", furi_string_get_cstr(pair->key));
|
||||
}
|
||||
furi_string_free(signal_name);
|
||||
}
|
||||
|
||||
furi_string_free(key);
|
||||
dict_signals_clear(signals_dict);
|
||||
furi_string_free(key);
|
||||
furi_string_free(signal_name);
|
||||
dict_signals_clear(signals_dict);
|
||||
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(ff);
|
||||
furi_string_free(remote_path);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
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();
|
||||
const char* remote_file = NULL;
|
||||
uint32_t i = 0;
|
||||
bool success = false;
|
||||
FuriString* remote_path = furi_string_alloc_printf(
|
||||
"%s/%s.ir", EXT_PATH(INFRARED_ASSETS_FOLDER), furi_string_get_cstr(remote_name));
|
||||
|
||||
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;
|
||||
}
|
||||
infrared_brute_force_set_db_filename(brute_force, furi_string_get_cstr(remote_path));
|
||||
infrared_brute_force_add_record(
|
||||
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, furi_string_get_cstr(signal_name));
|
||||
|
||||
infrared_brute_force_set_db_filename(brute_force, remote_file);
|
||||
infrared_brute_force_add_record(brute_force, i++, furi_string_get_cstr(signal));
|
||||
|
||||
success = infrared_brute_force_calculate_messages(brute_force);
|
||||
if(success) {
|
||||
uint32_t record_count;
|
||||
uint32_t index = 0;
|
||||
int records_sent = 0;
|
||||
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;
|
||||
do {
|
||||
if(furi_string_empty(signal_name)) {
|
||||
printf("Missing signal name.\r\n");
|
||||
break;
|
||||
}
|
||||
if(!infrared_brute_force_calculate_messages(brute_force)) {
|
||||
printf("Invalid remote name.\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
int records_sent = 0;
|
||||
while(running) {
|
||||
running = infrared_brute_force_send_next(brute_force);
|
||||
|
||||
@@ -510,14 +450,35 @@ static void
|
||||
}
|
||||
|
||||
infrared_brute_force_stop(brute_force);
|
||||
} else {
|
||||
printf("Invalid signal.\r\n");
|
||||
}
|
||||
} while(false);
|
||||
|
||||
furi_string_free(remote_path);
|
||||
infrared_brute_force_reset(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) {
|
||||
UNUSED(context);
|
||||
if(furi_hal_infrared_is_busy()) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_stack.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
@@ -16,6 +16,7 @@ ADD_SCENE(infrared, remote_list, RemoteList)
|
||||
ADD_SCENE(infrared, universal, Universal)
|
||||
ADD_SCENE(infrared, universal_tv, UniversalTV)
|
||||
ADD_SCENE(infrared, universal_ac, UniversalAC)
|
||||
ADD_SCENE(infrared, universal_audio, UniversalAudio)
|
||||
ADD_SCENE(infrared, debug, Debug)
|
||||
ADD_SCENE(infrared, error_databases, ErrorDatabases)
|
||||
ADD_SCENE(infrared, rpc, Rpc)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../infrared_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void infrared_scene_learn_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
@@ -27,6 +28,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == InfraredCustomEventTypeSignalReceived) {
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess);
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
#include "../infrared_i.h"
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void infrared_scene_learn_done_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
DOLPHIN_DEED(DolphinDeedIrSave);
|
||||
|
||||
if(infrared->app_state.is_learning_new_remote) {
|
||||
popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../infrared_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void infrared_scene_learn_enter_name_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
@@ -49,6 +50,7 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e
|
||||
|
||||
if(success) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearnDone);
|
||||
DOLPHIN_DEED(DolphinDeedIrSave);
|
||||
} else {
|
||||
dialog_message_show_storage_error(infrared->dialogs, "Failed to save file");
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "../infrared_i.h"
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static void
|
||||
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
|
||||
Infrared* infrared = context;
|
||||
@@ -13,7 +11,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
|
||||
DialogEx* dialog_ex = infrared->dialog_ex;
|
||||
InfraredSignal* signal = infrared->received_signal;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
|
||||
@@ -21,6 +21,12 @@ void infrared_scene_universal_on_enter(void* context) {
|
||||
SubmenuIndexUniversalTV,
|
||||
infrared_scene_universal_submenu_callback,
|
||||
context);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Audio Players",
|
||||
SubmenuIndexUniversalAudio,
|
||||
infrared_scene_universal_submenu_callback,
|
||||
context);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Air Conditioners",
|
||||
@@ -45,7 +51,7 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexUniversalAudio) {
|
||||
//TODO Implement Audio universal remote
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAudio);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ App(
|
||||
icon="A_125khz_14",
|
||||
stack_size=2 * 1024,
|
||||
order=20,
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
App(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
@@ -31,7 +32,7 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
||||
}
|
||||
|
||||
static LfRfid* lfrfid_alloc() {
|
||||
LfRfid* lfrfid = malloc(sizeof(LfRfid));
|
||||
LfRfid* lfrfid = malloc(sizeof(LfRfid)); //-V773
|
||||
|
||||
lfrfid->storage = furi_record_open(RECORD_STORAGE);
|
||||
lfrfid->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
@@ -182,12 +183,14 @@ int32_t lfrfid_app(void* p) {
|
||||
view_dispatcher_attach_to_gui(
|
||||
app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc);
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
} else {
|
||||
furi_string_set(app->file_path, args);
|
||||
lfrfid_load_key_data(app, app->file_path, true);
|
||||
view_dispatcher_attach_to_gui(
|
||||
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -311,4 +314,4 @@ void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context)
|
||||
void lfrfid_text_input_callback(void* context) {
|
||||
LfRfid* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <cli/cli.h>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_emulate_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
|
||||
popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop);
|
||||
if(!furi_string_empty(app->file_name)) {
|
||||
popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexASK,
|
||||
@@ -57,10 +58,12 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
|
||||
if(event.event == SubmenuIndexASK) {
|
||||
app->read_type = LFRFIDWorkerReadTypeASKOnly;
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexPSK) {
|
||||
app->read_type = LFRFIDWorkerReadTypePSKOnly;
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRAW) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
|
||||
|
||||
@@ -46,7 +46,6 @@ static void
|
||||
void lfrfid_scene_read_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
|
||||
} else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
||||
@@ -79,10 +78,10 @@ bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadDone) {
|
||||
app->protocol_id = app->protocol_id_next;
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
furi_string_reset(app->file_name);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadStartPSK) {
|
||||
if(app->read_type == LFRFIDWorkerReadTypeAuto) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexSave,
|
||||
@@ -43,6 +44,7 @@ bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event)
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_save_data_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
@@ -32,7 +31,6 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
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);
|
||||
DOLPHIN_DEED(DolphinDeedRfidAdd);
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_save_name_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
@@ -55,6 +56,13 @@ bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(lfrfid_save_key(app)) {
|
||||
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 {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, LfRfidSceneReadKeyMenu);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_save_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
@@ -8,7 +7,6 @@ void lfrfid_scene_save_success_on_enter(void* context) {
|
||||
// Clear state of data enter scene
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0);
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidSave);
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||
popup_set_context(popup, app);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexEmulate,
|
||||
@@ -42,6 +43,7 @@ bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexRead,
|
||||
@@ -47,6 +48,7 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexRead) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSaved) {
|
||||
furi_string_set(app->file_path, LFRFID_APP_FOLDER);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lfrfid_view_read.h"
|
||||
#include <gui/elements.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define TEMP_STR_LEN 128
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) {
|
||||
mful->version.storage_size = 0x15;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
|
||||
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
|
||||
nfc_generate_common_start(data);
|
||||
nfc_generate_mf_classic_common(data, uid_len, type);
|
||||
|
||||
@@ -337,6 +337,9 @@ static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClas
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 18
|
||||
data->nfc_data.sak = 0x18;
|
||||
|
||||
} else if(type == MfClassicType1k) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
|
||||
@@ -347,6 +350,8 @@ static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClas
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 08
|
||||
data->nfc_data.sak = 0x08;
|
||||
}
|
||||
|
||||
mfc->type = type;
|
||||
|
||||
@@ -11,3 +11,5 @@ struct NfcGenerator {
|
||||
};
|
||||
|
||||
extern const NfcGenerator* const nfc_generators[];
|
||||
|
||||
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "nfc_i.h"
|
||||
#include "furi_hal_nfc.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
bool nfc_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
@@ -115,7 +116,9 @@ void nfc_free(Nfc* nfc) {
|
||||
// Stop worker
|
||||
nfc_worker_stop(nfc->worker);
|
||||
// Save data in shadow file
|
||||
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
||||
if(furi_string_size(nfc->dev->load_path)) {
|
||||
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
|
||||
}
|
||||
}
|
||||
if(nfc->rpc_ctx) {
|
||||
rpc_system_app_send_exited(nfc->rpc_ctx);
|
||||
@@ -217,6 +220,13 @@ void nfc_blink_stop(Nfc* nfc) {
|
||||
notification_message(nfc->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
bool nfc_save_file(Nfc* nfc) {
|
||||
furi_string_printf(
|
||||
nfc->dev->load_path, "%s/%s%s", NFC_APP_FOLDER, nfc->dev->dev_name, NFC_APP_EXTENSION);
|
||||
bool file_saved = nfc_device_save(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
|
||||
return file_saved;
|
||||
}
|
||||
|
||||
void nfc_show_loading_popup(void* context, bool show) {
|
||||
Nfc* nfc = context;
|
||||
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
||||
@@ -275,12 +285,15 @@ int32_t nfc_app(void* p) {
|
||||
if(nfc_device_load(nfc->dev, p, true)) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
}
|
||||
} else {
|
||||
// Exit app
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <cli/cli.h>
|
||||
@@ -113,4 +114,6 @@ void nfc_blink_detect_start(Nfc* nfc);
|
||||
|
||||
void nfc_blink_stop(Nfc* nfc);
|
||||
|
||||
bool nfc_save_file(Nfc* nfc);
|
||||
|
||||
void nfc_show_loading_popup(void* context, bool show);
|
||||
|
||||
@@ -37,6 +37,12 @@ ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
|
||||
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
|
||||
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
|
||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||
ADD_SCENE(nfc, 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_menu, EmvMenu)
|
||||
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
||||
@@ -55,3 +61,4 @@ ADD_SCENE(nfc, detect_reader, DetectReader)
|
||||
ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo)
|
||||
ADD_SCENE(nfc, mfkey_complete, MfkeyComplete)
|
||||
ADD_SCENE(nfc, nfc_data_info, NfcDataInfo)
|
||||
ADD_SCENE(nfc, read_card_type, ReadCardType)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcDetectReader);
|
||||
|
||||
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);
|
||||
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
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
|
||||
// Setup Widget
|
||||
nfc_scene_emulate_uid_widget_config(nfc, false);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_emv_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
@@ -15,7 +14,6 @@ void nfc_scene_emv_read_success_widget_callback(
|
||||
void nfc_scene_emv_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup Custom Widget view
|
||||
widget_add_button_element(
|
||||
|
||||
@@ -29,8 +29,13 @@ bool nfc_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == DialogExResultRight) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == DialogExResultLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneReadCardType)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneReadCardType);
|
||||
} else {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexReadCardType,
|
||||
SubmenuIndexMfClassicKeys,
|
||||
SubmenuIndexMfUltralightUnlock,
|
||||
};
|
||||
@@ -15,6 +16,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read Specific Card Type",
|
||||
SubmenuIndexReadCardType,
|
||||
nfc_scene_extra_actions_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Mifare Classic Keys",
|
||||
@@ -44,9 +51,15 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexMfUltralightUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexReadCardType) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ void nfc_scene_file_select_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
// Process file_select return
|
||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
||||
if(!furi_string_size(nfc->dev->load_path)) {
|
||||
furi_string_set_str(nfc->dev->load_path, NFC_APP_FOLDER);
|
||||
}
|
||||
if(nfc_file_select(nfc->dev)) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "NfcMfClassicDictAttack"
|
||||
|
||||
@@ -110,6 +111,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
} else {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.event == NfcWorkerEventAborted) {
|
||||
@@ -119,6 +121,8 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
} else {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
|
||||
// Counting failed attempts too
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.event == NfcWorkerEventCardDetected) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL)
|
||||
#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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
@@ -50,7 +48,10 @@ bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent even
|
||||
NFC_MF_CLASSIC_DATA_CHANGED) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_NOT_CHANGED);
|
||||
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
||||
// Save shadow file
|
||||
if(furi_string_size(nfc->dev->load_path)) {
|
||||
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
|
||||
}
|
||||
}
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_classic_keys_add_byte_input_callback(void* 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);
|
||||
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcMfcAdd);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
DOLPHIN_DEED(DolphinDeedNfcMfcAdd);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexSave);
|
||||
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(
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexEmulate);
|
||||
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;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_set_scene_state(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_classic_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
@@ -18,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
Widget* widget = nfc->widget;
|
||||
widget_add_button_element(
|
||||
@@ -27,7 +24,7 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc);
|
||||
|
||||
FuriString* temp_str;
|
||||
FuriString* temp_str = NULL;
|
||||
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
|
||||
@@ -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, furi_string_get_cstr(nfc->dev->load_path))) {
|
||||
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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
@@ -48,6 +49,11 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event)
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulateUid) {
|
||||
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;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define NFC_MF_UL_DATA_NOT_CHANGED (0UL)
|
||||
#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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
@@ -50,7 +48,10 @@ bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent e
|
||||
NFC_MF_UL_DATA_CHANGED) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_NOT_CHANGED);
|
||||
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
||||
// Save shadow file
|
||||
if(furi_string_size(nfc->dev->load_path)) {
|
||||
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
|
||||
}
|
||||
}
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexUnlockByReader,
|
||||
@@ -63,6 +64,11 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
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;
|
||||
} else if(event.event == SubmenuIndexUnlockByReader) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockAuto);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||
|
||||
nfc_device_clear(nfc->dev);
|
||||
// Setup view
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_ultralight_read_auth_result_widget_callback(
|
||||
GuiButtonType result,
|
||||
@@ -40,7 +39,6 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) {
|
||||
widget_add_string_element(
|
||||
widget, 0, 17, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));
|
||||
if(mf_ul_data->auth_success) {
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
furi_string_printf(
|
||||
temp_str,
|
||||
"Password: %02X %02X %02X %02X",
|
||||
@@ -57,8 +55,6 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) {
|
||||
config_pages->auth_data.pack.raw[1]);
|
||||
widget_add_string_element(
|
||||
widget, 0, 39, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));
|
||||
} else {
|
||||
DOLPHIN_DEED(DolphinDeedNfcMfulError);
|
||||
}
|
||||
furi_string_printf(
|
||||
temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
||||
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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup widget view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
@@ -33,7 +31,7 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
|
||||
FuriString* temp_str;
|
||||
FuriString* temp_str = NULL;
|
||||
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_mf_ultralight_unlock_warn_dialog_callback(DialogExResult result, void* 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.event == DialogExResultCenter) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuth);
|
||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSaveUid,
|
||||
@@ -41,6 +42,11 @@ bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulateUid) {
|
||||
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;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_nfca_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
@@ -16,8 +15,6 @@ void nfc_scene_nfca_read_success_widget_callback(
|
||||
void nfc_scene_nfca_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
@@ -39,7 +39,6 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
|
||||
|
||||
void nfc_scene_read_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||
|
||||
nfc_device_clear(nfc->dev);
|
||||
// Setup view
|
||||
@@ -62,28 +61,34 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||
(event.event == NfcWorkerEventReadUidNfcV)) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadUidNfcA) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfUltralight) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
// Set unlock password input to 0xFFFFFFFF only on fresh read
|
||||
memset(nfc->byte_input_store, 0xFF, 4);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfClassicDone) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfDesfire) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadBankCard) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) {
|
||||
if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_read_card_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
@@ -18,7 +17,6 @@ void nfc_scene_read_card_success_on_enter(void* context) {
|
||||
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "nfc_worker_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexReadMifareClassic,
|
||||
SubmenuIndexReadMifareDesfire,
|
||||
SubmenuIndexReadMfUltralight,
|
||||
SubmenuIndexReadEMV,
|
||||
SubmenuIndexReadNFCA,
|
||||
};
|
||||
|
||||
void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_read_card_type_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read Mifare Classic",
|
||||
SubmenuIndexReadMifareClassic,
|
||||
nfc_scene_read_card_type_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read Mifare DESFire",
|
||||
SubmenuIndexReadMifareDesfire,
|
||||
nfc_scene_read_card_type_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read NTAG/Ultralight",
|
||||
SubmenuIndexReadMfUltralight,
|
||||
nfc_scene_read_card_type_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read EMV card",
|
||||
SubmenuIndexReadEMV,
|
||||
nfc_scene_read_card_type_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read NFC-A data",
|
||||
SubmenuIndexReadNFCA,
|
||||
nfc_scene_read_card_type_submenu_callback,
|
||||
nfc);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
|
||||
submenu_set_selected_item(submenu, state);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexReadMifareClassic) {
|
||||
nfc->dev->dev_data.read_mode = NfcReadModeMfClassic;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||
consumed = true;
|
||||
}
|
||||
if(event.event == SubmenuIndexReadMifareDesfire) {
|
||||
nfc->dev->dev_data.read_mode = NfcReadModeMfDesfire;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||
consumed = true;
|
||||
}
|
||||
if(event.event == SubmenuIndexReadMfUltralight) {
|
||||
nfc->dev->dev_data.read_mode = NfcReadModeMfUltralight;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||
consumed = true;
|
||||
}
|
||||
if(event.event == SubmenuIndexReadEMV) {
|
||||
nfc->dev->dev_data.read_mode = NfcReadModeEMV;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||
consumed = true;
|
||||
}
|
||||
if(event.event == SubmenuIndexReadNFCA) {
|
||||
nfc->dev->dev_data.read_mode = NfcReadModeNFCA;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_read_card_type_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <toolbox/path.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_save_name_text_input_callback(void* context) {
|
||||
Nfc* nfc = context;
|
||||
@@ -61,8 +62,15 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||
}
|
||||
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
||||
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
||||
if(nfc_save_file(nfc)) {
|
||||
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;
|
||||
} else {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_save_success_popup_callback(void* 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) {
|
||||
Nfc* nfc = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcSave);
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexEditUid,
|
||||
SubmenuIndexDetectReader,
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexUpdate,
|
||||
SubmenuIndexRename,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
@@ -43,6 +47,28 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
submenu_add_item(
|
||||
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, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl &&
|
||||
@@ -93,6 +119,16 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
} else {
|
||||
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;
|
||||
} else if(event.event == SubmenuIndexRename) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_set_uid_byte_input_callback(void* context) {
|
||||
Nfc* nfc = context;
|
||||
@@ -30,10 +29,9 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventByteInputDone) {
|
||||
DOLPHIN_DEED(DolphinDeedNfcAddSave);
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {
|
||||
if(nfc_save_file(nfc)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
@@ -43,6 +41,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user