Selaa lähdekoodia

Merge pull request #45 from Next-Flip/feat/nfc-maker-types

NFC Maker: Support MIFARE Classic and SLIX, UI Improvements
WillyJL 9 kuukautta sitten
vanhempi
commit
d2552a2852

BIN
nfc_maker/.catalog/1.png


BIN
nfc_maker/.catalog/3.png


BIN
nfc_maker/.catalog/4.png


BIN
nfc_maker/.catalog/5.png


BIN
nfc_maker/.catalog/6.png


+ 13 - 0
nfc_maker/.catalog/CHANGELOG.md

@@ -1,3 +1,16 @@
+v2.0:
+- Added support for creating more types of tags:
+  - MIFARE Classic Mini 0.3K
+  - MIFARE Classic 1K
+  - MIFARE Classic 4K
+  - SLIX
+  - SLIX-S
+  - SLIX-L
+  - SLIX2
+- Added memory size information to Tag Type list
+- Save errors don't return to the main menu anymore
+- Added version number to title screen
+
 v1.3:
 - Allow setting custom UID
 - Show extra symbols for WiFi SSID/Password and Emails (by @956MB)

+ 15 - 6
nfc_maker/.catalog/README.md

@@ -12,9 +12,18 @@ Supported data types:
   - WiFi Login
 
 Supported tag types:
