[FL-1919] NFC rework with Flipper File Format (#756)

* nfc: allocate nfc device on heap
* nfc: rework save with flipper file format
* nfc: rework nfc device load with flipper file
* nfc: save AID length and data
* nfc: remove file worker usage
* nfc: format sources
* nfc: rework with flipper file format addons
* assets: update EMV resources with flipper file format
* nfc: rework EMV resources parsing with new file format
* assets: fix EMV AID file format
* nfc: fix nfc_device usage

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich
2021-11-09 00:55:06 +03:00
committed by GitHub
parent 54dc16134d
commit 90d450368c
36 changed files with 1008 additions and 1070 deletions

View File

@@ -1,49 +1,80 @@
#include "nfc_emv_parser.h"
#include <lib/flipper_file/flipper_file.h>
#include <file-worker.h>
static const char* nfc_resources_header = "Flipper EMV resources";
static const uint32_t nfc_resources_file_version = 1;
static bool
nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) {
bool found = false;
FileWorker* file_worker = file_worker_alloc(true);
static bool nfc_emv_parser_search_data(
Storage* storage,
const char* file_name,
string_t key,
string_t data) {
bool parsed = false;
FlipperFile* file = flipper_file_alloc(storage);
string_t temp_str;
string_init(temp_str);
if(file_worker_open(file_worker, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) {
found = true;
}
}
do {
// Open file
if(!flipper_file_open_existing(file, file_name)) break;
// Read file header and version
uint32_t version = 0;
if(!flipper_file_read_header(file, temp_str, &version)) break;
if(string_cmp_str(temp_str, nfc_resources_header) ||
(version != nfc_resources_file_version))
break;
if(!flipper_file_read_string(file, string_get_cstr(key), data)) break;
parsed = true;
} while(false);
file_worker_close(file_worker);
file_worker_free(file_worker);
return found;
string_clear(temp_str);
flipper_file_free(file);
return parsed;
}
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name) {
bool result = false;
bool nfc_emv_parser_get_aid_name(
Storage* storage,
uint8_t* aid,
uint8_t aid_len,
string_t aid_name) {
furi_assert(storage);
bool parsed = false;
string_t key;
string_init(key);
for(uint8_t i = 0; i < aid_len; i++) {
string_cat_printf(key, "%02X", aid[i]);
}
result = nfc_emv_parser_get_value("/ext/nfc/emv/aid.nfc", key, ' ', aid_name);
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/aid.nfc", key, aid_name)) {
parsed = true;
}
string_clear(key);
return result;
return parsed;
}
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) {
bool result = false;
bool nfc_emv_parser_get_country_name(
Storage* storage,
uint16_t country_code,
string_t country_name) {
bool parsed = false;
string_t key;
string_init_printf(key, "%04X", country_code);
result = nfc_emv_parser_get_value("/ext/nfc/emv/country_code.nfc", key, ' ', country_name);
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/country_code.nfc", key, country_name)) {
parsed = true;
}
string_clear(key);
return result;
return parsed;
}
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) {
bool result = false;
bool nfc_emv_parser_get_currency_name(
Storage* storage,
uint16_t currency_code,
string_t currency_name) {
bool parsed = false;
string_t key;
string_init_printf(key, "%04X", currency_code);
result = nfc_emv_parser_get_value("/ext/nfc/emv/currency_code.nfc", key, ' ', currency_name);
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/currency_code.nfc", key, currency_name)) {
parsed = true;
}
string_clear(key);
return result;
return parsed;
}

View File

@@ -3,25 +3,39 @@
#include <stdint.h>
#include <stdbool.h>
#include <m-string.h>
#include <storage/storage.h>
/** Get EMV application name by number
* @param storage Storage instance
* @param aid - AID number array
* @param aid_len - AID length
* @param aid_name - string to keep AID name
* @return - true if AID found, false otherwies
*/
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name);
bool nfc_emv_parser_get_aid_name(
Storage* storage,
uint8_t* aid,
uint8_t aid_len,
string_t aid_name);
/** Get country name by country code
* @param storage Storage instance
* @param country_code - ISO 3166 country code
* @param country_name - string to keep country name
* @return - true if country found, false otherwies
*/
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name);
bool nfc_emv_parser_get_country_name(
Storage* storage,
uint16_t country_code,
string_t country_name);
/** Get currency name by currency code
* @param storage Storage instance
* @param currency_code - ISO 3166 currency code
* @param currency_name - string to keep currency name
* @return - true if currency found, false otherwies
*/
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name);
bool nfc_emv_parser_get_currency_name(
Storage* storage,
uint16_t currency_code,
string_t currency_name);

View File

