[FL-3666] NFC API improvements (#3214)
* drivers: expose st25r3916 driver API * nfc poller: add start with custom callback * mf classic: rework sync API with poller custom start * mf ultralight: rework sync API with poller custom start * iso14443_3a poller: remove unused col res state * nfc: rework nfc poller custom start * mf ultralight: rename sync API * mf classic: rename sync API * iso14443-3a: rename sync API * nfc: remove async prefix in internal functions * nfc: expose internal API * nfc: fix sync api include and docs * targets: fix f18 build * nfc: rework NfcGenericEventEx type * nfc poller: add documentation * iso14443-3a poller: add documentation * felica poller: add documentation * iso14443_3b poller: add documentation * so14443_4a poller: add documentation * iso14443_4b poller: add documentation * iso15693 poller: add documentation * slix poller: add documentation * mf desfire poller: add documentation * mf ultralight poller: fix API and add documentation * mf classic poller: add documentation Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									d0b9a3a4ae
								
							
						
					
					
						commit
						c00776ca22
					
				@ -7,10 +7,10 @@
 | 
				
			|||||||
#include <nfc/nfc_poller.h>
 | 
					#include <nfc/nfc_poller.h>
 | 
				
			||||||
#include <nfc/nfc_listener.h>
 | 
					#include <nfc/nfc_listener.h>
 | 
				
			||||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
 | 
					#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
 | 
				
			||||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller_sync_api.h>
 | 
					#include <nfc/protocols/iso14443_3a/iso14443_3a_poller_sync.h>
 | 
				
			||||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
 | 
					#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
 | 
				
			||||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync_api.h>
 | 
					#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h>
 | 
				
			||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync_api.h>
 | 
					#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nfc/helpers/nfc_dict.h>
 | 
					#include <nfc/helpers/nfc_dict.h>
 | 
				
			||||||
#include <nfc/nfc.h>
 | 
					#include <nfc/nfc.h>
 | 
				
			||||||
@ -182,8 +182,8 @@ MU_TEST(iso14443_3a_reader) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Iso14443_3aData iso14443_3a_poller_data = {};
 | 
					    Iso14443_3aData iso14443_3a_poller_data = {};
 | 
				
			||||||
    mu_assert(
 | 
					    mu_assert(
 | 
				
			||||||
        iso14443_3a_poller_read(poller, &iso14443_3a_poller_data) == Iso14443_3aErrorNone,
 | 
					        iso14443_3a_poller_sync_read(poller, &iso14443_3a_poller_data) == Iso14443_3aErrorNone,
 | 
				
			||||||
        "iso14443_3a_poller_read() failed");
 | 
					        "iso14443_3a_poller_sync_read() failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(iso3_listener);
 | 
					    nfc_listener_stop(iso3_listener);
 | 
				
			||||||
    mu_assert(
 | 
					    mu_assert(
 | 
				
			||||||
@ -221,8 +221,8 @@ static void mf_ultralight_reader_test(const char* path) {
 | 
				
			|||||||
    nfc_listener_start(mfu_listener, NULL, NULL);
 | 
					    nfc_listener_start(mfu_listener, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
					    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
				
			||||||
    MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
 | 
					    MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
 | 
				
			||||||
    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
 | 
					    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(mfu_listener);
 | 
					    nfc_listener_stop(mfu_listener);
 | 
				
			||||||
    nfc_listener_free(mfu_listener);
 | 
					    nfc_listener_free(mfu_listener);
 | 
				
			||||||
@ -270,8 +270,8 @@ MU_TEST(ntag_213_locked_reader) {
 | 
				
			|||||||
    nfc_listener_start(mfu_listener, NULL, NULL);
 | 
					    nfc_listener_start(mfu_listener, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
					    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
				
			||||||
    MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
 | 
					    MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
 | 
				
			||||||
    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
 | 
					    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(mfu_listener);
 | 
					    nfc_listener_stop(mfu_listener);
 | 
				
			||||||
    nfc_listener_free(mfu_listener);
 | 
					    nfc_listener_free(mfu_listener);
 | 
				
			||||||
@ -308,8 +308,8 @@ static void mf_ultralight_write() {
 | 
				
			|||||||
    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
					    MfUltralightData* mfu_data = mf_ultralight_alloc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initial read
 | 
					    // Initial read
 | 
				
			||||||
    MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
 | 
					    MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
 | 
				
			||||||
    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
 | 
					    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mu_assert(
 | 
					    mu_assert(
 | 
				
			||||||
        mf_ultralight_is_equal(mfu_data, nfc_device_get_data(nfc_device, NfcProtocolMfUltralight)),
 | 
					        mf_ultralight_is_equal(mfu_data, nfc_device_get_data(nfc_device, NfcProtocolMfUltralight)),
 | 
				
			||||||
@ -321,13 +321,13 @@ static void mf_ultralight_write() {
 | 
				
			|||||||
        FURI_LOG_D(TAG, "Writing page %d", i);
 | 
					        FURI_LOG_D(TAG, "Writing page %d", i);
 | 
				
			||||||
        furi_hal_random_fill_buf(page.data, sizeof(MfUltralightPage));
 | 
					        furi_hal_random_fill_buf(page.data, sizeof(MfUltralightPage));
 | 
				
			||||||
        mfu_data->page[i] = page;
 | 
					        mfu_data->page[i] = page;
 | 
				
			||||||
        error = mf_ultralight_poller_write_page(poller, i, &page);
 | 
					        error = mf_ultralight_poller_sync_write_page(poller, i, &page);
 | 
				
			||||||
        mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_write_page() failed");
 | 
					        mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_write_page() failed");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Verification read
 | 
					    // Verification read
 | 
				
			||||||
    error = mf_ultralight_poller_read_card(poller, mfu_data);
 | 
					    error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
 | 
				
			||||||
    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
 | 
					    mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(mfu_listener);
 | 
					    nfc_listener_stop(mfu_listener);
 | 
				
			||||||
    const MfUltralightData* mfu_listener_data =
 | 
					    const MfUltralightData* mfu_listener_data =
 | 
				
			||||||
@ -355,7 +355,7 @@ static void mf_classic_reader() {
 | 
				
			|||||||
    MfClassicBlock block = {};
 | 
					    MfClassicBlock block = {};
 | 
				
			||||||
    MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
 | 
					    MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_classic_poller_read_block(poller, 0, &key, MfClassicKeyTypeA, &block);
 | 
					    mf_classic_poller_sync_read_block(poller, 0, &key, MfClassicKeyTypeA, &block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(mfc_listener);
 | 
					    nfc_listener_stop(mfc_listener);
 | 
				
			||||||
    nfc_listener_free(mfc_listener);
 | 
					    nfc_listener_free(mfc_listener);
 | 
				
			||||||
@ -383,8 +383,8 @@ static void mf_classic_write() {
 | 
				
			|||||||
    furi_hal_random_fill_buf(block_write.data, sizeof(MfClassicBlock));
 | 
					    furi_hal_random_fill_buf(block_write.data, sizeof(MfClassicBlock));
 | 
				
			||||||
    MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
 | 
					    MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_classic_poller_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
 | 
					    mf_classic_poller_sync_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
 | 
				
			||||||
    mf_classic_poller_read_block(poller, 1, &key, MfClassicKeyTypeA, &block_read);
 | 
					    mf_classic_poller_sync_read_block(poller, 1, &key, MfClassicKeyTypeA, &block_read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nfc_listener_stop(mfc_listener);
 | 
					    nfc_listener_stop(mfc_listener);
 | 
				
			||||||
    nfc_listener_free(mfc_listener);
 | 
					    nfc_listener_free(mfc_listener);
 | 
				
			||||||
@ -413,16 +413,18 @@ static void mf_classic_value_block() {
 | 
				
			|||||||
    mf_classic_value_to_block(value, 1, &block_write);
 | 
					    mf_classic_value_to_block(value, 1, &block_write);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfClassicError error = MfClassicErrorNone;
 | 
					    MfClassicError error = MfClassicErrorNone;
 | 
				
			||||||
    error = mf_classic_poller_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
 | 
					    error = mf_classic_poller_sync_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
 | 
				
			||||||
    mu_assert(error == MfClassicErrorNone, "Write failed");
 | 
					    mu_assert(error == MfClassicErrorNone, "Write failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int32_t data = 200;
 | 
					    int32_t data = 200;
 | 
				
			||||||
    int32_t new_value = 0;
 | 
					    int32_t new_value = 0;
 | 
				
			||||||
    error = mf_classic_poller_change_value(poller, 1, &key, MfClassicKeyTypeA, data, &new_value);
 | 
					    error =
 | 
				
			||||||
 | 
					        mf_classic_poller_sync_change_value(poller, 1, &key, MfClassicKeyTypeA, data, &new_value);
 | 
				
			||||||
    mu_assert(error == MfClassicErrorNone, "Value increment failed");
 | 
					    mu_assert(error == MfClassicErrorNone, "Value increment failed");
 | 
				
			||||||
    mu_assert(new_value == value + data, "Value not match");
 | 
					    mu_assert(new_value == value + data, "Value not match");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    error = mf_classic_poller_change_value(poller, 1, &key, MfClassicKeyTypeA, -data, &new_value);
 | 
					    error =
 | 
				
			||||||
 | 
					        mf_classic_poller_sync_change_value(poller, 1, &key, MfClassicKeyTypeA, -data, &new_value);
 | 
				
			||||||
    mu_assert(error == MfClassicErrorNone, "Value decrement failed");
 | 
					    mu_assert(error == MfClassicErrorNone, "Value decrement failed");
 | 
				
			||||||
    mu_assert(new_value == value, "Value not match");
 | 
					    mu_assert(new_value == value, "Value not match");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <nfc/nfc_device.h>
 | 
					#include <nfc/nfc_device.h>
 | 
				
			||||||
#include <nfc/helpers/nfc_util.h>
 | 
					#include <nfc/helpers/nfc_util.h>
 | 
				
			||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync_api.h>
 | 
					#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TAG "Plantain"
 | 
					#define TAG "Plantain"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,7 +91,7 @@ static bool plantain_verify_type(Nfc* nfc, MfClassicType type) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        MfClassicAuthContext auth_context;
 | 
					        MfClassicAuthContext auth_context;
 | 
				
			||||||
        MfClassicError error =
 | 
					        MfClassicError error =
 | 
				
			||||||
            mf_classic_poller_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
 | 
					            mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -119,7 +119,7 @@ static bool plantain_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        MfClassicType type = MfClassicTypeMini;
 | 
					        MfClassicType type = MfClassicTypeMini;
 | 
				
			||||||
        MfClassicError error = mf_classic_poller_detect_type(nfc, &type);
 | 
					        MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data->type = type;
 | 
					        data->type = type;
 | 
				
			||||||
@ -134,7 +134,7 @@ static bool plantain_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
            FURI_BIT_SET(keys.key_b_mask, i);
 | 
					            FURI_BIT_SET(keys.key_b_mask, i);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_poller_read(nfc, &keys, data);
 | 
					        error = mf_classic_poller_sync_read(nfc, &keys, data);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_W(TAG, "Failed to read data");
 | 
					            FURI_LOG_W(TAG, "Failed to read data");
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <nfc/nfc_device.h>
 | 
					#include <nfc/nfc_device.h>
 | 
				
			||||||
#include <nfc/helpers/nfc_util.h>
 | 
					#include <nfc/helpers/nfc_util.h>
 | 
				
			||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync_api.h>
 | 
					#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TAG "Troika"
 | 
					#define TAG "Troika"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,7 +91,7 @@ static bool troika_verify_type(Nfc* nfc, MfClassicType type) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        MfClassicAuthContext auth_context;
 | 
					        MfClassicAuthContext auth_context;
 | 
				
			||||||
        MfClassicError error =
 | 
					        MfClassicError error =
 | 
				
			||||||
            mf_classic_poller_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
 | 
					            mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -118,7 +118,7 @@ static bool troika_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        MfClassicType type = MfClassicTypeMini;
 | 
					        MfClassicType type = MfClassicTypeMini;
 | 
				
			||||||
        MfClassicError error = mf_classic_poller_detect_type(nfc, &type);
 | 
					        MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data->type = type;
 | 
					        data->type = type;
 | 
				
			||||||
@ -136,7 +136,7 @@ static bool troika_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
            FURI_BIT_SET(keys.key_b_mask, i);
 | 
					            FURI_BIT_SET(keys.key_b_mask, i);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_poller_read(nfc, &keys, data);
 | 
					        error = mf_classic_poller_sync_read(nfc, &keys, data);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_W(TAG, "Failed to read data");
 | 
					            FURI_LOG_W(TAG, "Failed to read data");
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <nfc/nfc_device.h>
 | 
					#include <nfc/nfc_device.h>
 | 
				
			||||||
#include <nfc/helpers/nfc_util.h>
 | 
					#include <nfc/helpers/nfc_util.h>
 | 
				
			||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync_api.h>
 | 
					#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TAG "TwoCities"
 | 
					#define TAG "TwoCities"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,7 +49,7 @@ bool two_cities_verify(Nfc* nfc) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        MfClassicAuthContext auth_ctx = {};
 | 
					        MfClassicAuthContext auth_ctx = {};
 | 
				
			||||||
        MfClassicError error =
 | 
					        MfClassicError error =
 | 
				
			||||||
            mf_classic_poller_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
 | 
					            mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -72,7 +72,7 @@ static bool two_cities_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        MfClassicType type = MfClassicTypeMini;
 | 
					        MfClassicType type = MfClassicTypeMini;
 | 
				
			||||||
        MfClassicError error = mf_classic_poller_detect_type(nfc, &type);
 | 
					        MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data->type = type;
 | 
					        data->type = type;
 | 
				
			||||||
@ -84,7 +84,7 @@ static bool two_cities_read(Nfc* nfc, NfcDevice* device) {
 | 
				
			|||||||
            FURI_BIT_SET(keys.key_b_mask, i);
 | 
					            FURI_BIT_SET(keys.key_b_mask, i);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_poller_read(nfc, &keys, data);
 | 
					        error = mf_classic_poller_sync_read(nfc, &keys, data);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_W(TAG, "Failed to read data");
 | 
					            FURI_LOG_W(TAG, "Failed to read data");
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@ env.Append(
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    SDK_HEADERS=[
 | 
					    SDK_HEADERS=[
 | 
				
			||||||
        File("cc1101_regs.h"),
 | 
					        File("cc1101_regs.h"),
 | 
				
			||||||
 | 
					        File("st25r3916_reg.h"),
 | 
				
			||||||
 | 
					        File("st25r3916.h"),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,9 +36,9 @@ env.Append(
 | 
				
			|||||||
        File("protocols/mf_ultralight/mf_ultralight_listener.h"),
 | 
					        File("protocols/mf_ultralight/mf_ultralight_listener.h"),
 | 
				
			||||||
        File("protocols/mf_classic/mf_classic_listener.h"),
 | 
					        File("protocols/mf_classic/mf_classic_listener.h"),
 | 
				
			||||||
        # Sync API
 | 
					        # Sync API
 | 
				
			||||||
        File("protocols/iso14443_3a/iso14443_3a_poller_sync_api.h"),
 | 
					        File("protocols/iso14443_3a/iso14443_3a_poller_sync.h"),
 | 
				
			||||||
        File("protocols/mf_ultralight/mf_ultralight_poller_sync_api.h"),
 | 
					        File("protocols/mf_ultralight/mf_ultralight_poller_sync.h"),
 | 
				
			||||||
        File("protocols/mf_classic/mf_classic_poller_sync_api.h"),
 | 
					        File("protocols/mf_classic/mf_classic_poller_sync.h"),
 | 
				
			||||||
        # Misc
 | 
					        # Misc
 | 
				
			||||||
        File("helpers/nfc_util.h"),
 | 
					        File("helpers/nfc_util.h"),
 | 
				
			||||||
        File("helpers/iso14443_crc.h"),
 | 
					        File("helpers/iso14443_crc.h"),
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,9 @@ struct NfcPoller {
 | 
				
			|||||||
    NfcPollerList list;
 | 
					    NfcPollerList list;
 | 
				
			||||||
    NfcPollerSessionState session_state;
 | 
					    NfcPollerSessionState session_state;
 | 
				
			||||||
    bool protocol_detected;
 | 
					    bool protocol_detected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcGenericCallbackEx callback;
 | 
				
			||||||
 | 
					    void* context;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nfc_poller_list_alloc(NfcPoller* instance) {
 | 
					static void nfc_poller_list_alloc(NfcPoller* instance) {
 | 
				
			||||||
@ -127,6 +130,75 @@ void nfc_poller_start(NfcPoller* instance, NfcGenericCallback callback, void* co
 | 
				
			|||||||
    nfc_start(instance->nfc, nfc_poller_start_callback, instance);
 | 
					    nfc_start(instance->nfc, nfc_poller_start_callback, instance);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static NfcCommand nfc_poller_start_ex_tail_callback(NfcGenericEvent event, void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    furi_assert(event.protocol != NfcProtocolInvalid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcPoller* instance = context;
 | 
				
			||||||
 | 
					    NfcCommand command = NfcCommandContinue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcGenericEventEx poller_event = {
 | 
				
			||||||
 | 
					        .poller = instance->list.tail->poller,
 | 
				
			||||||
 | 
					        .parent_event_data = event.event_data,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = instance->callback(poller_event, instance->context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return command;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static NfcCommand nfc_poller_start_ex_head_callback(NfcEvent event, void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcCommand command = NfcCommandContinue;
 | 
				
			||||||
 | 
					    NfcPoller* instance = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcProtocol parent_protocol = nfc_protocol_get_parent(instance->protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(parent_protocol == NfcProtocolInvalid) {
 | 
				
			||||||
 | 
					        NfcGenericEventEx poller_event = {
 | 
				
			||||||
 | 
					            .poller = instance->list.tail->poller,
 | 
				
			||||||
 | 
					            .parent_event_data = &event,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        command = instance->callback(poller_event, instance->context);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        NfcGenericEvent poller_event = {
 | 
				
			||||||
 | 
					            .protocol = NfcProtocolInvalid,
 | 
				
			||||||
 | 
					            .instance = instance->nfc,
 | 
				
			||||||
 | 
					            .event_data = &event,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        NfcPollerListElement* head_poller = instance->list.head;
 | 
				
			||||||
 | 
					        command = head_poller->poller_api->run(poller_event, head_poller->poller);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(instance->session_state == NfcPollerSessionStateStopRequest) {
 | 
				
			||||||
 | 
					        command = NfcCommandStop;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return command;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nfc_poller_start_ex(NfcPoller* instance, NfcGenericCallbackEx callback, void* context) {
 | 
				
			||||||
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					    furi_assert(callback);
 | 
				
			||||||
 | 
					    furi_assert(instance->session_state == NfcPollerSessionStateIdle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    instance->callback = callback;
 | 
				
			||||||
 | 
					    instance->context = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NfcProtocol parent_protocol = nfc_protocol_get_parent(instance->protocol);
 | 
				
			||||||
 | 
					    if(parent_protocol != NfcProtocolInvalid) {
 | 
				
			||||||
 | 
					        NfcPollerListElement* iter = instance->list.head;
 | 
				
			||||||
 | 
					        while(iter->protocol != parent_protocol) iter = iter->child;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        iter->poller_api->set_callback(iter->poller, nfc_poller_start_ex_tail_callback, instance);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    instance->session_state = NfcPollerSessionStateActive;
 | 
				
			||||||
 | 
					    nfc_start(instance->nfc, nfc_poller_start_ex_head_callback, instance);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nfc_poller_stop(NfcPoller* instance) {
 | 
					void nfc_poller_stop(NfcPoller* instance) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,31 @@ extern "C" {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct NfcPoller NfcPoller;
 | 
					typedef struct NfcPoller NfcPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Extended generic Nfc event type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * An extended generic Nfc event contains protocol poller and it's parent protocol event data.
 | 
				
			||||||
 | 
					 * If protocol has no parent, then events are produced by Nfc instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The parent_event_data field is protocol-specific and should be cast to the appropriate type before use.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    NfcGenericInstance* poller; /**< Pointer to the protocol poller. */
 | 
				
			||||||
 | 
					    NfcGenericEventData*
 | 
				
			||||||
 | 
					        parent_event_data /**< Pointer to the protocol's parent poller event data. */;
 | 
				
			||||||
 | 
					} NfcGenericEventEx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Extended generic Nfc event callback type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A function of this type must be passed as the callback parameter upon extended start of a poller.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param [in] event Nfc  extended generic event, passed by value, complete with protocol type and data.
 | 
				
			||||||
 | 
					 * @param [in,out] context pointer to the user-specific context (set when starting a poller/listener instance).
 | 
				
			||||||
 | 
					 * @returns the command which the event producer must execute.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef NfcCommand (*NfcGenericCallbackEx)(NfcGenericEventEx event, void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Allocate an NfcPoller instance.
 | 
					 * @brief Allocate an NfcPoller instance.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -57,6 +82,18 @@ void nfc_poller_free(NfcPoller* instance);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void nfc_poller_start(NfcPoller* instance, NfcGenericCallback callback, void* context);
 | 
					void nfc_poller_start(NfcPoller* instance, NfcGenericCallback callback, void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Start an NfcPoller instance in extended mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * When nfc poller is started in extended mode, callback will be called with parent protocol events
 | 
				
			||||||
 | 
					 * and protocol instance. This mode enables to make custom poller state machines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in,out] instance pointer to the instance to be started.
 | 
				
			||||||
 | 
					 * @param[in] callback pointer to a user-defined callback function which will receive events.
 | 
				
			||||||
 | 
					 * @param[in] context pointer to a user-specific context (will be passed to the callback).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nfc_poller_start_ex(NfcPoller* instance, NfcGenericCallbackEx callback, void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Stop an NfcPoller instance.
 | 
					 * @brief Stop an NfcPoller instance.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -66,7 +66,7 @@ static NfcCommand felica_poller_run(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        if(instance->state != FelicaPollerStateActivated) {
 | 
					        if(instance->state != FelicaPollerStateActivated) {
 | 
				
			||||||
            FelicaError error = felica_poller_async_activate(instance, instance->data);
 | 
					            FelicaError error = felica_poller_activate(instance, instance->data);
 | 
				
			||||||
            if(error == FelicaErrorNone) {
 | 
					            if(error == FelicaErrorNone) {
 | 
				
			||||||
                instance->felica_event.type = FelicaPollerEventTypeReady;
 | 
					                instance->felica_event.type = FelicaPollerEventTypeReady;
 | 
				
			||||||
                instance->felica_event_data.error = error;
 | 
					                instance->felica_event_data.error = error;
 | 
				
			||||||
@ -100,7 +100,7 @@ static bool felica_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    furi_assert(instance->state == FelicaPollerStateIdle);
 | 
					    furi_assert(instance->state == FelicaPollerStateIdle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        FelicaError error = felica_poller_async_activate(instance, instance->data);
 | 
					        FelicaError error = felica_poller_activate(instance, instance->data);
 | 
				
			||||||
        protocol_detected = (error == FelicaErrorNone);
 | 
					        protocol_detected = (error == FelicaErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,22 +9,50 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief FelicaPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct FelicaPoller FelicaPoller;
 | 
					typedef struct FelicaPoller FelicaPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Felica poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    FelicaPollerEventTypeError,
 | 
					    FelicaPollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    FelicaPollerEventTypeReady,
 | 
					    FelicaPollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} FelicaPollerEventType;
 | 
					} FelicaPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    FelicaError error;
 | 
					 * @brief Felica poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    FelicaError error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} FelicaPollerEventData;
 | 
					} FelicaPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief FelicaPoller poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    FelicaPollerEventType type;
 | 
					    FelicaPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    FelicaPollerEventData* data;
 | 
					    FelicaPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} FelicaPollerEvent;
 | 
					} FelicaPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform collision resolution procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perfoms the collision resolution procedure as defined in FeliCa standars. The data
 | 
				
			||||||
 | 
					 * field will be filled with Felica data on success.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the Felica data structure to be filled.
 | 
				
			||||||
 | 
					 * @return FelicaErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					FelicaError felica_poller_activate(FelicaPoller* instance, FelicaData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,7 @@ static FelicaError felica_poller_frame_exchange(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FelicaError felica_poller_async_polling(
 | 
					FelicaError felica_poller_polling(
 | 
				
			||||||
    FelicaPoller* instance,
 | 
					    FelicaPoller* instance,
 | 
				
			||||||
    const FelicaPollerPollingCommand* cmd,
 | 
					    const FelicaPollerPollingCommand* cmd,
 | 
				
			||||||
    FelicaPollerPollingResponse* resp) {
 | 
					    FelicaPollerPollingResponse* resp) {
 | 
				
			||||||
@ -93,7 +93,7 @@ FelicaError felica_poller_async_polling(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FelicaError felica_poller_async_activate(FelicaPoller* instance, FelicaData* data) {
 | 
					FelicaError felica_poller_activate(FelicaPoller* instance, FelicaData* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    felica_reset(data);
 | 
					    felica_reset(data);
 | 
				
			||||||
@ -112,7 +112,7 @@ FelicaError felica_poller_async_activate(FelicaPoller* instance, FelicaData* dat
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        FelicaPollerPollingResponse polling_resp = {};
 | 
					        FelicaPollerPollingResponse polling_resp = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = felica_poller_async_polling(instance, &polling_cmd, &polling_resp);
 | 
					        ret = felica_poller_polling(instance, &polling_cmd, &polling_resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(ret != FelicaErrorNone) {
 | 
					        if(ret != FelicaErrorNone) {
 | 
				
			||||||
            FURI_LOG_T(TAG, "Activation failed error: %d", ret);
 | 
					            FURI_LOG_T(TAG, "Activation failed error: %d", ret);
 | 
				
			||||||
 | 
				
			|||||||
@ -48,13 +48,11 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const FelicaData* felica_poller_get_data(FelicaPoller* instance);
 | 
					const FelicaData* felica_poller_get_data(FelicaPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FelicaError felica_poller_async_polling(
 | 
					FelicaError felica_poller_polling(
 | 
				
			||||||
    FelicaPoller* instance,
 | 
					    FelicaPoller* instance,
 | 
				
			||||||
    const FelicaPollerPollingCommand* cmd,
 | 
					    const FelicaPollerPollingCommand* cmd,
 | 
				
			||||||
    FelicaPollerPollingResponse* resp);
 | 
					    FelicaPollerPollingResponse* resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FelicaError felica_poller_async_activate(FelicaPoller* instance, FelicaData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ static NfcCommand iso14443_3a_poller_run(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        if(instance->state != Iso14443_3aPollerStateActivated) {
 | 
					        if(instance->state != Iso14443_3aPollerStateActivated) {
 | 
				
			||||||
            Iso14443_3aData data = {};
 | 
					            Iso14443_3aData data = {};
 | 
				
			||||||
            Iso14443_3aError error = iso14443_3a_poller_async_activate(instance, &data);
 | 
					            Iso14443_3aError error = iso14443_3a_poller_activate(instance, &data);
 | 
				
			||||||
            if(error == Iso14443_3aErrorNone) {
 | 
					            if(error == Iso14443_3aErrorNone) {
 | 
				
			||||||
                instance->state = Iso14443_3aPollerStateActivated;
 | 
					                instance->state = Iso14443_3aPollerStateActivated;
 | 
				
			||||||
                instance->iso14443_3a_event.type = Iso14443_3aPollerEventTypeReady;
 | 
					                instance->iso14443_3a_event.type = Iso14443_3aPollerEventTypeReady;
 | 
				
			||||||
@ -111,7 +111,7 @@ static bool iso14443_3a_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    furi_assert(instance->state == Iso14443_3aPollerStateIdle);
 | 
					    furi_assert(instance->state == Iso14443_3aPollerStateIdle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        Iso14443_3aError error = iso14443_3a_poller_async_activate(instance, NULL);
 | 
					        Iso14443_3aError error = iso14443_3a_poller_activate(instance, NULL);
 | 
				
			||||||
        protocol_detected = (error == Iso14443_3aErrorNone);
 | 
					        protocol_detected = (error == Iso14443_3aErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,34 +9,137 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_3aPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct Iso14443_3aPoller Iso14443_3aPoller;
 | 
					typedef struct Iso14443_3aPoller Iso14443_3aPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Iso14443_3a poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    Iso14443_3aPollerEventTypeError,
 | 
					    Iso14443_3aPollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    Iso14443_3aPollerEventTypeReady,
 | 
					    Iso14443_3aPollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} Iso14443_3aPollerEventType;
 | 
					} Iso14443_3aPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    Iso14443_3aError error;
 | 
					 * @brief Iso14443_3a poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    Iso14443_3aError error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} Iso14443_3aPollerEventData;
 | 
					} Iso14443_3aPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_3a poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    Iso14443_3aPollerEventType type;
 | 
					    Iso14443_3aPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    Iso14443_3aPollerEventData* data;
 | 
					    Iso14443_3aPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} Iso14443_3aPollerEvent;
 | 
					} Iso14443_3aPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_3a frames in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_txrx(
 | 
					Iso14443_3aError iso14443_3a_poller_txrx(
 | 
				
			||||||
    Iso14443_3aPoller* instance,
 | 
					    Iso14443_3aPoller* instance,
 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
    BitBuffer* rx_buffer,
 | 
					    BitBuffer* rx_buffer,
 | 
				
			||||||
    uint32_t fwt);
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_3a standard frames in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_send_standard_frame(
 | 
					Iso14443_3aError iso14443_3a_poller_send_standard_frame(
 | 
				
			||||||
    Iso14443_3aPoller* instance,
 | 
					    Iso14443_3aPoller* instance,
 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
    BitBuffer* rx_buffer,
 | 
					    BitBuffer* rx_buffer,
 | 
				
			||||||
    uint32_t fwt);
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_3a frames with custom parity bits in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Custom parity bits must be set in the tx_buffer. The rx_buffer will contain
 | 
				
			||||||
 | 
					 * the received data with the parity bits.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3aError iso14443_3a_poller_txrx_custom_parity(
 | 
				
			||||||
 | 
					    Iso14443_3aPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer,
 | 
				
			||||||
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Checks presence of Iso14443_3a complient card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone if card is present, an error code otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3aError iso14443_3a_poller_check_presence(Iso14443_3aPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform collision resolution procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perfoms the collision resolution procedure as defined in Iso14443-3a. The iso14443_3a_data
 | 
				
			||||||
 | 
					 * field will be filled with Iso14443-3a data on success.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] iso14443_3a_data pointer to the Iso14443_3a data structure to be filled.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3aError
 | 
				
			||||||
 | 
					    iso14443_3a_poller_activate(Iso14443_3aPoller* instance, Iso14443_3aData* iso14443_3a_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send HALT command to the card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Halts card and changes internal Iso14443_3aPoller state to Idle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return Iso14443_3aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3aError iso14443_3a_poller_halt(Iso14443_3aPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -94,9 +94,8 @@ Iso14443_3aError iso14443_3a_poller_halt(Iso14443_3aPoller* instance) {
 | 
				
			|||||||
    return Iso14443_3aErrorNone;
 | 
					    return Iso14443_3aErrorNone;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_async_activate(
 | 
					Iso14443_3aError
 | 
				
			||||||
    Iso14443_3aPoller* instance,
 | 
					    iso14443_3a_poller_activate(Iso14443_3aPoller* instance, Iso14443_3aData* iso14443_3a_data) {
 | 
				
			||||||
    Iso14443_3aData* iso14443_3a_data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
    furi_assert(instance->tx_buffer);
 | 
					    furi_assert(instance->tx_buffer);
 | 
				
			||||||
 | 
				
			|||||||
@ -39,15 +39,9 @@ typedef enum {
 | 
				
			|||||||
    Iso14443_3aPollerStateActivated,
 | 
					    Iso14443_3aPollerStateActivated,
 | 
				
			||||||
} Iso14443_3aPollerState;
 | 
					} Iso14443_3aPollerState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    Iso14443_3aPollerConfigStateIdle,
 | 
					 | 
				
			||||||
    Iso14443_3aPollerConfigStateDone,
 | 
					 | 
				
			||||||
} Iso14443_3aPollerConfigState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Iso14443_3aPoller {
 | 
					struct Iso14443_3aPoller {
 | 
				
			||||||
    Nfc* nfc;
 | 
					    Nfc* nfc;
 | 
				
			||||||
    Iso14443_3aPollerState state;
 | 
					    Iso14443_3aPollerState state;
 | 
				
			||||||
    Iso14443_3aPollerConfigState config_state;
 | 
					 | 
				
			||||||
    Iso14443_3aPollerColRes col_res;
 | 
					    Iso14443_3aPollerColRes col_res;
 | 
				
			||||||
    Iso14443_3aData* data;
 | 
					    Iso14443_3aData* data;
 | 
				
			||||||
    BitBuffer* tx_buffer;
 | 
					    BitBuffer* tx_buffer;
 | 
				
			||||||
@ -62,20 +56,6 @@ struct Iso14443_3aPoller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Iso14443_3aData* iso14443_3a_poller_get_data(Iso14443_3aPoller* instance);
 | 
					const Iso14443_3aData* iso14443_3a_poller_get_data(Iso14443_3aPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_check_presence(Iso14443_3aPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_async_activate(
 | 
					 | 
				
			||||||
    Iso14443_3aPoller* instance,
 | 
					 | 
				
			||||||
    Iso14443_3aData* iso14443_3a_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_halt(Iso14443_3aPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_txrx_custom_parity(
 | 
					 | 
				
			||||||
    Iso14443_3aPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer,
 | 
					 | 
				
			||||||
    uint32_t fwt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
#include "iso14443_3a_poller_sync_api.h"
 | 
					#include "iso14443_3a_poller_sync.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "iso14443_3a_poller_i.h"
 | 
					#include "iso14443_3a_poller_i.h"
 | 
				
			||||||
#include <nfc/nfc_poller.h>
 | 
					#include <nfc/nfc_poller.h>
 | 
				
			||||||
@ -34,7 +34,7 @@ NfcCommand iso14443_3a_poller_read_callback(NfcGenericEvent event, void* context
 | 
				
			|||||||
    return NfcCommandStop;
 | 
					    return NfcCommandStop;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_read(Nfc* nfc, Iso14443_3aData* iso14443_3a_data) {
 | 
					Iso14443_3aError iso14443_3a_poller_sync_read(Nfc* nfc, Iso14443_3aData* iso14443_3a_data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(iso14443_3a_data);
 | 
					    furi_assert(iso14443_3a_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3aError iso14443_3a_poller_read(Nfc* nfc, Iso14443_3aData* iso14443_3a_data);
 | 
					Iso14443_3aError iso14443_3a_poller_sync_read(Nfc* nfc, Iso14443_3aData* iso14443_3a_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -70,7 +70,7 @@ static NfcCommand iso14443_3b_poller_run(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        if(instance->state != Iso14443_3bPollerStateActivated) {
 | 
					        if(instance->state != Iso14443_3bPollerStateActivated) {
 | 
				
			||||||
            Iso14443_3bError error = iso14443_3b_poller_async_activate(instance, instance->data);
 | 
					            Iso14443_3bError error = iso14443_3b_poller_activate(instance, instance->data);
 | 
				
			||||||
            if(error == Iso14443_3bErrorNone) {
 | 
					            if(error == Iso14443_3bErrorNone) {
 | 
				
			||||||
                instance->iso14443_3b_event.type = Iso14443_3bPollerEventTypeReady;
 | 
					                instance->iso14443_3b_event.type = Iso14443_3bPollerEventTypeReady;
 | 
				
			||||||
                instance->iso14443_3b_event_data.error = error;
 | 
					                instance->iso14443_3b_event_data.error = error;
 | 
				
			||||||
@ -104,7 +104,7 @@ static bool iso14443_3b_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    furi_assert(instance->state == Iso14443_3bPollerStateIdle);
 | 
					    furi_assert(instance->state == Iso14443_3bPollerStateIdle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        Iso14443_3bError error = iso14443_3b_poller_async_activate(instance, instance->data);
 | 
					        Iso14443_3bError error = iso14443_3b_poller_activate(instance, instance->data);
 | 
				
			||||||
        protocol_detected = (error == Iso14443_3bErrorNone);
 | 
					        protocol_detected = (error == Iso14443_3bErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,22 +9,81 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_3bPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct Iso14443_3bPoller Iso14443_3bPoller;
 | 
					typedef struct Iso14443_3bPoller Iso14443_3bPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Iso14443_3b poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    Iso14443_3bPollerEventTypeError,
 | 
					    Iso14443_3bPollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    Iso14443_3bPollerEventTypeReady,
 | 
					    Iso14443_3bPollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} Iso14443_3bPollerEventType;
 | 
					} Iso14443_3bPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    Iso14443_3bError error;
 | 
					 * @brief Iso14443_3b poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    Iso14443_3bError error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} Iso14443_3bPollerEventData;
 | 
					} Iso14443_3bPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_3b poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    Iso14443_3bPollerEventType type;
 | 
					    Iso14443_3bPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    Iso14443_3bPollerEventData* data;
 | 
					    Iso14443_3bPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} Iso14443_3bPollerEvent;
 | 
					} Iso14443_3bPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_3b frames in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return Iso14443_3bErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3bError iso14443_3b_poller_send_frame(
 | 
				
			||||||
 | 
					    Iso14443_3bPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform collision resolution procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perfoms the collision resolution procedure as defined in Iso14443-3b. The data
 | 
				
			||||||
 | 
					 * field will be filled with Iso14443-3b data on success.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the Iso14443_3b data structure to be filled.
 | 
				
			||||||
 | 
					 * @return Iso14443_3bErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3bError iso14443_3b_poller_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send HALT command to the card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Halts card and changes internal Iso14443_3bPoller state to Idle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return Iso14443_3bErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_3bError iso14443_3b_poller_halt(Iso14443_3bPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ static Iso14443_3bError iso14443_3b_poller_prepare_trx(Iso14443_3bPoller* instan
 | 
				
			|||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(instance->state == Iso14443_3bPollerStateIdle) {
 | 
					    if(instance->state == Iso14443_3bPollerStateIdle) {
 | 
				
			||||||
        return iso14443_3b_poller_async_activate(instance, NULL);
 | 
					        return iso14443_3b_poller_activate(instance, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Iso14443_3bErrorNone;
 | 
					    return Iso14443_3bErrorNone;
 | 
				
			||||||
@ -63,8 +63,7 @@ static Iso14443_3bError iso14443_3b_poller_frame_exchange(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3bError
 | 
					Iso14443_3bError iso14443_3b_poller_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data) {
 | 
				
			||||||
    iso14443_3b_poller_async_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -34,16 +34,6 @@ struct Iso14443_3bPoller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Iso14443_3bData* iso14443_3b_poller_get_data(Iso14443_3bPoller* instance);
 | 
					const Iso14443_3bData* iso14443_3b_poller_get_data(Iso14443_3bPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_3bError
 | 
					 | 
				
			||||||
    iso14443_3b_poller_async_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_3bError iso14443_3b_poller_halt(Iso14443_3bPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_3bError iso14443_3b_poller_send_frame(
 | 
					 | 
				
			||||||
    Iso14443_3bPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
 | 
					#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <lib/toolbox/simple_array.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -28,7 +30,19 @@ typedef enum {
 | 
				
			|||||||
    Iso14443_4aFrameOptionCid,
 | 
					    Iso14443_4aFrameOptionCid,
 | 
				
			||||||
} Iso14443_4aFrameOption;
 | 
					} Iso14443_4aFrameOption;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct Iso14443_4aData Iso14443_4aData;
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint8_t tl;
 | 
				
			||||||
 | 
					    uint8_t t0;
 | 
				
			||||||
 | 
					    uint8_t ta_1;
 | 
				
			||||||
 | 
					    uint8_t tb_1;
 | 
				
			||||||
 | 
					    uint8_t tc_1;
 | 
				
			||||||
 | 
					    SimpleArray* t1_tk;
 | 
				
			||||||
 | 
					} Iso14443_4aAtsData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    Iso14443_3aData* iso14443_3a_data;
 | 
				
			||||||
 | 
					    Iso14443_4aAtsData ats_data;
 | 
				
			||||||
 | 
					} Iso14443_4aData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Virtual methods
 | 
					// Virtual methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "iso14443_4a.h"
 | 
					#include "iso14443_4a.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <lib/toolbox/simple_array.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ISO14443_4A_CMD_READ_ATS (0xE0)
 | 
					#define ISO14443_4A_CMD_READ_ATS (0xE0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ATS bit definitions
 | 
					// ATS bit definitions
 | 
				
			||||||
@ -23,20 +21,6 @@
 | 
				
			|||||||
#define ISO14443_4A_ATS_TC1_NAD (1U << 0)
 | 
					#define ISO14443_4A_ATS_TC1_NAD (1U << 0)
 | 
				
			||||||
#define ISO14443_4A_ATS_TC1_CID (1U << 1)
 | 
					#define ISO14443_4A_ATS_TC1_CID (1U << 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint8_t tl;
 | 
					 | 
				
			||||||
    uint8_t t0;
 | 
					 | 
				
			||||||
    uint8_t ta_1;
 | 
					 | 
				
			||||||
    uint8_t tb_1;
 | 
					 | 
				
			||||||
    uint8_t tc_1;
 | 
					 | 
				
			||||||
    SimpleArray* t1_tk;
 | 
					 | 
				
			||||||
} Iso14443_4aAtsData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Iso14443_4aData {
 | 
					 | 
				
			||||||
    Iso14443_3aData* iso14443_3a_data;
 | 
					 | 
				
			||||||
    Iso14443_4aAtsData ats_data;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool iso14443_4a_ats_parse(Iso14443_4aAtsData* data, const BitBuffer* buf);
 | 
					bool iso14443_4a_ats_parse(Iso14443_4aAtsData* data, const BitBuffer* buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_4aError iso14443_4a_process_error(Iso14443_3aError error);
 | 
					Iso14443_4aError iso14443_4a_process_error(Iso14443_3aError error);
 | 
				
			||||||
 | 
				
			|||||||
@ -55,8 +55,7 @@ static NfcCommand iso14443_4a_poller_handler_idle(Iso14443_4aPoller* instance) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand iso14443_4a_poller_handler_read_ats(Iso14443_4aPoller* instance) {
 | 
					static NfcCommand iso14443_4a_poller_handler_read_ats(Iso14443_4aPoller* instance) {
 | 
				
			||||||
    Iso14443_4aError error =
 | 
					    Iso14443_4aError error = iso14443_4a_poller_read_ats(instance, &instance->data->ats_data);
 | 
				
			||||||
        iso14443_4a_poller_async_read_ats(instance, &instance->data->ats_data);
 | 
					 | 
				
			||||||
    if(error == Iso14443_4aErrorNone) {
 | 
					    if(error == Iso14443_4aErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read ATS success");
 | 
					        FURI_LOG_D(TAG, "Read ATS success");
 | 
				
			||||||
        instance->poller_state = Iso14443_4aPollerStateReady;
 | 
					        instance->poller_state = Iso14443_4aPollerStateReady;
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,80 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_4aPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct Iso14443_4aPoller Iso14443_4aPoller;
 | 
					typedef struct Iso14443_4aPoller Iso14443_4aPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Iso14443_4a poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    Iso14443_4aPollerEventTypeError,
 | 
					    Iso14443_4aPollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    Iso14443_4aPollerEventTypeReady,
 | 
					    Iso14443_4aPollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} Iso14443_4aPollerEventType;
 | 
					} Iso14443_4aPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    Iso14443_4aError error;
 | 
					 * @brief Iso14443_4a poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    Iso14443_4aError error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} Iso14443_4aPollerEventData;
 | 
					} Iso14443_4aPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_4a poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    Iso14443_4aPollerEventType type;
 | 
					    Iso14443_4aPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    Iso14443_4aPollerEventData* data;
 | 
					    Iso14443_4aPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} Iso14443_4aPollerEvent;
 | 
					} Iso14443_4aPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_4a blocks in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer. The fwt parameter is calculated during activation procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @return Iso14443_4aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_4aError iso14443_4a_poller_send_block(
 | 
				
			||||||
 | 
					    Iso14443_4aPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send HALT command to the card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Halts card and changes internal Iso14443_4aPoller state to Idle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return Iso14443_4aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_4aError iso14443_4a_poller_halt(Iso14443_4aPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read Answer To Select (ATS) from the card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Send Request Answer To Select (RATS) command to the card and parse the response.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the buffer to be filled with ATS data.
 | 
				
			||||||
 | 
					 * @return Iso14443_4aErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_4aError
 | 
				
			||||||
 | 
					    iso14443_4a_poller_read_ats(Iso14443_4aPoller* instance, Iso14443_4aAtsData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ Iso14443_4aError iso14443_4a_poller_halt(Iso14443_4aPoller* instance) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_4aError
 | 
					Iso14443_4aError
 | 
				
			||||||
    iso14443_4a_poller_async_read_ats(Iso14443_4aPoller* instance, Iso14443_4aAtsData* data) {
 | 
					    iso14443_4a_poller_read_ats(Iso14443_4aPoller* instance, Iso14443_4aAtsData* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->tx_buffer);
 | 
					    bit_buffer_reset(instance->tx_buffer);
 | 
				
			||||||
 | 
				
			|||||||
@ -45,16 +45,6 @@ struct Iso14443_4aPoller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Iso14443_4aData* iso14443_4a_poller_get_data(Iso14443_4aPoller* instance);
 | 
					const Iso14443_4aData* iso14443_4a_poller_get_data(Iso14443_4aPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_4aError iso14443_4a_poller_halt(Iso14443_4aPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_4aError
 | 
					 | 
				
			||||||
    iso14443_4a_poller_async_read_ats(Iso14443_4aPoller* instance, Iso14443_4aAtsData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_4aError iso14443_4a_poller_send_block(
 | 
					 | 
				
			||||||
    Iso14443_4aPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,66 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_4bPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct Iso14443_4bPoller Iso14443_4bPoller;
 | 
					typedef struct Iso14443_4bPoller Iso14443_4bPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Iso14443_4b poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    Iso14443_4bPollerEventTypeError,
 | 
					    Iso14443_4bPollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    Iso14443_4bPollerEventTypeReady,
 | 
					    Iso14443_4bPollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} Iso14443_4bPollerEventType;
 | 
					} Iso14443_4bPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    Iso14443_4bError error;
 | 
					 * @brief Iso14443_4b poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    Iso14443_4bError error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} Iso14443_4bPollerEventData;
 | 
					} Iso14443_4bPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso14443_4b poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    Iso14443_4bPollerEventType type;
 | 
					    Iso14443_4bPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    Iso14443_4bPollerEventData* data;
 | 
					    Iso14443_4bPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} Iso14443_4bPollerEvent;
 | 
					} Iso14443_4bPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso14443_4b blocks in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer. The fwt parameter is calculated during activation procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @return Iso14443_4bErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_4bError iso14443_4b_poller_send_block(
 | 
				
			||||||
 | 
					    Iso14443_4bPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send HALT command to the card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Halts card and changes internal Iso14443_4aPoller state to Idle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return Iso14443_4bErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso14443_4bError iso14443_4b_poller_halt(Iso14443_4bPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -42,13 +42,6 @@ struct Iso14443_4bPoller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Iso14443_4bData* iso14443_4b_poller_get_data(Iso14443_4bPoller* instance);
 | 
					const Iso14443_4bData* iso14443_4b_poller_get_data(Iso14443_4bPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso14443_4bError iso14443_4b_poller_halt(Iso14443_4bPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso14443_4bError iso14443_4b_poller_send_block(
 | 
					 | 
				
			||||||
    Iso14443_4bPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -70,7 +70,7 @@ static NfcCommand iso15693_3_poller_run(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        if(instance->state != Iso15693_3PollerStateActivated) {
 | 
					        if(instance->state != Iso15693_3PollerStateActivated) {
 | 
				
			||||||
            Iso15693_3Error error = iso15693_3_poller_async_activate(instance, instance->data);
 | 
					            Iso15693_3Error error = iso15693_3_poller_activate(instance, instance->data);
 | 
				
			||||||
            if(error == Iso15693_3ErrorNone) {
 | 
					            if(error == Iso15693_3ErrorNone) {
 | 
				
			||||||
                instance->iso15693_3_event.type = Iso15693_3PollerEventTypeReady;
 | 
					                instance->iso15693_3_event.type = Iso15693_3PollerEventTypeReady;
 | 
				
			||||||
                instance->iso15693_3_event_data.error = error;
 | 
					                instance->iso15693_3_event_data.error = error;
 | 
				
			||||||
@ -105,7 +105,7 @@ static bool iso15693_3_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        uint8_t uid[ISO15693_3_UID_SIZE];
 | 
					        uint8_t uid[ISO15693_3_UID_SIZE];
 | 
				
			||||||
        Iso15693_3Error error = iso15693_3_poller_async_inventory(instance, uid);
 | 
					        Iso15693_3Error error = iso15693_3_poller_inventory(instance, uid);
 | 
				
			||||||
        protocol_detected = (error == Iso15693_3ErrorNone);
 | 
					        protocol_detected = (error == Iso15693_3ErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,142 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso15693_3Poller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct Iso15693_3Poller Iso15693_3Poller;
 | 
					typedef struct Iso15693_3Poller Iso15693_3Poller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Iso15693_3 poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    Iso15693_3PollerEventTypeError,
 | 
					    Iso15693_3PollerEventTypeError, /**< The card was activated by the poller. */
 | 
				
			||||||
    Iso15693_3PollerEventTypeReady,
 | 
					    Iso15693_3PollerEventTypeReady, /**< An error occured during activation procedure. */
 | 
				
			||||||
} Iso15693_3PollerEventType;
 | 
					} Iso15693_3PollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    Iso15693_3Error error;
 | 
					 * @brief Iso15693_3 poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    Iso15693_3Error error; /**< Error code indicating card activation fail reason. */
 | 
				
			||||||
} Iso15693_3PollerEventData;
 | 
					} Iso15693_3PollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Iso15693_3 poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    Iso15693_3PollerEventType type;
 | 
					    Iso15693_3PollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    Iso15693_3PollerEventData* data;
 | 
					    Iso15693_3PollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} Iso15693_3PollerEvent;
 | 
					} Iso15693_3PollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Iso15693_3 frames in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_send_frame(
 | 
				
			||||||
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer,
 | 
				
			||||||
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform activation procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perfoms the activation procedure as defined in Iso15693_3. The data
 | 
				
			||||||
 | 
					 * field will be filled with Iso15693_3Data data on success.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the Iso15693_3 data structure to be filled.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_activate(Iso15693_3Poller* instance, Iso15693_3Data* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send invertory command and parse response.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] uid pointer to the buffer to be filled with the UID.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_inventory(Iso15693_3Poller* instance, uint8_t* uid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send get system info command and parse response.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the Iso15693_3SystemInfo structure to be filled.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error
 | 
				
			||||||
 | 
					    iso15693_3_poller_get_system_info(Iso15693_3Poller* instance, Iso15693_3SystemInfo* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read Iso15693_3 block.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the buffer to be filled with the block data.
 | 
				
			||||||
 | 
					 * @param[in] block_number block number to be read.
 | 
				
			||||||
 | 
					 * @param[in] block_size size of the block to be read.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_read_block(
 | 
				
			||||||
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
 | 
					    uint8_t* data,
 | 
				
			||||||
 | 
					    uint8_t block_number,
 | 
				
			||||||
 | 
					    uint8_t block_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read multiple Iso15693_3 blocks.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the buffer to be filled with the block data.
 | 
				
			||||||
 | 
					 * @param[in] block_count number of blocks to be read.
 | 
				
			||||||
 | 
					 * @param[in] block_size size of the blocks to be read.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_read_blocks(
 | 
				
			||||||
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
 | 
					    uint8_t* data,
 | 
				
			||||||
 | 
					    uint16_t block_count,
 | 
				
			||||||
 | 
					    uint8_t block_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Get Iso15693_3 block security status.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the buffer to be filled with the block security status.
 | 
				
			||||||
 | 
					 * @param[in] block_count block security number to be read.
 | 
				
			||||||
 | 
					 * @return Iso15693_3ErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Iso15693_3Error iso15693_3_poller_get_blocks_security(
 | 
				
			||||||
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
 | 
					    uint8_t* data,
 | 
				
			||||||
 | 
					    uint16_t block_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ static Iso15693_3Error iso15693_3_poller_prepare_trx(Iso15693_3Poller* instance)
 | 
				
			|||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(instance->state == Iso15693_3PollerStateIdle) {
 | 
					    if(instance->state == Iso15693_3PollerStateIdle) {
 | 
				
			||||||
        return iso15693_3_poller_async_activate(instance, NULL);
 | 
					        return iso15693_3_poller_activate(instance, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Iso15693_3ErrorNone;
 | 
					    return Iso15693_3ErrorNone;
 | 
				
			||||||
@ -80,8 +80,7 @@ static Iso15693_3Error iso15693_3_poller_frame_exchange(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error
 | 
					Iso15693_3Error iso15693_3_poller_activate(Iso15693_3Poller* instance, Iso15693_3Data* data) {
 | 
				
			||||||
    iso15693_3_poller_async_activate(Iso15693_3Poller* instance, Iso15693_3Data* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,7 +92,7 @@ Iso15693_3Error
 | 
				
			|||||||
        instance->state = Iso15693_3PollerStateColResInProgress;
 | 
					        instance->state = Iso15693_3PollerStateColResInProgress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Inventory: Mandatory command
 | 
					        // Inventory: Mandatory command
 | 
				
			||||||
        ret = iso15693_3_poller_async_inventory(instance, data->uid);
 | 
					        ret = iso15693_3_poller_inventory(instance, data->uid);
 | 
				
			||||||
        if(ret != Iso15693_3ErrorNone) {
 | 
					        if(ret != Iso15693_3ErrorNone) {
 | 
				
			||||||
            instance->state = Iso15693_3PollerStateColResFailed;
 | 
					            instance->state = Iso15693_3PollerStateColResFailed;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -103,7 +102,7 @@ Iso15693_3Error
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Get system info: Optional command
 | 
					        // Get system info: Optional command
 | 
				
			||||||
        Iso15693_3SystemInfo* system_info = &data->system_info;
 | 
					        Iso15693_3SystemInfo* system_info = &data->system_info;
 | 
				
			||||||
        ret = iso15693_3_poller_async_get_system_info(instance, system_info);
 | 
					        ret = iso15693_3_poller_get_system_info(instance, system_info);
 | 
				
			||||||
        if(ret != Iso15693_3ErrorNone) {
 | 
					        if(ret != Iso15693_3ErrorNone) {
 | 
				
			||||||
            ret = iso15693_3_poller_filter_error(ret);
 | 
					            ret = iso15693_3_poller_filter_error(ret);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -111,7 +110,7 @@ Iso15693_3Error
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Read blocks: Optional command
 | 
					        // Read blocks: Optional command
 | 
				
			||||||
        simple_array_init(data->block_data, system_info->block_count * system_info->block_size);
 | 
					        simple_array_init(data->block_data, system_info->block_count * system_info->block_size);
 | 
				
			||||||
        ret = iso15693_3_poller_async_read_blocks(
 | 
					        ret = iso15693_3_poller_read_blocks(
 | 
				
			||||||
            instance,
 | 
					            instance,
 | 
				
			||||||
            simple_array_get_data(data->block_data),
 | 
					            simple_array_get_data(data->block_data),
 | 
				
			||||||
            system_info->block_count,
 | 
					            system_info->block_count,
 | 
				
			||||||
@ -124,7 +123,7 @@ Iso15693_3Error
 | 
				
			|||||||
        // Get block security status: Optional command
 | 
					        // Get block security status: Optional command
 | 
				
			||||||
        simple_array_init(data->block_security, system_info->block_count);
 | 
					        simple_array_init(data->block_security, system_info->block_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = iso15693_3_poller_async_get_blocks_security(
 | 
					        ret = iso15693_3_poller_get_blocks_security(
 | 
				
			||||||
            instance, simple_array_get_data(data->block_security), system_info->block_count);
 | 
					            instance, simple_array_get_data(data->block_security), system_info->block_count);
 | 
				
			||||||
        if(ret != Iso15693_3ErrorNone) {
 | 
					        if(ret != Iso15693_3ErrorNone) {
 | 
				
			||||||
            ret = iso15693_3_poller_filter_error(ret);
 | 
					            ret = iso15693_3_poller_filter_error(ret);
 | 
				
			||||||
@ -136,7 +135,7 @@ Iso15693_3Error
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_inventory(Iso15693_3Poller* instance, uint8_t* uid) {
 | 
					Iso15693_3Error iso15693_3_poller_inventory(Iso15693_3Poller* instance, uint8_t* uid) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
    furi_assert(uid);
 | 
					    furi_assert(uid);
 | 
				
			||||||
@ -165,9 +164,8 @@ Iso15693_3Error iso15693_3_poller_async_inventory(Iso15693_3Poller* instance, ui
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_get_system_info(
 | 
					Iso15693_3Error
 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					    iso15693_3_poller_get_system_info(Iso15693_3Poller* instance, Iso15693_3SystemInfo* data) {
 | 
				
			||||||
    Iso15693_3SystemInfo* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -193,7 +191,7 @@ Iso15693_3Error iso15693_3_poller_async_get_system_info(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_read_block(
 | 
					Iso15693_3Error iso15693_3_poller_read_block(
 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
    uint8_t* data,
 | 
					    uint8_t* data,
 | 
				
			||||||
    uint8_t block_number,
 | 
					    uint8_t block_number,
 | 
				
			||||||
@ -222,7 +220,7 @@ Iso15693_3Error iso15693_3_poller_async_read_block(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_read_blocks(
 | 
					Iso15693_3Error iso15693_3_poller_read_blocks(
 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
    uint8_t* data,
 | 
					    uint8_t* data,
 | 
				
			||||||
    uint16_t block_count,
 | 
					    uint16_t block_count,
 | 
				
			||||||
@ -235,14 +233,14 @@ Iso15693_3Error iso15693_3_poller_async_read_blocks(
 | 
				
			|||||||
    Iso15693_3Error ret = Iso15693_3ErrorNone;
 | 
					    Iso15693_3Error ret = Iso15693_3ErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(uint32_t i = 0; i < block_count; ++i) {
 | 
					    for(uint32_t i = 0; i < block_count; ++i) {
 | 
				
			||||||
        ret = iso15693_3_poller_async_read_block(instance, &data[block_size * i], i, block_size);
 | 
					        ret = iso15693_3_poller_read_block(instance, &data[block_size * i], i, block_size);
 | 
				
			||||||
        if(ret != Iso15693_3ErrorNone) break;
 | 
					        if(ret != Iso15693_3ErrorNone) break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_get_blocks_security(
 | 
					Iso15693_3Error iso15693_3_poller_get_blocks_security(
 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					    Iso15693_3Poller* instance,
 | 
				
			||||||
    uint8_t* data,
 | 
					    uint8_t* data,
 | 
				
			||||||
    uint16_t block_count) {
 | 
					    uint16_t block_count) {
 | 
				
			||||||
 | 
				
			|||||||
@ -35,36 +35,6 @@ struct Iso15693_3Poller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Iso15693_3Data* iso15693_3_poller_get_data(Iso15693_3Poller* instance);
 | 
					const Iso15693_3Data* iso15693_3_poller_get_data(Iso15693_3Poller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_activate(Iso15693_3Poller* instance, Iso15693_3Data* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_inventory(Iso15693_3Poller* instance, uint8_t* uid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error
 | 
					 | 
				
			||||||
    iso15693_3_poller_async_get_system_info(Iso15693_3Poller* instance, Iso15693_3SystemInfo* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_read_block(
 | 
					 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					 | 
				
			||||||
    uint8_t* data,
 | 
					 | 
				
			||||||
    uint8_t block_number,
 | 
					 | 
				
			||||||
    uint8_t block_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_read_blocks(
 | 
					 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					 | 
				
			||||||
    uint8_t* data,
 | 
					 | 
				
			||||||
    uint16_t block_count,
 | 
					 | 
				
			||||||
    uint8_t block_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_async_get_blocks_security(
 | 
					 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					 | 
				
			||||||
    uint8_t* data,
 | 
					 | 
				
			||||||
    uint16_t block_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Iso15693_3Error iso15693_3_poller_send_frame(
 | 
					 | 
				
			||||||
    Iso15693_3Poller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer,
 | 
					 | 
				
			||||||
    uint32_t fwt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ NfcCommand mf_classic_poller_handler_detect_type(MfClassicPoller* instance) {
 | 
				
			|||||||
        iso14443_3a_copy(
 | 
					        iso14443_3a_copy(
 | 
				
			||||||
            instance->data->iso14443_3a_data,
 | 
					            instance->data->iso14443_3a_data,
 | 
				
			||||||
            iso14443_3a_poller_get_data(instance->iso14443_3a_poller));
 | 
					            iso14443_3a_poller_get_data(instance->iso14443_3a_poller));
 | 
				
			||||||
        MfClassicError error = mf_classic_async_get_nt(instance, 254, MfClassicKeyTypeA, NULL);
 | 
					        MfClassicError error = mf_classic_poller_get_nt(instance, 254, MfClassicKeyTypeA, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            instance->data->type = MfClassicType4k;
 | 
					            instance->data->type = MfClassicType4k;
 | 
				
			||||||
            instance->state = MfClassicPollerStateStart;
 | 
					            instance->state = MfClassicPollerStateStart;
 | 
				
			||||||
@ -95,7 +95,7 @@ NfcCommand mf_classic_poller_handler_detect_type(MfClassicPoller* instance) {
 | 
				
			|||||||
            instance->current_type_check = MfClassicType1k;
 | 
					            instance->current_type_check = MfClassicType1k;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else if(instance->current_type_check == MfClassicType1k) {
 | 
					    } else if(instance->current_type_check == MfClassicType1k) {
 | 
				
			||||||
        MfClassicError error = mf_classic_async_get_nt(instance, 62, MfClassicKeyTypeA, NULL);
 | 
					        MfClassicError error = mf_classic_poller_get_nt(instance, 62, MfClassicKeyTypeA, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            instance->data->type = MfClassicType1k;
 | 
					            instance->data->type = MfClassicType1k;
 | 
				
			||||||
            FURI_LOG_D(TAG, "1K detected");
 | 
					            FURI_LOG_D(TAG, "1K detected");
 | 
				
			||||||
@ -234,7 +234,7 @@ NfcCommand mf_classic_poller_handler_read_block(MfClassicPoller* instance) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        // Authenticate to sector
 | 
					        // Authenticate to sector
 | 
				
			||||||
        error = mf_classic_async_auth(
 | 
					        error = mf_classic_poller_auth(
 | 
				
			||||||
            instance, write_ctx->current_block, auth_key, write_ctx->key_type_read, NULL);
 | 
					            instance, write_ctx->current_block, auth_key, write_ctx->key_type_read, NULL);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to auth to block %d", write_ctx->current_block);
 | 
					            FURI_LOG_D(TAG, "Failed to auth to block %d", write_ctx->current_block);
 | 
				
			||||||
@ -243,8 +243,8 @@ NfcCommand mf_classic_poller_handler_read_block(MfClassicPoller* instance) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Read block from tag
 | 
					        // Read block from tag
 | 
				
			||||||
        error =
 | 
					        error = mf_classic_poller_read_block(
 | 
				
			||||||
            mf_classic_async_read_block(instance, write_ctx->current_block, &write_ctx->tag_block);
 | 
					            instance, write_ctx->current_block, &write_ctx->tag_block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %d", write_ctx->current_block);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %d", write_ctx->current_block);
 | 
				
			||||||
            instance->state = MfClassicPollerStateFail;
 | 
					            instance->state = MfClassicPollerStateFail;
 | 
				
			||||||
@ -252,11 +252,11 @@ NfcCommand mf_classic_poller_handler_read_block(MfClassicPoller* instance) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(write_ctx->is_value_block) {
 | 
					        if(write_ctx->is_value_block) {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            instance->state = MfClassicPollerStateWriteValueBlock;
 | 
					            instance->state = MfClassicPollerStateWriteValueBlock;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if(write_ctx->need_halt_before_write) {
 | 
					            if(write_ctx->need_halt_before_write) {
 | 
				
			||||||
                mf_classic_async_halt(instance);
 | 
					                mf_classic_poller_halt(instance);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            instance->state = MfClassicPollerStateWriteBlock;
 | 
					            instance->state = MfClassicPollerStateWriteBlock;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -292,7 +292,7 @@ NfcCommand mf_classic_poller_handler_write_block(MfClassicPoller* instance) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Reauth if necessary
 | 
					        // Reauth if necessary
 | 
				
			||||||
        if(write_ctx->need_halt_before_write) {
 | 
					        if(write_ctx->need_halt_before_write) {
 | 
				
			||||||
            error = mf_classic_async_auth(
 | 
					            error = mf_classic_poller_auth(
 | 
				
			||||||
                instance, write_ctx->current_block, auth_key, write_ctx->key_type_write, NULL);
 | 
					                instance, write_ctx->current_block, auth_key, write_ctx->key_type_write, NULL);
 | 
				
			||||||
            if(error != MfClassicErrorNone) {
 | 
					            if(error != MfClassicErrorNone) {
 | 
				
			||||||
                FURI_LOG_D(
 | 
					                FURI_LOG_D(
 | 
				
			||||||
@ -303,7 +303,7 @@ NfcCommand mf_classic_poller_handler_write_block(MfClassicPoller* instance) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Write block
 | 
					        // Write block
 | 
				
			||||||
        error = mf_classic_async_write_block(
 | 
					        error = mf_classic_poller_write_block(
 | 
				
			||||||
            instance,
 | 
					            instance,
 | 
				
			||||||
            write_ctx->current_block,
 | 
					            write_ctx->current_block,
 | 
				
			||||||
            &instance->mfc_event_data.write_block_data.write_block);
 | 
					            &instance->mfc_event_data.write_block_data.write_block);
 | 
				
			||||||
@ -315,7 +315,7 @@ NfcCommand mf_classic_poller_handler_write_block(MfClassicPoller* instance) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_classic_async_halt(instance);
 | 
					    mf_classic_poller_halt(instance);
 | 
				
			||||||
    write_ctx->current_block++;
 | 
					    write_ctx->current_block++;
 | 
				
			||||||
    instance->state = MfClassicPollerStateCheckWriteConditions;
 | 
					    instance->state = MfClassicPollerStateCheckWriteConditions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -403,18 +403,18 @@ NfcCommand mf_classic_poller_handler_write_value_block(MfClassicPoller* instance
 | 
				
			|||||||
                                                                   &write_ctx->sec_tr.key_b;
 | 
					                                                                   &write_ctx->sec_tr.key_b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicError error =
 | 
					        MfClassicError error =
 | 
				
			||||||
            mf_classic_async_auth(instance, write_ctx->current_block, key, auth_key_type, NULL);
 | 
					            mf_classic_poller_auth(instance, write_ctx->current_block, key, auth_key_type, NULL);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_value_cmd(instance, write_ctx->current_block, value_cmd, diff);
 | 
					        error = mf_classic_poller_value_cmd(instance, write_ctx->current_block, value_cmd, diff);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_value_transfer(instance, write_ctx->current_block);
 | 
					        error = mf_classic_poller_value_transfer(instance, write_ctx->current_block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_classic_async_halt(instance);
 | 
					    mf_classic_poller_halt(instance);
 | 
				
			||||||
    write_ctx->is_value_block = false;
 | 
					    write_ctx->is_value_block = false;
 | 
				
			||||||
    write_ctx->current_block++;
 | 
					    write_ctx->current_block++;
 | 
				
			||||||
    instance->state = MfClassicPollerStateCheckWriteConditions;
 | 
					    instance->state = MfClassicPollerStateCheckWriteConditions;
 | 
				
			||||||
@ -462,7 +462,7 @@ NfcCommand mf_classic_poller_handler_request_read_sector_blocks(MfClassicPoller*
 | 
				
			|||||||
                sec_read_ctx->current_block,
 | 
					                sec_read_ctx->current_block,
 | 
				
			||||||
                sec_read_ctx->key_type == MfClassicKeyTypeA ? 'A' : 'B',
 | 
					                sec_read_ctx->key_type == MfClassicKeyTypeA ? 'A' : 'B',
 | 
				
			||||||
                key);
 | 
					                key);
 | 
				
			||||||
            error = mf_classic_async_auth(
 | 
					            error = mf_classic_poller_auth(
 | 
				
			||||||
                instance,
 | 
					                instance,
 | 
				
			||||||
                sec_read_ctx->current_block,
 | 
					                sec_read_ctx->current_block,
 | 
				
			||||||
                &sec_read_ctx->key,
 | 
					                &sec_read_ctx->key,
 | 
				
			||||||
@ -481,7 +481,7 @@ NfcCommand mf_classic_poller_handler_request_read_sector_blocks(MfClassicPoller*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        FURI_LOG_D(TAG, "Reading block %d", sec_read_ctx->current_block);
 | 
					        FURI_LOG_D(TAG, "Reading block %d", sec_read_ctx->current_block);
 | 
				
			||||||
        MfClassicBlock read_block = {};
 | 
					        MfClassicBlock read_block = {};
 | 
				
			||||||
        error = mf_classic_async_read_block(instance, sec_read_ctx->current_block, &read_block);
 | 
					        error = mf_classic_poller_read_block(instance, sec_read_ctx->current_block, &read_block);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            mf_classic_set_block_read(instance->data, sec_read_ctx->current_block, &read_block);
 | 
					            mf_classic_set_block_read(instance->data, sec_read_ctx->current_block, &read_block);
 | 
				
			||||||
            if(sec_read_ctx->key_type == MfClassicKeyTypeA) {
 | 
					            if(sec_read_ctx->key_type == MfClassicKeyTypeA) {
 | 
				
			||||||
@ -489,7 +489,7 @@ NfcCommand mf_classic_poller_handler_request_read_sector_blocks(MfClassicPoller*
 | 
				
			|||||||
                    instance, sec_read_ctx->current_block, &read_block);
 | 
					                    instance, sec_read_ctx->current_block, &read_block);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            sec_read_ctx->auth_passed = false;
 | 
					            sec_read_ctx->auth_passed = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
@ -497,7 +497,7 @@ NfcCommand mf_classic_poller_handler_request_read_sector_blocks(MfClassicPoller*
 | 
				
			|||||||
    uint8_t sec_tr_num = mf_classic_get_sector_trailer_num_by_sector(sec_read_ctx->current_sector);
 | 
					    uint8_t sec_tr_num = mf_classic_get_sector_trailer_num_by_sector(sec_read_ctx->current_sector);
 | 
				
			||||||
    sec_read_ctx->current_block++;
 | 
					    sec_read_ctx->current_block++;
 | 
				
			||||||
    if(sec_read_ctx->current_block > sec_tr_num) {
 | 
					    if(sec_read_ctx->current_block > sec_tr_num) {
 | 
				
			||||||
        mf_classic_async_halt(instance);
 | 
					        mf_classic_poller_halt(instance);
 | 
				
			||||||
        instance->state = MfClassicPollerStateRequestReadSector;
 | 
					        instance->state = MfClassicPollerStateRequestReadSector;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -532,7 +532,7 @@ NfcCommand mf_classic_poller_handler_auth_a(MfClassicPoller* instance) {
 | 
				
			|||||||
        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
					        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
				
			||||||
        FURI_LOG_D(TAG, "Auth to block %d with key A: %06llx", block, key);
 | 
					        FURI_LOG_D(TAG, "Auth to block %d with key A: %06llx", block, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicError error = mf_classic_async_auth(
 | 
					        MfClassicError error = mf_classic_poller_auth(
 | 
				
			||||||
            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
 | 
					            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_I(TAG, "Key A found");
 | 
					            FURI_LOG_I(TAG, "Key A found");
 | 
				
			||||||
@ -545,7 +545,7 @@ NfcCommand mf_classic_poller_handler_auth_a(MfClassicPoller* instance) {
 | 
				
			|||||||
            dict_attack_ctx->auth_passed = true;
 | 
					            dict_attack_ctx->auth_passed = true;
 | 
				
			||||||
            instance->state = MfClassicPollerStateReadSector;
 | 
					            instance->state = MfClassicPollerStateReadSector;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            instance->state = MfClassicPollerStateAuthKeyB;
 | 
					            instance->state = MfClassicPollerStateAuthKeyB;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -570,7 +570,7 @@ NfcCommand mf_classic_poller_handler_auth_b(MfClassicPoller* instance) {
 | 
				
			|||||||
        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
					        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
				
			||||||
        FURI_LOG_D(TAG, "Auth to block %d with key B: %06llx", block, key);
 | 
					        FURI_LOG_D(TAG, "Auth to block %d with key B: %06llx", block, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicError error = mf_classic_async_auth(
 | 
					        MfClassicError error = mf_classic_poller_auth(
 | 
				
			||||||
            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
 | 
					            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_I(TAG, "Key B found");
 | 
					            FURI_LOG_I(TAG, "Key B found");
 | 
				
			||||||
@ -584,7 +584,7 @@ NfcCommand mf_classic_poller_handler_auth_b(MfClassicPoller* instance) {
 | 
				
			|||||||
            dict_attack_ctx->auth_passed = true;
 | 
					            dict_attack_ctx->auth_passed = true;
 | 
				
			||||||
            instance->state = MfClassicPollerStateReadSector;
 | 
					            instance->state = MfClassicPollerStateReadSector;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            instance->state = MfClassicPollerStateRequestKey;
 | 
					            instance->state = MfClassicPollerStateRequestKey;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -621,7 +621,7 @@ NfcCommand mf_classic_poller_handler_read_sector(MfClassicPoller* instance) {
 | 
				
			|||||||
        if(mf_classic_is_block_read(instance->data, block_num)) break;
 | 
					        if(mf_classic_is_block_read(instance->data, block_num)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!dict_attack_ctx->auth_passed) {
 | 
					        if(!dict_attack_ctx->auth_passed) {
 | 
				
			||||||
            error = mf_classic_async_auth(
 | 
					            error = mf_classic_poller_auth(
 | 
				
			||||||
                instance,
 | 
					                instance,
 | 
				
			||||||
                block_num,
 | 
					                block_num,
 | 
				
			||||||
                &dict_attack_ctx->current_key,
 | 
					                &dict_attack_ctx->current_key,
 | 
				
			||||||
@ -635,10 +635,10 @@ NfcCommand mf_classic_poller_handler_read_sector(MfClassicPoller* instance) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FURI_LOG_D(TAG, "Reading block %d", block_num);
 | 
					        FURI_LOG_D(TAG, "Reading block %d", block_num);
 | 
				
			||||||
        error = mf_classic_async_read_block(instance, block_num, &block);
 | 
					        error = mf_classic_poller_read_block(instance, block_num, &block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            dict_attack_ctx->auth_passed = false;
 | 
					            dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %d", block_num);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %d", block_num);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -655,7 +655,7 @@ NfcCommand mf_classic_poller_handler_read_sector(MfClassicPoller* instance) {
 | 
				
			|||||||
    if(dict_attack_ctx->current_block > sec_tr_block_num) {
 | 
					    if(dict_attack_ctx->current_block > sec_tr_block_num) {
 | 
				
			||||||
        mf_classic_poller_handle_data_update(instance);
 | 
					        mf_classic_poller_handle_data_update(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mf_classic_async_halt(instance);
 | 
					        mf_classic_poller_halt(instance);
 | 
				
			||||||
        dict_attack_ctx->auth_passed = false;
 | 
					        dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(dict_attack_ctx->current_sector == instance->sectors_total) {
 | 
					        if(dict_attack_ctx->current_sector == instance->sectors_total) {
 | 
				
			||||||
@ -713,7 +713,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* insta
 | 
				
			|||||||
        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
					        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
				
			||||||
        FURI_LOG_D(TAG, "Key attack auth to block %d with key A: %06llx", block, key);
 | 
					        FURI_LOG_D(TAG, "Key attack auth to block %d with key A: %06llx", block, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicError error = mf_classic_async_auth(
 | 
					        MfClassicError error = mf_classic_poller_auth(
 | 
				
			||||||
            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
 | 
					            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_I(TAG, "Key A found");
 | 
					            FURI_LOG_I(TAG, "Key A found");
 | 
				
			||||||
@ -726,7 +726,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* insta
 | 
				
			|||||||
            dict_attack_ctx->auth_passed = true;
 | 
					            dict_attack_ctx->auth_passed = true;
 | 
				
			||||||
            instance->state = MfClassicPollerStateKeyReuseReadSector;
 | 
					            instance->state = MfClassicPollerStateKeyReuseReadSector;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            dict_attack_ctx->auth_passed = false;
 | 
					            dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
            instance->state = MfClassicPollerStateKeyReuseStart;
 | 
					            instance->state = MfClassicPollerStateKeyReuseStart;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -748,7 +748,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_b(MfClassicPoller* insta
 | 
				
			|||||||
        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
					        uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
 | 
				
			||||||
        FURI_LOG_D(TAG, "Key attack auth to block %d with key B: %06llx", block, key);
 | 
					        FURI_LOG_D(TAG, "Key attack auth to block %d with key B: %06llx", block, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicError error = mf_classic_async_auth(
 | 
					        MfClassicError error = mf_classic_poller_auth(
 | 
				
			||||||
            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
 | 
					            instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            FURI_LOG_I(TAG, "Key B found");
 | 
					            FURI_LOG_I(TAG, "Key B found");
 | 
				
			||||||
@ -762,7 +762,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_b(MfClassicPoller* insta
 | 
				
			|||||||
            dict_attack_ctx->auth_passed = true;
 | 
					            dict_attack_ctx->auth_passed = true;
 | 
				
			||||||
            instance->state = MfClassicPollerStateKeyReuseReadSector;
 | 
					            instance->state = MfClassicPollerStateKeyReuseReadSector;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            dict_attack_ctx->auth_passed = false;
 | 
					            dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
            instance->state = MfClassicPollerStateKeyReuseStart;
 | 
					            instance->state = MfClassicPollerStateKeyReuseStart;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -783,7 +783,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_read_sector(MfClassicPoller* inst
 | 
				
			|||||||
        if(mf_classic_is_block_read(instance->data, block_num)) break;
 | 
					        if(mf_classic_is_block_read(instance->data, block_num)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!dict_attack_ctx->auth_passed) {
 | 
					        if(!dict_attack_ctx->auth_passed) {
 | 
				
			||||||
            error = mf_classic_async_auth(
 | 
					            error = mf_classic_poller_auth(
 | 
				
			||||||
                instance,
 | 
					                instance,
 | 
				
			||||||
                block_num,
 | 
					                block_num,
 | 
				
			||||||
                &dict_attack_ctx->current_key,
 | 
					                &dict_attack_ctx->current_key,
 | 
				
			||||||
@ -796,10 +796,10 @@ NfcCommand mf_classic_poller_handler_key_reuse_read_sector(MfClassicPoller* inst
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FURI_LOG_D(TAG, "Reading block %d", block_num);
 | 
					        FURI_LOG_D(TAG, "Reading block %d", block_num);
 | 
				
			||||||
        error = mf_classic_async_read_block(instance, block_num, &block);
 | 
					        error = mf_classic_poller_read_block(instance, block_num, &block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(error != MfClassicErrorNone) {
 | 
					        if(error != MfClassicErrorNone) {
 | 
				
			||||||
            mf_classic_async_halt(instance);
 | 
					            mf_classic_poller_halt(instance);
 | 
				
			||||||
            dict_attack_ctx->auth_passed = false;
 | 
					            dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read block %d", block_num);
 | 
					            FURI_LOG_D(TAG, "Failed to read block %d", block_num);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -814,7 +814,7 @@ NfcCommand mf_classic_poller_handler_key_reuse_read_sector(MfClassicPoller* inst
 | 
				
			|||||||
        mf_classic_get_sector_trailer_num_by_sector(dict_attack_ctx->reuse_key_sector);
 | 
					        mf_classic_get_sector_trailer_num_by_sector(dict_attack_ctx->reuse_key_sector);
 | 
				
			||||||
    dict_attack_ctx->current_block++;
 | 
					    dict_attack_ctx->current_block++;
 | 
				
			||||||
    if(dict_attack_ctx->current_block > sec_tr_block_num) {
 | 
					    if(dict_attack_ctx->current_block > sec_tr_block_num) {
 | 
				
			||||||
        mf_classic_async_halt(instance);
 | 
					        mf_classic_poller_halt(instance);
 | 
				
			||||||
        dict_attack_ctx->auth_passed = false;
 | 
					        dict_attack_ctx->auth_passed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mf_classic_poller_handle_data_update(instance);
 | 
					        mf_classic_poller_handle_data_update(instance);
 | 
				
			||||||
 | 
				
			|||||||
@ -7,103 +7,274 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassicPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct MfClassicPoller MfClassicPoller;
 | 
					typedef struct MfClassicPoller MfClassicPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible MfClassic poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    // Start event
 | 
					    MfClassicPollerEventTypeRequestMode, /**< Poller requests to fill the mode. */
 | 
				
			||||||
    MfClassicPollerEventTypeRequestMode,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Read with key cache events
 | 
					    MfClassicPollerEventTypeRequestReadSector, /**< Poller requests data to read sector. */
 | 
				
			||||||
    MfClassicPollerEventTypeRequestReadSector,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Write events
 | 
					    MfClassicPollerEventTypeRequestSectorTrailer, /**< Poller requests sector trailer for writing block. */
 | 
				
			||||||
    MfClassicPollerEventTypeRequestSectorTrailer,
 | 
					    MfClassicPollerEventTypeRequestWriteBlock, /**< Poller requests data to write block. */
 | 
				
			||||||
    MfClassicPollerEventTypeRequestWriteBlock,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dictionary attack events
 | 
					    MfClassicPollerEventTypeRequestKey, /**< Poller requests key for sector authentication. */
 | 
				
			||||||
    MfClassicPollerEventTypeRequestKey,
 | 
					    MfClassicPollerEventTypeNextSector, /**< Poller switches to next sector during dictionary attack. */
 | 
				
			||||||
    MfClassicPollerEventTypeNextSector,
 | 
					    MfClassicPollerEventTypeDataUpdate, /**< Poller updates data. */
 | 
				
			||||||
    MfClassicPollerEventTypeDataUpdate,
 | 
					    MfClassicPollerEventTypeFoundKeyA, /**< Poller found key A. */
 | 
				
			||||||
    MfClassicPollerEventTypeFoundKeyA,
 | 
					    MfClassicPollerEventTypeFoundKeyB, /**< Poller found key B. */
 | 
				
			||||||
    MfClassicPollerEventTypeFoundKeyB,
 | 
					    MfClassicPollerEventTypeKeyAttackStart, /**< Poller starts key attack. */
 | 
				
			||||||
    MfClassicPollerEventTypeCardNotDetected,
 | 
					    MfClassicPollerEventTypeKeyAttackStop, /**< Poller stops key attack. */
 | 
				
			||||||
    MfClassicPollerEventTypeKeyAttackStart,
 | 
					    MfClassicPollerEventTypeKeyAttackNextSector, /**< Poller switches to next sector during key attack. */
 | 
				
			||||||
    MfClassicPollerEventTypeKeyAttackStop,
 | 
					 | 
				
			||||||
    MfClassicPollerEventTypeKeyAttackNextSector,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Common events
 | 
					    MfClassicPollerEventTypeCardDetected, /**< Poller detected card. */
 | 
				
			||||||
    MfClassicPollerEventTypeCardDetected,
 | 
					    MfClassicPollerEventTypeCardLost, /**< Poller lost card. */
 | 
				
			||||||
    MfClassicPollerEventTypeCardLost,
 | 
					    MfClassicPollerEventTypeSuccess, /**< Poller succeeded. */
 | 
				
			||||||
    MfClassicPollerEventTypeSuccess,
 | 
					    MfClassicPollerEventTypeFail, /**< Poller failed. */
 | 
				
			||||||
    MfClassicPollerEventTypeFail,
 | 
					 | 
				
			||||||
} MfClassicPollerEventType;
 | 
					} MfClassicPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller mode.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    MfClassicPollerModeRead,
 | 
					    MfClassicPollerModeRead, /**< Poller reading mode. */
 | 
				
			||||||
    MfClassicPollerModeWrite,
 | 
					    MfClassicPollerModeWrite, /**< Poller writing mode. */
 | 
				
			||||||
    MfClassicPollerModeDictAttack,
 | 
					    MfClassicPollerModeDictAttack, /**< Poller dictionary attack mode. */
 | 
				
			||||||
} MfClassicPollerMode;
 | 
					} MfClassicPollerMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller request mode event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This instance of this structure must be filled on MfClassicPollerEventTypeRequestMode event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfClassicPollerMode mode;
 | 
					    MfClassicPollerMode mode; /**< Mode to be used by poller. */
 | 
				
			||||||
    const MfClassicData* data;
 | 
					    const MfClassicData* data; /**< Data to be used by poller. */
 | 
				
			||||||
} MfClassicPollerEventDataRequestMode;
 | 
					} MfClassicPollerEventDataRequestMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller next sector event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure is filled by poller and passed with
 | 
				
			||||||
 | 
					 * MfClassicPollerEventTypeNextSector event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t current_sector;
 | 
					    uint8_t current_sector; /**< Current sector number. */
 | 
				
			||||||
} MfClassicPollerEventDataDictAttackNextSector;
 | 
					} MfClassicPollerEventDataDictAttackNextSector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller update event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure is filled by poller and passed with
 | 
				
			||||||
 | 
					 * MfClassicPollerEventTypeDataUpdate event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t sectors_read;
 | 
					    uint8_t sectors_read; /**< Number of sectors read. */
 | 
				
			||||||
    uint8_t keys_found;
 | 
					    uint8_t keys_found; /**< Number of keys found. */
 | 
				
			||||||
    uint8_t current_sector;
 | 
					    uint8_t current_sector; /**< Current sector number. */
 | 
				
			||||||
} MfClassicPollerEventDataUpdate;
 | 
					} MfClassicPollerEventDataUpdate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller key request event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure must be filled on MfClassicPollerEventTypeRequestKey event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfClassicKey key;
 | 
					    MfClassicKey key; /**< Key to be used by poller. */
 | 
				
			||||||
    bool key_provided;
 | 
					    bool key_provided; /**< Flag indicating if key is provided. */
 | 
				
			||||||
} MfClassicPollerEventDataKeyRequest;
 | 
					} MfClassicPollerEventDataKeyRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller read sector request event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure must be filled on MfClassicPollerEventTypeRequestReadSector event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t sector_num;
 | 
					    uint8_t sector_num; /**< Sector number to be read. */
 | 
				
			||||||
    MfClassicKey key;
 | 
					    MfClassicKey key; /**< Key to be used by poller. */
 | 
				
			||||||
    MfClassicKeyType key_type;
 | 
					    MfClassicKeyType key_type; /**< Key type to be used by poller. */
 | 
				
			||||||
    bool key_provided;
 | 
					    bool key_provided; /**< Flag indicating if key is provided. */
 | 
				
			||||||
} MfClassicPollerEventDataReadSectorRequest;
 | 
					} MfClassicPollerEventDataReadSectorRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller sector trailer request event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure must be filled on MfClassicPollerEventTypeRequestSectorTrailer event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t sector_num;
 | 
					    uint8_t sector_num; /**< Sector number to be read. */
 | 
				
			||||||
    MfClassicBlock sector_trailer;
 | 
					    MfClassicBlock sector_trailer; /**< Sector trailer to be used by poller. */
 | 
				
			||||||
    bool sector_trailer_provided;
 | 
					    bool sector_trailer_provided; /**< Flag indicating if sector trailer is provided. */
 | 
				
			||||||
} MfClassicPollerEventDataSectorTrailerRequest;
 | 
					} MfClassicPollerEventDataSectorTrailerRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller write block request event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure must be filled on MfClassicPollerEventTypeRequestWriteBlock event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t block_num;
 | 
					    uint8_t block_num; /**< Block number to be written. */
 | 
				
			||||||
    MfClassicBlock write_block;
 | 
					    MfClassicBlock write_block; /**< Block to be written. */
 | 
				
			||||||
    bool write_block_provided;
 | 
					    bool write_block_provided; /**< Flag indicating if block is provided. */
 | 
				
			||||||
} MfClassicPollerEventDataWriteBlockRequest;
 | 
					} MfClassicPollerEventDataWriteBlockRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller key attack event data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The instance of this structure is filled by poller and passed with
 | 
				
			||||||
 | 
					 * MfClassicPollerEventTypeKeyAttackNextSector event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t current_sector;
 | 
					    uint8_t current_sector; /**< Current sector number. */
 | 
				
			||||||
} MfClassicPollerEventKeyAttackData;
 | 
					} MfClassicPollerEventKeyAttackData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef union {
 | 
					typedef union {
 | 
				
			||||||
    MfClassicError error;
 | 
					    MfClassicError error; /**< Error code on MfClassicPollerEventTypeFail event. */
 | 
				
			||||||
    MfClassicPollerEventDataRequestMode poller_mode;
 | 
					    MfClassicPollerEventDataRequestMode poller_mode; /**< Poller mode context. */
 | 
				
			||||||
    MfClassicPollerEventDataDictAttackNextSector next_sector_data;
 | 
					    MfClassicPollerEventDataDictAttackNextSector next_sector_data; /**< Next sector context. */
 | 
				
			||||||
    MfClassicPollerEventDataKeyRequest key_request_data;
 | 
					    MfClassicPollerEventDataKeyRequest key_request_data; /**< Key request context. */
 | 
				
			||||||
    MfClassicPollerEventDataUpdate data_update;
 | 
					    MfClassicPollerEventDataUpdate data_update; /**< Data update context. */
 | 
				
			||||||
    MfClassicPollerEventDataReadSectorRequest read_sector_request_data;
 | 
					    MfClassicPollerEventDataReadSectorRequest
 | 
				
			||||||
    MfClassicPollerEventKeyAttackData key_attack_data;
 | 
					        read_sector_request_data; /**< Read sector request context. */
 | 
				
			||||||
    MfClassicPollerEventDataSectorTrailerRequest sec_tr_data;
 | 
					    MfClassicPollerEventKeyAttackData key_attack_data; /**< Key attack context. */
 | 
				
			||||||
    MfClassicPollerEventDataWriteBlockRequest write_block_data;
 | 
					    MfClassicPollerEventDataSectorTrailerRequest sec_tr_data; /**< Sector trailer request context. */
 | 
				
			||||||
 | 
					    MfClassicPollerEventDataWriteBlockRequest write_block_data; /**< Write block request context. */
 | 
				
			||||||
} MfClassicPollerEventData;
 | 
					} MfClassicPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfClassic poller event.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfClassicPollerEventType type;
 | 
					    MfClassicPollerEventType type; /**< Event type. */
 | 
				
			||||||
    MfClassicPollerEventData* data;
 | 
					    MfClassicPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} MfClassicPollerEvent;
 | 
					} MfClassicPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Collect tag nonce during authentication.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Starts authentication procedure and collects tag nonce.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number for authentication.
 | 
				
			||||||
 | 
					 * @param[in] key_type key type to be used for authentication.
 | 
				
			||||||
 | 
					 * @param[out] nt pointer to the MfClassicNt structure to be filled with nonce data.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_get_nt(
 | 
				
			||||||
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t block_num,
 | 
				
			||||||
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
 | 
					    MfClassicNt* nt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform authentication.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perform authentication as specified in Mf Classic protocol. Initialize crypto state for futher
 | 
				
			||||||
 | 
					 * communication with the tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number for authentication.
 | 
				
			||||||
 | 
					 * @param[in] key key to be used for authentication.
 | 
				
			||||||
 | 
					 * @param[in] key_type key type to be used for authentication.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to MfClassicAuthContext structure to be filled with authentication data.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_auth(
 | 
				
			||||||
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t block_num,
 | 
				
			||||||
 | 
					    MfClassicKey* key,
 | 
				
			||||||
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
 | 
					    MfClassicAuthContext* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Halt the tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Halt the tag and reset crypto state of the poller.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_halt(MfClassicPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read block from tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number to be read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfClassicBlock structure to be filled with block data.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_read_block(
 | 
				
			||||||
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t block_num,
 | 
				
			||||||
 | 
					    MfClassicBlock* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Write block to tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number to be written.
 | 
				
			||||||
 | 
					 * @param[in] data pointer to the MfClassicBlock structure to be written.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_write_block(
 | 
				
			||||||
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t block_num,
 | 
				
			||||||
 | 
					    MfClassicBlock* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform value command on tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Perform Increment, Decrement or Restore command on tag. The result is stored in internal transfer
 | 
				
			||||||
 | 
					 * block of the tag. Use mf_classic_poller_value_transfer to transfer the result to the tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number to be used for value command.
 | 
				
			||||||
 | 
					 * @param[in] cmd value command to be performed.
 | 
				
			||||||
 | 
					 * @param[in] data value to be used for value command.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_value_cmd(
 | 
				
			||||||
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t block_num,
 | 
				
			||||||
 | 
					    MfClassicValueCommand cmd,
 | 
				
			||||||
 | 
					    int32_t data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transfer internal transfer block to tag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Transfer internal transfer block to tag. The block is filled by mf_classic_poller_value_cmd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] block_num block number to be used for value command.
 | 
				
			||||||
 | 
					 * @return MfClassicErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfClassicError mf_classic_poller_value_transfer(MfClassicPoller* instance, uint8_t block_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@ MfClassicError mf_classic_process_error(Iso14443_3aError error) {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_get_nt(
 | 
					MfClassicError mf_classic_poller_get_nt(
 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
@ -69,7 +69,7 @@ MfClassicError mf_classic_async_get_nt(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_auth(
 | 
					MfClassicError mf_classic_poller_auth(
 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -84,7 +84,7 @@ MfClassicError mf_classic_async_auth(
 | 
				
			|||||||
            iso14443_3a_poller_get_data(instance->iso14443_3a_poller));
 | 
					            iso14443_3a_poller_get_data(instance->iso14443_3a_poller));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicNt nt = {};
 | 
					        MfClassicNt nt = {};
 | 
				
			||||||
        ret = mf_classic_async_get_nt(instance, block_num, key_type, &nt);
 | 
					        ret = mf_classic_poller_get_nt(instance, block_num, key_type, &nt);
 | 
				
			||||||
        if(ret != MfClassicErrorNone) break;
 | 
					        if(ret != MfClassicErrorNone) break;
 | 
				
			||||||
        if(data) {
 | 
					        if(data) {
 | 
				
			||||||
            data->nt = nt;
 | 
					            data->nt = nt;
 | 
				
			||||||
@ -130,7 +130,7 @@ MfClassicError mf_classic_async_auth(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_halt(MfClassicPoller* instance) {
 | 
					MfClassicError mf_classic_poller_halt(MfClassicPoller* instance) {
 | 
				
			||||||
    MfClassicError ret = MfClassicErrorNone;
 | 
					    MfClassicError ret = MfClassicErrorNone;
 | 
				
			||||||
    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
					    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -158,7 +158,7 @@ MfClassicError mf_classic_async_halt(MfClassicPoller* instance) {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_read_block(
 | 
					MfClassicError mf_classic_poller_read_block(
 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicBlock* data) {
 | 
					    MfClassicBlock* data) {
 | 
				
			||||||
@ -204,7 +204,7 @@ MfClassicError mf_classic_async_read_block(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_write_block(
 | 
					MfClassicError mf_classic_poller_write_block(
 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicBlock* data) {
 | 
					    MfClassicBlock* data) {
 | 
				
			||||||
@ -275,7 +275,7 @@ MfClassicError mf_classic_async_write_block(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_value_cmd(
 | 
					MfClassicError mf_classic_poller_value_cmd(
 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					    MfClassicPoller* instance,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicValueCommand cmd,
 | 
					    MfClassicValueCommand cmd,
 | 
				
			||||||
@ -345,7 +345,7 @@ MfClassicError mf_classic_async_value_cmd(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_value_transfer(MfClassicPoller* instance, uint8_t block_num) {
 | 
					MfClassicError mf_classic_poller_value_transfer(MfClassicPoller* instance, uint8_t block_num) {
 | 
				
			||||||
    MfClassicError ret = MfClassicErrorNone;
 | 
					    MfClassicError ret = MfClassicErrorNone;
 | 
				
			||||||
    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
					    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -169,37 +169,6 @@ MfClassicPoller* mf_classic_poller_alloc(Iso14443_3aPoller* iso14443_3a_poller);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void mf_classic_poller_free(MfClassicPoller* instance);
 | 
					void mf_classic_poller_free(MfClassicPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_async_get_nt(
 | 
					 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t block_num,
 | 
					 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					 | 
				
			||||||
    MfClassicNt* nt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError mf_classic_async_auth(
 | 
					 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t block_num,
 | 
					 | 
				
			||||||
    MfClassicKey* key,
 | 
					 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					 | 
				
			||||||
    MfClassicAuthContext* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError mf_classic_async_halt(MfClassicPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError
 | 
					 | 
				
			||||||
    mf_classic_async_read_block(MfClassicPoller* instance, uint8_t block_num, MfClassicBlock* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError mf_classic_async_write_block(
 | 
					 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t block_num,
 | 
					 | 
				
			||||||
    MfClassicBlock* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError mf_classic_async_value_cmd(
 | 
					 | 
				
			||||||
    MfClassicPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t block_num,
 | 
					 | 
				
			||||||
    MfClassicValueCommand cmd,
 | 
					 | 
				
			||||||
    int32_t data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfClassicError mf_classic_async_value_transfer(MfClassicPoller* instance, uint8_t block_num);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					#include "mf_classic_poller_sync.h"
 | 
				
			||||||
#include "mf_classic_poller_i.h"
 | 
					#include "mf_classic_poller_i.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nfc/nfc_poller.h>
 | 
					#include <nfc/nfc_poller.h>
 | 
				
			||||||
@ -32,7 +33,7 @@ typedef MfClassicError (
 | 
				
			|||||||
static MfClassicError mf_classic_poller_collect_nt_handler(
 | 
					static MfClassicError mf_classic_poller_collect_nt_handler(
 | 
				
			||||||
    MfClassicPoller* poller,
 | 
					    MfClassicPoller* poller,
 | 
				
			||||||
    MfClassicPollerContextData* data) {
 | 
					    MfClassicPollerContextData* data) {
 | 
				
			||||||
    return mf_classic_async_get_nt(
 | 
					    return mf_classic_poller_get_nt(
 | 
				
			||||||
        poller,
 | 
					        poller,
 | 
				
			||||||
        data->collect_nt_context.block,
 | 
					        data->collect_nt_context.block,
 | 
				
			||||||
        data->collect_nt_context.key_type,
 | 
					        data->collect_nt_context.key_type,
 | 
				
			||||||
@ -41,7 +42,7 @@ static MfClassicError mf_classic_poller_collect_nt_handler(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static MfClassicError
 | 
					static MfClassicError
 | 
				
			||||||
    mf_classic_poller_auth_handler(MfClassicPoller* poller, MfClassicPollerContextData* data) {
 | 
					    mf_classic_poller_auth_handler(MfClassicPoller* poller, MfClassicPollerContextData* data) {
 | 
				
			||||||
    return mf_classic_async_auth(
 | 
					    return mf_classic_poller_auth(
 | 
				
			||||||
        poller,
 | 
					        poller,
 | 
				
			||||||
        data->auth_context.block_num,
 | 
					        data->auth_context.block_num,
 | 
				
			||||||
        &data->auth_context.key,
 | 
					        &data->auth_context.key,
 | 
				
			||||||
@ -55,7 +56,7 @@ static MfClassicError mf_classic_poller_read_block_handler(
 | 
				
			|||||||
    MfClassicError error = MfClassicErrorNone;
 | 
					    MfClassicError error = MfClassicErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        error = mf_classic_async_auth(
 | 
					        error = mf_classic_poller_auth(
 | 
				
			||||||
            poller,
 | 
					            poller,
 | 
				
			||||||
            data->read_block_context.block_num,
 | 
					            data->read_block_context.block_num,
 | 
				
			||||||
            &data->read_block_context.key,
 | 
					            &data->read_block_context.key,
 | 
				
			||||||
@ -63,11 +64,11 @@ static MfClassicError mf_classic_poller_read_block_handler(
 | 
				
			|||||||
            NULL);
 | 
					            NULL);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_read_block(
 | 
					        error = mf_classic_poller_read_block(
 | 
				
			||||||
            poller, data->read_block_context.block_num, &data->read_block_context.block);
 | 
					            poller, data->read_block_context.block_num, &data->read_block_context.block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_halt(poller);
 | 
					        error = mf_classic_poller_halt(poller);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
@ -81,7 +82,7 @@ static MfClassicError mf_classic_poller_write_block_handler(
 | 
				
			|||||||
    MfClassicError error = MfClassicErrorNone;
 | 
					    MfClassicError error = MfClassicErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        error = mf_classic_async_auth(
 | 
					        error = mf_classic_poller_auth(
 | 
				
			||||||
            poller,
 | 
					            poller,
 | 
				
			||||||
            data->read_block_context.block_num,
 | 
					            data->read_block_context.block_num,
 | 
				
			||||||
            &data->read_block_context.key,
 | 
					            &data->read_block_context.key,
 | 
				
			||||||
@ -89,11 +90,11 @@ static MfClassicError mf_classic_poller_write_block_handler(
 | 
				
			|||||||
            NULL);
 | 
					            NULL);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_write_block(
 | 
					        error = mf_classic_poller_write_block(
 | 
				
			||||||
            poller, data->write_block_context.block_num, &data->write_block_context.block);
 | 
					            poller, data->write_block_context.block_num, &data->write_block_context.block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_halt(poller);
 | 
					        error = mf_classic_poller_halt(poller);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
@ -107,7 +108,7 @@ static MfClassicError mf_classic_poller_read_value_handler(
 | 
				
			|||||||
    MfClassicError error = MfClassicErrorNone;
 | 
					    MfClassicError error = MfClassicErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        error = mf_classic_async_auth(
 | 
					        error = mf_classic_poller_auth(
 | 
				
			||||||
            poller,
 | 
					            poller,
 | 
				
			||||||
            data->read_value_context.block_num,
 | 
					            data->read_value_context.block_num,
 | 
				
			||||||
            &data->read_value_context.key,
 | 
					            &data->read_value_context.key,
 | 
				
			||||||
@ -116,7 +117,7 @@ static MfClassicError mf_classic_poller_read_value_handler(
 | 
				
			|||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicBlock block = {};
 | 
					        MfClassicBlock block = {};
 | 
				
			||||||
        error = mf_classic_async_read_block(poller, data->read_value_context.block_num, &block);
 | 
					        error = mf_classic_poller_read_block(poller, data->read_value_context.block_num, &block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!mf_classic_block_to_value(&block, &data->read_value_context.value, NULL)) {
 | 
					        if(!mf_classic_block_to_value(&block, &data->read_value_context.value, NULL)) {
 | 
				
			||||||
@ -124,7 +125,7 @@ static MfClassicError mf_classic_poller_read_value_handler(
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_halt(poller);
 | 
					        error = mf_classic_poller_halt(poller);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
@ -138,7 +139,7 @@ static MfClassicError mf_classic_poller_change_value_handler(
 | 
				
			|||||||
    MfClassicError error = MfClassicErrorNone;
 | 
					    MfClassicError error = MfClassicErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        error = mf_classic_async_auth(
 | 
					        error = mf_classic_poller_auth(
 | 
				
			||||||
            poller,
 | 
					            poller,
 | 
				
			||||||
            data->change_value_context.block_num,
 | 
					            data->change_value_context.block_num,
 | 
				
			||||||
            &data->change_value_context.key,
 | 
					            &data->change_value_context.key,
 | 
				
			||||||
@ -146,21 +147,21 @@ static MfClassicError mf_classic_poller_change_value_handler(
 | 
				
			|||||||
            NULL);
 | 
					            NULL);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_value_cmd(
 | 
					        error = mf_classic_poller_value_cmd(
 | 
				
			||||||
            poller,
 | 
					            poller,
 | 
				
			||||||
            data->change_value_context.block_num,
 | 
					            data->change_value_context.block_num,
 | 
				
			||||||
            data->change_value_context.value_cmd,
 | 
					            data->change_value_context.value_cmd,
 | 
				
			||||||
            data->change_value_context.data);
 | 
					            data->change_value_context.data);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_value_transfer(poller, data->change_value_context.block_num);
 | 
					        error = mf_classic_poller_value_transfer(poller, data->change_value_context.block_num);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MfClassicBlock block = {};
 | 
					        MfClassicBlock block = {};
 | 
				
			||||||
        error = mf_classic_async_read_block(poller, data->change_value_context.block_num, &block);
 | 
					        error = mf_classic_poller_read_block(poller, data->change_value_context.block_num, &block);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_classic_async_halt(poller);
 | 
					        error = mf_classic_poller_halt(poller);
 | 
				
			||||||
        if(error != MfClassicErrorNone) break;
 | 
					        if(error != MfClassicErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!mf_classic_block_to_value(&block, &data->change_value_context.new_value, NULL)) {
 | 
					        if(!mf_classic_block_to_value(&block, &data->change_value_context.new_value, NULL)) {
 | 
				
			||||||
@ -182,16 +183,14 @@ static const MfClassicPollerCmdHandler mf_classic_poller_cmd_handlers[MfClassicP
 | 
				
			|||||||
    [MfClassicPollerCmdTypeChangeValue] = mf_classic_poller_change_value_handler,
 | 
					    [MfClassicPollerCmdTypeChangeValue] = mf_classic_poller_change_value_handler,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_classic_poller_cmd_callback(NfcGenericEvent event, void* context) {
 | 
					static NfcCommand mf_classic_poller_cmd_callback(NfcGenericEventEx event, void* context) {
 | 
				
			||||||
    furi_assert(event.instance);
 | 
					    furi_assert(event.poller);
 | 
				
			||||||
    furi_assert(event.protocol == NfcProtocolIso14443_3a);
 | 
					    furi_assert(event.parent_event_data);
 | 
				
			||||||
    furi_assert(event.event_data);
 | 
					 | 
				
			||||||
    furi_assert(context);
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfClassicPollerContext* poller_context = context;
 | 
					    MfClassicPollerContext* poller_context = context;
 | 
				
			||||||
    Iso14443_3aPollerEvent* iso14443_3a_event = event.event_data;
 | 
					    Iso14443_3aPollerEvent* iso14443_3a_event = event.parent_event_data;
 | 
				
			||||||
    Iso14443_3aPoller* iso14443_3a_poller = event.instance;
 | 
					    MfClassicPoller* mfc_poller = event.poller;
 | 
				
			||||||
    MfClassicPoller* mfc_poller = mf_classic_poller_alloc(iso14443_3a_poller);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
					    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
				
			||||||
        poller_context->error = mf_classic_poller_cmd_handlers[poller_context->cmd_type](
 | 
					        poller_context->error = mf_classic_poller_cmd_handlers[poller_context->cmd_type](
 | 
				
			||||||
@ -202,8 +201,6 @@ static NfcCommand mf_classic_poller_cmd_callback(NfcGenericEvent event, void* co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    furi_thread_flags_set(poller_context->thread_id, MF_CLASSIC_POLLER_COMPLETE_EVENT);
 | 
					    furi_thread_flags_set(poller_context->thread_id, MF_CLASSIC_POLLER_COMPLETE_EVENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_classic_poller_free(mfc_poller);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return NfcCommandStop;
 | 
					    return NfcCommandStop;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -212,8 +209,8 @@ static MfClassicError mf_classic_poller_cmd_execute(Nfc* nfc, MfClassicPollerCon
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    poller_ctx->thread_id = furi_thread_get_current_id();
 | 
					    poller_ctx->thread_id = furi_thread_get_current_id();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NfcPoller* poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a);
 | 
					    NfcPoller* poller = nfc_poller_alloc(nfc, NfcProtocolMfClassic);
 | 
				
			||||||
    nfc_poller_start(poller, mf_classic_poller_cmd_callback, poller_ctx);
 | 
					    nfc_poller_start_ex(poller, mf_classic_poller_cmd_callback, poller_ctx);
 | 
				
			||||||
    furi_thread_flags_wait(MF_CLASSIC_POLLER_COMPLETE_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
					    furi_thread_flags_wait(MF_CLASSIC_POLLER_COMPLETE_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
				
			||||||
    furi_thread_flags_clear(MF_CLASSIC_POLLER_COMPLETE_EVENT);
 | 
					    furi_thread_flags_clear(MF_CLASSIC_POLLER_COMPLETE_EVENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -223,7 +220,7 @@ static MfClassicError mf_classic_poller_cmd_execute(Nfc* nfc, MfClassicPollerCon
 | 
				
			|||||||
    return poller_ctx->error;
 | 
					    return poller_ctx->error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_collect_nt(
 | 
					MfClassicError mf_classic_poller_sync_collect_nt(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
@ -247,7 +244,7 @@ MfClassicError mf_classic_poller_collect_nt(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_auth(
 | 
					MfClassicError mf_classic_poller_sync_auth(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -274,7 +271,7 @@ MfClassicError mf_classic_poller_auth(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_read_block(
 | 
					MfClassicError mf_classic_poller_sync_read_block(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -300,7 +297,7 @@ MfClassicError mf_classic_poller_read_block(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_write_block(
 | 
					MfClassicError mf_classic_poller_sync_write_block(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -323,7 +320,7 @@ MfClassicError mf_classic_poller_write_block(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_read_value(
 | 
					MfClassicError mf_classic_poller_sync_read_value(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -349,7 +346,7 @@ MfClassicError mf_classic_poller_read_value(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_change_value(
 | 
					MfClassicError mf_classic_poller_sync_change_value(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -461,7 +458,7 @@ NfcCommand mf_classic_poller_read_callback(NfcGenericEvent event, void* context)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError
 | 
					MfClassicError
 | 
				
			||||||
    mf_classic_poller_read(Nfc* nfc, const MfClassicDeviceKeys* keys, MfClassicData* data) {
 | 
					    mf_classic_poller_sync_read(Nfc* nfc, const MfClassicDeviceKeys* keys, MfClassicData* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(keys);
 | 
					    furi_assert(keys);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
@ -498,7 +495,7 @@ MfClassicError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_detect_type(Nfc* nfc, MfClassicType* type) {
 | 
					MfClassicError mf_classic_poller_sync_detect_type(Nfc* nfc, MfClassicType* type) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(type);
 | 
					    furi_assert(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -512,7 +509,7 @@ MfClassicError mf_classic_poller_detect_type(Nfc* nfc, MfClassicType* type) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    size_t i = 0;
 | 
					    size_t i = 0;
 | 
				
			||||||
    for(i = 0; i < COUNT_OF(mf_classic_verify_block); i++) {
 | 
					    for(i = 0; i < COUNT_OF(mf_classic_verify_block); i++) {
 | 
				
			||||||
        error = mf_classic_poller_collect_nt(
 | 
					        error = mf_classic_poller_sync_collect_nt(
 | 
				
			||||||
            nfc, mf_classic_verify_block[MfClassicTypeNum - i - 1], MfClassicKeyTypeA, NULL);
 | 
					            nfc, mf_classic_verify_block[MfClassicTypeNum - i - 1], MfClassicKeyTypeA, NULL);
 | 
				
			||||||
        if(error == MfClassicErrorNone) {
 | 
					        if(error == MfClassicErrorNone) {
 | 
				
			||||||
            *type = MfClassicTypeNum - i - 1;
 | 
					            *type = MfClassicTypeNum - i - 1;
 | 
				
			||||||
@ -7,41 +7,41 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_collect_nt(
 | 
					MfClassicError mf_classic_poller_sync_collect_nt(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
    MfClassicNt* nt);
 | 
					    MfClassicNt* nt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_auth(
 | 
					MfClassicError mf_classic_poller_sync_auth(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
    MfClassicAuthContext* data);
 | 
					    MfClassicAuthContext* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_read_block(
 | 
					MfClassicError mf_classic_poller_sync_read_block(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
    MfClassicBlock* data);
 | 
					    MfClassicBlock* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_write_block(
 | 
					MfClassicError mf_classic_poller_sync_write_block(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
    MfClassicBlock* data);
 | 
					    MfClassicBlock* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_read_value(
 | 
					MfClassicError mf_classic_poller_sync_read_value(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
    MfClassicKeyType key_type,
 | 
					    MfClassicKeyType key_type,
 | 
				
			||||||
    int32_t* value);
 | 
					    int32_t* value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_change_value(
 | 
					MfClassicError mf_classic_poller_sync_change_value(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t block_num,
 | 
					    uint8_t block_num,
 | 
				
			||||||
    MfClassicKey* key,
 | 
					    MfClassicKey* key,
 | 
				
			||||||
@ -49,10 +49,10 @@ MfClassicError mf_classic_poller_change_value(
 | 
				
			|||||||
    int32_t data,
 | 
					    int32_t data,
 | 
				
			||||||
    int32_t* new_value);
 | 
					    int32_t* new_value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError mf_classic_poller_detect_type(Nfc* nfc, MfClassicType* type);
 | 
					MfClassicError mf_classic_poller_sync_detect_type(Nfc* nfc, MfClassicType* type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfClassicError
 | 
					MfClassicError
 | 
				
			||||||
    mf_classic_poller_read(Nfc* nfc, const MfClassicDeviceKeys* keys, MfClassicData* data);
 | 
					    mf_classic_poller_sync_read(Nfc* nfc, const MfClassicDeviceKeys* keys, MfClassicData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -61,7 +61,7 @@ static NfcCommand mf_desfire_poller_handler_idle(MfDesfirePoller* instance) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_version(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_version(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error = mf_desfire_poller_async_read_version(instance, &instance->data->version);
 | 
					    instance->error = mf_desfire_poller_read_version(instance, &instance->data->version);
 | 
				
			||||||
    if(instance->error == MfDesfireErrorNone) {
 | 
					    if(instance->error == MfDesfireErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read version success");
 | 
					        FURI_LOG_D(TAG, "Read version success");
 | 
				
			||||||
        instance->state = MfDesfirePollerStateReadFreeMemory;
 | 
					        instance->state = MfDesfirePollerStateReadFreeMemory;
 | 
				
			||||||
@ -75,8 +75,7 @@ static NfcCommand mf_desfire_poller_handler_read_version(MfDesfirePoller* instan
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_free_memory(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_free_memory(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error =
 | 
					    instance->error = mf_desfire_poller_read_free_memory(instance, &instance->data->free_memory);
 | 
				
			||||||
        mf_desfire_poller_async_read_free_memory(instance, &instance->data->free_memory);
 | 
					 | 
				
			||||||
    if(instance->error == MfDesfireErrorNone) {
 | 
					    if(instance->error == MfDesfireErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read free memory success");
 | 
					        FURI_LOG_D(TAG, "Read free memory success");
 | 
				
			||||||
        instance->state = MfDesfirePollerStateReadMasterKeySettings;
 | 
					        instance->state = MfDesfirePollerStateReadMasterKeySettings;
 | 
				
			||||||
@ -91,7 +90,7 @@ static NfcCommand mf_desfire_poller_handler_read_free_memory(MfDesfirePoller* in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_master_key_settings(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_master_key_settings(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error =
 | 
					    instance->error =
 | 
				
			||||||
        mf_desfire_poller_async_read_key_settings(instance, &instance->data->master_key_settings);
 | 
					        mf_desfire_poller_read_key_settings(instance, &instance->data->master_key_settings);
 | 
				
			||||||
    if(instance->error == MfDesfireErrorNone) {
 | 
					    if(instance->error == MfDesfireErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read master key settings success");
 | 
					        FURI_LOG_D(TAG, "Read master key settings success");
 | 
				
			||||||
        instance->state = MfDesfirePollerStateReadMasterKeyVersion;
 | 
					        instance->state = MfDesfirePollerStateReadMasterKeyVersion;
 | 
				
			||||||
@ -105,7 +104,7 @@ static NfcCommand mf_desfire_poller_handler_read_master_key_settings(MfDesfirePo
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_master_key_version(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_master_key_version(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error = mf_desfire_poller_async_read_key_versions(
 | 
					    instance->error = mf_desfire_poller_read_key_versions(
 | 
				
			||||||
        instance,
 | 
					        instance,
 | 
				
			||||||
        instance->data->master_key_versions,
 | 
					        instance->data->master_key_versions,
 | 
				
			||||||
        instance->data->master_key_settings.max_keys);
 | 
					        instance->data->master_key_settings.max_keys);
 | 
				
			||||||
@ -123,7 +122,7 @@ static NfcCommand mf_desfire_poller_handler_read_master_key_version(MfDesfirePol
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_application_ids(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_application_ids(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error =
 | 
					    instance->error =
 | 
				
			||||||
        mf_desfire_poller_async_read_application_ids(instance, instance->data->application_ids);
 | 
					        mf_desfire_poller_read_application_ids(instance, instance->data->application_ids);
 | 
				
			||||||
    if(instance->error == MfDesfireErrorNone) {
 | 
					    if(instance->error == MfDesfireErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read application ids success");
 | 
					        FURI_LOG_D(TAG, "Read application ids success");
 | 
				
			||||||
        instance->state = MfDesfirePollerStateReadApplications;
 | 
					        instance->state = MfDesfirePollerStateReadApplications;
 | 
				
			||||||
@ -137,7 +136,7 @@ static NfcCommand mf_desfire_poller_handler_read_application_ids(MfDesfirePoller
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_desfire_poller_handler_read_applications(MfDesfirePoller* instance) {
 | 
					static NfcCommand mf_desfire_poller_handler_read_applications(MfDesfirePoller* instance) {
 | 
				
			||||||
    instance->error = mf_desfire_poller_async_read_applications(
 | 
					    instance->error = mf_desfire_poller_read_applications(
 | 
				
			||||||
        instance, instance->data->application_ids, instance->data->applications);
 | 
					        instance, instance->data->application_ids, instance->data->applications);
 | 
				
			||||||
    if(instance->error == MfDesfireErrorNone) {
 | 
					    if(instance->error == MfDesfireErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read applications success");
 | 
					        FURI_LOG_D(TAG, "Read applications success");
 | 
				
			||||||
@ -227,7 +226,7 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
 | 
					    if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
 | 
				
			||||||
        MfDesfireVersion version = {};
 | 
					        MfDesfireVersion version = {};
 | 
				
			||||||
        const MfDesfireError error = mf_desfire_poller_async_read_version(instance, &version);
 | 
					        const MfDesfireError error = mf_desfire_poller_read_version(instance, &version);
 | 
				
			||||||
        protocol_detected = (error == MfDesfireErrorNone);
 | 
					        protocol_detected = (error == MfDesfireErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,24 +8,267 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfDesfirePoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct MfDesfirePoller MfDesfirePoller;
 | 
					typedef struct MfDesfirePoller MfDesfirePoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible MfDesfire poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    MfDesfirePollerEventTypeReadSuccess,
 | 
					    MfDesfirePollerEventTypeReadSuccess, /**< Card was read successfully. */
 | 
				
			||||||
    MfDesfirePollerEventTypeReadFailed,
 | 
					    MfDesfirePollerEventTypeReadFailed, /**< Poller failed to read card. */
 | 
				
			||||||
} MfDesfirePollerEventType;
 | 
					} MfDesfirePollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    union {
 | 
					 * @brief MfDesfire poller event data.
 | 
				
			||||||
        MfDesfireError error;
 | 
					 */
 | 
				
			||||||
    };
 | 
					typedef union {
 | 
				
			||||||
 | 
					    MfDesfireError error; /**< Error code indicating card reading fail reason. */
 | 
				
			||||||
} MfDesfirePollerEventData;
 | 
					} MfDesfirePollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfDesfire poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfDesfirePollerEventType type;
 | 
					    MfDesfirePollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    MfDesfirePollerEventData* data;
 | 
					    MfDesfirePollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} MfDesfirePollerEvent;
 | 
					} MfDesfirePollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive MfDesfire chunks in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_send_chunks(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read MfDesfire card version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireVersion structure to be filled with version data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_version(MfDesfirePoller* instance, MfDesfireVersion* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read free memory available on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireFreeMemory structure to be filled with free memory data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError
 | 
				
			||||||
 | 
					    mf_desfire_poller_read_free_memory(MfDesfirePoller* instance, MfDesfireFreeMemory* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read key settings on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireKeySettings structure to be filled with key settings data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError
 | 
				
			||||||
 | 
					    mf_desfire_poller_read_key_settings(MfDesfirePoller* instance, MfDesfireKeySettings* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read key versions on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure to be filled with key versions data.
 | 
				
			||||||
 | 
					 * @param[in] count number of key versions to read.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_key_versions(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    SimpleArray* data,
 | 
				
			||||||
 | 
					    uint32_t count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read applications IDs on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure to be filled with application ids data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError
 | 
				
			||||||
 | 
					    mf_desfire_poller_read_application_ids(MfDesfirePoller* instance, SimpleArray* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Select application on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] id pointer to the MfDesfireApplicationId structure with application id to select.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_select_application(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    const MfDesfireApplicationId* id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read file IDs for selected application on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure to be filled with file ids data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_ids(MfDesfirePoller* instance, SimpleArray* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read file settings on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] id file id to read settings for.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireFileSettings structure to be filled with file settings data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_settings(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
 | 
					    MfDesfireFileSettings* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read multiple file settings on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] file_ids pointer to the SimpleArray structure array with file ids to read settings for.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure array to be filled with file settings data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_settings_multi(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    const SimpleArray* file_ids,
 | 
				
			||||||
 | 
					    SimpleArray* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read file data on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] id file id to read data from.
 | 
				
			||||||
 | 
					 * @param[in] offset offset in bytes to start reading from.
 | 
				
			||||||
 | 
					 * @param[in] size number of bytes to read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireFileData structure to be filled with file data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_data(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
 | 
					    uint32_t offset,
 | 
				
			||||||
 | 
					    size_t size,
 | 
				
			||||||
 | 
					    MfDesfireFileData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read file value on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] id file id to read value from.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireFileData structure to be filled with file value.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_value(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
 | 
					    MfDesfireFileData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read file records on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] id file id to read data from.
 | 
				
			||||||
 | 
					 * @param[in] offset offset in bytes to start reading from.
 | 
				
			||||||
 | 
					 * @param[in] size number of bytes to read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireFileData structure to be filled with file records data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_records(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
 | 
					    uint32_t offset,
 | 
				
			||||||
 | 
					    size_t size,
 | 
				
			||||||
 | 
					    MfDesfireFileData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read data from multiple files on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] file_ids pointer to the SimpleArray structure array with files ids to read data from.
 | 
				
			||||||
 | 
					 * @param[in] file_settings pointer to the SimpleArray structure array with files settings to read data from.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure array to be filled with files data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_file_data_multi(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    const SimpleArray* file_ids,
 | 
				
			||||||
 | 
					    const SimpleArray* file_settings,
 | 
				
			||||||
 | 
					    SimpleArray* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read application data for selected application on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfDesfireApplication structure to be filled with application data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError
 | 
				
			||||||
 | 
					    mf_desfire_poller_read_application(MfDesfirePoller* instance, MfDesfireApplication* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read multiple applications data on MfDesfire card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] app_ids pointer to the SimpleArray structure array with application ids to read data from.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SimpleArray structure array to be filled with applications data.
 | 
				
			||||||
 | 
					 * @return MfDesfireErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfDesfireError mf_desfire_poller_read_applications(
 | 
				
			||||||
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
 | 
					    const SimpleArray* app_ids,
 | 
				
			||||||
 | 
					    SimpleArray* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -74,8 +74,7 @@ MfDesfireError mf_desfire_send_chunks(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError
 | 
					MfDesfireError mf_desfire_poller_read_version(MfDesfirePoller* instance, MfDesfireVersion* data) {
 | 
				
			||||||
    mf_desfire_poller_async_read_version(MfDesfirePoller* instance, MfDesfireVersion* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->input_buffer);
 | 
					    bit_buffer_reset(instance->input_buffer);
 | 
				
			||||||
@ -97,7 +96,7 @@ MfDesfireError
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError
 | 
					MfDesfireError
 | 
				
			||||||
    mf_desfire_poller_async_read_free_memory(MfDesfirePoller* instance, MfDesfireFreeMemory* data) {
 | 
					    mf_desfire_poller_read_free_memory(MfDesfirePoller* instance, MfDesfireFreeMemory* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->input_buffer);
 | 
					    bit_buffer_reset(instance->input_buffer);
 | 
				
			||||||
@ -118,9 +117,8 @@ MfDesfireError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_key_settings(
 | 
					MfDesfireError
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    mf_desfire_poller_read_key_settings(MfDesfirePoller* instance, MfDesfireKeySettings* data) {
 | 
				
			||||||
    MfDesfireKeySettings* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->input_buffer);
 | 
					    bit_buffer_reset(instance->input_buffer);
 | 
				
			||||||
@ -141,7 +139,7 @@ MfDesfireError mf_desfire_poller_async_read_key_settings(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_key_versions(
 | 
					MfDesfireError mf_desfire_poller_read_key_versions(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    SimpleArray* data,
 | 
					    SimpleArray* data,
 | 
				
			||||||
    uint32_t count) {
 | 
					    uint32_t count) {
 | 
				
			||||||
@ -172,7 +170,7 @@ MfDesfireError mf_desfire_poller_async_read_key_versions(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError
 | 
					MfDesfireError
 | 
				
			||||||
    mf_desfire_poller_async_read_application_ids(MfDesfirePoller* instance, SimpleArray* data) {
 | 
					    mf_desfire_poller_read_application_ids(MfDesfirePoller* instance, SimpleArray* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->input_buffer);
 | 
					    bit_buffer_reset(instance->input_buffer);
 | 
				
			||||||
@ -203,7 +201,7 @@ MfDesfireError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_select_application(
 | 
					MfDesfireError mf_desfire_poller_select_application(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    const MfDesfireApplicationId* id) {
 | 
					    const MfDesfireApplicationId* id) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
@ -219,8 +217,7 @@ MfDesfireError mf_desfire_poller_async_select_application(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError
 | 
					MfDesfireError mf_desfire_poller_read_file_ids(MfDesfirePoller* instance, SimpleArray* data) {
 | 
				
			||||||
    mf_desfire_poller_async_read_file_ids(MfDesfirePoller* instance, SimpleArray* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bit_buffer_reset(instance->input_buffer);
 | 
					    bit_buffer_reset(instance->input_buffer);
 | 
				
			||||||
@ -250,7 +247,7 @@ MfDesfireError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_settings(
 | 
					MfDesfireError mf_desfire_poller_read_file_settings(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    MfDesfireFileId id,
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
    MfDesfireFileSettings* data) {
 | 
					    MfDesfireFileSettings* data) {
 | 
				
			||||||
@ -275,7 +272,7 @@ MfDesfireError mf_desfire_poller_async_read_file_settings(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_settings_multi(
 | 
					MfDesfireError mf_desfire_poller_read_file_settings_multi(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    const SimpleArray* file_ids,
 | 
					    const SimpleArray* file_ids,
 | 
				
			||||||
    SimpleArray* data) {
 | 
					    SimpleArray* data) {
 | 
				
			||||||
@ -290,15 +287,14 @@ MfDesfireError mf_desfire_poller_async_read_file_settings_multi(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for(uint32_t i = 0; i < file_id_count; ++i) {
 | 
					    for(uint32_t i = 0; i < file_id_count; ++i) {
 | 
				
			||||||
        const MfDesfireFileId file_id = *(const MfDesfireFileId*)simple_array_cget(file_ids, i);
 | 
					        const MfDesfireFileId file_id = *(const MfDesfireFileId*)simple_array_cget(file_ids, i);
 | 
				
			||||||
        error = mf_desfire_poller_async_read_file_settings(
 | 
					        error = mf_desfire_poller_read_file_settings(instance, file_id, simple_array_get(data, i));
 | 
				
			||||||
            instance, file_id, simple_array_get(data, i));
 | 
					 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_data(
 | 
					MfDesfireError mf_desfire_poller_read_file_data(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    MfDesfireFileId id,
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
    uint32_t offset,
 | 
					    uint32_t offset,
 | 
				
			||||||
@ -327,7 +323,7 @@ MfDesfireError mf_desfire_poller_async_read_file_data(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_value(
 | 
					MfDesfireError mf_desfire_poller_read_file_value(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    MfDesfireFileId id,
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
    MfDesfireFileData* data) {
 | 
					    MfDesfireFileData* data) {
 | 
				
			||||||
@ -352,7 +348,7 @@ MfDesfireError mf_desfire_poller_async_read_file_value(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_records(
 | 
					MfDesfireError mf_desfire_poller_read_file_records(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    MfDesfireFileId id,
 | 
					    MfDesfireFileId id,
 | 
				
			||||||
    uint32_t offset,
 | 
					    uint32_t offset,
 | 
				
			||||||
@ -381,7 +377,7 @@ MfDesfireError mf_desfire_poller_async_read_file_records(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_data_multi(
 | 
					MfDesfireError mf_desfire_poller_read_file_data_multi(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    const SimpleArray* file_ids,
 | 
					    const SimpleArray* file_ids,
 | 
				
			||||||
    const SimpleArray* file_settings,
 | 
					    const SimpleArray* file_settings,
 | 
				
			||||||
@ -404,14 +400,14 @@ MfDesfireError mf_desfire_poller_async_read_file_data_multi(
 | 
				
			|||||||
        MfDesfireFileData* file_data = simple_array_get(data, i);
 | 
					        MfDesfireFileData* file_data = simple_array_get(data, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(file_type == MfDesfireFileTypeStandard || file_type == MfDesfireFileTypeBackup) {
 | 
					        if(file_type == MfDesfireFileTypeStandard || file_type == MfDesfireFileTypeBackup) {
 | 
				
			||||||
            error = mf_desfire_poller_async_read_file_data(
 | 
					            error = mf_desfire_poller_read_file_data(
 | 
				
			||||||
                instance, file_id, 0, file_settings_cur->data.size, file_data);
 | 
					                instance, file_id, 0, file_settings_cur->data.size, file_data);
 | 
				
			||||||
        } else if(file_type == MfDesfireFileTypeValue) {
 | 
					        } else if(file_type == MfDesfireFileTypeValue) {
 | 
				
			||||||
            error = mf_desfire_poller_async_read_file_value(instance, file_id, file_data);
 | 
					            error = mf_desfire_poller_read_file_value(instance, file_id, file_data);
 | 
				
			||||||
        } else if(
 | 
					        } else if(
 | 
				
			||||||
            file_type == MfDesfireFileTypeLinearRecord ||
 | 
					            file_type == MfDesfireFileTypeLinearRecord ||
 | 
				
			||||||
            file_type == MfDesfireFileTypeCyclicRecord) {
 | 
					            file_type == MfDesfireFileTypeCyclicRecord) {
 | 
				
			||||||
            error = mf_desfire_poller_async_read_file_records(
 | 
					            error = mf_desfire_poller_read_file_records(
 | 
				
			||||||
                instance, file_id, 0, file_settings_cur->data.size, file_data);
 | 
					                instance, file_id, 0, file_settings_cur->data.size, file_data);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -421,30 +417,29 @@ MfDesfireError mf_desfire_poller_async_read_file_data_multi(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_application(
 | 
					MfDesfireError
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    mf_desfire_poller_read_application(MfDesfirePoller* instance, MfDesfireApplication* data) {
 | 
				
			||||||
    MfDesfireApplication* data) {
 | 
					 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfDesfireError error;
 | 
					    MfDesfireError error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        error = mf_desfire_poller_async_read_key_settings(instance, &data->key_settings);
 | 
					        error = mf_desfire_poller_read_key_settings(instance, &data->key_settings);
 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_desfire_poller_async_read_key_versions(
 | 
					        error = mf_desfire_poller_read_key_versions(
 | 
				
			||||||
            instance, data->key_versions, data->key_settings.max_keys);
 | 
					            instance, data->key_versions, data->key_settings.max_keys);
 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_desfire_poller_async_read_file_ids(instance, data->file_ids);
 | 
					        error = mf_desfire_poller_read_file_ids(instance, data->file_ids);
 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_desfire_poller_async_read_file_settings_multi(
 | 
					        error = mf_desfire_poller_read_file_settings_multi(
 | 
				
			||||||
            instance, data->file_ids, data->file_settings);
 | 
					            instance, data->file_ids, data->file_settings);
 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        error = mf_desfire_poller_async_read_file_data_multi(
 | 
					        error = mf_desfire_poller_read_file_data_multi(
 | 
				
			||||||
            instance, data->file_ids, data->file_settings, data->file_data);
 | 
					            instance, data->file_ids, data->file_settings, data->file_data);
 | 
				
			||||||
        if(error != MfDesfireErrorNone) break;
 | 
					        if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -453,7 +448,7 @@ MfDesfireError mf_desfire_poller_async_read_application(
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_applications(
 | 
					MfDesfireError mf_desfire_poller_read_applications(
 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					    MfDesfirePoller* instance,
 | 
				
			||||||
    const SimpleArray* app_ids,
 | 
					    const SimpleArray* app_ids,
 | 
				
			||||||
    SimpleArray* data) {
 | 
					    SimpleArray* data) {
 | 
				
			||||||
@ -468,12 +463,11 @@ MfDesfireError mf_desfire_poller_async_read_applications(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for(uint32_t i = 0; i < app_id_count; ++i) {
 | 
					    for(uint32_t i = 0; i < app_id_count; ++i) {
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
            error = mf_desfire_poller_async_select_application(
 | 
					            error = mf_desfire_poller_select_application(instance, simple_array_cget(app_ids, i));
 | 
				
			||||||
                instance, simple_array_cget(app_ids, i));
 | 
					 | 
				
			||||||
            if(error != MfDesfireErrorNone) break;
 | 
					            if(error != MfDesfireErrorNone) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            MfDesfireApplication* current_app = simple_array_get(data, i);
 | 
					            MfDesfireApplication* current_app = simple_array_get(data, i);
 | 
				
			||||||
            error = mf_desfire_poller_async_read_application(instance, current_app);
 | 
					            error = mf_desfire_poller_read_application(instance, current_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } while(false);
 | 
					        } while(false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -49,78 +49,6 @@ MfDesfireError mf_desfire_process_error(Iso14443_4aError error);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const MfDesfireData* mf_desfire_poller_get_data(MfDesfirePoller* instance);
 | 
					const MfDesfireData* mf_desfire_poller_get_data(MfDesfirePoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfDesfireError mf_desfire_send_chunks(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError
 | 
					 | 
				
			||||||
    mf_desfire_poller_async_read_version(MfDesfirePoller* instance, MfDesfireVersion* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError
 | 
					 | 
				
			||||||
    mf_desfire_poller_async_read_free_memory(MfDesfirePoller* instance, MfDesfireFreeMemory* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_key_settings(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    MfDesfireKeySettings* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_key_versions(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    SimpleArray* data,
 | 
					 | 
				
			||||||
    uint32_t count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError
 | 
					 | 
				
			||||||
    mf_desfire_poller_async_read_application_ids(MfDesfirePoller* instance, SimpleArray* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_select_application(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    const MfDesfireApplicationId* id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_ids(MfDesfirePoller* instance, SimpleArray* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_settings(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    MfDesfireFileId id,
 | 
					 | 
				
			||||||
    MfDesfireFileSettings* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_settings_multi(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    const SimpleArray* file_ids,
 | 
					 | 
				
			||||||
    SimpleArray* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_data(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    MfDesfireFileId id,
 | 
					 | 
				
			||||||
    uint32_t offset,
 | 
					 | 
				
			||||||
    size_t size,
 | 
					 | 
				
			||||||
    MfDesfireFileData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_value(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    MfDesfireFileId id,
 | 
					 | 
				
			||||||
    MfDesfireFileData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_records(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    MfDesfireFileId id,
 | 
					 | 
				
			||||||
    uint32_t offset,
 | 
					 | 
				
			||||||
    size_t size,
 | 
					 | 
				
			||||||
    MfDesfireFileData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_file_data_multi(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    const SimpleArray* file_ids,
 | 
					 | 
				
			||||||
    const SimpleArray* file_settings,
 | 
					 | 
				
			||||||
    SimpleArray* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError
 | 
					 | 
				
			||||||
    mf_desfire_poller_async_read_application(MfDesfirePoller* instance, MfDesfireApplication* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfDesfireError mf_desfire_poller_async_read_applications(
 | 
					 | 
				
			||||||
    MfDesfirePoller* instance,
 | 
					 | 
				
			||||||
    const SimpleArray* app_ids,
 | 
					 | 
				
			||||||
    SimpleArray* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -230,7 +230,7 @@ static NfcCommand mf_ultralight_poller_handler_idle(MfUltralightPoller* instance
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_ultralight_poller_handler_read_version(MfUltralightPoller* instance) {
 | 
					static NfcCommand mf_ultralight_poller_handler_read_version(MfUltralightPoller* instance) {
 | 
				
			||||||
    instance->error = mf_ultralight_poller_async_read_version(instance, &instance->data->version);
 | 
					    instance->error = mf_ultralight_poller_read_version(instance, &instance->data->version);
 | 
				
			||||||
    if(instance->error == MfUltralightErrorNone) {
 | 
					    if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Read version success");
 | 
					        FURI_LOG_D(TAG, "Read version success");
 | 
				
			||||||
        instance->data->type = mf_ultralight_get_type_by_version(&instance->data->version);
 | 
					        instance->data->type = mf_ultralight_get_type_by_version(&instance->data->version);
 | 
				
			||||||
@ -245,7 +245,7 @@ static NfcCommand mf_ultralight_poller_handler_read_version(MfUltralightPoller*
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_ultralight_poller_handler_check_ultralight_c(MfUltralightPoller* instance) {
 | 
					static NfcCommand mf_ultralight_poller_handler_check_ultralight_c(MfUltralightPoller* instance) {
 | 
				
			||||||
    instance->error = mf_ultralight_poller_async_authenticate(instance);
 | 
					    instance->error = mf_ultralight_poller_authenticate(instance);
 | 
				
			||||||
    if(instance->error == MfUltralightErrorNone) {
 | 
					    if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Ultralight C detected");
 | 
					        FURI_LOG_D(TAG, "Ultralight C detected");
 | 
				
			||||||
        instance->data->type = MfUltralightTypeMfulC;
 | 
					        instance->data->type = MfUltralightTypeMfulC;
 | 
				
			||||||
@ -260,7 +260,7 @@ static NfcCommand mf_ultralight_poller_handler_check_ultralight_c(MfUltralightPo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_ultralight_poller_handler_check_ntag_203(MfUltralightPoller* instance) {
 | 
					static NfcCommand mf_ultralight_poller_handler_check_ntag_203(MfUltralightPoller* instance) {
 | 
				
			||||||
    MfUltralightPageReadCommandData data = {};
 | 
					    MfUltralightPageReadCommandData data = {};
 | 
				
			||||||
    instance->error = mf_ultralight_poller_async_read_page(instance, 41, &data);
 | 
					    instance->error = mf_ultralight_poller_read_page(instance, 41, &data);
 | 
				
			||||||
    if(instance->error == MfUltralightErrorNone) {
 | 
					    if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "NTAG203 detected");
 | 
					        FURI_LOG_D(TAG, "NTAG203 detected");
 | 
				
			||||||
        instance->data->type = MfUltralightTypeNTAG203;
 | 
					        instance->data->type = MfUltralightTypeNTAG203;
 | 
				
			||||||
@ -294,7 +294,7 @@ static NfcCommand mf_ultralight_poller_handler_read_signature(MfUltralightPoller
 | 
				
			|||||||
           instance->feature_set, MfUltralightFeatureSupportReadSignature)) {
 | 
					           instance->feature_set, MfUltralightFeatureSupportReadSignature)) {
 | 
				
			||||||
        FURI_LOG_D(TAG, "Reading signature");
 | 
					        FURI_LOG_D(TAG, "Reading signature");
 | 
				
			||||||
        instance->error =
 | 
					        instance->error =
 | 
				
			||||||
            mf_ultralight_poller_async_read_signature(instance, &instance->data->signature);
 | 
					            mf_ultralight_poller_read_signature(instance, &instance->data->signature);
 | 
				
			||||||
        if(instance->error != MfUltralightErrorNone) {
 | 
					        if(instance->error != MfUltralightErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Read signature failed");
 | 
					            FURI_LOG_D(TAG, "Read signature failed");
 | 
				
			||||||
            next_state = MfUltralightPollerStateReadFailed;
 | 
					            next_state = MfUltralightPollerStateReadFailed;
 | 
				
			||||||
@ -337,7 +337,7 @@ static NfcCommand mf_ultralight_poller_handler_read_counters(MfUltralightPoller*
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FURI_LOG_D(TAG, "Reading counter %d", instance->counters_read);
 | 
					        FURI_LOG_D(TAG, "Reading counter %d", instance->counters_read);
 | 
				
			||||||
        instance->error = mf_ultralight_poller_async_read_counter(
 | 
					        instance->error = mf_ultralight_poller_read_counter(
 | 
				
			||||||
            instance, instance->counters_read, &instance->data->counter[instance->counters_read]);
 | 
					            instance, instance->counters_read, &instance->data->counter[instance->counters_read]);
 | 
				
			||||||
        if(instance->error != MfUltralightErrorNone) {
 | 
					        if(instance->error != MfUltralightErrorNone) {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to read %d counter", instance->counters_read);
 | 
					            FURI_LOG_D(TAG, "Failed to read %d counter", instance->counters_read);
 | 
				
			||||||
@ -363,7 +363,7 @@ static NfcCommand mf_ultralight_poller_handler_read_tearing_flags(MfUltralightPo
 | 
				
			|||||||
            if(single_counter) instance->tearing_flag_read = 2;
 | 
					            if(single_counter) instance->tearing_flag_read = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            FURI_LOG_D(TAG, "Reading tearing flag %d", instance->tearing_flag_read);
 | 
					            FURI_LOG_D(TAG, "Reading tearing flag %d", instance->tearing_flag_read);
 | 
				
			||||||
            instance->error = mf_ultralight_poller_async_read_tearing_flag(
 | 
					            instance->error = mf_ultralight_poller_read_tearing_flag(
 | 
				
			||||||
                instance,
 | 
					                instance,
 | 
				
			||||||
                instance->tearing_flag_read,
 | 
					                instance->tearing_flag_read,
 | 
				
			||||||
                &instance->data->tearing_flag[instance->tearing_flag_read]);
 | 
					                &instance->data->tearing_flag[instance->tearing_flag_read]);
 | 
				
			||||||
@ -396,8 +396,7 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance
 | 
				
			|||||||
            uint32_t pass = nfc_util_bytes2num(
 | 
					            uint32_t pass = nfc_util_bytes2num(
 | 
				
			||||||
                instance->auth_context.password.data, sizeof(MfUltralightAuthPassword));
 | 
					                instance->auth_context.password.data, sizeof(MfUltralightAuthPassword));
 | 
				
			||||||
            FURI_LOG_D(TAG, "Trying to authenticate with password %08lX", pass);
 | 
					            FURI_LOG_D(TAG, "Trying to authenticate with password %08lX", pass);
 | 
				
			||||||
            instance->error =
 | 
					            instance->error = mf_ultralight_poller_auth_pwd(instance, &instance->auth_context);
 | 
				
			||||||
                mf_ultralight_poller_async_auth_pwd(instance, &instance->auth_context);
 | 
					 | 
				
			||||||
            if(instance->error == MfUltralightErrorNone) {
 | 
					            if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
                FURI_LOG_D(TAG, "Auth success");
 | 
					                FURI_LOG_D(TAG, "Auth success");
 | 
				
			||||||
                instance->auth_context.auth_success = true;
 | 
					                instance->auth_context.auth_success = true;
 | 
				
			||||||
@ -428,13 +427,13 @@ static NfcCommand mf_ultralight_poller_handler_read_pages(MfUltralightPoller* in
 | 
				
			|||||||
        if(mf_ultralight_poller_ntag_i2c_addr_lin_to_tag(
 | 
					        if(mf_ultralight_poller_ntag_i2c_addr_lin_to_tag(
 | 
				
			||||||
               instance, start_page, §or, &tag, &pages_left)) {
 | 
					               instance, start_page, §or, &tag, &pages_left)) {
 | 
				
			||||||
            instance->error =
 | 
					            instance->error =
 | 
				
			||||||
                mf_ultralight_poller_async_read_page_from_sector(instance, sector, tag, &data);
 | 
					                mf_ultralight_poller_read_page_from_sector(instance, sector, tag, &data);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            FURI_LOG_D(TAG, "Failed to calculate sector and tag from %d page", start_page);
 | 
					            FURI_LOG_D(TAG, "Failed to calculate sector and tag from %d page", start_page);
 | 
				
			||||||
            instance->error = MfUltralightErrorProtocol;
 | 
					            instance->error = MfUltralightErrorProtocol;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        instance->error = mf_ultralight_poller_async_read_page(instance, start_page, &data);
 | 
					        instance->error = mf_ultralight_poller_read_page(instance, start_page, &data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(instance->error == MfUltralightErrorNone) {
 | 
					    if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
@ -478,8 +477,7 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll
 | 
				
			|||||||
                MF_ULTRALIGHT_DEFAULT_PASSWORD,
 | 
					                MF_ULTRALIGHT_DEFAULT_PASSWORD,
 | 
				
			||||||
                sizeof(MfUltralightAuthPassword),
 | 
					                sizeof(MfUltralightAuthPassword),
 | 
				
			||||||
                instance->auth_context.password.data);
 | 
					                instance->auth_context.password.data);
 | 
				
			||||||
            instance->error =
 | 
					            instance->error = mf_ultralight_poller_auth_pwd(instance, &instance->auth_context);
 | 
				
			||||||
                mf_ultralight_poller_async_auth_pwd(instance, &instance->auth_context);
 | 
					 | 
				
			||||||
            if(instance->error == MfUltralightErrorNone) {
 | 
					            if(instance->error == MfUltralightErrorNone) {
 | 
				
			||||||
                FURI_LOG_D(TAG, "Default password detected");
 | 
					                FURI_LOG_D(TAG, "Default password detected");
 | 
				
			||||||
                nfc_util_num2bytes(
 | 
					                nfc_util_num2bytes(
 | 
				
			||||||
@ -576,8 +574,7 @@ static bool mf_ultralight_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
					    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
				
			||||||
        MfUltralightPageReadCommandData read_page_cmd_data = {};
 | 
					        MfUltralightPageReadCommandData read_page_cmd_data = {};
 | 
				
			||||||
        MfUltralightError error =
 | 
					        MfUltralightError error = mf_ultralight_poller_read_page(instance, 0, &read_page_cmd_data);
 | 
				
			||||||
            mf_ultralight_poller_async_read_page(instance, 0, &read_page_cmd_data);
 | 
					 | 
				
			||||||
        protocol_detected = (error == MfUltralightErrorNone);
 | 
					        protocol_detected = (error == MfUltralightErrorNone);
 | 
				
			||||||
        iso14443_3a_poller_halt(instance->iso14443_3a_poller);
 | 
					        iso14443_3a_poller_halt(instance->iso14443_3a_poller);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,35 +7,181 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfUltralightPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct MfUltralightPoller MfUltralightPoller;
 | 
					typedef struct MfUltralightPoller MfUltralightPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible MfUltralight poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    MfUltralightPollerEventTypeAuthRequest,
 | 
					    MfUltralightPollerEventTypeAuthRequest, /**< Poller requests to fill authentication context. */
 | 
				
			||||||
    MfUltralightPollerEventTypeAuthSuccess,
 | 
					    MfUltralightPollerEventTypeAuthSuccess, /**< Authentication succeeded. */
 | 
				
			||||||
    MfUltralightPollerEventTypeAuthFailed,
 | 
					    MfUltralightPollerEventTypeAuthFailed, /**< Authentication failed. */
 | 
				
			||||||
    MfUltralightPollerEventTypeReadSuccess,
 | 
					    MfUltralightPollerEventTypeReadSuccess, /**< Poller read card successfully. */
 | 
				
			||||||
    MfUltralightPollerEventTypeReadFailed,
 | 
					    MfUltralightPollerEventTypeReadFailed, /**< Poller failed to read card. */
 | 
				
			||||||
} MfUltralightPollerEventType;
 | 
					} MfUltralightPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfUltralight poller authentication context.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfUltralightAuthPassword password;
 | 
					    MfUltralightAuthPassword password; /**< Password to be used for authentication. */
 | 
				
			||||||
    MfUltralightAuthPack pack;
 | 
					    MfUltralightAuthPack pack; /**< Pack received on successfull authentication. */
 | 
				
			||||||
    bool auth_success;
 | 
					    bool auth_success; /**< Set to true if authentication succeeded, false otherwise. */
 | 
				
			||||||
    bool skip_auth;
 | 
					    bool skip_auth; /**< Set to true if authentication should be skipped, false otherwise. */
 | 
				
			||||||
} MfUltralightPollerAuthContext;
 | 
					} MfUltralightPollerAuthContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    union {
 | 
					 * @brief MfUltralight poller event data.
 | 
				
			||||||
        MfUltralightPollerAuthContext auth_context;
 | 
					 */
 | 
				
			||||||
        MfUltralightError error;
 | 
					typedef union {
 | 
				
			||||||
    };
 | 
					    MfUltralightPollerAuthContext auth_context; /**< Authentication context. */
 | 
				
			||||||
 | 
					    MfUltralightError error; /**< Error code indicating reading fail reason. */
 | 
				
			||||||
} MfUltralightPollerEventData;
 | 
					} MfUltralightPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief MfUltralight poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MfUltralightPollerEventType type;
 | 
					    MfUltralightPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    MfUltralightPollerEventData* data;
 | 
					    MfUltralightPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} MfUltralightPollerEvent;
 | 
					} MfUltralightPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Perform authentication with password.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in, out] data pointer to the authentication context.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_auth_pwd(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    MfUltralightPollerAuthContext* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Start authentication procedure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function now is used only to identify Mf Ultralight C cards.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone if card supports authentication command, an error code on otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_authenticate(MfUltralightPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read page from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Send read command and parse response. The response on this command is data of 4 pages starting
 | 
				
			||||||
 | 
					 * from the page specified in the command.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] start_page page number to be read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightPageReadCommandData structure to be filled with page data.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_read_page(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t start_page,
 | 
				
			||||||
 | 
					    MfUltralightPageReadCommandData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read page from sector.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This command should be used for NTAGI2C tags.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] sector sector number to be read.
 | 
				
			||||||
 | 
					 * @param[in] tag tag number to be read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightPageReadCommandData structure to be filled with page data.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_read_page_from_sector(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t sector,
 | 
				
			||||||
 | 
					    uint8_t tag,
 | 
				
			||||||
 | 
					    MfUltralightPageReadCommandData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Write page to card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] page page number to be written.
 | 
				
			||||||
 | 
					 * @param[in] data pointer to the MfUltralightPage structure to be written.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_write_page(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t page,
 | 
				
			||||||
 | 
					    const MfUltralightPage* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read version from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightVersion structure to be filled.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError
 | 
				
			||||||
 | 
					    mf_ultralight_poller_read_version(MfUltralightPoller* instance, MfUltralightVersion* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read signature from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightSignature structure to be filled.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError
 | 
				
			||||||
 | 
					    mf_ultralight_poller_read_signature(MfUltralightPoller* instance, MfUltralightSignature* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read counter from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] counter_num counter number to be read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightCounter structure to be filled.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_read_counter(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t counter_num,
 | 
				
			||||||
 | 
					    MfUltralightCounter* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read tearing flag from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tearing_falg_num tearing flag number to be read.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the MfUltralightTearingFlag structure to be filled.
 | 
				
			||||||
 | 
					 * @return MfUltralightErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_read_tearing_flag(
 | 
				
			||||||
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
 | 
					    uint8_t tearing_falg_num,
 | 
				
			||||||
 | 
					    MfUltralightTearingFlag* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@ MfUltralightError mf_ultralight_process_error(Iso14443_3aError error) {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_auth_pwd(
 | 
					MfUltralightError mf_ultralight_poller_auth_pwd(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    MfUltralightPollerAuthContext* data) {
 | 
					    MfUltralightPollerAuthContext* data) {
 | 
				
			||||||
    uint8_t auth_cmd[5] = {MF_ULTRALIGHT_CMD_PWD_AUTH}; //-V1009
 | 
					    uint8_t auth_cmd[5] = {MF_ULTRALIGHT_CMD_PWD_AUTH}; //-V1009
 | 
				
			||||||
@ -59,7 +59,7 @@ MfUltralightError mf_ultralight_poller_async_auth_pwd(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_authenticate(MfUltralightPoller* instance) {
 | 
					MfUltralightError mf_ultralight_poller_authenticate(MfUltralightPoller* instance) {
 | 
				
			||||||
    uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00};
 | 
					    uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00};
 | 
				
			||||||
    bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd));
 | 
					    bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -86,7 +86,7 @@ MfUltralightError mf_ultralight_poller_async_authenticate(MfUltralightPoller* in
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_page_from_sector(
 | 
					MfUltralightError mf_ultralight_poller_read_page_from_sector(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    uint8_t sector,
 | 
					    uint8_t sector,
 | 
				
			||||||
    uint8_t tag,
 | 
					    uint8_t tag,
 | 
				
			||||||
@ -122,13 +122,13 @@ MfUltralightError mf_ultralight_poller_async_read_page_from_sector(
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = mf_ultralight_poller_async_read_page(instance, tag, data);
 | 
					        ret = mf_ultralight_poller_read_page(instance, tag, data);
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_page(
 | 
					MfUltralightError mf_ultralight_poller_read_page(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    uint8_t start_page,
 | 
					    uint8_t start_page,
 | 
				
			||||||
    MfUltralightPageReadCommandData* data) {
 | 
					    MfUltralightPageReadCommandData* data) {
 | 
				
			||||||
@ -158,10 +158,10 @@ MfUltralightError mf_ultralight_poller_async_read_page(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_write_page(
 | 
					MfUltralightError mf_ultralight_poller_write_page(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    uint8_t page,
 | 
					    uint8_t page,
 | 
				
			||||||
    MfUltralightPage* data) {
 | 
					    const MfUltralightPage* data) {
 | 
				
			||||||
    MfUltralightError ret = MfUltralightErrorNone;
 | 
					    MfUltralightError ret = MfUltralightErrorNone;
 | 
				
			||||||
    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
					    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -191,9 +191,8 @@ MfUltralightError mf_ultralight_poller_async_write_page(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_version(
 | 
					MfUltralightError
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    mf_ultralight_poller_read_version(MfUltralightPoller* instance, MfUltralightVersion* data) {
 | 
				
			||||||
    MfUltralightVersion* data) {
 | 
					 | 
				
			||||||
    MfUltralightError ret = MfUltralightErrorNone;
 | 
					    MfUltralightError ret = MfUltralightErrorNone;
 | 
				
			||||||
    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
					    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -221,9 +220,8 @@ MfUltralightError mf_ultralight_poller_async_read_version(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_signature(
 | 
					MfUltralightError
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    mf_ultralight_poller_read_signature(MfUltralightPoller* instance, MfUltralightSignature* data) {
 | 
				
			||||||
    MfUltralightSignature* data) {
 | 
					 | 
				
			||||||
    MfUltralightError ret = MfUltralightErrorNone;
 | 
					    MfUltralightError ret = MfUltralightErrorNone;
 | 
				
			||||||
    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
					    Iso14443_3aError error = Iso14443_3aErrorNone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -249,7 +247,7 @@ MfUltralightError mf_ultralight_poller_async_read_signature(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_counter(
 | 
					MfUltralightError mf_ultralight_poller_read_counter(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    uint8_t counter_num,
 | 
					    uint8_t counter_num,
 | 
				
			||||||
    MfUltralightCounter* data) {
 | 
					    MfUltralightCounter* data) {
 | 
				
			||||||
@ -278,7 +276,7 @@ MfUltralightError mf_ultralight_poller_async_read_counter(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_tearing_flag(
 | 
					MfUltralightError mf_ultralight_poller_read_tearing_flag(
 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					    MfUltralightPoller* instance,
 | 
				
			||||||
    uint8_t tearing_falg_num,
 | 
					    uint8_t tearing_falg_num,
 | 
				
			||||||
    MfUltralightTearingFlag* data) {
 | 
					    MfUltralightTearingFlag* data) {
 | 
				
			||||||
 | 
				
			|||||||
@ -103,46 +103,6 @@ bool mf_ultralight_poller_ntag_i2c_addr_lin_to_tag(
 | 
				
			|||||||
    uint8_t* tag,
 | 
					    uint8_t* tag,
 | 
				
			||||||
    uint8_t* pages_left);
 | 
					    uint8_t* pages_left);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_auth_pwd(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    MfUltralightPollerAuthContext* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_authenticate(MfUltralightPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_page(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t start_page,
 | 
					 | 
				
			||||||
    MfUltralightPageReadCommandData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_page_from_sector(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t sector,
 | 
					 | 
				
			||||||
    uint8_t tag,
 | 
					 | 
				
			||||||
    MfUltralightPageReadCommandData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_write_page(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t page,
 | 
					 | 
				
			||||||
    MfUltralightPage* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_version(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    MfUltralightVersion* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_signature(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    MfUltralightSignature* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_counter(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t counter_num,
 | 
					 | 
				
			||||||
    MfUltralightCounter* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_async_read_tearing_flag(
 | 
					 | 
				
			||||||
    MfUltralightPoller* instance,
 | 
					 | 
				
			||||||
    uint8_t tearing_falg_num,
 | 
					 | 
				
			||||||
    MfUltralightTearingFlag* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					#include "mf_ultralight_poller_sync.h"
 | 
				
			||||||
#include "mf_ultralight_poller_i.h"
 | 
					#include "mf_ultralight_poller_i.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nfc/nfc_poller.h>
 | 
					#include <nfc/nfc_poller.h>
 | 
				
			||||||
@ -31,40 +32,39 @@ typedef MfUltralightError (*MfUltralightPollerCmdHandler)(
 | 
				
			|||||||
MfUltralightError mf_ultralight_poller_read_page_handler(
 | 
					MfUltralightError mf_ultralight_poller_read_page_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_read_page(
 | 
					    return mf_ultralight_poller_read_page(poller, data->read_cmd.start_page, &data->read_cmd.data);
 | 
				
			||||||
        poller, data->read_cmd.start_page, &data->read_cmd.data);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_write_page_handler(
 | 
					MfUltralightError mf_ultralight_poller_write_page_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_write_page(
 | 
					    return mf_ultralight_poller_write_page(
 | 
				
			||||||
        poller, data->write_cmd.page_to_write, &data->write_cmd.page);
 | 
					        poller, data->write_cmd.page_to_write, &data->write_cmd.page);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_version_handler(
 | 
					MfUltralightError mf_ultralight_poller_read_version_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_read_version(poller, &data->version);
 | 
					    return mf_ultralight_poller_read_version(poller, &data->version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_signature_handler(
 | 
					MfUltralightError mf_ultralight_poller_read_signature_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_read_signature(poller, &data->signature);
 | 
					    return mf_ultralight_poller_read_signature(poller, &data->signature);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_counter_handler(
 | 
					MfUltralightError mf_ultralight_poller_read_counter_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_read_counter(
 | 
					    return mf_ultralight_poller_read_counter(
 | 
				
			||||||
        poller, data->counter_cmd.counter_num, &data->counter_cmd.data);
 | 
					        poller, data->counter_cmd.counter_num, &data->counter_cmd.data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_tearing_flag_handler(
 | 
					MfUltralightError mf_ultralight_poller_read_tearing_flag_handler(
 | 
				
			||||||
    MfUltralightPoller* poller,
 | 
					    MfUltralightPoller* poller,
 | 
				
			||||||
    MfUltralightPollerContextData* data) {
 | 
					    MfUltralightPollerContextData* data) {
 | 
				
			||||||
    return mf_ultralight_poller_async_read_tearing_flag(
 | 
					    return mf_ultralight_poller_read_tearing_flag(
 | 
				
			||||||
        poller, data->tearing_flag_cmd.tearing_flag_num, &data->tearing_flag_cmd.data);
 | 
					        poller, data->tearing_flag_cmd.tearing_flag_num, &data->tearing_flag_cmd.data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,16 +79,14 @@ static const MfUltralightPollerCmdHandler
 | 
				
			|||||||
            mf_ultralight_poller_read_tearing_flag_handler,
 | 
					            mf_ultralight_poller_read_tearing_flag_handler,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand mf_ultralight_poller_cmd_callback(NfcGenericEvent event, void* context) {
 | 
					static NfcCommand mf_ultralight_poller_cmd_callback(NfcGenericEventEx event, void* context) {
 | 
				
			||||||
    furi_assert(event.instance);
 | 
					    furi_assert(event.poller);
 | 
				
			||||||
    furi_assert(event.protocol == NfcProtocolIso14443_3a);
 | 
					    furi_assert(event.parent_event_data);
 | 
				
			||||||
    furi_assert(event.event_data);
 | 
					 | 
				
			||||||
    furi_assert(context);
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MfUltralightPollerContext* poller_context = context;
 | 
					    MfUltralightPollerContext* poller_context = context;
 | 
				
			||||||
    Iso14443_3aPollerEvent* iso14443_3a_event = event.event_data;
 | 
					    Iso14443_3aPollerEvent* iso14443_3a_event = event.parent_event_data;
 | 
				
			||||||
    Iso14443_3aPoller* iso14443_3a_poller = event.instance;
 | 
					    MfUltralightPoller* mfu_poller = event.poller;
 | 
				
			||||||
    MfUltralightPoller* mfu_poller = mf_ultralight_poller_alloc(iso14443_3a_poller);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
					    if(iso14443_3a_event->type == Iso14443_3aPollerEventTypeReady) {
 | 
				
			||||||
        poller_context->error = mf_ultralight_poller_cmd_handlers[poller_context->cmd_type](
 | 
					        poller_context->error = mf_ultralight_poller_cmd_handlers[poller_context->cmd_type](
 | 
				
			||||||
@ -99,8 +97,6 @@ static NfcCommand mf_ultralight_poller_cmd_callback(NfcGenericEvent event, void*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    furi_thread_flags_set(poller_context->thread_id, MF_ULTRALIGHT_POLLER_COMPLETE_EVENT);
 | 
					    furi_thread_flags_set(poller_context->thread_id, MF_ULTRALIGHT_POLLER_COMPLETE_EVENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mf_ultralight_poller_free(mfu_poller);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return NfcCommandStop;
 | 
					    return NfcCommandStop;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,8 +106,8 @@ static MfUltralightError
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    poller_ctx->thread_id = furi_thread_get_current_id();
 | 
					    poller_ctx->thread_id = furi_thread_get_current_id();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NfcPoller* poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a);
 | 
					    NfcPoller* poller = nfc_poller_alloc(nfc, NfcProtocolMfUltralight);
 | 
				
			||||||
    nfc_poller_start(poller, mf_ultralight_poller_cmd_callback, poller_ctx);
 | 
					    nfc_poller_start_ex(poller, mf_ultralight_poller_cmd_callback, poller_ctx);
 | 
				
			||||||
    furi_thread_flags_wait(MF_ULTRALIGHT_POLLER_COMPLETE_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
					    furi_thread_flags_wait(MF_ULTRALIGHT_POLLER_COMPLETE_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
				
			||||||
    furi_thread_flags_clear(MF_ULTRALIGHT_POLLER_COMPLETE_EVENT);
 | 
					    furi_thread_flags_clear(MF_ULTRALIGHT_POLLER_COMPLETE_EVENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -121,7 +117,8 @@ static MfUltralightError
 | 
				
			|||||||
    return poller_ctx->error;
 | 
					    return poller_ctx->error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_page(Nfc* nfc, uint16_t page, MfUltralightPage* data) {
 | 
					MfUltralightError
 | 
				
			||||||
 | 
					    mf_ultralight_poller_sync_read_page(Nfc* nfc, uint16_t page, MfUltralightPage* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,7 +137,7 @@ MfUltralightError mf_ultralight_poller_read_page(Nfc* nfc, uint16_t page, MfUltr
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError
 | 
					MfUltralightError
 | 
				
			||||||
    mf_ultralight_poller_write_page(Nfc* nfc, uint16_t page, MfUltralightPage* data) {
 | 
					    mf_ultralight_poller_sync_write_page(Nfc* nfc, uint16_t page, MfUltralightPage* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -158,7 +155,7 @@ MfUltralightError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_version(Nfc* nfc, MfUltralightVersion* data) {
 | 
					MfUltralightError mf_ultralight_poller_sync_read_version(Nfc* nfc, MfUltralightVersion* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -175,7 +172,7 @@ MfUltralightError mf_ultralight_poller_read_version(Nfc* nfc, MfUltralightVersio
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_signature(Nfc* nfc, MfUltralightSignature* data) {
 | 
					MfUltralightError mf_ultralight_poller_sync_read_signature(Nfc* nfc, MfUltralightSignature* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -192,8 +189,10 @@ MfUltralightError mf_ultralight_poller_read_signature(Nfc* nfc, MfUltralightSign
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError
 | 
					MfUltralightError mf_ultralight_poller_sync_read_counter(
 | 
				
			||||||
    mf_ultralight_poller_read_counter(Nfc* nfc, uint8_t counter_num, MfUltralightCounter* data) {
 | 
					    Nfc* nfc,
 | 
				
			||||||
 | 
					    uint8_t counter_num,
 | 
				
			||||||
 | 
					    MfUltralightCounter* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -211,7 +210,7 @@ MfUltralightError
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_tearing_flag(
 | 
					MfUltralightError mf_ultralight_poller_sync_read_tearing_flag(
 | 
				
			||||||
    Nfc* nfc,
 | 
					    Nfc* nfc,
 | 
				
			||||||
    uint8_t flag_num,
 | 
					    uint8_t flag_num,
 | 
				
			||||||
    MfUltralightTearingFlag* data) {
 | 
					    MfUltralightTearingFlag* data) {
 | 
				
			||||||
@ -261,7 +260,7 @@ static NfcCommand mf_ultralight_poller_read_callback(NfcGenericEvent event, void
 | 
				
			|||||||
    return command;
 | 
					    return command;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_card(Nfc* nfc, MfUltralightData* data) {
 | 
					MfUltralightError mf_ultralight_poller_sync_read_card(Nfc* nfc, MfUltralightData* data) {
 | 
				
			||||||
    furi_assert(nfc);
 | 
					    furi_assert(nfc);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mf_ultralight.h"
 | 
				
			||||||
 | 
					#include <nfc/nfc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError
 | 
				
			||||||
 | 
					    mf_ultralight_poller_sync_read_page(Nfc* nfc, uint16_t page, MfUltralightPage* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError
 | 
				
			||||||
 | 
					    mf_ultralight_poller_sync_write_page(Nfc* nfc, uint16_t page, MfUltralightPage* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_sync_read_version(Nfc* nfc, MfUltralightVersion* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_sync_read_signature(Nfc* nfc, MfUltralightSignature* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_sync_read_counter(
 | 
				
			||||||
 | 
					    Nfc* nfc,
 | 
				
			||||||
 | 
					    uint8_t counter_num,
 | 
				
			||||||
 | 
					    MfUltralightCounter* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_sync_read_tearing_flag(
 | 
				
			||||||
 | 
					    Nfc* nfc,
 | 
				
			||||||
 | 
					    uint8_t flag_num,
 | 
				
			||||||
 | 
					    MfUltralightTearingFlag* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MfUltralightError mf_ultralight_poller_sync_read_card(Nfc* nfc, MfUltralightData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -1,30 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "mf_ultralight.h"
 | 
					 | 
				
			||||||
#include <nfc/nfc.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					 | 
				
			||||||
extern "C" {
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_page(Nfc* nfc, uint16_t page, MfUltralightPage* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_write_page(Nfc* nfc, uint16_t page, MfUltralightPage* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_version(Nfc* nfc, MfUltralightVersion* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_signature(Nfc* nfc, MfUltralightSignature* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError
 | 
					 | 
				
			||||||
    mf_ultralight_poller_read_counter(Nfc* nfc, uint8_t counter_num, MfUltralightCounter* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_tearing_flag(
 | 
					 | 
				
			||||||
    Nfc* nfc,
 | 
					 | 
				
			||||||
    uint8_t flag_num,
 | 
					 | 
				
			||||||
    MfUltralightTearingFlag* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MfUltralightError mf_ultralight_poller_read_card(Nfc* nfc, MfUltralightData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@ -61,9 +61,9 @@
 | 
				
			|||||||
 *             |                                 |
 | 
					 *             |                                 |
 | 
				
			||||||
 *             +- protocol_name_listener_defs.h  |
 | 
					 *             +- protocol_name_listener_defs.h  |
 | 
				
			||||||
 *             |
 | 
					 *             |
 | 
				
			||||||
 *             +- protocol_name_sync_api.h       |
 | 
					 *             +- protocol_name_sync.h           |
 | 
				
			||||||
 *             |                                 |- add for synchronous API support
 | 
					 *             |                                 |- add for synchronous API support
 | 
				
			||||||
 *             +- protocol_name_sync_api.c       |
 | 
					 *             +- protocol_name_sync.c           |
 | 
				
			||||||
 *             |
 | 
					 *             |
 | 
				
			||||||
 * ```
 | 
					 * ```
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -83,8 +83,8 @@
 | 
				
			|||||||
 * | protocol_name_listener.h      | Protocol-specific listener and associated functions declarations. Optional, needed for emulation support. |
 | 
					 * | protocol_name_listener.h      | Protocol-specific listener and associated functions declarations. Optional, needed for emulation support. |
 | 
				
			||||||
 * | protocol_name_listener.c      | Implementation of functions declared in `protocol_name_listener.h`. Optional, needed for emulation support. |
 | 
					 * | protocol_name_listener.c      | Implementation of functions declared in `protocol_name_listener.h`. Optional, needed for emulation support. |
 | 
				
			||||||
 * | protocol_name_listener_defs.h | Declarations for use by the NfcListener library. See nfc_listener_base.h for more info. Optional, needed for emulation support. |
 | 
					 * | protocol_name_listener_defs.h | Declarations for use by the NfcListener library. See nfc_listener_base.h for more info. Optional, needed for emulation support. |
 | 
				
			||||||
 * | protocol_name_sync_api.h      | Synchronous API declarations. (See below for sync API explanation). Optional.|
 | 
					 * | protocol_name_sync.h          | Synchronous API declarations. (See below for sync API explanation). Optional.|
 | 
				
			||||||
 * | protocol_name_sync_api.c      | Synchronous API implementation. Optional. |
 | 
					 * | protocol_name_sync.c          | Synchronous API implementation. Optional. |
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * ## 3 Implement the code
 | 
					 * ## 3 Implement the code
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -145,7 +145,7 @@
 | 
				
			|||||||
 *    `protocol_name_poller_defs` structure under the appropriate index.
 | 
					 *    `protocol_name_poller_defs` structure under the appropriate index.
 | 
				
			||||||
 * 5. (Optional) If emulation support was implemented, do the step 4, but for the listener.
 | 
					 * 5. (Optional) If emulation support was implemented, do the step 4, but for the listener.
 | 
				
			||||||
 * 6. Add `protocol_name.h`, `protocol_name_poller.h`, and optionally, `protocol_name_listener.h`
 | 
					 * 6. Add `protocol_name.h`, `protocol_name_poller.h`, and optionally, `protocol_name_listener.h`
 | 
				
			||||||
 *    and `protocol_name_sync_api.h` into the `SDK_HEADERS` list in the SConscript file.
 | 
					 *    and `protocol_name_sync.h` into the `SDK_HEADERS` list in the SConscript file.
 | 
				
			||||||
 *    This will export the protocol's types and functions for use by the applications.
 | 
					 *    This will export the protocol's types and functions for use by the applications.
 | 
				
			||||||
 * 7. Done!
 | 
					 * 7. Done!
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -50,8 +50,7 @@ static NfcCommand slix_poller_handler_idle(SlixPoller* instance) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand slix_poller_handler_get_nfc_system_info(SlixPoller* instance) {
 | 
					static NfcCommand slix_poller_handler_get_nfc_system_info(SlixPoller* instance) {
 | 
				
			||||||
    instance->error =
 | 
					    instance->error = slix_poller_get_nxp_system_info(instance, &instance->data->system_info);
 | 
				
			||||||
        slix_poller_async_get_nxp_system_info(instance, &instance->data->system_info);
 | 
					 | 
				
			||||||
    if(instance->error == SlixErrorNone) {
 | 
					    if(instance->error == SlixErrorNone) {
 | 
				
			||||||
        instance->poller_state = SlixPollerStateReadSignature;
 | 
					        instance->poller_state = SlixPollerStateReadSignature;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -62,7 +61,7 @@ static NfcCommand slix_poller_handler_get_nfc_system_info(SlixPoller* instance)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static NfcCommand slix_poller_handler_read_signature(SlixPoller* instance) {
 | 
					static NfcCommand slix_poller_handler_read_signature(SlixPoller* instance) {
 | 
				
			||||||
    instance->error = slix_poller_async_read_signature(instance, &instance->data->signature);
 | 
					    instance->error = slix_poller_read_signature(instance, &instance->data->signature);
 | 
				
			||||||
    if(instance->error == SlixErrorNone) {
 | 
					    if(instance->error == SlixErrorNone) {
 | 
				
			||||||
        instance->poller_state = SlixPollerStateReady;
 | 
					        instance->poller_state = SlixPollerStateReady;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -141,7 +140,7 @@ static bool slix_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    if(iso15693_3_event->type == Iso15693_3PollerEventTypeReady) {
 | 
					    if(iso15693_3_event->type == Iso15693_3PollerEventTypeReady) {
 | 
				
			||||||
        if(slix_get_type(instance->data) < SlixTypeCount) {
 | 
					        if(slix_get_type(instance->data) < SlixTypeCount) {
 | 
				
			||||||
            SlixSystemInfo system_info = {};
 | 
					            SlixSystemInfo system_info = {};
 | 
				
			||||||
            SlixError error = slix_poller_async_get_nxp_system_info(instance, &system_info);
 | 
					            SlixError error = slix_poller_get_nxp_system_info(instance, &system_info);
 | 
				
			||||||
            protocol_detected = (error == SlixErrorNone);
 | 
					            protocol_detected = (error == SlixErrorNone);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,78 @@
 | 
				
			|||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief SlixPoller opaque type definition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct SlixPoller SlixPoller;
 | 
					typedef struct SlixPoller SlixPoller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enumeration of possible Slix poller event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    SlixPollerEventTypeError,
 | 
					    SlixPollerEventTypeError, /**< An error occured while reading card. */
 | 
				
			||||||
    SlixPollerEventTypeReady,
 | 
					    SlixPollerEventTypeReady, /**< The card was successfully read by the poller. */
 | 
				
			||||||
} SlixPollerEventType;
 | 
					} SlixPollerEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					/**
 | 
				
			||||||
    SlixError error;
 | 
					 * @brief Slixs poller event data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
					    SlixError error; /**< Error code indicating card reaing fail reason. */
 | 
				
			||||||
} SlixPollerEventData;
 | 
					} SlixPollerEventData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Slix poller event structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Upon emission of an event, an instance of this struct will be passed to the callback.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    SlixPollerEventType type;
 | 
					    SlixPollerEventType type; /**< Type of emmitted event. */
 | 
				
			||||||
    SlixPollerEventData* data;
 | 
					    SlixPollerEventData* data; /**< Pointer to event specific data. */
 | 
				
			||||||
} SlixPollerEvent;
 | 
					} SlixPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transmit and receive Slix frames in poller mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The rx_buffer will be filled with any data received as a response to data
 | 
				
			||||||
 | 
					 * sent from tx_buffer, with a timeout defined by the fwt parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
 | 
				
			||||||
 | 
					 * @param[out] rx_buffer pointer to the buffer to be filled with received data.
 | 
				
			||||||
 | 
					 * @param[in] fwt frame wait time (response timeout), in carrier cycles.
 | 
				
			||||||
 | 
					 * @return SlixErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SlixError slix_poller_send_frame(
 | 
				
			||||||
 | 
					    SlixPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_data,
 | 
				
			||||||
 | 
					    BitBuffer* rx_data,
 | 
				
			||||||
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Send get nxp system info command and parse response.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SlixSystemInfo structure to be filled.
 | 
				
			||||||
 | 
					 * @return SlixErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SlixError slix_poller_get_nxp_system_info(SlixPoller* instance, SlixSystemInfo* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read signature from card.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must ONLY be used inside the callback function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in, out] instance pointer to the instance to be used in the transaction.
 | 
				
			||||||
 | 
					 * @param[out] data pointer to the SlixSignature structure to be filled.
 | 
				
			||||||
 | 
					 * @return SlixErrorNone on success, an error code on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SlixError slix_poller_read_signature(SlixPoller* instance, SlixSignature* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ SlixError slix_poller_send_frame(
 | 
				
			|||||||
    return slix_process_iso15693_3_error(iso15693_3_error);
 | 
					    return slix_process_iso15693_3_error(iso15693_3_error);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SlixError slix_poller_async_get_nxp_system_info(SlixPoller* instance, SlixSystemInfo* data) {
 | 
					SlixError slix_poller_get_nxp_system_info(SlixPoller* instance, SlixSystemInfo* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,7 +50,7 @@ SlixError slix_poller_async_get_nxp_system_info(SlixPoller* instance, SlixSystem
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SlixError slix_poller_async_read_signature(SlixPoller* instance, SlixSignature* data) {
 | 
					SlixError slix_poller_read_signature(SlixPoller* instance, SlixSignature* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(data);
 | 
					    furi_assert(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -33,16 +33,6 @@ struct SlixPoller {
 | 
				
			|||||||
    void* context;
 | 
					    void* context;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SlixError slix_poller_send_frame(
 | 
					 | 
				
			||||||
    SlixPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_data,
 | 
					 | 
				
			||||||
    BitBuffer* rx_data,
 | 
					 | 
				
			||||||
    uint32_t fwt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SlixError slix_poller_async_get_nxp_system_info(SlixPoller* instance, SlixSystemInfo* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SlixError slix_poller_async_read_signature(SlixPoller* instance, SlixSignature* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -71,7 +71,7 @@ static NfcCommand st25tb_poller_run(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        if(instance->state != St25tbPollerStateActivated) {
 | 
					        if(instance->state != St25tbPollerStateActivated) {
 | 
				
			||||||
            St25tbError error = st25tb_poller_async_activate(instance, instance->data);
 | 
					            St25tbError error = st25tb_poller_activate(instance, instance->data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(error == St25tbErrorNone) {
 | 
					            if(error == St25tbErrorNone) {
 | 
				
			||||||
                instance->st25tb_event.type = St25tbPollerEventTypeReady;
 | 
					                instance->st25tb_event.type = St25tbPollerEventTypeReady;
 | 
				
			||||||
@ -106,7 +106,7 @@ static bool st25tb_poller_detect(NfcGenericEvent event, void* context) {
 | 
				
			|||||||
    furi_assert(instance->state == St25tbPollerStateIdle);
 | 
					    furi_assert(instance->state == St25tbPollerStateIdle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
					    if(nfc_event->type == NfcEventTypePollerReady) {
 | 
				
			||||||
        St25tbError error = st25tb_poller_async_initiate(instance, NULL);
 | 
					        St25tbError error = st25tb_poller_initiate(instance, NULL);
 | 
				
			||||||
        protocol_detected = (error == St25tbErrorNone);
 | 
					        protocol_detected = (error == St25tbErrorNone);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,23 @@ typedef struct {
 | 
				
			|||||||
    St25tbPollerEventData* data;
 | 
					    St25tbPollerEventData* data;
 | 
				
			||||||
} St25tbPollerEvent;
 | 
					} St25tbPollerEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError st25tb_poller_send_frame(
 | 
				
			||||||
 | 
					    St25tbPoller* instance,
 | 
				
			||||||
 | 
					    const BitBuffer* tx_buffer,
 | 
				
			||||||
 | 
					    BitBuffer* rx_buffer,
 | 
				
			||||||
 | 
					    uint32_t fwt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError st25tb_poller_initiate(St25tbPoller* instance, uint8_t* chip_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError st25tb_poller_activate(St25tbPoller* instance, St25tbData* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError st25tb_poller_get_uid(St25tbPoller* instance, uint8_t* uid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError
 | 
				
			||||||
 | 
					    st25tb_poller_read_block(St25tbPoller* instance, uint32_t* block, uint8_t block_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					St25tbError st25tb_poller_halt(St25tbPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ static St25tbError st25tb_poller_prepare_trx(St25tbPoller* instance) {
 | 
				
			|||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(instance->state == St25tbPollerStateIdle) {
 | 
					    if(instance->state == St25tbPollerStateIdle) {
 | 
				
			||||||
        return st25tb_poller_async_activate(instance, NULL);
 | 
					        return st25tb_poller_activate(instance, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return St25tbErrorNone;
 | 
					    return St25tbErrorNone;
 | 
				
			||||||
@ -85,7 +85,7 @@ St25tbType st25tb_get_type_from_uid(const uint8_t uid[ST25TB_UID_SIZE]) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
St25tbError st25tb_poller_async_initiate(St25tbPoller* instance, uint8_t* chip_id) {
 | 
					St25tbError st25tb_poller_initiate(St25tbPoller* instance, uint8_t* chip_id) {
 | 
				
			||||||
    // Send Initiate()
 | 
					    // Send Initiate()
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
@ -117,7 +117,7 @@ St25tbError st25tb_poller_async_initiate(St25tbPoller* instance, uint8_t* chip_i
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* data) {
 | 
					St25tbError st25tb_poller_activate(St25tbPoller* instance, St25tbData* data) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -126,7 +126,7 @@ St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* dat
 | 
				
			|||||||
    St25tbError ret;
 | 
					    St25tbError ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        ret = st25tb_poller_async_initiate(instance, &data->chip_id);
 | 
					        ret = st25tb_poller_initiate(instance, &data->chip_id);
 | 
				
			||||||
        if(ret != St25tbErrorNone) {
 | 
					        if(ret != St25tbErrorNone) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -162,7 +162,7 @@ St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* dat
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        instance->state = St25tbPollerStateActivated;
 | 
					        instance->state = St25tbPollerStateActivated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = st25tb_poller_async_get_uid(instance, data->uid);
 | 
					        ret = st25tb_poller_get_uid(instance, data->uid);
 | 
				
			||||||
        if(ret != St25tbErrorNone) {
 | 
					        if(ret != St25tbErrorNone) {
 | 
				
			||||||
            instance->state = St25tbPollerStateActivationFailed;
 | 
					            instance->state = St25tbPollerStateActivationFailed;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -171,7 +171,7 @@ St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* dat
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        bool read_blocks = true;
 | 
					        bool read_blocks = true;
 | 
				
			||||||
        for(uint8_t i = 0; i < st25tb_get_block_count(data->type); i++) {
 | 
					        for(uint8_t i = 0; i < st25tb_get_block_count(data->type); i++) {
 | 
				
			||||||
            ret = st25tb_poller_async_read_block(instance, &data->blocks[i], i);
 | 
					            ret = st25tb_poller_read_block(instance, &data->blocks[i], i);
 | 
				
			||||||
            if(ret != St25tbErrorNone) {
 | 
					            if(ret != St25tbErrorNone) {
 | 
				
			||||||
                read_blocks = false;
 | 
					                read_blocks = false;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -180,14 +180,13 @@ St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* dat
 | 
				
			|||||||
        if(!read_blocks) {
 | 
					        if(!read_blocks) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ret = st25tb_poller_async_read_block(
 | 
					        ret = st25tb_poller_read_block(instance, &data->system_otp_block, ST25TB_SYSTEM_OTP_BLOCK);
 | 
				
			||||||
            instance, &data->system_otp_block, ST25TB_SYSTEM_OTP_BLOCK);
 | 
					 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
St25tbError st25tb_poller_async_get_uid(St25tbPoller* instance, uint8_t uid[ST25TB_UID_SIZE]) {
 | 
					St25tbError st25tb_poller_get_uid(St25tbPoller* instance, uint8_t* uid) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -221,7 +220,7 @@ St25tbError st25tb_poller_async_get_uid(St25tbPoller* instance, uint8_t uid[ST25
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
St25tbError
 | 
					St25tbError
 | 
				
			||||||
    st25tb_poller_async_read_block(St25tbPoller* instance, uint32_t* block, uint8_t block_number) {
 | 
					    st25tb_poller_read_block(St25tbPoller* instance, uint32_t* block, uint8_t block_number) {
 | 
				
			||||||
    furi_assert(instance);
 | 
					    furi_assert(instance);
 | 
				
			||||||
    furi_assert(instance->nfc);
 | 
					    furi_assert(instance->nfc);
 | 
				
			||||||
    furi_assert(block);
 | 
					    furi_assert(block);
 | 
				
			||||||
 | 
				
			|||||||
@ -34,23 +34,6 @@ struct St25tbPoller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const St25tbData* st25tb_poller_get_data(St25tbPoller* instance);
 | 
					const St25tbData* st25tb_poller_get_data(St25tbPoller* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
St25tbError st25tb_poller_async_initiate(St25tbPoller* instance, uint8_t* chip_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
St25tbError st25tb_poller_async_activate(St25tbPoller* instance, St25tbData* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
St25tbError st25tb_poller_async_get_uid(St25tbPoller* instance, uint8_t uid[ST25TB_UID_SIZE]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
St25tbError
 | 
					 | 
				
			||||||
    st25tb_poller_async_read_block(St25tbPoller* instance, uint32_t* block, uint8_t block_number);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
St25tbError st25tb_poller_halt(St25tbPoller* instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
St25tbError st25tb_poller_send_frame(
 | 
					 | 
				
			||||||
    St25tbPoller* instance,
 | 
					 | 
				
			||||||
    const BitBuffer* tx_buffer,
 | 
					 | 
				
			||||||
    BitBuffer* rx_buffer,
 | 
					 | 
				
			||||||
    uint32_t fwt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
entry,status,name,type,params
 | 
					entry,status,name,type,params
 | 
				
			||||||
Version,+,44.0,,
 | 
					Version,+,45.0,,
 | 
				
			||||||
Header,+,applications/services/bt/bt_service/bt.h,,
 | 
					Header,+,applications/services/bt/bt_service/bt.h,,
 | 
				
			||||||
Header,+,applications/services/cli/cli.h,,
 | 
					Header,+,applications/services/cli/cli.h,,
 | 
				
			||||||
Header,+,applications/services/cli/cli_vcp.h,,
 | 
					Header,+,applications/services/cli/cli_vcp.h,,
 | 
				
			||||||
@ -39,6 +39,8 @@ Header,+,applications/services/storage/storage.h,,
 | 
				
			|||||||
Header,+,lib/digital_signal/digital_sequence.h,,
 | 
					Header,+,lib/digital_signal/digital_sequence.h,,
 | 
				
			||||||
Header,+,lib/digital_signal/digital_signal.h,,
 | 
					Header,+,lib/digital_signal/digital_signal.h,,
 | 
				
			||||||
Header,+,lib/drivers/cc1101_regs.h,,
 | 
					Header,+,lib/drivers/cc1101_regs.h,,
 | 
				
			||||||
 | 
					Header,+,lib/drivers/st25r3916.h,,
 | 
				
			||||||
 | 
					Header,+,lib/drivers/st25r3916_reg.h,,
 | 
				
			||||||
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
 | 
					Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
 | 
				
			||||||
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
 | 
					Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
 | 
				
			||||||
Header,+,lib/flipper_application/flipper_application.h,,
 | 
					Header,+,lib/flipper_application/flipper_application.h,,
 | 
				
			||||||
@ -2045,6 +2047,29 @@ Function,+,srand,void,unsigned
 | 
				
			|||||||
Function,-,srand48,void,long
 | 
					Function,-,srand48,void,long
 | 
				
			||||||
Function,-,srandom,void,unsigned
 | 
					Function,-,srandom,void,unsigned
 | 
				
			||||||
Function,+,sscanf,int,"const char*, const char*, ..."
 | 
					Function,+,sscanf,int,"const char*, const char*, ..."
 | 
				
			||||||
 | 
					Function,+,st25r3916_change_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_change_test_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_check_reg,_Bool,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_clear_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_direct_cmd,void,"FuriHalSpiBusHandle*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_get_irq,uint32_t,FuriHalSpiBusHandle*
 | 
				
			||||||
 | 
					Function,+,st25r3916_mask_irq,void,"FuriHalSpiBusHandle*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_modify_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_burst_regs,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_fifo,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, size_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_pta_mem,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_test_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_reg_read_fifo,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_reg_write_fifo,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_set_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_burst_regs,void,"FuriHalSpiBusHandle*, uint8_t, const uint8_t*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_fifo,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_pta_mem,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_ptf_mem,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_pttsn_mem,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_test_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*"
 | 
					Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*"
 | 
				
			||||||
Function,+,storage_common_exists,_Bool,"Storage*, const char*"
 | 
					Function,+,storage_common_exists,_Bool,"Storage*, const char*"
 | 
				
			||||||
Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*"
 | 
					Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*"
 | 
				
			||||||
 | 
				
			|||||||
		
		
			
  | 
@ -1,5 +1,5 @@
 | 
				
			|||||||
entry,status,name,type,params
 | 
					entry,status,name,type,params
 | 
				
			||||||
Version,+,44.0,,
 | 
					Version,+,45.0,,
 | 
				
			||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
 | 
					Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
 | 
				
			||||||
Header,+,applications/services/bt/bt_service/bt.h,,
 | 
					Header,+,applications/services/bt/bt_service/bt.h,,
 | 
				
			||||||
Header,+,applications/services/cli/cli.h,,
 | 
					Header,+,applications/services/cli/cli.h,,
 | 
				
			||||||
@ -40,6 +40,8 @@ Header,+,applications/services/storage/storage.h,,
 | 
				
			|||||||
Header,+,lib/digital_signal/digital_sequence.h,,
 | 
					Header,+,lib/digital_signal/digital_sequence.h,,
 | 
				
			||||||
Header,+,lib/digital_signal/digital_signal.h,,
 | 
					Header,+,lib/digital_signal/digital_signal.h,,
 | 
				
			||||||
Header,+,lib/drivers/cc1101_regs.h,,
 | 
					Header,+,lib/drivers/cc1101_regs.h,,
 | 
				
			||||||
 | 
					Header,+,lib/drivers/st25r3916.h,,
 | 
				
			||||||
 | 
					Header,+,lib/drivers/st25r3916_reg.h,,
 | 
				
			||||||
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
 | 
					Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
 | 
				
			||||||
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
 | 
					Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
 | 
				
			||||||
Header,+,lib/flipper_application/flipper_application.h,,
 | 
					Header,+,lib/flipper_application/flipper_application.h,,
 | 
				
			||||||
@ -117,7 +119,7 @@ Header,+,lib/nfc/nfc_scanner.h,,
 | 
				
			|||||||
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_sync_api.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_sync.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/iso14443_4a/iso14443_4a.h,,
 | 
					Header,+,lib/nfc/protocols/iso14443_4a/iso14443_4a.h,,
 | 
				
			||||||
@ -128,13 +130,13 @@ Header,+,lib/nfc/protocols/iso14443_4b/iso14443_4b_poller.h,,
 | 
				
			|||||||
Header,+,lib/nfc/protocols/mf_classic/mf_classic.h,,
 | 
					Header,+,lib/nfc/protocols/mf_classic/mf_classic.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_classic/mf_classic_listener.h,,
 | 
					Header,+,lib/nfc/protocols/mf_classic/mf_classic_listener.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller.h,,
 | 
					Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller_sync_api.h,,
 | 
					Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller_sync.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_desfire/mf_desfire.h,,
 | 
					Header,+,lib/nfc/protocols/mf_desfire/mf_desfire.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_desfire/mf_desfire_poller.h,,
 | 
					Header,+,lib/nfc/protocols/mf_desfire/mf_desfire_poller.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight.h,,
 | 
					Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h,,
 | 
					Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h,,
 | 
					Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync_api.h,,
 | 
					Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/slix/slix.h,,
 | 
					Header,+,lib/nfc/protocols/slix/slix.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/st25tb/st25tb.h,,
 | 
					Header,+,lib/nfc/protocols/st25tb/st25tb.h,,
 | 
				
			||||||
Header,+,lib/nfc/protocols/st25tb/st25tb_poller.h,,
 | 
					Header,+,lib/nfc/protocols/st25tb/st25tb_poller.h,,
 | 
				
			||||||
@ -1861,9 +1863,13 @@ Function,+,iso14443_3a_get_sak,uint8_t,const Iso14443_3aData*
 | 
				
			|||||||
Function,+,iso14443_3a_get_uid,const uint8_t*,"const Iso14443_3aData*, size_t*"
 | 
					Function,+,iso14443_3a_get_uid,const uint8_t*,"const Iso14443_3aData*, size_t*"
 | 
				
			||||||
Function,+,iso14443_3a_is_equal,_Bool,"const Iso14443_3aData*, const Iso14443_3aData*"
 | 
					Function,+,iso14443_3a_is_equal,_Bool,"const Iso14443_3aData*, const Iso14443_3aData*"
 | 
				
			||||||
Function,+,iso14443_3a_load,_Bool,"Iso14443_3aData*, FlipperFormat*, uint32_t"
 | 
					Function,+,iso14443_3a_load,_Bool,"Iso14443_3aData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
Function,+,iso14443_3a_poller_read,Iso14443_3aError,"Nfc*, Iso14443_3aData*"
 | 
					Function,+,iso14443_3a_poller_activate,Iso14443_3aError,"Iso14443_3aPoller*, Iso14443_3aData*"
 | 
				
			||||||
 | 
					Function,+,iso14443_3a_poller_check_presence,Iso14443_3aError,Iso14443_3aPoller*
 | 
				
			||||||
 | 
					Function,+,iso14443_3a_poller_halt,Iso14443_3aError,Iso14443_3aPoller*
 | 
				
			||||||
Function,+,iso14443_3a_poller_send_standard_frame,Iso14443_3aError,"Iso14443_3aPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
					Function,+,iso14443_3a_poller_send_standard_frame,Iso14443_3aError,"Iso14443_3aPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,iso14443_3a_poller_sync_read,Iso14443_3aError,"Nfc*, Iso14443_3aData*"
 | 
				
			||||||
Function,+,iso14443_3a_poller_txrx,Iso14443_3aError,"Iso14443_3aPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
					Function,+,iso14443_3a_poller_txrx,Iso14443_3aError,"Iso14443_3aPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,iso14443_3a_poller_txrx_custom_parity,Iso14443_3aError,"Iso14443_3aPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
				
			||||||
Function,+,iso14443_3a_reset,void,Iso14443_3aData*
 | 
					Function,+,iso14443_3a_reset,void,Iso14443_3aData*
 | 
				
			||||||
Function,+,iso14443_3a_save,_Bool,"const Iso14443_3aData*, FlipperFormat*"
 | 
					Function,+,iso14443_3a_save,_Bool,"const Iso14443_3aData*, FlipperFormat*"
 | 
				
			||||||
Function,+,iso14443_3a_set_atqa,void,"Iso14443_3aData*, const uint8_t[2]"
 | 
					Function,+,iso14443_3a_set_atqa,void,"Iso14443_3aData*, const uint8_t[2]"
 | 
				
			||||||
@ -1882,6 +1888,9 @@ Function,+,iso14443_3b_get_fwt_fc_max,uint32_t,const Iso14443_3bData*
 | 
				
			|||||||
Function,+,iso14443_3b_get_uid,const uint8_t*,"const Iso14443_3bData*, size_t*"
 | 
					Function,+,iso14443_3b_get_uid,const uint8_t*,"const Iso14443_3bData*, size_t*"
 | 
				
			||||||
Function,+,iso14443_3b_is_equal,_Bool,"const Iso14443_3bData*, const Iso14443_3bData*"
 | 
					Function,+,iso14443_3b_is_equal,_Bool,"const Iso14443_3bData*, const Iso14443_3bData*"
 | 
				
			||||||
Function,+,iso14443_3b_load,_Bool,"Iso14443_3bData*, FlipperFormat*, uint32_t"
 | 
					Function,+,iso14443_3b_load,_Bool,"Iso14443_3bData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,iso14443_3b_poller_activate,Iso14443_3bError,"Iso14443_3bPoller*, Iso14443_3bData*"
 | 
				
			||||||
 | 
					Function,+,iso14443_3b_poller_halt,Iso14443_3bError,Iso14443_3bPoller*
 | 
				
			||||||
 | 
					Function,+,iso14443_3b_poller_send_frame,Iso14443_3bError,"Iso14443_3bPoller*, const BitBuffer*, BitBuffer*"
 | 
				
			||||||
Function,+,iso14443_3b_reset,void,Iso14443_3bData*
 | 
					Function,+,iso14443_3b_reset,void,Iso14443_3bData*
 | 
				
			||||||
Function,+,iso14443_3b_save,_Bool,"const Iso14443_3bData*, FlipperFormat*"
 | 
					Function,+,iso14443_3b_save,_Bool,"const Iso14443_3bData*, FlipperFormat*"
 | 
				
			||||||
Function,+,iso14443_3b_set_uid,_Bool,"Iso14443_3bData*, const uint8_t*, size_t"
 | 
					Function,+,iso14443_3b_set_uid,_Bool,"Iso14443_3bData*, const uint8_t*, size_t"
 | 
				
			||||||
@ -1900,6 +1909,9 @@ Function,+,iso14443_4a_get_historical_bytes,const uint8_t*,"const Iso14443_4aDat
 | 
				
			|||||||
Function,+,iso14443_4a_get_uid,const uint8_t*,"const Iso14443_4aData*, size_t*"
 | 
					Function,+,iso14443_4a_get_uid,const uint8_t*,"const Iso14443_4aData*, size_t*"
 | 
				
			||||||
Function,+,iso14443_4a_is_equal,_Bool,"const Iso14443_4aData*, const Iso14443_4aData*"
 | 
					Function,+,iso14443_4a_is_equal,_Bool,"const Iso14443_4aData*, const Iso14443_4aData*"
 | 
				
			||||||
Function,+,iso14443_4a_load,_Bool,"Iso14443_4aData*, FlipperFormat*, uint32_t"
 | 
					Function,+,iso14443_4a_load,_Bool,"Iso14443_4aData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,iso14443_4a_poller_halt,Iso14443_4aError,Iso14443_4aPoller*
 | 
				
			||||||
 | 
					Function,+,iso14443_4a_poller_read_ats,Iso14443_4aError,"Iso14443_4aPoller*, Iso14443_4aAtsData*"
 | 
				
			||||||
 | 
					Function,+,iso14443_4a_poller_send_block,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*"
 | 
				
			||||||
Function,+,iso14443_4a_reset,void,Iso14443_4aData*
 | 
					Function,+,iso14443_4a_reset,void,Iso14443_4aData*
 | 
				
			||||||
Function,+,iso14443_4a_save,_Bool,"const Iso14443_4aData*, FlipperFormat*"
 | 
					Function,+,iso14443_4a_save,_Bool,"const Iso14443_4aData*, FlipperFormat*"
 | 
				
			||||||
Function,+,iso14443_4a_set_uid,_Bool,"Iso14443_4aData*, const uint8_t*, size_t"
 | 
					Function,+,iso14443_4a_set_uid,_Bool,"Iso14443_4aData*, const uint8_t*, size_t"
 | 
				
			||||||
@ -1914,6 +1926,8 @@ Function,+,iso14443_4b_get_device_name,const char*,"const Iso14443_4bData*, NfcD
 | 
				
			|||||||
Function,+,iso14443_4b_get_uid,const uint8_t*,"const Iso14443_4bData*, size_t*"
 | 
					Function,+,iso14443_4b_get_uid,const uint8_t*,"const Iso14443_4bData*, size_t*"
 | 
				
			||||||
Function,+,iso14443_4b_is_equal,_Bool,"const Iso14443_4bData*, const Iso14443_4bData*"
 | 
					Function,+,iso14443_4b_is_equal,_Bool,"const Iso14443_4bData*, const Iso14443_4bData*"
 | 
				
			||||||
Function,+,iso14443_4b_load,_Bool,"Iso14443_4bData*, FlipperFormat*, uint32_t"
 | 
					Function,+,iso14443_4b_load,_Bool,"Iso14443_4bData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,iso14443_4b_poller_halt,Iso14443_4bError,Iso14443_4bPoller*
 | 
				
			||||||
 | 
					Function,+,iso14443_4b_poller_send_block,Iso14443_4bError,"Iso14443_4bPoller*, const BitBuffer*, BitBuffer*"
 | 
				
			||||||
Function,+,iso14443_4b_reset,void,Iso14443_4bData*
 | 
					Function,+,iso14443_4b_reset,void,Iso14443_4bData*
 | 
				
			||||||
Function,+,iso14443_4b_save,_Bool,"const Iso14443_4bData*, FlipperFormat*"
 | 
					Function,+,iso14443_4b_save,_Bool,"const Iso14443_4bData*, FlipperFormat*"
 | 
				
			||||||
Function,+,iso14443_4b_set_uid,_Bool,"Iso14443_4bData*, const uint8_t*, size_t"
 | 
					Function,+,iso14443_4b_set_uid,_Bool,"Iso14443_4bData*, const uint8_t*, size_t"
 | 
				
			||||||
@ -2141,14 +2155,21 @@ Function,+,mf_classic_is_sector_read,_Bool,"const MfClassicData*, uint8_t"
 | 
				
			|||||||
Function,+,mf_classic_is_sector_trailer,_Bool,uint8_t
 | 
					Function,+,mf_classic_is_sector_trailer,_Bool,uint8_t
 | 
				
			||||||
Function,+,mf_classic_is_value_block,_Bool,"MfClassicSectorTrailer*, uint8_t"
 | 
					Function,+,mf_classic_is_value_block,_Bool,"MfClassicSectorTrailer*, uint8_t"
 | 
				
			||||||
Function,+,mf_classic_load,_Bool,"MfClassicData*, FlipperFormat*, uint32_t"
 | 
					Function,+,mf_classic_load,_Bool,"MfClassicData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
Function,+,mf_classic_poller_auth,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*"
 | 
					Function,+,mf_classic_poller_auth,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*"
 | 
				
			||||||
Function,+,mf_classic_poller_change_value,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, int32_t, int32_t*"
 | 
					Function,+,mf_classic_poller_get_nt,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKeyType, MfClassicNt*"
 | 
				
			||||||
Function,+,mf_classic_poller_collect_nt,MfClassicError,"Nfc*, uint8_t, MfClassicKeyType, MfClassicNt*"
 | 
					Function,+,mf_classic_poller_halt,MfClassicError,MfClassicPoller*
 | 
				
			||||||
Function,+,mf_classic_poller_detect_type,MfClassicError,"Nfc*, MfClassicType*"
 | 
					Function,+,mf_classic_poller_read_block,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicBlock*"
 | 
				
			||||||
Function,+,mf_classic_poller_read,MfClassicError,"Nfc*, const MfClassicDeviceKeys*, MfClassicData*"
 | 
					Function,+,mf_classic_poller_sync_auth,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*"
 | 
				
			||||||
Function,+,mf_classic_poller_read_block,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicBlock*"
 | 
					Function,+,mf_classic_poller_sync_change_value,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, int32_t, int32_t*"
 | 
				
			||||||
Function,+,mf_classic_poller_read_value,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, int32_t*"
 | 
					Function,+,mf_classic_poller_sync_collect_nt,MfClassicError,"Nfc*, uint8_t, MfClassicKeyType, MfClassicNt*"
 | 
				
			||||||
Function,+,mf_classic_poller_write_block,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicBlock*"
 | 
					Function,+,mf_classic_poller_sync_detect_type,MfClassicError,"Nfc*, MfClassicType*"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_sync_read,MfClassicError,"Nfc*, const MfClassicDeviceKeys*, MfClassicData*"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_sync_read_block,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicBlock*"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_sync_read_value,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, int32_t*"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_sync_write_block,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicBlock*"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_value_cmd,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicValueCommand, int32_t"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_value_transfer,MfClassicError,"MfClassicPoller*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,mf_classic_poller_write_block,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicBlock*"
 | 
				
			||||||
Function,+,mf_classic_reset,void,MfClassicData*
 | 
					Function,+,mf_classic_reset,void,MfClassicData*
 | 
				
			||||||
Function,+,mf_classic_save,_Bool,"const MfClassicData*, FlipperFormat*"
 | 
					Function,+,mf_classic_save,_Bool,"const MfClassicData*, FlipperFormat*"
 | 
				
			||||||
Function,+,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlock*"
 | 
					Function,+,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlock*"
 | 
				
			||||||
@ -2168,8 +2189,24 @@ Function,+,mf_desfire_get_file_settings,const MfDesfireFileSettings*,"const MfDe
 | 
				
			|||||||
Function,+,mf_desfire_get_uid,const uint8_t*,"const MfDesfireData*, size_t*"
 | 
					Function,+,mf_desfire_get_uid,const uint8_t*,"const MfDesfireData*, size_t*"
 | 
				
			||||||
Function,+,mf_desfire_is_equal,_Bool,"const MfDesfireData*, const MfDesfireData*"
 | 
					Function,+,mf_desfire_is_equal,_Bool,"const MfDesfireData*, const MfDesfireData*"
 | 
				
			||||||
Function,+,mf_desfire_load,_Bool,"MfDesfireData*, FlipperFormat*, uint32_t"
 | 
					Function,+,mf_desfire_load,_Bool,"MfDesfireData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_application,MfDesfireError,"MfDesfirePoller*, MfDesfireApplication*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_application_ids,MfDesfireError,"MfDesfirePoller*, SimpleArray*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_applications,MfDesfireError,"MfDesfirePoller*, const SimpleArray*, SimpleArray*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_data,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, uint32_t, size_t, MfDesfireFileData*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_data_multi,MfDesfireError,"MfDesfirePoller*, const SimpleArray*, const SimpleArray*, SimpleArray*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_ids,MfDesfireError,"MfDesfirePoller*, SimpleArray*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_records,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, uint32_t, size_t, MfDesfireFileData*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_settings,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, MfDesfireFileSettings*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_settings_multi,MfDesfireError,"MfDesfirePoller*, const SimpleArray*, SimpleArray*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_file_value,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, MfDesfireFileData*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_free_memory,MfDesfireError,"MfDesfirePoller*, MfDesfireFreeMemory*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_key_settings,MfDesfireError,"MfDesfirePoller*, MfDesfireKeySettings*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_key_versions,MfDesfireError,"MfDesfirePoller*, SimpleArray*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_read_version,MfDesfireError,"MfDesfirePoller*, MfDesfireVersion*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_poller_select_application,MfDesfireError,"MfDesfirePoller*, const MfDesfireApplicationId*"
 | 
				
			||||||
Function,+,mf_desfire_reset,void,MfDesfireData*
 | 
					Function,+,mf_desfire_reset,void,MfDesfireData*
 | 
				
			||||||
Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*"
 | 
					Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*"
 | 
				
			||||||
 | 
					Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*"
 | 
				
			||||||
Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t"
 | 
					Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t"
 | 
				
			||||||
Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*"
 | 
					Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*"
 | 
				
			||||||
Function,+,mf_ultralight_alloc,MfUltralightData*,
 | 
					Function,+,mf_ultralight_alloc,MfUltralightData*,
 | 
				
			||||||
@ -2190,13 +2227,22 @@ Function,+,mf_ultralight_is_counter_configured,_Bool,const MfUltralightData*
 | 
				
			|||||||
Function,+,mf_ultralight_is_equal,_Bool,"const MfUltralightData*, const MfUltralightData*"
 | 
					Function,+,mf_ultralight_is_equal,_Bool,"const MfUltralightData*, const MfUltralightData*"
 | 
				
			||||||
Function,+,mf_ultralight_is_page_pwd_or_pack,_Bool,"MfUltralightType, uint16_t"
 | 
					Function,+,mf_ultralight_is_page_pwd_or_pack,_Bool,"MfUltralightType, uint16_t"
 | 
				
			||||||
Function,+,mf_ultralight_load,_Bool,"MfUltralightData*, FlipperFormat*, uint32_t"
 | 
					Function,+,mf_ultralight_load,_Bool,"MfUltralightData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_card,MfUltralightError,"Nfc*, MfUltralightData*"
 | 
					Function,+,mf_ultralight_poller_auth_pwd,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*"
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_counter,MfUltralightError,"Nfc*, uint8_t, MfUltralightCounter*"
 | 
					Function,+,mf_ultralight_poller_authenticate,MfUltralightError,MfUltralightPoller*
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_page,MfUltralightError,"Nfc*, uint16_t, MfUltralightPage*"
 | 
					Function,+,mf_ultralight_poller_read_counter,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightCounter*"
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_signature,MfUltralightError,"Nfc*, MfUltralightSignature*"
 | 
					Function,+,mf_ultralight_poller_read_page,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightPageReadCommandData*"
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_tearing_flag,MfUltralightError,"Nfc*, uint8_t, MfUltralightTearingFlag*"
 | 
					Function,+,mf_ultralight_poller_read_page_from_sector,MfUltralightError,"MfUltralightPoller*, uint8_t, uint8_t, MfUltralightPageReadCommandData*"
 | 
				
			||||||
Function,+,mf_ultralight_poller_read_version,MfUltralightError,"Nfc*, MfUltralightVersion*"
 | 
					Function,+,mf_ultralight_poller_read_signature,MfUltralightError,"MfUltralightPoller*, MfUltralightSignature*"
 | 
				
			||||||
Function,+,mf_ultralight_poller_write_page,MfUltralightError,"Nfc*, uint16_t, MfUltralightPage*"
 | 
					Function,+,mf_ultralight_poller_read_tearing_flag,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightTearingFlag*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_read_version,MfUltralightError,"MfUltralightPoller*, MfUltralightVersion*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_card,MfUltralightError,"Nfc*, MfUltralightData*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_counter,MfUltralightError,"Nfc*, uint8_t, MfUltralightCounter*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_page,MfUltralightError,"Nfc*, uint16_t, MfUltralightPage*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_signature,MfUltralightError,"Nfc*, MfUltralightSignature*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_tearing_flag,MfUltralightError,"Nfc*, uint8_t, MfUltralightTearingFlag*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_read_version,MfUltralightError,"Nfc*, MfUltralightVersion*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_sync_write_page,MfUltralightError,"Nfc*, uint16_t, MfUltralightPage*"
 | 
				
			||||||
 | 
					Function,+,mf_ultralight_poller_write_page,MfUltralightError,"MfUltralightPoller*, uint8_t, const MfUltralightPage*"
 | 
				
			||||||
Function,+,mf_ultralight_reset,void,MfUltralightData*
 | 
					Function,+,mf_ultralight_reset,void,MfUltralightData*
 | 
				
			||||||
Function,+,mf_ultralight_save,_Bool,"const MfUltralightData*, FlipperFormat*"
 | 
					Function,+,mf_ultralight_save,_Bool,"const MfUltralightData*, FlipperFormat*"
 | 
				
			||||||
Function,+,mf_ultralight_set_uid,_Bool,"MfUltralightData*, const uint8_t*, size_t"
 | 
					Function,+,mf_ultralight_set_uid,_Bool,"MfUltralightData*, const uint8_t*, size_t"
 | 
				
			||||||
@ -2290,6 +2336,7 @@ Function,+,nfc_poller_free,void,NfcPoller*
 | 
				
			|||||||
Function,+,nfc_poller_get_data,const NfcDeviceData*,const NfcPoller*
 | 
					Function,+,nfc_poller_get_data,const NfcDeviceData*,const NfcPoller*
 | 
				
			||||||
Function,+,nfc_poller_get_protocol,NfcProtocol,const NfcPoller*
 | 
					Function,+,nfc_poller_get_protocol,NfcProtocol,const NfcPoller*
 | 
				
			||||||
Function,+,nfc_poller_start,void,"NfcPoller*, NfcGenericCallback, void*"
 | 
					Function,+,nfc_poller_start,void,"NfcPoller*, NfcGenericCallback, void*"
 | 
				
			||||||
 | 
					Function,+,nfc_poller_start_ex,void,"NfcPoller*, NfcGenericCallbackEx, void*"
 | 
				
			||||||
Function,+,nfc_poller_stop,void,NfcPoller*
 | 
					Function,+,nfc_poller_stop,void,NfcPoller*
 | 
				
			||||||
Function,+,nfc_poller_trx,NfcError,"Nfc*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
					Function,+,nfc_poller_trx,NfcError,"Nfc*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
				
			||||||
Function,+,nfc_protocol_get_parent,NfcProtocol,NfcProtocol
 | 
					Function,+,nfc_protocol_get_parent,NfcProtocol,NfcProtocol
 | 
				
			||||||
@ -2608,6 +2655,29 @@ Function,+,srand,void,unsigned
 | 
				
			|||||||
Function,-,srand48,void,long
 | 
					Function,-,srand48,void,long
 | 
				
			||||||
Function,-,srandom,void,unsigned
 | 
					Function,-,srandom,void,unsigned
 | 
				
			||||||
Function,+,sscanf,int,"const char*, const char*, ..."
 | 
					Function,+,sscanf,int,"const char*, const char*, ..."
 | 
				
			||||||
 | 
					Function,+,st25r3916_change_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_change_test_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_check_reg,_Bool,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_clear_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_direct_cmd,void,"FuriHalSpiBusHandle*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_get_irq,uint32_t,FuriHalSpiBusHandle*
 | 
				
			||||||
 | 
					Function,+,st25r3916_mask_irq,void,"FuriHalSpiBusHandle*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_modify_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_burst_regs,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_fifo,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, size_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_pta_mem,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_read_test_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25r3916_reg_read_fifo,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_reg_write_fifo,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_set_reg_bits,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_burst_regs,void,"FuriHalSpiBusHandle*, uint8_t, const uint8_t*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_fifo,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_pta_mem,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_ptf_mem,void,"FuriHalSpiBusHandle*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_pttsn_mem,void,"FuriHalSpiBusHandle*, uint8_t*, size_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25r3916_write_test_reg,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t"
 | 
				
			||||||
Function,+,st25tb_alloc,St25tbData*,
 | 
					Function,+,st25tb_alloc,St25tbData*,
 | 
				
			||||||
Function,+,st25tb_copy,void,"St25tbData*, const St25tbData*"
 | 
					Function,+,st25tb_copy,void,"St25tbData*, const St25tbData*"
 | 
				
			||||||
Function,+,st25tb_free,void,St25tbData*
 | 
					Function,+,st25tb_free,void,St25tbData*
 | 
				
			||||||
@ -2617,6 +2687,12 @@ Function,+,st25tb_get_device_name,const char*,"const St25tbData*, NfcDeviceNameT
 | 
				
			|||||||
Function,+,st25tb_get_uid,const uint8_t*,"const St25tbData*, size_t*"
 | 
					Function,+,st25tb_get_uid,const uint8_t*,"const St25tbData*, size_t*"
 | 
				
			||||||
Function,+,st25tb_is_equal,_Bool,"const St25tbData*, const St25tbData*"
 | 
					Function,+,st25tb_is_equal,_Bool,"const St25tbData*, const St25tbData*"
 | 
				
			||||||
Function,+,st25tb_load,_Bool,"St25tbData*, FlipperFormat*, uint32_t"
 | 
					Function,+,st25tb_load,_Bool,"St25tbData*, FlipperFormat*, uint32_t"
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_activate,St25tbError,"St25tbPoller*, St25tbData*"
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_get_uid,St25tbError,"St25tbPoller*, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_halt,St25tbError,St25tbPoller*
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_initiate,St25tbError,"St25tbPoller*, uint8_t*"
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_read_block,St25tbError,"St25tbPoller*, uint32_t*, uint8_t"
 | 
				
			||||||
 | 
					Function,+,st25tb_poller_send_frame,St25tbError,"St25tbPoller*, const BitBuffer*, BitBuffer*, uint32_t"
 | 
				
			||||||
Function,+,st25tb_reset,void,St25tbData*
 | 
					Function,+,st25tb_reset,void,St25tbData*
 | 
				
			||||||
Function,+,st25tb_save,_Bool,"const St25tbData*, FlipperFormat*"
 | 
					Function,+,st25tb_save,_Bool,"const St25tbData*, FlipperFormat*"
 | 
				
			||||||
Function,+,st25tb_set_uid,_Bool,"St25tbData*, const uint8_t*, size_t"
 | 
					Function,+,st25tb_set_uid,_Bool,"St25tbData*, const uint8_t*, size_t"
 | 
				
			||||||
 | 
				
			|||||||
		
		
			
  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user