mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-23 05:24:46 -07:00
[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:
@@ -0,0 +1,101 @@
|
||||
#include "nfc_cli_raw_felica.h"
|
||||
#include "../../../helpers/nfc_cli_format.h"
|
||||
|
||||
#include <nfc/helpers/felica_crc.h>
|
||||
#include <nfc/protocols/felica/felica.h>
|
||||
#include <nfc/protocols/felica/felica_poller_i.h>
|
||||
|
||||
#define TAG "FELICA"
|
||||
|
||||
#define BIT_BUFFER_EMPTY(buffer) ((bit_buffer_get_size_bytes(buffer) == 0))
|
||||
|
||||
static inline void felica_format_activation_data(const FelicaData* data, FuriString* output) {
|
||||
nfc_cli_format_array(data->idm.data, FELICA_IDM_SIZE, "IDm: ", output);
|
||||
nfc_cli_format_array(data->pmm.data, FELICA_PMM_SIZE, " PMm: ", output);
|
||||
}
|
||||
|
||||
static NfcCliRawError nfc_cli_raw_felica_process_error(FelicaError error) {
|
||||
switch(error) {
|
||||
case FelicaErrorNone:
|
||||
return NfcCliRawErrorNone;
|
||||
case FelicaErrorTimeout:
|
||||
return NfcCliRawErrorTimeout;
|
||||
case FelicaErrorWrongCrc:
|
||||
return NfcCliRawErrorWrongCrc;
|
||||
case FelicaErrorNotPresent:
|
||||
return NfcCliRawErrorNotPresent;
|
||||
default:
|
||||
return NfcCliRawErrorProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
static FelicaError nfc_cli_raw_felica_poller_process_error(NfcError error) {
|
||||
switch(error) {
|
||||
case NfcErrorNone:
|
||||
return FelicaErrorNone;
|
||||
case NfcErrorTimeout:
|
||||
return FelicaErrorTimeout;
|
||||
default:
|
||||
return FelicaErrorNotPresent;
|
||||
}
|
||||
}
|
||||
|
||||
static inline NfcCliRawError
|
||||
nfc_cli_raw_felica_activate(NfcGenericInstance* poller, FuriString* activation_string) {
|
||||
FelicaData felica_data = {};
|
||||
FelicaPoller* felica_poller = poller;
|
||||
FURI_LOG_D(TAG, "Activating...");
|
||||
|
||||
FelicaError error = felica_poller_activate(felica_poller, &felica_data);
|
||||
if(error == FelicaErrorNone) {
|
||||
felica_format_activation_data(&felica_data, activation_string);
|
||||
}
|
||||
|
||||
return nfc_cli_raw_felica_process_error(error);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError nfc_cli_raw_felica_txrx(
|
||||
NfcGenericInstance* poller,
|
||||
BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t timeout) {
|
||||
FURI_LOG_D(TAG, "TxRx");
|
||||
FelicaPoller* felica_poller = poller;
|
||||
|
||||
bit_buffer_reset(rx_buffer);
|
||||
|
||||
FelicaError error = FelicaErrorNone;
|
||||
|
||||
NfcError nfc_error = nfc_poller_trx(felica_poller->nfc, tx_buffer, rx_buffer, timeout);
|
||||
if(nfc_error != NfcErrorNone) {
|
||||
error = nfc_cli_raw_felica_poller_process_error(nfc_error);
|
||||
} else if(!felica_crc_check(rx_buffer)) {
|
||||
error = FelicaErrorWrongCrc;
|
||||
}
|
||||
|
||||
return nfc_cli_raw_felica_process_error(error);
|
||||
}
|
||||
|
||||
NfcCommand nfc_cli_raw_felica_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response) {
|
||||
do {
|
||||
if(request->select) {
|
||||
response->result = nfc_cli_raw_felica_activate(poller, response->activation_string);
|
||||
}
|
||||
|
||||
if(response->result != NfcCliRawErrorNone) break;
|
||||
if(BIT_BUFFER_EMPTY(request->tx_buffer)) break;
|
||||
|
||||
if(request->append_crc) {
|
||||
FURI_LOG_D(TAG, "Add CRC");
|
||||
felica_crc_append(request->tx_buffer);
|
||||
}
|
||||
|
||||
uint32_t timeout = request->timeout > 0 ? request->timeout : FELICA_FDT_POLL_FC;
|
||||
response->result =
|
||||
nfc_cli_raw_felica_txrx(poller, request->tx_buffer, response->rx_buffer, timeout);
|
||||
} while(false);
|
||||
return request->keep_field ? NfcCommandContinue : NfcCommandStop;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_cli_raw_common_types.h"
|
||||
|
||||
NfcCommand nfc_cli_raw_felica_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response);
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "nfc_cli_raw_iso14443_3a.h"
|
||||
#include "../../../helpers/nfc_cli_format.h"
|
||||
|
||||
#include <nfc/helpers/iso14443_crc.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
|
||||
#define TAG "ISO14A"
|
||||
|
||||
#define BIT_BUFFER_EMPTY(buffer) ((bit_buffer_get_size_bytes(buffer) == 0))
|
||||
|
||||
static NfcCliRawError nfc_cli_raw_iso14443_3a_process_error(Iso14443_3aError error) {
|
||||
switch(error) {
|
||||
case Iso14443_3aErrorNone:
|
||||
return NfcCliRawErrorNone;
|
||||
case Iso14443_3aErrorTimeout:
|
||||
return NfcCliRawErrorTimeout;
|
||||
case Iso14443_3aErrorWrongCrc:
|
||||
return NfcCliRawErrorWrongCrc;
|
||||
case Iso14443_3aErrorNotPresent:
|
||||
return NfcCliRawErrorNotPresent;
|
||||
default:
|
||||
return NfcCliRawErrorProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
static void iso14443_3a_format_activation_data(const Iso14443_3aData* data, FuriString* output) {
|
||||
nfc_cli_format_array(data->uid, data->uid_len, "UID: ", output);
|
||||
furi_string_cat_printf(
|
||||
output, " ATQA: %02X%02X SAK: %02X", data->atqa[0], data->atqa[1], data->sak);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError
|
||||
nfc_cli_raw_iso14443_3a_activate(NfcGenericInstance* poller, FuriString* activation_string) {
|
||||
Iso14443_3aData iso3_data = {};
|
||||
FURI_LOG_D(TAG, "Activating...");
|
||||
|
||||
Iso14443_3aError error = iso14443_3a_poller_activate(poller, &iso3_data);
|
||||
if(error == Iso14443_3aErrorNone)
|
||||
iso14443_3a_format_activation_data(&iso3_data, activation_string);
|
||||
|
||||
return nfc_cli_raw_iso14443_3a_process_error(error);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError nfc_cli_raw_iso14443_3a_txrx(
|
||||
NfcGenericInstance* poller,
|
||||
BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t timeout) {
|
||||
FURI_LOG_D(TAG, "TxRx");
|
||||
bit_buffer_reset(rx_buffer);
|
||||
Iso14443_3aError error = iso14443_3a_poller_txrx(poller, tx_buffer, rx_buffer, timeout);
|
||||
return nfc_cli_raw_iso14443_3a_process_error(error);
|
||||
}
|
||||
|
||||
NfcCommand nfc_cli_raw_iso14443_3a_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response) {
|
||||
do {
|
||||
response->result = NfcCliRawErrorNone;
|
||||
if(request->select) {
|
||||
response->result =
|
||||
nfc_cli_raw_iso14443_3a_activate(poller, response->activation_string);
|
||||
}
|
||||
|
||||
if(response->result != NfcCliRawErrorNone) break;
|
||||
if(BIT_BUFFER_EMPTY(request->tx_buffer)) break;
|
||||
|
||||
if(request->append_crc) {
|
||||
FURI_LOG_D(TAG, "Add CRC");
|
||||
iso14443_crc_append(Iso14443CrcTypeA, request->tx_buffer);
|
||||
}
|
||||
|
||||
uint32_t timeout = request->timeout > 0 ? request->timeout : ISO14443_3A_FDT_LISTEN_FC;
|
||||
response->result =
|
||||
nfc_cli_raw_iso14443_3a_txrx(poller, request->tx_buffer, response->rx_buffer, timeout);
|
||||
} while(false);
|
||||
|
||||
return request->keep_field ? NfcCommandContinue : NfcCommandStop;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_cli_raw_common_types.h"
|
||||
|
||||
NfcCommand nfc_cli_raw_iso14443_3a_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response);
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "nfc_cli_raw_iso14443_3b.h"
|
||||
#include "../../../helpers/nfc_cli_format.h"
|
||||
|
||||
#include <nfc/helpers/iso14443_crc.h>
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b_i.h>
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h>
|
||||
|
||||
#define TAG "ISO14B"
|
||||
|
||||
#define BIT_BUFFER_EMPTY(buffer) ((bit_buffer_get_size_bytes(buffer) == 0))
|
||||
|
||||
static NfcCliRawError nfc_cli_raw_iso14443_3b_process_error(Iso14443_3bError error) {
|
||||
switch(error) {
|
||||
case Iso14443_3bErrorNone:
|
||||
return NfcCliRawErrorNone;
|
||||
case Iso14443_3bErrorTimeout:
|
||||
return NfcCliRawErrorTimeout;
|
||||
case Iso14443_3bErrorWrongCrc:
|
||||
return NfcCliRawErrorWrongCrc;
|
||||
case Iso14443_3bErrorNotPresent:
|
||||
return NfcCliRawErrorNotPresent;
|
||||
default:
|
||||
return NfcCliRawErrorProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
static Iso14443_3bError nfc_cli_raw_iso14443_3b_poller_process_error(NfcError error) {
|
||||
switch(error) {
|
||||
case NfcErrorNone:
|
||||
return Iso14443_3bErrorNone;
|
||||
case NfcErrorTimeout:
|
||||
return Iso14443_3bErrorTimeout;
|
||||
default:
|
||||
return Iso14443_3bErrorNotPresent;
|
||||
}
|
||||
}
|
||||
|
||||
static void iso14443_3b_format_activation_data(const Iso14443_3bData* data, FuriString* output) {
|
||||
nfc_cli_format_array(data->uid, ISO14443_3B_UID_SIZE, "UID: ", output);
|
||||
|
||||
const Iso14443_3bProtocolInfo* info = &data->protocol_info;
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
" BitRate: %d, Protocol: %d, Max Frame Size: %d, Fo: %d, Adc: %d, Fwi: %d",
|
||||
info->bit_rate_capability,
|
||||
info->protocol_type,
|
||||
info->max_frame_size,
|
||||
info->fo,
|
||||
info->adc,
|
||||
info->fwi);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError nfc_cli_raw_iso14443_3b_activate(
|
||||
NfcGenericInstance* poller,
|
||||
Iso14443_3bData* iso3b_data,
|
||||
FuriString* activation_string) {
|
||||
FURI_LOG_D(TAG, "Activating...");
|
||||
|
||||
Iso14443_3bError error = iso14443_3b_poller_activate(poller, iso3b_data);
|
||||
if(error == Iso14443_3bErrorNone)
|
||||
iso14443_3b_format_activation_data(iso3b_data, activation_string);
|
||||
|
||||
return nfc_cli_raw_iso14443_3b_process_error(error);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError nfc_cli_raw_iso14443_3b_txrx(
|
||||
NfcGenericInstance* poller,
|
||||
BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t timeout) {
|
||||
FURI_LOG_D(TAG, "TxRx");
|
||||
Iso14443_3bPoller* iso14b_poller = poller;
|
||||
|
||||
bit_buffer_reset(rx_buffer);
|
||||
|
||||
Iso14443_3bError error = Iso14443_3bErrorNone;
|
||||
|
||||
NfcError nfc_error = nfc_poller_trx(iso14b_poller->nfc, tx_buffer, rx_buffer, timeout);
|
||||
if(nfc_error != NfcErrorNone) {
|
||||
error = nfc_cli_raw_iso14443_3b_poller_process_error(nfc_error);
|
||||
} else if(!iso14443_crc_check(Iso14443CrcTypeB, rx_buffer)) {
|
||||
error = Iso14443_3bErrorWrongCrc;
|
||||
}
|
||||
|
||||
return nfc_cli_raw_iso14443_3b_process_error(error);
|
||||
}
|
||||
|
||||
NfcCommand nfc_cli_raw_iso14443_3b_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response) {
|
||||
Iso14443_3bData iso3b_data = {0};
|
||||
bool activated = false;
|
||||
do {
|
||||
response->result = NfcCliRawErrorNone;
|
||||
if(request->select) {
|
||||
response->result =
|
||||
nfc_cli_raw_iso14443_3b_activate(poller, &iso3b_data, response->activation_string);
|
||||
activated = response->result == NfcCliRawErrorNone;
|
||||
}
|
||||
|
||||
if(response->result != NfcCliRawErrorNone) break;
|
||||
if(BIT_BUFFER_EMPTY(request->tx_buffer)) break;
|
||||
|
||||
uint32_t timeout = ISO14443_3B_FDT_POLL_FC;
|
||||
if(request->timeout > 0) {
|
||||
timeout = request->timeout;
|
||||
} else if(activated) {
|
||||
timeout = iso14443_3b_get_fwt_fc_max(&iso3b_data);
|
||||
}
|
||||
|
||||
if(request->append_crc) {
|
||||
FURI_LOG_D(TAG, "Add CRC");
|
||||
iso14443_crc_append(Iso14443CrcTypeB, request->tx_buffer);
|
||||
}
|
||||
|
||||
response->result =
|
||||
nfc_cli_raw_iso14443_3b_txrx(poller, request->tx_buffer, response->rx_buffer, timeout);
|
||||
} while(false);
|
||||
return request->keep_field ? NfcCommandContinue : NfcCommandStop;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_cli_raw_common_types.h"
|
||||
|
||||
NfcCommand nfc_cli_raw_iso14443_3b_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response);
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "nfc_cli_raw_iso15693_3.h"
|
||||
#include "../../../helpers/nfc_cli_format.h"
|
||||
|
||||
#include <nfc/helpers/iso13239_crc.h>
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3.h>
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3_poller_i.h>
|
||||
|
||||
#define TAG "ISO15"
|
||||
|
||||
#define BIT_BUFFER_EMPTY(buffer) ((bit_buffer_get_size_bytes(buffer) == 0))
|
||||
|
||||
static NfcCliRawError nfc_cli_raw_iso15693_3_process_error(Iso15693_3Error error) {
|
||||
switch(error) {
|
||||
case Iso15693_3ErrorNone:
|
||||
return NfcCliRawErrorNone;
|
||||
case Iso15693_3ErrorTimeout:
|
||||
return NfcCliRawErrorTimeout;
|
||||
case Iso15693_3ErrorWrongCrc:
|
||||
return NfcCliRawErrorWrongCrc;
|
||||
case Iso15693_3ErrorNotPresent:
|
||||
return NfcCliRawErrorNotPresent;
|
||||
default:
|
||||
return NfcCliRawErrorProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
static Iso15693_3Error nfc_cli_raw_iso15693_3_poller_process_nfc_error(NfcError error) {
|
||||
switch(error) {
|
||||
case NfcErrorNone:
|
||||
return Iso15693_3ErrorNone;
|
||||
case NfcErrorTimeout:
|
||||
return Iso15693_3ErrorTimeout;
|
||||
default:
|
||||
return Iso15693_3ErrorNotPresent;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso15693_3_format_activation_data(const uint8_t* data, FuriString* output) {
|
||||
nfc_cli_format_array(data, ISO15693_3_UID_SIZE, "UID: ", output);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError
|
||||
nfc_cli_raw_iso15693_3_activate(NfcGenericInstance* poller, FuriString* activation_string) {
|
||||
FURI_LOG_D(TAG, "Activating...");
|
||||
|
||||
Iso15693_3Poller* iso15_poller = poller;
|
||||
uint8_t uid[ISO15693_3_UID_SIZE] = {0};
|
||||
|
||||
Iso15693_3Error error = iso15693_3_poller_inventory(iso15_poller, uid);
|
||||
if(error == Iso15693_3ErrorNone) {
|
||||
iso15693_3_format_activation_data(uid, activation_string);
|
||||
}
|
||||
return nfc_cli_raw_iso15693_3_process_error(error);
|
||||
}
|
||||
|
||||
static inline NfcCliRawError nfc_cli_raw_iso15693_3_txrx(
|
||||
NfcGenericInstance* poller,
|
||||
BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t timeout) {
|
||||
FURI_LOG_D(TAG, "TxRx");
|
||||
|
||||
Iso15693_3Poller* iso15_poller = poller;
|
||||
|
||||
bit_buffer_reset(rx_buffer);
|
||||
|
||||
Iso15693_3Error error = Iso15693_3ErrorNone;
|
||||
|
||||
NfcError nfc_error = nfc_poller_trx(iso15_poller->nfc, tx_buffer, rx_buffer, timeout);
|
||||
if(nfc_error != NfcErrorNone) {
|
||||
error = nfc_cli_raw_iso15693_3_poller_process_nfc_error(nfc_error);
|
||||
} else if(!iso13239_crc_check(Iso13239CrcTypeDefault, rx_buffer)) {
|
||||
error = Iso15693_3ErrorWrongCrc;
|
||||
}
|
||||
|
||||
return nfc_cli_raw_iso15693_3_process_error(error);
|
||||
}
|
||||
|
||||
NfcCommand nfc_cli_raw_iso15693_3_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response) {
|
||||
do {
|
||||
if(request->select) {
|
||||
response->result =
|
||||
nfc_cli_raw_iso15693_3_activate(poller, response->activation_string);
|
||||
}
|
||||
|
||||
if(response->result != NfcCliRawErrorNone) break;
|
||||
if(BIT_BUFFER_EMPTY(request->tx_buffer)) break;
|
||||
|
||||
if(request->append_crc) {
|
||||
FURI_LOG_D(TAG, "Add CRC");
|
||||
iso13239_crc_append(Iso13239CrcTypeDefault, request->tx_buffer);
|
||||
}
|
||||
|
||||
uint32_t timeout = request->timeout > 0 ? request->timeout : ISO15693_3_FDT_POLL_FC;
|
||||
response->result =
|
||||
nfc_cli_raw_iso15693_3_txrx(poller, request->tx_buffer, response->rx_buffer, timeout);
|
||||
} while(false);
|
||||
return request->keep_field ? NfcCommandContinue : NfcCommandStop;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_cli_raw_common_types.h"
|
||||
|
||||
NfcCommand nfc_cli_raw_iso15693_3_handler(
|
||||
NfcGenericInstance* poller,
|
||||
const NfcCliRawRequest* request,
|
||||
NfcCliRawResponse* const response);
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/nfc_poller.h>
|
||||
|
||||
typedef enum {
|
||||
NfcCliRawErrorNone,
|
||||
NfcCliRawErrorTimeout,
|
||||
NfcCliRawErrorNotPresent,
|
||||
NfcCliRawErrorWrongCrc,
|
||||
NfcCliRawErrorProtocol,
|
||||
} NfcCliRawError;
|
||||
|
||||
typedef struct {
|
||||
bool select;
|
||||
bool keep_field;
|
||||
bool append_crc;
|
||||
NfcProtocol protocol;
|
||||
BitBuffer* tx_buffer;
|
||||
uint32_t timeout;
|
||||
} NfcCliRawRequest;
|
||||
|
||||
typedef struct {
|
||||
NfcCliRawError result;
|
||||
BitBuffer* rx_buffer;
|
||||
FuriString* activation_string;
|
||||
} NfcCliRawResponse;
|
||||
Reference in New Issue
Block a user