@@ -31,6 +31,9 @@ Nfc* nfc_alloc() {
view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback);
view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100);
// Nfc device
nfc->dev = nfc_device_alloc();
// Open GUI record
nfc->gui = furi_record_open("gui");
view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
@@ -82,6 +85,9 @@ Nfc* nfc_alloc() {
void nfc_free(Nfc* nfc) {
furi_assert(nfc);
// Nfc device
nfc_device_free(nfc->dev);
// Submenu
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
submenu_free(nfc->submenu);
@@ -154,8 +160,8 @@ int32_t nfc_app(void* p) {
char* args = p;
// Check argument and run corresponding scene
if((*args != '\0') && nfc_device_load(&nfc->dev, p)) {
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
if((*args != '\0') && nfc_device_load(nfc->dev, p)) {
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);

View File

@@ -1,45 +1,38 @@
#include "nfc_device_i.h"
#include "nfc_device.h"
#include <file-worker.h>
#include <lib/toolbox/path.h>
#include <lib/toolbox/hex.h>
#define NFC_DEVICE_MAX_DATA_LEN 14
#include <lib/flipper_file/flipper_file.h>
static const char* nfc_app_folder = "/any/nfc";
static const char* nfc_app_extension = ".nfc";
static const char* nfc_app_shadow_extension = ".shd";
static const char* nfc_file_header = "Flipper NFC device";
static const uint32_t nfc_file_version = 2;
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len, uint8_t delim_len) {
string_strim(str);
uint8_t nibble_high = 0;
uint8_t nibble_low = 0;
bool parsed = true;
for(uint16_t i = 0; i < len; i++) {
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
buff[i] = (nibble_high << 4) | nibble_low;
string_right(str, delim_len + 2);
} else {
parsed = false;
break;
}
}
return parsed;
NfcDevice* nfc_device_alloc() {
NfcDevice* nfc_dev = furi_alloc(sizeof(NfcDevice));
nfc_dev->storage = furi_record_open("storage");
nfc_dev->dialogs = furi_record_open("dialogs");
return nfc_dev;
}
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
void nfc_device_free(NfcDevice* nfc_dev) {
furi_assert(nfc_dev);
furi_record_close("storage");
furi_record_close("dialogs");
free(nfc_dev);
}
void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
if(dev->format == NfcDeviceSaveFormatUid) {
string_set_str(format_string, "UID\n");
string_set_str(format_string, "UID");
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
string_set_str(format_string, "Bank card\n");
string_set_str(format_string, "Bank card");
} else if(dev->format == NfcDeviceSaveFormatMifareUl) {
string_set_str(format_string, "Mifare Ultralight\n");
string_set_str(format_string, "Mifare Ultralight");
} else {
string_set_str(format_string, "Unknown\n");
string_set_str(format_string, "Unknown");
}
return string_size(format_string);
}
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
@@ -59,228 +52,166 @@ bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
return false;
}
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) {
NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data;
string_printf(uid_string, "UID len: %02X UID: ", dev->dev_data.nfc_data.uid_len);
for(uint8_t i = 0; i < uid_data->uid_len; i++) {
string_cat_printf(uid_string, "%02X ", uid_data->uid[i]);
}
string_cat_printf(
uid_string,
"ATQA: %02X %02X SAK: %02X\n",
uid_data->atqa[0],
uid_data->atqa[1],
uid_data->sak);
return string_size(uid_string);
}
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) {
NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data;
bool parsed = false;
do {
// strlen("UID len: ") = 9
string_right(uid_string, 9);
if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1, 1)) {
break;
}
// strlen("UID: ") = 5
string_right(uid_string, 5);
if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len, 1)) {
break;
}
// strlen("ATQA: ") = 6
string_right(uid_string, 6);
if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2, 1)) {
break;
}
// strlen("SAK: ") = 5
string_right(uid_string, 5);
if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1, 1)) {
break;
}
parsed = true;
} while(0);
return parsed;
}
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
static bool nfc_device_save_mifare_ul_data(FlipperFile* file, NfcDevice* dev) {
bool saved = false;
MifareUlData* data = &dev->dev_data.mf_ul_data;
string_printf(mifare_ul_string, "Signature:");
for(uint8_t i = 0; i < sizeof(data->signature); i++) {
string_cat_printf(mifare_ul_string, " %02X", data->signature[i]);
}
string_cat_printf(mifare_ul_string, "\nVersion:");
uint8_t* version = (uint8_t*)&data->version;
for(uint8_t i = 0; i < sizeof(data->version); i++) {
string_cat_printf(mifare_ul_string, " %02X", version[i]);
}
for(uint8_t i = 0; i < 3; i++) {
string_cat_printf(
mifare_ul_string,
"\nCounter %d: %lu Tearing flag %d: %02X",
i,
data->counter[i],
i,
data->tearing[i]);
}
string_cat_printf(mifare_ul_string, "\nData size: %d\n", data->data_size);
for(uint16_t i = 0; i < data->data_size; i += 4) {
string_cat_printf(
mifare_ul_string,
"%02X %02X %02X %02X\n",
data->data[i],
data->data[i + 1],
data->data[i + 2],
data->data[i + 3]);
}
return string_size(mifare_ul_string);
}
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
MifareUlData* data = &dev->dev_data.mf_ul_data;
uint16_t tearing_tmp = 0;
uint16_t cnt_num = 0;
size_t ws = 0;
int res = 0;
bool parsed = false;
string_t temp_str;
string_init(temp_str);
// Save Mifare Ultralight specific data
do {
// strlen("Signature: ") = 11
string_right(mifare_ul_string, 11);
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) {
if(!flipper_file_write_comment_cstr(file, "Mifare Ultralight specific data")) break;
if(!flipper_file_write_hex(file, "Signature", data->signature, sizeof(data->signature)))
break;
}
// strlen("Version: ") = 9
string_right(mifare_ul_string, 9);
if(!nfc_device_read_hex(
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) {
if(!flipper_file_write_hex(
file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version)))
break;
}
string_strim(mifare_ul_string);
// Read counters and tearing flags
// Write conters and tearing flags data
bool counters_saved = true;
for(uint8_t i = 0; i < 3; i++) {
res = sscanf(
string_get_cstr(mifare_ul_string),
"Counter %hX: %lu Tearing flag %hX: %02hX",
&cnt_num,
&data->counter[i],
&cnt_num,
&tearing_tmp);
if(res != 4) {
string_printf(temp_str, "Counter %d", i);
if(!flipper_file_write_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) {
counters_saved = false;
break;
}
string_printf(temp_str, "Tearing %d", i);
if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) {
counters_saved = false;
break;
}
data->tearing[i] = tearing_tmp;
ws = string_search_char(mifare_ul_string, '\n');
string_right(mifare_ul_string, ws + 1);
}
// Read data size
res = sscanf(string_get_cstr(mifare_ul_string), "Data size: %hu", &data->data_size);
if(res != 1) {
break;
}
ws = string_search_char(mifare_ul_string, '\n');
string_right(mifare_ul_string, ws + 1);
// Read data
if(!counters_saved) break;
// Write pages data
uint32_t pages_total = data->data_size / 4;
if(!flipper_file_write_uint32(file, "Pages total", &pages_total, 1)) break;
bool pages_saved = true;
for(uint16_t i = 0; i < data->data_size; i += 4) {
if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4, 1)) {
string_printf(temp_str, "Page %d", i / 4);
if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->data[i], 4)) {
pages_saved = false;
break;
}
}
parsed = true;
} while(0);
if(!pages_saved) break;
saved = true;
} while(false);
string_clear(temp_str);
return saved;
}
bool nfc_device_load_mifare_ul_data(FlipperFile* file, NfcDevice* dev) {
bool parsed = false;
MifareUlData* data = &dev->dev_data.mf_ul_data;
string_t temp_str;
string_init(temp_str);
do {
// Read signature
if(!flipper_file_read_hex(file, "Signature", data->signature, sizeof(data->signature)))
break;
// Read Mifare version
if(!flipper_file_read_hex(
file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version)))
break;
// Read counters and tearing flags
bool counters_parsed = true;
for(uint8_t i = 0; i < 3; i++) {
string_printf(temp_str, "Counter %d", i);
if(!flipper_file_read_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) {
counters_parsed = false;
break;
}
string_printf(temp_str, "Tearing %d", i);
if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) {
counters_parsed = false;
break;
}
}
if(!counters_parsed) break;
// Read pages
uint32_t pages = 0;
if(!flipper_file_read_uint32(file, "Pages total", &pages, 1)) break;
data->data_size = pages * 4;
bool pages_parsed = true;
for(uint16_t i = 0; i < pages; i++) {
string_printf(temp_str, "Page %d", i);
if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) {
pages_parsed = false;
break;
}
}
if(!pages_parsed) break;
parsed = true;
} while(false);
string_clear(temp_str);
return parsed;
}
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
static bool nfc_device_save_bank_card_data(FlipperFile* file, NfcDevice* dev) {
bool saved = false;
NfcEmvData* data = &dev->dev_data.emv_data;
string_printf(bank_card_string, "AID len: %d, AID:", data->aid_len);
for(uint8_t i = 0; i < data->aid_len; i++) {
string_cat_printf(bank_card_string, " %02X", data->aid[i]);
}
string_cat_printf(
bank_card_string, "\nName: %s\nNumber len: %d\nNumber:", data->name, data->number_len);
for(uint8_t i = 0; i < data->number_len; i++) {
string_cat_printf(bank_card_string, " %02X", data->number[i]);
}
if(data->exp_mon) {
string_cat_printf(
bank_card_string, "\nExp date: %02X/%02X", data->exp_mon, data->exp_year);
}
if(data->country_code) {
string_cat_printf(bank_card_string, "\nCountry code: %04X", data->country_code);
}
if(data->currency_code) {
string_cat_printf(bank_card_string, "\nCurrency code: %04X", data->currency_code);
}
return string_size(bank_card_string);
}
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
NfcEmvData* data = &dev->dev_data.emv_data;
bool parsed = false;
int res = 0;
uint8_t code[2] = {};
memset(data, 0, sizeof(NfcEmvData));
uint32_t data_temp = 0;
do {
res = sscanf(string_get_cstr(bank_card_string), "AID len: %hu", &data->aid_len);
if(res != 1) {
break;
// Write Bank card specific data
if(!flipper_file_write_comment_cstr(file, "Bank card specific data")) break;
if(!flipper_file_write_hex(file, "AID", data->aid, data->aid_len)) break;
if(!flipper_file_write_string_cstr(file, "Name", data->name)) break;
if(!flipper_file_write_hex(file, "Number", data->number, data->number_len)) break;
if(data->exp_mon) {
uint8_t exp_data[2] = {data->exp_mon, data->exp_year};
if(!flipper_file_write_hex(file, "Exp data", exp_data, sizeof(exp_data))) break;
}
// strlen("AID len: ") = 9
string_right(bank_card_string, 9);
size_t ws = string_search_char(bank_card_string, ':');
string_right(bank_card_string, ws + 1);
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) {
break;
if(data->country_code) {
data_temp = data->country_code;
if(!flipper_file_write_uint32(file, "Country code", &data_temp, 1)) break;
}
res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name);
if(res != 1) {
break;
if(data->currency_code) {
data_temp = data->currency_code;
if(!flipper_file_write_uint32(file, "Currency code", &data_temp, 1)) break;
}
ws = string_search_char(bank_card_string, '\n');
string_right(bank_card_string, ws + 1);
res = sscanf(string_get_cstr(bank_card_string), "Number len: %hhu", &data->number_len);
if(res != 1) {
break;
}
ws = string_search_char(bank_card_string, '\n');
string_right(bank_card_string, ws + 1);
// strlen("Number: ") = 8
string_right(bank_card_string, 8);
if(!nfc_device_read_hex(bank_card_string, data->number, data->number_len, 1)) {
break;
}
parsed = true;
// Check expiration date presence
ws = string_search_str(bank_card_string, "Exp date: ");
if(ws != STRING_FAILURE) {
// strlen("Exp date: ") = 10
string_right(bank_card_string, 10);
nfc_device_read_hex(bank_card_string, &data->exp_mon, 1, 1);
nfc_device_read_hex(bank_card_string, &data->exp_year, 1, 1);
}
// Check country code presence
ws = string_search_str(bank_card_string, "Country code: ");
if(ws != STRING_FAILURE) {
// strlen("Country code: ") = 14
string_right(bank_card_string, 14);
nfc_device_read_hex(bank_card_string, code, 2, 0);
data->country_code = code[0] << 8 | code[1];
}
// Check currency code presence
ws = string_search_str(bank_card_string, "Currency code: ");
if(ws != STRING_FAILURE) {
// strlen("Currency code: ") = 15
string_right(bank_card_string, 15);
nfc_device_read_hex(bank_card_string, code, 2, 0);
data->currency_code = code[0] << 8 | code[1];
}
} while(0);
saved = true;
} while(false);
return saved;
}
bool nfc_device_load_bank_card_data(FlipperFile* file, NfcDevice* dev) {
bool parsed = false;
NfcEmvData* data = &dev->dev_data.emv_data;
memset(data, 0, sizeof(NfcEmvData));
uint32_t data_cnt = 0;
string_t temp_str;
string_init(temp_str);
do {
// Load essential data
if(!flipper_file_get_value_count(file, "AID", &data_cnt)) break;
data->aid_len = data_cnt;
if(!flipper_file_read_hex(file, "AID", data->aid, data->aid_len)) break;
if(!flipper_file_read_string(file, "Name", temp_str)) break;
strlcpy(data->name, string_get_cstr(temp_str), sizeof(data->name));
if(!flipper_file_get_value_count(file, "Number", &data_cnt)) break;
data->number_len = data_cnt;
if(!flipper_file_read_hex(file, "Number", data->number, data->number_len)) break;
parsed = true;
// Load optional data
uint8_t exp_data[2] = {};
if(flipper_file_read_hex(file, "Exp data", exp_data, 2)) {
data->exp_mon = exp_data[0];
data->exp_year = exp_data[1];
}
if(flipper_file_read_uint32(file, "Country code", &data_cnt, 1)) {
data->country_code = data_cnt;
}
if(flipper_file_read_uint32(file, "Currency code", &data_cnt, 1)) {
data->currency_code = data_cnt;
}
} while(false);
string_clear(temp_str);
return parsed;
}
@@ -297,58 +228,49 @@ static bool nfc_device_save_file(
const char* extension) {
furi_assert(dev);
FileWorker* file_worker = file_worker_alloc(false);
string_t dev_file_name;
string_init(dev_file_name);
bool saved = false;
FlipperFile* file = flipper_file_alloc(dev->storage);
NfcDeviceCommonData* data = &dev->dev_data.nfc_data;
string_t temp_str;
string_init(temp_str);
uint16_t string_len = 0;
do {
// Create nfc directory if necessary
if(!file_worker_mkdir(file_worker, nfc_app_folder)) {
break;
};
if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break;
// First remove nfc device file if it was saved
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;
};
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
// Open file
if(!file_worker_open(
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
if(!flipper_file_open_always(file, string_get_cstr(temp_str))) break;
// Write header
if(!flipper_file_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
// Write nfc device type
if(!flipper_file_write_comment_cstr(
file, "Nfc device type can be UID, Mifare Ultralight, Bank card"))
break;
}
// Prepare and write format name on 1st line
string_len = nfc_device_prepare_format_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
nfc_device_prepare_format_string(dev, temp_str);
if(!flipper_file_write_string(file, "Device type", temp_str)) break;
// Write UID, ATQA, SAK
if(!flipper_file_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats"))
break;
}
// Prepare and write UID data on 2nd line
string_len = nfc_device_prepare_uid_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
if(!flipper_file_write_hex(file, "UID", data->uid, data->uid_len)) break;
if(!flipper_file_write_hex(file, "ATQA", data->atqa, 2)) break;
if(!flipper_file_write_hex(file, "SAK", &data->sak, 1)) break;
// Save more data if necessary
if(dev->format == NfcDeviceSaveFormatMifareUl) {
string_len = nfc_device_prepare_mifare_ul_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
string_len = nfc_device_prepare_bank_card_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
if(!nfc_device_save_bank_card_data(file, dev)) break;
}
saved = true;
} while(0);
if(!saved) {
dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file");
}
string_clear(temp_str);
string_clear(dev_file_name);
file_worker_close(file_worker);
file_worker_free(file_worker);
return true;
flipper_file_close(file);
flipper_file_free(file);
return saved;
}
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
@@ -360,73 +282,64 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
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);
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
bool parsed = false;
FlipperFile* file = flipper_file_alloc(dev->storage);
NfcDeviceCommonData* data = &dev->dev_data.nfc_data;
uint32_t data_cnt = 0;
string_t temp_str;
string_init(temp_str);
bool depricated_version = false;
do {
// 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;
}
string_set_n(temp_str, path, 0, ext_start);
string_cat_printf(temp_str, "%s", nfc_app_shadow_extension);
dev->shadow_file_exist =
storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK;
// 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;
}
if(!flipper_file_open_existing(file, string_get_cstr(temp_str))) break;
} else {
if(!file_worker_open(
file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
break;
}
if(!flipper_file_open_existing(file, string_get_cstr(path))) break;
}
// Read and parse format from 1st line
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
break;
}
if(!nfc_device_parse_format_string(dev, temp_string)) {
break;
}
// Read and parse UID data from 2nd line
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
break;
}
if(!nfc_device_parse_uid_string(dev, temp_string)) {
// Read and verify file header
uint32_t version = 0;
if(!flipper_file_read_header(file, temp_str, &version)) break;
if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) {
depricated_version = true;
break;
}
// Read Nfc device type
if(!flipper_file_read_string(file, "Device type", temp_str)) break;
if(!nfc_device_parse_format_string(dev, temp_str)) break;
// Read and parse UID, ATQA and SAK
if(!flipper_file_get_value_count(file, "UID", &data_cnt)) break;
data->uid_len = data_cnt;
if(!flipper_file_read_hex(file, "UID", data->uid, data->uid_len)) break;
if(!flipper_file_read_hex(file, "ATQA", data->atqa, 2)) break;
if(!flipper_file_read_hex(file, "SAK", &data->sak, 1)) break;
// Parse other data
if(dev->format == NfcDeviceSaveFormatMifareUl) {
// Read until EOF
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
break;
}
if(!nfc_device_parse_mifare_ul_string(dev, temp_string)) {
break;
}
if(!nfc_device_load_mifare_ul_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
// Read until EOF
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
break;
}
if(!nfc_device_parse_bank_card_string(dev, temp_string)) {
break;
}
if(!nfc_device_load_bank_card_data(file, dev)) break;
}
parsed = true;
} while(0);
} while(false);
if(!parsed) {
file_worker_show_error(file_worker, "Can not parse\nfile");
if(depricated_version) {
dialog_message_show_storage_error(dev->dialogs, "File format depricated");
} else {
dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile");
}
}
string_clear(temp_string);
string_clear(temp_str);
flipper_file_close(file);
flipper_file_free(file);
return parsed;
}
@@ -434,19 +347,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
furi_assert(dev);
furi_assert(file_path);
FileWorker* file_worker = file_worker_alloc(false);
// Load device data
string_t path;
string_init_set_str(path, file_path);
bool dev_load = nfc_device_load_data(file_worker, path, dev);
bool dev_load = nfc_device_load_data(dev, path);
if(dev_load) {
// Set device name
path_extract_filename_no_ext(file_path, path);
nfc_device_set_name(dev, string_get_cstr(path));
}
string_clear(path);
file_worker_close(file_worker);
file_worker_free(file_worker);
return dev_load;
}
@@ -454,10 +364,9 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
bool nfc_file_select(NfcDevice* dev) {
furi_assert(dev);
FileWorker* file_worker = file_worker_alloc(false);
// Input events and views are managed by file_select
bool res = file_worker_file_select(
file_worker,
bool res = dialog_file_select_show(
dev->dialogs,
nfc_app_folder,
nfc_app_extension,
dev->file_name,
@@ -465,18 +374,14 @@ bool nfc_file_select(NfcDevice* dev) {
dev->dev_name);
if(res) {
string_t dev_str;
// Get key file path
string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension);
res = nfc_device_load_data(file_worker, dev_str, dev);
res = nfc_device_load_data(dev, dev_str);
if(res) {
nfc_device_set_name(dev, dev->file_name);
}
string_clear(dev_str);
}
file_worker_close(file_worker);
file_worker_free(file_worker);
return res;
}
@@ -491,61 +396,48 @@ void nfc_device_clear(NfcDevice* dev) {
bool nfc_device_delete(NfcDevice* dev) {
furi_assert(dev);
bool result = true;
FileWorker* file_worker = file_worker_alloc(false);
bool deleted = false;
string_t file_path;
string_init(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;
}
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) 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;
}
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
}
deleted = true;
} while(0);
if(!deleted) {
dialog_message_show_storage_error(dev->dialogs, "Can not remove file");
}
string_clear(file_path);
file_worker_close(file_worker);
file_worker_free(file_worker);
return result;
return deleted;
}
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);
bool restored = 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;
}
if(!storage_simply_remove(dev->storage, string_get_cstr(path))) 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;
}
if(!nfc_device_load_data(dev, path)) break;
restored = true;
} while(0);
string_clear(path);
file_worker_close(file_worker);
file_worker_free(file_worker);
return result;
return restored;
}

