NFC Unit tests part 1.1 (#1927)
* Mifare Classic 1/4K, 4/7b uid, NFC-A: NFC-A is not complete yet, as there are no 4b uid tests. Also, Mifare Classic tests don't cover the key cache yet. * NFC unit tests require access to the NFC app * Made nfc_device_save accept full path as an argument * Move from cstrs to furi strings and fix logic * nfc tests: fix memory leak * nfc: add mf_classic_get_total_blocks() to API * nfc tests: simplify nfc tests * nfc: fix memory leak in shadow file saving * nfc: fix set uid scene * nfc: fix saving files * nfc: fix preload nfc file path * nfc: remove comments Co-authored-by: Sergey Gavrilov <who.just.the.doctor@gmail.com> Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
a66e8d9ac9
commit
820afd2aec
@ -5,6 +5,8 @@
|
|||||||
#include <lib/nfc/protocols/nfca.h>
|
#include <lib/nfc/protocols/nfca.h>
|
||||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||||
#include <lib/digital_signal/digital_signal.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/flipper_format/flipper_format_i.h>
|
||||||
#include <lib/toolbox/stream/file_stream.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_SHORT_FILE "nfc_nfca_signal_short.nfc"
|
||||||
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.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_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 char* nfc_test_file_type = "Flipper NFC test";
|
||||||
static const uint32_t nfc_test_file_version = 1;
|
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);
|
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) {
|
MU_TEST_SUITE(nfc) {
|
||||||
nfc_test_alloc();
|
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(nfc_digital_signal_test);
|
||||||
MU_RUN_TEST(mf_classic_dict_test);
|
MU_RUN_TEST(mf_classic_dict_test);
|
||||||
MU_RUN_TEST(mf_classic_dict_load_test);
|
MU_RUN_TEST(mf_classic_dict_load_test);
|
||||||
|
@ -314,7 +314,7 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) {
|
|||||||
mful->version.storage_size = 0x15;
|
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_common_start(data);
|
||||||
nfc_generate_mf_classic_common(data, uid_len, type);
|
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]);
|
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||||
}
|
}
|
||||||
|
// Set SAK to 18
|
||||||
|
data->nfc_data.sak = 0x18;
|
||||||
|
|
||||||
} else if(type == MfClassicType1k) {
|
} else if(type == MfClassicType1k) {
|
||||||
// Set every block to 0xFF
|
// Set every block to 0xFF
|
||||||
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
|
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]);
|
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||||
}
|
}
|
||||||
|
// Set SAK to 08
|
||||||
|
data->nfc_data.sak = 0x08;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfc->type = type;
|
mfc->type = type;
|
||||||
|
@ -11,3 +11,5 @@ struct NfcGenerator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const NfcGenerator* const nfc_generators[];
|
extern const NfcGenerator* const nfc_generators[];
|
||||||
|
|
||||||
|
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type);
|
||||||
|
@ -116,7 +116,9 @@ void nfc_free(Nfc* nfc) {
|
|||||||
// Stop worker
|
// Stop worker
|
||||||
nfc_worker_stop(nfc->worker);
|
nfc_worker_stop(nfc->worker);
|
||||||
// Save data in shadow file
|
// 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) {
|
if(nfc->rpc_ctx) {
|
||||||
rpc_system_app_send_exited(nfc->rpc_ctx);
|
rpc_system_app_send_exited(nfc->rpc_ctx);
|
||||||
@ -218,6 +220,13 @@ void nfc_blink_stop(Nfc* nfc) {
|
|||||||
notification_message(nfc->notifications, &sequence_blink_stop);
|
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) {
|
void nfc_show_loading_popup(void* context, bool show) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
||||||
|
@ -114,4 +114,6 @@ void nfc_blink_detect_start(Nfc* nfc);
|
|||||||
|
|
||||||
void nfc_blink_stop(Nfc* nfc);
|
void nfc_blink_stop(Nfc* nfc);
|
||||||
|
|
||||||
|
bool nfc_save_file(Nfc* nfc);
|
||||||
|
|
||||||
void nfc_show_loading_popup(void* context, bool show);
|
void nfc_show_loading_popup(void* context, bool show);
|
||||||
|
@ -5,6 +5,9 @@ void nfc_scene_file_select_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
// Process file_select return
|
// Process file_select return
|
||||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
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)) {
|
if(nfc_file_select(nfc->dev)) {
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||||
|
@ -48,7 +48,10 @@ bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent even
|
|||||||
NFC_MF_CLASSIC_DATA_CHANGED) {
|
NFC_MF_CLASSIC_DATA_CHANGED) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_NOT_CHANGED);
|
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;
|
consumed = false;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ bool nfc_scene_mf_classic_update_on_event(void* context, SceneManagerEvent event
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcWorkerEventSuccess) {
|
if(event.event == NfcWorkerEventSuccess) {
|
||||||
nfc_worker_stop(nfc->worker);
|
nfc_worker_stop(nfc->worker);
|
||||||
if(nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name)) {
|
if(nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path))) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicUpdateSuccess);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicUpdateSuccess);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
|
||||||
|
@ -48,7 +48,10 @@ bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent e
|
|||||||
NFC_MF_UL_DATA_CHANGED) {
|
NFC_MF_UL_DATA_CHANGED) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_NOT_CHANGED);
|
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;
|
consumed = false;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
|||||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||||
}
|
}
|
||||||
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
||||||
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
if(nfc_save_file(nfc)) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||||
if(!scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
if(!scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||||
// Nothing, do not count editing as saving
|
// Nothing, do not count editing as saving
|
||||||
|
@ -31,7 +31,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == NfcCustomEventByteInputDone) {
|
if(event.event == NfcCustomEventByteInputDone) {
|
||||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||||
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {
|
if(nfc_save_file(nfc)) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
@ -41,6 +41,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ FIRMWARE_APPS = {
|
|||||||
"basic_services",
|
"basic_services",
|
||||||
"updater_app",
|
"updater_app",
|
||||||
"unit_tests",
|
"unit_tests",
|
||||||
|
"nfc",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,7.3,,
|
Version,+,7.4,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@ -1844,6 +1844,7 @@ Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*,
|
|||||||
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
|
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
|
||||||
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
|
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
|
||||||
Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
|
Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
|
||||||
|
Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType
|
||||||
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
|
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
|
||||||
Function,-,mf_classic_get_type_str,const char*,MfClassicType
|
Function,-,mf_classic_get_type_str,const char*,MfClassicType
|
||||||
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
|
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
|
||||||
|
|
@ -1006,12 +1006,7 @@ static void nfc_device_get_shadow_path(FuriString* orig_path, FuriString* shadow
|
|||||||
furi_string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION);
|
furi_string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfc_device_save_file(
|
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||||
NfcDevice* dev,
|
|
||||||
const char* dev_name,
|
|
||||||
const char* folder,
|
|
||||||
const char* extension,
|
|
||||||
bool use_load_path) {
|
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
|
|
||||||
bool saved = false;
|
bool saved = false;
|
||||||
@ -1021,19 +1016,10 @@ static bool nfc_device_save_file(
|
|||||||
temp_str = furi_string_alloc();
|
temp_str = furi_string_alloc();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(use_load_path && !furi_string_empty(dev->load_path)) {
|
|
||||||
// Get directory name
|
|
||||||
path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str);
|
|
||||||
// Create nfc directory if necessary
|
|
||||||
if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(temp_str))) break;
|
|
||||||
// Make path to file to save
|
|
||||||
furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension);
|
|
||||||
} else {
|
|
||||||
// Create nfc directory if necessary
|
// Create nfc directory if necessary
|
||||||
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
|
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
|
||||||
// First remove nfc device file if it was saved
|
// First remove nfc device file if it was saved
|
||||||
furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
furi_string_printf(temp_str, "%s", dev_name);
|
||||||
}
|
|
||||||
// Open file
|
// Open file
|
||||||
if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
|
if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
|
||||||
// Write header
|
// Write header
|
||||||
@ -1072,13 +1058,19 @@ static bool nfc_device_save_file(
|
|||||||
return saved;
|
return saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
bool nfc_device_save_shadow(NfcDevice* dev, const char* path) {
|
||||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
|
|
||||||
dev->shadow_file_exist = true;
|
dev->shadow_file_exist = true;
|
||||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true);
|
// Replace extension from .nfc to .shd if necessary
|
||||||
|
FuriString* orig_path = furi_string_alloc();
|
||||||
|
furi_string_set_str(orig_path, path);
|
||||||
|
FuriString* shadow_path = furi_string_alloc();
|
||||||
|
nfc_device_get_shadow_path(orig_path, shadow_path);
|
||||||
|
|
||||||
|
bool file_saved = nfc_device_save(dev, furi_string_get_cstr(shadow_path));
|
||||||
|
furi_string_free(orig_path);
|
||||||
|
furi_string_free(shadow_path);
|
||||||
|
|
||||||
|
return file_saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dialog) {
|
static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dialog) {
|
||||||
@ -1195,7 +1187,7 @@ bool nfc_file_select(NfcDevice* dev) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool res =
|
bool res =
|
||||||
dialog_file_browser_show(dev->dialogs, dev->load_path, nfc_app_folder, &browser_options);
|
dialog_file_browser_show(dev->dialogs, dev->load_path, dev->load_path, &browser_options);
|
||||||
|
|
||||||
furi_string_free(nfc_app_folder);
|
furi_string_free(nfc_app_folder);
|
||||||
if(res) {
|
if(res) {
|
||||||
|
@ -82,7 +82,7 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t mf_classic_get_total_block_num(MfClassicType type) {
|
uint16_t mf_classic_get_total_block_num(MfClassicType type) {
|
||||||
if(type == MfClassicType1k) {
|
if(type == MfClassicType1k) {
|
||||||
return 64;
|
return 64;
|
||||||
} else if(type == MfClassicType4k) {
|
} else if(type == MfClassicType4k) {
|
||||||
|
@ -98,6 +98,8 @@ MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t S
|
|||||||
|
|
||||||
uint8_t mf_classic_get_total_sectors_num(MfClassicType type);
|
uint8_t mf_classic_get_total_sectors_num(MfClassicType type);
|
||||||
|
|
||||||
|
uint16_t mf_classic_get_total_block_num(MfClassicType type);
|
||||||
|
|
||||||
uint8_t mf_classic_get_sector_trailer_block_num_by_sector(uint8_t sector);
|
uint8_t mf_classic_get_sector_trailer_block_num_by_sector(uint8_t sector);
|
||||||
|
|
||||||
bool mf_classic_is_sector_trailer(uint8_t block);
|
bool mf_classic_is_sector_trailer(uint8_t block);
|
||||||
|
Loading…
Reference in New Issue
Block a user