[FL-3569] NFC CLI commands (#4158)

* feat: FuriThread stdin

* ci: fix f18

* feat: stdio callback context

* feat: FuriPipe

* POTENTIALLY EXPLOSIVE pipe welding

* fix: non-explosive welding

* Revert welding

* docs: furi_pipe

* feat: pipe event loop integration

* update f18 sdk

* f18

* docs: make doxygen happy

* fix: event loop not triggering when pipe attached to stdio

* fix: partial stdout in pipe

* allow simultaneous in and out subscription in event loop

* feat: vcp i/o

* feat: cli ansi stuffs and history

* feat: more line editing

* working but slow cli rewrite

* restore previous speed after 4 days of debugging 🥲

* fix: cli_app_should_stop

* fix: cli and event_loop memory leaks

* style: remove commented out code

* ci: fix pvs warnings

* fix: unit tests, event_loop crash

* ci: fix build

* ci: silence pvs warning

* feat: cli gpio

* ci: fix formatting

* Fix memory leak during event loop unsubscription

* Event better memory leak fix

* feat: cli completions

* Merge remote-tracking branch 'origin/dev' into portasynthinca3/3928-cli-threads

* merge fixups

* temporarily exclude speaker_debug app

* pvs and unit tests fixups

* feat: commands in fals

* move commands out of flash, code cleanup

* ci: fix errors

* fix: run commands in buffer when stopping session

* speedup cli file transfer

* fix f18

* separate cli_shell into modules

* fix pvs warning

* fix qflipper refusing to connect

* remove temp debug logs

* remove erroneous conclusion

* Fix memory leak during event loop unsubscription

* Event better memory leak fix

* unit test for the fix

* improve thread stdio callback signatures

* pipe stdout timeout

* update api symbols

* fix f18, formatting

* fix pvs warnings

* increase stack size, hope to fix unit tests

* cli completions

* more key combos

* commands in fals

* move commands out of flash

* ci: fix errors

* speedup cli file transfer

* merge fixups

* fix f18

* cli: revert flag changes

* cli: fix formatting

* cli, fbt: loopback perf benchmark

* thread, event_loop: subscribing to thread flags

* cli: signal internal events using thread flags, improve performance

* fix f18, formatting

* event_loop: fix crash

* storage_cli: increase write_chunk buffer size again

* cli: explanation for order=0

* thread, event_loop: thread flags callback refactor

* cli: increase stack size

* cli: rename cli_app_should_stop -> cli_is_pipe_broken_or_is_etx_next_char

* cli: use plain array instead of mlib for history

* cli: prepend file name to static fns

* cli: fix formatting

* cli_shell: increase stack size

* Now cli_shell can be customized with another motd and another command set

* Added custom motd callback definition

* Now user can alloc and free his own cli command set

* cli_vcp can now restart shell with another command set

* Help command modified to show available commands from different command sets

* Api adjustement

* Reworked nfc_cli to start new shell with another command set

* Revert custom shell changes from vcp

* Custom motd callback moved to cli_shell

* Cli Shell now can be started from ongoing cli command

* Help command moved to a separate function so it can be used for custom shell

* Now nfc command spawns separate shell for further nfc commands

* cli_shell: give up pipe to command thread

* fix formatting

* cli_shell: separate into toolbox

* speaker_debug: fix

* fix: format

* Merge branch 'portasynthinca3/3928-3929-cli-fals-threads' into portasynthinca3/3965-cli_shell-toolbox

* fix merge

* fix. merge.

* fix formatting

* fix: cmd flags

* fix: formatting

* Added basic command descriptor structs and macros

* Basic nfc commands definitions added

* Nfc cli commands collection and functions added

* Raw skeleton of nfc cli processor added

* cli: increase default stack depth

* New callbacks for ctx alloc / free added

* nfc_cli moved to cli folder

* Some more logic for command processor

* Scanner command no works via command_processor

* plugin manifest adj

* Argument descriptors were removed, now only keys left

* Some helper command function implemented

* Command processor logic now mostly works

* Added all parsers and dummy implementation of raw cmd

* Now processor checks duplicated keys and treat them as errors

* Some renamings

* Arguments processing moved to separate function

* Now command processor can reuse context of previuos command for the next one if it's allowed

* can_reuse callback added for checking if context can be reused

* command processor is now freed on nfc cli exit

* Some cleanups

* First working version of raw command

* Now input data are placed directly to bit buffer

* Added tag

* Introduced request/response structs

* Moved raw command to a separate folder

* Moved some common types to header

* Added protocol specific handlers for iso14a and felica

* Opened felica crc header for referencing

* Added handler for iso14443_3b

* Opened iso15693_3_poller for referencing

* Added iso15693_3 handler for raw command

* NfcCliRawError enum introduced for response result

* Refactored handlers implementation

* Formatting functions now added as helpers

* New printing result logic

* Not present error value added to enum

* Timeout added to raw command

* Command processor now supports multivalue keys

* Apdu command implementation added

* NfcScanner moved to helpers and command now uses it

* Helper now can format protocol names

* Dump command added

* Added some more functions to scanner helper

* Dump main logic simplified

* Dump handlers moved to protocols folder

* Protocol parser added to simplify searching protocol by name

* Protocol and key arguments added to dump command

* Cleanups

* Apdu now parses protocol using helper parser

* Raw now parses protocol using helper parser

* Wrong naming fix

* Emulate command added to cli

* Description added to action descriptor and command macros

* Description field added to all commands

* Removed unnecessary enum for commands

* Added functions for formatting command and action info

* Proper error messages and help added

* Fix for unsupported single action command

* Function renamed to more appropriate

* Field command moved to all other commands

* Cleanups

* Nfc commands modified with new cli shell

* Removed previous nfc_cli.c after merge

* Removed nfc_cli.h header

* Some renamings and cleanups

* Some comments and instructions added

* Some comments and instructions added

* TODOs removed

* Fix for missing parse callback

* Added not implemented dummy for mfu actions, for now

* Fix name mismatch

* Remove unneeded header

* Mfu command moved to separate folder, also raw info action logic added

* Dictionary with id/vendors added to assets. It is used by nfc_cli_mfu_info_get_vendor function

* One more unneeded header removed

* Moved mfu info action to a separate file

* Info action now uses sync mfu poller

* mfu rdbl action added

* wrbl action added for mfu command

* Some formatting for rdbl command

* Function for formatting mfu errors added

* All mfu actions now show errors in the same way

* Fix error with sync poller. Previously when read failed function returned ErrorNone, now it processes iso14a error to get proper value

* Make PVS happy

* Nfc cli now doesn't start if desktop app is running

* Make action description look more common

* Scanner now has -t key and can show detected protocol hierarchies

* Apdu now checks max input payload data

* Proper format

* Proper error handling added to dump command

* Timeout key added dump command

* Fix merge issue

* formatting

* Pragma pack replaced with FURI_PACKED

* Fix felica memory leak

---------

Co-authored-by: Anna Antonenko <portasynthinca3@gmail.com>
Co-authored-by: Georgii Surkov <georgii.surkov@outlook.com>
Co-authored-by: あく <alleteam@gmail.com>
Co-authored-by: hedger <hedger@users.noreply.github.com>
Co-authored-by: hedger <hedger@nanode.su>
This commit is contained in:
RebornedBrain
2025-09-29 13:34:49 +03:00
committed by GitHub
parent 2ef556d456
commit eea53491de
84 changed files with 4180 additions and 79 deletions

View File

@@ -0,0 +1,32 @@
#include "nfc_cli_dump_felica.h"
#include <nfc/protocols/felica/felica_poller.h>
NfcCommand nfc_cli_dump_poller_callback_felica(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolFelica);
NfcCliDumpContext* instance = context;
const FelicaPollerEvent* felica_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(felica_event->type == FelicaPollerEventTypeReady ||
felica_event->type == FelicaPollerEventTypeIncomplete) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolFelica, nfc_poller_get_data(instance->poller));
command = NfcCommandStop;
instance->result = NfcCliDumpErrorNone;
} else if(felica_event->type == FelicaPollerEventTypeError) {
command = NfcCommandStop;
instance->result = NfcCliDumpErrorFailedToRead;
} else if(felica_event->type == FelicaPollerEventTypeRequestAuthContext) {
FelicaAuthenticationContext* ctx = felica_event->data->auth_context;
const NfcCliDumpAuthContext* dump_auth_ctx = &instance->auth_ctx;
ctx->skip_auth = dump_auth_ctx->skip_auth;
ctx->card_key = dump_auth_ctx->key.felica_key;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_felica(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,25 @@
#include "nfc_cli_dump_iso14443_3a.h"
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
NfcCommand nfc_cli_dump_poller_callback_iso14443_3a(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolIso14443_3a);
NfcCliDumpContext* instance = context;
const Iso14443_3aPollerEvent* iso14443_3a_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolIso14443_3a, nfc_poller_get_data(instance->poller));
command = NfcCommandStop;
} else if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeError) {
command = NfcCommandStop;
instance->result = NfcCliDumpErrorFailedToRead;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_iso14443_3a(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,27 @@
#include "nfc_cli_dump_iso14443_3b.h"
#include <nfc/protocols/iso14443_3b/iso14443_3b_poller.h>
NfcCommand nfc_cli_dump_poller_callback_iso14443_3b(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolIso14443_3b);
NfcCliDumpContext* instance = context;
const Iso14443_3bPollerEvent* iso14443_3b_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(iso14443_3b_event->type == Iso14443_3bPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolIso14443_3b, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(iso14443_3b_event->type == Iso14443_3bPollerEventTypeError) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return NfcCommandContinue;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_iso14443_3b(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,26 @@
#include "nfc_cli_dump_iso14443_4a.h"
#include <nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
NfcCommand nfc_cli_dump_poller_callback_iso14443_4a(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolIso14443_4a);
NfcCliDumpContext* instance = context;
const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_iso14443_4a(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,25 @@
#include "nfc_cli_dump_iso14443_4b.h"
#include <nfc/protocols/iso14443_4b/iso14443_4b_poller.h>
NfcCommand nfc_cli_dump_poller_callback_iso14443_4b(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolIso14443_4b);
NfcCliDumpContext* instance = context;
const Iso14443_4bPollerEvent* iso14443_4b_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(iso14443_4b_event->type == Iso14443_4bPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolIso14443_4b, nfc_poller_get_data(instance->poller));
command = NfcCommandStop;
} else if(iso14443_4b_event->type == Iso14443_4bPollerEventTypeError) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_iso14443_4b(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,26 @@
#include "nfc_cli_dump_iso15693_3.h"
#include <nfc/protocols/iso15693_3/iso15693_3_poller.h>
NfcCommand nfc_cli_dump_poller_callback_iso15693_3(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolIso15693_3);
NfcCliDumpContext* instance = context;
const Iso15693_3PollerEvent* iso15693_3_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(iso15693_3_event->type == Iso15693_3PollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolIso15693_3, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
} else if(iso15693_3_event->type == Iso15693_3PollerEventTypeError) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_iso15693_3(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,54 @@
#include "nfc_cli_dump_mf_classic.h"
#include <nfc/protocols/mf_classic/mf_classic_poller.h>
#define TAG "MFC"
NfcCommand nfc_cli_dump_poller_callback_mf_classic(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolMfClassic);
NfcCliDumpContext* 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_D(TAG, "Key cache found");
mfc_event->data->poller_mode.mode = MfClassicPollerModeRead;
} else {
FURI_LOG_D(TAG, "Key cache not found");
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
} else if(mfc_event->type == MfClassicPollerEventTypeRequestReadSector) {
uint8_t sector_num = 0;
MfClassicKey key = {};
MfClassicKeyType key_type = MfClassicKeyTypeA;
if(mf_classic_key_cache_get_next_key(
instance->mfc_key_cache, &sector_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));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(mfc_event->type == MfClassicPollerEventTypeFail) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_mf_classic(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,27 @@
#include "nfc_cli_dump_mf_desfire.h"
#include <nfc/protocols/mf_desfire/mf_desfire_poller.h>
#define TAG "MFDES"
NfcCommand nfc_cli_dump_poller_callback_mf_desfire(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolMfDesfire);
NfcCommand command = NfcCommandContinue;
NfcCliDumpContext* 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));
instance->result = NfcCliDumpErrorNone;
furi_semaphore_release(instance->sem_done);
command = NfcCommandStop;
} else if(mf_desfire_event->type == MfDesfirePollerEventTypeReadFailed) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandReset;
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_mf_desfire(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,31 @@
#include "nfc_cli_dump_mf_plus.h"
#include <nfc/protocols/mf_plus/mf_plus_poller.h>
#define TAG "MFPLUS"
NfcCommand nfc_cli_dump_poller_callback_mf_plus(NfcGenericEvent event, void* context) {
furi_assert(context);
furi_assert(event.protocol == NfcProtocolMfPlus);
furi_assert(event.event_data);
NfcCliDumpContext* instance = context;
const MfPlusPollerEvent* mf_plus_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(mf_plus_event->type == MfPlusPollerEventTypeReadSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolMfPlus, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(mf_plus_event->type == MfPlusPollerEventTypeReadFailed) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandReset;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_mf_plus(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,39 @@
#include "nfc_cli_dump_mf_ultralight.h"
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
#define TAG "MFU"
NfcCommand nfc_cli_dump_poller_callback_mf_ultralight(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolMfUltralight);
NfcCliDumpContext* instance = context;
const MfUltralightPollerEvent* mf_ultralight_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(mf_ultralight_event->type == MfUltralightPollerEventTypeReadSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
const NfcCliDumpAuthContext* auth_ctx = &instance->auth_ctx;
mf_ultralight_event->data->auth_context.skip_auth = auth_ctx->skip_auth;
mf_ultralight_event->data->auth_context.password = auth_ctx->key.password;
mf_ultralight_event->data->auth_context.tdes_key = auth_ctx->key.tdes_key;
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthFailed) {
instance->result = NfcCliDumpErrorAuthFailed;
command = NfcCommandStop;
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeReadFailed) {
instance->result = NfcCliDumpErrorAuthFailed;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_mf_ultralight(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,59 @@
#pragma once
#include <furi.h>
#include "../../../../helpers/mf_classic_key_cache.h"
#include "../../helpers/nfc_cli_scanner.h"
#include <nfc/nfc.h>
#include <nfc/protocols/nfc_protocol.h>
#include <nfc/nfc_device.h>
#include <nfc/nfc_poller.h>
#include <nfc/protocols/felica/felica.h>
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
#include <storage/storage.h>
#define NFC_CLI_DUMP_KEY_MAX_SIZE (16)
typedef union {
MfUltralightAuthPassword password;
FelicaCardKey felica_key;
MfUltralightC3DesAuthKey tdes_key;
uint8_t key[NFC_CLI_DUMP_KEY_MAX_SIZE];
} NfcCliDumpKeyUnion;
typedef struct {
NfcCliDumpKeyUnion key;
uint8_t key_size;
bool skip_auth;
} NfcCliDumpAuthContext;
typedef enum {
NfcCliDumpErrorNone,
NfcCliDumpErrorTimeout,
NfcCliDumpErrorNotPresent,
NfcCliDumpErrorFailedToRead,
NfcCliDumpErrorAuthFailed,
NfcCliDumpErrorNum,
} NfcCliDumpError;
typedef struct {
Nfc* nfc;
FuriString* file_path;
Storage* storage;
NfcCliScanner* scanner;
NfcProtocol desired_protocol;
uint32_t timeout;
FuriSemaphore* sem_done;
NfcCliDumpError result;
NfcCliDumpAuthContext auth_ctx;
MfClassicKeyCache* mfc_key_cache;
NfcPoller* poller;
NfcDevice* nfc_device;
} NfcCliDumpContext;

View File

@@ -0,0 +1,26 @@
#include "nfc_cli_dump_slix.h"
#include <nfc/protocols/slix/slix_poller.h>
NfcCommand nfc_cli_dump_poller_callback_slix(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolSlix);
NfcCliDumpContext* instance = context;
const SlixPollerEvent* slix_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(slix_event->type == SlixPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolSlix, nfc_poller_get_data(instance->poller));
command = NfcCommandStop;
} else if(slix_event->type == SlixPollerEventTypeError) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_slix(NfcGenericEvent event, void* context);

View File

@@ -0,0 +1,29 @@
#include "nfc_cli_dump_st25tb.h"
#include <nfc/protocols/st25tb/st25tb_poller.h>
NfcCommand nfc_cli_dump_poller_callback_st25tb(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolSt25tb);
NfcCliDumpContext* instance = context;
const St25tbPollerEvent* st25tb_event = event.event_data;
NfcCommand command = NfcCommandContinue;
if(st25tb_event->type == St25tbPollerEventTypeRequestMode) {
st25tb_event->data->mode_request.mode = St25tbPollerModeRead;
} else if(st25tb_event->type == St25tbPollerEventTypeSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolSt25tb, nfc_poller_get_data(instance->poller));
instance->result = NfcCliDumpErrorNone;
command = NfcCommandStop;
} else if(st25tb_event->type == St25tbPollerEventTypeFailure) {
instance->result = NfcCliDumpErrorFailedToRead;
command = NfcCommandStop;
}
if(command == NfcCommandStop) {
furi_semaphore_release(instance->sem_done);
}
return command;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "../nfc_cli_dump_common_types.h"
NfcCommand nfc_cli_dump_poller_callback_st25tb(NfcGenericEvent event, void* context);