View File

@@ -2,6 +2,8 @@
#include <stdint.h>
#include <stdbool.h>
#include <storage/storage.h>
#include <dialogs/dialogs.h>
#include "mifare_ultralight.h"
@@ -57,6 +59,8 @@ typedef struct {
} NfcDeviceData;
typedef struct {
Storage* storage;
DialogsApp* dialogs;
NfcDeviceData dev_data;
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
char file_name[NFC_FILE_NAME_MAX_LEN];
@@ -64,6 +68,10 @@ typedef struct {
bool shadow_file_exist;
} NfcDevice;
NfcDevice* nfc_device_alloc();
void nfc_device_free(NfcDevice* nfc_dev);
void nfc_device_set_name(NfcDevice* dev, const char* name);
bool nfc_device_save(NfcDevice* dev, const char* dev_name);

View File

@@ -1,16 +0,0 @@
#pragma once
#include "nfc_device.h"
#include <m-string.h>
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string);
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string);
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string);
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string);
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string);
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string);

View File

@@ -36,7 +36,7 @@ struct Nfc {
Gui* gui;
NotificationApp* notifications;
SceneManager* scene_manager;
NfcDevice dev;
NfcDevice* dev;
NfcDeviceCommonData dev_edit_data;
char text_store[NFC_TEXT_STORE_SIZE + 1];

View File

@@ -248,6 +248,8 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
result->emv_data.aid_len = emv_app.aid_len;
memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len);
} else {
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
furi_hal_nfc_deactivate();

View File

@@ -17,7 +17,7 @@ void nfc_scene_card_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
if(nfc->dev.dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
if(nfc->dev->dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
submenu_add_item(
submenu,
"Run compatible app",
@@ -48,9 +48,9 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexRunApp) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
} else if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
} else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
}
return true;
@@ -66,7 +66,7 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
return true;
} else if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave);
nfc->dev.format = NfcDeviceSaveFormatUid;
nfc->dev->format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
}

