[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:
parent
54dc16134d
commit
90d450368c
@ -1,49 +1,80 @@
|
|||||||
#include "nfc_emv_parser.h"
|
#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
|
static bool nfc_emv_parser_search_data(
|
||||||
nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) {
|
Storage* storage,
|
||||||
bool found = false;
|
const char* file_name,
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
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)) {
|
do {
|
||||||
if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) {
|
// Open file
|
||||||
found = true;
|
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);
|
string_clear(temp_str);
|
||||||
file_worker_free(file_worker);
|
flipper_file_free(file);
|
||||||
return found;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
||||||
bool result = false;
|
Storage* storage,
|
||||||
|
uint8_t* aid,
|
||||||
|
uint8_t aid_len,
|
||||||
|
string_t aid_name) {
|
||||||
|
furi_assert(storage);
|
||||||
|
bool parsed = false;
|
||||||
string_t key;
|
string_t key;
|
||||||
string_init(key);
|
string_init(key);
|
||||||
for(uint8_t i = 0; i < aid_len; i++) {
|
for(uint8_t i = 0; i < aid_len; i++) {
|
||||||
string_cat_printf(key, "%02X", aid[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);
|
string_clear(key);
|
||||||
return result;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) {
|
bool nfc_emv_parser_get_country_name(
|
||||||
bool result = false;
|
Storage* storage,
|
||||||
|
uint16_t country_code,
|
||||||
|
string_t country_name) {
|
||||||
|
bool parsed = false;
|
||||||
string_t key;
|
string_t key;
|
||||||
string_init_printf(key, "%04X", country_code);
|
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);
|
string_clear(key);
|
||||||
return result;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) {
|
bool nfc_emv_parser_get_currency_name(
|
||||||
bool result = false;
|
Storage* storage,
|
||||||
|
uint16_t currency_code,
|
||||||
|
string_t currency_name) {
|
||||||
|
bool parsed = false;
|
||||||
string_t key;
|
string_t key;
|
||||||
string_init_printf(key, "%04X", currency_code);
|
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);
|
string_clear(key);
|
||||||
return result;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,25 +3,39 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
/** Get EMV application name by number
|
/** Get EMV application name by number
|
||||||
|
* @param storage Storage instance
|
||||||
* @param aid - AID number array
|
* @param aid - AID number array
|
||||||
* @param aid_len - AID length
|
* @param aid_len - AID length
|
||||||
* @param aid_name - string to keep AID name
|
* @param aid_name - string to keep AID name
|
||||||
* @return - true if AID found, false otherwies
|
* @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
|
/** Get country name by country code
|
||||||
|
* @param storage Storage instance
|
||||||
* @param country_code - ISO 3166 country code
|
* @param country_code - ISO 3166 country code
|
||||||
* @param country_name - string to keep country name
|
* @param country_name - string to keep country name
|
||||||
* @return - true if country found, false otherwies
|
* @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
|
/** Get currency name by currency code
|
||||||
|
* @param storage Storage instance
|
||||||
* @param currency_code - ISO 3166 currency code
|
* @param currency_code - ISO 3166 currency code
|
||||||
* @param currency_name - string to keep currency name
|
* @param currency_name - string to keep currency name
|
||||||
* @return - true if currency found, false otherwies
|
* @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);
|
||||||
|
|||||||
@ -31,6 +31,9 @@ Nfc* nfc_alloc() {
|
|||||||
view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback);
|
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);
|
view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100);
|
||||||
|
|
||||||
|
// Nfc device
|
||||||
|
nfc->dev = nfc_device_alloc();
|
||||||
|
|
||||||
// Open GUI record
|
// Open GUI record
|
||||||
nfc->gui = furi_record_open("gui");
|
nfc->gui = furi_record_open("gui");
|
||||||
view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
|
view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
|
||||||
@ -82,6 +85,9 @@ Nfc* nfc_alloc() {
|
|||||||
void nfc_free(Nfc* nfc) {
|
void nfc_free(Nfc* nfc) {
|
||||||
furi_assert(nfc);
|
furi_assert(nfc);
|
||||||
|
|
||||||
|
// Nfc device
|
||||||
|
nfc_device_free(nfc->dev);
|
||||||
|
|
||||||
// Submenu
|
// Submenu
|
||||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
|
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
submenu_free(nfc->submenu);
|
submenu_free(nfc->submenu);
|
||||||
@ -154,8 +160,8 @@ int32_t nfc_app(void* p) {
|
|||||||
char* args = p;
|
char* args = p;
|
||||||
|
|
||||||
// Check argument and run corresponding scene
|
// Check argument and run corresponding scene
|
||||||
if((*args != '\0') && nfc_device_load(&nfc->dev, p)) {
|
if((*args != '\0') && nfc_device_load(nfc->dev, p)) {
|
||||||
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||||
|
|||||||
@ -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/path.h>
|
||||||
#include <lib/toolbox/hex.h>
|
#include <lib/flipper_file/flipper_file.h>
|
||||||
|
|
||||||
#define NFC_DEVICE_MAX_DATA_LEN 14
|
|
||||||
|
|
||||||
static const char* nfc_app_folder = "/any/nfc";
|
static const char* nfc_app_folder = "/any/nfc";
|
||||||
static const char* nfc_app_extension = ".nfc";
|
static const char* nfc_app_extension = ".nfc";
|
||||||
static const char* nfc_app_shadow_extension = ".shd";
|
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) {
|
NfcDevice* nfc_device_alloc() {
|
||||||
string_strim(str);
|
NfcDevice* nfc_dev = furi_alloc(sizeof(NfcDevice));
|
||||||
uint8_t nibble_high = 0;
|
nfc_dev->storage = furi_record_open("storage");
|
||||||
uint8_t nibble_low = 0;
|
nfc_dev->dialogs = furi_record_open("dialogs");
|
||||||
bool parsed = true;
|
return nfc_dev;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if(dev->format == NfcDeviceSaveFormatUid) {
|
||||||
string_set_str(format_string, "UID\n");
|
string_set_str(format_string, "UID");
|
||||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
} 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) {
|
} else if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
string_set_str(format_string, "Mifare Ultralight\n");
|
string_set_str(format_string, "Mifare Ultralight");
|
||||||
} else {
|
} 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) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) {
|
static bool nfc_device_save_mifare_ul_data(FlipperFile* file, NfcDevice* dev) {
|
||||||
NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data;
|
bool saved = false;
|
||||||
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) {
|
|
||||||
MifareUlData* data = &dev->dev_data.mf_ul_data;
|
MifareUlData* data = &dev->dev_data.mf_ul_data;
|
||||||
string_printf(mifare_ul_string, "Signature:");
|
string_t temp_str;
|
||||||
for(uint8_t i = 0; i < sizeof(data->signature); i++) {
|
string_init(temp_str);
|
||||||
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;
|
|
||||||
|
|
||||||
|
// Save Mifare Ultralight specific data
|
||||||
do {
|
do {
|
||||||
// strlen("Signature: ") = 11
|
if(!flipper_file_write_comment_cstr(file, "Mifare Ultralight specific data")) break;
|
||||||
string_right(mifare_ul_string, 11);
|
if(!flipper_file_write_hex(file, "Signature", data->signature, sizeof(data->signature)))
|
||||||
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
if(!flipper_file_write_hex(
|
||||||
// strlen("Version: ") = 9
|
file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version)))
|
||||||
string_right(mifare_ul_string, 9);
|
|
||||||
if(!nfc_device_read_hex(
|
|
||||||
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
// Write conters and tearing flags data
|
||||||
string_strim(mifare_ul_string);
|
bool counters_saved = true;
|
||||||
// Read counters and tearing flags
|
|
||||||
for(uint8_t i = 0; i < 3; i++) {
|
for(uint8_t i = 0; i < 3; i++) {
|
||||||
res = sscanf(
|
string_printf(temp_str, "Counter %d", i);
|
||||||
string_get_cstr(mifare_ul_string),
|
if(!flipper_file_write_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) {
|
||||||
"Counter %hX: %lu Tearing flag %hX: %02hX",
|
counters_saved = false;
|
||||||
&cnt_num,
|
break;
|
||||||
&data->counter[i],
|
}
|
||||||
&cnt_num,
|
string_printf(temp_str, "Tearing %d", i);
|
||||||
&tearing_tmp);
|
if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) {
|
||||||
if(res != 4) {
|
counters_saved = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
data->tearing[i] = tearing_tmp;
|
|
||||||
ws = string_search_char(mifare_ul_string, '\n');
|
|
||||||
string_right(mifare_ul_string, ws + 1);
|
|
||||||
}
|
}
|
||||||
// Read data size
|
if(!counters_saved) break;
|
||||||
res = sscanf(string_get_cstr(mifare_ul_string), "Data size: %hu", &data->data_size);
|
// Write pages data
|
||||||
if(res != 1) {
|
uint32_t pages_total = data->data_size / 4;
|
||||||
break;
|
if(!flipper_file_write_uint32(file, "Pages total", &pages_total, 1)) break;
|
||||||
}
|
bool pages_saved = true;
|
||||||
ws = string_search_char(mifare_ul_string, '\n');
|
|
||||||
string_right(mifare_ul_string, ws + 1);
|
|
||||||
// Read data
|
|
||||||
for(uint16_t i = 0; i < data->data_size; i += 4) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsed = true;
|
if(!pages_saved) break;
|
||||||
} while(0);
|
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;
|
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;
|
NfcEmvData* data = &dev->dev_data.emv_data;
|
||||||
string_printf(bank_card_string, "AID len: %d, AID:", data->aid_len);
|
uint32_t data_temp = 0;
|
||||||
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));
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = sscanf(string_get_cstr(bank_card_string), "AID len: %hu", &data->aid_len);
|
// Write Bank card specific data
|
||||||
if(res != 1) {
|
if(!flipper_file_write_comment_cstr(file, "Bank card specific data")) break;
|
||||||
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
|
if(data->country_code) {
|
||||||
string_right(bank_card_string, 9);
|
data_temp = data->country_code;
|
||||||
size_t ws = string_search_char(bank_card_string, ':');
|
if(!flipper_file_write_uint32(file, "Country code", &data_temp, 1)) break;
|
||||||
string_right(bank_card_string, ws + 1);
|
|
||||||
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name);
|
if(data->currency_code) {
|
||||||
if(res != 1) {
|
data_temp = data->currency_code;
|
||||||
break;
|
if(!flipper_file_write_uint32(file, "Currency code", &data_temp, 1)) break;
|
||||||
}
|
}
|
||||||
ws = string_search_char(bank_card_string, '\n');
|
saved = true;
|
||||||
string_right(bank_card_string, ws + 1);
|
} while(false);
|
||||||
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);
|
|
||||||
|
|
||||||
|
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;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,58 +228,49 @@ static bool nfc_device_save_file(
|
|||||||
const char* extension) {
|
const char* extension) {
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
|
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
bool saved = false;
|
||||||
string_t dev_file_name;
|
FlipperFile* file = flipper_file_alloc(dev->storage);
|
||||||
string_init(dev_file_name);
|
NfcDeviceCommonData* data = &dev->dev_data.nfc_data;
|
||||||
string_t temp_str;
|
string_t temp_str;
|
||||||
string_init(temp_str);
|
string_init(temp_str);
|
||||||
uint16_t string_len = 0;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Create nfc directory if necessary
|
// Create nfc directory if necessary
|
||||||
if(!file_worker_mkdir(file_worker, nfc_app_folder)) {
|
if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break;
|
||||||
break;
|
|
||||||
};
|
|
||||||
// First remove nfc device file if it was saved
|
// First remove nfc device file if it was saved
|
||||||
string_printf(dev_file_name, "%s/%s%s", folder, dev_name, extension);
|
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
||||||
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
// Open file
|
// Open file
|
||||||
if(!file_worker_open(
|
if(!flipper_file_open_always(file, string_get_cstr(temp_str))) break;
|
||||||
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
// 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;
|
break;
|
||||||
}
|
nfc_device_prepare_format_string(dev, temp_str);
|
||||||
// Prepare and write format name on 1st line
|
if(!flipper_file_write_string(file, "Device type", temp_str)) break;
|
||||||
string_len = nfc_device_prepare_format_string(dev, temp_str);
|
// Write UID, ATQA, SAK
|
||||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
if(!flipper_file_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats"))
|
||||||
break;
|
break;
|
||||||
}
|
if(!flipper_file_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||||
// Prepare and write UID data on 2nd line
|
if(!flipper_file_write_hex(file, "ATQA", data->atqa, 2)) break;
|
||||||
string_len = nfc_device_prepare_uid_string(dev, temp_str);
|
if(!flipper_file_write_hex(file, "SAK", &data->sak, 1)) break;
|
||||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Save more data if necessary
|
// Save more data if necessary
|
||||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
string_len = nfc_device_prepare_mifare_ul_string(dev, temp_str);
|
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
||||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
string_len = nfc_device_prepare_bank_card_string(dev, temp_str);
|
if(!nfc_device_save_bank_card_data(file, dev)) break;
|
||||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
saved = true;
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
if(!saved) {
|
||||||
|
dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file");
|
||||||
|
}
|
||||||
string_clear(temp_str);
|
string_clear(temp_str);
|
||||||
string_clear(dev_file_name);
|
flipper_file_close(file);
|
||||||
file_worker_close(file_worker);
|
flipper_file_free(file);
|
||||||
file_worker_free(file_worker);
|
return saved;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
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);
|
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) {
|
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
|
||||||
string_t temp_string;
|
|
||||||
string_init(temp_string);
|
|
||||||
bool parsed = false;
|
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 {
|
do {
|
||||||
// Check existance of shadow file
|
// Check existance of shadow file
|
||||||
size_t ext_start = string_search_str(path, nfc_app_extension);
|
size_t ext_start = string_search_str(path, nfc_app_extension);
|
||||||
string_set_n(temp_string, path, 0, ext_start);
|
string_set_n(temp_str, path, 0, ext_start);
|
||||||
string_cat_printf(temp_string, "%s", nfc_app_shadow_extension);
|
string_cat_printf(temp_str, "%s", nfc_app_shadow_extension);
|
||||||
if(!file_worker_is_file_exist(
|
dev->shadow_file_exist =
|
||||||
file_worker, string_get_cstr(temp_string), &dev->shadow_file_exist)) {
|
storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK;
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Open shadow file if it exists. If not - open original
|
// Open shadow file if it exists. If not - open original
|
||||||
if(dev->shadow_file_exist) {
|
if(dev->shadow_file_exist) {
|
||||||
if(!file_worker_open(
|
if(!flipper_file_open_existing(file, string_get_cstr(temp_str))) break;
|
||||||
file_worker, string_get_cstr(temp_string), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(!file_worker_open(
|
if(!flipper_file_open_existing(file, string_get_cstr(path))) break;
|
||||||
file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Read and verify file header
|
||||||
// Read and parse format from 1st line
|
uint32_t version = 0;
|
||||||
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
|
if(!flipper_file_read_header(file, temp_str, &version)) break;
|
||||||
break;
|
if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) {
|
||||||
}
|
depricated_version = true;
|
||||||
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)) {
|
|
||||||
break;
|
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
|
// Parse other data
|
||||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
// Read until EOF
|
if(!nfc_device_load_mifare_ul_data(file, dev)) break;
|
||||||
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!nfc_device_parse_mifare_ul_string(dev, temp_string)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
// Read until EOF
|
if(!nfc_device_load_bank_card_data(file, dev)) break;
|
||||||
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!nfc_device_parse_bank_card_string(dev, temp_string)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
parsed = true;
|
parsed = true;
|
||||||
} while(0);
|
} while(false);
|
||||||
|
|
||||||
if(!parsed) {
|
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;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,19 +347,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
|||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
furi_assert(file_path);
|
furi_assert(file_path);
|
||||||
|
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
|
||||||
// Load device data
|
// Load device data
|
||||||
string_t path;
|
string_t path;
|
||||||
string_init_set_str(path, file_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) {
|
if(dev_load) {
|
||||||
// Set device name
|
// Set device name
|
||||||
path_extract_filename_no_ext(file_path, path);
|
path_extract_filename_no_ext(file_path, path);
|
||||||
nfc_device_set_name(dev, string_get_cstr(path));
|
nfc_device_set_name(dev, string_get_cstr(path));
|
||||||
}
|
}
|
||||||
string_clear(path);
|
string_clear(path);
|
||||||
file_worker_close(file_worker);
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
|
|
||||||
return dev_load;
|
return dev_load;
|
||||||
}
|
}
|
||||||
@ -454,10 +364,9 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
|||||||
bool nfc_file_select(NfcDevice* dev) {
|
bool nfc_file_select(NfcDevice* dev) {
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
|
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
|
||||||
// Input events and views are managed by file_select
|
// Input events and views are managed by file_select
|
||||||
bool res = file_worker_file_select(
|
bool res = dialog_file_select_show(
|
||||||
file_worker,
|
dev->dialogs,
|
||||||
nfc_app_folder,
|
nfc_app_folder,
|
||||||
nfc_app_extension,
|
nfc_app_extension,
|
||||||
dev->file_name,
|
dev->file_name,
|
||||||
@ -465,18 +374,14 @@ bool nfc_file_select(NfcDevice* dev) {
|
|||||||
dev->dev_name);
|
dev->dev_name);
|
||||||
if(res) {
|
if(res) {
|
||||||
string_t dev_str;
|
string_t dev_str;
|
||||||
|
|
||||||
// Get key file path
|
// Get key file path
|
||||||
string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension);
|
string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension);
|
||||||
|
res = nfc_device_load_data(dev, dev_str);
|
||||||
res = nfc_device_load_data(file_worker, dev_str, dev);
|
|
||||||
if(res) {
|
if(res) {
|
||||||
nfc_device_set_name(dev, dev->file_name);
|
nfc_device_set_name(dev, dev->file_name);
|
||||||
}
|
}
|
||||||
string_clear(dev_str);
|
string_clear(dev_str);
|
||||||
}
|
}
|
||||||
file_worker_close(file_worker);
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -491,61 +396,48 @@ void nfc_device_clear(NfcDevice* dev) {
|
|||||||
bool nfc_device_delete(NfcDevice* dev) {
|
bool nfc_device_delete(NfcDevice* dev) {
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
|
|
||||||
bool result = true;
|
bool deleted = false;
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
|
||||||
string_t file_path;
|
string_t file_path;
|
||||||
|
string_init(file_path);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Delete original file
|
// Delete original file
|
||||||
string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
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))) {
|
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Delete shadow file if it exists
|
// Delete shadow file if it exists
|
||||||
if(dev->shadow_file_exist) {
|
if(dev->shadow_file_exist) {
|
||||||
string_clean(file_path);
|
|
||||||
string_printf(
|
string_printf(
|
||||||
file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
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))) {
|
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
deleted = true;
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
if(!deleted) {
|
||||||
|
dialog_message_show_storage_error(dev->dialogs, "Can not remove file");
|
||||||
|
}
|
||||||
|
|
||||||
string_clear(file_path);
|
string_clear(file_path);
|
||||||
file_worker_close(file_worker);
|
return deleted;
|
||||||
file_worker_free(file_worker);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_device_restore(NfcDevice* dev) {
|
bool nfc_device_restore(NfcDevice* dev) {
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
furi_assert(dev->shadow_file_exist);
|
furi_assert(dev->shadow_file_exist);
|
||||||
|
|
||||||
bool result = true;
|
bool restored = false;
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
|
||||||
string_t path;
|
string_t path;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
string_init_printf(
|
string_init_printf(
|
||||||
path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||||
if(!file_worker_remove(file_worker, string_get_cstr(path))) {
|
if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break;
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dev->shadow_file_exist = false;
|
dev->shadow_file_exist = false;
|
||||||
string_clean(path);
|
|
||||||
string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||||
if(!nfc_device_load_data(file_worker, path, dev)) {
|
if(!nfc_device_load_data(dev, path)) break;
|
||||||
result = false;
|
restored = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
string_clear(path);
|
string_clear(path);
|
||||||
file_worker_close(file_worker);
|
return restored;
|
||||||
file_worker_free(file_worker);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
|
|
||||||
#include "mifare_ultralight.h"
|
#include "mifare_ultralight.h"
|
||||||
|
|
||||||
@ -57,6 +59,8 @@ typedef struct {
|
|||||||
} NfcDeviceData;
|
} NfcDeviceData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Storage* storage;
|
||||||
|
DialogsApp* dialogs;
|
||||||
NfcDeviceData dev_data;
|
NfcDeviceData dev_data;
|
||||||
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
|
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
|
||||||
char file_name[NFC_FILE_NAME_MAX_LEN];
|
char file_name[NFC_FILE_NAME_MAX_LEN];
|
||||||
@ -64,6 +68,10 @@ typedef struct {
|
|||||||
bool shadow_file_exist;
|
bool shadow_file_exist;
|
||||||
} NfcDevice;
|
} NfcDevice;
|
||||||
|
|
||||||
|
NfcDevice* nfc_device_alloc();
|
||||||
|
|
||||||
|
void nfc_device_free(NfcDevice* nfc_dev);
|
||||||
|
|
||||||
void nfc_device_set_name(NfcDevice* dev, const char* name);
|
void nfc_device_set_name(NfcDevice* dev, const char* name);
|
||||||
|
|
||||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name);
|
bool nfc_device_save(NfcDevice* dev, const char* dev_name);
|
||||||
|
|||||||
@ -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);
|
|
||||||
@ -36,7 +36,7 @@ struct Nfc {
|
|||||||
Gui* gui;
|
Gui* gui;
|
||||||
NotificationApp* notifications;
|
NotificationApp* notifications;
|
||||||
SceneManager* scene_manager;
|
SceneManager* scene_manager;
|
||||||
NfcDevice dev;
|
NfcDevice* dev;
|
||||||
NfcDeviceCommonData dev_edit_data;
|
NfcDeviceCommonData dev_edit_data;
|
||||||
|
|
||||||
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
||||||
|
|||||||
@ -248,6 +248,8 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
|||||||
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
|
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
|
||||||
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
|
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
|
||||||
FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
|
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 {
|
} else {
|
||||||
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
|
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
|
||||||
furi_hal_nfc_deactivate();
|
furi_hal_nfc_deactivate();
|
||||||
|
|||||||
@ -17,7 +17,7 @@ void nfc_scene_card_menu_on_enter(void* context) {
|
|||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
Submenu* submenu = nfc->submenu;
|
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_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Run compatible app",
|
"Run compatible app",
|
||||||
@ -48,9 +48,9 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == SubmenuIndexRunApp) {
|
if(event.event == SubmenuIndexRunApp) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
|
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);
|
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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -66,7 +66,7 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
return true;
|
return true;
|
||||||
} else if(event.event == SubmenuIndexSave) {
|
} else if(event.event == SubmenuIndexSave) {
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, 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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,14 +12,14 @@ void nfc_scene_delete_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup Custom Widget view
|
// Setup Custom Widget view
|
||||||
char delete_str[64];
|
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_text_box_element(nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, delete_str);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
||||||
char uid_str[32];
|
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) {
|
if(data->uid_len == 4) {
|
||||||
snprintf(
|
snprintf(
|
||||||
uid_str,
|
uid_str,
|
||||||
@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == GuiButtonTypeLeft) {
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
return scene_manager_previous_scene(nfc->scene_manager);
|
return scene_manager_previous_scene(nfc->scene_manager);
|
||||||
} else if(event.event == GuiButtonTypeRight) {
|
} 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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "../nfc_i.h"
|
#include "../nfc_i.h"
|
||||||
|
#include "../helpers/nfc_emv_parser.h"
|
||||||
|
|
||||||
#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL)
|
#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
|
// Setup Custom Widget view
|
||||||
widget_add_text_box_element(
|
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(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
|
||||||
char uid_str[32];
|
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) {
|
if(data->uid_len == 4) {
|
||||||
snprintf(
|
snprintf(
|
||||||
uid_str,
|
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);
|
widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str);
|
||||||
|
|
||||||
// Setup Data View
|
// Setup Data View
|
||||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Back");
|
dialog_ex_set_left_button_text(dialog_ex, "Back");
|
||||||
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
|
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
|
||||||
dialog_ex_set_context(dialog_ex, nfc);
|
dialog_ex_set_context(dialog_ex, nfc);
|
||||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
|
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
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;
|
TextBox* text_box = nfc->text_box;
|
||||||
text_box_set_context(text_box, nfc);
|
text_box_set_context(text_box, nfc);
|
||||||
text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback);
|
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]);
|
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));
|
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||||
BankCard* bank_card = nfc->bank_card;
|
BankCard* bank_card = nfc->bank_card;
|
||||||
bank_card_set_name(bank_card, emv_data->name);
|
bank_card_set_name(bank_card, emv_data->name);
|
||||||
bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
|
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) {
|
if(emv_data->exp_mon) {
|
||||||
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
|
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) {
|
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) {
|
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);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
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)) {
|
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
|
||||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||||
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
|
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
|
||||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
|
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
|
// Clear Custom Widget
|
||||||
widget_clear(nfc->widget);
|
widget_clear(nfc->widget);
|
||||||
|
|
||||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||||
// Clear Dialog
|
// Clear Dialog
|
||||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
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_center_button_text(dialog_ex, NULL);
|
||||||
dialog_ex_set_result_callback(dialog_ex, NULL);
|
dialog_ex_set_result_callback(dialog_ex, NULL);
|
||||||
dialog_ex_set_context(dialog_ex, NULL);
|
dialog_ex_set_context(dialog_ex, NULL);
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
// Clear TextBox
|
// Clear TextBox
|
||||||
text_box_clean(nfc->text_box);
|
text_box_clean(nfc->text_box);
|
||||||
string_clean(nfc->text_box_store);
|
string_clean(nfc->text_box_store);
|
||||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
// Clear Bank Card
|
// Clear Bank Card
|
||||||
bank_card_clear(nfc->bank_card);
|
bank_card_clear(nfc->bank_card);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ void nfc_scene_emulate_apdu_sequence_on_enter(void* context) {
|
|||||||
// Setup and start worker
|
// Setup and start worker
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
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) {
|
bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
@ -14,8 +14,8 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
Popup* popup = nfc->popup;
|
Popup* popup = nfc->popup;
|
||||||
if(strcmp(nfc->dev.dev_name, "")) {
|
if(strcmp(nfc->dev->dev_name, "")) {
|
||||||
nfc_text_store_set(nfc, "%s", 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_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||||
popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop);
|
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_start(
|
||||||
nfc->worker,
|
nfc->worker,
|
||||||
NfcWorkerStateEmulateMifareUl,
|
NfcWorkerStateEmulateMifareUl,
|
||||||
&nfc->dev.dev_data,
|
&nfc->dev->dev_data,
|
||||||
nfc_emulate_mifare_ul_worker_callback,
|
nfc_emulate_mifare_ul_worker_callback,
|
||||||
nfc);
|
nfc);
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event
|
|||||||
NFC_MF_UL_DATA_CHANGED) {
|
NFC_MF_UL_DATA_CHANGED) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED);
|
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;
|
consumed = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,10 @@ void nfc_scene_emulate_uid_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
Popup* popup = nfc->popup;
|
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, "")) {
|
if(strcmp(nfc->dev->dev_name, "")) {
|
||||||
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
|
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
|
||||||
} else if(data->uid_len == 4) {
|
} else if(data->uid_len == 4) {
|
||||||
nfc_text_store_set(
|
nfc_text_store_set(
|
||||||
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
|
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
|
// Setup and start worker
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
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) {
|
bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
void nfc_scene_file_select_on_enter(void* context) {
|
void nfc_scene_file_select_on_enter(void* context) {
|
||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
// Process file_select return
|
// Process file_select return
|
||||||
if(nfc_file_select(&nfc->dev)) {
|
if(nfc_file_select(nfc->dev)) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
||||||
|
|||||||
@ -32,9 +32,9 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == SubmenuIndexSave) {
|
if(event.event == SubmenuIndexSave) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
|
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
|
||||||
nfc->dev.format = NfcDeviceSaveFormatMifareUl;
|
nfc->dev->format = NfcDeviceSaveFormatMifareUl;
|
||||||
// Clear device name
|
// Clear device name
|
||||||
nfc_device_set_name(&nfc->dev, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||||
return true;
|
return true;
|
||||||
} else if(event.event == SubmenuIndexEmulate) {
|
} else if(event.event == SubmenuIndexEmulate) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ void nfc_scene_read_card_on_enter(void* context) {
|
|||||||
// Start worker
|
// Start worker
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||||
nfc_worker_start(
|
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) {
|
bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ void nfc_scene_read_card_success_on_enter(void* context) {
|
|||||||
notification_message(nfc->notifications, &sequence_success);
|
notification_message(nfc->notifications, &sequence_success);
|
||||||
|
|
||||||
// Setup view
|
// 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;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
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);
|
return scene_manager_previous_scene(nfc->scene_manager);
|
||||||
} else if(event.event == DialogExResultRight) {
|
} else if(event.event == DialogExResultRight) {
|
||||||
// Clear device name
|
// Clear device name
|
||||||
nfc_device_set_name(&nfc->dev, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ void nfc_scene_read_emv_app_on_enter(void* context) {
|
|||||||
nfc_worker_start(
|
nfc_worker_start(
|
||||||
nfc->worker,
|
nfc->worker,
|
||||||
NfcWorkerStateReadEMVApp,
|
NfcWorkerStateReadEMVApp,
|
||||||
&nfc->dev.dev_data,
|
&nfc->dev->dev_data,
|
||||||
nfc_read_emv_app_worker_callback,
|
nfc_read_emv_app_worker_callback,
|
||||||
nfc);
|
nfc);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
|
|||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
|
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "Run app");
|
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
|
// Display UID and AID
|
||||||
string_t aid;
|
string_t aid;
|
||||||
string_init(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) {
|
if(!aid_found) {
|
||||||
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
|
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
|
||||||
string_cat_printf(aid, "%02X", emv_data->aid[i]);
|
string_cat_printf(aid, "%02X", emv_data->aid[i]);
|
||||||
|
|||||||
@ -17,12 +17,12 @@ void nfc_scene_read_emv_data_on_enter(void* context) {
|
|||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||||
// Clear emv data
|
// 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
|
// Start worker
|
||||||
nfc_worker_start(
|
nfc_worker_start(
|
||||||
nfc->worker,
|
nfc->worker,
|
||||||
NfcWorkerStateReadEMV,
|
NfcWorkerStateReadEMV,
|
||||||
&nfc->dev.dev_data,
|
&nfc->dev->dev_data,
|
||||||
nfc_read_emv_data_worker_callback,
|
nfc_read_emv_data_worker_callback,
|
||||||
nfc);
|
nfc);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,8 @@ void nfc_scene_read_emv_data_success_widget_callback(
|
|||||||
|
|
||||||
void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||||
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
|
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||||
|
|
||||||
// Setup Custom Widget view
|
// Setup Custom Widget view
|
||||||
// Add frame
|
// Add frame
|
||||||
@ -34,7 +34,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
|||||||
nfc);
|
nfc);
|
||||||
// Add card name
|
// Add card name
|
||||||
widget_add_string_element(
|
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
|
// Add cad number
|
||||||
string_t pan_str;
|
string_t pan_str;
|
||||||
string_init(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_t country_name;
|
||||||
string_init(country_name);
|
string_init(country_name);
|
||||||
if((emv_data->country_code) &&
|
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_t disp_country;
|
||||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||||
widget_add_string_element(
|
widget_add_string_element(
|
||||||
@ -61,7 +61,8 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
|||||||
string_t currency_name;
|
string_t currency_name;
|
||||||
string_init(currency_name);
|
string_init(currency_name);
|
||||||
if((emv_data->currency_code) &&
|
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_t disp_currency;
|
||||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||||
widget_add_string_element(
|
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);
|
nfc->scene_manager, NfcSceneReadEmvAppSuccess);
|
||||||
} else if(event.event == GuiButtonTypeRight) {
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
// Clear device name
|
// Clear device name
|
||||||
nfc_device_set_name(&nfc->dev, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
nfc->dev.format = NfcDeviceSaveFormatBankCard;
|
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) {
|
|||||||
nfc_worker_start(
|
nfc_worker_start(
|
||||||
nfc->worker,
|
nfc->worker,
|
||||||
NfcWorkerStateReadMifareUl,
|
NfcWorkerStateReadMifareUl,
|
||||||
&nfc->dev.dev_data,
|
&nfc->dev->dev_data,
|
||||||
nfc_read_mifare_ul_worker_callback,
|
nfc_read_mifare_ul_worker_callback,
|
||||||
nfc);
|
nfc);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
|
|||||||
notification_message(nfc->notifications, &sequence_success);
|
notification_message(nfc->notifications, &sequence_success);
|
||||||
|
|
||||||
// Setup dialog view
|
// 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;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
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);
|
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback);
|
||||||
|
|
||||||
// Setup TextBox view
|
// 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;
|
TextBox* text_box = nfc->text_box;
|
||||||
text_box_set_context(text_box, nfc);
|
text_box_set_context(text_box, nfc);
|
||||||
text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);
|
text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);
|
||||||
|
|||||||
@ -15,11 +15,11 @@ void nfc_scene_save_name_on_enter(void* context) {
|
|||||||
// Setup view
|
// Setup view
|
||||||
TextInput* text_input = nfc->text_input;
|
TextInput* text_input = nfc->text_input;
|
||||||
bool dev_name_empty = false;
|
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));
|
set_random_name(nfc->text_store, sizeof(nfc->text_store));
|
||||||
dev_name_empty = true;
|
dev_name_empty = true;
|
||||||
} else {
|
} 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_header_text(text_input, "Name the card");
|
||||||
text_input_set_result_callback(
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
|
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
|
||||||
if(strcmp(nfc->dev.dev_name, "")) {
|
if(strcmp(nfc->dev->dev_name, "")) {
|
||||||
nfc_device_delete(&nfc->dev);
|
nfc_device_delete(nfc->dev);
|
||||||
}
|
}
|
||||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
|
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);
|
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
||||||
if(nfc_device_save(&nfc->dev, nfc->text_store)) {
|
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
|||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
Submenu* submenu = nfc->submenu;
|
Submenu* submenu = nfc->submenu;
|
||||||
|
|
||||||
if(nfc->dev.format != NfcDeviceSaveFormatBankCard) {
|
if(nfc->dev->format != NfcDeviceSaveFormatBankCard) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
|
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
|||||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
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_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Restore original",
|
"Restore original",
|
||||||
@ -49,7 +49,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event);
|
||||||
if(event.event == SubmenuIndexEmulate) {
|
if(event.event == SubmenuIndexEmulate) {
|
||||||
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
} 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(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneStart);
|
nfc->scene_manager, NfcSceneStart);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
|
|||||||
nfc_scene_set_atqa_byte_input_callback,
|
nfc_scene_set_atqa_byte_input_callback,
|
||||||
NULL,
|
NULL,
|
||||||
nfc,
|
nfc,
|
||||||
nfc->dev.dev_data.nfc_data.atqa,
|
nfc->dev->dev_data.nfc_data.atqa,
|
||||||
2);
|
2);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ void nfc_scene_set_sak_on_enter(void* context) {
|
|||||||
nfc_scene_set_sak_byte_input_callback,
|
nfc_scene_set_sak_byte_input_callback,
|
||||||
NULL,
|
NULL,
|
||||||
nfc,
|
nfc,
|
||||||
&nfc->dev.dev_data.nfc_data.sak,
|
&nfc->dev->dev_data.nfc_data.sak,
|
||||||
1);
|
1);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ void nfc_scene_set_type_on_enter(void* context) {
|
|||||||
Nfc* nfc = (Nfc*)context;
|
Nfc* nfc = (Nfc*)context;
|
||||||
Submenu* submenu = nfc->submenu;
|
Submenu* submenu = nfc->submenu;
|
||||||
// Clear device name
|
// Clear device name
|
||||||
nfc_device_set_name(&nfc->dev, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
|
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
@ -28,13 +28,13 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexNFCA7) {
|
if(event.event == SubmenuIndexNFCA7) {
|
||||||
nfc->dev.dev_data.nfc_data.uid_len = 7;
|
nfc->dev->dev_data.nfc_data.uid_len = 7;
|
||||||
nfc->dev.format = NfcDeviceSaveFormatUid;
|
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
||||||
return true;
|
return true;
|
||||||
} else if(event.event == SubmenuIndexNFCA4) {
|
} else if(event.event == SubmenuIndexNFCA4) {
|
||||||
nfc->dev.dev_data.nfc_data.uid_len = 4;
|
nfc->dev->dev_data.nfc_data.uid_len = 4;
|
||||||
nfc->dev.format = NfcDeviceSaveFormatUid;
|
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
|
|||||||
// Setup view
|
// Setup view
|
||||||
ByteInput* byte_input = nfc->byte_input;
|
ByteInput* byte_input = nfc->byte_input;
|
||||||
byte_input_set_header_text(byte_input, "Enter uid in hex");
|
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_set_result_callback(
|
||||||
byte_input,
|
byte_input,
|
||||||
nfc_scene_set_uid_byte_input_callback,
|
nfc_scene_set_uid_byte_input_callback,
|
||||||
|
|||||||
@ -34,7 +34,7 @@ void nfc_scene_start_on_enter(void* context) {
|
|||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
|
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_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
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);
|
furi_assert(bank_card);
|
||||||
string_t country_name;
|
widget_add_string_element(
|
||||||
string_init(country_name);
|
bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
furi_assert(bank_card);
|
||||||
string_t currency_name;
|
widget_add_string_element(
|
||||||
string_init(currency_name);
|
bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, 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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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_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);
|
||||||
|
|||||||
@ -1,148 +1,151 @@
|
|||||||
A00000000305076010 VISA ELO Credit
|
Filetype: Flipper EMV resources
|
||||||
A0000000031010 VISA Debit/Credit (Classic)
|
Version: 1
|
||||||
A000000003101001 VISA Credit
|
# EMV Application ID code: Application ID name
|
||||||
A000000003101002 VISA Debit
|
A00000000305076010: VISA ELO Credit
|
||||||
A0000000032010 VISA Electron
|
A0000000031010: VISA Debit/Credit (Classic)
|
||||||
A0000000032020 VISA
|
A000000003101001: VISA Credit
|
||||||
A0000000033010 VISA Interlink
|
A000000003101002: VISA Debit
|
||||||
A0000000034010 VISA Specific
|
A0000000032010: VISA Electron
|
||||||
A0000000035010 VISA Specific
|
A0000000032020: VISA
|
||||||
A0000000036010 Domestic Visa Cash
|
A0000000033010: VISA Interlink
|
||||||
A0000000036020 International Visa Cash
|
A0000000034010: VISA Specific
|
||||||
A0000000038002 VISA Auth EMV-CAP (DPA)
|
A0000000035010: VISA Specific
|
||||||
A0000000038010 VISA Plus
|
A0000000036010: Domestic Visa Cash
|
||||||
A0000000039010 VISA Loyalty
|
A0000000036020: International Visa Cash
|
||||||
A000000003999910 VISA Proprietary ATM
|
A0000000038002: VISA Auth EMV-CAP (DPA)
|
||||||
A00000000401 MasterCard PayPass
|
A0000000038010: VISA Plus
|
||||||
A0000000041010 MasterCard Global
|
A0000000039010: VISA Loyalty
|
||||||
A00000000410101213 MasterCard Credit
|
A000000003999910: VISA Proprietary ATM
|
||||||
A00000000410101215 MasterCard Credit
|
A00000000401: MasterCard PayPass
|
||||||
A0000000042010 MasterCard Specific
|
A0000000041010: MasterCard Global
|
||||||
A0000000043010 MasterCard Specific
|
A00000000410101213: MasterCard Credit
|
||||||
A0000000043060 Maestro (Debit)
|
A00000000410101215: MasterCard Credit
|
||||||
A000000004306001 Maestro (Debit)
|
A0000000042010: MasterCard Specific
|
||||||
A0000000044010 MasterCard Specific
|
A0000000043010: MasterCard Specific
|
||||||
A0000000045010 MasterCard Specific
|
A0000000043060: Maestro (Debit)
|
||||||
A0000000046000 Cirrus
|
A000000004306001: Maestro (Debit)
|
||||||
A0000000048002 SecureCode EMV-CAP
|
A0000000044010: MasterCard Specific
|
||||||
A0000000049999 MasterCard PayPass
|
A0000000045010: MasterCard Specific
|
||||||
A0000000050001 Maestro UK
|
A0000000046000: Cirrus
|
||||||
A0000000050002 Solo
|
A0000000048002: SecureCode EMV-CAP
|
||||||
A00000002401 Self Service
|
A0000000049999: MasterCard PayPass
|
||||||
A000000025 American Express
|
A0000000050001: Maestro UK
|
||||||
A0000000250000 American Express
|
A0000000050002: Solo
|
||||||
A00000002501 American Express
|
A00000002401: Self Service
|
||||||
A000000025010402 American Express
|
A000000025: American Express
|
||||||
A000000025010701 ExpressPay
|
A0000000250000: American Express
|
||||||
A000000025010801 American Express
|
A00000002501: American Express
|
||||||
A0000000291010 Link / American Express
|
A000000025010402: American Express
|
||||||
A0000000421010 Cartes Bancaire EMV Card
|
A000000025010701: ExpressPay
|
||||||
A0000000426010 Apple Pay
|
A000000025010801: American Express
|
||||||
A00000006510 JCB
|
A0000000291010: Link / American Express
|
||||||
A0000000651010 JCB J Smart Credit
|
A0000000421010: Cartes Bancaire EMV Card
|
||||||
A00000006900 Moneo
|
A0000000426010: Apple Pay
|
||||||
A000000077010000021000000000003B Visa AEPN
|
A00000006510: JCB
|
||||||
A000000098 Debit Card
|
A0000000651010: JCB J Smart Credit
|
||||||
A0000000980848 Debit Card
|
A00000006900: Moneo
|
||||||
A0000001211010 Dankort VISA GEM Vision
|
A000000077010000021000000000003B: Visa AEPN
|
||||||
A0000001410001 PagoBANCOMAT
|
A000000098: Debit Card
|
||||||
A0000001523010 Discover, Pulse D Pas
|
A0000000980848: Debit Card
|
||||||
A0000001524010 Discover
|
A0000001211010: Dankort VISA GEM Vision
|
||||||
A0000001544442 Banricompras Debito
|
A0000001410001: PagoBANCOMAT
|
||||||
A000000172950001 BAROC Taiwan
|
A0000001523010: Discover, Pulse D Pas
|
||||||
A0000002281010 SPAN (M/Chip)
|
A0000001524010: Discover
|
||||||
A0000002282010 SPAN (VIS)
|
A0000001544442: Banricompras Debito
|
||||||
A0000002771010 INTERAC
|
A000000172950001: BAROC Taiwan
|
||||||
A00000031510100528 Currence PuC
|
A0000002281010: SPAN (M/Chip)
|
||||||
A0000003156020 Chipknip
|
A0000002282010: SPAN (VIS)
|
||||||
A0000003591010028001 Girocard EAPS
|
A0000002771010: INTERAC
|
||||||
A0000003710001 InterSwitch Verve Card
|
A00000031510100528: Currence PuC
|
||||||
A0000004540010 Etranzact Genesis Card
|
A0000003156020: Chipknip
|
||||||
A0000004540011 Etranzact Genesis Card 2
|
A0000003591010028001: Girocard EAPS
|
||||||
A0000004766C GOOGLE_PAYMENT
|
A0000003710001: InterSwitch Verve Card
|
||||||
A0000005241010 RuPay
|
A0000004540010: Etranzact Genesis Card
|
||||||
A0000006723010 TROY chip credit card
|
A0000004540011: Etranzact Genesis Card 2
|
||||||
A0000006723020 TROY chip debit card
|
A0000004766C: GOOGLE_PAYMENT
|
||||||
A0000007705850 XTRAPOWER
|
A0000005241010: RuPay
|
||||||
B012345678 Maestro TEST
|
A0000006723010: TROY chip credit card
|
||||||
D27600002545500100 Girocard
|
A0000006723020: TROY chip debit card
|
||||||
D5780000021010 Bankaxept
|
A0000007705850: XTRAPOWER
|
||||||
F0000000030001 BRADESCO
|
B012345678: Maestro TEST
|
||||||
A000000003000000 (VISA) Card Manager
|
D27600002545500100: Girocard
|
||||||
A000000003534441 Schlumberger SD
|
D5780000021010: Bankaxept
|
||||||
A0000000035350 Security Domain
|
F0000000030001: BRADESCO
|
||||||
A000000003535041 Security Domain
|
A000000003000000: (VISA) Card Manager
|
||||||
A0000000040000 MasterCard Card Manager
|
A000000003534441: Schlumberger SD
|
||||||
A000000018434D Gemplus card manager
|
A0000000035350: Security Domain
|
||||||
A000000018434D00 Gemplus Security Domain
|
A000000003535041: Security Domain
|
||||||
A0000000960200 Proton WISD
|
A0000000040000: MasterCard Card Manager
|
||||||
A0000001510000 Global Platform SD
|
A000000018434D: Gemplus card manager
|
||||||
A00000015153504341534400 CASD_AID
|
A000000018434D00: Gemplus Security Domain
|
||||||
A000000476A010 GSD_MANAGER_AID
|
A0000000960200: Proton WISD
|
||||||
A000000476A110 GSD_MANAGER_AID
|
A0000001510000: Global Platform SD
|
||||||
315041592E5359532E4444463031 Visa PSE
|
A00000015153504341534400: CASD_AID
|
||||||
325041592E5359532E4444463031 Visa PPSE
|
A000000476A010: GSD_MANAGER_AID
|
||||||
A0000000042203 MasterCard Specific
|
A000000476A110: GSD_MANAGER_AID
|
||||||
A0000000045555 APDULogger
|
315041592E5359532E4444463031: Visa PSE
|
||||||
A0000000090001FF44FF1289 Orange
|
325041592E5359532E4444463031: Visa PPSE
|
||||||
A0000000101030 Maestro-CH
|
A0000000042203: MasterCard Specific
|
||||||
A00000001800 Gemplus
|
A0000000045555: APDULogger
|
||||||
A0000000181001 gemplus util packages
|
A0000000090001FF44FF1289: Orange
|
||||||
A000000025010104 American Express
|
A0000000101030: Maestro-CH
|
||||||
A00000002949034010100001 HSBC
|
A00000001800: Gemplus
|
||||||
A00000002949282010100000 Barclay
|
A0000000181001: gemplus util packages
|
||||||
A00000005945430100 Girocard Electronic Cash
|
A000000025010104: American Express
|
||||||
A0000000980840 Visa Common Debit
|
A00000002949034010100001: HSBC
|
||||||
A0000001570010 AMEX
|
A00000002949282010100000: Barclay
|
||||||
A0000001570020 MasterCard
|
A00000005945430100: Girocard Electronic Cash
|
||||||
A0000001570021 Maestro
|
A0000000980840: Visa Common Debit
|
||||||
A0000001570022 Maestro
|
A0000001570010: AMEX
|
||||||
A0000001570023 CASH
|
A0000001570020: MasterCard
|
||||||
A0000001570030 VISA
|
A0000001570021: Maestro
|
||||||
A0000001570031 VISA
|
A0000001570022: Maestro
|
||||||
A0000001570040 JCB
|
A0000001570023: CASH
|
||||||
A0000001570050 Postcard
|
A0000001570030: VISA
|
||||||
A0000001570051 Postcard
|
A0000001570031: VISA
|
||||||
A0000001570100 MCard
|
A0000001570040: JCB
|
||||||
A0000001570104 MyOne
|
A0000001570050: Postcard
|
||||||
A000000157010C WIRCard
|
A0000001570051: Postcard
|
||||||
A000000157010D Power Card
|
A0000001570100: MCard
|
||||||
A0000001574443 DINERS CLUB
|
A0000001570104: MyOne
|
||||||
A0000001574444 Supercard Plus
|
A000000157010C: WIRCard
|
||||||
A00000022820101010 SPAN
|
A000000157010D: Power Card
|
||||||
A000000308000010000100 ID-ONE PIV BIO
|
A0000001574443: DINERS CLUB
|
||||||
A0000003241010 Discover Zip
|
A0000001574444: Supercard Plus
|
||||||
A000000333010101 UnionPay Debit
|
A00000022820101010: SPAN
|
||||||
A000000333010102 UnionPay Credit
|
A000000308000010000100: ID-ONE PIV BIO
|
||||||
A000000333010103 UnionPay Quasi Credit
|
A0000003241010: Discover Zip
|
||||||
A000000333010106 UnionPay Electronic Cash
|
A000000333010101: UnionPay Debit
|
||||||
A000000333010108 U.S. UnionPay Common Debit
|
A000000333010102: UnionPay Credit
|
||||||
A000000337102000 Classic
|
A000000333010103: UnionPay Quasi Credit
|
||||||
A000000337101001 Prepaye Online
|
A000000333010106: UnionPay Electronic Cash
|
||||||
A000000337102001 Prepaye Possibile Offiline
|
A000000333010108: U.S. UnionPay Common Debit
|
||||||
A000000337601001 Porte Monnaie Electronique
|
A000000337102000: Classic
|
||||||
A0000006581010 MIR Credit
|
A000000337101001: Prepaye Online
|
||||||
A0000006581011 MIR Credit
|
A000000337102001: Prepaye Possibile Offiline
|
||||||
A0000006582010 MIR Debit
|
A000000337601001: Porte Monnaie Electronique
|
||||||
D040000001000002 Paylife Quick IEP
|
A0000006581010: MIR Credit
|
||||||
D040000002000002 RFU
|
A0000006581011: MIR Credit
|
||||||
D040000003000002 POS
|
A0000006582010: MIR Debit
|
||||||
D040000004000002 ATM
|
D040000001000002: Paylife Quick IEP
|
||||||
D04000000B000002 Retail
|
D040000002000002: RFU
|
||||||
D04000000C000002 Bank_Data
|
D040000003000002: POS
|
||||||
D04000000D000002 Shopping
|
D040000004000002: ATM
|
||||||
D040000013000001 DF_UNI_Kepler1
|
D04000000B000002: Retail
|
||||||
D040000013000001 DF_Schüler1
|
D04000000C000002: Bank_Data
|
||||||
D040000013000002 DF_UNI_Kepler2
|
D04000000D000002: Shopping
|
||||||
D040000013000002 DF_Schüler2
|
D040000013000001: DF_UNI_Kepler1
|
||||||
D040000014000001 DF_Mensa
|
D040000013000001: DF_Schüler1
|
||||||
D040000015000001 DF_UNI_Ausweis
|
D040000013000002: DF_UNI_Kepler2
|
||||||
D040000015000001 DF_Ausweis
|
D040000013000002: DF_Schüler2
|
||||||
D0400000190001 EMV ATM Maestro
|
D040000014000001: DF_Mensa
|
||||||
D0400000190002 EMV POS Maestro
|
D040000015000001: DF_UNI_Ausweis
|
||||||
D0400000190003 EMV ATM MasterCard
|
D040000015000001: DF_Ausweis
|
||||||
D0400000190004 EMV POS MasterCard
|
D0400000190001: EMV ATM Maestro
|
||||||
D276000025 Girocard
|
D0400000190002: EMV POS Maestro
|
||||||
D27600002547410100 Girocard ATM
|
D0400000190003: EMV ATM MasterCard
|
||||||
D7560000010101 Reka Card
|
D0400000190004: EMV POS MasterCard
|
||||||
D7560000300101 M Budget
|
D276000025: Girocard
|
||||||
|
D27600002547410100: Girocard ATM
|
||||||
|
D7560000010101: Reka Card
|
||||||
|
D7560000300101: M Budget
|
||||||
@ -1,249 +1,252 @@
|
|||||||
0004 AFG
|
Filetype: Flipper EMV resources
|
||||||
0008 ALB
|
Version: 1
|
||||||
0010 ATA
|
# EMV country code: country name
|
||||||
0012 DZA
|
0004: AFG
|
||||||
0016 ASM
|
0008: ALB
|
||||||
0020 AND
|
0010: ATA
|
||||||
0024 AGO
|
0012: DZA
|
||||||
0028 ATG
|
0016: ASM
|
||||||
0031 AZE
|
0020: AND
|
||||||
0032 ARG
|
0024: AGO
|
||||||
0036 AUS
|
0028: ATG
|
||||||
0040 AUT
|
0031: AZE
|
||||||
0044 BHS
|
0032: ARG
|
||||||
0048 BHR
|
0036: AUS
|
||||||
0050 BGD
|
0040: AUT
|
||||||
0051 ARM
|
0044: BHS
|
||||||
0052 BRB
|
0048: BHR
|
||||||
0056 BEL
|
0050: BGD
|
||||||
0060 BMU
|
0051: ARM
|
||||||
0064 BTN
|
0052: BRB
|
||||||
0068 BOL
|
0056: BEL
|
||||||
0070 BIH
|
0060: BMU
|
||||||
0072 BWA
|
0064: BTN
|
||||||
0074 BVT
|
0068: BOL
|
||||||
0076 BRA
|
0070: BIH
|
||||||
0084 BLZ
|
0072: BWA
|
||||||
0086 IOT
|
0074: BVT
|
||||||
0090 SLB
|
0076: BRA
|
||||||
0092 VGB
|
0084: BLZ
|
||||||
0096 BRN
|
0086: IOT
|
||||||
0100 BGR
|
0090: SLB
|
||||||
0104 MMR
|
0092: VGB
|
||||||
0108 BDI
|
0096: BRN
|
||||||
0112 BLR
|
0100: BGR
|
||||||
0116 KHM
|
0104: MMR
|
||||||
0120 CMR
|
0108: BDI
|
||||||
0124 CAN
|
0112: BLR
|
||||||
0132 CPV
|
0116: KHM
|
||||||
0136 CYM
|
0120: CMR
|
||||||
0140 CAF
|
0124: CAN
|
||||||
0144 LKA
|
0132: CPV
|
||||||
0148 TCD
|
0136: CYM
|
||||||
0152 CHL
|
0140: CAF
|
||||||
0156 CHN
|
0144: LKA
|
||||||
0158 TWN
|
0148: TCD
|
||||||
0162 CXR
|
0152: CHL
|
||||||
0166 CCK
|
0156: CHN
|
||||||
0170 COL
|
0158: TWN
|
||||||
0174 COM
|
0162: CXR
|
||||||
0175 MYT
|
0166: CCK
|
||||||
0178 COG
|
0170: COL
|
||||||
0180 COD
|
0174: COM
|
||||||
0184 COK
|
0175: MYT
|
||||||
0188 CRI
|
0178: COG
|
||||||
0191 HRV
|
0180: COD
|
||||||
0192 CUB
|
0184: COK
|
||||||
0196 CYP
|
0188: CRI
|
||||||
0203 CZE
|
0191: HRV
|
||||||
0204 BEN
|
0192: CUB
|
||||||
0208 DNK
|
0196: CYP
|
||||||
0212 DMA
|
0203: CZE
|
||||||
0214 DOM
|
0204: BEN
|
||||||
0218 ECU
|
0208: DNK
|
||||||
0222 SLV
|
0212: DMA
|
||||||
0226 GNQ
|
0214: DOM
|
||||||
0231 ETH
|
0218: ECU
|
||||||
0232 ERI
|
0222: SLV
|
||||||
0233 EST
|
0226: GNQ
|
||||||
0234 FRO
|
0231: ETH
|
||||||
0238 FLK
|
0232: ERI
|
||||||
0239 SGS
|
0233: EST
|
||||||
0242 FJI
|
0234: FRO
|
||||||
0246 FIN
|
0238: FLK
|
||||||
0248 ALA
|
0239: SGS
|
||||||
0250 FRA
|
0242: FJI
|
||||||
0254 GUF
|
0246: FIN
|
||||||
0258 PYF
|
0248: ALA
|
||||||
0260 ATF
|
0250: FRA
|
||||||
0262 DJI
|
0254: GUF
|
||||||
0266 GAB
|
0258: PYF
|
||||||
0268 GEO
|
0260: ATF
|
||||||
0270 GMB
|
0262: DJI
|
||||||
0275 PSE
|
0266: GAB
|
||||||
0276 DEU
|
0268: GEO
|
||||||
0288 GHA
|
0270: GMB
|
||||||
0292 GIB
|
0275: PSE
|
||||||
0296 KIR
|
0276: DEU
|
||||||
0300 GRC
|
0288: GHA
|
||||||
0304 GRL
|
0292: GIB
|
||||||
0308 GRD
|
0296: KIR
|
||||||
0312 GLP
|
0300: GRC
|
||||||
0316 GUM
|
0304: GRL
|
||||||
0320 GTM
|
0308: GRD
|
||||||
0324 GIN
|
0312: GLP
|
||||||
0328 GUY
|
0316: GUM
|
||||||
0332 HTI
|
0320: GTM
|
||||||
0334 HMD
|
0324: GIN
|
||||||
0336 VAT
|
0328: GUY
|
||||||
0340 HND
|
0332: HTI
|
||||||
0344 HKG
|
0334: HMD
|
||||||
0348 HUN
|
0336: VAT
|
||||||
0352 ISL
|
0340: HND
|
||||||
0356 IND
|
0344: HKG
|
||||||
0360 IDN
|
0348: HUN
|
||||||
0364 IRN
|
0352: ISL
|
||||||
0368 IRQ
|
0356: IND
|
||||||
0372 IRL
|
0360: IDN
|
||||||
0376 ISR
|
0364: IRN
|
||||||
0380 ITA
|
0368: IRQ
|
||||||
0384 CIV
|
0372: IRL
|
||||||
0388 JAM
|
0376: ISR
|
||||||
0392 JPN
|
0380: ITA
|
||||||
0398 KAZ
|
0384: CIV
|
||||||
0400 JOR
|
0388: JAM
|
||||||
0404 KEN
|
0392: JPN
|
||||||
0408 PRK
|
0398: KAZ
|
||||||
0410 KOR
|
0400: JOR
|
||||||
0414 KWT
|
0404: KEN
|
||||||
0417 KGZ
|
0408: PRK
|
||||||
0418 LAO
|
0410: KOR
|
||||||
0422 LBN
|
0414: KWT
|
||||||
0426 LSO
|
0417: KGZ
|
||||||
0428 LVA
|
0418: LAO
|
||||||
0430 LBR
|
0422: LBN
|
||||||
0434 LBY
|
0426: LSO
|
||||||
0438 LIE
|
0428: LVA
|
||||||
0440 LTU
|
0430: LBR
|
||||||
0442 LUX
|
0434: LBY
|
||||||
0446 MAC
|
0438: LIE
|
||||||
0450 MDG
|
0440: LTU
|
||||||
0454 MWI
|
0442: LUX
|
||||||
0458 MYS
|
0446: MAC
|
||||||
0462 MDV
|
0450: MDG
|
||||||
0466 MLI
|
0454: MWI
|
||||||
0470 MLT
|
0458: MYS
|
||||||
0474 MTQ
|
0462: MDV
|
||||||
0478 MRT
|
0466: MLI
|
||||||
0480 MUS
|
0470: MLT
|
||||||
0484 MEX
|
0474: MTQ
|
||||||
0492 MCO
|
0478: MRT
|
||||||
0496 MNG
|
0480: MUS
|
||||||
0498 MDA
|
0484: MEX
|
||||||
0499 MNE
|
0492: MCO
|
||||||
0500 MSR
|
0496: MNG
|
||||||
0504 MAR
|
0498: MDA
|
||||||
0508 MOZ
|
0499: MNE
|
||||||
0512 OMN
|
0500: MSR
|
||||||
0516 NAM
|
0504: MAR
|
||||||
0520 NRU
|
0508: MOZ
|
||||||
0524 NPL
|
0512: OMN
|
||||||
0528 NLD
|
0516: NAM
|
||||||
0531 CUW
|
0520: NRU
|
||||||
0533 ABW
|
0524: NPL
|
||||||
0534 SXM
|
0528: NLD
|
||||||
0535 BES
|
0531: CUW
|
||||||
0540 NCL
|
0533: ABW
|
||||||
0548 VUT
|
0534: SXM
|
||||||
0554 NZL
|
0535: BES
|
||||||
0558 NIC
|
0540: NCL
|
||||||
0562 NER
|
0548: VUT
|
||||||
0566 NGA
|
0554: NZL
|
||||||
0570 NIU
|
0558: NIC
|
||||||
0574 NFK
|
0562: NER
|
||||||
0578 NOR
|
0566: NGA
|
||||||
0580 MNP
|
0570: NIU
|
||||||
0581 UMI
|
0574: NFK
|
||||||
0583 FSM
|
0578: NOR
|
||||||
0584 MHL
|
0580: MNP
|
||||||
0585 PLW
|
0581: UMI
|
||||||
0586 PAK
|
0583: FSM
|
||||||
0591 PAN
|
0584: MHL
|
||||||
0598 PNG
|
0585: PLW
|
||||||
0600 PRY
|
0586: PAK
|
||||||
0604 PER
|
0591: PAN
|
||||||
0608 PHL
|
0598: PNG
|
||||||
0612 PCN
|
0600: PRY
|
||||||
0616 POL
|
0604: PER
|
||||||
0620 PRT
|
0608: PHL
|
||||||
0624 GNB
|
0612: PCN
|
||||||
0626 TLS
|
0616: POL
|
||||||
0630 PRI
|
0620: PRT
|
||||||
0634 QAT
|
0624: GNB
|
||||||
0638 REU
|
0626: TLS
|
||||||
0642 ROU
|
0630: PRI
|
||||||
0643 RUS
|
0634: QAT
|
||||||
0646 RWA
|
0638: REU
|
||||||
0652 BLM
|
0642: ROU
|
||||||
0654 SHN
|
0643: RUS
|
||||||
0659 KNA
|
0646: RWA
|
||||||
0660 AIA
|
0652: BLM
|
||||||
0662 LCA
|
0654: SHN
|
||||||
0663 MAF
|
0659: KNA
|
||||||
0666 SPM
|
0660: AIA
|
||||||
0670 VCT
|
0662: LCA
|
||||||
0674 SMR
|
0663: MAF
|
||||||
0678 STP
|
0666: SPM
|
||||||
0682 SAU
|
0670: VCT
|
||||||
0686 SEN
|
0674: SMR
|
||||||
0688 SRB
|
0678: STP
|
||||||
0690 SYC
|
0682: SAU
|
||||||
0694 SLE
|
0686: SEN
|
||||||
0702 SGP
|
0688: SRB
|
||||||
0703 SVK
|
0690: SYC
|
||||||
0704 VNM
|
0694: SLE
|
||||||
0705 SVN
|
0702: SGP
|
||||||
0706 SOM
|
0703: SVK
|
||||||
0710 ZAF
|
0704: VNM
|
||||||
0716 ZWE
|
0705: SVN
|
||||||
0724 ESP
|
0706: SOM
|
||||||
0728 SSD
|
0710: ZAF
|
||||||
0729 SDN
|
0716: ZWE
|
||||||
0732 ESH
|
0724: ESP
|
||||||
0740 SUR
|
0728: SSD
|
||||||
0744 SJM
|
0729: SDN
|
||||||
0748 SWZ
|
0732: ESH
|
||||||
0752 SWE
|
0740: SUR
|
||||||
0756 CHE
|
0744: SJM
|
||||||
0760 SYR
|
0748: SWZ
|
||||||
0762 TJK
|
0752: SWE
|
||||||
0764 THA
|
0756: CHE
|
||||||
0768 TGO
|
0760: SYR
|
||||||
0772 TKL
|
0762: TJK
|
||||||
0776 TON
|
0764: THA
|
||||||
0780 TTO
|
0768: TGO
|
||||||
0784 ARE
|
0772: TKL
|
||||||
0788 TUN
|
0776: TON
|
||||||
0792 TUR
|
0780: TTO
|
||||||
0795 TKM
|
0784: ARE
|
||||||
0796 TCA
|
0788: TUN
|
||||||
0798 TUV
|
0792: TUR
|
||||||
0800 UGA
|
0795: TKM
|
||||||
0804 UKR
|
0796: TCA
|
||||||
0807 MKD
|
0798: TUV
|
||||||
0818 EGY
|
0800: UGA
|
||||||
0826 GBR
|
0804: UKR
|
||||||
0831 GGY
|
0807: MKD
|
||||||
0832 JEY
|
0818: EGY
|
||||||
0833 IMN
|
0826: GBR
|
||||||
0834 TZA
|
0831: GGY
|
||||||
0840 USA
|
0832: JEY
|
||||||
0850 VIR
|
0833: IMN
|
||||||
0854 BFA
|
0834: TZA
|
||||||
0858 URY
|
0840: USA
|
||||||
0860 UZB
|
0850: VIR
|
||||||
0862 VEN
|
0854: BFA
|
||||||
0876 WLF
|
0858: URY
|
||||||
0882 WSM
|
0860: UZB
|
||||||
0887 YEM
|
0862: VEN
|
||||||
0894 ZMB
|
0876: WLF
|
||||||
|
0882: WSM
|
||||||
|
0887: YEM
|
||||||
|
0894: ZMB
|
||||||
@ -1,168 +1,171 @@
|
|||||||
0997 USN
|
Filetype: Flipper EMV resources
|
||||||
0994 XSU
|
Version: 1
|
||||||
0990 CLF
|
# EMV currency code: currency name
|
||||||
0986 BRL
|
0997: USN
|
||||||
0985 PLN
|
0994: XSU
|
||||||
0984 BOV
|
0990: CLF
|
||||||
0981 GEL
|
0986: BRL
|
||||||
0980 UAH
|
0985: PLN
|
||||||
0979 MXV
|
0984: BOV
|
||||||
0978 EUR
|
0981: GEL
|
||||||
0977 BAM
|
0980: UAH
|
||||||
0976 CDF
|
0979: MXV
|
||||||
0975 BGN
|
0978: EUR
|
||||||
0973 AOA
|
0977: BAM
|
||||||
0972 TJS
|
0976: CDF
|
||||||
0971 AFN
|
0975: BGN
|
||||||
0970 COU
|
0973: AOA
|
||||||
0969 MGA
|
0972: TJS
|
||||||
0968 SRD
|
0971: AFN
|
||||||
0967 ZMW
|
0970: COU
|
||||||
0965 XUA
|
0969: MGA
|
||||||
0960 XDR
|
0968: SRD
|
||||||
0953 XPF
|
0967: ZMW
|
||||||
0952 XOF
|
0965: XUA
|
||||||
0951 XCD
|
0960: XDR
|
||||||
0950 XAF
|
0953: XPF
|
||||||
0949 TRY
|
0952: XOF
|
||||||
0948 CHW
|
0951: XCD
|
||||||
0947 CHE
|
0950: XAF
|
||||||
0946 RON
|
0949: TRY
|
||||||
0944 AZN
|
0948: CHW
|
||||||
0943 MZN
|
0947: CHE
|
||||||
0941 RSD
|
0946: RON
|
||||||
0940 UYI
|
0944: AZN
|
||||||
0938 SDG
|
0943: MZN
|
||||||
0937 VEF
|
0941: RSD
|
||||||
0936 GHS
|
0940: UYI
|
||||||
0934 TMT
|
0938: SDG
|
||||||
0933 BYN
|
0937: VEF
|
||||||
0932 ZWL
|
0936: GHS
|
||||||
0931 CUC
|
0934: TMT
|
||||||
0930 STN
|
0933: BYN
|
||||||
0929 MRU
|
0932: ZWL
|
||||||
0901 TWD
|
0931: CUC
|
||||||
0886 YER
|
0930: STN
|
||||||
0882 WST
|
0929: MRU
|
||||||
0860 UZS
|
0901: TWD
|
||||||
0858 UYU
|
0886: YER
|
||||||
0840 USD
|
0882: WST
|
||||||
0834 TZS
|
0860: UZS
|
||||||
0826 GBP
|
0858: UYU
|
||||||
0818 EGP
|
0840: USD
|
||||||
0807 MKD
|
0834: TZS
|
||||||
0800 UGX
|
0826: GBP
|
||||||
0788 TND
|
0818: EGP
|
||||||
0784 AED
|
0807: MKD
|
||||||
0780 TTD
|
0800: UGX
|
||||||
0776 TOP
|
0788: TND
|
||||||
0764 THB
|
0784: AED
|
||||||
0760 SYP
|
0780: TTD
|
||||||
0756 CHF
|
0776: TOP
|
||||||
0752 SEK
|
0764: THB
|
||||||
0748 SZL
|
0760: SYP
|
||||||
0728 SSP
|
0756: CHF
|
||||||
0710 ZAR
|
0752: SEK
|
||||||
0706 SOS
|
0748: SZL
|
||||||
0704 VND
|
0728: SSP
|
||||||
0702 SGD
|
0710: ZAR
|
||||||
0694 SLL
|
0706: SOS
|
||||||
0690 SCR
|
0704: VND
|
||||||
0682 SAR
|
0702: SGD
|
||||||
0654 SHP
|
0694: SLL
|
||||||
0646 RWF
|
0690: SCR
|
||||||
0643 RUB
|
0682: SAR
|
||||||
0634 QAR
|
0654: SHP
|
||||||
0608 PHP
|
0646: RWF
|
||||||
0604 PEN
|
0643: RUB
|
||||||
0600 PYG
|
0634: QAR
|
||||||
0598 PGK
|
0608: PHP
|
||||||
0590 PAB
|
0604: PEN
|
||||||
0586 PKR
|
0600: PYG
|
||||||
0578 NOK
|
0598: PGK
|
||||||
0566 NGN
|
0590: PAB
|
||||||
0558 NIO
|
0586: PKR
|
||||||
0554 NZD
|
0578: NOK
|
||||||
0548 VUV
|
0566: NGN
|
||||||
0533 AWG
|
0558: NIO
|
||||||
0532 ANG
|
0554: NZD
|
||||||
0524 NPR
|
0548: VUV
|
||||||
0516 NAD
|
0533: AWG
|
||||||
0512 OMR
|
0532: ANG
|
||||||
0504 MAD
|
0524: NPR
|
||||||
0498 MDL
|
0516: NAD
|
||||||
0496 MNT
|
0512: OMR
|
||||||
0484 MXN
|
0504: MAD
|
||||||
0480 MUR
|
0498: MDL
|
||||||
0462 MVR
|
0496: MNT
|
||||||
0458 MYR
|
0484: MXN
|
||||||
0454 MWK
|
0480: MUR
|
||||||
0446 MOP
|
0462: MVR
|
||||||
0434 LYD
|
0458: MYR
|
||||||
0430 LRD
|
0454: MWK
|
||||||
0426 LSL
|
0446: MOP
|
||||||
0422 LBP
|
0434: LYD
|
||||||
0418 LAK
|
0430: LRD
|
||||||
0417 KGS
|
0426: LSL
|
||||||
0414 KWD
|
0422: LBP
|
||||||
0410 KRW
|
0418: LAK
|
||||||
0408 KPW
|
0417: KGS
|
||||||
0404 KES
|
0414: KWD
|
||||||
0400 JOD
|
0410: KRW
|
||||||
0398 KZT
|
0408: KPW
|
||||||
0392 JPY
|
0404: KES
|
||||||
0388 JMD
|
0400: JOD
|
||||||
0376 ILS
|
0398: KZT
|
||||||
0368 IQD
|
0392: JPY
|
||||||
0364 IRR
|
0388: JMD
|
||||||
0360 IDR
|
0376: ILS
|
||||||
0356 INR
|
0368: IQD
|
||||||
0352 ISK
|
0364: IRR
|
||||||
0348 HUF
|
0360: IDR
|
||||||
0344 HKD
|
0356: INR
|
||||||
0340 HNL
|
0352: ISK
|
||||||
0332 HTG
|
0348: HUF
|
||||||
0328 GYD
|
0344: HKD
|
||||||
0324 GNF
|
0340: HNL
|
||||||
0320 GTQ
|
0332: HTG
|
||||||
0292 GIP
|
0328: GYD
|
||||||
0270 GMD
|
0324: GNF
|
||||||
0262 DJF
|
0320: GTQ
|
||||||
0242 FJD
|
0292: GIP
|
||||||
0238 FKP
|
0270: GMD
|
||||||
0232 ERN
|
0262: DJF
|
||||||
0230 ETB
|
0242: FJD
|
||||||
0222 SVC
|
0238: FKP
|
||||||
0214 DOP
|
0232: ERN
|
||||||
0208 DKK
|
0230: ETB
|
||||||
0203 CZK
|
0222: SVC
|
||||||
0192 CUP
|
0214: DOP
|
||||||
0191 HRK
|
0208: DKK
|
||||||
0188 CRC
|
0203: CZK
|
||||||
0174 KMF
|
0192: CUP
|
||||||
0170 COP
|
0191: HRK
|
||||||
0156 CNY
|
0188: CRC
|
||||||
0152 CLP
|
0174: KMF
|
||||||
0144 LKR
|
0170: COP
|
||||||
0136 KYD
|
0156: CNY
|
||||||
0132 CVE
|
0152: CLP
|
||||||
0124 CAD
|
0144: LKR
|
||||||
0116 KHR
|
0136: KYD
|
||||||
0108 BIF
|
0132: CVE
|
||||||
0104 MMK
|
0124: CAD
|
||||||
0096 BND
|
0116: KHR
|
||||||
0090 SBD
|
0108: BIF
|
||||||
0084 BZD
|
0104: MMK
|
||||||
0072 BWP
|
0096: BND
|
||||||
0068 BOB
|
0090: SBD
|
||||||
0064 BTN
|
0084: BZD
|
||||||
0060 BMD
|
0072: BWP
|
||||||
0052 BBD
|
0068: BOB
|
||||||
0051 AMD
|
0064: BTN
|
||||||
0050 BDT
|
0060: BMD
|
||||||
0048 BHD
|
0052: BBD
|
||||||
0044 BSD
|
0051: AMD
|
||||||
0036 AUD
|
0050: BDT
|
||||||
0032 ARS
|
0048: BHD
|
||||||
0012 DZD
|
0044: BSD
|
||||||
0008 ALL
|
0036: AUD
|
||||||
|
0032: ARS
|
||||||
|
0012: DZD
|
||||||
|
0008: ALL
|
||||||
Loading…
x
Reference in New Issue
Block a user