mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
NFC refactoring (#3050)
"A long time ago in a galaxy far, far away...." we started NFC subsystem refactoring. Starring: - @gornekich - NFC refactoring project lead, architect, senior developer - @gsurkov - architect, senior developer - @RebornedBrain - senior developer Supporting roles: - @skotopes, @DrZlo13, @hedger - general architecture advisors, code review - @Astrrra, @doomwastaken, @Hellitron, @ImagineVagon333 - quality assurance Special thanks: @bettse, @pcunning, @nxv, @noproto, @AloneLiberty and everyone else who has been helping us all this time and contributing valuable knowledges, ideas and source code.
This commit is contained in:
108
applications/main/nfc/helpers/protocol_support/felica/felica.c
Normal file
108
applications/main/nfc/helpers/protocol_support/felica/felica.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "felica.h"
|
||||
#include "felica_render.h"
|
||||
|
||||
#include <nfc/protocols/felica/felica_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_felica(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const FelicaData* data = nfc_device_get_data(device, NfcProtocolFelica);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_felica_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_felica(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolFelica);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const FelicaPollerEvent* felica_event = event.event_data;
|
||||
|
||||
if(felica_event->type == FelicaPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolFelica, 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_felica(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_felica, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_felica(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const FelicaData* data = nfc_device_get_data(device, NfcProtocolFelica);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_felica_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 bool nfc_scene_saved_menu_on_event_felica(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_felica = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_felica,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_felica,
|
||||
.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_felica,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_felica,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_felica;
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "felica_render.h"
|
||||
|
||||
void nfc_render_felica_info(
|
||||
const FelicaData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
furi_string_cat_printf(str, "IDm:");
|
||||
|
||||
for(size_t i = 0; i < FELICA_IDM_SIZE; i++) {
|
||||
furi_string_cat_printf(str, " %02X", data->idm.data[i]);
|
||||
}
|
||||
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
furi_string_cat_printf(str, "\nPMm:");
|
||||
for(size_t i = 0; i < FELICA_PMM_SIZE; ++i) {
|
||||
furi_string_cat_printf(str, " %02X", data->pmm.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/felica/felica.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_felica_info(
|
||||
const FelicaData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "iso14443_3a.h"
|
||||
#include "iso14443_3a_render.h"
|
||||
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso14443_3a(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_3aData* data = nfc_device_get_data(device, NfcProtocolIso14443_3a);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_3a_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_read_poller_callback_iso14443_3a(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3a);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Iso14443_3aPollerEvent* iso14443_3a_event = event.event_data;
|
||||
|
||||
if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolIso14443_3a, 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_iso14443_3a(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso14443_3a, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_iso14443_3a(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_3aData* data = nfc_device_get_data(device, NfcProtocolIso14443_3a);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_3a_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 NfcCommand
|
||||
nfc_scene_emulate_listener_callback_iso14443_3a(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3a);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
Iso14443_3aListenerEvent* iso14443_3a_event = event.event_data;
|
||||
|
||||
if(iso14443_3a_event->type == Iso14443_3aListenerEventTypeReceivedStandardFrame) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_3a_event->data->buffer);
|
||||
i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso14443_3a_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_iso14443_3a(NfcApp* instance) {
|
||||
const Iso14443_3aData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_3a);
|
||||
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_3a, data);
|
||||
nfc_listener_start(
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso14443_3a, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_3a(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureEditUid,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_iso14443_3a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_iso14443_3a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_3a,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_iso14443_3a,
|
||||
.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,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso14443_3a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a;
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "iso14443_3a_render.h"
|
||||
|
||||
void nfc_render_iso14443_3a_format_bytes(FuriString* str, const uint8_t* const data, size_t size) {
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
furi_string_cat_printf(str, " %02X", data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_iso14443_3a_info(
|
||||
const Iso14443_3aData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
const char iso_type = iso14443_3a_supports_iso14443_4(data) ? '4' : '3';
|
||||
furi_string_cat_printf(str, "ISO 14443-%c (NFC-A)\n", iso_type);
|
||||
}
|
||||
|
||||
nfc_render_iso14443_3a_brief(data, str);
|
||||
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
nfc_render_iso14443_3a_extra(data, str);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_iso14443_3a_brief(const Iso14443_3aData* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "UID:");
|
||||
|
||||
nfc_render_iso14443_3a_format_bytes(str, data->uid, data->uid_len);
|
||||
}
|
||||
|
||||
void nfc_render_iso14443_3a_extra(const Iso14443_3aData* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]);
|
||||
furi_string_cat_printf(str, "SAK: %02X", data->sak);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_iso14443_3a_info(
|
||||
const Iso14443_3aData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_iso14443_3a_format_bytes(FuriString* str, const uint8_t* const data, size_t size);
|
||||
|
||||
void nfc_render_iso14443_3a_brief(const Iso14443_3aData* data, FuriString* str);
|
||||
|
||||
void nfc_render_iso14443_3a_extra(const Iso14443_3aData* data, FuriString* str);
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "iso14443_3b.h"
|
||||
#include "iso14443_3b_render.h"
|
||||
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso14443_3b(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_3bData* data = nfc_device_get_data(device, NfcProtocolIso14443_3b);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_3b_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_read_poller_callback_iso14443_3b(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3b);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Iso14443_3bPollerEvent* iso14443_3b_event = event.event_data;
|
||||
|
||||
if(iso14443_3b_event->type == Iso14443_3bPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolIso14443_3b, 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_iso14443_3b(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso14443_3b, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_iso14443_3b(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_3bData* data = nfc_device_get_data(device, NfcProtocolIso14443_3b);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_3b_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);
|
||||
}
|
||||
|
||||
bool nfc_scene_saved_menu_on_event_iso14443_3b_common(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso14443_3b(NfcApp* instance, uint32_t event) {
|
||||
return nfc_scene_saved_menu_on_event_iso14443_3b_common(instance, event);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_iso14443_3b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_iso14443_3b,
|
||||
.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_iso14443_3b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso14443_3b,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b;
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b.h>
|
||||
|
||||
#include "iso14443_3b.h"
|
||||
|
||||
bool nfc_scene_saved_menu_on_event_iso14443_3b_common(NfcApp* instance, uint32_t event);
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "iso14443_3b_render.h"
|
||||
|
||||
void nfc_render_iso14443_3b_info(
|
||||
const Iso14443_3bData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
const char iso_type = iso14443_3b_supports_iso14443_4(data) ? '4' : '3';
|
||||
furi_string_cat_printf(str, "ISO 14443-%c (NFC-B)\n", iso_type);
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "UID:");
|
||||
|
||||
size_t uid_size;
|
||||
const uint8_t* uid = iso14443_3b_get_uid(data, &uid_size);
|
||||
|
||||
for(size_t i = 0; i < uid_size; i++) {
|
||||
furi_string_cat_printf(str, " %02X", uid[i]);
|
||||
}
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
|
||||
furi_string_cat_printf(str, "\n\e#Protocol info\n");
|
||||
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRateBoth106Kbit)) {
|
||||
furi_string_cat(str, "Bit rate PICC <-> PCD:\n 106 kBit/s supported\n");
|
||||
} else {
|
||||
furi_string_cat(str, "Bit rate PICC -> PCD:\n");
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePiccToPcd212Kbit)) {
|
||||
furi_string_cat(str, " 212 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePiccToPcd424Kbit)) {
|
||||
furi_string_cat(str, " 424 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePiccToPcd848Kbit)) {
|
||||
furi_string_cat(str, " 848 kBit/s supported\n");
|
||||
}
|
||||
|
||||
furi_string_cat(str, "Bit rate PICC <- PCD:\n");
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePcdToPicc212Kbit)) {
|
||||
furi_string_cat(str, " 212 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePcdToPicc424Kbit)) {
|
||||
furi_string_cat(str, " 424 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_3b_supports_bit_rate(data, Iso14443_3bBitRatePcdToPicc848Kbit)) {
|
||||
furi_string_cat(str, " 848 kBit/s supported\n");
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_cat(str, "Max frame size: ");
|
||||
|
||||
const uint16_t max_frame_size = iso14443_3b_get_frame_size_max(data);
|
||||
if(max_frame_size != 0) {
|
||||
furi_string_cat_printf(str, "%u bytes\n", max_frame_size);
|
||||
} else {
|
||||
furi_string_cat(str, "? (RFU)\n");
|
||||
}
|
||||
|
||||
const double fwt = iso14443_3b_get_fwt_fc_max(data) / 13.56e6;
|
||||
furi_string_cat_printf(str, "Max waiting time: %4.2g s\n", fwt);
|
||||
|
||||
const char* nad_support_str =
|
||||
iso14443_3b_supports_frame_option(data, Iso14443_3bFrameOptionNad) ? "" : "not ";
|
||||
furi_string_cat_printf(str, "NAD: %ssupported\n", nad_support_str);
|
||||
|
||||
const char* cid_support_str =
|
||||
iso14443_3b_supports_frame_option(data, Iso14443_3bFrameOptionCid) ? "" : "not ";
|
||||
furi_string_cat_printf(str, "CID: %ssupported", cid_support_str);
|
||||
|
||||
furi_string_cat_printf(str, "\n\e#Application data\nRaw:");
|
||||
|
||||
size_t app_data_size;
|
||||
const uint8_t* app_data = iso14443_3b_get_application_data(data, &app_data_size);
|
||||
for(size_t i = 0; i < app_data_size; ++i) {
|
||||
furi_string_cat_printf(str, " %02X", app_data[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_iso14443_3b_info(
|
||||
const Iso14443_3bData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "iso14443_4a.h"
|
||||
#include "iso14443_4a_render.h"
|
||||
|
||||
#include <nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
|
||||
#include <nfc/protocols/iso14443_4a/iso14443_4a_listener.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso14443_4a(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_4aData* data = nfc_device_get_data(device, NfcProtocolIso14443_4a);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_4a_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_read_poller_callback_iso14443_4a(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_4a);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
|
||||
|
||||
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolIso14443_4a, 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_iso14443_4a(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso14443_4a, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_iso14443_4a(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_4aData* data = nfc_device_get_data(device, NfcProtocolIso14443_4a);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_4a_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_saved_menu_on_enter_iso14443_4a(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
|
||||
NfcCommand nfc_scene_emulate_listener_callback_iso14443_4a(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_4a);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
Iso14443_4aListenerEvent* iso14443_4a_event = event.event_data;
|
||||
|
||||
if(iso14443_4a_event->type == Iso14443_4aListenerEventTypeReceivedData) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer);
|
||||
i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso14443_4a_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_iso14443_4a(NfcApp* instance) {
|
||||
const Iso14443_4aData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
|
||||
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, data);
|
||||
nfc_listener_start(
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_4a(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureEditUid,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_4a,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_saved_menu_on_enter_iso14443_4a,
|
||||
.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,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a;
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_4a/iso14443_4a.h>
|
||||
|
||||
#include "iso14443_4a.h"
|
||||
|
||||
NfcCommand nfc_scene_emulate_listener_callback_iso14443_4a(NfcGenericEvent event, void* context);
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "iso14443_4a_render.h"
|
||||
|
||||
#include "../iso14443_3a/iso14443_3a_render.h"
|
||||
|
||||
void nfc_render_iso14443_4a_info(
|
||||
const Iso14443_4aData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_4a_brief(data, str);
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
|
||||
nfc_render_iso14443_4a_extra(data, str);
|
||||
}
|
||||
|
||||
void nfc_render_iso14443_4a_brief(const Iso14443_4aData* data, FuriString* str) {
|
||||
nfc_render_iso14443_3a_brief(iso14443_4a_get_base_data(data), str);
|
||||
}
|
||||
|
||||
void nfc_render_iso14443_4a_extra(const Iso14443_4aData* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "\n\e#Protocol info\n");
|
||||
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRateBoth106Kbit)) {
|
||||
furi_string_cat(str, "Bit rate PICC <-> PCD:\n 106 kBit/s supported\n");
|
||||
} else {
|
||||
furi_string_cat(str, "Bit rate PICC -> PCD:\n");
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePiccToPcd212Kbit)) {
|
||||
furi_string_cat(str, " 212 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePiccToPcd424Kbit)) {
|
||||
furi_string_cat(str, " 424 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePiccToPcd848Kbit)) {
|
||||
furi_string_cat(str, " 848 kBit/s supported\n");
|
||||
}
|
||||
|
||||
furi_string_cat(str, "Bit rate PICC <- PCD:\n");
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePcdToPicc212Kbit)) {
|
||||
furi_string_cat(str, " 212 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePcdToPicc424Kbit)) {
|
||||
furi_string_cat(str, " 424 kBit/s supported\n");
|
||||
}
|
||||
if(iso14443_4a_supports_bit_rate(data, Iso14443_4aBitRatePcdToPicc848Kbit)) {
|
||||
furi_string_cat(str, " 848 kBit/s supported\n");
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_cat(str, "Max frame size: ");
|
||||
|
||||
const uint16_t max_frame_size = iso14443_4a_get_frame_size_max(data);
|
||||
if(max_frame_size != 0) {
|
||||
furi_string_cat_printf(str, "%u bytes\n", max_frame_size);
|
||||
} else {
|
||||
furi_string_cat(str, "? (RFU)\n");
|
||||
}
|
||||
|
||||
const uint32_t fwt_fc = iso14443_4a_get_fwt_fc_max(data);
|
||||
if(fwt_fc != 0) {
|
||||
furi_string_cat_printf(str, "Max waiting time: %4.2g s\n", (double)(fwt_fc / 13.56e6));
|
||||
}
|
||||
|
||||
const char* nad_support_str =
|
||||
iso14443_4a_supports_frame_option(data, Iso14443_4aFrameOptionNad) ? "" : "not ";
|
||||
furi_string_cat_printf(str, "NAD: %ssupported\n", nad_support_str);
|
||||
|
||||
const char* cid_support_str =
|
||||
iso14443_4a_supports_frame_option(data, Iso14443_4aFrameOptionCid) ? "" : "not ";
|
||||
furi_string_cat_printf(str, "CID: %ssupported", cid_support_str);
|
||||
|
||||
uint32_t hist_bytes_count;
|
||||
const uint8_t* hist_bytes = iso14443_4a_get_historical_bytes(data, &hist_bytes_count);
|
||||
|
||||
if(hist_bytes_count > 0) {
|
||||
furi_string_cat_printf(str, "\n\e#Historical bytes\nRaw:");
|
||||
|
||||
for(size_t i = 0; i < hist_bytes_count; ++i) {
|
||||
furi_string_cat_printf(str, " %02X", hist_bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_cat(str, "\n\e#ISO14443-3A data");
|
||||
nfc_render_iso14443_3a_extra(iso14443_4a_get_base_data(data), str);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_4a/iso14443_4a.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_iso14443_4a_info(
|
||||
const Iso14443_4aData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_iso14443_4a_brief(const Iso14443_4aData* data, FuriString* str);
|
||||
|
||||
void nfc_render_iso14443_4a_extra(const Iso14443_4aData* data, FuriString* str);
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "iso14443_4b.h"
|
||||
#include "iso14443_4b_render.h"
|
||||
|
||||
#include <nfc/protocols/iso14443_4b/iso14443_4b_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
#include "../iso14443_3b/iso14443_3b_i.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_4bData* data = nfc_device_get_data(device, NfcProtocolIso14443_4b);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_4b_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_read_poller_callback_iso14443_4b(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_4b);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Iso14443_4bPollerEvent* iso14443_4b_event = event.event_data;
|
||||
|
||||
if(iso14443_4b_event->type == Iso14443_4bPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolIso14443_4b, 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_iso14443_4b(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso14443_4b, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso14443_4bData* data = nfc_device_get_data(device, NfcProtocolIso14443_4b);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso14443_4b_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_saved_menu_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_4b(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso14443_4b(NfcApp* instance, uint32_t event) {
|
||||
return nfc_scene_saved_menu_on_event_iso14443_3b_common(instance, event);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_iso14443_4b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_iso14443_4b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_4b,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_iso14443_4b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_saved_menu_on_enter_iso14443_4b,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso14443_4b,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b;
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "iso14443_4b_render.h"
|
||||
|
||||
#include "../iso14443_3b/iso14443_3b_render.h"
|
||||
|
||||
void nfc_render_iso14443_4b_info(
|
||||
const Iso14443_4bData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_3b_info(iso14443_4b_get_base_data(data), format_type, str);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_4b/iso14443_4b.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_iso14443_4b_info(
|
||||
const Iso14443_4bData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "iso15693_3.h"
|
||||
#include "iso15693_3_render.h"
|
||||
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3_poller.h>
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3_listener.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso15693_3(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso15693_3Data* data = nfc_device_get_data(device, NfcProtocolIso15693_3);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso15693_3_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_iso15693_3(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso15693_3);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Iso15693_3PollerEvent* iso15693_3_event = event.event_data;
|
||||
|
||||
if(iso15693_3_event->type == Iso15693_3PollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolIso15693_3, 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_iso15693_3(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso15693_3, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_iso15693_3(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Iso15693_3Data* data = nfc_device_get_data(device, NfcProtocolIso15693_3);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_iso15693_3_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 NfcCommand
|
||||
nfc_scene_emulate_listener_callback_iso15693_3(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolIso15693_3);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
Iso15693_3ListenerEvent* iso15693_3_event = event.event_data;
|
||||
|
||||
if(iso15693_3_event->type == Iso15693_3ListenerEventTypeCustomCommand) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso15693_3_event->data->buffer); i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso15693_3_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_iso15693_3(NfcApp* instance) {
|
||||
const Iso15693_3Data* data = nfc_device_get_data(instance->nfc_device, NfcProtocolIso15693_3);
|
||||
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolIso15693_3, data);
|
||||
nfc_listener_start(
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso15693_3, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso15693_3(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureEditUid,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_iso15693_3,
|
||||
.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_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso15693_3,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_iso15693_3;
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "iso15693_3_render.h"
|
||||
|
||||
#define NFC_RENDER_ISO15693_3_MAX_BYTES (128U)
|
||||
|
||||
void nfc_render_iso15693_3_info(
|
||||
const Iso15693_3Data* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
furi_string_cat(str, "ISO15693-3 (NFC-V)\n");
|
||||
}
|
||||
|
||||
nfc_render_iso15693_3_brief(data, str);
|
||||
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
nfc_render_iso15693_3_extra(data, str);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_iso15693_3_brief(const Iso15693_3Data* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "UID:");
|
||||
|
||||
size_t uid_len;
|
||||
const uint8_t* uid = iso15693_3_get_uid(data, &uid_len);
|
||||
|
||||
for(size_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(str, " %02X", uid[i]);
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_MEMORY) {
|
||||
const uint16_t block_count = iso15693_3_get_block_count(data);
|
||||
const uint8_t block_size = iso15693_3_get_block_size(data);
|
||||
|
||||
furi_string_cat_printf(str, "Memory: %u bytes\n", block_count * block_size);
|
||||
furi_string_cat_printf(str, "(%u blocks x %u bytes)", block_count, block_size);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_iso15693_3_extra(const Iso15693_3Data* data, FuriString* str) {
|
||||
furi_string_cat(str, "\n\e#General info\n");
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_DSFID) {
|
||||
furi_string_cat_printf(str, "DSFID: %02X\n", data->system_info.ic_ref);
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_AFI) {
|
||||
furi_string_cat_printf(str, "AFI: %02X\n", data->system_info.afi);
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_IC_REF) {
|
||||
furi_string_cat_printf(str, "IC Reference: %02X\n", data->system_info.ic_ref);
|
||||
}
|
||||
|
||||
furi_string_cat(str, "\e#Lock bits\n");
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_DSFID) {
|
||||
furi_string_cat_printf(
|
||||
str, "DSFID: %s locked\n", data->settings.lock_bits.dsfid ? "" : "not");
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_AFI) {
|
||||
furi_string_cat_printf(
|
||||
str, "AFI: %s locked\n", data->settings.lock_bits.dsfid ? "" : "not");
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_MEMORY) {
|
||||
furi_string_cat(str, "\e#Memory data\n\e*--------------------\n");
|
||||
|
||||
const uint16_t block_count = iso15693_3_get_block_count(data);
|
||||
const uint8_t block_size = iso15693_3_get_block_size(data);
|
||||
const uint16_t display_block_count =
|
||||
MIN(NFC_RENDER_ISO15693_3_MAX_BYTES / block_size, block_count);
|
||||
|
||||
for(uint32_t i = 0; i < display_block_count; ++i) {
|
||||
furi_string_cat(str, "\e*");
|
||||
|
||||
const uint8_t* block_data = iso15693_3_get_block_data(data, i);
|
||||
for(uint32_t j = 0; j < block_size; ++j) {
|
||||
furi_string_cat_printf(str, "%02X ", block_data[j]);
|
||||
}
|
||||
|
||||
const char* lock_str = iso15693_3_is_block_locked(data, i) ? "[LOCK]" : "";
|
||||
furi_string_cat_printf(str, "| %s\n", lock_str);
|
||||
}
|
||||
|
||||
if(block_count != display_block_count) {
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"(Data is too big. Showing only the first %u bytes.)",
|
||||
display_block_count * block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_iso15693_3_info(
|
||||
const Iso15693_3Data* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_iso15693_3_brief(const Iso15693_3Data* data, FuriString* str);
|
||||
|
||||
void nfc_render_iso15693_3_extra(const Iso15693_3Data* data, FuriString* str);
|
||||
@@ -0,0 +1,252 @@
|
||||
#include "mf_classic.h"
|
||||
#include "mf_classic_render.h"
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
#define TAG "MfClassicApp"
|
||||
|
||||
enum {
|
||||
SubmenuIndexDetectReader = SubmenuIndexCommonMax,
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexUpdate,
|
||||
};
|
||||
|
||||
static void nfc_scene_info_on_enter_mf_classic(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_mf_classic_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_mf_classic(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfClassicData* mfc_data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
||||
|
||||
furi_string_reset(instance->text_box_store);
|
||||
nfc_render_mf_classic_dump(mfc_data, instance->text_box_store);
|
||||
|
||||
text_box_set_font(instance->text_box, TextBoxFontHex);
|
||||
text_box_set_text(instance->text_box, furi_string_get_cstr(instance->text_box_store));
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_mf_classic(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolMfClassic);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const MfClassicPollerEvent* mfc_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(mfc_event->type == MfClassicPollerEventTypeRequestMode) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfClassic, nfc_poller_get_data(instance->poller));
|
||||
size_t uid_len = 0;
|
||||
const uint8_t* uid = nfc_device_get_uid(instance->nfc_device, &uid_len);
|
||||
if(mf_classic_key_cache_load(instance->mfc_key_cache, uid, uid_len)) {
|
||||
FURI_LOG_I(TAG, "Key cache found");
|
||||
mfc_event->data->poller_mode.mode = MfClassicPollerModeRead;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key cache not found");
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerIncomplete);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeRequestReadSector) {
|
||||
uint8_t sector_num = 0;
|
||||
MfClassicKey key = {};
|
||||
MfClassicKeyType key_type = MfClassicKeyTypeA;
|
||||
if(mf_classic_key_cahce_get_next_key(
|
||||
instance->mfc_key_cache, §or_num, &key, &key_type)) {
|
||||
mfc_event->data->read_sector_request_data.sector_num = sector_num;
|
||||
mfc_event->data->read_sector_request_data.key = key;
|
||||
mfc_event->data->read_sector_request_data.key_type = key_type;
|
||||
mfc_event->data->read_sector_request_data.key_provided = true;
|
||||
} else {
|
||||
mfc_event->data->read_sector_request_data.key_provided = false;
|
||||
}
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfClassic, nfc_poller_get_data(instance->poller));
|
||||
const MfClassicData* mfc_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
NfcCustomEvent custom_event = mf_classic_is_card_read(mfc_data) ?
|
||||
NfcCustomEventPollerSuccess :
|
||||
NfcCustomEventPollerIncomplete;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, custom_event);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_mf_classic(NfcApp* instance) {
|
||||
mf_classic_key_cache_reset(instance->mfc_key_cache);
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_classic, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_on_event_mf_classic(NfcApp* instance, uint32_t event) {
|
||||
if(event == NfcCustomEventPollerIncomplete) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
const MfClassicData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
|
||||
if(!mf_classic_is_card_read(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Detect Reader",
|
||||
SubmenuIndexDetectReader,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_mf_classic(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_mf_classic_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_saved_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
const MfClassicData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
|
||||
if(!mf_classic_is_card_read(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Detect Reader",
|
||||
SubmenuIndexDetectReader,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write to Initial Card",
|
||||
SubmenuIndexWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Update from Initial Card",
|
||||
SubmenuIndexUpdate,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_mf_classic(NfcApp* instance) {
|
||||
const MfClassicData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolMfClassic, data);
|
||||
nfc_listener_start(instance->listener, NULL, NULL);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_mf_classic(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexDetectReader) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
dolphin_deed(DolphinDeedNfcDetectReader);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_mf_classic(NfcApp* instance, uint32_t event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event == SubmenuIndexDetectReader) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
consumed = true;
|
||||
} else if(event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicWriteInitial);
|
||||
consumed = true;
|
||||
} else if(event == SubmenuIndexUpdate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicUpdateInitial);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static bool nfc_scene_save_name_on_event_mf_classic(NfcApp* instance, uint32_t event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event == NfcCustomEventTextInputDone) {
|
||||
mf_classic_key_cache_save(
|
||||
instance->mfc_key_cache,
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic));
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_classic = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_mf_classic,
|
||||
.on_event = nfc_scene_read_on_event_mf_classic,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_read_menu_on_enter_mf_classic,
|
||||
.on_event = nfc_scene_read_menu_on_event_mf_classic,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_saved_menu_on_enter_mf_classic,
|
||||
.on_event = nfc_scene_saved_menu_on_event_mf_classic,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_save_name_on_event_mf_classic,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_mf_classic;
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "mf_classic_render.h"
|
||||
|
||||
#include "../iso14443_3a/iso14443_3a_render.h"
|
||||
|
||||
void nfc_render_mf_classic_info(
|
||||
const MfClassicData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_3a_info(data->iso14443_3a_data, format_type, str);
|
||||
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found);
|
||||
|
||||
furi_string_cat_printf(str, "\nKeys Found: %u/%u", keys_found, keys_total);
|
||||
furi_string_cat_printf(str, "\nSectors Read: %u/%u", sectors_read, sectors_total);
|
||||
}
|
||||
|
||||
void nfc_render_mf_classic_dump(const MfClassicData* data, FuriString* str) {
|
||||
uint16_t total_blocks = mf_classic_get_total_block_num(data->type);
|
||||
|
||||
for(size_t i = 0; i < total_blocks; i++) {
|
||||
for(size_t j = 0; j < sizeof(MfClassicBlock); j += 2) {
|
||||
furi_string_cat_printf(
|
||||
str, "%02X%02X ", data->block[i].data[j], data->block[i].data[j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_mf_classic_info(
|
||||
const MfClassicData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_mf_classic_dump(const MfClassicData* data, FuriString* str);
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "mf_desfire.h"
|
||||
#include "mf_desfire_render.h"
|
||||
|
||||
#include <nfc/protocols/mf_desfire/mf_desfire_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_mf_desfire(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfDesfireData* data = nfc_device_get_data(device, NfcProtocolMfDesfire);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_mf_desfire_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_mf_desfire(NfcApp* instance) {
|
||||
// Jump to advanced scene right away
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfDesfireMoreInfo);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_mf_desfire(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolMfDesfire);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const MfDesfirePollerEvent* mf_desfire_event = event.event_data;
|
||||
|
||||
if(mf_desfire_event->type == MfDesfirePollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfDesfire, 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_mf_desfire(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_desfire, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_mf_desfire(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfDesfireData* data = nfc_device_get_data(device, NfcProtocolMfDesfire);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_mf_desfire_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_mf_desfire(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_mf_desfire = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_mf_desfire,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_mf_desfire,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_mf_desfire,
|
||||
.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_mf_desfire,
|
||||
.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,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_desfire,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_mf_desfire;
|
||||
@@ -0,0 +1,249 @@
|
||||
#include "mf_desfire_render.h"
|
||||
|
||||
#include "../iso14443_4a/iso14443_4a_render.h"
|
||||
|
||||
void nfc_render_mf_desfire_info(
|
||||
const MfDesfireData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_4a_brief(mf_desfire_get_base_data(data), str);
|
||||
|
||||
const uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1);
|
||||
const uint32_t bytes_free = data->free_memory.is_present ? data->free_memory.bytes_free : 0;
|
||||
|
||||
furi_string_cat_printf(str, "\n%lu", bytes_total);
|
||||
|
||||
if(data->version.sw_storage & 1) {
|
||||
furi_string_push_back(str, '+');
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, " bytes, %lu bytes free\n", bytes_free);
|
||||
|
||||
const uint32_t app_count = simple_array_get_count(data->applications);
|
||||
uint32_t file_count = 0;
|
||||
|
||||
for(uint32_t i = 0; i < app_count; ++i) {
|
||||
const MfDesfireApplication* app = simple_array_cget(data->applications, i);
|
||||
file_count += simple_array_get_count(app->file_ids);
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "%lu Application%s", app_count, app_count != 1 ? "s" : "");
|
||||
furi_string_cat_printf(str, ", %lu File%s", file_count, file_count != 1 ? "s" : "");
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
|
||||
furi_string_cat(str, "\n\e#ISO14443-4 data");
|
||||
nfc_render_iso14443_4a_extra(mf_desfire_get_base_data(data), str);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_data(const MfDesfireData* data, FuriString* str) {
|
||||
nfc_render_mf_desfire_version(&data->version, str);
|
||||
nfc_render_mf_desfire_free_memory(&data->free_memory, str);
|
||||
nfc_render_mf_desfire_key_settings(&data->master_key_settings, str);
|
||||
|
||||
for(uint32_t i = 0; i < simple_array_get_count(data->master_key_versions); ++i) {
|
||||
nfc_render_mf_desfire_key_version(simple_array_cget(data->master_key_versions, i), i, str);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_version(const MfDesfireVersion* data, FuriString* str) {
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"hw %02x type %02x sub %02x\n"
|
||||
" maj %02x min %02x\n"
|
||||
" size %02x proto %02x\n",
|
||||
data->hw_vendor,
|
||||
data->hw_type,
|
||||
data->hw_subtype,
|
||||
data->hw_major,
|
||||
data->hw_minor,
|
||||
data->hw_storage,
|
||||
data->hw_proto);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"sw %02x type %02x sub %02x\n"
|
||||
" maj %02x min %02x\n"
|
||||
" size %02x proto %02x\n",
|
||||
data->sw_vendor,
|
||||
data->sw_type,
|
||||
data->sw_subtype,
|
||||
data->sw_major,
|
||||
data->sw_minor,
|
||||
data->sw_storage,
|
||||
data->sw_proto);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"batch %02x:%02x:%02x:%02x:%02x\n"
|
||||
"week %d year %d\n",
|
||||
data->batch[0],
|
||||
data->batch[1],
|
||||
data->batch[2],
|
||||
data->batch[3],
|
||||
data->batch[4],
|
||||
data->prod_week,
|
||||
data->prod_year);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_free_memory(const MfDesfireFreeMemory* data, FuriString* str) {
|
||||
if(data->is_present) {
|
||||
furi_string_cat_printf(str, "freeMem %lu\n", data->bytes_free);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_key_settings(const MfDesfireKeySettings* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "changeKeyID %d\n", data->change_key_id);
|
||||
furi_string_cat_printf(str, "configChangeable %d\n", data->is_config_changeable);
|
||||
furi_string_cat_printf(str, "freeCreateDelete %d\n", data->is_free_create_delete);
|
||||
furi_string_cat_printf(str, "freeDirectoryList %d\n", data->is_free_directory_list);
|
||||
furi_string_cat_printf(str, "masterChangeable %d\n", data->is_master_key_changeable);
|
||||
|
||||
if(data->flags) {
|
||||
furi_string_cat_printf(str, "flags %d\n", data->flags);
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "maxKeys %d\n", data->max_keys);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_key_version(
|
||||
const MfDesfireKeyVersion* data,
|
||||
uint32_t index,
|
||||
FuriString* str) {
|
||||
furi_string_cat_printf(str, "key %lu version %u\n", index, *data);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_application_id(const MfDesfireApplicationId* data, FuriString* str) {
|
||||
const uint8_t* app_id = data->data;
|
||||
furi_string_cat_printf(str, "Application %02x%02x%02x\n", app_id[0], app_id[1], app_id[2]);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_application(const MfDesfireApplication* data, FuriString* str) {
|
||||
nfc_render_mf_desfire_key_settings(&data->key_settings, str);
|
||||
|
||||
for(uint32_t i = 0; i < simple_array_get_count(data->key_versions); ++i) {
|
||||
nfc_render_mf_desfire_key_version(simple_array_cget(data->key_versions, i), i, str);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_file_id(const MfDesfireFileId* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "File %d\n", *data);
|
||||
}
|
||||
|
||||
void nfc_render_mf_desfire_file_settings_data(
|
||||
const MfDesfireFileSettings* settings,
|
||||
const MfDesfireFileData* data,
|
||||
FuriString* str) {
|
||||
const char* type;
|
||||
switch(settings->type) {
|
||||
case MfDesfireFileTypeStandard:
|
||||
type = "standard";
|
||||
break;
|
||||
case MfDesfireFileTypeBackup:
|
||||
type = "backup";
|
||||
break;
|
||||
case MfDesfireFileTypeValue:
|
||||
type = "value";
|
||||
break;
|
||||
case MfDesfireFileTypeLinearRecord:
|
||||
type = "linear";
|
||||
break;
|
||||
case MfDesfireFileTypeCyclicRecord:
|
||||
type = "cyclic";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
}
|
||||
|
||||
const char* comm;
|
||||
switch(settings->comm) {
|
||||
case MfDesfireFileCommunicationSettingsPlaintext:
|
||||
comm = "plain";
|
||||
break;
|
||||
case MfDesfireFileCommunicationSettingsAuthenticated:
|
||||
comm = "auth";
|
||||
break;
|
||||
case MfDesfireFileCommunicationSettingsEnciphered:
|
||||
comm = "enciphered";
|
||||
break;
|
||||
default:
|
||||
comm = "unknown";
|
||||
}
|
||||
|
||||
furi_string_cat_printf(str, "%s %s\n", type, comm);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"r %d w %d rw %d c %d\n",
|
||||
settings->access_rights >> 12 & 0xF,
|
||||
settings->access_rights >> 8 & 0xF,
|
||||
settings->access_rights >> 4 & 0xF,
|
||||
settings->access_rights & 0xF);
|
||||
|
||||
uint32_t record_count = 1;
|
||||
uint32_t record_size = 0;
|
||||
|
||||
switch(settings->type) {
|
||||
case MfDesfireFileTypeStandard:
|
||||
case MfDesfireFileTypeBackup:
|
||||
record_size = settings->data.size;
|
||||
furi_string_cat_printf(str, "size %lu\n", record_size);
|
||||
break;
|
||||
case MfDesfireFileTypeValue:
|
||||
furi_string_cat_printf(
|
||||
str, "lo %lu hi %lu\n", settings->value.lo_limit, settings->value.hi_limit);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"limit %lu enabled %d\n",
|
||||
settings->value.limited_credit_value,
|
||||
settings->value.limited_credit_enabled);
|
||||
break;
|
||||
case MfDesfireFileTypeLinearRecord:
|
||||
case MfDesfireFileTypeCyclicRecord:
|
||||
record_count = settings->record.cur;
|
||||
record_size = settings->record.size;
|
||||
furi_string_cat_printf(str, "size %lu\n", record_size);
|
||||
furi_string_cat_printf(str, "num %lu max %lu\n", record_count, settings->record.max);
|
||||
break;
|
||||
}
|
||||
|
||||
if(simple_array_get_count(data->data) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t rec = 0; rec < record_count; rec++) {
|
||||
furi_string_cat_printf(str, "record %lu\n", rec);
|
||||
for(uint32_t ch = 0; ch < record_size; ch += 4) {
|
||||
furi_string_cat_printf(str, "%03lx|", ch);
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
if(ch + i < record_size) {
|
||||
const uint32_t data_index = rec * record_size + ch + i;
|
||||
const uint8_t data_byte =
|
||||
*(const uint8_t*)simple_array_cget(data->data, data_index);
|
||||
furi_string_cat_printf(str, "%02x ", data_byte);
|
||||
} else {
|
||||
furi_string_cat_printf(str, " ");
|
||||
}
|
||||
}
|
||||
for(uint32_t i = 0; i < 4 && ch + i < record_size; i++) {
|
||||
const uint32_t data_index = rec * record_size + ch + i;
|
||||
const uint8_t data_byte =
|
||||
*(const uint8_t*)simple_array_cget(data->data, data_index);
|
||||
if(isprint(data_byte)) {
|
||||
furi_string_cat_printf(str, "%c", data_byte);
|
||||
} else {
|
||||
furi_string_cat_printf(str, ".");
|
||||
}
|
||||
}
|
||||
furi_string_push_back(str, '\n');
|
||||
}
|
||||
furi_string_push_back(str, '\n');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/mf_desfire/mf_desfire.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_mf_desfire_info(
|
||||
const MfDesfireData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_data(const MfDesfireData* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_version(const MfDesfireVersion* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_free_memory(const MfDesfireFreeMemory* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_key_settings(const MfDesfireKeySettings* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_key_version(
|
||||
const MfDesfireKeyVersion* data,
|
||||
uint32_t index,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_application_id(const MfDesfireApplicationId* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_application(const MfDesfireApplication* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_file_id(const MfDesfireFileId* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_desfire_file_settings_data(
|
||||
const MfDesfireFileSettings* settings,
|
||||
const MfDesfireFileData* data,
|
||||
FuriString* str);
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "mf_ultralight.h"
|
||||
#include "mf_ultralight_render.h"
|
||||
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
enum {
|
||||
SubmenuIndexUnlock = SubmenuIndexCommonMax,
|
||||
SubmenuIndexUnlockByReader,
|
||||
SubmenuIndexUnlockByPassword,
|
||||
};
|
||||
|
||||
static void nfc_scene_info_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfUltralightData* data = nfc_device_get_data(device, NfcProtocolMfUltralight);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_mf_ultralight_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_mf_ultralight(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfUltralightData* mfu = nfc_device_get_data(device, NfcProtocolMfUltralight);
|
||||
|
||||
furi_string_reset(instance->text_box_store);
|
||||
nfc_render_mf_ultralight_dump(mfu, instance->text_box_store);
|
||||
|
||||
text_box_set_font(instance->text_box, TextBoxFontHex);
|
||||
text_box_set_text(instance->text_box, furi_string_get_cstr(instance->text_box_store));
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_read_poller_callback_mf_ultralight(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolMfUltralight);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const MfUltralightPollerEvent* mf_ultralight_event = event.event_data;
|
||||
|
||||
if(mf_ultralight_event->type == MfUltralightPollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
return NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
|
||||
const MfUltralightData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
if(instance->mf_ul_auth->type == MfUltralightAuthTypeXiaomi) {
|
||||
if(mf_ultralight_generate_xiaomi_pass(
|
||||
instance->mf_ul_auth,
|
||||
data->iso14443_3a_data->uid,
|
||||
data->iso14443_3a_data->uid_len)) {
|
||||
mf_ultralight_event->data->auth_context.skip_auth = false;
|
||||
}
|
||||
} else if(instance->mf_ul_auth->type == MfUltralightAuthTypeAmiibo) {
|
||||
if(mf_ultralight_generate_amiibo_pass(
|
||||
instance->mf_ul_auth,
|
||||
data->iso14443_3a_data->uid,
|
||||
data->iso14443_3a_data->uid_len)) {
|
||||
mf_ultralight_event->data->auth_context.skip_auth = false;
|
||||
}
|
||||
} else if(
|
||||
instance->mf_ul_auth->type == MfUltralightAuthTypeManual ||
|
||||
instance->mf_ul_auth->type == MfUltralightAuthTypeReader) {
|
||||
mf_ultralight_event->data->auth_context.skip_auth = false;
|
||||
} else {
|
||||
mf_ultralight_event->data->auth_context.skip_auth = true;
|
||||
}
|
||||
if(!mf_ultralight_event->data->auth_context.skip_auth) {
|
||||
mf_ultralight_event->data->auth_context.password = instance->mf_ul_auth->password;
|
||||
}
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthSuccess) {
|
||||
instance->mf_ul_auth->pack = mf_ultralight_event->data->auth_context.pack;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_ultralight, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
|
||||
const MfUltralightData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
|
||||
if(!mf_ultralight_is_all_data_read(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Unlock",
|
||||
SubmenuIndexUnlock,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfUltralightData* data = nfc_device_get_data(device, NfcProtocolMfUltralight);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
|
||||
bool unlocked =
|
||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneMfUltralightUnlockWarn);
|
||||
if(unlocked) {
|
||||
nfc_render_mf_ultralight_pwd_pack(data, temp_str);
|
||||
} else {
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
|
||||
nfc_render_mf_ultralight_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||
}
|
||||
|
||||
mf_ultralight_auth_reset(instance->mf_ul_auth);
|
||||
|
||||
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_mf_ultralight(NfcApp* instance) {
|
||||
const MfUltralightData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolMfUltralight, data);
|
||||
nfc_listener_start(instance->listener, NULL, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_scene_read_and_saved_menu_on_event_mf_ultralight(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_read_and_saved_menu_on_enter_mf_ultralight,
|
||||
.on_event = nfc_scene_read_and_saved_menu_on_event_mf_ultralight,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
.on_enter = nfc_scene_read_success_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_read_and_saved_menu_on_enter_mf_ultralight,
|
||||
.on_event = nfc_scene_read_and_saved_menu_on_event_mf_ultralight,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight;
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "mf_ultralight_render.h"
|
||||
|
||||
#include "../iso14443_3a/iso14443_3a_render.h"
|
||||
|
||||
static void nfc_render_mf_ultralight_pages_count(const MfUltralightData* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "\nPages Read: %u/%u", data->pages_read, data->pages_total);
|
||||
if(data->pages_read != data->pages_total) {
|
||||
furi_string_cat_printf(str, "\nPassword-protected pages!");
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_mf_ultralight_pwd_pack(const MfUltralightData* data, FuriString* str) {
|
||||
bool all_pages = mf_ultralight_is_all_data_read(data);
|
||||
furi_string_cat_printf(str, "\e#%s pages unlocked!", all_pages ? "All" : "Not all");
|
||||
|
||||
MfUltralightConfigPages* config;
|
||||
mf_ultralight_get_config_page(data, &config);
|
||||
|
||||
furi_string_cat_printf(str, "\nPassword: ");
|
||||
nfc_render_iso14443_3a_format_bytes(
|
||||
str, config->password.data, MF_ULTRALIGHT_AUTH_PASSWORD_SIZE);
|
||||
|
||||
furi_string_cat_printf(str, "\nPACK: ");
|
||||
nfc_render_iso14443_3a_format_bytes(str, config->pack.data, MF_ULTRALIGHT_AUTH_PACK_SIZE);
|
||||
|
||||
nfc_render_mf_ultralight_pages_count(data, str);
|
||||
}
|
||||
|
||||
void nfc_render_mf_ultralight_info(
|
||||
const MfUltralightData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_3a_info(data->iso14443_3a_data, format_type, str);
|
||||
|
||||
nfc_render_mf_ultralight_pages_count(data, str);
|
||||
}
|
||||
|
||||
void nfc_render_mf_ultralight_dump(const MfUltralightData* data, FuriString* str) {
|
||||
for(size_t i = 0; i < data->pages_read; i++) {
|
||||
const uint8_t* page_data = data->page[i].data;
|
||||
for(size_t j = 0; j < MF_ULTRALIGHT_PAGE_SIZE; j += 2) {
|
||||
furi_string_cat_printf(str, "%02X%02X ", page_data[j], page_data[j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_mf_ultralight_info(
|
||||
const MfUltralightData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_mf_ultralight_dump(const MfUltralightData* data, FuriString* str);
|
||||
|
||||
void nfc_render_mf_ultralight_pwd_pack(const MfUltralightData* data, FuriString* str);
|
||||
@@ -0,0 +1,786 @@
|
||||
/**
|
||||
* @file nfc_protocol_support.c
|
||||
* @brief Common implementation of application-level protocol support.
|
||||
*
|
||||
* @see nfc_protocol_support_base.h
|
||||
* @see nfc_protocol_support_common.h
|
||||
*/
|
||||
#include "nfc_protocol_support.h"
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
#include "nfc/helpers/nfc_supported_cards.h"
|
||||
|
||||
#include "nfc_protocol_support_defs.h"
|
||||
#include "nfc_protocol_support_gui_common.h"
|
||||
|
||||
/**
|
||||
* @brief Common scene entry handler.
|
||||
*
|
||||
* @param[in,out] instance pointer to the NFC application instance.
|
||||
*/
|
||||
typedef void (*NfcProtocolSupportCommonOnEnter)(NfcApp* instance);
|
||||
|
||||
/**
|
||||
* @brief Common scene custom event handler.
|
||||
*
|
||||
* @param[in,out] instance pointer to the NFC application instance.
|
||||
* @param[in] event custom event to be handled.
|
||||
* @returns true if the event was handled, false otherwise.
|
||||
*/
|
||||
typedef bool (*NfcProtocolSupportCommonOnEvent)(NfcApp* instance, SceneManagerEvent event);
|
||||
|
||||
/**
|
||||
* @brief Common scene exit handler.
|
||||
*
|
||||
* @param[in,out] instance pointer to the NFC application instance.
|
||||
*/
|
||||
typedef void (*NfcProtocolSupportCommonOnExit)(NfcApp* instance);
|
||||
|
||||
/**
|
||||
* @brief Structure containing common scene handler pointers.
|
||||
*/
|
||||
typedef struct {
|
||||
NfcProtocolSupportCommonOnEnter on_enter; /**< Pointer to the on_enter() function. */
|
||||
NfcProtocolSupportCommonOnEvent on_event; /**< Pointer to the on_event() function. */
|
||||
NfcProtocolSupportCommonOnExit on_exit; /**< Pointer to the on_exit() function. */
|
||||
} NfcProtocolSupportCommonSceneBase;
|
||||
|
||||
static const NfcProtocolSupportCommonSceneBase nfc_protocol_support_scenes[];
|
||||
|
||||
// Interface functions
|
||||
void nfc_protocol_support_on_enter(NfcProtocolSupportScene scene, void* context) {
|
||||
furi_assert(scene < NfcProtocolSupportSceneCount);
|
||||
furi_assert(context);
|
||||
|
||||
NfcApp* instance = context;
|
||||
nfc_protocol_support_scenes[scene].on_enter(instance);
|
||||
}
|
||||
|
||||
bool nfc_protocol_support_on_event(
|
||||
NfcProtocolSupportScene scene,
|
||||
void* context,
|
||||
SceneManagerEvent event) {
|
||||
furi_assert(scene < NfcProtocolSupportSceneCount);
|
||||
furi_assert(context);
|
||||
|
||||
NfcApp* instance = context;
|
||||
return nfc_protocol_support_scenes[scene].on_event(instance, event);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_on_exit(NfcProtocolSupportScene scene, void* context) {
|
||||
furi_assert(scene < NfcProtocolSupportSceneCount);
|
||||
furi_assert(context);
|
||||
|
||||
NfcApp* instance = context;
|
||||
nfc_protocol_support_scenes[scene].on_exit(instance);
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_has_feature(NfcProtocol protocol, NfcProtocolFeature feature) {
|
||||
return nfc_protocol_support[protocol]->features & feature;
|
||||
}
|
||||
|
||||
// Common scene handlers
|
||||
// SceneInfo
|
||||
static void nfc_protocol_support_scene_info_on_enter(NfcApp* instance) {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
nfc_protocol_support[protocol]->scene_info.on_enter(instance);
|
||||
|
||||
if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureMoreInfo)) {
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeRight,
|
||||
"More",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_scene_info_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMoreInfo);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
// If the card could not be parsed, return to the respective menu
|
||||
if(!scene_manager_get_scene_state(instance->scene_manager, NfcSceneSupportedCard)) {
|
||||
const uint32_t scenes[] = {NfcSceneSavedMenu, NfcSceneReadMenu};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
instance->scene_manager, scenes, COUNT_OF(scenes));
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_info_on_exit(NfcApp* instance) {
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
// SceneMoreInfo
|
||||
static void nfc_protocol_support_scene_more_info_on_enter(NfcApp* instance) {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
nfc_protocol_support[protocol]->scene_more_info.on_enter(instance);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_more_info_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
consumed = nfc_protocol_support[protocol]->scene_more_info.on_event(instance, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_more_info_on_exit(NfcApp* instance) {
|
||||
text_box_reset(instance->text_box);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
}
|
||||
|
||||
// SceneRead
|
||||
static void nfc_protocol_support_scene_read_on_enter(NfcApp* instance) {
|
||||
popup_set_header(
|
||||
instance->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 12, 23, &A_Loading_24);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
|
||||
const NfcProtocol protocol =
|
||||
instance->protocols_detected[instance->protocols_detected_selected_idx];
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, protocol);
|
||||
|
||||
// Start poller with the appropriate callback
|
||||
nfc_protocol_support[protocol]->scene_read.on_enter(instance);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
|
||||
nfc_blink_detect_start(instance);
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventPollerSuccess) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventPollerIncomplete) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
bool card_read = nfc_supported_cards_read(instance->nfc_device, instance->nfc);
|
||||
if(card_read) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
} else {
|
||||
const NfcProtocol protocol =
|
||||
instance->protocols_detected[instance->protocols_detected_selected_idx];
|
||||
consumed =
|
||||
nfc_protocol_support[protocol]->scene_read.on_event(instance, event.event);
|
||||
}
|
||||
} else if(event.event == NfcCustomEventPollerFailure) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
if(scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDetect)) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneDetect);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
static const uint32_t possible_scenes[] = {NfcSceneSelectProtocol, NfcSceneStart};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
instance->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_read_on_exit(NfcApp* instance) {
|
||||
popup_reset(instance->popup);
|
||||
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
|
||||
// SceneReadMenu
|
||||
static void nfc_protocol_support_scene_read_menu_on_enter(NfcApp* instance) {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
Submenu* submenu = instance->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Save",
|
||||
SubmenuIndexCommonSave,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate UID",
|
||||
SubmenuIndexCommonEmulate,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
} else if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateFull)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexCommonEmulate,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
nfc_protocol_support[protocol]->scene_read_menu.on_enter(instance);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Info",
|
||||
SubmenuIndexCommonInfo,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
submenu_set_selected_item(
|
||||
instance->submenu,
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneReadMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_read_menu_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneReadMenu, event.event);
|
||||
|
||||
if(event.event == SubmenuIndexCommonSave) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonInfo) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneInfo);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEmulate) {
|
||||
dolphin_deed(DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
consumed = true;
|
||||
} else {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
consumed =
|
||||
nfc_protocol_support[protocol]->scene_read_menu.on_event(instance, event.event);
|
||||
}
|
||||
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneSavedMenu, 0);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
// Same for read_menu and saved_menu
|
||||
static void nfc_protocol_support_scene_read_saved_menu_on_exit(NfcApp* instance) {
|
||||
submenu_reset(instance->submenu);
|
||||
}
|
||||
|
||||
// SceneReadSuccess
|
||||
static void nfc_protocol_support_scene_read_success_on_enter(NfcApp* instance) {
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
if(nfc_supported_cards_parse(instance->nfc_device, temp_str)) {
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
} else {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
nfc_protocol_support[protocol]->scene_read_success.on_enter(instance);
|
||||
}
|
||||
|
||||
furi_string_free(temp_str);
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_protocol_support_common_widget_callback, instance);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_protocol_support_common_widget_callback, instance);
|
||||
|
||||
notification_message_block(instance->notifications, &sequence_set_green_255);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_read_success_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadMenu);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_read_success_on_exit(NfcApp* instance) {
|
||||
notification_message_block(instance->notifications, &sequence_reset_green);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
// SceneSavedMenu
|
||||
static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
Submenu* submenu = instance->submenu;
|
||||
|
||||
// Header submenu items
|
||||
if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate UID",
|
||||
SubmenuIndexCommonEmulate,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
} else if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateFull)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexCommonEmulate,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEditUid)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Edit UID",
|
||||
SubmenuIndexCommonEdit,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
// Protocol-dependent menu items
|
||||
nfc_protocol_support[protocol]->scene_saved_menu.on_enter(instance);
|
||||
|
||||
// Trailer submenu items
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Info",
|
||||
SubmenuIndexCommonInfo,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Rename",
|
||||
SubmenuIndexCommonRename,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Delete",
|
||||
SubmenuIndexCommonDelete,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
if(nfc_has_shadow_file(instance)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Restore Data Changes",
|
||||
SubmenuIndexCommonRestore,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
submenu_set_selected_item(
|
||||
instance->submenu,
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneSavedMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_saved_menu_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneSavedMenu, event.event);
|
||||
|
||||
if(event.event == SubmenuIndexCommonRestore) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneRestoreOriginalConfirm);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonInfo) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSupportedCard);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonRename) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonDelete) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneDelete);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEmulate) {
|
||||
const bool is_added =
|
||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSetType);
|
||||
dolphin_deed(is_added ? DolphinDeedNfcAddEmulate : DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
consumed = true;
|
||||
} else {
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
consumed =
|
||||
nfc_protocol_support[protocol]->scene_saved_menu.on_event(instance, event.event);
|
||||
}
|
||||
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneSavedMenu, 0);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
// SceneSaveName
|
||||
|
||||
static void nfc_protocol_support_scene_save_name_on_enter(NfcApp* instance) {
|
||||
FuriString* folder_path = furi_string_alloc();
|
||||
TextInput* text_input = instance->text_input;
|
||||
|
||||
bool name_is_empty = furi_string_empty(instance->file_name);
|
||||
if(name_is_empty) {
|
||||
furi_string_set(instance->file_path, NFC_APP_FOLDER);
|
||||
name_generator_make_auto(
|
||||
instance->text_store, NFC_TEXT_STORE_SIZE, NFC_APP_FILENAME_PREFIX);
|
||||
furi_string_set(folder_path, NFC_APP_FOLDER);
|
||||
} else {
|
||||
nfc_text_store_set(instance, "%s", furi_string_get_cstr(instance->file_name));
|
||||
path_extract_dirname(furi_string_get_cstr(instance->file_path), folder_path);
|
||||
}
|
||||
|
||||
text_input_set_header_text(text_input, "Name the card");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
nfc_protocol_support_common_text_input_done_callback,
|
||||
instance,
|
||||
instance->text_store,
|
||||
NFC_NAME_SIZE,
|
||||
name_is_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
furi_string_get_cstr(folder_path),
|
||||
NFC_APP_EXTENSION,
|
||||
furi_string_get_cstr(instance->file_name));
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
furi_string_free(folder_path);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextInput);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_save_name_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventTextInputDone) {
|
||||
if(!furi_string_empty(instance->file_name)) {
|
||||
nfc_delete(instance);
|
||||
}
|
||||
furi_string_set(instance->file_name, instance->text_store);
|
||||
|
||||
if(nfc_save(instance)) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess);
|
||||
dolphin_deed(
|
||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSetType) ?
|
||||
DolphinDeedNfcAddSave :
|
||||
DolphinDeedNfcSave);
|
||||
const NfcProtocol protocol =
|
||||
instance->protocols_detected[instance->protocols_detected_selected_idx];
|
||||
consumed = nfc_protocol_support[protocol]->scene_save_name.on_event(
|
||||
instance, event.event);
|
||||
} else {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_save_name_on_exit(NfcApp* instance) {
|
||||
void* validator_context = text_input_get_validator_callback_context(instance->text_input);
|
||||
text_input_set_validator(instance->text_input, NULL, NULL);
|
||||
validator_is_file_free(validator_context);
|
||||
|
||||
text_input_reset(instance->text_input);
|
||||
}
|
||||
|
||||
// SceneEmulate
|
||||
/**
|
||||
* @brief Current view displayed on the emulation scene.
|
||||
*
|
||||
* The emulation scehe has two states: the default one showing information about
|
||||
* the card being emulated, and the logs which show the raw data received from the reader.
|
||||
*
|
||||
* The user has the ability to switch betweeen these two scenes, however the prompt to switch is
|
||||
* only shown after some information had appered in the log view.
|
||||
*/
|
||||
enum {
|
||||
NfcSceneEmulateStateWidget, /**< Widget view is displayed. */
|
||||
NfcSceneEmulateStateTextBox, /**< TextBox view is displayed. */
|
||||
};
|
||||
|
||||
static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) {
|
||||
Widget* widget = instance->widget;
|
||||
TextBox* text_box = instance->text_box;
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61);
|
||||
|
||||
if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) {
|
||||
widget_add_string_element(
|
||||
widget, 90, 13, AlignCenter, AlignTop, FontPrimary, "Emulating UID");
|
||||
|
||||
size_t uid_len;
|
||||
const uint8_t* uid = nfc_device_get_uid(instance->nfc_device, &uid_len);
|
||||
|
||||
for(size_t i = 0; i < uid_len; ++i) {
|
||||
furi_string_cat_printf(temp_str, "%02X ", uid[i]);
|
||||
}
|
||||
|
||||
furi_string_trim(temp_str);
|
||||
|
||||
} else {
|
||||
widget_add_string_element(widget, 90, 13, AlignCenter, AlignTop, FontPrimary, "Emulating");
|
||||
furi_string_set(
|
||||
temp_str, nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull));
|
||||
}
|
||||
|
||||
widget_add_text_box_element(
|
||||
widget, 56, 28, 71, 25, AlignCenter, AlignTop, furi_string_get_cstr(temp_str), false);
|
||||
|
||||
furi_string_free(temp_str);
|
||||
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
text_box_set_focus(text_box, TextBoxFocusEnd);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
|
||||
// instance->listener is allocated in the respective on_enter() handler
|
||||
nfc_protocol_support[protocol]->scene_emulate.on_enter(instance);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneEmulate, NfcSceneEmulateStateWidget);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
nfc_blink_emulate_start(instance);
|
||||
}
|
||||
|
||||
static bool
|
||||
nfc_protocol_support_scene_emulate_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
const uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcSceneEmulate);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventListenerUpdate) {
|
||||
// Add data button to widget if data is received for the first time
|
||||
if(furi_string_size(instance->text_box_store)) {
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeCenter,
|
||||
"Log",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
}
|
||||
// Update TextBox data
|
||||
text_box_set_text(instance->text_box, furi_string_get_cstr(instance->text_box_store));
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeCenter) {
|
||||
if(state == NfcSceneEmulateStateWidget) {
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextBox);
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneEmulate, NfcSceneEmulateStateTextBox);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == NfcSceneEmulateStateTextBox) {
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneEmulate, NfcSceneEmulateStateWidget);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_emulate_stop_listener(NfcApp* instance) {
|
||||
nfc_listener_stop(instance->listener);
|
||||
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
if(protocol == nfc_listener_get_protocol(instance->listener)) {
|
||||
const NfcDeviceData* data = nfc_listener_get_data(instance->listener, protocol);
|
||||
|
||||
if(!nfc_device_is_equal_data(instance->nfc_device, protocol, data)) {
|
||||
nfc_device_set_data(instance->nfc_device, protocol, data);
|
||||
nfc_save_shadow_file(instance);
|
||||
}
|
||||
}
|
||||
|
||||
nfc_listener_free(instance->listener);
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_emulate_on_exit(NfcApp* instance) {
|
||||
nfc_protocol_support_scene_emulate_stop_listener(instance);
|
||||
|
||||
// Clear view
|
||||
widget_reset(instance->widget);
|
||||
text_box_reset(instance->text_box);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_rpc_on_enter(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_rpc_setup_ui_and_emulate(NfcApp* instance) {
|
||||
nfc_text_store_set(instance, "emulating\n%s", furi_string_get_cstr(instance->file_name));
|
||||
|
||||
popup_set_header(instance->popup, "NFC", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(instance->popup, instance->text_store, 89, 44, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
|
||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||
nfc_blink_emulate_start(instance);
|
||||
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
nfc_protocol_support[protocol]->scene_emulate.on_enter(instance);
|
||||
|
||||
instance->rpc_state = NfcRpcStateEmulating;
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_scene_rpc_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventRpcLoad && instance->rpc_state == NfcRpcStateIdle) {
|
||||
furi_string_set(instance->file_path, rpc_system_app_get_data(instance->rpc_ctx));
|
||||
const bool load_success = nfc_load_file(instance, instance->file_path, false);
|
||||
if(load_success) {
|
||||
nfc_protocol_support_scene_rpc_setup_ui_and_emulate(instance);
|
||||
}
|
||||
rpc_system_app_confirm(instance->rpc_ctx, RpcAppEventLoadFile, load_success);
|
||||
} else if(event.event == NfcCustomEventRpcExit) {
|
||||
rpc_system_app_confirm(instance->rpc_ctx, RpcAppEventAppExit, true);
|
||||
scene_manager_stop(instance->scene_manager);
|
||||
view_dispatcher_stop(instance->view_dispatcher);
|
||||
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
||||
scene_manager_stop(instance->scene_manager);
|
||||
view_dispatcher_stop(instance->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_rpc_on_exit(NfcApp* instance) {
|
||||
if(instance->rpc_state == NfcRpcStateEmulating) {
|
||||
nfc_protocol_support_scene_emulate_stop_listener(instance);
|
||||
}
|
||||
|
||||
popup_reset(instance->popup);
|
||||
text_box_reset(instance->text_box);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
|
||||
static const NfcProtocolSupportCommonSceneBase
|
||||
nfc_protocol_support_scenes[NfcProtocolSupportSceneCount] = {
|
||||
[NfcProtocolSupportSceneInfo] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_info_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_info_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_info_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneMoreInfo] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_more_info_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_more_info_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_more_info_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneRead] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_read_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_read_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_read_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneReadMenu] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_read_menu_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_read_menu_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_read_saved_menu_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneReadSuccess] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_read_success_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_read_success_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_read_success_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneSavedMenu] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_saved_menu_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_saved_menu_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_read_saved_menu_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneSaveName] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_save_name_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_save_name_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_save_name_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneEmulate] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_emulate_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_emulate_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_emulate_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneRpc] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_rpc_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_rpc_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_rpc_on_exit,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @file nfc_protocol_support.h
|
||||
* @brief Interface for application-level protocol support.
|
||||
*
|
||||
* NFC protocol support helper abstracts common scenes with a single interface
|
||||
* and lets each protocol decide on concrete implementation.
|
||||
*
|
||||
* # Integrating a new protocol into the application
|
||||
*
|
||||
* Most of the scenes in the NFC application work through abstract APIs, so they do not need
|
||||
* protocol-specific versions of themselves. However, when such a situation
|
||||
* occurs, the protocol support helper provides another level of abstraction to hide
|
||||
* the protocol-specific details and isolate them to separate modules.
|
||||
*
|
||||
* @see nfc_protocol.h for more information on adding library protocols.
|
||||
*
|
||||
* The steps for adding support for a library protocol are described below.
|
||||
*
|
||||
* ## 1. Create the files
|
||||
*
|
||||
* ### 1.1 Recommended file structure
|
||||
*
|
||||
* The recommended file structure for a protocol support is as follows:
|
||||
*
|
||||
* ```text
|
||||
* protocol_support
|
||||
* |
|
||||
* +- protocol_name
|
||||
* |
|
||||
* +- protocol_name.h
|
||||
* |
|
||||
* +- protocol_name.c
|
||||
* |
|
||||
* +- protocol_name_render.h
|
||||
* |
|
||||
* +- protocol_name_render.c
|
||||
* |
|
||||
* ```
|
||||
* ### 1.2 File structure explanation
|
||||
*
|
||||
* | Filename | Explanation |
|
||||
* |:-----------------------|:------------|
|
||||
* | protocol_name.h | Interface structure declaration used in `nfc_protocol_support_defs.c`. |
|
||||
* | protocol_name.c | Protocol-specific scene implemenatations and definitions. |
|
||||
* | protocol_name_render.h | Protocol-specific rendering (formatting) functions. Used for converting protocol data into textual descriptions. |
|
||||
* | protocol_name_render.c | Implementations for functions declared in `protocol_name_render.h`.|
|
||||
*
|
||||
* ## 2. Implement the code
|
||||
*
|
||||
* ### 2.1 Features
|
||||
*
|
||||
* Decide what features the protocol will be providing. The features can be combined using bitwise OR (`"|"`).
|
||||
* This choice influences which scenes will have to be implemented in step 2.2.
|
||||
*
|
||||
* @see NfcProtocolFeature for the enumeration of possible features to implement.
|
||||
*
|
||||
* ### 2.2 Scenes
|
||||
*
|
||||
* If a particular scene is not implemented, its empty placeholder from nfc_protocol_support_gui_common.h must be used instead.
|
||||
*
|
||||
* @see nfc_protocol_support_common.h for the enumeration of all scenes that can be implemented.
|
||||
* @see nfc_protocol_support_base.h for the scene implementation details.
|
||||
*
|
||||
* ### 2.3. Registering the protocol support
|
||||
*
|
||||
* After completing the protocol support, it must be registered within the application in order for it to be usable.
|
||||
*
|
||||
* In nfc_protocol_support_defs.c, include the `protocol_name.h` file and add a new entry in the `nfc_protocol_support[]`
|
||||
* array under the appropriate index.
|
||||
*
|
||||
* ## Done!
|
||||
*
|
||||
* @note It will not always be possible to abstract all of the protocol's functionality using the protocol support helper.
|
||||
* In such cases, creating separate protocol-specific scenes is okay (as an example, note the `nfc/scenes/nfc_scene_mf_classic_*` scenes which didn't fit this paradigm).
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "nfc_protocol_support_common.h"
|
||||
|
||||
/**
|
||||
* @brief Abstract interface for on_enter() scene handler.
|
||||
*
|
||||
* Is to be called whenever a scene is entered to.
|
||||
*
|
||||
* @param[in] scene identifier of the scene associated with the handler.
|
||||
* @param[in,out] context pointer to a user-specified context (will be passed to concrete handler).
|
||||
*/
|
||||
void nfc_protocol_support_on_enter(NfcProtocolSupportScene scene, void* context);
|
||||
|
||||
/**
|
||||
* @brief Abstract interface for on_event() scene handler.
|
||||
*
|
||||
* @param[in] scene identifier of the scene associated with the handler.
|
||||
* @param[in,out] context pointer to a user-specified context (will be passed to concrete handler).
|
||||
* @param[in] event SceneManager event to be handled by the scene.
|
||||
* @returns true if the event was consumed, false otherwise.
|
||||
*/
|
||||
bool nfc_protocol_support_on_event(
|
||||
NfcProtocolSupportScene scene,
|
||||
void* context,
|
||||
SceneManagerEvent event);
|
||||
|
||||
/**
|
||||
* @brief Abstract interface for on_exit() scene handler.
|
||||
*
|
||||
* Is to be called whenever a scene is exited from.
|
||||
*
|
||||
* @param[in] scene identifier of the scene associated with the handler.
|
||||
* @param[in,out] context pointer to a user-specified context (will be passed to concrete handler).
|
||||
*/
|
||||
void nfc_protocol_support_on_exit(NfcProtocolSupportScene scene, void* context);
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_base.h
|
||||
* @brief Abstract interface for application-level protocol support.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <core/string.h>
|
||||
|
||||
#include "../../nfc_app.h"
|
||||
|
||||
/**
|
||||
* @brief Scene entry handler.
|
||||
*
|
||||
* @param[in,out] instance pointer to the NFC application instance.
|
||||
*/
|
||||
typedef void (*NfcProtocolSupportOnEnter)(NfcApp* instance);
|
||||
|
||||
/**
|
||||
* @brief Scene event handler.
|
||||
*
|
||||
* @param[in,out] instance pointer to the NFC application instance.
|
||||
* @param[in] event custom event that has occurred.
|
||||
* @returns true if the event was handled, false otherwise.
|
||||
*/
|
||||
typedef bool (*NfcProtocolSupportOnEvent)(NfcApp* instance, uint32_t event);
|
||||
|
||||
/**
|
||||
* @brief Abstract scene interface.
|
||||
*
|
||||
* on_exit() handler is not implemented due to being redundant.
|
||||
*/
|
||||
typedef struct {
|
||||
NfcProtocolSupportOnEnter on_enter; /**< Pointer to the on_enter() function. */
|
||||
NfcProtocolSupportOnEvent on_event; /**< Pointer to the on_event() function. */
|
||||
} NfcProtocolSupportSceneBase;
|
||||
|
||||
/**
|
||||
* @brief Abstract protocol support interface.
|
||||
*/
|
||||
typedef struct {
|
||||
const uint32_t features; /**< Feature bitmask supported by the protocol. */
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific info scene.
|
||||
*
|
||||
* This scene displays general information about a saved or recently read card.
|
||||
* It may include a button that will lead to more information being shown.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_info;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific extended info scene.
|
||||
*
|
||||
* This scene shows more information about a saved or
|
||||
* recently read card, such as memory dumps.
|
||||
*
|
||||
* It may include (a) button(s) and/or menu(s) that will lead to
|
||||
* protocol-specific scenes not covered in this helper.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_more_info;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific read scene.
|
||||
*
|
||||
* This scene is activated when a read operation is in progress.
|
||||
* It is responsible for creating a poller and for handling its events.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_read;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific read menu scene.
|
||||
*
|
||||
* This scene presents the user with options available for the
|
||||
* recenly read card. Such options may include:
|
||||
* * Saving
|
||||
* * Getting information
|
||||
* * Emulating etc.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_read_menu;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific read success scene.
|
||||
*
|
||||
* This scene is activated after a successful read operation.
|
||||
* It is responsible for displaying a very short summary about
|
||||
* the card that was just read.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_read_success;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific saved file menu scene.
|
||||
*
|
||||
* This scene presents the user with options available for a
|
||||
* card loaded from file. Such options may include:
|
||||
* * Renaming
|
||||
* * Deleting
|
||||
* * Getting information
|
||||
* * Emulating etc.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_saved_menu;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific name entry scene.
|
||||
*
|
||||
* This scene is used to enter a file name when saving or renaming a file.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_save_name;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific emulate scene.
|
||||
*
|
||||
* This scene is activated when an emulation operation is in progress.
|
||||
* It is responsible for creating a listener and for handling its events.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_emulate;
|
||||
} NfcProtocolSupportBase;
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_common.h
|
||||
* @brief Common application-level protocol support definitions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Enumeration of protocol features.
|
||||
*/
|
||||
typedef enum {
|
||||
NfcProtocolFeatureNone = 0, /**< No features are supported. */
|
||||
NfcProtocolFeatureEmulateUid = 1UL << 0, /**< Partial emulation is supported. */
|
||||
NfcProtocolFeatureEmulateFull = 1UL << 1, /**< Complete emulation is supported. */
|
||||
NfcProtocolFeatureEditUid = 1UL << 2, /**< UID editing is supported. */
|
||||
NfcProtocolFeatureMoreInfo = 1UL << 3, /**< More information is provided. */
|
||||
} NfcProtocolFeature;
|
||||
|
||||
/**
|
||||
* @brief Enumeration of protocol-aware scenes.
|
||||
*
|
||||
* These are the scenes that are common to all protocols, but require
|
||||
* a protocol-specific implementation.
|
||||
*/
|
||||
typedef enum {
|
||||
NfcProtocolSupportSceneInfo, /**< Display general card information. */
|
||||
NfcProtocolSupportSceneMoreInfo, /**< Display more card information. */
|
||||
NfcProtocolSupportSceneRead, /**< Shown when reading a card. */
|
||||
NfcProtocolSupportSceneReadMenu, /**< Menu with options available for the recently read card. */
|
||||
NfcProtocolSupportSceneReadSuccess, /**< Shown after having successfully read a card. */
|
||||
NfcProtocolSupportSceneSavedMenu, /**< Menu for the card that was loaded from file. */
|
||||
NfcProtocolSupportSceneSaveName, /**< Shown when saving or renaming a file. */
|
||||
NfcProtocolSupportSceneEmulate, /**< Shown when emulating a card. */
|
||||
NfcProtocolSupportSceneRpc, /**< Shown in remote-controlled (RPC) mode. */
|
||||
|
||||
NfcProtocolSupportSceneCount, /**< Special value equal to total scene count. Internal use. */
|
||||
} NfcProtocolSupportScene;
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_defs.c
|
||||
* @brief Application-level protocol support definitions.
|
||||
*
|
||||
* This file is to be modified whenever support for
|
||||
* a new protocol is to be added.
|
||||
*/
|
||||
#include "nfc_protocol_support_base.h"
|
||||
|
||||
#include <nfc/protocols/nfc_protocol.h>
|
||||
|
||||
#include "iso14443_3a/iso14443_3a.h"
|
||||
#include "iso14443_3b/iso14443_3b.h"
|
||||
#include "iso14443_4a/iso14443_4a.h"
|
||||
#include "iso14443_4b/iso14443_4b.h"
|
||||
#include "iso15693_3/iso15693_3.h"
|
||||
#include "felica/felica.h"
|
||||
#include "mf_ultralight/mf_ultralight.h"
|
||||
#include "mf_classic/mf_classic.h"
|
||||
#include "mf_desfire/mf_desfire.h"
|
||||
#include "slix/slix.h"
|
||||
#include "st25tb/st25tb.h"
|
||||
|
||||
/**
|
||||
* @brief Array of pointers to concrete protocol support implementations.
|
||||
*
|
||||
* When adding support for a new protocol, add it to the end of this array
|
||||
* under its respective index.
|
||||
*
|
||||
* @see nfc_protocol.h
|
||||
*/
|
||||
const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = {
|
||||
[NfcProtocolIso14443_3a] = &nfc_protocol_support_iso14443_3a,
|
||||
[NfcProtocolIso14443_3b] = &nfc_protocol_support_iso14443_3b,
|
||||
[NfcProtocolIso14443_4a] = &nfc_protocol_support_iso14443_4a,
|
||||
[NfcProtocolIso14443_4b] = &nfc_protocol_support_iso14443_4b,
|
||||
[NfcProtocolIso15693_3] = &nfc_protocol_support_iso15693_3,
|
||||
[NfcProtocolFelica] = &nfc_protocol_support_felica,
|
||||
[NfcProtocolMfUltralight] = &nfc_protocol_support_mf_ultralight,
|
||||
[NfcProtocolMfClassic] = &nfc_protocol_support_mf_classic,
|
||||
[NfcProtocolMfDesfire] = &nfc_protocol_support_mf_desfire,
|
||||
[NfcProtocolSlix] = &nfc_protocol_support_slix,
|
||||
[NfcProtocolSt25tb] = &nfc_protocol_support_st25tb,
|
||||
/* Add new protocol support implementations here */
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_defs.h
|
||||
* @brief Application-level protocol support declarations.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "nfc_protocol_support_base.h"
|
||||
|
||||
/**
|
||||
* @brief Declaraion of array of pointers to protocol support implementations.
|
||||
*/
|
||||
extern const NfcProtocolSupportBase* nfc_protocol_support[];
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "nfc_protocol_support_gui_common.h"
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
void nfc_protocol_support_common_submenu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
NfcApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
furi_assert(context);
|
||||
NfcApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_byte_input_done_callback(void* context) {
|
||||
furi_assert(context);
|
||||
NfcApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_text_input_done_callback(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_on_enter_empty(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
|
||||
bool nfc_protocol_support_common_on_event_empty(NfcApp* instance, uint32_t event) {
|
||||
UNUSED(instance);
|
||||
UNUSED(event);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_gui_common.h
|
||||
* @brief Common GUI functions and definitions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include "nfc/nfc_app.h"
|
||||
|
||||
/**
|
||||
* @brief Common submenu indices.
|
||||
*/
|
||||
enum {
|
||||
SubmenuIndexCommonSave, /**< Save menu option. */
|
||||
SubmenuIndexCommonEmulate, /**< Emulate menu option. */
|
||||
SubmenuIndexCommonEdit, /**< Edit menu option. */
|
||||
SubmenuIndexCommonInfo, /**< Info menu option. */
|
||||
SubmenuIndexCommonRename, /**< Rename menu option. */
|
||||
SubmenuIndexCommonDelete, /**< Delete menu option. */
|
||||
SubmenuIndexCommonRestore, /**< Restore menu option. */
|
||||
SubmenuIndexCommonMax, /**< Special value, internal use. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Common submenu callback.
|
||||
*
|
||||
* Called each time the user presses on a selected submenu item.
|
||||
*
|
||||
* @param[in,out] context pointer to a user-defined context object.
|
||||
* @param[in] index index of the item that was activated.
|
||||
*/
|
||||
void nfc_protocol_support_common_submenu_callback(void* context, uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Common widget callback.
|
||||
*
|
||||
* Called each time the user presses on a selected widget element.
|
||||
*
|
||||
* @param[in] result identifier of the activated button.
|
||||
* @param[in] type type of press action.
|
||||
* @param[in,out] context pointer to a user-defined context object.
|
||||
*/
|
||||
void nfc_protocol_support_common_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* @brief Common byte input callback.
|
||||
*
|
||||
* Called each time the user accepts the byte input.
|
||||
*
|
||||
* @param[in,out] context pointer to a user-defined context object.
|
||||
*/
|
||||
void nfc_protocol_support_common_byte_input_done_callback(void* context);
|
||||
|
||||
/**
|
||||
* @brief Common text input callback.
|
||||
*
|
||||
* Called each time the user accepts the text input.
|
||||
*
|
||||
* @param[in,out] context pointer to a user-defined context object.
|
||||
*/
|
||||
void nfc_protocol_support_common_text_input_done_callback(void* context);
|
||||
|
||||
/**
|
||||
* @brief Empty on_enter() handler.
|
||||
*
|
||||
* Does nothing.
|
||||
*
|
||||
* @param[in] instance pointer to the NFC application instance.
|
||||
*/
|
||||
void nfc_protocol_support_common_on_enter_empty(NfcApp* instance);
|
||||
|
||||
/**
|
||||
* @brief Empty on_event() handler.
|
||||
*
|
||||
* Does nothing and returns true.
|
||||
*
|
||||
* @param[in] instance pointer to the NFC application instance.
|
||||
* @param[in] event custom event type that has occurred.
|
||||
* @returns always true.
|
||||
*/
|
||||
bool nfc_protocol_support_common_on_event_empty(NfcApp* instance, uint32_t event);
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @file nfc_protocol_support_render_common.h
|
||||
* @brief Common formatting-related defines.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Displayed information verbosity level.
|
||||
*/
|
||||
typedef enum {
|
||||
NfcProtocolFormatTypeShort, /**< Short format, terse info. */
|
||||
NfcProtocolFormatTypeFull, /**< Full format, verbose info. */
|
||||
} NfcProtocolFormatType;
|
||||
141
applications/main/nfc/helpers/protocol_support/slix/slix.c
Normal file
141
applications/main/nfc/helpers/protocol_support/slix/slix.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "slix.h"
|
||||
#include "slix_render.h"
|
||||
|
||||
#include <nfc/protocols/slix/slix_poller.h>
|
||||
#include <nfc/protocols/slix/slix_listener.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_slix(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const SlixData* data = nfc_device_get_data(device, NfcProtocolSlix);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_slix_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_slix(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolSlix);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const SlixPollerEvent* slix_event = event.event_data;
|
||||
|
||||
if(slix_event->type == SlixPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolSlix, 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_slix(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_slix, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_slix(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const SlixData* data = nfc_device_get_data(device, NfcProtocolSlix);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_slix_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 NfcCommand nfc_scene_emulate_listener_callback_slix(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolSlix);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
SlixListenerEvent* slix_event = event.event_data;
|
||||
|
||||
if(slix_event->type == SlixListenerEventTypeCustomCommand) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(slix_event->data->buffer); i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(slix_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_slix(NfcApp* instance) {
|
||||
const SlixData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolSlix);
|
||||
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolSlix, data);
|
||||
nfc_listener_start(instance->listener, nfc_scene_emulate_listener_callback_slix, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_slix(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
.features = NfcProtocolFeatureEmulateFull,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_slix,
|
||||
.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_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_slix,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_scene_emulate_on_enter_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_slix;
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "slix_render.h"
|
||||
|
||||
#include "../iso15693_3/iso15693_3_render.h"
|
||||
|
||||
void nfc_render_slix_info(const SlixData* data, NfcProtocolFormatType format_type, FuriString* str) {
|
||||
nfc_render_iso15693_3_brief(slix_get_base_data(data), str);
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
const SlixType slix_type = slix_get_type(data);
|
||||
|
||||
furi_string_cat(str, "\n\e#Passwords\n");
|
||||
|
||||
static const char* slix_password_names[] = {
|
||||
"Read",
|
||||
"Write",
|
||||
"Privacy",
|
||||
"Destroy",
|
||||
"EAS/AFI",
|
||||
};
|
||||
|
||||
for(uint32_t i = 0; i < SlixPasswordTypeCount; ++i) {
|
||||
if(slix_type_supports_password(slix_type, i)) {
|
||||
furi_string_cat_printf(
|
||||
str, "%s : %08lX\n", slix_password_names[i], data->passwords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_cat(str, "\e#Lock bits\n");
|
||||
|
||||
if(slix_type_has_features(slix_type, SLIX_TYPE_FEATURE_EAS)) {
|
||||
furi_string_cat_printf(
|
||||
str, "EAS: %s locked\n", data->system_info.lock_bits.eas ? "" : "not");
|
||||
}
|
||||
|
||||
if(slix_type_has_features(slix_type, SLIX_TYPE_FEATURE_PROTECTION)) {
|
||||
furi_string_cat_printf(
|
||||
str, "PPL: %s locked\n", data->system_info.lock_bits.ppl ? "" : "not");
|
||||
|
||||
const SlixProtection protection = data->system_info.protection;
|
||||
|
||||
furi_string_cat(str, "\e#Page protection\n");
|
||||
furi_string_cat_printf(str, "Pointer: H >= %02X\n", protection.pointer);
|
||||
|
||||
const char* rh = (protection.condition & SLIX_PP_CONDITION_RH) ? "" : "un";
|
||||
const char* rl = (protection.condition & SLIX_PP_CONDITION_RL) ? "" : "un";
|
||||
|
||||
const char* wh = (protection.condition & SLIX_PP_CONDITION_WH) ? "" : "un";
|
||||
const char* wl = (protection.condition & SLIX_PP_CONDITION_WL) ? "" : "un";
|
||||
|
||||
furi_string_cat_printf(str, "R: H %sprotec. L %sprotec.\n", rh, rl);
|
||||
furi_string_cat_printf(str, "W: H %sprotec. L %sprotec.\n", wh, wl);
|
||||
}
|
||||
|
||||
if(slix_type_has_features(slix_type, SLIX_TYPE_FEATURE_PRIVACY)) {
|
||||
furi_string_cat(str, "\e#Privacy\n");
|
||||
furi_string_cat_printf(str, "Privacy mode: %sabled\n", data->privacy ? "en" : "dis");
|
||||
}
|
||||
|
||||
if(slix_type_has_features(slix_type, SLIX_TYPE_FEATURE_SIGNATURE)) {
|
||||
furi_string_cat(str, "\e#Signature\n");
|
||||
for(uint32_t i = 0; i < 4; ++i) {
|
||||
furi_string_cat_printf(str, "%02X ", data->signature[i]);
|
||||
}
|
||||
|
||||
furi_string_cat(str, "[ ... ]");
|
||||
|
||||
for(uint32_t i = 0; i < 3; ++i) {
|
||||
furi_string_cat_printf(str, " %02X", data->signature[sizeof(SlixSignature) - i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_cat(str, "\n\e#ISO15693-3 data");
|
||||
nfc_render_iso15693_3_extra(slix_get_base_data(data), str);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/slix/slix.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_slix_info(const SlixData* data, NfcProtocolFormatType format_type, FuriString* str);
|
||||
103
applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c
Normal file
103
applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "st25tb.h"
|
||||
#include "st25tb_render.h"
|
||||
|
||||
#include <nfc/protocols/st25tb/st25tb_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_st25tb(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const St25tbData* data = nfc_device_get_data(device, NfcProtocolSt25tb);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_st25tb_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_st25tb(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolSt25tb);
|
||||
|
||||
NfcApp* instance = context;
|
||||
const St25tbPollerEvent* st25tb_event = event.event_data;
|
||||
|
||||
if(st25tb_event->type == St25tbPollerEventTypeReady) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolSt25tb, 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_st25tb(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_st25tb, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_st25tb(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const St25tbData* data = nfc_device_get_data(device, NfcProtocolSt25tb);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_st25tb_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 bool nfc_scene_saved_menu_on_event_st25tb(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_st25tb = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_st25tb,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_st25tb,
|
||||
.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_st25tb,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_st25tb,
|
||||
},
|
||||
.scene_emulate =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_st25tb;
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "st25tb_render.h"
|
||||
#include <nfc/protocols/st25tb/st25tb.h>
|
||||
|
||||
void nfc_render_st25tb_info(
|
||||
const St25tbData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
furi_string_cat_printf(str, "UID");
|
||||
|
||||
for(size_t i = 0; i < ST25TB_UID_SIZE; i++) {
|
||||
furi_string_cat_printf(str, " %02X", data->uid[i]);
|
||||
}
|
||||
|
||||
if(format_type == NfcProtocolFormatTypeFull) {
|
||||
furi_string_cat_printf(str, "\nSys. OTP: %08lX", data->system_otp_block);
|
||||
furi_string_cat_printf(str, "\nBlocks:");
|
||||
for(size_t i = 0; i < st25tb_get_block_count(data->type); i += 2) {
|
||||
furi_string_cat_printf(
|
||||
str, "\n %02X %08lX %08lX", i, data->blocks[i], data->blocks[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/st25tb/st25tb.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_st25tb_info(
|
||||
const St25tbData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
Reference in New Issue
Block a user