View File

@@ -12,14 +12,14 @@ void nfc_scene_delete_on_enter(void* context) {
// Setup Custom Widget view
char delete_str[64];
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev.dev_name);
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev->dev_name);
widget_add_text_box_element(nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, delete_str);
widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
char uid_str[32];
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
if(data->uid_len == 4) {
snprintf(
uid_str,
@@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
if(event.event == GuiButtonTypeLeft) {
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == GuiButtonTypeRight) {
if(nfc_device_delete(&nfc->dev)) {
if(nfc_device_delete(nfc->dev)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
} else {
scene_manager_search_and_switch_to_previous_scene(

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h"
#include "../helpers/nfc_emv_parser.h"
#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL)
@@ -36,13 +37,13 @@ void nfc_scene_device_info_on_enter(void* context) {
// Setup Custom Widget view
widget_add_text_box_element(
nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev.dev_name);
nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev->dev_name);
widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
char uid_str[32];
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
if(data->uid_len == 4) {
snprintf(
uid_str,
@@ -87,14 +88,14 @@ void nfc_scene_device_info_on_enter(void* context) {
widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str);
// Setup Data View
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Back");
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
TextBox* text_box = nfc->text_box;
text_box_set_context(text_box, nfc);
text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback);
@@ -107,8 +108,8 @@ void nfc_scene_device_info_on_enter(void* context) {
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
}
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
BankCard* bank_card = nfc->bank_card;
bank_card_set_name(bank_card, emv_data->name);
bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
@@ -116,12 +117,29 @@ void nfc_scene_device_info_on_enter(void* context) {
if(emv_data->exp_mon) {
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
}
string_t display_str;
string_init(display_str);
if(emv_data->country_code) {
bank_card_set_country_name(bank_card, emv_data->country_code);
string_t country_name;
string_init(country_name);
if(nfc_emv_parser_get_country_name(
nfc->dev->storage, emv_data->country_code, country_name)) {
string_printf(display_str, "Reg:%s", string_get_cstr(country_name));
bank_card_set_country_name(bank_card, string_get_cstr(display_str));
}
string_clear(country_name);
}
if(emv_data->currency_code) {
bank_card_set_currency_name(bank_card, emv_data->currency_code);
string_t currency_name;
string_init(currency_name);
if(nfc_emv_parser_get_currency_name(
nfc->dev->storage, emv_data->country_code, currency_name)) {
string_printf(display_str, "Cur:%s", string_get_cstr(currency_name));
bank_card_set_currency_name(bank_card, string_get_cstr(display_str));
}
string_clear(currency_name);
}
string_clear(display_str);
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
@@ -136,17 +154,17 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
consumed = true;
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
consumed = true;
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
@@ -168,7 +186,7 @@ void nfc_scene_device_info_on_exit(void* context) {
// Clear Custom Widget
widget_clear(nfc->widget);
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
// Clear Dialog
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
@@ -179,11 +197,11 @@ void nfc_scene_device_info_on_exit(void* context) {
dialog_ex_set_center_button_text(dialog_ex, NULL);
dialog_ex_set_result_callback(dialog_ex, NULL);
dialog_ex_set_context(dialog_ex, NULL);
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
// Clear TextBox
text_box_clean(nfc->text_box);
string_clean(nfc->text_box_store);
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
// Clear Bank Card
bank_card_clear(nfc->bank_card);
}

View File

@@ -11,7 +11,7 @@ void nfc_scene_emulate_apdu_sequence_on_enter(void* context) {
// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev.dev_data, NULL, nfc);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev->dev_data, NULL, nfc);
}
bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) {

View File

@@ -14,8 +14,8 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
// Setup view
Popup* popup = nfc->popup;
if(strcmp(nfc->dev.dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
if(strcmp(nfc->dev->dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
}
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop);
@@ -25,7 +25,7 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
nfc_worker_start(
nfc->worker,
NfcWorkerStateEmulateMifareUl,
&nfc->dev.dev_data,
&nfc->dev->dev_data,
nfc_emulate_mifare_ul_worker_callback,
nfc);
}
@@ -45,7 +45,7 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event
NFC_MF_UL_DATA_CHANGED) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED);
nfc_device_save_shadow(&nfc->dev, nfc->dev.dev_name);
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
}
consumed = false;
}

View File

@@ -5,10 +5,10 @@ void nfc_scene_emulate_uid_on_enter(void* context) {
// Setup view
Popup* popup = nfc->popup;
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
if(strcmp(nfc->dev.dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
if(strcmp(nfc->dev->dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
} else if(data->uid_len == 4) {
nfc_text_store_set(
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
@@ -32,7 +32,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) {
// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev.dev_data, NULL, nfc);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc);
}
bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) {

View File

@@ -3,7 +3,7 @@
void nfc_scene_file_select_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Process file_select return
if(nfc_file_select(&nfc->dev)) {
if(nfc_file_select(nfc->dev)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
} else {
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);

View File

@@ -32,9 +32,9 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
nfc->dev.format = NfcDeviceSaveFormatMifareUl;
nfc->dev->format = NfcDeviceSaveFormatMifareUl;
// Clear device name
nfc_device_set_name(&nfc->dev, "");
nfc_device_set_name(nfc->dev, "");
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
} else if(event.event == SubmenuIndexEmulate) {

View File

@@ -18,7 +18,7 @@ void nfc_scene_read_card_on_enter(void* context) {
// Start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(
nfc->worker, NfcWorkerStateDetect, &nfc->dev.dev_data, nfc_read_card_worker_callback, nfc);
nfc->worker, NfcWorkerStateDetect, &nfc->dev->dev_data, nfc_read_card_worker_callback, nfc);
}
bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) {

View File

@@ -15,7 +15,7 @@ void nfc_scene_read_card_success_on_enter(void* context) {
notification_message(nfc->notifications, &sequence_success);
// Setup view
NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data;
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "More");
@@ -68,7 +68,7 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == DialogExResultRight) {
// Clear device name
nfc_device_set_name(&nfc->dev, "");
nfc_device_set_name(nfc->dev, "");
scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
return true;
}

View File

@@ -20,7 +20,7 @@ void nfc_scene_read_emv_app_on_enter(void* context) {
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadEMVApp,
&nfc->dev.dev_data,
&nfc->dev->dev_data,
nfc_read_emv_app_worker_callback,
nfc);
}

View File

@@ -13,8 +13,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup view
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "Run app");
@@ -23,7 +23,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
// Display UID and AID
string_t aid;
string_init(aid);
bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid);
bool aid_found =
nfc_emv_parser_get_aid_name(nfc->dev->storage, emv_data->aid, emv_data->aid_len, aid);
if(!aid_found) {
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
string_cat_printf(aid, "%02X", emv_data->aid[i]);

View File

@@ -17,12 +17,12 @@ void nfc_scene_read_emv_data_on_enter(void* context) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
// Clear emv data
memset(&nfc->dev.dev_data.emv_data, 0, sizeof(nfc->dev.dev_data.emv_data));
memset(&nfc->dev->dev_data.emv_data, 0, sizeof(nfc->dev->dev_data.emv_data));
// Start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadEMV,
&nfc->dev.dev_data,
&nfc->dev->dev_data,
nfc_read_emv_data_worker_callback,
nfc);
}

View File

@@ -13,8 +13,8 @@ void nfc_scene_read_emv_data_success_widget_callback(
void nfc_scene_read_emv_data_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
// Setup Custom Widget view
// Add frame
@@ -34,7 +34,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
nfc);
// Add card name
widget_add_string_element(
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name);
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name);
// Add cad number
string_t pan_str;
string_init(pan_str);
@@ -49,7 +49,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
string_t country_name;
string_init(country_name);
if((emv_data->country_code) &&
nfc_emv_parser_get_country_name(emv_data->country_code, country_name)) {
nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) {
string_t disp_country;
string_init_printf(disp_country, "Reg:%s", country_name);
widget_add_string_element(
@@ -61,7 +61,8 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
string_t currency_name;
string_init(currency_name);
if((emv_data->currency_code) &&
nfc_emv_parser_get_currency_name(emv_data->currency_code, currency_name)) {
nfc_emv_parser_get_currency_name(
nfc->dev->storage, emv_data->currency_code, currency_name)) {
string_t disp_currency;
string_init_printf(disp_currency, "Cur:%s", currency_name);
widget_add_string_element(
@@ -122,8 +123,8 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e
nfc->scene_manager, NfcSceneReadEmvAppSuccess);
} else if(event.event == GuiButtonTypeRight) {
// Clear device name
nfc_device_set_name(&nfc->dev, "");
nfc->dev.format = NfcDeviceSaveFormatBankCard;
nfc_device_set_name(nfc->dev, "");
nfc->dev->format = NfcDeviceSaveFormatBankCard;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
}

View File

@@ -20,7 +20,7 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) {
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadMifareUl,
&nfc->dev.dev_data,
&nfc->dev->dev_data,
nfc_read_mifare_ul_worker_callback,
nfc);
}

View File

@@ -27,7 +27,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
notification_message(nfc->notifications, &sequence_success);
// Setup dialog view
NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data;
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "More");
@@ -54,7 +54,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback);
// Setup TextBox view
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
TextBox* text_box = nfc->text_box;
text_box_set_context(text_box, nfc);
text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);

View File

@@ -15,11 +15,11 @@ void nfc_scene_save_name_on_enter(void* context) {
// Setup view
TextInput* text_input = nfc->text_input;
bool dev_name_empty = false;
if(!strcmp(nfc->dev.dev_name, "")) {
if(!strcmp(nfc->dev->dev_name, "")) {
set_random_name(nfc->text_store, sizeof(nfc->text_store));
dev_name_empty = true;
} else {
nfc_text_store_set(nfc, nfc->dev.dev_name);
nfc_text_store_set(nfc, nfc->dev->dev_name);
}
text_input_set_header_text(text_input, "Name the card");
text_input_set_result_callback(
@@ -37,14 +37,14 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
if(strcmp(nfc->dev.dev_name, "")) {
nfc_device_delete(&nfc->dev);
if(strcmp(nfc->dev->dev_name, "")) {
nfc_device_delete(nfc->dev);
}
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
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);
if(nfc_device_save(&nfc->dev, nfc->text_store)) {
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
if(nfc_device_save(nfc->dev, nfc->text_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
return true;
} else {

View File

@@ -18,7 +18,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
if(nfc->dev.format != NfcDeviceSaveFormatBankCard) {
if(nfc->dev->format != NfcDeviceSaveFormatBankCard) {
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
}
@@ -30,7 +30,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
if(nfc->dev.shadow_file_exist) {
if(nfc->dev->shadow_file_exist) {
submenu_add_item(
submenu,
"Restore original",
@@ -49,7 +49,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event);
if(event.event == SubmenuIndexEmulate) {
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
@@ -65,7 +65,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
consumed = true;
} else if(event.event == SubmenuIndexRestoreOriginal) {
if(!nfc_device_restore(&nfc->dev)) {
if(!nfc_device_restore(nfc->dev)) {
scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
} else {

View File

@@ -19,7 +19,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
nfc_scene_set_atqa_byte_input_callback,
NULL,
nfc,
nfc->dev.dev_data.nfc_data.atqa,
nfc->dev->dev_data.nfc_data.atqa,
2);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}

View File

@@ -19,7 +19,7 @@ void nfc_scene_set_sak_on_enter(void* context) {
nfc_scene_set_sak_byte_input_callback,
NULL,
nfc,
&nfc->dev.dev_data.nfc_data.sak,
&nfc->dev->dev_data.nfc_data.sak,
1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}

View File

@@ -15,7 +15,7 @@ void nfc_scene_set_type_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
// Clear device name
nfc_device_set_name(&nfc->dev, "");
nfc_device_set_name(nfc->dev, "");
submenu_add_item(
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
submenu_add_item(
@@ -28,13 +28,13 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexNFCA7) {
nfc->dev.dev_data.nfc_data.uid_len = 7;
nfc->dev.format = NfcDeviceSaveFormatUid;
nfc->dev->dev_data.nfc_data.uid_len = 7;
nfc->dev->format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
return true;
} else if(event.event == SubmenuIndexNFCA4) {
nfc->dev.dev_data.nfc_data.uid_len = 4;
nfc->dev.format = NfcDeviceSaveFormatUid;
nfc->dev->dev_data.nfc_data.uid_len = 4;
nfc->dev->format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
return true;
}

View File

@@ -14,7 +14,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
// Setup view
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter uid in hex");
nfc->dev_edit_data = nfc->dev.dev_data.nfc_data;
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
byte_input_set_result_callback(
byte_input,
nfc_scene_set_uid_byte_input_callback,

View File

@@ -34,7 +34,7 @@ void nfc_scene_start_on_enter(void* context) {
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
nfc_device_clear(&nfc->dev);
nfc_device_clear(nfc->dev);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}

View File

@@ -67,42 +67,14 @@ void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
}
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code) {
void bank_card_set_country_name(BankCard* bank_card, const char* country_name) {
furi_assert(bank_card);
string_t country_name;
string_init(country_name);
if(nfc_emv_parser_get_country_name(country_code, country_name)) {
string_t disp_country;
string_init_printf(disp_country, "Reg:%s", country_name);
widget_add_string_element(
bank_card->widget,
120,
18,
AlignRight,
AlignTop,
FontSecondary,
string_get_cstr(disp_country));
string_clear(disp_country);
}
string_clear(country_name);
widget_add_string_element(
bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name);
}
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code) {
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) {
furi_assert(bank_card);
string_t currency_name;
string_init(currency_name);
if(nfc_emv_parser_get_currency_name(currency_code, currency_name)) {
string_t disp_currency;
string_init_printf(disp_currency, "Cur:%s", currency_name);
widget_add_string_element(
bank_card->widget,
31,
18,
AlignLeft,
AlignTop,
FontSecondary,
string_get_cstr(disp_currency));
string_clear(disp_currency);
}
string_clear(currency_name);
widget_add_string_element(
bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name);
}

View File

@@ -21,6 +21,6 @@ void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len);
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code);
void bank_card_set_country_name(BankCard* bank_card, const char* country_name);
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code);
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name);