mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-12 15:28:36 -07:00
@@ -173,6 +173,15 @@ App(
|
||||
sources=["plugins/supported_cards/washcity.c"],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="emv_parser",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="emv_plugin_ep",
|
||||
targets=["f7"],
|
||||
requires=["nfc", "storage"],
|
||||
sources=["plugins/supported_cards/emv.c", "helpers/nfc_emv_parser.c"],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="ndef_parser",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
|
||||
@@ -34,7 +34,7 @@ static bool nfc_emv_parser_search_data(
|
||||
|
||||
bool nfc_emv_parser_get_aid_name(
|
||||
Storage* storage,
|
||||
uint8_t* aid,
|
||||
const uint8_t* aid,
|
||||
uint8_t aid_len,
|
||||
FuriString* aid_name) {
|
||||
furi_assert(storage);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
bool nfc_emv_parser_get_aid_name(
|
||||
Storage* storage,
|
||||
uint8_t* aid,
|
||||
const uint8_t* aid,
|
||||
uint8_t aid_len,
|
||||
FuriString* aid_name);
|
||||
|
||||
|
||||
115
applications/main/nfc/helpers/protocol_support/emv/emv.c
Normal file
115
applications/main/nfc/helpers/protocol_support/emv/emv.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "emv.h"
|
||||
#include "emv_render.h"
|
||||
|
||||
#include <nfc/protocols/emv/emv_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
#include "../iso14443_4a/iso14443_4a_i.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_emv(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
// furi_string_cat_printf(
|
||||
// temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_emv_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_more_info_on_enter_emv(NfcApp* instance) {
|
||||
// Jump to advanced scene right away
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmvMoreInfo);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_emv(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolEmv);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const EmvPollerEvent* emv_event = event.event_data;
|
||||
|
||||
if(emv_event->type == EmvPollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolEmv, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
return NfcCommandStop;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_emv(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_emv, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
// furi_string_cat_printf(
|
||||
// temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_emv_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
// static void nfc_scene_emulate_on_enter_emv(NfcApp* instance) {
|
||||
// const Iso14443_4aData* iso14443_4a_data =
|
||||
// nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
|
||||
|
||||
// instance->listener =
|
||||
// nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, iso14443_4a_data);
|
||||
// nfc_listener_start(
|
||||
// instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
|
||||
// }
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
||||
.features = NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_emv,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_emv,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_emv,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_emv,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
5
applications/main/nfc/helpers/protocol_support/emv/emv.h
Normal file
5
applications/main/nfc/helpers/protocol_support/emv/emv.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_emv;
|
||||
182
applications/main/nfc/helpers/protocol_support/emv/emv_render.c
Normal file
182
applications/main/nfc/helpers/protocol_support/emv/emv_render.c
Normal file
@@ -0,0 +1,182 @@
|
||||
#include "emv_render.h"
|
||||
|
||||
#include "../iso14443_4a/iso14443_4a_render.h"
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str) {
|
||||
nfc_render_emv_header(str);
|
||||
nfc_render_emv_uid(
|
||||
data->iso14443_4a_data->iso14443_3a_data->uid,
|
||||
data->iso14443_4a_data->iso14443_3a_data->uid_len,
|
||||
str);
|
||||
|
||||
if(format_type == NfcProtocolFormatTypeFull) nfc_render_emv_extra(data, str);
|
||||
}
|
||||
|
||||
void nfc_render_emv_header(FuriString* str) {
|
||||
furi_string_cat_printf(str, "\e#%s\n", "EMV");
|
||||
}
|
||||
|
||||
void nfc_render_emv_uid(const uint8_t* uid, const uint8_t uid_len, FuriString* str) {
|
||||
if(uid_len == 0) return;
|
||||
|
||||
furi_string_cat_printf(str, "UID: ");
|
||||
|
||||
for(uint8_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(str, "%02X ", uid[i]);
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "\n");
|
||||
}
|
||||
|
||||
void nfc_render_emv_aid(const uint8_t* uid, const uint8_t uid_len, FuriString* str) {
|
||||
if(uid_len == 0) return;
|
||||
|
||||
furi_string_cat_printf(str, "UID: ");
|
||||
|
||||
for(uint8_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(str, "%02X ", uid[i]);
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "\n");
|
||||
}
|
||||
|
||||
void nfc_render_emv_data(const EmvData* data, FuriString* str) {
|
||||
nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str);
|
||||
nfc_render_emv_name(data->emv_application.name, str);
|
||||
}
|
||||
|
||||
void nfc_render_emv_pan(const uint8_t* data, const uint8_t len, FuriString* str) {
|
||||
if(len == 0) return;
|
||||
|
||||
FuriString* card_number = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < len; i++) {
|
||||
if((i % 2 == 0) && (i != 0)) furi_string_cat_printf(card_number, " ");
|
||||
furi_string_cat_printf(card_number, "%02X", data[i]);
|
||||
}
|
||||
|
||||
// Cut padding 'F' from card number
|
||||
furi_string_trim(card_number, "F");
|
||||
furi_string_cat(str, card_number);
|
||||
furi_string_free(card_number);
|
||||
|
||||
furi_string_cat_printf(str, "\n");
|
||||
}
|
||||
|
||||
void nfc_render_emv_expired(const EmvApplication* apl, FuriString* str) {
|
||||
if(apl->exp_month == 0) return;
|
||||
furi_string_cat_printf(str, "Exp: %02X/%02X\n", apl->exp_month, apl->exp_year);
|
||||
}
|
||||
|
||||
void nfc_render_emv_currency(uint16_t cur_code, FuriString* str) {
|
||||
if(!cur_code) return;
|
||||
|
||||
furi_string_cat_printf(str, "Currency code: %04X\n", cur_code);
|
||||
}
|
||||
|
||||
void nfc_render_emv_country(uint16_t country_code, FuriString* str) {
|
||||
if(!country_code) return;
|
||||
|
||||
furi_string_cat_printf(str, "Country code: %04X\n", country_code);
|
||||
}
|
||||
|
||||
void nfc_render_emv_application(const EmvApplication* apl, FuriString* str) {
|
||||
const uint8_t len = apl->aid_len;
|
||||
|
||||
if(!len) {
|
||||
furi_string_cat_printf(str, "No Pay Application found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "AID: ");
|
||||
|
||||
for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%02X", apl->aid[i]);
|
||||
|
||||
furi_string_cat_printf(str, "\n");
|
||||
}
|
||||
|
||||
static void nfc_render_emv_pin_try_counter(uint8_t counter, FuriString* str) {
|
||||
if(counter == 0xff) return;
|
||||
furi_string_cat_printf(str, "PIN try left: %d\n", counter);
|
||||
}
|
||||
|
||||
void nfc_render_emv_transactions(const EmvApplication* apl, FuriString* str) {
|
||||
if(apl->transaction_counter)
|
||||
furi_string_cat_printf(str, "Transactions: %d\n", apl->transaction_counter);
|
||||
if(apl->last_online_atc)
|
||||
furi_string_cat_printf(str, "Last Online ATC: %d\n", apl->last_online_atc);
|
||||
|
||||
const uint8_t len = apl->active_tr;
|
||||
if(!len) {
|
||||
furi_string_cat_printf(str, "No transactions info\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
|
||||
//furi_string_cat_printf(str, "Transactions:\n");
|
||||
for(int i = 0; i < len; i++) {
|
||||
if(!apl->trans[i].amount) continue;
|
||||
// transaction counter
|
||||
furi_string_cat_printf(str, "\e#%d: ", apl->trans[i].atc);
|
||||
|
||||
// Print transaction amount
|
||||
uint8_t* a = (uint8_t*)&apl->trans[i].amount;
|
||||
bool top = true;
|
||||
for(int x = 0; x < 6; x++) {
|
||||
// cents
|
||||
if(x == 5) {
|
||||
furi_string_cat_printf(str, ".%02X", a[x]);
|
||||
break;
|
||||
}
|
||||
if(a[x]) {
|
||||
if(top) {
|
||||
furi_string_cat_printf(str, "%X", a[x]);
|
||||
top = false;
|
||||
} else {
|
||||
furi_string_cat_printf(str, "%02X", a[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(apl->trans[i].currency) {
|
||||
furi_string_set_str(tmp, "UNK");
|
||||
nfc_emv_parser_get_currency_name(storage, apl->trans[i].currency, tmp);
|
||||
furi_string_cat_printf(str, " %s\n", furi_string_get_cstr(tmp));
|
||||
}
|
||||
|
||||
if(apl->trans[i].country) {
|
||||
furi_string_set_str(tmp, "UNK");
|
||||
nfc_emv_parser_get_country_name(storage, apl->trans[i].country, tmp);
|
||||
furi_string_cat_printf(str, "Country: %s\n", furi_string_get_cstr(tmp));
|
||||
}
|
||||
|
||||
if(apl->trans[i].date)
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"%02lx/%02lx/%02lx ",
|
||||
apl->trans[i].date >> 16,
|
||||
(apl->trans[i].date >> 8) & 0xff,
|
||||
apl->trans[i].date & 0xff);
|
||||
|
||||
if(apl->trans[i].time)
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"%02lx:%02lx:%02lx\n",
|
||||
apl->trans[i].time & 0xff,
|
||||
(apl->trans[i].time >> 8) & 0xff,
|
||||
apl->trans[i].time >> 16);
|
||||
}
|
||||
|
||||
furi_string_free(tmp);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
void nfc_render_emv_extra(const EmvData* data, FuriString* str) {
|
||||
nfc_render_emv_application(&data->emv_application, str);
|
||||
|
||||
nfc_render_emv_currency(data->emv_application.currency_code, str);
|
||||
nfc_render_emv_country(data->emv_application.country_code, str);
|
||||
nfc_render_emv_pin_try_counter(data->emv_application.pin_try_counter, str);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/emv/emv.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str);
|
||||
|
||||
void nfc_render_emv_data(const EmvData* data, FuriString* str);
|
||||
|
||||
void nfc_render_emv_pan(const uint8_t* data, const uint8_t len, FuriString* str);
|
||||
|
||||
void nfc_render_emv_name(const char* data, FuriString* str);
|
||||
|
||||
void nfc_render_emv_application(const EmvApplication* data, FuriString* str);
|
||||
|
||||
void nfc_render_emv_extra(const EmvData* data, FuriString* str);
|
||||
|
||||
void nfc_render_emv_expired(const EmvApplication* apl, FuriString* str);
|
||||
|
||||
void nfc_render_emv_country(uint16_t country_code, FuriString* str);
|
||||
|
||||
void nfc_render_emv_currency(uint16_t cur_code, FuriString* str);
|
||||
|
||||
void nfc_render_emv_transactions(const EmvApplication* data, FuriString* str);
|
||||
|
||||
void nfc_render_emv_uid(const uint8_t* uid, const uint8_t uid_len, FuriString* str);
|
||||
|
||||
void nfc_render_emv_header(FuriString* str);
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mf_ultralight/mf_ultralight.h"
|
||||
#include "mf_classic/mf_classic.h"
|
||||
#include "mf_desfire/mf_desfire.h"
|
||||
#include "emv/emv.h"
|
||||
#include "slix/slix.h"
|
||||
#include "st25tb/st25tb.h"
|
||||
|
||||
@@ -41,5 +42,6 @@ const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = {
|
||||
[NfcProtocolMfDesfire] = &nfc_protocol_support_mf_desfire,
|
||||
[NfcProtocolSlix] = &nfc_protocol_support_slix,
|
||||
[NfcProtocolSt25tb] = &nfc_protocol_support_st25tb,
|
||||
[NfcProtocolEmv] = &nfc_protocol_support_emv,
|
||||
/* Add new protocol support implementations here */
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "helpers/mf_ultralight_auth.h"
|
||||
#include "helpers/mf_user_dict.h"
|
||||
#include "helpers/mfkey32_logger.h"
|
||||
#include "helpers/nfc_emv_parser.h"
|
||||
#include "helpers/mf_classic_key_cache.h"
|
||||
#include "helpers/nfc_supported_cards.h"
|
||||
|
||||
|
||||
134
applications/main/nfc/plugins/supported_cards/emv.c
Normal file
134
applications/main/nfc/plugins/supported_cards/emv.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Parser for EMV cards.
|
||||
*
|
||||
* Copyright 2023 Leptoptilos <leptoptilos@icloud.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "core/string.h"
|
||||
#include "furi_hal_rtc.h"
|
||||
#include "helpers/nfc_emv_parser.h"
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
|
||||
#include "protocols/emv/emv.h"
|
||||
#include "protocols/nfc_protocol.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
|
||||
#define TAG "EMV"
|
||||
|
||||
bool emv_get_currency_name(uint16_t cur_code, FuriString* currency_name) {
|
||||
if(!cur_code) return false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool succsess = nfc_emv_parser_get_currency_name(storage, cur_code, currency_name);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return succsess;
|
||||
}
|
||||
|
||||
bool emv_get_country_name(uint16_t country_code, FuriString* country_name) {
|
||||
if(!country_code) return false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool succsess = nfc_emv_parser_get_country_name(storage, country_code, country_name);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return succsess;
|
||||
}
|
||||
|
||||
bool emv_get_aid_name(const EmvApplication* apl, FuriString* aid_name) {
|
||||
const uint8_t len = apl->aid_len;
|
||||
|
||||
if(!len) return false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool succsess = nfc_emv_parser_get_aid_name(storage, apl->aid, len, aid_name);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return succsess;
|
||||
}
|
||||
|
||||
static bool emv_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
furi_assert(device);
|
||||
bool parsed = false;
|
||||
|
||||
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
||||
const EmvApplication app = data->emv_application;
|
||||
|
||||
do {
|
||||
if(app.name_found)
|
||||
furi_string_cat_printf(parsed_data, "\e#%s\n", app.name);
|
||||
else
|
||||
furi_string_cat_printf(parsed_data, "\e#%s\n", "EMV");
|
||||
|
||||
if(app.pan_len) {
|
||||
FuriString* pan = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < app.pan_len; i += 2) {
|
||||
furi_string_cat_printf(pan, "%02X%02X ", app.pan[i], app.pan[i + 1]);
|
||||
}
|
||||
|
||||
// Cut padding 'F' from card number
|
||||
size_t end = furi_string_search_rchar(pan, 'F');
|
||||
if(end) furi_string_left(pan, end);
|
||||
furi_string_cat(parsed_data, pan);
|
||||
furi_string_free(pan);
|
||||
}
|
||||
|
||||
if(app.exp_month | app.exp_year)
|
||||
furi_string_cat_printf(parsed_data, "\nExp: %02X/%02X\n", app.exp_month, app.exp_year);
|
||||
|
||||
FuriString* str = furi_string_alloc();
|
||||
bool storage_readed = emv_get_country_name(app.country_code, str);
|
||||
|
||||
if(storage_readed)
|
||||
furi_string_cat_printf(parsed_data, "Country: %s\n", furi_string_get_cstr(str));
|
||||
|
||||
storage_readed = emv_get_currency_name(app.currency_code, str);
|
||||
if(storage_readed)
|
||||
furi_string_cat_printf(parsed_data, "Currency: %s\n", furi_string_get_cstr(str));
|
||||
|
||||
if(app.pin_try_counter != 0xFF)
|
||||
furi_string_cat_printf(parsed_data, "PIN try left: %d\n", app.pin_try_counter);
|
||||
|
||||
parsed = true;
|
||||
} while(false);
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/* Actual implementation of app<>plugin interface */
|
||||
static const NfcSupportedCardsPlugin emv_plugin = {
|
||||
.protocol = NfcProtocolEmv,
|
||||
.verify = NULL,
|
||||
.read = NULL,
|
||||
.parse = emv_parse,
|
||||
};
|
||||
|
||||
/* Plugin descriptor to comply with basic plugin specification */
|
||||
static const FlipperAppPluginDescriptor emv_plugin_descriptor = {
|
||||
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
|
||||
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
|
||||
.entry_point = &emv_plugin,
|
||||
};
|
||||
|
||||
/* Plugin entry point - must return a pointer to const descriptor */
|
||||
const FlipperAppPluginDescriptor* emv_plugin_ep() {
|
||||
return &emv_plugin_descriptor;
|
||||
}
|
||||
@@ -37,6 +37,8 @@ ADD_SCENE(nfc, mf_ultralight_capture_pass, MfUltralightCapturePass)
|
||||
ADD_SCENE(nfc, mf_desfire_more_info, MfDesfireMoreInfo)
|
||||
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
||||
|
||||
ADD_SCENE(nfc, emv_more_info, EmvMoreInfo)
|
||||
|
||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||
ADD_SCENE(nfc, mf_classic_detect_reader, MfClassicDetectReader)
|
||||
ADD_SCENE(nfc, mf_classic_mfkey_nonces_info, MfClassicMfkeyNoncesInfo)
|
||||
|
||||
74
applications/main/nfc/scenes/nfc_scene_emv_more_info.c
Normal file
74
applications/main/nfc/scenes/nfc_scene_emv_more_info.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
#include "../helpers/protocol_support/nfc_protocol_support_gui_common.h"
|
||||
#include "../helpers/protocol_support/emv/emv_render.h"
|
||||
|
||||
enum {
|
||||
EmvMoreInfoStateMenu,
|
||||
EmvMoreInfoStateItem, // MUST be last, states >= this correspond with submenu index
|
||||
};
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexTransactions,
|
||||
SubmenuIndexDynamic, // dynamic indices start here
|
||||
};
|
||||
|
||||
void nfc_scene_emv_more_info_on_enter(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
text_box_set_font(nfc->text_box, TextBoxFontHex);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Transactions",
|
||||
SubmenuIndexTransactions,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_emv_more_info_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
const uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMoreInfo);
|
||||
const EmvData* data = nfc_device_get_data(nfc->nfc_device, NfcProtocolEmv);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexTransactions) {
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
nfc_render_emv_transactions(&data->emv_application, temp_str);
|
||||
widget_add_text_scroll_element(
|
||||
nfc->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
furi_string_free(temp_str);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager,
|
||||
NfcSceneEmvMoreInfo,
|
||||
EmvMoreInfoStateItem + SubmenuIndexTransactions);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state >= EmvMoreInfoStateItem) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneEmvMoreInfo, EmvMoreInfoStateMenu);
|
||||
} else {
|
||||
// Return directly to the Info scene
|
||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneInfo);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_emv_more_info_on_exit(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
|
||||
// Clear views
|
||||
widget_reset(nfc->widget);
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
||||
Reference in New Issue
Block a user