[FL-1526] Mifare Ultralight emulation (#645)
* rfal: add discovery parameter for passing listen activation * nfc: add discovery parameter to furi_hal_nfc_listen * mifare_ul: add emulation parsing commands * nfc: add mifare ul emulation * nfc: switch to mifare ultralight emulation form menu * furi-hal-nfc: add first frame reception in emulation mode * nfc: change argument check * nfc: rework nfc worker and mifare ul lib * mifare_ul: add write and cnt increment commands * nfc: add card modification check * mifare_ul: add data changed flag * nfc: add shodow files * nfc: add restore original file Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
static const char* nfc_app_folder = "/any/nfc";
|
||||
static const char* nfc_app_extension = ".nfc";
|
||||
static const char* nfc_app_shadow_extension = ".shd";
|
||||
|
||||
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) {
|
||||
string_strim(str);
|
||||
@@ -259,7 +260,11 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) {
|
||||
strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN);
|
||||
}
|
||||
|
||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
static bool nfc_device_save_file(
|
||||
NfcDevice* dev,
|
||||
const char* dev_name,
|
||||
const char* folder,
|
||||
const char* extension) {
|
||||
furi_assert(dev);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
@@ -275,7 +280,7 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
break;
|
||||
};
|
||||
// First remove nfc device file if it was saved
|
||||
string_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev_name, nfc_app_extension);
|
||||
string_printf(dev_file_name, "%s/%s%s", folder, dev_name, extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
|
||||
break;
|
||||
};
|
||||
@@ -316,16 +321,42 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_extension);
|
||||
}
|
||||
|
||||
bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
|
||||
dev->shadow_file_exist = true;
|
||||
return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_shadow_extension);
|
||||
}
|
||||
|
||||
static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevice* dev) {
|
||||
string_t temp_string;
|
||||
string_init(temp_string);
|
||||
bool parsed = false;
|
||||
|
||||
do {
|
||||
// Open key file
|
||||
if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
// Check existance of shadow file
|
||||
size_t ext_start = string_search_str(path, nfc_app_extension);
|
||||
string_set_n(temp_string, path, 0, ext_start);
|
||||
string_cat_printf(temp_string, "%s", nfc_app_shadow_extension);
|
||||
if(!file_worker_is_file_exist(
|
||||
file_worker, string_get_cstr(temp_string), &dev->shadow_file_exist)) {
|
||||
break;
|
||||
}
|
||||
// Open shadow file if it exists. If not - open original
|
||||
if(dev->shadow_file_exist) {
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(temp_string), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Read and parse format from 1st line
|
||||
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
|
||||
break;
|
||||
@@ -427,13 +458,61 @@ void nfc_device_clear(NfcDevice* dev) {
|
||||
bool nfc_device_delete(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
|
||||
bool result = false;
|
||||
bool result = true;
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t file_path;
|
||||
string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||
result = file_worker_remove(file_worker, string_get_cstr(file_path));
|
||||
|
||||
do {
|
||||
// Delete original file
|
||||
string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(file_path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
// Delete shadow file if it exists
|
||||
if(dev->shadow_file_exist) {
|
||||
string_clean(file_path);
|
||||
string_printf(
|
||||
file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(file_path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(0);
|
||||
|
||||
string_clear(file_path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nfc_device_restore(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
furi_assert(dev->shadow_file_exist);
|
||||
|
||||
bool result = true;
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t path;
|
||||
|
||||
do {
|
||||
string_init_printf(
|
||||
path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
dev->shadow_file_exist = false;
|
||||
string_clean(path);
|
||||
string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||
if(!nfc_device_load_data(file_worker, path, dev)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
|
||||
string_clear(path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user