-  - NTAG203
-  - NTAG213
-  - NTAG215
-  - NTAG216
-  - NTAG I2C 1K
-  - NTAG I2C 2K
+- NTAG 203
+- NTAG 213
+- NTAG 215
+- NTAG 216
+- NTAG I2C 1K
+- NTAG I2C 2K
+- MIFARE Classic Mini 0.3K
+- MIFARE Classic 1K
+- MIFARE Classic 4K
+- SLIX
+- SLIX-S
+- SLIX-L
+- SLIX2
+
+Note that not all NDEF record types are supported on all devices. In particular, iPhones and other iOS devices lack support for many useful types such as Contact Vcards and WiFi Logins. You can find more information [here](https://gist.github.com/equipter/de2d9e421be9af1615e9b9cad4834ddc).

+ 2 - 2
nfc_maker/application.fam

@@ -3,12 +3,12 @@ App(
     name="NFC Maker",
     apptype=FlipperAppType.EXTERNAL,
     entry_point="nfc_maker",
-    stack_size=1 * 1024,
+    stack_size=2 * 1024,
     fap_icon="nfc_maker_10px.png",
     fap_category="NFC",
     fap_author="@Willy-JL",
     fap_weburl="https://github.com/Next-Flip/Momentum-Apps/tree/dev/nfc_maker",
-    fap_version="1.3",
+    fap_version="2.0",
     fap_description="Create NFC files for BT MACs, Contacts, Links, Emails, Phones, Text and WiFis",
     fap_icon_assets="icons",
     fap_libs=["assets"],

+ 5 - 6
nfc_maker/dropin/text_input.c

@@ -1,9 +1,6 @@
-#ifndef FW_ORIGIN_Momentum
 #include "text_input.h"
-#include <gui/elements.h>
-#if __has_include(<assets_icons.h>)
-#include <assets_icons.h>
-#else
+
+#ifndef FW_ORIGIN_Momentum
 extern const Icon I_KeySaveSelected_22x11;
 extern const Icon I_KeySave_22x11;
 extern const Icon I_KeyKeyboardSelected_10x11;
@@ -11,7 +8,8 @@ extern const Icon I_KeyKeyboard_10x11;
 extern const Icon I_KeyBackspaceSelected_17x11;
 extern const Icon I_KeyBackspace_17x11;
 extern const Icon I_WarningDolphin_45x42;
-#endif
+
+#include <gui/elements.h>
 #include <furi.h>
 
 struct TextInput {
@@ -805,4 +803,5 @@ void text_input_set_header_text(TextInput* text_input, const char* text) {
     furi_check(text_input);
     with_view_model(text_input->view, TextInputModel * model, { model->header = text; }, true);
 }
+
 #endif

+ 2 - 0
nfc_maker/dropin/text_input.h

@@ -6,6 +6,7 @@
 #pragma once
 
 #ifndef FW_ORIGIN_Momentum
+
 #include <gui/view.h>
 #include <gui/modules/validators.h>
 
@@ -99,4 +100,5 @@ void text_input_set_header_text(TextInput* text_input, const char* text);
 #ifdef __cplusplus
 }
 #endif
+
 #endif

+ 108 - 24
nfc_maker/nfc_maker.c

@@ -1,28 +1,112 @@
 #include "nfc_maker.h"
 
-const NfcDataGeneratorType ntag_generators[NtagMAX] = {
-    [Ntag203] = NfcDataGeneratorTypeNTAG203,
-    [Ntag213] = NfcDataGeneratorTypeNTAG213,
-    [Ntag215] = NfcDataGeneratorTypeNTAG215,
-    [Ntag216] = NfcDataGeneratorTypeNTAG216,
-    [NtagI2C1K] = NfcDataGeneratorTypeNTAGI2C1k,
-    [NtagI2C2K] = NfcDataGeneratorTypeNTAGI2C2k,
-};
-const char* ntag_names[NtagMAX] = {
-    [Ntag203] = "NTAG203",
-    [Ntag213] = "NTAG213",
-    [Ntag215] = "NTAG215",
-    [Ntag216] = "NTAG216",
-    [NtagI2C1K] = "NTAG I2C 1K",
-    [NtagI2C2K] = "NTAG I2C 2K",
-};
-const size_t ntag_sizes[NtagMAX] = {
-    [Ntag203] = 0x12 * NTAG_DATA_AREA_UNIT_SIZE,
-    [Ntag213] = 0x12 * NTAG_DATA_AREA_UNIT_SIZE,
-    [Ntag215] = 0x3E * NTAG_DATA_AREA_UNIT_SIZE,
-    [Ntag216] = 0x6D * NTAG_DATA_AREA_UNIT_SIZE,
-    [NtagI2C1K] = 0x6D * NTAG_DATA_AREA_UNIT_SIZE,
-    [NtagI2C2K] = 0xEA * NTAG_DATA_AREA_UNIT_SIZE,
+const CardDef cards[CardMAX] = {
+    // MfUltralight
+    [CardNtag203] =
+        {
+            .name = "NTAG 203 (144B)",
+            .size = 0x12 * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAG203,
+        },
+    [CardNtag213] =
+        {
+            .name = "NTAG 213 (144B)",
+            .size = 0x12 * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAG213,
+        },
+    [CardNtag215] =
+        {
+            .name = "NTAG 215 (496B)",
+            .size = 0x3E * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAG215,
+        },
+    [CardNtag216] =
+        {
+            .name = "NTAG 216 (872B)",
+            .size = 0x6D * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAG216,
+        },
+    [CardNtagI2C1K] =
+        {
+            .name = "NTAG I2C 1K (872B)",
+            .size = 0x6D * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAGI2C1k,
+        },
+    [CardNtagI2C2K] =
+        {
+            .name = "NTAG I2C 2K (1872B)",
+            .size = 0xEA * NTAG_DATA_AREA_UNIT_SIZE,
+            .protocol = NfcProtocolMfUltralight,
+            .generator = NfcDataGeneratorTypeNTAGI2C2k,
+        },
+
+    // MfClassic (size excludes sector trailers and MAD1/2 sectors)
+    [CardMfClassicMini] =
+        {
+            .name = "MIFARE Classic Mini 0.3K",
+            .size = (5 - 1) * (4 - 1) * MF_CLASSIC_BLOCK_SIZE,
+            .protocol = NfcProtocolMfClassic,
+            .generator = NfcDataGeneratorTypeMfClassicMini,
+        },
+    [CardMfClassic1K4b] =
+        {
+            .name = "MIFARE Classic 1K UID4",
+            .size = (16 - 1) * (4 - 1) * MF_CLASSIC_BLOCK_SIZE,
+            .protocol = NfcProtocolMfClassic,
+            .generator = NfcDataGeneratorTypeMfClassic1k_4b,
+        },
+    [CardMfClassic1K7b] =
+        {
+            .name = "MIFARE Classic 1K UID7",
+            .size = (16 - 1) * (4 - 1) * MF_CLASSIC_BLOCK_SIZE,
+            .protocol = NfcProtocolMfClassic,
+            .generator = NfcDataGeneratorTypeMfClassic1k_7b,
+        },
+    [CardMfClassic4K4b] =
+        {
+            .name = "MIFARE Classic 4K UID4",
+            .size = (((32 - 2) * (4 - 1)) + ((8) * (16 - 1))) * MF_CLASSIC_BLOCK_SIZE,
+            .protocol = NfcProtocolMfClassic,
+            .generator = NfcDataGeneratorTypeMfClassic4k_4b,
+        },
+    [CardMfClassic4K7b] =
+        {
+            .name = "MIFARE Classic 4K UID7",
+            .size = (((32 - 2) * (4 - 1)) + ((8) * (16 - 1))) * MF_CLASSIC_BLOCK_SIZE,
+            .protocol = NfcProtocolMfClassic,
+            .generator = NfcDataGeneratorTypeMfClassic4k_7b,
+        },
+
+    // Slix (size excludes first block which is Capability Container)
+    [CardSlix] =
+        {
+            .name = "SLIX (108B)",
+            .size = (28 - 1) * SLIX_BLOCK_SIZE,
+            .protocol = NfcProtocolSlix,
+        },
+    [CardSlixS] =
+        {
+            .name = "SLIX-S (156B)",
+            .size = (40 - 1) * SLIX_BLOCK_SIZE,
+            .protocol = NfcProtocolSlix,
+        },
+    [CardSlixL] =
+        {
+            .name = "SLIX-L (28B)",
+            .size = (8 - 1) * SLIX_BLOCK_SIZE,
+            .protocol = NfcProtocolSlix,
+        },
+    [CardSlix2] =
+        {
+            .name = "SLIX2 (316B)",
+            .size = (80 - 1) * SLIX_BLOCK_SIZE,
+            .protocol = NfcProtocolSlix,
+        },
 };
 
 static bool nfc_maker_custom_event_callback(void* context, uint32_t event) {
@@ -105,7 +189,7 @@ void nfc_maker_free(NfcMaker* app) {
     free(app);
 }
 
-extern int32_t nfc_maker(void* p) {
+int32_t nfc_maker(void* p) {
     UNUSED(p);
     NfcMaker* app = nfc_maker_alloc();
     scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneStart, NfcMakerSceneHttps);

+ 42 - 20
nfc_maker/nfc_maker.h

@@ -1,12 +1,13 @@
 #pragma once
 
 #include <furi.h>
+#include <furi_hal.h>
 #include <gui/gui.h>
 #include <gui/view.h>
 #include <gui/modules/validators.h>
 #include <gui/view_dispatcher.h>
 #include <gui/scene_manager.h>
-#if __has_include(<assets_icons.h>)
+#ifdef FW_ORIGIN_Momentum
 #include <assets_icons.h>
 #else
 extern const Icon I_DolphinDone_80x58;
@@ -23,36 +24,57 @@ extern const Icon I_WarningDolphinFlip_45x42;
 #include "scenes/nfc_maker_scene.h"
 #include <lib/flipper_format/flipper_format.h>
 #include <toolbox/name_generator.h>
-#if __has_include(<applications/main/nfc/nfc_app_i.h>)
+#include <bit_lib/bit_lib.h>
+#if defined(FW_ORIGIN_Momentum) && __has_include(<applications/main/nfc/nfc_app_i.h>)
 #include <applications/main/nfc/nfc_app_i.h>
 #else
 #define NFC_APP_FOLDER    EXT_PATH("nfc")
 #define NFC_APP_EXTENSION ".nfc"
 #endif
 #include <lib/nfc/protocols/mf_ultralight/mf_ultralight.h>
+#include <lib/nfc/protocols/mf_classic/mf_classic.h>
+#include <lib/nfc/protocols/slix/slix.h>
 #include <lib/nfc/helpers/nfc_data_generator.h>
-#include <furi_hal_bt.h>
 
-#define MAC_INPUT_LEN   GAP_MAC_ADDR_SIZE
-#define MAIL_INPUT_LEN  128
-#define PHONE_INPUT_LEN 17
+#define MAC_INPUT_LEN   (GAP_MAC_ADDR_SIZE)
+#define MAIL_INPUT_LEN  (128)
+#define PHONE_INPUT_LEN (17)
 
-#define BIG_INPUT_LEN   248
-#define SMALL_INPUT_LEN 90
+#define BIG_INPUT_LEN   (248)
+#define SMALL_INPUT_LEN (90)
 
-#define NTAG_DATA_AREA_UNIT_SIZE 2 * MF_ULTRALIGHT_PAGE_SIZE
+#define NTAG_DATA_AREA_UNIT_SIZE (2 * MF_ULTRALIGHT_PAGE_SIZE)
 typedef enum {
-    Ntag203,
-    Ntag213,
-    Ntag215,
-    Ntag216,
-    NtagI2C1K,
-    NtagI2C2K,
-    NtagMAX,
-} Ntag;
-extern const NfcDataGeneratorType ntag_generators[NtagMAX];
-extern const char* ntag_names[NtagMAX];
-extern const size_t ntag_sizes[NtagMAX];
+    // MfUltralight
+    CardNtag203,
+    CardNtag213,
+    CardNtag215,
+    CardNtag216,
+    CardNtagI2C1K,
+    CardNtagI2C2K,
+
+    // MfClassic
+    CardMfClassicMini,
+    CardMfClassic1K4b,
+    CardMfClassic1K7b,
+    CardMfClassic4K4b,
+    CardMfClassic4K7b,
+
+    // Slix
+    CardSlix,
+    CardSlixS,
+    CardSlixL,
+    CardSlix2,
+
+    CardMAX,
+} Card;
+typedef struct {
+    const char* name;
+    size_t size;
+    NfcProtocol protocol;
+    NfcDataGeneratorType generator;
+} CardDef;
+extern const CardDef cards[CardMAX];
 
 typedef enum {
     WifiAuthenticationOpen = 0x01,

+ 1 - 1
nfc_maker/scenes/nfc_maker_scene_config.h

@@ -15,6 +15,6 @@ ADD_SCENE(nfc_maker, wifi_auth, WifiAuth)
 ADD_SCENE(nfc_maker, wifi_encr, WifiEncr)
 ADD_SCENE(nfc_maker, wifi_pass, WifiPass)
 ADD_SCENE(nfc_maker, save_generate, SaveGenerate)
-ADD_SCENE(nfc_maker, save_uid_mful, SaveUidMful)
+ADD_SCENE(nfc_maker, save_uid, SaveUid)
 ADD_SCENE(nfc_maker, save_name, SaveName)
 ADD_SCENE(nfc_maker, save_result, SaveResult)

+ 176 - 21
nfc_maker/scenes/nfc_maker_scene_save_generate.c

@@ -286,6 +286,163 @@ static void nfc_maker_scene_save_generate_populate_ndef_buffer(NfcMaker* app) {
     furi_check(app->ndef_size == (size_t)(buf - app->ndef_buffer));
 }
 
+static void nfc_maker_scene_save_generate_populate_device_mful(NfcMaker* app, Card card_type) {
+    const CardDef* card = &cards[card_type];
+
+    nfc_data_generator_fill_data(card->generator, app->nfc_device);
+    MfUltralightData* data = mf_ultralight_alloc();
+    nfc_device_copy_data(app->nfc_device, NfcProtocolMfUltralight, data);
+
+    size_t size =
+        MIN(card->size, // Known size
+            data->page[3].data[2] * NTAG_DATA_AREA_UNIT_SIZE // Capability Container
+        );
+    furi_check(app->ndef_size <= size);
+    memcpy(&data->page[4].data[0], app->ndef_buffer, app->ndef_size);
+    free(app->ndef_buffer);
+    app->ndef_buffer = NULL;
+
+    nfc_device_set_data(app->nfc_device, NfcProtocolMfUltralight, data);
+    mf_ultralight_free(data);
+}
+
+static void nfc_maker_scene_save_generate_populate_device_mfc(NfcMaker* app, Card card_type) {
+    const CardDef* card = &cards[card_type];
+
+    nfc_data_generator_fill_data(card->generator, app->nfc_device);
+    MfClassicData* data = mf_classic_alloc();
+    nfc_device_copy_data(app->nfc_device, NfcProtocolMfClassic, data);
+    const size_t sector_count = mf_classic_get_total_sectors_num(data->type);
+
+    const uint8_t* buf = app->ndef_buffer;
+    size_t len = app->ndef_size;
+    size_t real_block = 4; // Skip MAD1
+
+    uint8_t* cur = &data->block[real_block].data[0];
+    while(len) {
+        size_t sector_trailer = mf_classic_get_sector_trailer_num_by_block(real_block);
+        const uint8_t* end = &data->block[sector_trailer].data[0];
+
+        const size_t chunk_len = MIN((size_t)(end - cur), len);
+        memcpy(cur, buf, chunk_len);
+        buf += chunk_len;
+        len -= chunk_len;
+
+        if(len) {
+            real_block = sector_trailer + 1;
+            if(real_block == 64) {
+                real_block += 4; // Skip MAD2
+            }
+            cur = &data->block[real_block].data[0];
+        }
+    }
+
+    // Format data sector trailers
+    MfClassicSectorTrailer data_tr = {
+        .key_a = {{0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}}, // NFC key
+        .access_bits = {{0x7F, 0x07, 0x88, 0x40}}, // Default access rights
+        .key_b = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, // Default key
+    };
+    for(size_t sector = 0; sector < sector_count; sector++) {
+        mf_classic_set_sector_trailer_read(
+            data, mf_classic_get_sector_trailer_num_by_sector(sector), &data_tr);
+    }
+
+    // https://www.nxp.com/docs/en/application-note/AN10787.pdf
+    // Format MAD1
+    size_t mad_block = 1;
+    uint8_t* mad = &data->block[mad_block].data[0];
+    mad[1] = 0x01; // Info byte
+    mad[2] = 0x03; // NDEF app ID
+    mad[3] = 0xE1; // NDEF app ID
+    mad[0] = bit_lib_crc8(&mad[1], MF_CLASSIC_BLOCK_SIZE * 2 - 1, 0x1D, 0xC7, false, false, 0x00);
+    MfClassicSectorTrailer mad_tr = {
+        .key_a = {{0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}}, // MAD key
+        .access_bits = {{0x78, 0x77, 0x88, 0xC1}}, // Read with A/B, write with B
+        .key_b = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, // Default key
+    };
+    mf_classic_set_sector_trailer_read(
+        data, mf_classic_get_sector_trailer_num_by_block(mad_block), &mad_tr);
+    // Format MAD2
+    if(sector_count > 16) {
+        mad_block = 64;
+        mad = &data->block[mad_block].data[0];
+        mad[1] = 0x01; // Info byte
+        mad[0] =
+            bit_lib_crc8(&mad[1], MF_CLASSIC_BLOCK_SIZE * 3 - 1, 0x1D, 0xC7, false, false, 0x00);
+        mf_classic_set_sector_trailer_read(
+            data, mf_classic_get_sector_trailer_num_by_block(mad_block), &mad_tr);
+    }
+
+    free(app->ndef_buffer);
+    app->ndef_buffer = NULL;
+
+    nfc_device_set_data(app->nfc_device, NfcProtocolMfClassic, data);
+    mf_classic_free(data);
+}
+
+static void nfc_maker_scene_save_generate_populate_device_slix(NfcMaker* app, Card card_type) {
+    SlixData* data = slix_alloc();
+
+    size_t block_count = 0;
+    data->iso15693_3_data->system_info.flags =
+        ISO15693_3_SYSINFO_FLAG_DSFID | ISO15693_3_SYSINFO_FLAG_AFI |
+        ISO15693_3_SYSINFO_FLAG_MEMORY | ISO15693_3_SYSINFO_FLAG_IC_REF;
+    uint8_t uid[8];
+    furi_hal_random_fill_buf(uid, sizeof(uid));
+    uid[0] = 0xE0; // All ISO15693-3 cards must have this as first UID byte
+    uid[1] = 0x04; // NXP manufacturer code
+
+    switch(card_type) {
+    case CardSlix:
+        block_count = 28;
+        uid[2] = 0x01; // ICODE Type
+        uid[3] &= ~(0x03 << 3);
+        uid[3] |= 0x02 << 3; // Type Indicator
+        break;
+    case CardSlixS:
+        block_count = 40;
+        uid[2] = 0x02; // ICODE Type
+        break;
+    case CardSlixL:
+        block_count = 8;
+        uid[2] = 0x03; // ICODE Type
+        break;
+    case CardSlix2:
+        block_count = 80;
+        uid[2] = 0x01; // ICODE Type
+        uid[3] &= ~(0x03 << 3);
+        uid[3] |= 0x01 << 3; // Type Indicator
+        break;
+    default:
+        break;
+    }
+
+    slix_set_uid(data, uid, sizeof(uid));
+    const size_t block_size = SLIX_BLOCK_SIZE;
+    const size_t data_area = block_count * block_size;
+    data->iso15693_3_data->system_info.block_size = block_size;
+    data->iso15693_3_data->system_info.block_count = block_count;
+    simple_array_init(data->iso15693_3_data->block_data, data_area);
+    simple_array_init(data->iso15693_3_data->block_security, block_count);
+
+    uint8_t* blocks = simple_array_get_data(data->iso15693_3_data->block_data);
+    memcpy(&blocks[1 * block_size], app->ndef_buffer, app->ndef_size);
+
+    // https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/nfc/7583/1/EEOL_2011FEB16_EMS_RFD_AN_01.pdf
+    // Format Capability Container
+    blocks[0] = 0xE1; // NFC Magic Number
+    blocks[1] = 0x40; // 0x4X: Version 1, 0xX0: Full R/W access
+    blocks[2] = data_area / 8; // Data Area Size: Total byte size / 8
+    blocks[3] = 0x01; // MBREAD: Supports Multiple Block Read command
+
+    free(app->ndef_buffer);
+    app->ndef_buffer = NULL;
+
+    nfc_device_set_data(app->nfc_device, NfcProtocolSlix, data);
+    slix_free(data);
+}
+
 void nfc_maker_scene_save_generate_submenu_callback(void* context, uint32_t index) {
     NfcMaker* app = context;
     view_dispatcher_send_custom_event(app->view_dispatcher, index);
@@ -298,14 +455,14 @@ void nfc_maker_scene_save_generate_on_enter(void* context) {
 
     submenu_set_header(submenu, "Tag Type:");
 
-    for(Ntag ntag = 0; ntag < NtagMAX; ntag++) {
+    for(Card card = 0; card < CardMAX; card++) {
         submenu_add_lockable_item(
             submenu,
-            ntag_names[ntag],
-            ntag,
+            cards[card].name,
+            card,
             nfc_maker_scene_save_generate_submenu_callback,
             app,
-            app->ndef_size > ntag_sizes[ntag],
+            app->ndef_size > cards[card].size,
             "Data is\ntoo large!");
     }
 
@@ -321,26 +478,24 @@ bool nfc_maker_scene_save_generate_on_event(void* context, SceneManagerEvent eve
 
     if(event.type == SceneManagerEventTypeCustom) {
         scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneSaveGenerate, event.event);
-        if(event.event >= NtagMAX) return consumed;
+        if(event.event >= CardMAX) return consumed;
         consumed = true;
 
-        nfc_data_generator_fill_data(ntag_generators[event.event], app->nfc_device);
-        MfUltralightData* data = mf_ultralight_alloc();
-        nfc_device_copy_data(app->nfc_device, NfcProtocolMfUltralight, data);
-
-        size_t size =
-            MIN(ntag_sizes[event.event], // Known size
-                data->page[3].data[2] * NTAG_DATA_AREA_UNIT_SIZE // Capability Container
-            );
-        furi_check(app->ndef_size <= size);
-        memcpy(&data->page[4].data[0], app->ndef_buffer, app->ndef_size);
-        free(app->ndef_buffer);
-        app->ndef_buffer = NULL;
-
-        nfc_device_set_data(app->nfc_device, NfcProtocolMfUltralight, data);
-        mf_ultralight_free(data);
+        switch(cards[event.event].protocol) {
+        case NfcProtocolMfUltralight:
+            nfc_maker_scene_save_generate_populate_device_mful(app, event.event);
+            break;
+        case NfcProtocolMfClassic:
+            nfc_maker_scene_save_generate_populate_device_mfc(app, event.event);
+            break;
+        case NfcProtocolSlix:
+            nfc_maker_scene_save_generate_populate_device_slix(app, event.event);
+            break;
+        default:
+            break;
+        }
 
-        scene_manager_next_scene(app->scene_manager, NfcMakerSceneSaveUidMful);
+        scene_manager_next_scene(app->scene_manager, NfcMakerSceneSaveUid);
     }
 
     return consumed;

+ 13 - 2
nfc_maker/scenes/nfc_maker_scene_save_result.c

@@ -2,14 +2,21 @@
 
 enum PopupEvent {
     PopupEventExit,
+    PopupEventFailed,
 };
 
-static void nfc_maker_scene_save_result_popup_callback(void* context) {
+static void nfc_maker_scene_save_result_popup_callback_exit(void* context) {
     NfcMaker* app = context;
 
     view_dispatcher_send_custom_event(app->view_dispatcher, PopupEventExit);
 }
 
+static void nfc_maker_scene_save_result_popup_callback_failed(void* context) {
+    NfcMaker* app = context;
+
+    view_dispatcher_send_custom_event(app->view_dispatcher, PopupEventFailed);
+}
+
 void nfc_maker_scene_save_result_on_enter(void* context) {
     NfcMaker* app = context;
     Popup* popup = app->popup;
@@ -23,14 +30,15 @@ void nfc_maker_scene_save_result_on_enter(void* context) {
         popup_set_icon(popup, 36, 5, &I_DolphinDone_80x58);
         popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
         popup_enable_timeout(popup);
+        popup_set_callback(popup, nfc_maker_scene_save_result_popup_callback_exit);
     } else {
         popup_set_icon(popup, 69, 15, &I_WarningDolphinFlip_45x42);
         popup_set_header(popup, "Error!", 13, 22, AlignLeft, AlignBottom);
         popup_disable_timeout(popup);
+        popup_set_callback(popup, nfc_maker_scene_save_result_popup_callback_failed);
     }
     popup_set_timeout(popup, 1500);
     popup_set_context(popup, app);
-    popup_set_callback(popup, nfc_maker_scene_save_result_popup_callback);
 
     view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewPopup);
 }
@@ -46,6 +54,9 @@ bool nfc_maker_scene_save_result_on_event(void* context, SceneManagerEvent event
             scene_manager_search_and_switch_to_previous_scene(
                 app->scene_manager, NfcMakerSceneStart);
             break;
+        case PopupEventFailed:
+            scene_manager_previous_scene(app->scene_manager);
+            break;
         default:
             break;
         }

+ 7 - 7
nfc_maker/scenes/nfc_maker_scene_save_uid_mful.c → nfc_maker/scenes/nfc_maker_scene_save_uid.c

@@ -4,7 +4,7 @@ enum ByteInputResult {
     ByteInputResultOk,
 };
 
-static void nfc_maker_scene_save_uid_mful_byte_input_callback(void* context) {
+static void nfc_maker_scene_save_uid_byte_input_callback(void* context) {
     NfcMaker* app = context;
 
     size_t uid_len;
@@ -18,13 +18,13 @@ static void nfc_maker_scene_save_uid_mful_byte_input_callback(void* context) {
     }
 }
 
-static void nfc_maker_scene_save_uid_mful_byte_input_changed(void* context) {
+static void nfc_maker_scene_save_uid_byte_input_changed(void* context) {
     NfcMaker* app = context;
 
     byte_input_set_header_text(app->byte_input, "Change UID:");
 }
 
-void nfc_maker_scene_save_uid_mful_on_enter(void* context) {
+void nfc_maker_scene_save_uid_on_enter(void* context) {
     NfcMaker* app = context;
     ByteInput* byte_input = app->byte_input;
 
@@ -36,8 +36,8 @@ void nfc_maker_scene_save_uid_mful_on_enter(void* context) {
 
     byte_input_set_result_callback(
         byte_input,
-        nfc_maker_scene_save_uid_mful_byte_input_callback,
-        nfc_maker_scene_save_uid_mful_byte_input_changed,
+        nfc_maker_scene_save_uid_byte_input_callback,
+        nfc_maker_scene_save_uid_byte_input_changed,
         app,
         app->uid_buf,
         uid_len);
@@ -45,7 +45,7 @@ void nfc_maker_scene_save_uid_mful_on_enter(void* context) {
     view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewByteInput);
 }
 
-bool nfc_maker_scene_save_uid_mful_on_event(void* context, SceneManagerEvent event) {
+bool nfc_maker_scene_save_uid_on_event(void* context, SceneManagerEvent event) {
     NfcMaker* app = context;
     bool consumed = false;
 
@@ -63,7 +63,7 @@ bool nfc_maker_scene_save_uid_mful_on_event(void* context, SceneManagerEvent eve
     return consumed;
 }
 
-void nfc_maker_scene_save_uid_mful_on_exit(void* context) {
+void nfc_maker_scene_save_uid_on_exit(void* context) {
     NfcMaker* app = context;
     byte_input_set_result_callback(app->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_header_text(app->byte_input, "");

+ 1 - 1
nfc_maker/scenes/nfc_maker_scene_start.c

@@ -9,7 +9,7 @@ void nfc_maker_scene_start_on_enter(void* context) {
     NfcMaker* app = context;
     Submenu* submenu = app->submenu;
 
-    submenu_set_header(submenu, "NFC Tag Maker:");
+    submenu_set_header(submenu, "NFC Tag Maker v" FAP_VERSION);
 
     submenu_add_item(
         submenu,