mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-12 10:38:36 -07:00
Temporarily backport app updates from apps repo
This commit is contained in:
BIN
applications/external/nfc_magic/125_10px.png
vendored
Normal file
BIN
applications/external/nfc_magic/125_10px.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 308 B |
BIN
applications/external/nfc_magic/Nfc_10px.png
vendored
BIN
applications/external/nfc_magic/Nfc_10px.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 304 B |
@@ -1,6 +1,6 @@
|
||||
App(
|
||||
appid="nfc_magic",
|
||||
name="NFC Magic",
|
||||
name="Nfc Magic",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
targets=["f7"],
|
||||
entry_point="nfc_magic_app",
|
||||
@@ -9,7 +9,9 @@ App(
|
||||
"gui",
|
||||
],
|
||||
stack_size=4 * 1024,
|
||||
fap_icon="Nfc_10px.png",
|
||||
fap_description="Application for writing to NFC tags with modifiable sector 0",
|
||||
fap_version="1.1",
|
||||
fap_icon="125_10px.png",
|
||||
fap_category="NFC",
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
|
||||
14
applications/external/nfc_magic/helpers/nfc_magic_custom_events.h
vendored
Normal file
14
applications/external/nfc_magic/helpers/nfc_magic_custom_events.h
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
// Reserve first 100 events for button types and indexes, starting from 0
|
||||
NfcMagicCustomEventReserved = 100,
|
||||
|
||||
NfcMagicCustomEventViewExit,
|
||||
|
||||
NfcMagicCustomEventCardDetected,
|
||||
NfcMagicCustomEventCardLost,
|
||||
NfcMagicCustomEventWorkerSuccess,
|
||||
NfcMagicCustomEventWorkerFail,
|
||||
|
||||
} NfcMagicCustomEvent;
|
||||
@@ -1,145 +0,0 @@
|
||||
#include "classic_gen1.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
#define TAG "Magic"
|
||||
|
||||
#define MAGIC_CMD_WUPA (0x40)
|
||||
#define MAGIC_CMD_ACCESS (0x43)
|
||||
|
||||
#define MAGIC_MIFARE_READ_CMD (0x30)
|
||||
#define MAGIC_MIFARE_WRITE_CMD (0xA0)
|
||||
|
||||
#define MAGIC_ACK (0x0A)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (32)
|
||||
|
||||
bool magic_gen1_wupa() {
|
||||
bool magic_activated = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_WUPA;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
7,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
magic_activated = true;
|
||||
} while(false);
|
||||
|
||||
return magic_activated;
|
||||
}
|
||||
|
||||
bool magic_gen1_data_access_cmd() {
|
||||
bool write_cmd_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_CMD_ACCESS;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
write_cmd_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_cmd_success;
|
||||
}
|
||||
|
||||
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool read_success = false;
|
||||
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_MIFARE_READ_CMD;
|
||||
tx_data[1] = block_num;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
2 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 16 * 8) break;
|
||||
memcpy(data->value, rx_data, sizeof(data->value));
|
||||
read_success = true;
|
||||
} while(false);
|
||||
|
||||
return read_success;
|
||||
}
|
||||
|
||||
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_MIFARE_WRITE_CMD;
|
||||
tx_data[1] = block_num;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
2 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
memcpy(tx_data, data->value, sizeof(data->value));
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
16 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
bool magic_gen1_wupa();
|
||||
|
||||
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data);
|
||||
|
||||
bool magic_gen1_data_access_cmd();
|
||||
|
||||
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data);
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
#define REQA (0x26)
|
||||
#define CL1_PREFIX (0x93)
|
||||
#define SELECT (0x70)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (32)
|
||||
|
||||
bool magic_activate() {
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
// Setup nfc poller
|
||||
furi_hal_nfc_exit_sleep();
|
||||
furi_hal_nfc_ll_txrx_on();
|
||||
furi_hal_nfc_ll_poll();
|
||||
ret = furi_hal_nfc_ll_set_mode(
|
||||
FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106);
|
||||
if(ret != FuriHalNfcReturnOk) return false;
|
||||
|
||||
furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc);
|
||||
furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void magic_deactivate() {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_sleep();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
MagicTypeClassicGen1,
|
||||
MagicTypeClassicDirectWrite,
|
||||
MagicTypeClassicAPDU,
|
||||
MagicTypeUltralightGen1,
|
||||
MagicTypeUltralightDirectWrite,
|
||||
MagicTypeUltralightC_Gen1,
|
||||
MagicTypeUltralightC_DirectWrite,
|
||||
MagicTypeGen4,
|
||||
} MagicType;
|
||||
|
||||
bool magic_activate();
|
||||
|
||||
void magic_deactivate();
|
||||
199
applications/external/nfc_magic/lib/magic/gen4.c
vendored
199
applications/external/nfc_magic/lib/magic/gen4.c
vendored
@@ -1,199 +0,0 @@
|
||||
#include "gen4.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TAG "Magic"
|
||||
|
||||
#define MAGIC_CMD_PREFIX (0xCF)
|
||||
|
||||
#define MAGIC_CMD_GET_CFG (0xC6)
|
||||
#define MAGIC_CMD_WRITE (0xCD)
|
||||
#define MAGIC_CMD_READ (0xCE)
|
||||
#define MAGIC_CMD_SET_CFG (0xF0)
|
||||
#define MAGIC_CMD_FUSE_CFG (0xF1)
|
||||
#define MAGIC_CMD_SET_PWD (0xFE)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (40)
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_CONFIG[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00
|
||||
};
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_BLOCK0[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 };
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static bool magic_gen4_is_block_num_trailer(uint8_t n) {
|
||||
n++;
|
||||
if (n < 32 * 4) {
|
||||
return (n % 4 == 0);
|
||||
}
|
||||
|
||||
return (n % 16 == 0);
|
||||
}
|
||||
|
||||
bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) {
|
||||
bool is_valid_config_len = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = MAGIC_CMD_GET_CFG;
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
6,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 30 && rx_len != 32) break;
|
||||
memcpy(config, rx_data, rx_len);
|
||||
is_valid_config_len = true;
|
||||
} while(false);
|
||||
|
||||
return is_valid_config_len;
|
||||
}
|
||||
|
||||
bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) {
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG;
|
||||
memcpy(tx_data + 6, config, config_length);
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
6 + config_length,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) {
|
||||
bool change_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(old_pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(old_pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(old_pwd >> 8);
|
||||
tx_data[4] = (uint8_t)old_pwd;
|
||||
tx_data[5] = MAGIC_CMD_SET_PWD;
|
||||
tx_data[6] = (uint8_t)(new_pwd >> 24);
|
||||
tx_data[7] = (uint8_t)(new_pwd >> 16);
|
||||
tx_data[8] = (uint8_t)(new_pwd >> 8);
|
||||
tx_data[9] = (uint8_t)new_pwd;
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
10,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len);
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
change_success = true;
|
||||
} while(false);
|
||||
|
||||
return change_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) {
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = MAGIC_CMD_WRITE;
|
||||
tx_data[6] = block_num;
|
||||
memcpy(tx_data + 7, data, 16);
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
23,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(200));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_wipe(uint32_t pwd) {
|
||||
if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) {
|
||||
FURI_LOG_E(TAG, "Set config failed");
|
||||
return false;
|
||||
}
|
||||
if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) {
|
||||
FURI_LOG_E(TAG, "Block 0 write failed");
|
||||
return false;
|
||||
}
|
||||
for(size_t i = 1; i < 64; i++) {
|
||||
const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK;
|
||||
if(!magic_gen4_write_blk(pwd, i, block)) {
|
||||
FURI_LOG_E(TAG, "Block %d write failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(size_t i = 65; i < 256; i++) {
|
||||
if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) {
|
||||
FURI_LOG_E(TAG, "Block %d write failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
48
applications/external/nfc_magic/lib/magic/gen4.h
vendored
48
applications/external/nfc_magic/lib/magic/gen4.h
vendored
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
#define MAGIC_GEN4_DEFAULT_PWD 0x00000000
|
||||
#define MAGIC_GEN4_CONFIG_LEN 32
|
||||
|
||||
#define NFCID1_SINGLE_SIZE 4
|
||||
#define NFCID1_DOUBLE_SIZE 7
|
||||
#define NFCID1_TRIPLE_SIZE 10
|
||||
|
||||
typedef enum {
|
||||
MagicGen4UIDLengthSingle = 0x00,
|
||||
MagicGen4UIDLengthDouble = 0x01,
|
||||
MagicGen4UIDLengthTriple = 0x02
|
||||
} MagicGen4UIDLength;
|
||||
|
||||
typedef enum {
|
||||
MagicGen4UltralightModeUL_EV1 = 0x00,
|
||||
MagicGen4UltralightModeNTAG = 0x01,
|
||||
MagicGen4UltralightModeUL_C = 0x02,
|
||||
MagicGen4UltralightModeUL = 0x03
|
||||
} MagicGen4UltralightMode;
|
||||
|
||||
typedef enum {
|
||||
// for writing original (shadow) data
|
||||
MagicGen4ShadowModePreWrite = 0x00,
|
||||
// written data can be read once before restored to original
|
||||
MagicGen4ShadowModeRestore = 0x01,
|
||||
// written data is discarded
|
||||
MagicGen4ShadowModeIgnore = 0x02,
|
||||
// apparently for UL?
|
||||
MagicGen4ShadowModeHighSpeedIgnore = 0x03
|
||||
} MagicGen4ShadowMode;
|
||||
|
||||
bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config);
|
||||
|
||||
bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse);
|
||||
|
||||
bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd);
|
||||
|
||||
bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data);
|
||||
|
||||
bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data);
|
||||
|
||||
bool magic_gen4_wipe(uint32_t pwd);
|
||||
|
||||
void magic_gen4_deactivate();
|
||||
150
applications/external/nfc_magic/lib/magic/nfc_magic_scanner.c
vendored
Normal file
150
applications/external/nfc_magic/lib/magic/nfc_magic_scanner.c
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "nfc_magic_scanner.h"
|
||||
|
||||
#include "protocols/gen1a/gen1a_poller.h"
|
||||
#include "protocols/gen4/gen4_poller.h"
|
||||
#include <nfc/nfc_poller.h>
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
typedef enum {
|
||||
NfcMagicScannerSessionStateIdle,
|
||||
NfcMagicScannerSessionStateActive,
|
||||
NfcMagicScannerSessionStateStopRequest,
|
||||
} NfcMagicScannerSessionState;
|
||||
|
||||
struct NfcMagicScanner {
|
||||
Nfc* nfc;
|
||||
NfcMagicScannerSessionState session_state;
|
||||
NfcMagicProtocol current_protocol;
|
||||
|
||||
uint32_t gen4_password;
|
||||
bool magic_protocol_detected;
|
||||
|
||||
NfcMagicScannerCallback callback;
|
||||
void* context;
|
||||
|
||||
FuriThread* scan_worker;
|
||||
};
|
||||
|
||||
static const NfcProtocol nfc_magic_scanner_not_magic_protocols[] = {
|
||||
NfcProtocolIso14443_3b,
|
||||
NfcProtocolIso15693_3,
|
||||
NfcProtocolFelica,
|
||||
};
|
||||
|
||||
static void nfc_magic_scanner_reset(NfcMagicScanner* instance) {
|
||||
instance->session_state = NfcMagicScannerSessionStateIdle;
|
||||
instance->current_protocol = NfcMagicProtocolGen1;
|
||||
}
|
||||
|
||||
NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
|
||||
NfcMagicScanner* instance = malloc(sizeof(NfcMagicScanner));
|
||||
instance->nfc = nfc;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_magic_scanner_free(NfcMagicScanner* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->gen4_password = password;
|
||||
}
|
||||
|
||||
static int32_t nfc_magic_scanner_worker(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
NfcMagicScanner* instance = context;
|
||||
furi_assert(instance->session_state == NfcMagicScannerSessionStateActive);
|
||||
|
||||
while(instance->session_state == NfcMagicScannerSessionStateActive) {
|
||||
if(instance->current_protocol == NfcMagicProtocolGen1) {
|
||||
instance->magic_protocol_detected = gen1a_poller_detect(instance->nfc);
|
||||
} else if(instance->current_protocol == NfcMagicProtocolGen4) {
|
||||
Gen4PollerError error = gen4_poller_detect(instance->nfc, instance->gen4_password);
|
||||
if(error == Gen4PollerErrorProtocol) {
|
||||
NfcMagicScannerEvent event = {
|
||||
.type = NfcMagicScannerEventTypeDetectedNotMagic,
|
||||
};
|
||||
instance->callback(event, instance->context);
|
||||
break;
|
||||
} else {
|
||||
instance->magic_protocol_detected = (error == Gen4PollerErrorNone);
|
||||
}
|
||||
}
|
||||
|
||||
if(instance->magic_protocol_detected) {
|
||||
NfcMagicScannerEvent event = {
|
||||
.type = NfcMagicScannerEventTypeDetected,
|
||||
.data.protocol = instance->current_protocol,
|
||||
};
|
||||
instance->callback(event, instance->context);
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->current_protocol == NfcMagicProtocolNum - 1) {
|
||||
bool not_magic_protocol_detected = false;
|
||||
for(size_t i = 0; i < COUNT_OF(nfc_magic_scanner_not_magic_protocols); i++) {
|
||||
NfcProtocol protocol = nfc_magic_scanner_not_magic_protocols[i];
|
||||
NfcPoller* poller = nfc_poller_alloc(instance->nfc, protocol);
|
||||
not_magic_protocol_detected = nfc_poller_detect(poller);
|
||||
nfc_poller_free(poller);
|
||||
if(not_magic_protocol_detected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(not_magic_protocol_detected) {
|
||||
NfcMagicScannerEvent event = {
|
||||
.type = NfcMagicScannerEventTypeDetectedNotMagic,
|
||||
};
|
||||
instance->callback(event, instance->context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
instance->current_protocol = (instance->current_protocol + 1) % NfcMagicProtocolNum;
|
||||
}
|
||||
|
||||
nfc_magic_scanner_reset(instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfc_magic_scanner_start(
|
||||
NfcMagicScanner* instance,
|
||||
NfcMagicScannerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
|
||||
instance->scan_worker = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->scan_worker, "NfcMagicScanWorker");
|
||||
furi_thread_set_context(instance->scan_worker, instance);
|
||||
furi_thread_set_stack_size(instance->scan_worker, 4 * 1024);
|
||||
furi_thread_set_callback(instance->scan_worker, nfc_magic_scanner_worker);
|
||||
furi_thread_start(instance->scan_worker);
|
||||
|
||||
instance->session_state = NfcMagicScannerSessionStateActive;
|
||||
}
|
||||
|
||||
void nfc_magic_scanner_stop(NfcMagicScanner* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->session_state = NfcMagicScannerSessionStateStopRequest;
|
||||
furi_thread_join(instance->scan_worker);
|
||||
instance->session_state = NfcMagicScannerSessionStateIdle;
|
||||
|
||||
furi_thread_free(instance->scan_worker);
|
||||
instance->scan_worker = NULL;
|
||||
instance->callback = NULL;
|
||||
instance->context = NULL;
|
||||
}
|
||||
44
applications/external/nfc_magic/lib/magic/nfc_magic_scanner.h
vendored
Normal file
44
applications/external/nfc_magic/lib/magic/nfc_magic_scanner.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include "protocols/nfc_magic_protocols.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NfcMagicScannerEventTypeDetected,
|
||||
NfcMagicScannerEventTypeDetectedNotMagic,
|
||||
NfcMagicScannerEventTypeNotDetected,
|
||||
} NfcMagicScannerEventType;
|
||||
|
||||
typedef struct {
|
||||
NfcMagicProtocol protocol;
|
||||
} NfcMagicScannerEventData;
|
||||
|
||||
typedef struct {
|
||||
NfcMagicScannerEventType type;
|
||||
NfcMagicScannerEventData data;
|
||||
} NfcMagicScannerEvent;
|
||||
|
||||
typedef void (*NfcMagicScannerCallback)(NfcMagicScannerEvent event, void* context);
|
||||
|
||||
typedef struct NfcMagicScanner NfcMagicScanner;
|
||||
|
||||
NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc);
|
||||
|
||||
void nfc_magic_scanner_free(NfcMagicScanner* instance);
|
||||
|
||||
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password);
|
||||
|
||||
void nfc_magic_scanner_start(
|
||||
NfcMagicScanner* instance,
|
||||
NfcMagicScannerCallback callback,
|
||||
void* context);
|
||||
|
||||
void nfc_magic_scanner_stop(NfcMagicScanner* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
279
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller.c
vendored
Normal file
279
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller.c
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
#include "gen1a_poller_i.h"
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
#include <nfc/helpers/nfc_data_generator.h>
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
#define GEN1A_POLLER_THREAD_FLAG_DETECTED (1U << 0)
|
||||
|
||||
typedef NfcCommand (*Gen1aPollerStateHandler)(Gen1aPoller* instance);
|
||||
|
||||
typedef struct {
|
||||
Nfc* nfc;
|
||||
BitBuffer* tx_buffer;
|
||||
BitBuffer* rx_buffer;
|
||||
FuriThreadId thread_id;
|
||||
bool detected;
|
||||
} Gen1aPollerDetectContext;
|
||||
|
||||
Gen1aPoller* gen1a_poller_alloc(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
|
||||
Gen1aPoller* instance = malloc(sizeof(Gen1aPoller));
|
||||
instance->nfc = nfc;
|
||||
|
||||
nfc_config(instance->nfc, NfcModePoller, NfcTechIso14443a);
|
||||
nfc_set_guard_time_us(instance->nfc, ISO14443_3A_GUARD_TIME_US);
|
||||
nfc_set_fdt_poll_fc(instance->nfc, ISO14443_3A_FDT_POLL_FC);
|
||||
nfc_set_fdt_poll_poll_us(instance->nfc, ISO14443_3A_POLL_POLL_MIN_US);
|
||||
|
||||
instance->tx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
|
||||
instance->rx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
|
||||
|
||||
instance->mfc_device = nfc_device_alloc();
|
||||
|
||||
instance->gen1a_event.data = &instance->gen1a_event_data;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void gen1a_poller_free(Gen1aPoller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
bit_buffer_free(instance->tx_buffer);
|
||||
bit_buffer_free(instance->rx_buffer);
|
||||
|
||||
nfc_device_free(instance->mfc_device);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_detect_callback(NfcEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
NfcCommand command = NfcCommandStop;
|
||||
Gen1aPollerDetectContext* gen1a_poller_detect_ctx = context;
|
||||
|
||||
if(event.type == NfcEventTypePollerReady) {
|
||||
do {
|
||||
bit_buffer_set_size(gen1a_poller_detect_ctx->tx_buffer, 7);
|
||||
bit_buffer_set_byte(gen1a_poller_detect_ctx->tx_buffer, 0, 0x40);
|
||||
|
||||
NfcError error = nfc_poller_trx(
|
||||
gen1a_poller_detect_ctx->nfc,
|
||||
gen1a_poller_detect_ctx->tx_buffer,
|
||||
gen1a_poller_detect_ctx->rx_buffer,
|
||||
GEN1A_POLLER_MAX_FWT);
|
||||
|
||||
if(error != NfcErrorNone) break;
|
||||
if(bit_buffer_get_size(gen1a_poller_detect_ctx->rx_buffer) != 4) break;
|
||||
if(bit_buffer_get_byte(gen1a_poller_detect_ctx->rx_buffer, 0) != 0x0A) break;
|
||||
|
||||
gen1a_poller_detect_ctx->detected = true;
|
||||
} while(false);
|
||||
}
|
||||
furi_thread_flags_set(gen1a_poller_detect_ctx->thread_id, GEN1A_POLLER_THREAD_FLAG_DETECTED);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
bool gen1a_poller_detect(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
|
||||
nfc_config(nfc, NfcModePoller, NfcTechIso14443a);
|
||||
nfc_set_guard_time_us(nfc, ISO14443_3A_GUARD_TIME_US);
|
||||
nfc_set_fdt_poll_fc(nfc, ISO14443_3A_FDT_POLL_FC);
|
||||
nfc_set_fdt_poll_poll_us(nfc, ISO14443_3A_POLL_POLL_MIN_US);
|
||||
|
||||
Gen1aPollerDetectContext gen1a_poller_detect_ctx = {};
|
||||
gen1a_poller_detect_ctx.nfc = nfc;
|
||||
gen1a_poller_detect_ctx.tx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
|
||||
gen1a_poller_detect_ctx.rx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
|
||||
gen1a_poller_detect_ctx.thread_id = furi_thread_get_current_id();
|
||||
gen1a_poller_detect_ctx.detected = false;
|
||||
|
||||
nfc_start(nfc, gen1a_poller_detect_callback, &gen1a_poller_detect_ctx);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
GEN1A_POLLER_THREAD_FLAG_DETECTED, FuriFlagWaitAny, FuriWaitForever);
|
||||
if(flags & GEN1A_POLLER_THREAD_FLAG_DETECTED) {
|
||||
furi_thread_flags_clear(GEN1A_POLLER_THREAD_FLAG_DETECTED);
|
||||
}
|
||||
nfc_stop(nfc);
|
||||
|
||||
bit_buffer_free(gen1a_poller_detect_ctx.tx_buffer);
|
||||
bit_buffer_free(gen1a_poller_detect_ctx.rx_buffer);
|
||||
|
||||
return gen1a_poller_detect_ctx.detected;
|
||||
}
|
||||
|
||||
static void gen1a_poller_reset(Gen1aPoller* instance) {
|
||||
instance->current_block = 0;
|
||||
nfc_data_generator_fill_data(NfcDataGeneratorTypeMfClassic1k_4b, instance->mfc_device);
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_idle_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
gen1a_poller_reset(instance);
|
||||
Gen1aPollerError error = gen1a_poller_wupa(instance);
|
||||
if(error == Gen1aPollerErrorNone) {
|
||||
instance->state = Gen1aPollerStateRequestMode;
|
||||
instance->gen1a_event.type = Gen1aPollerEventTypeDetected;
|
||||
command = instance->callback(instance->gen1a_event, instance->context);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_request_mode_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen1a_event.type = Gen1aPollerEventTypeRequestMode;
|
||||
command = instance->callback(instance->gen1a_event, instance->context);
|
||||
if(instance->gen1a_event_data.request_mode.mode == Gen1aPollerModeWipe) {
|
||||
instance->state = Gen1aPollerStateWipe;
|
||||
} else {
|
||||
instance->state = Gen1aPollerStateWriteDataRequest;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_wipe_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
Gen1aPollerError error = Gen1aPollerErrorNone;
|
||||
|
||||
const MfClassicData* mfc_data =
|
||||
nfc_device_get_data(instance->mfc_device, NfcProtocolMfClassic);
|
||||
uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
|
||||
|
||||
if(instance->current_block == total_block_num) {
|
||||
instance->state = Gen1aPollerStateSuccess;
|
||||
} else {
|
||||
do {
|
||||
if(instance->current_block == 0) {
|
||||
error = gen1a_poller_data_access(instance);
|
||||
if(error != Gen1aPollerErrorNone) {
|
||||
instance->state = Gen1aPollerStateFail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
error = gen1a_poller_write_block(
|
||||
instance, instance->current_block, &mfc_data->block[instance->current_block]);
|
||||
if(error != Gen1aPollerErrorNone) {
|
||||
instance->state = Gen1aPollerStateFail;
|
||||
break;
|
||||
}
|
||||
instance->current_block++;
|
||||
} while(false);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_write_data_request_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen1a_event.type = Gen1aPollerEventTypeRequestDataToWrite;
|
||||
command = instance->callback(instance->gen1a_event, instance->context);
|
||||
instance->state = Gen1aPollerStateWrite;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_write_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
Gen1aPollerError error = Gen1aPollerErrorNone;
|
||||
|
||||
const MfClassicData* mfc_data = instance->gen1a_event_data.data_to_write.mfc_data;
|
||||
uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
|
||||
|
||||
if(instance->current_block == total_block_num) {
|
||||
instance->state = Gen1aPollerStateSuccess;
|
||||
} else {
|
||||
do {
|
||||
if(instance->current_block == 0) {
|
||||
error = gen1a_poller_data_access(instance);
|
||||
if(error != Gen1aPollerErrorNone) {
|
||||
instance->state = Gen1aPollerStateFail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
error = gen1a_poller_write_block(
|
||||
instance, instance->current_block, &mfc_data->block[instance->current_block]);
|
||||
if(error != Gen1aPollerErrorNone) {
|
||||
instance->state = Gen1aPollerStateFail;
|
||||
break;
|
||||
}
|
||||
instance->current_block++;
|
||||
} while(false);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_success_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen1a_event.type = Gen1aPollerEventTypeSuccess;
|
||||
command = instance->callback(instance->gen1a_event, instance->context);
|
||||
instance->state = Gen1aPollerStateIdle;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen1a_poller_fail_handler(Gen1aPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen1a_event.type = Gen1aPollerEventTypeFail;
|
||||
command = instance->callback(instance->gen1a_event, instance->context);
|
||||
instance->state = Gen1aPollerStateIdle;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static const Gen1aPollerStateHandler gen1a_poller_state_handlers[Gen1aPollerStateNum] = {
|
||||
[Gen1aPollerStateIdle] = gen1a_poller_idle_handler,
|
||||
[Gen1aPollerStateRequestMode] = gen1a_poller_request_mode_handler,
|
||||
[Gen1aPollerStateWipe] = gen1a_poller_wipe_handler,
|
||||
[Gen1aPollerStateWriteDataRequest] = gen1a_poller_write_data_request_handler,
|
||||
[Gen1aPollerStateWrite] = gen1a_poller_write_handler,
|
||||
[Gen1aPollerStateSuccess] = gen1a_poller_success_handler,
|
||||
[Gen1aPollerStateFail] = gen1a_poller_fail_handler,
|
||||
|
||||
};
|
||||
|
||||
NfcCommand gen1a_poller_run(NfcEvent event, void* context) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
Gen1aPoller* instance = context;
|
||||
|
||||
if(event.type == NfcEventTypePollerReady) {
|
||||
command = gen1a_poller_state_handlers[instance->state](instance);
|
||||
}
|
||||
|
||||
if(instance->session_state == Gen1aPollerSessionStateStopRequest) {
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
void gen1a_poller_start(Gen1aPoller* instance, Gen1aPollerCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
|
||||
instance->session_state = Gen1aPollerSessionStateStarted;
|
||||
nfc_start(instance->nfc, gen1a_poller_run, instance);
|
||||
}
|
||||
|
||||
void gen1a_poller_stop(Gen1aPoller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->session_state = Gen1aPollerSessionStateStopRequest;
|
||||
nfc_stop(instance->nfc);
|
||||
instance->session_state = Gen1aPollerSessionStateIdle;
|
||||
}
|
||||
59
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller.h
vendored
Normal file
59
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/protocols/nfc_generic_event.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
Gen1aPollerEventTypeDetected,
|
||||
Gen1aPollerEventTypeRequestMode,
|
||||
Gen1aPollerEventTypeRequestDataToWrite,
|
||||
|
||||
Gen1aPollerEventTypeSuccess,
|
||||
Gen1aPollerEventTypeFail,
|
||||
} Gen1aPollerEventType;
|
||||
|
||||
typedef enum {
|
||||
Gen1aPollerModeWipe,
|
||||
Gen1aPollerModeWrite,
|
||||
} Gen1aPollerMode;
|
||||
|
||||
typedef struct {
|
||||
Gen1aPollerMode mode;
|
||||
} Gen1aPollerEventDataRequestMode;
|
||||
|
||||
typedef struct {
|
||||
const MfClassicData* mfc_data;
|
||||
} Gen1aPollerEventDataRequestDataToWrite;
|
||||
|
||||
typedef union {
|
||||
Gen1aPollerEventDataRequestMode request_mode;
|
||||
Gen1aPollerEventDataRequestDataToWrite data_to_write;
|
||||
} Gen1aPollerEventData;
|
||||
|
||||
typedef struct {
|
||||
Gen1aPollerEventType type;
|
||||
Gen1aPollerEventData* data;
|
||||
} Gen1aPollerEvent;
|
||||
|
||||
typedef NfcCommand (*Gen1aPollerCallback)(Gen1aPollerEvent event, void* context);
|
||||
|
||||
typedef struct Gen1aPoller Gen1aPoller;
|
||||
|
||||
bool gen1a_poller_detect(Nfc* nfc);
|
||||
|
||||
Gen1aPoller* gen1a_poller_alloc(Nfc* nfc);
|
||||
|
||||
void gen1a_poller_free(Gen1aPoller* instance);
|
||||
|
||||
void gen1a_poller_start(Gen1aPoller* instance, Gen1aPollerCallback callback, void* context);
|
||||
|
||||
void gen1a_poller_stop(Gen1aPoller* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
132
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller_i.c
vendored
Normal file
132
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller_i.c
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "gen1a_poller_i.h"
|
||||
#include <nfc/helpers/iso14443_crc.h>
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
static Gen1aPollerError gen1a_poller_process_nfc_error(NfcError error) {
|
||||
Gen1aPollerError ret = Gen1aPollerErrorNone;
|
||||
|
||||
if(error == NfcErrorNone) {
|
||||
ret = Gen1aPollerErrorNone;
|
||||
} else if(error == NfcErrorTimeout) {
|
||||
ret = Gen1aPollerErrorTimeout;
|
||||
} else {
|
||||
ret = Gen1aPollerErrorNotPresent;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen1aPollerError gen1a_poller_wupa(Gen1aPoller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
Gen1aPollerError ret = Gen1aPollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
bit_buffer_set_size(instance->tx_buffer, 7);
|
||||
bit_buffer_set_byte(instance->tx_buffer, 0, 0x40);
|
||||
|
||||
NfcError error = nfc_poller_trx(
|
||||
instance->nfc, instance->tx_buffer, instance->rx_buffer, GEN1A_POLLER_MAX_FWT);
|
||||
|
||||
if(error != NfcErrorNone) {
|
||||
ret = gen1a_poller_process_nfc_error(error);
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_size(instance->rx_buffer) != 4) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_byte(instance->rx_buffer, 0) != 0x0A) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen1aPollerError gen1a_poller_data_access(Gen1aPoller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
Gen1aPollerError ret = Gen1aPollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
bit_buffer_set_size(instance->tx_buffer, 8);
|
||||
bit_buffer_set_byte(instance->tx_buffer, 0, 0x43);
|
||||
|
||||
NfcError error = nfc_poller_trx(
|
||||
instance->nfc, instance->tx_buffer, instance->rx_buffer, GEN1A_POLLER_MAX_FWT);
|
||||
|
||||
if(error != NfcErrorNone) {
|
||||
ret = gen1a_poller_process_nfc_error(error);
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_size(instance->rx_buffer) != 4) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_byte(instance->rx_buffer, 0) != 0x0A) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen1aPollerError gen1a_poller_write_block(
|
||||
Gen1aPoller* instance,
|
||||
uint8_t block_num,
|
||||
const MfClassicBlock* block) {
|
||||
furi_assert(instance);
|
||||
furi_assert(block);
|
||||
|
||||
Gen1aPollerError ret = Gen1aPollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
bit_buffer_append_byte(instance->tx_buffer, 0xA0);
|
||||
bit_buffer_append_byte(instance->tx_buffer, block_num);
|
||||
iso14443_crc_append(Iso14443CrcTypeA, instance->tx_buffer);
|
||||
|
||||
NfcError error = nfc_poller_trx(
|
||||
instance->nfc, instance->tx_buffer, instance->rx_buffer, GEN1A_POLLER_MAX_FWT);
|
||||
|
||||
if(error != NfcErrorNone) {
|
||||
ret = gen1a_poller_process_nfc_error(error);
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_size(instance->rx_buffer) != 4) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_byte(instance->rx_buffer, 0) != 0x0A) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
bit_buffer_copy_bytes(instance->tx_buffer, block->data, sizeof(MfClassicBlock));
|
||||
iso14443_crc_append(Iso14443CrcTypeA, instance->tx_buffer);
|
||||
|
||||
error = nfc_poller_trx(
|
||||
instance->nfc, instance->tx_buffer, instance->rx_buffer, GEN1A_POLLER_MAX_FWT);
|
||||
|
||||
if(error != NfcErrorNone) {
|
||||
ret = gen1a_poller_process_nfc_error(error);
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_size(instance->rx_buffer) != 4) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
if(bit_buffer_get_byte(instance->rx_buffer, 0) != 0x0A) {
|
||||
ret = Gen1aPollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
67
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller_i.h
vendored
Normal file
67
applications/external/nfc_magic/lib/magic/protocols/gen1a/gen1a_poller_i.h
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "gen1a_poller.h"
|
||||
#include <nfc/protocols/nfc_generic_event.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GEN1A_POLLER_MAX_BUFFER_SIZE (64U)
|
||||
#define GEN1A_POLLER_MAX_FWT (60000U)
|
||||
|
||||
typedef enum {
|
||||
Gen1aPollerErrorNone,
|
||||
Gen1aPollerErrorTimeout,
|
||||
Gen1aPollerErrorNotPresent,
|
||||
Gen1aPollerErrorProtocol,
|
||||
} Gen1aPollerError;
|
||||
|
||||
typedef enum {
|
||||
Gen1aPollerStateIdle,
|
||||
Gen1aPollerStateRequestMode,
|
||||
Gen1aPollerStateWipe,
|
||||
Gen1aPollerStateWriteDataRequest,
|
||||
Gen1aPollerStateWrite,
|
||||
Gen1aPollerStateSuccess,
|
||||
Gen1aPollerStateFail,
|
||||
|
||||
Gen1aPollerStateNum,
|
||||
} Gen1aPollerState;
|
||||
|
||||
typedef enum {
|
||||
Gen1aPollerSessionStateIdle,
|
||||
Gen1aPollerSessionStateStarted,
|
||||
Gen1aPollerSessionStateStopRequest,
|
||||
} Gen1aPollerSessionState;
|
||||
|
||||
struct Gen1aPoller {
|
||||
Nfc* nfc;
|
||||
Gen1aPollerState state;
|
||||
Gen1aPollerSessionState session_state;
|
||||
|
||||
uint16_t current_block;
|
||||
NfcDevice* mfc_device;
|
||||
|
||||
BitBuffer* tx_buffer;
|
||||
BitBuffer* rx_buffer;
|
||||
|
||||
Gen1aPollerEvent gen1a_event;
|
||||
Gen1aPollerEventData gen1a_event_data;
|
||||
|
||||
Gen1aPollerCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
Gen1aPollerError gen1a_poller_wupa(Gen1aPoller* instance);
|
||||
|
||||
Gen1aPollerError gen1a_poller_data_access(Gen1aPoller* instance);
|
||||
|
||||
Gen1aPollerError
|
||||
gen1a_poller_write_block(Gen1aPoller* instance, uint8_t block_num, const MfClassicBlock* block);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
533
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller.c
vendored
Normal file
533
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller.c
vendored
Normal file
@@ -0,0 +1,533 @@
|
||||
#include "gen4_poller_i.h"
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/nfc_poller.h>
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
#define GEN4_POLLER_THREAD_FLAG_DETECTED (1U << 0)
|
||||
|
||||
typedef NfcCommand (*Gen4PollerStateHandler)(Gen4Poller* instance);
|
||||
|
||||
typedef struct {
|
||||
NfcPoller* poller;
|
||||
uint32_t password;
|
||||
BitBuffer* tx_buffer;
|
||||
BitBuffer* rx_buffer;
|
||||
FuriThreadId thread_id;
|
||||
Gen4PollerError error;
|
||||
} Gen4PollerDetectContext;
|
||||
|
||||
static const uint8_t gen4_poller_default_config[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA,
|
||||
0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00};
|
||||
static const uint8_t gen4_poller_default_block_0[GEN4_POLLER_BLOCK_SIZE] =
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static const uint8_t gen4_poller_default_empty_block[GEN4_POLLER_BLOCK_SIZE] = {0};
|
||||
|
||||
static const uint8_t gen4_poller_default_sector_trailer_block[GEN4_POLLER_BLOCK_SIZE] =
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
static bool gen4_poller_is_sector_trailer(uint8_t block_num) {
|
||||
uint8_t sec_tr_block_num = 0;
|
||||
|
||||
if(block_num < 128) {
|
||||
sec_tr_block_num = block_num | 0x03;
|
||||
} else {
|
||||
sec_tr_block_num = block_num | 0x0f;
|
||||
}
|
||||
|
||||
return block_num == sec_tr_block_num;
|
||||
}
|
||||
|
||||
Gen4Poller* gen4_poller_alloc(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
|
||||
Gen4Poller* instance = malloc(sizeof(Gen4Poller));
|
||||
instance->poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a);
|
||||
|
||||
instance->gen4_event.data = &instance->gen4_event_data;
|
||||
|
||||
instance->tx_buffer = bit_buffer_alloc(GEN4_POLLER_MAX_BUFFER_SIZE);
|
||||
instance->rx_buffer = bit_buffer_alloc(GEN4_POLLER_MAX_BUFFER_SIZE);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void gen4_poller_free(Gen4Poller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
nfc_poller_free(instance->poller);
|
||||
|
||||
bit_buffer_free(instance->tx_buffer);
|
||||
bit_buffer_free(instance->rx_buffer);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void gen4_poller_set_password(Gen4Poller* instance, uint32_t password) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->password = password;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_detect_callback(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3a);
|
||||
furi_assert(event.instance);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcCommand command = NfcCommandStop;
|
||||
Gen4PollerDetectContext* gen4_poller_detect_ctx = context;
|
||||
Iso14443_3aPoller* iso3_poller = event.instance;
|
||||
Iso14443_3aPollerEvent* iso3_event = event.event_data;
|
||||
gen4_poller_detect_ctx->error = Gen4PollerErrorTimeout;
|
||||
|
||||
if(iso3_event->type == Iso14443_3aPollerEventTypeReady) {
|
||||
do {
|
||||
bit_buffer_append_byte(gen4_poller_detect_ctx->tx_buffer, GEN4_CMD_PREFIX);
|
||||
uint8_t pwd_arr[4] = {};
|
||||
nfc_util_num2bytes(gen4_poller_detect_ctx->password, COUNT_OF(pwd_arr), pwd_arr);
|
||||
bit_buffer_append_bytes(gen4_poller_detect_ctx->tx_buffer, pwd_arr, COUNT_OF(pwd_arr));
|
||||
bit_buffer_append_byte(gen4_poller_detect_ctx->tx_buffer, GEN4_CMD_GET_CFG);
|
||||
|
||||
Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
|
||||
iso3_poller,
|
||||
gen4_poller_detect_ctx->tx_buffer,
|
||||
gen4_poller_detect_ctx->rx_buffer,
|
||||
GEN4_POLLER_MAX_FWT);
|
||||
|
||||
if(error != Iso14443_3aErrorNone) {
|
||||
gen4_poller_detect_ctx->error = Gen4PollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
size_t rx_bytes = bit_buffer_get_size_bytes(gen4_poller_detect_ctx->rx_buffer);
|
||||
if((rx_bytes != 30) && (rx_bytes != 32)) {
|
||||
gen4_poller_detect_ctx->error = Gen4PollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
gen4_poller_detect_ctx->error = Gen4PollerErrorNone;
|
||||
} while(false);
|
||||
} else if(iso3_event->type == Iso14443_3aPollerEventTypeError) {
|
||||
gen4_poller_detect_ctx->error = Gen4PollerErrorTimeout;
|
||||
}
|
||||
furi_thread_flags_set(gen4_poller_detect_ctx->thread_id, GEN4_POLLER_THREAD_FLAG_DETECTED);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
Gen4PollerError gen4_poller_detect(Nfc* nfc, uint32_t password) {
|
||||
furi_assert(nfc);
|
||||
|
||||
Gen4PollerDetectContext gen4_poller_detect_ctx = {};
|
||||
gen4_poller_detect_ctx.poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a);
|
||||
gen4_poller_detect_ctx.password = password;
|
||||
gen4_poller_detect_ctx.tx_buffer = bit_buffer_alloc(GEN4_POLLER_MAX_BUFFER_SIZE);
|
||||
gen4_poller_detect_ctx.rx_buffer = bit_buffer_alloc(GEN4_POLLER_MAX_BUFFER_SIZE);
|
||||
gen4_poller_detect_ctx.thread_id = furi_thread_get_current_id();
|
||||
gen4_poller_detect_ctx.error = Gen4PollerErrorNone;
|
||||
|
||||
nfc_poller_start(
|
||||
gen4_poller_detect_ctx.poller, gen4_poller_detect_callback, &gen4_poller_detect_ctx);
|
||||
uint32_t flags =
|
||||
furi_thread_flags_wait(GEN4_POLLER_THREAD_FLAG_DETECTED, FuriFlagWaitAny, FuriWaitForever);
|
||||
if(flags & GEN4_POLLER_THREAD_FLAG_DETECTED) {
|
||||
furi_thread_flags_clear(GEN4_POLLER_THREAD_FLAG_DETECTED);
|
||||
}
|
||||
nfc_poller_stop(gen4_poller_detect_ctx.poller);
|
||||
|
||||
nfc_poller_free(gen4_poller_detect_ctx.poller);
|
||||
bit_buffer_free(gen4_poller_detect_ctx.tx_buffer);
|
||||
bit_buffer_free(gen4_poller_detect_ctx.rx_buffer);
|
||||
|
||||
return gen4_poller_detect_ctx.error;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_idle_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->current_block = 0;
|
||||
memset(instance->config, 0, sizeof(instance->config));
|
||||
instance->gen4_event.type = Gen4PollerEventTypeCardDetected;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
instance->state = Gen4PollerStateRequestMode;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_request_mode_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen4_event.type = Gen4PollerEventTypeRequestMode;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeWipe) {
|
||||
instance->state = Gen4PollerStateWipe;
|
||||
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeWrite) {
|
||||
instance->state = Gen4PollerStateRequestWriteData;
|
||||
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeSetPassword) {
|
||||
instance->state = Gen4PollerStateChangePassword;
|
||||
} else {
|
||||
instance->state = Gen4PollerStateFail;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_wipe_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
do {
|
||||
Gen4PollerError error = Gen4PollerErrorNone;
|
||||
if(instance->current_block == 0) {
|
||||
error = gen4_poller_set_config(
|
||||
instance,
|
||||
instance->password,
|
||||
gen4_poller_default_config,
|
||||
sizeof(gen4_poller_default_config),
|
||||
false);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to set default config: %d", error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
error = gen4_poller_write_block(
|
||||
instance, instance->password, instance->current_block, gen4_poller_default_block_0);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write 0 block: %d", error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
} else if(instance->current_block < GEN4_POLLER_BLOCKS_TOTAL) {
|
||||
const uint8_t* block = gen4_poller_is_sector_trailer(instance->current_block) ?
|
||||
gen4_poller_default_sector_trailer_block :
|
||||
gen4_poller_default_empty_block;
|
||||
error = gen4_poller_write_block(
|
||||
instance, instance->password, instance->current_block, block);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write %d block: %d", instance->current_block, error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
instance->state = Gen4PollerStateSuccess;
|
||||
break;
|
||||
}
|
||||
instance->current_block++;
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_request_write_data_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen4_event.type = Gen4PollerEventTypeRequestDataToWrite;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
instance->protocol = instance->gen4_event_data.request_data.protocol;
|
||||
instance->data = instance->gen4_event_data.request_data.data;
|
||||
|
||||
if((instance->protocol == NfcProtocolMfClassic) ||
|
||||
(instance->protocol == NfcProtocolMfUltralight)) {
|
||||
instance->state = Gen4PollerStateWrite;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsupported protocol");
|
||||
instance->state = Gen4PollerStateFail;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static NfcCommand gen4_poller_write_mf_classic(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
do {
|
||||
const MfClassicData* mfc_data = instance->data;
|
||||
const Iso14443_3aData* iso3_data = mfc_data->iso14443_3a_data;
|
||||
if(instance->current_block == 0) {
|
||||
instance->config[0] = 0x00;
|
||||
instance->total_blocks = mf_classic_get_total_block_num(mfc_data->type);
|
||||
|
||||
if(iso3_data->uid_len == 4) {
|
||||
instance->config[1] = Gen4PollerUIDLengthSingle;
|
||||
} else if(iso3_data->uid_len == 7) {
|
||||
instance->config[1] = Gen4PollerUIDLengthDouble;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsupported UID len: %d", iso3_data->uid_len);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->config[6] = Gen4PollerShadowModeIgnore;
|
||||
instance->config[24] = iso3_data->atqa[0];
|
||||
instance->config[25] = iso3_data->atqa[1];
|
||||
instance->config[26] = iso3_data->sak;
|
||||
instance->config[27] = 0x00;
|
||||
instance->config[28] = instance->total_blocks;
|
||||
instance->config[29] = 0x01;
|
||||
|
||||
Gen4PollerError error = gen4_poller_set_config(
|
||||
instance, instance->password, instance->config, sizeof(instance->config), false);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write config: %d", error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(instance->current_block < instance->total_blocks) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", instance->current_block);
|
||||
Gen4PollerError error = gen4_poller_write_block(
|
||||
instance,
|
||||
instance->password,
|
||||
instance->current_block,
|
||||
mfc_data->block[instance->current_block].data);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write %d block: %d", instance->current_block, error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
instance->state = Gen4PollerStateSuccess;
|
||||
break;
|
||||
}
|
||||
instance->current_block++;
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static NfcCommand gen4_poller_write_mf_ultralight(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
do {
|
||||
const MfUltralightData* mfu_data = instance->data;
|
||||
const Iso14443_3aData* iso3_data = mfu_data->iso14443_3a_data;
|
||||
if(instance->current_block == 0) {
|
||||
instance->total_blocks = 64;
|
||||
instance->config[0] = 0x01;
|
||||
switch(mfu_data->type) {
|
||||
case MfUltralightTypeNTAG203:
|
||||
case MfUltralightTypeNTAG213:
|
||||
case MfUltralightTypeNTAG215:
|
||||
case MfUltralightTypeNTAG216:
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
instance->config[27] = Gen4PollerUltralightModeNTAG;
|
||||
instance->total_blocks = 64 * 2;
|
||||
break;
|
||||
|
||||
case MfUltralightTypeUL11:
|
||||
case MfUltralightTypeUL21:
|
||||
// UL-C?
|
||||
// UL?
|
||||
default:
|
||||
instance->config[27] = Gen4PollerUltralightModeUL_EV1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(iso3_data->uid_len == 4) {
|
||||
instance->config[1] = Gen4PollerUIDLengthSingle;
|
||||
} else if(iso3_data->uid_len == 7) {
|
||||
instance->config[1] = Gen4PollerUIDLengthDouble;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsupported UID len: %d", iso3_data->uid_len);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->config[6] = Gen4PollerShadowModeHighSpeedIgnore;
|
||||
instance->config[24] = iso3_data->atqa[0];
|
||||
instance->config[25] = iso3_data->atqa[1];
|
||||
instance->config[26] = iso3_data->sak;
|
||||
instance->config[27] = 0x00;
|
||||
instance->config[28] = instance->total_blocks;
|
||||
instance->config[29] = 0x01;
|
||||
|
||||
Gen4PollerError error = gen4_poller_set_config(
|
||||
instance, instance->password, instance->config, sizeof(instance->config), false);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write config: %d", error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(instance->current_block < mfu_data->pages_read) {
|
||||
FURI_LOG_D(
|
||||
TAG, "Writing page %zu / %zu", instance->current_block, mfu_data->pages_read);
|
||||
Gen4PollerError error = gen4_poller_write_block(
|
||||
instance,
|
||||
instance->password,
|
||||
instance->current_block,
|
||||
mfu_data->page[instance->current_block].data);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to write %d page: %d", instance->current_block, error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
instance->current_block++;
|
||||
} else {
|
||||
uint8_t block[GEN4_POLLER_BLOCK_SIZE] = {};
|
||||
bool write_success = true;
|
||||
for(size_t i = 0; i < 8; i++) {
|
||||
memcpy(block, &mfu_data->signature.data[i * 4], 4); //-V1086
|
||||
Gen4PollerError error =
|
||||
gen4_poller_write_block(instance, instance->password, 0xF2 + i, block);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
write_success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!write_success) {
|
||||
FURI_LOG_E(TAG, "Failed to write Signature");
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
block[0] = mfu_data->version.header;
|
||||
block[1] = mfu_data->version.vendor_id;
|
||||
block[2] = mfu_data->version.prod_type;
|
||||
block[3] = mfu_data->version.prod_subtype;
|
||||
Gen4PollerError error =
|
||||
gen4_poller_write_block(instance, instance->password, 0xFA, block);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_E(TAG, "Failed to write 1st part Version");
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
block[0] = mfu_data->version.prod_ver_major;
|
||||
block[1] = mfu_data->version.prod_ver_minor;
|
||||
block[2] = mfu_data->version.storage_size;
|
||||
block[3] = mfu_data->version.protocol_type;
|
||||
error = gen4_poller_write_block(instance, instance->password, 0xFB, block);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_E(TAG, "Failed to write 2nd part Version");
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->state = Gen4PollerStateSuccess;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_write_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
memcpy(instance->config, gen4_poller_default_config, sizeof(gen4_poller_default_config));
|
||||
uint8_t password_arr[4] = {};
|
||||
nfc_util_num2bytes(instance->password, sizeof(password_arr), password_arr);
|
||||
memcpy(&instance->config[2], password_arr, sizeof(password_arr));
|
||||
memset(&instance->config[7], 0, 17);
|
||||
if(instance->protocol == NfcProtocolMfClassic) {
|
||||
command = gen4_poller_write_mf_classic(instance);
|
||||
} else if(instance->protocol == NfcProtocolMfUltralight) {
|
||||
command = gen4_poller_write_mf_ultralight(instance);
|
||||
} else {
|
||||
furi_crash("Unsupported protocol to write");
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_change_password_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
do {
|
||||
instance->gen4_event.type = Gen4PollerEventTypeRequestNewPassword;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
if(command != NfcCommandContinue) break;
|
||||
|
||||
uint32_t new_password = instance->gen4_event_data.request_password.password;
|
||||
Gen4PollerError error =
|
||||
gen4_poller_change_password(instance, instance->password, new_password);
|
||||
if(error != Gen4PollerErrorNone) {
|
||||
FURI_LOG_E(TAG, "Failed to change password: %d", error);
|
||||
instance->state = Gen4PollerStateFail;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->password = new_password;
|
||||
instance->state = Gen4PollerStateSuccess;
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_success_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen4_event.type = Gen4PollerEventTypeSuccess;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
if(command != NfcCommandStop) {
|
||||
furi_delay_ms(100);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand gen4_poller_fail_handler(Gen4Poller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->gen4_event.type = Gen4PollerEventTypeFail;
|
||||
command = instance->callback(instance->gen4_event, instance->context);
|
||||
if(command != NfcCommandStop) {
|
||||
furi_delay_ms(100);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static const Gen4PollerStateHandler gen4_poller_state_handlers[Gen4PollerStateNum] = {
|
||||
[Gen4PollerStateIdle] = gen4_poller_idle_handler,
|
||||
[Gen4PollerStateRequestMode] = gen4_poller_request_mode_handler,
|
||||
[Gen4PollerStateRequestWriteData] = gen4_poller_request_write_data_handler,
|
||||
[Gen4PollerStateWrite] = gen4_poller_write_handler,
|
||||
[Gen4PollerStateWipe] = gen4_poller_wipe_handler,
|
||||
[Gen4PollerStateChangePassword] = gen4_poller_change_password_handler,
|
||||
[Gen4PollerStateSuccess] = gen4_poller_success_handler,
|
||||
[Gen4PollerStateFail] = gen4_poller_fail_handler,
|
||||
|
||||
};
|
||||
|
||||
static NfcCommand gen4_poller_callback(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3a);
|
||||
furi_assert(event.event_data);
|
||||
furi_assert(event.instance);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
Gen4Poller* instance = context;
|
||||
instance->iso3_poller = event.instance;
|
||||
Iso14443_3aPollerEvent* iso3_event = event.event_data;
|
||||
|
||||
if(iso3_event->type == Iso14443_3aPollerEventTypeReady) {
|
||||
command = gen4_poller_state_handlers[instance->state](instance);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
void gen4_poller_start(Gen4Poller* instance, Gen4PollerCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
|
||||
nfc_poller_start(instance->poller, gen4_poller_callback, instance);
|
||||
}
|
||||
|
||||
void gen4_poller_stop(Gen4Poller* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
nfc_poller_stop(instance->poller);
|
||||
}
|
||||
84
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller.h
vendored
Normal file
84
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller.h
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/protocols/nfc_protocol.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GEN4_CMD_PREFIX (0xCF)
|
||||
#define GEN4_CMD_GET_CFG (0xC6)
|
||||
#define GEN4_CMD_WRITE (0xCD)
|
||||
#define GEN4_CMD_READ (0xCE)
|
||||
#define GEN4_CMD_SET_CFG (0xF0)
|
||||
#define GEN4_CMD_FUSE_CFG (0xF1)
|
||||
#define GEN4_CMD_SET_PWD (0xFE)
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerErrorNone,
|
||||
Gen4PollerErrorTimeout,
|
||||
Gen4PollerErrorProtocol,
|
||||
} Gen4PollerError;
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerEventTypeCardDetected,
|
||||
Gen4PollerEventTypeRequestMode,
|
||||
Gen4PollerEventTypeRequestDataToWrite,
|
||||
Gen4PollerEventTypeRequestNewPassword,
|
||||
|
||||
Gen4PollerEventTypeSuccess,
|
||||
Gen4PollerEventTypeFail,
|
||||
} Gen4PollerEventType;
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerModeWipe,
|
||||
Gen4PollerModeWrite,
|
||||
Gen4PollerModeSetPassword,
|
||||
} Gen4PollerMode;
|
||||
|
||||
typedef struct {
|
||||
Gen4PollerMode mode;
|
||||
} Gen4PollerEventDataRequestMode;
|
||||
|
||||
typedef struct {
|
||||
NfcProtocol protocol;
|
||||
const NfcDeviceData* data;
|
||||
} Gen4PollerEventDataRequestDataToWrite;
|
||||
|
||||
typedef struct {
|
||||
uint32_t password;
|
||||
} Gen4PollerEventDataRequestNewPassword;
|
||||
|
||||
typedef union {
|
||||
Gen4PollerEventDataRequestMode request_mode;
|
||||
Gen4PollerEventDataRequestDataToWrite request_data;
|
||||
Gen4PollerEventDataRequestNewPassword request_password;
|
||||
} Gen4PollerEventData;
|
||||
|
||||
typedef struct {
|
||||
Gen4PollerEventType type;
|
||||
Gen4PollerEventData* data;
|
||||
} Gen4PollerEvent;
|
||||
|
||||
typedef NfcCommand (*Gen4PollerCallback)(Gen4PollerEvent event, void* context);
|
||||
|
||||
typedef struct Gen4Poller Gen4Poller;
|
||||
|
||||
Gen4PollerError gen4_poller_detect(Nfc* nfc, uint32_t password);
|
||||
|
||||
Gen4Poller* gen4_poller_alloc(Nfc* nfc);
|
||||
|
||||
void gen4_poller_free(Gen4Poller* instance);
|
||||
|
||||
void gen4_poller_set_password(Gen4Poller* instance, uint32_t password);
|
||||
|
||||
void gen4_poller_start(Gen4Poller* instance, Gen4PollerCallback callback, void* context);
|
||||
|
||||
void gen4_poller_stop(Gen4Poller* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
129
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.c
vendored
Normal file
129
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.c
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "gen4_poller_i.h"
|
||||
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
|
||||
#define GEN4_CMD_PREFIX (0xCF)
|
||||
|
||||
#define GEN4_CMD_GET_CFG (0xC6)
|
||||
#define GEN4_CMD_WRITE (0xCD)
|
||||
#define GEN4_CMD_READ (0xCE)
|
||||
#define GEN4_CMD_SET_CFG (0xF0)
|
||||
#define GEN4_CMD_FUSE_CFG (0xF1)
|
||||
#define GEN4_CMD_SET_PWD (0xFE)
|
||||
|
||||
static Gen4PollerError gen4_poller_process_error(Iso14443_3aError error) {
|
||||
Gen4PollerError ret = Gen4PollerErrorNone;
|
||||
|
||||
if(error == Iso14443_3aErrorNone) {
|
||||
ret = Gen4PollerErrorNone;
|
||||
} else {
|
||||
ret = Gen4PollerErrorTimeout;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen4PollerError gen4_poller_set_config(
|
||||
Gen4Poller* instance,
|
||||
uint32_t password,
|
||||
const uint8_t* config,
|
||||
size_t config_size,
|
||||
bool fuse) {
|
||||
Gen4PollerError ret = Gen4PollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
uint8_t password_arr[4] = {};
|
||||
nfc_util_num2bytes(password, COUNT_OF(password_arr), password_arr);
|
||||
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_PREFIX);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
|
||||
uint8_t fuse_config = fuse ? GEN4_CMD_FUSE_CFG : GEN4_CMD_SET_CFG;
|
||||
bit_buffer_append_byte(instance->tx_buffer, fuse_config);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, config, config_size);
|
||||
|
||||
Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
|
||||
instance->iso3_poller, instance->tx_buffer, instance->rx_buffer, GEN4_POLLER_MAX_FWT);
|
||||
|
||||
if(error != Iso14443_3aErrorNone) {
|
||||
ret = gen4_poller_process_error(error);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t rx_bytes = bit_buffer_get_size_bytes(instance->rx_buffer);
|
||||
if(rx_bytes != 2) {
|
||||
ret = Gen4PollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen4PollerError gen4_poller_write_block(
|
||||
Gen4Poller* instance,
|
||||
uint32_t password,
|
||||
uint8_t block_num,
|
||||
const uint8_t* data) {
|
||||
Gen4PollerError ret = Gen4PollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
uint8_t password_arr[4] = {};
|
||||
nfc_util_num2bytes(password, COUNT_OF(password_arr), password_arr);
|
||||
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_PREFIX);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
|
||||
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_WRITE);
|
||||
bit_buffer_append_byte(instance->tx_buffer, block_num);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, data, GEN4_POLLER_BLOCK_SIZE);
|
||||
|
||||
Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
|
||||
instance->iso3_poller, instance->tx_buffer, instance->rx_buffer, GEN4_POLLER_MAX_FWT);
|
||||
|
||||
if(error != Iso14443_3aErrorNone) {
|
||||
ret = gen4_poller_process_error(error);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t rx_bytes = bit_buffer_get_size_bytes(instance->rx_buffer);
|
||||
if(rx_bytes != 2) {
|
||||
ret = Gen4PollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Gen4PollerError
|
||||
gen4_poller_change_password(Gen4Poller* instance, uint32_t pwd_current, uint32_t pwd_new) {
|
||||
Gen4PollerError ret = Gen4PollerErrorNone;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
|
||||
do {
|
||||
uint8_t password_arr[4] = {};
|
||||
nfc_util_num2bytes(pwd_current, COUNT_OF(password_arr), password_arr);
|
||||
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_PREFIX);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
|
||||
|
||||
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_SET_PWD);
|
||||
nfc_util_num2bytes(pwd_new, COUNT_OF(password_arr), password_arr);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
|
||||
|
||||
Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
|
||||
instance->iso3_poller, instance->tx_buffer, instance->rx_buffer, GEN4_POLLER_MAX_FWT);
|
||||
|
||||
if(error != Iso14443_3aErrorNone) {
|
||||
ret = gen4_poller_process_error(error);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t rx_bytes = bit_buffer_get_size_bytes(instance->rx_buffer);
|
||||
if(rx_bytes != 2) {
|
||||
ret = Gen4PollerErrorProtocol;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
101
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.h
vendored
Normal file
101
applications/external/nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
|
||||
#include "gen4_poller.h"
|
||||
#include <nfc/nfc_poller.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
|
||||
|
||||
#define TAG "Gen4Poller"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GEN4_POLLER_MAX_BUFFER_SIZE (64U)
|
||||
#define GEN4_POLLER_MAX_FWT (200000U)
|
||||
|
||||
#define GEN4_POLLER_BLOCK_SIZE (16)
|
||||
#define GEN4_POLLER_BLOCKS_TOTAL (256)
|
||||
|
||||
#define GEN4_POLLER_CONFIG_SIZE_MAX (30)
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerUIDLengthSingle = 0x00,
|
||||
Gen4PollerUIDLengthDouble = 0x01,
|
||||
Gen4PollerUIDLengthTriple = 0x02
|
||||
} Gen4PollerUIDLength;
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerUltralightModeUL_EV1 = 0x00,
|
||||
Gen4PollerUltralightModeNTAG = 0x01,
|
||||
Gen4PollerUltralightModeUL_C = 0x02,
|
||||
Gen4PollerUltralightModeUL = 0x03
|
||||
} Gen4PollerUltralightMode;
|
||||
|
||||
typedef enum {
|
||||
// for writing original (shadow) data
|
||||
Gen4PollerShadowModePreWrite = 0x00,
|
||||
// written data can be read once before restored to original
|
||||
Gen4PollerShadowModeRestore = 0x01,
|
||||
// written data is discarded
|
||||
Gen4PollerShadowModeIgnore = 0x02,
|
||||
// apparently for UL?
|
||||
Gen4PollerShadowModeHighSpeedIgnore = 0x03
|
||||
} Gen4PollerShadowMode;
|
||||
|
||||
typedef enum {
|
||||
Gen4PollerStateIdle,
|
||||
Gen4PollerStateRequestMode,
|
||||
Gen4PollerStateRequestWriteData,
|
||||
Gen4PollerStateWrite,
|
||||
Gen4PollerStateWipe,
|
||||
Gen4PollerStateChangePassword,
|
||||
Gen4PollerStateSuccess,
|
||||
Gen4PollerStateFail,
|
||||
|
||||
Gen4PollerStateNum,
|
||||
} Gen4PollerState;
|
||||
|
||||
struct Gen4Poller {
|
||||
NfcPoller* poller;
|
||||
Iso14443_3aPoller* iso3_poller;
|
||||
Gen4PollerState state;
|
||||
uint32_t password;
|
||||
|
||||
BitBuffer* tx_buffer;
|
||||
BitBuffer* rx_buffer;
|
||||
|
||||
uint16_t current_block;
|
||||
uint16_t total_blocks;
|
||||
|
||||
NfcProtocol protocol;
|
||||
const NfcDeviceData* data;
|
||||
uint32_t new_password;
|
||||
|
||||
uint8_t config[GEN4_POLLER_CONFIG_SIZE_MAX];
|
||||
|
||||
Gen4PollerEvent gen4_event;
|
||||
Gen4PollerEventData gen4_event_data;
|
||||
|
||||
Gen4PollerCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
Gen4PollerError gen4_poller_set_config(
|
||||
Gen4Poller* instance,
|
||||
uint32_t password,
|
||||
const uint8_t* config,
|
||||
size_t config_size,
|
||||
bool fuse);
|
||||
|
||||
Gen4PollerError gen4_poller_write_block(
|
||||
Gen4Poller* instance,
|
||||
uint32_t password,
|
||||
uint8_t block_num,
|
||||
const uint8_t* data);
|
||||
|
||||
Gen4PollerError
|
||||
gen4_poller_change_password(Gen4Poller* instance, uint32_t pwd_current, uint32_t pwd_new);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
14
applications/external/nfc_magic/lib/magic/protocols/nfc_magic_protocols.c
vendored
Normal file
14
applications/external/nfc_magic/lib/magic/protocols/nfc_magic_protocols.c
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "nfc_magic_protocols.h"
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
static const char* nfc_magic_protocol_names[NfcMagicProtocolNum] = {
|
||||
[NfcMagicProtocolGen1] = "Classic Gen 1A/B",
|
||||
[NfcMagicProtocolGen4] = "Gen 4 GTU",
|
||||
};
|
||||
|
||||
const char* nfc_magic_protocols_get_name(NfcMagicProtocol protocol) {
|
||||
furi_assert(protocol < NfcMagicProtocolNum);
|
||||
|
||||
return nfc_magic_protocol_names[protocol];
|
||||
}
|
||||
19
applications/external/nfc_magic/lib/magic/protocols/nfc_magic_protocols.h
vendored
Normal file
19
applications/external/nfc_magic/lib/magic/protocols/nfc_magic_protocols.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NfcMagicProtocolGen1,
|
||||
NfcMagicProtocolGen4,
|
||||
|
||||
NfcMagicProtocolNum,
|
||||
NfcMagicProtocolInvalid,
|
||||
} NfcMagicProtocol;
|
||||
|
||||
const char* nfc_magic_protocols_get_name(NfcMagicProtocol protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
#include "types.h"
|
||||
|
||||
const char* nfc_magic_type(MagicType type) {
|
||||
if(type == MagicTypeClassicGen1) {
|
||||
return "Classic Gen 1A/B";
|
||||
} else if(type == MagicTypeClassicDirectWrite) {
|
||||
return "Classic DirectWrite";
|
||||
} else if(type == MagicTypeClassicAPDU) {
|
||||
return "Classic APDU";
|
||||
} else if(type == MagicTypeUltralightGen1) {
|
||||
return "Ultralight Gen 1";
|
||||
} else if(type == MagicTypeUltralightDirectWrite) {
|
||||
return "Ultralight DirectWrite";
|
||||
} else if(type == MagicTypeUltralightC_Gen1) {
|
||||
return "Ultralight-C Gen 1";
|
||||
} else if(type == MagicTypeUltralightC_DirectWrite) {
|
||||
return "Ultralight-C DirectWrite";
|
||||
} else if(type == MagicTypeGen4) {
|
||||
return "Gen 4 GTU";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
const char* nfc_magic_type(MagicType type);
|
||||
183
applications/external/nfc_magic/nfc_magic.c
vendored
183
applications/external/nfc_magic/nfc_magic.c
vendored
@@ -1,183 +0,0 @@
|
||||
#include "nfc_magic_i.h"
|
||||
|
||||
bool nfc_magic_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
NfcMagic* nfc_magic = context;
|
||||
return scene_manager_handle_custom_event(nfc_magic->scene_manager, event);
|
||||
}
|
||||
|
||||
bool nfc_magic_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
NfcMagic* nfc_magic = context;
|
||||
return scene_manager_handle_back_event(nfc_magic->scene_manager);
|
||||
}
|
||||
|
||||
void nfc_magic_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
NfcMagic* nfc_magic = context;
|
||||
scene_manager_handle_tick_event(nfc_magic->scene_manager);
|
||||
}
|
||||
|
||||
void nfc_magic_show_loading_popup(void* context, bool show) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
if(show) {
|
||||
// Raise timer priority so that animations can play
|
||||
furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
|
||||
} else {
|
||||
// Restore default timer priority
|
||||
furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
|
||||
}
|
||||
}
|
||||
|
||||
NfcMagic* nfc_magic_alloc() {
|
||||
NfcMagic* nfc_magic = malloc(sizeof(NfcMagic));
|
||||
|
||||
nfc_magic->worker = nfc_magic_worker_alloc();
|
||||
nfc_magic->view_dispatcher = view_dispatcher_alloc();
|
||||
nfc_magic->scene_manager = scene_manager_alloc(&nfc_magic_scene_handlers, nfc_magic);
|
||||
view_dispatcher_enable_queue(nfc_magic->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(nfc_magic->view_dispatcher, nfc_magic);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
nfc_magic->view_dispatcher, nfc_magic_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
nfc_magic->view_dispatcher, nfc_magic_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100);
|
||||
|
||||
// Nfc device
|
||||
nfc_magic->dev = malloc(sizeof(NfcMagicDevice));
|
||||
nfc_magic->source_dev = nfc_device_alloc();
|
||||
furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER);
|
||||
|
||||
// Open GUI record
|
||||
nfc_magic->gui = furi_record_open(RECORD_GUI);
|
||||
view_dispatcher_attach_to_gui(
|
||||
nfc_magic->view_dispatcher, nfc_magic->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Open Notification record
|
||||
nfc_magic->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Submenu
|
||||
nfc_magic->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher, NfcMagicViewMenu, submenu_get_view(nfc_magic->submenu));
|
||||
|
||||
// Popup
|
||||
nfc_magic->popup = popup_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher, NfcMagicViewPopup, popup_get_view(nfc_magic->popup));
|
||||
|
||||
// Loading
|
||||
nfc_magic->loading = loading_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher, NfcMagicViewLoading, loading_get_view(nfc_magic->loading));
|
||||
|
||||
// Text Input
|
||||
nfc_magic->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher,
|
||||
NfcMagicViewTextInput,
|
||||
text_input_get_view(nfc_magic->text_input));
|
||||
|
||||
// Byte Input
|
||||
nfc_magic->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher,
|
||||
NfcMagicViewByteInput,
|
||||
byte_input_get_view(nfc_magic->byte_input));
|
||||
|
||||
// Custom Widget
|
||||
nfc_magic->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher, NfcMagicViewWidget, widget_get_view(nfc_magic->widget));
|
||||
|
||||
return nfc_magic;
|
||||
}
|
||||
|
||||
void nfc_magic_free(NfcMagic* nfc_magic) {
|
||||
furi_assert(nfc_magic);
|
||||
|
||||
// Nfc device
|
||||
free(nfc_magic->dev);
|
||||
nfc_device_free(nfc_magic->source_dev);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
submenu_free(nfc_magic->submenu);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
popup_free(nfc_magic->popup);
|
||||
|
||||
// Loading
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
|
||||
loading_free(nfc_magic->loading);
|
||||
|
||||
// Text Input
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput);
|
||||
text_input_free(nfc_magic->text_input);
|
||||
|
||||
// Byte Input
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
byte_input_free(nfc_magic->byte_input);
|
||||
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
widget_free(nfc_magic->widget);
|
||||
|
||||
// Worker
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
nfc_magic_worker_free(nfc_magic->worker);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(nfc_magic->view_dispatcher);
|
||||
|
||||
// Scene Manager
|
||||
scene_manager_free(nfc_magic->scene_manager);
|
||||
|
||||
// GUI
|
||||
furi_record_close(RECORD_GUI);
|
||||
nfc_magic->gui = NULL;
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
nfc_magic->notifications = NULL;
|
||||
|
||||
free(nfc_magic);
|
||||
}
|
||||
|
||||
static const NotificationSequence nfc_magic_sequence_blink_start_cyan = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_cyan,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence nfc_magic_sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void nfc_magic_blink_start(NfcMagic* nfc_magic) {
|
||||
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_cyan);
|
||||
}
|
||||
|
||||
void nfc_magic_blink_stop(NfcMagic* nfc_magic) {
|
||||
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_stop);
|
||||
}
|
||||
|
||||
int32_t nfc_magic_app(void* p) {
|
||||
UNUSED(p);
|
||||
NfcMagic* nfc_magic = nfc_magic_alloc();
|
||||
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
|
||||
view_dispatcher_run(nfc_magic->view_dispatcher);
|
||||
|
||||
magic_deactivate();
|
||||
nfc_magic_free(nfc_magic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
5
applications/external/nfc_magic/nfc_magic.h
vendored
5
applications/external/nfc_magic/nfc_magic.h
vendored
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct NfcMagicDevice NfcMagicDevice;
|
||||
|
||||
typedef struct NfcMagic NfcMagic;
|
||||
289
applications/external/nfc_magic/nfc_magic_app.c
vendored
Normal file
289
applications/external/nfc_magic/nfc_magic_app.c
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
#include "nfc_magic_app_i.h"
|
||||
|
||||
bool nfc_magic_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
return scene_manager_handle_custom_event(instance->scene_manager, event);
|
||||
}
|
||||
|
||||
bool nfc_magic_app_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
return scene_manager_handle_back_event(instance->scene_manager);
|
||||
}
|
||||
|
||||
void nfc_magic_app_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
scene_manager_handle_tick_event(instance->scene_manager);
|
||||
}
|
||||
|
||||
void nfc_magic_app_show_loading_popup(void* context, bool show) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
if(show) {
|
||||
// Raise timer priority so that animations can play
|
||||
furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewLoading);
|
||||
} else {
|
||||
// Restore default timer priority
|
||||
furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
|
||||
}
|
||||
}
|
||||
|
||||
NfcMagicApp* nfc_magic_app_alloc() {
|
||||
NfcMagicApp* instance = malloc(sizeof(NfcMagicApp));
|
||||
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
instance->scene_manager = scene_manager_alloc(&nfc_magic_scene_handlers, instance);
|
||||
view_dispatcher_enable_queue(instance->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
instance->view_dispatcher, nfc_magic_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
instance->view_dispatcher, nfc_magic_app_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
instance->view_dispatcher, nfc_magic_app_tick_event_callback, 100);
|
||||
|
||||
// Nfc device
|
||||
instance->source_dev = nfc_device_alloc();
|
||||
nfc_device_set_loading_callback(
|
||||
instance->source_dev, nfc_magic_app_show_loading_popup, instance);
|
||||
instance->file_path = furi_string_alloc_set(NFC_APP_FOLDER);
|
||||
instance->file_name = furi_string_alloc();
|
||||
|
||||
// Open GUI record
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
view_dispatcher_attach_to_gui(
|
||||
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Open Notification record
|
||||
instance->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Open Dialogs
|
||||
instance->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
// Open Storage
|
||||
instance->storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
// Submenu
|
||||
instance->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher, NfcMagicAppViewMenu, submenu_get_view(instance->submenu));
|
||||
|
||||
// Popup
|
||||
instance->popup = popup_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher, NfcMagicAppViewPopup, popup_get_view(instance->popup));
|
||||
|
||||
// Loading
|
||||
instance->loading = loading_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher, NfcMagicAppViewLoading, loading_get_view(instance->loading));
|
||||
|
||||
// Text Input
|
||||
instance->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher,
|
||||
NfcMagicAppViewTextInput,
|
||||
text_input_get_view(instance->text_input));
|
||||
|
||||
// Byte Input
|
||||
instance->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher,
|
||||
NfcMagicAppViewByteInput,
|
||||
byte_input_get_view(instance->byte_input));
|
||||
|
||||
// Custom Widget
|
||||
instance->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
instance->view_dispatcher, NfcMagicAppViewWidget, widget_get_view(instance->widget));
|
||||
|
||||
instance->nfc = nfc_alloc();
|
||||
instance->scanner = nfc_magic_scanner_alloc(instance->nfc);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_magic_app_free(NfcMagicApp* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// Nfc device
|
||||
nfc_device_free(instance->source_dev);
|
||||
furi_string_free(instance->file_name);
|
||||
furi_string_free(instance->file_path);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewMenu);
|
||||
submenu_free(instance->submenu);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
popup_free(instance->popup);
|
||||
|
||||
// Loading
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewLoading);
|
||||
loading_free(instance->loading);
|
||||
|
||||
// Text Input
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewTextInput);
|
||||
text_input_free(instance->text_input);
|
||||
|
||||
// Byte Input
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewByteInput);
|
||||
byte_input_free(instance->byte_input);
|
||||
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
widget_free(instance->widget);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(instance->view_dispatcher);
|
||||
|
||||
// Scene Manager
|
||||
scene_manager_free(instance->scene_manager);
|
||||
|
||||
// GUI
|
||||
furi_record_close(RECORD_GUI);
|
||||
instance->gui = NULL;
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
instance->notifications = NULL;
|
||||
|
||||
// Dialogs
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
instance->dialogs = NULL;
|
||||
|
||||
// Storage
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
instance->storage = NULL;
|
||||
|
||||
nfc_magic_scanner_free(instance->scanner);
|
||||
nfc_free(instance->nfc);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static const NotificationSequence nfc_magic_sequence_blink_start_cyan = {
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_cyan,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence nfc_magic_sequence_blink_stop = {
|
||||
&message_blink_stop,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void nfc_magic_app_blink_start(NfcMagicApp* instance) {
|
||||
notification_message(instance->notifications, &nfc_magic_sequence_blink_start_cyan);
|
||||
}
|
||||
|
||||
void nfc_magic_app_blink_stop(NfcMagicApp* instance) {
|
||||
notification_message(instance->notifications, &nfc_magic_sequence_blink_stop);
|
||||
}
|
||||
|
||||
static bool nfc_magic_set_shadow_file_path(FuriString* file_path, FuriString* shadow_file_path) {
|
||||
furi_assert(file_path);
|
||||
furi_assert(shadow_file_path);
|
||||
|
||||
bool shadow_file_path_set = false;
|
||||
if(furi_string_end_with(file_path, NFC_APP_SHADOW_EXTENSION)) {
|
||||
furi_string_set(shadow_file_path, file_path);
|
||||
shadow_file_path_set = true;
|
||||
} else if(furi_string_end_with(file_path, NFC_APP_EXTENSION)) {
|
||||
size_t path_len = furi_string_size(file_path);
|
||||
// Cut .nfc
|
||||
furi_string_set_n(shadow_file_path, file_path, 0, path_len - 4);
|
||||
furi_string_cat_printf(shadow_file_path, "%s", NFC_APP_SHADOW_EXTENSION);
|
||||
shadow_file_path_set = true;
|
||||
}
|
||||
|
||||
return shadow_file_path_set;
|
||||
}
|
||||
|
||||
static bool nfc_magic_has_shadow_file_internal(NfcMagicApp* instance, FuriString* path) {
|
||||
furi_assert(path);
|
||||
|
||||
bool has_shadow_file = false;
|
||||
FuriString* shadow_file_path = furi_string_alloc();
|
||||
do {
|
||||
if(furi_string_empty(path)) break;
|
||||
if(!nfc_magic_set_shadow_file_path(path, shadow_file_path)) break;
|
||||
has_shadow_file =
|
||||
storage_common_exists(instance->storage, furi_string_get_cstr(shadow_file_path));
|
||||
} while(false);
|
||||
|
||||
furi_string_free(shadow_file_path);
|
||||
|
||||
return has_shadow_file;
|
||||
}
|
||||
|
||||
bool nfc_magic_load_file(NfcMagicApp* instance, FuriString* path, bool show_dialog) {
|
||||
furi_assert(instance);
|
||||
furi_assert(path);
|
||||
bool result = false;
|
||||
|
||||
FuriString* load_path = furi_string_alloc();
|
||||
if(nfc_magic_has_shadow_file_internal(instance, path)) {
|
||||
nfc_magic_set_shadow_file_path(path, load_path);
|
||||
} else if(furi_string_end_with(path, NFC_APP_SHADOW_EXTENSION)) {
|
||||
size_t path_len = furi_string_size(path);
|
||||
furi_string_set_n(load_path, path, 0, path_len - 4);
|
||||
furi_string_cat_printf(load_path, "%s", NFC_APP_EXTENSION);
|
||||
} else {
|
||||
furi_string_set(load_path, path);
|
||||
}
|
||||
|
||||
result = nfc_device_load(instance->source_dev, furi_string_get_cstr(load_path));
|
||||
|
||||
if(result) {
|
||||
path_extract_filename(load_path, instance->file_name, true);
|
||||
}
|
||||
|
||||
if((!result) && (show_dialog)) {
|
||||
dialog_message_show_storage_error(instance->dialogs, "Cannot load\nkey file");
|
||||
}
|
||||
|
||||
furi_string_free(load_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nfc_magic_load_from_file_select(NfcMagicApp* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, NFC_APP_EXTENSION, &I_Nfc_10px);
|
||||
browser_options.base_path = NFC_APP_FOLDER;
|
||||
browser_options.hide_dot_files = true;
|
||||
|
||||
// Input events and views are managed by file_browser
|
||||
bool result = dialog_file_browser_show(
|
||||
instance->dialogs, instance->file_path, instance->file_path, &browser_options);
|
||||
|
||||
if(result) {
|
||||
result = nfc_magic_load_file(instance, instance->file_path, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t nfc_magic_app(void* p) {
|
||||
UNUSED(p);
|
||||
NfcMagicApp* instance = nfc_magic_app_alloc();
|
||||
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneStart);
|
||||
|
||||
view_dispatcher_run(instance->view_dispatcher);
|
||||
|
||||
nfc_magic_app_free(instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
5
applications/external/nfc_magic/nfc_magic_app.h
vendored
Normal file
5
applications/external/nfc_magic/nfc_magic_app.h
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct NfcMagicAppDevice NfcMagicAppDevice;
|
||||
|
||||
typedef struct NfcMagicApp NfcMagicApp;
|
||||
103
applications/external/nfc_magic/nfc_magic_app_i.h
vendored
Normal file
103
applications/external/nfc_magic/nfc_magic_app_i.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include "nfc_magic_app.h"
|
||||
#include "helpers/nfc_magic_custom_events.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/loading.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#include "scenes/nfc_magic_scene.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include "nfc_magic_icons.h"
|
||||
|
||||
#include <assets_icons.h>
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
|
||||
#include "lib/magic/nfc_magic_scanner.h"
|
||||
#include "lib/magic/protocols/nfc_magic_protocols.h"
|
||||
#include "lib/magic/protocols/gen1a/gen1a_poller.h"
|
||||
#include "lib/magic/protocols/gen4/gen4_poller.h"
|
||||
|
||||
#define NFC_APP_FOLDER ANY_PATH("nfc")
|
||||
#define NFC_APP_EXTENSION ".nfc"
|
||||
#define NFC_APP_SHADOW_EXTENSION ".shd"
|
||||
|
||||
#define NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE (4)
|
||||
|
||||
enum NfcMagicAppCustomEvent {
|
||||
// Reserve first 100 events for button types and indexes, starting from 0
|
||||
NfcMagicAppCustomEventReserved = 100,
|
||||
|
||||
NfcMagicAppCustomEventViewExit,
|
||||
NfcMagicAppCustomEventWorkerExit,
|
||||
NfcMagicAppCustomEventByteInputDone,
|
||||
NfcMagicAppCustomEventTextInputDone,
|
||||
};
|
||||
|
||||
struct NfcMagicApp {
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
Storage* storage;
|
||||
|
||||
SceneManager* scene_manager;
|
||||
NfcDevice* source_dev;
|
||||
FuriString* file_name;
|
||||
FuriString* file_path;
|
||||
|
||||
Nfc* nfc;
|
||||
NfcMagicProtocol protocol;
|
||||
NfcMagicScanner* scanner;
|
||||
Gen1aPoller* gen1a_poller;
|
||||
Gen4Poller* gen4_poller;
|
||||
|
||||
uint32_t gen4_password;
|
||||
uint32_t gen4_password_new;
|
||||
|
||||
FuriString* text_box_store;
|
||||
uint8_t byte_input_store[NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE];
|
||||
|
||||
// Common Views
|
||||
Submenu* submenu;
|
||||
Popup* popup;
|
||||
Loading* loading;
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
Widget* widget;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NfcMagicAppViewMenu,
|
||||
NfcMagicAppViewPopup,
|
||||
NfcMagicAppViewLoading,
|
||||
NfcMagicAppViewTextInput,
|
||||
NfcMagicAppViewByteInput,
|
||||
NfcMagicAppViewWidget,
|
||||
} NfcMagicAppView;
|
||||
|
||||
void nfc_magic_app_blink_start(NfcMagicApp* nfc_magic);
|
||||
|
||||
void nfc_magic_app_blink_stop(NfcMagicApp* nfc_magic);
|
||||
|
||||
void nfc_magic_app_show_loading_popup(void* context, bool show);
|
||||
|
||||
bool nfc_magic_load_from_file_select(NfcMagicApp* instance);
|
||||
95
applications/external/nfc_magic/nfc_magic_i.h
vendored
95
applications/external/nfc_magic/nfc_magic_i.h
vendored
@@ -1,95 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "nfc_magic.h"
|
||||
#include "nfc_magic_worker.h"
|
||||
|
||||
#include "lib/magic/common.h"
|
||||
#include "lib/magic/types.h"
|
||||
#include "lib/magic/classic_gen1.h"
|
||||
#include "lib/magic/gen4.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/loading.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#include "scenes/nfc_magic_scene.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include "nfc_magic_icons.h"
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define NFC_APP_FOLDER EXT_PATH("nfc")
|
||||
|
||||
enum NfcMagicCustomEvent {
|
||||
// Reserve first 100 events for button types and indexes, starting from 0
|
||||
NfcMagicCustomEventReserved = 100,
|
||||
|
||||
NfcMagicCustomEventViewExit,
|
||||
NfcMagicCustomEventWorkerExit,
|
||||
NfcMagicCustomEventByteInputDone,
|
||||
NfcMagicCustomEventTextInputDone,
|
||||
};
|
||||
|
||||
struct NfcMagicDevice {
|
||||
MagicType type;
|
||||
uint32_t cuid;
|
||||
uint8_t uid_len;
|
||||
uint32_t password;
|
||||
};
|
||||
|
||||
struct NfcMagic {
|
||||
NfcMagicWorker* worker;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
SceneManager* scene_manager;
|
||||
struct NfcMagicDevice* dev;
|
||||
NfcDevice* source_dev;
|
||||
|
||||
uint32_t new_password;
|
||||
|
||||
FuriString* text_box_store;
|
||||
|
||||
// Common Views
|
||||
Submenu* submenu;
|
||||
Popup* popup;
|
||||
Loading* loading;
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
Widget* widget;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NfcMagicViewMenu,
|
||||
NfcMagicViewPopup,
|
||||
NfcMagicViewLoading,
|
||||
NfcMagicViewTextInput,
|
||||
NfcMagicViewByteInput,
|
||||
NfcMagicViewWidget,
|
||||
} NfcMagicView;
|
||||
|
||||
NfcMagic* nfc_magic_alloc();
|
||||
|
||||
void nfc_magic_text_store_set(NfcMagic* nfc_magic, const char* text, ...);
|
||||
|
||||
void nfc_magic_text_store_clear(NfcMagic* nfc_magic);
|
||||
|
||||
void nfc_magic_blink_start(NfcMagic* nfc_magic);
|
||||
|
||||
void nfc_magic_blink_stop(NfcMagic* nfc_magic);
|
||||
|
||||
void nfc_magic_show_loading_popup(void* context, bool show);
|
||||
483
applications/external/nfc_magic/nfc_magic_worker.c
vendored
483
applications/external/nfc_magic/nfc_magic_worker.c
vendored
@@ -1,483 +0,0 @@
|
||||
#include "nfc_magic_worker_i.h"
|
||||
|
||||
#include "nfc_magic_i.h"
|
||||
#include "lib/magic/common.h"
|
||||
#include "lib/magic/classic_gen1.h"
|
||||
#include "lib/magic/gen4.h"
|
||||
|
||||
#define TAG "NfcMagicWorker"
|
||||
|
||||
static void
|
||||
nfc_magic_worker_change_state(NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state) {
|
||||
furi_assert(nfc_magic_worker);
|
||||
|
||||
nfc_magic_worker->state = state;
|
||||
}
|
||||
|
||||
NfcMagicWorker* nfc_magic_worker_alloc() {
|
||||
NfcMagicWorker* nfc_magic_worker = malloc(sizeof(NfcMagicWorker));
|
||||
|
||||
// Worker thread attributes
|
||||
nfc_magic_worker->thread =
|
||||
furi_thread_alloc_ex("NfcMagicWorker", 8192, nfc_magic_worker_task, nfc_magic_worker);
|
||||
|
||||
nfc_magic_worker->callback = NULL;
|
||||
nfc_magic_worker->context = NULL;
|
||||
|
||||
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
|
||||
|
||||
return nfc_magic_worker;
|
||||
}
|
||||
|
||||
void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) {
|
||||
furi_assert(nfc_magic_worker);
|
||||
|
||||
furi_thread_free(nfc_magic_worker->thread);
|
||||
free(nfc_magic_worker);
|
||||
}
|
||||
|
||||
void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
|
||||
furi_assert(nfc_magic_worker);
|
||||
|
||||
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop);
|
||||
furi_thread_join(nfc_magic_worker->thread);
|
||||
}
|
||||
|
||||
void nfc_magic_worker_start(
|
||||
NfcMagicWorker* nfc_magic_worker,
|
||||
NfcMagicWorkerState state,
|
||||
NfcMagicDevice* magic_dev,
|
||||
NfcDeviceData* dev_data,
|
||||
uint32_t new_password,
|
||||
NfcMagicWorkerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(nfc_magic_worker);
|
||||
furi_assert(magic_dev);
|
||||
furi_assert(dev_data);
|
||||
|
||||
furi_hal_nfc_deinit();
|
||||
furi_hal_nfc_init();
|
||||
|
||||
nfc_magic_worker->callback = callback;
|
||||
nfc_magic_worker->context = context;
|
||||
nfc_magic_worker->magic_dev = magic_dev;
|
||||
nfc_magic_worker->dev_data = dev_data;
|
||||
nfc_magic_worker->new_password = new_password;
|
||||
nfc_magic_worker_change_state(nfc_magic_worker, state);
|
||||
furi_thread_start(nfc_magic_worker->thread);
|
||||
}
|
||||
|
||||
int32_t nfc_magic_worker_task(void* context) {
|
||||
NfcMagicWorker* nfc_magic_worker = context;
|
||||
|
||||
if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
|
||||
nfc_magic_worker_check(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||
nfc_magic_worker_write(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) {
|
||||
nfc_magic_worker_rekey(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||
nfc_magic_worker_wipe(nfc_magic_worker);
|
||||
}
|
||||
|
||||
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
|
||||
bool card_found_notified = false;
|
||||
bool done = false;
|
||||
FuriHalNfcDevData nfc_data = {};
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
NfcDeviceData* dev_data = nfc_magic_worker->dev_data;
|
||||
NfcProtocol dev_protocol = dev_data->protocol;
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||
do {
|
||||
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
magic_deactivate();
|
||||
magic_activate();
|
||||
if(!magic_gen1_wupa()) {
|
||||
FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
magic_activate();
|
||||
if(magic_gen1_wupa()) {
|
||||
magic_gen1_data_access_cmd();
|
||||
|
||||
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||
for(size_t i = 0; i < 64; i++) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||
if(!magic_gen1_write_blk(i, &mfc_data->block[i])) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
done = true;
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done = true;
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
} else if(magic_dev->type == MagicTypeGen4) {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
uint8_t gen4_config[28];
|
||||
uint32_t password = magic_dev->password;
|
||||
|
||||
uint32_t cuid;
|
||||
if(dev_protocol == NfcDeviceProtocolMifareClassic) {
|
||||
gen4_config[0] = 0x00;
|
||||
gen4_config[27] = 0x00;
|
||||
} else if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &dev_data->mf_ul_data;
|
||||
gen4_config[0] = 0x01;
|
||||
switch(mf_ul_data->type) {
|
||||
case MfUltralightTypeUL11:
|
||||
case MfUltralightTypeUL21:
|
||||
// UL-C?
|
||||
// UL?
|
||||
default:
|
||||
gen4_config[27] = MagicGen4UltralightModeUL_EV1;
|
||||
break;
|
||||
case MfUltralightTypeNTAG203:
|
||||
case MfUltralightTypeNTAG213:
|
||||
case MfUltralightTypeNTAG215:
|
||||
case MfUltralightTypeNTAG216:
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
gen4_config[27] = MagicGen4UltralightModeNTAG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dev_data->nfc_data.uid_len == 4) {
|
||||
gen4_config[1] = MagicGen4UIDLengthSingle;
|
||||
} else if(dev_data->nfc_data.uid_len == 7) {
|
||||
gen4_config[1] = MagicGen4UIDLengthDouble;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
gen4_config[2] = (uint8_t)(password >> 24);
|
||||
gen4_config[3] = (uint8_t)(password >> 16);
|
||||
gen4_config[4] = (uint8_t)(password >> 8);
|
||||
gen4_config[5] = (uint8_t)password;
|
||||
|
||||
if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore;
|
||||
} else {
|
||||
gen4_config[6] = MagicGen4ShadowModeIgnore;
|
||||
}
|
||||
gen4_config[7] = 0x00;
|
||||
memset(gen4_config + 8, 0, 16);
|
||||
gen4_config[24] = dev_data->nfc_data.atqa[0];
|
||||
gen4_config[25] = dev_data->nfc_data.atqa[1];
|
||||
gen4_config[26] = dev_data->nfc_data.sak;
|
||||
|
||||
furi_hal_nfc_sleep();
|
||||
furi_hal_nfc_activate_nfca(200, &cuid);
|
||||
if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if(dev_protocol == NfcDeviceProtocolMifareClassic) {
|
||||
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||
size_t block_count = 64;
|
||||
if(mfc_data->type == MfClassicType4k) block_count = 256;
|
||||
for(size_t i = 0; i < block_count; i++) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||
if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &dev_data->mf_ul_data;
|
||||
for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) {
|
||||
size_t data_offset = i * 4;
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Writing page %zu (%zu/%u)",
|
||||
i,
|
||||
data_offset,
|
||||
mf_ul_data->data_read);
|
||||
uint8_t* block = mf_ul_data->data + data_offset;
|
||||
if(!magic_gen4_write_blk(password, i, block)) {
|
||||
FURI_LOG_E(TAG, "Failed to write %zu page", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t buffer[16] = {0};
|
||||
|
||||
for(size_t i = 0; i < 8; i++) {
|
||||
memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086
|
||||
if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write signature block %d", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[0] = mf_ul_data->version.header;
|
||||
buffer[1] = mf_ul_data->version.vendor_id;
|
||||
buffer[2] = mf_ul_data->version.prod_type;
|
||||
buffer[3] = mf_ul_data->version.prod_subtype;
|
||||
if(!magic_gen4_write_blk(password, 0xFA, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write version block 0");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[0] = mf_ul_data->version.prod_ver_major;
|
||||
buffer[1] = mf_ul_data->version.prod_ver_minor;
|
||||
buffer[2] = mf_ul_data->version.storage_size;
|
||||
buffer[3] = mf_ul_data->version.protocol_type;
|
||||
if(!magic_gen4_write_blk(password, 0xFB, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write version block 1");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(done) break;
|
||||
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
||||
FuriHalNfcDevData nfc_data = {};
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN];
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
|
||||
magic_activate();
|
||||
if(magic_gen1_wupa()) {
|
||||
magic_dev->type = MagicTypeClassicGen1;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
magic_dev->cuid = nfc_data.cuid;
|
||||
magic_dev->uid_len = nfc_data.uid_len;
|
||||
} else {
|
||||
// wrong BCC
|
||||
magic_dev->uid_len = 4;
|
||||
}
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
} else {
|
||||
magic_deactivate();
|
||||
magic_activate();
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
magic_dev->cuid = nfc_data.cuid;
|
||||
magic_dev->uid_len = nfc_data.uid_len;
|
||||
if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) {
|
||||
magic_dev->type = MagicTypeGen4;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
} else {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) {
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
|
||||
if(magic_dev->type != MagicTypeGen4) {
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
return;
|
||||
}
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) {
|
||||
magic_activate();
|
||||
uint32_t cuid;
|
||||
furi_hal_nfc_activate_nfca(200, &cuid);
|
||||
if(cuid != magic_dev->cuid) {
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
|
||||
if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) {
|
||||
magic_dev->password = nfc_magic_worker->new_password;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
if(card_found_notified) { //-V547
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
bool card_wiped = false;
|
||||
|
||||
MfClassicBlock block;
|
||||
memset(&block, 0, sizeof(MfClassicBlock));
|
||||
MfClassicBlock empty_block;
|
||||
memset(&empty_block, 0, sizeof(MfClassicBlock));
|
||||
MfClassicBlock trailer_block;
|
||||
memset(&trailer_block, 0xff, sizeof(MfClassicBlock));
|
||||
|
||||
block.value[0] = 0x01;
|
||||
block.value[1] = 0x02;
|
||||
block.value[2] = 0x03;
|
||||
block.value[3] = 0x04;
|
||||
block.value[4] = 0x04;
|
||||
block.value[5] = 0x08;
|
||||
block.value[6] = 0x04;
|
||||
|
||||
trailer_block.value[7] = 0x07;
|
||||
trailer_block.value[8] = 0x80;
|
||||
trailer_block.value[9] = 0x69;
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||
do {
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
if(!magic_activate()) break;
|
||||
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||
if(!magic_gen1_wupa()) break;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
if(!magic_gen1_data_access_cmd()) break;
|
||||
if(!magic_gen1_write_blk(0, &block)) break;
|
||||
|
||||
for(size_t i = 1; i < 64; i++) {
|
||||
FURI_LOG_D(TAG, "Wiping block %d", i);
|
||||
bool success = false;
|
||||
if((i | 0x03) == i) {
|
||||
success = magic_gen1_write_blk(i, &trailer_block);
|
||||
} else {
|
||||
success = magic_gen1_write_blk(i, &empty_block);
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
card_wiped = true;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
} else if(magic_dev->type == MagicTypeGen4) {
|
||||
uint32_t cuid;
|
||||
if(!furi_hal_nfc_activate_nfca(200, &cuid)) break;
|
||||
if(cuid != magic_dev->cuid) break;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
if(!magic_gen4_wipe(magic_dev->password)) break;
|
||||
|
||||
card_wiped = true;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(card_wiped) break;
|
||||
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include "nfc_magic.h"
|
||||
|
||||
typedef struct NfcMagicWorker NfcMagicWorker;
|
||||
|
||||
typedef enum {
|
||||
NfcMagicWorkerStateReady,
|
||||
|
||||
NfcMagicWorkerStateCheck,
|
||||
NfcMagicWorkerStateWrite,
|
||||
NfcMagicWorkerStateRekey,
|
||||
NfcMagicWorkerStateWipe,
|
||||
|
||||
NfcMagicWorkerStateStop,
|
||||
} NfcMagicWorkerState;
|
||||
|
||||
typedef enum {
|
||||
NfcMagicWorkerEventSuccess,
|
||||
NfcMagicWorkerEventFail,
|
||||
NfcMagicWorkerEventCardDetected,
|
||||
NfcMagicWorkerEventNoCardDetected,
|
||||
NfcMagicWorkerEventWrongCard,
|
||||
} NfcMagicWorkerEvent;
|
||||
|
||||
typedef bool (*NfcMagicWorkerCallback)(NfcMagicWorkerEvent event, void* context);
|
||||
|
||||
NfcMagicWorker* nfc_magic_worker_alloc();
|
||||
|
||||
void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_start(
|
||||
NfcMagicWorker* nfc_magic_worker,
|
||||
NfcMagicWorkerState state,
|
||||
NfcMagicDevice* magic_dev,
|
||||
NfcDeviceData* dev_data,
|
||||
uint32_t new_password,
|
||||
NfcMagicWorkerCallback callback,
|
||||
void* context);
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include "nfc_magic_worker.h"
|
||||
#include "lib/magic/common.h"
|
||||
|
||||
struct NfcMagicWorker {
|
||||
FuriThread* thread;
|
||||
|
||||
NfcMagicDevice* magic_dev;
|
||||
NfcDeviceData* dev_data;
|
||||
uint32_t new_password;
|
||||
|
||||
NfcMagicWorkerCallback callback;
|
||||
void* context;
|
||||
|
||||
NfcMagicWorkerState state;
|
||||
};
|
||||
|
||||
int32_t nfc_magic_worker_task(void* context);
|
||||
|
||||
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker);
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_actions_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
Submenu* submenu = nfc_magic->submenu;
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions));
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_actions_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
submenu_reset(nfc_magic->submenu);
|
||||
}
|
||||
108
applications/external/nfc_magic/scenes/nfc_magic_scene_change_key.c
vendored
Normal file
108
applications/external/nfc_magic/scenes/nfc_magic_scene_change_key.c
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneChangeKeyStateCardSearch,
|
||||
NfcMagicSceneChangeKeyStateCardFound,
|
||||
};
|
||||
|
||||
NfcCommand nfc_mafic_scene_change_key_gen4_poller_callback(Gen4PollerEvent event, void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
furi_assert(event.data);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(event.type == Gen4PollerEventTypeCardDetected) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventCardDetected);
|
||||
} else if(event.type == Gen4PollerEventTypeRequestMode) {
|
||||
event.data->request_mode.mode = Gen4PollerModeSetPassword;
|
||||
} else if(event.type == Gen4PollerEventTypeRequestNewPassword) {
|
||||
event.data->request_password.password = instance->gen4_password_new;
|
||||
} else if(event.type == Gen4PollerEventTypeSuccess) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(event.type == Gen4PollerEventTypeFail) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_change_key_setup_view(NfcMagicApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneChangeKey);
|
||||
|
||||
if(state == NfcMagicSceneChangeKeyStateCardSearch) {
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(
|
||||
instance->popup, "Apply the\nsame card\nto the back", 128, 32, AlignRight, AlignCenter);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_change_key_on_enter(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcMagicSceneChangeKey, NfcMagicSceneChangeKeyStateCardSearch);
|
||||
nfc_magic_scene_change_key_setup_view(instance);
|
||||
|
||||
nfc_magic_app_blink_start(instance);
|
||||
|
||||
instance->gen4_poller = gen4_poller_alloc(instance->nfc);
|
||||
gen4_poller_start(
|
||||
instance->gen4_poller, nfc_mafic_scene_change_key_gen4_poller_callback, instance);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_change_key_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcMagicSceneChangeKey,
|
||||
NfcMagicSceneChangeKeyStateCardFound);
|
||||
nfc_magic_scene_change_key_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventCardLost) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcMagicSceneChangeKey,
|
||||
NfcMagicSceneChangeKeyStateCardSearch);
|
||||
nfc_magic_scene_change_key_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerSuccess) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerFail) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneChangeKeyFail);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_change_key_on_exit(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
gen4_poller_stop(instance->gen4_poller);
|
||||
gen4_poller_free(instance->gen4_poller);
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcMagicSceneChangeKey, NfcMagicSceneChangeKeyStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(instance->popup);
|
||||
|
||||
nfc_magic_app_blink_stop(instance);
|
||||
}
|
||||
54
applications/external/nfc_magic/scenes/nfc_magic_scene_change_key_fail.c
vendored
Normal file
54
applications/external/nfc_magic/scenes/nfc_magic_scene_change_key_fail.c
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_change_key_fail_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_change_key_fail_on_enter(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!");
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Finish",
|
||||
nfc_magic_scene_change_key_fail_widget_callback,
|
||||
instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_change_key_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_change_key_fail_on_exit(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
@@ -1,89 +1,54 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneCheckStateCardSearch,
|
||||
NfcMagicSceneCheckStateCardFound,
|
||||
};
|
||||
|
||||
bool nfc_magic_check_worker_callback(NfcMagicWorkerEvent event, void* context) {
|
||||
void nfc_magic_check_worker_callback(NfcMagicScannerEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_check_setup_view(NfcMagic* nfc_magic) {
|
||||
Popup* popup = nfc_magic->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||
|
||||
if(state == NfcMagicSceneCheckStateCardSearch) {
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(
|
||||
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
if(event.type == NfcMagicScannerEventTypeDetected) {
|
||||
instance->protocol = event.data.protocol;
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
} else if(event.type == NfcMagicScannerEventTypeDetectedNotMagic) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_check_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
|
||||
nfc_magic_scene_check_setup_view(nfc_magic);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(instance->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
||||
|
||||
// Setup and start worker
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateCheck,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_check_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
nfc_magic_app_blink_start(instance);
|
||||
|
||||
nfc_magic_scanner_start(instance->scanner, nfc_magic_check_worker_callback, instance);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_check_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicWorkerEventSuccess) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneMagicInfo);
|
||||
if(event.event == NfcMagicCustomEventWorkerSuccess) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneMagicInfo);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventWrongCard) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardFound);
|
||||
nfc_magic_scene_check_setup_view(nfc_magic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
|
||||
nfc_magic_scene_check_setup_view(nfc_magic);
|
||||
} else if(event.event == NfcMagicCustomEventWorkerFail) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneNotMagic);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_check_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
|
||||
nfc_magic_blink_stop(nfc_magic);
|
||||
nfc_magic_scanner_stop(instance->scanner);
|
||||
popup_reset(instance->popup);
|
||||
nfc_magic_app_blink_stop(instance);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
ADD_SCENE(nfc_magic, start, Start)
|
||||
ADD_SCENE(nfc_magic, key_input, KeyInput)
|
||||
ADD_SCENE(nfc_magic, actions, Actions)
|
||||
ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions)
|
||||
ADD_SCENE(nfc_magic, new_key_input, NewKeyInput)
|
||||
ADD_SCENE(nfc_magic, file_select, FileSelect)
|
||||
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
|
||||
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
|
||||
ADD_SCENE(nfc_magic, write, Write)
|
||||
ADD_SCENE(nfc_magic, write_fail, WriteFail)
|
||||
ADD_SCENE(nfc_magic, success, Success)
|
||||
ADD_SCENE(nfc_magic, check, Check)
|
||||
ADD_SCENE(nfc_magic, not_magic, NotMagic)
|
||||
ADD_SCENE(nfc_magic, key_input, KeyInput)
|
||||
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
|
||||
ADD_SCENE(nfc_magic, rekey, Rekey)
|
||||
ADD_SCENE(nfc_magic, rekey_fail, RekeyFail)
|
||||
ADD_SCENE(nfc_magic, gen1_menu, Gen1Menu)
|
||||
ADD_SCENE(nfc_magic, gen4_menu, Gen4Menu)
|
||||
ADD_SCENE(nfc_magic, wipe, Wipe)
|
||||
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)
|
||||
ADD_SCENE(nfc_magic, success, Success)
|
||||
ADD_SCENE(nfc_magic, file_select, FileSelect)
|
||||
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
|
||||
ADD_SCENE(nfc_magic, write, Write)
|
||||
ADD_SCENE(nfc_magic, write_fail, WriteFail)
|
||||
ADD_SCENE(nfc_magic, change_key, ChangeKey)
|
||||
ADD_SCENE(nfc_magic, change_key_fail, ChangeKeyFail)
|
||||
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
|
||||
ADD_SCENE(nfc_magic, not_magic, NotMagic)
|
||||
|
||||
@@ -1,66 +1,51 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) {
|
||||
NfcDevice* nfc_dev = nfc_magic->source_dev;
|
||||
if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
switch(nfc_magic->dev->type) {
|
||||
case MagicTypeClassicGen1:
|
||||
case MagicTypeClassicDirectWrite:
|
||||
case MagicTypeClassicAPDU:
|
||||
if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) ||
|
||||
(nfc_dev->dev_data.nfc_data.uid_len != nfc_magic->dev->uid_len)) {
|
||||
return false;
|
||||
static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagicApp* instance) {
|
||||
NfcProtocol protocol = nfc_device_get_protocol(instance->source_dev);
|
||||
size_t uid_len = 0;
|
||||
nfc_device_get_uid(instance->source_dev, &uid_len);
|
||||
|
||||
bool suitable = false;
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
if((uid_len == 4) && (protocol == NfcProtocolMfClassic)) {
|
||||
const MfClassicData* mfc_data =
|
||||
nfc_device_get_data(instance->source_dev, NfcProtocolMfClassic);
|
||||
if(mfc_data->type == MfClassicType1k) {
|
||||
suitable = true;
|
||||
}
|
||||
return true;
|
||||
|
||||
case MagicTypeGen4:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if(
|
||||
(nfc_dev->format == NfcDeviceSaveFormatMifareUl) &&
|
||||
(nfc_dev->dev_data.nfc_data.uid_len == 7)) {
|
||||
switch(nfc_magic->dev->type) {
|
||||
case MagicTypeUltralightGen1:
|
||||
case MagicTypeUltralightDirectWrite:
|
||||
case MagicTypeUltralightC_Gen1:
|
||||
case MagicTypeUltralightC_DirectWrite:
|
||||
case MagicTypeGen4:
|
||||
switch(nfc_dev->dev_data.mf_ul_data.type) {
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
} else if(instance->protocol == NfcMagicProtocolGen4) {
|
||||
if(protocol == NfcProtocolMfClassic) {
|
||||
suitable = true;
|
||||
} else if(protocol == NfcProtocolMfUltralight) {
|
||||
const MfUltralightData* mfu_data =
|
||||
nfc_device_get_data(instance->source_dev, NfcProtocolMfUltralight);
|
||||
const Iso14443_3aData* iso3_data = mfu_data->iso14443_3a_data;
|
||||
if(iso3_data->uid_len == 7) {
|
||||
MfUltralightType mfu_type = mfu_data->type;
|
||||
suitable = (mfu_type != MfUltralightTypeNTAGI2C1K) &&
|
||||
(mfu_type != MfUltralightTypeNTAGI2C2K) &&
|
||||
(mfu_type != MfUltralightTypeNTAGI2CPlus1K) &&
|
||||
(mfu_type != MfUltralightTypeNTAGI2CPlus2K);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return suitable;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_file_select_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
// Process file_select return
|
||||
nfc_device_set_loading_callback(
|
||||
nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
if(!furi_string_size(nfc_magic->source_dev->load_path)) {
|
||||
furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER);
|
||||
}
|
||||
if(nfc_file_select(nfc_magic->source_dev)) {
|
||||
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);
|
||||
if(nfc_magic_load_from_file_select(instance)) {
|
||||
if(nfc_magic_scene_file_select_is_file_suitable(instance)) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWriteConfirm);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWrongCard);
|
||||
}
|
||||
} else {
|
||||
scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +56,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
|
||||
void nfc_magic_scene_file_select_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic);
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
53
applications/external/nfc_magic/scenes/nfc_magic_scene_gen1_menu.c
vendored
Normal file
53
applications/external/nfc_magic/scenes/nfc_magic_scene_gen1_menu.c
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_gen1_menu_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen1_menu_on_enter(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
Submenu* submenu = instance->submenu;
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_gen1_menu_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_gen1_menu_submenu_callback, instance);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu));
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_gen1_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen1_menu_on_exit(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
submenu_reset(instance->submenu);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexChangePassword,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_actions_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
Submenu* submenu = nfc_magic->submenu;
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexWrite,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change password",
|
||||
SubmenuIndexChangePassword,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Wipe",
|
||||
SubmenuIndexWipe,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu,
|
||||
scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions));
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexChangePassword) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_actions_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
submenu_reset(nfc_magic->submenu);
|
||||
}
|
||||
63
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_menu.c
vendored
Normal file
63
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_menu.c
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexChangePassword,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_gen4_menu_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_menu_on_enter(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
Submenu* submenu = instance->submenu;
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_gen4_menu_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change password",
|
||||
SubmenuIndexChangePassword,
|
||||
nfc_magic_scene_gen4_menu_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_gen4_menu_submenu_callback, instance);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu));
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_gen4_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexChangePassword) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneKeyInput);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_menu_on_exit(void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
submenu_reset(instance->submenu);
|
||||
}
|
||||
@@ -1,35 +1,45 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
|
||||
void nfc_magic_scene_key_input_byte_input_callback(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone);
|
||||
instance->view_dispatcher, NfcMagicAppCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_key_input_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc_magic->byte_input;
|
||||
ByteInput* byte_input = instance->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_magic_scene_key_input_byte_input_callback,
|
||||
NULL,
|
||||
nfc_magic,
|
||||
(uint8_t*)&nfc_magic->dev->password,
|
||||
4);
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
instance,
|
||||
instance->byte_input_store,
|
||||
NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewByteInput);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventByteInputDone) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||
if(event.event == NfcMagicAppCustomEventByteInputDone) {
|
||||
if(scene_manager_has_previous_scene(instance->scene_manager, NfcMagicSceneGen4Menu)) {
|
||||
instance->gen4_password_new = nfc_util_bytes2num(
|
||||
instance->byte_input_store, NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneChangeKey);
|
||||
} else {
|
||||
instance->gen4_password = nfc_util_bytes2num(
|
||||
instance->byte_input_store, NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneCheck);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
@@ -37,9 +47,9 @@ bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event)
|
||||
}
|
||||
|
||||
void nfc_magic_scene_key_input_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(nfc_magic->byte_input, "");
|
||||
byte_input_set_result_callback(instance->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(instance->byte_input, "");
|
||||
}
|
||||
|
||||
@@ -1,50 +1,54 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../lib/magic/types.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_magic_info_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_magic_info_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
const char* card_type = nfc_magic_type(nfc_magic->dev->type);
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_success);
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected");
|
||||
widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type);
|
||||
widget_add_string_element(
|
||||
widget,
|
||||
3,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
nfc_magic_protocols_get_name(instance->protocol));
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, instance);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
MagicType type = nfc_magic->dev->type;
|
||||
if(type == MagicTypeGen4) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions);
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneGen1Menu);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneGen4Menu);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +57,7 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event)
|
||||
}
|
||||
|
||||
void nfc_magic_scene_magic_info_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
void nfc_magic_scene_new_key_input_byte_input_callback(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_new_key_input_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc_magic->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_magic_scene_new_key_input_byte_input_callback,
|
||||
NULL,
|
||||
nfc_magic,
|
||||
(uint8_t*)&nfc_magic->new_password,
|
||||
4);
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventByteInputDone) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_new_key_input_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(nfc_magic->byte_input, "");
|
||||
}
|
||||
@@ -1,43 +1,43 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_not_magic_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_not_magic_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
|
||||
widget_add_string_multiline_element(
|
||||
widget, 4, 17, AlignLeft, AlignTop, FontSecondary, "Not magic or unsupported\ncard");
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_not_magic_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_not_magic_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_not_magic_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_not_magic_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneRekeyStateCardSearch,
|
||||
NfcMagicSceneRekeyStateCardFound,
|
||||
};
|
||||
|
||||
bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) {
|
||||
Popup* popup = nfc_magic->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey);
|
||||
|
||||
if(state == NfcMagicSceneRekeyStateCardSearch) {
|
||||
popup_set_text(
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
|
||||
// Setup and start worker
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateRekey,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_rekey_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicWorkerEventSuccess) {
|
||||
nfc_magic->dev->password = nfc_magic->new_password;
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventFail) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
|
||||
nfc_magic_blink_stop(nfc_magic);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
void nfc_magic_scene_rekey_fail_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_fail_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!");
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_fail_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
}
|
||||
@@ -1,49 +1,51 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexCheck,
|
||||
SubmenuIndexAuthenticateGen4,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
|
||||
NfcMagicApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_start_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
Submenu* submenu = nfc_magic->submenu;
|
||||
Submenu* submenu = instance->submenu;
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Check Magic Tag",
|
||||
SubmenuIndexCheck,
|
||||
nfc_magic_scene_start_submenu_callback,
|
||||
nfc_magic);
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Authenticate Gen4",
|
||||
SubmenuIndexAuthenticateGen4,
|
||||
nfc_magic_scene_start_submenu_callback,
|
||||
nfc_magic);
|
||||
instance);
|
||||
|
||||
instance->gen4_password = 0;
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart));
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneStart));
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexCheck) {
|
||||
nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD;
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||
instance->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneCheck);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexAuthenticateGen4) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneKeyInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +53,7 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void nfc_magic_scene_start_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
submenu_reset(nfc_magic->submenu);
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
submenu_reset(instance->submenu);
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_success_popup_callback(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, NfcMagicCustomEventViewExit);
|
||||
NfcMagicApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcMagicAppCustomEventViewExit);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_success_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_success);
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
Popup* popup = nfc_magic->popup;
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Success!", 10, 20, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, nfc_magic);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_magic_scene_success_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_success_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventViewExit) {
|
||||
if(event.event == NfcMagicAppCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_success_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
popup_reset(instance->popup);
|
||||
}
|
||||
|
||||
@@ -1,97 +1,136 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneWipeStateCardSearch,
|
||||
NfcMagicSceneWipeStateCardFound,
|
||||
};
|
||||
|
||||
bool nfc_magic_wipe_worker_callback(NfcMagicWorkerEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
NfcCommand nfc_mafic_scene_wipe_gen1_poller_callback(Gen1aPollerEvent event, void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
furi_assert(event.data);
|
||||
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
return true;
|
||||
if(event.type == Gen1aPollerEventTypeDetected) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventCardDetected);
|
||||
} else if(event.type == Gen1aPollerEventTypeRequestMode) {
|
||||
event.data->request_mode.mode = Gen1aPollerModeWipe;
|
||||
} else if(event.type == Gen1aPollerEventTypeSuccess) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(event.type == Gen1aPollerEventTypeFail) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) {
|
||||
Popup* popup = nfc_magic->popup;
|
||||
NfcCommand nfc_mafic_scene_wipe_gen4_poller_callback(Gen4PollerEvent event, void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(event.type == Gen4PollerEventTypeCardDetected) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventCardDetected);
|
||||
} else if(event.type == Gen4PollerEventTypeRequestMode) {
|
||||
event.data->request_mode.mode = Gen4PollerModeWipe;
|
||||
} else if(event.type == Gen4PollerEventTypeSuccess) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(event.type == Gen4PollerEventTypeFail) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_wipe_setup_view(NfcMagicApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneWipe);
|
||||
|
||||
if(state == NfcMagicSceneWipeStateCardSearch) {
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
instance->popup, "Apply the\nsame card\nto the back", 128, 32, AlignRight, AlignCenter);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wipe_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
nfc_magic_scene_wipe_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
nfc_magic_scene_wipe_setup_view(instance);
|
||||
|
||||
// Setup and start worker
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateWipe,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_wipe_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
nfc_magic_app_blink_start(instance);
|
||||
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
instance->gen1a_poller = gen1a_poller_alloc(instance->nfc);
|
||||
gen1a_poller_start(
|
||||
instance->gen1a_poller, nfc_mafic_scene_wipe_gen1_poller_callback, instance);
|
||||
} else {
|
||||
instance->gen4_poller = gen4_poller_alloc(instance->nfc);
|
||||
gen4_poller_set_password(instance->gen4_poller, instance->gen4_password);
|
||||
gen4_poller_start(
|
||||
instance->gen4_poller, nfc_mafic_scene_wipe_gen4_poller_callback, instance);
|
||||
}
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_wipe_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicWorkerEventSuccess) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventFail) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipeFail);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventWrongCard) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventCardDetected) {
|
||||
if(event.event == NfcMagicCustomEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardFound);
|
||||
nfc_magic_scene_wipe_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardFound);
|
||||
nfc_magic_scene_wipe_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
|
||||
} else if(event.event == NfcMagicCustomEventCardLost) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
nfc_magic_scene_wipe_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
nfc_magic_scene_wipe_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerSuccess) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerFail) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWipeFail);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wipe_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
gen1a_poller_stop(instance->gen1a_poller);
|
||||
gen1a_poller_free(instance->gen1a_poller);
|
||||
} else {
|
||||
gen4_poller_stop(instance->gen4_poller);
|
||||
gen4_poller_free(instance->gen4_poller);
|
||||
}
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
instance->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
popup_reset(instance->popup);
|
||||
|
||||
nfc_magic_blink_stop(nfc_magic);
|
||||
nfc_magic_app_blink_stop(instance);
|
||||
}
|
||||
|
||||
@@ -1,41 +1,43 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_wipe_fail_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wipe_fail_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
Widget* widget = instance->widget;
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Wipe failed");
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wipe_fail_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wipe_fail_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_wipe_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wipe_fail_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
@@ -1,97 +1,144 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneWriteStateCardSearch,
|
||||
NfcMagicSceneWriteStateCardFound,
|
||||
};
|
||||
|
||||
bool nfc_magic_write_worker_callback(NfcMagicWorkerEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
NfcCommand nfc_mafic_scene_write_gen1_poller_callback(Gen1aPollerEvent event, void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
furi_assert(event.data);
|
||||
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
return true;
|
||||
if(event.type == Gen1aPollerEventTypeDetected) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventCardDetected);
|
||||
} else if(event.type == Gen1aPollerEventTypeRequestMode) {
|
||||
event.data->request_mode.mode = Gen1aPollerModeWrite;
|
||||
} else if(event.type == Gen1aPollerEventTypeRequestDataToWrite) {
|
||||
const MfClassicData* mfc_data =
|
||||
nfc_device_get_data(instance->source_dev, NfcProtocolMfClassic);
|
||||
event.data->data_to_write.mfc_data = mfc_data;
|
||||
} else if(event.type == Gen1aPollerEventTypeSuccess) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(event.type == Gen1aPollerEventTypeFail) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) {
|
||||
Popup* popup = nfc_magic->popup;
|
||||
NfcCommand nfc_mafic_scene_write_gen4_poller_callback(Gen4PollerEvent event, void* context) {
|
||||
NfcMagicApp* instance = context;
|
||||
furi_assert(event.data);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(event.type == Gen4PollerEventTypeCardDetected) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventCardDetected);
|
||||
} else if(event.type == Gen4PollerEventTypeRequestMode) {
|
||||
event.data->request_mode.mode = Gen4PollerModeWrite;
|
||||
} else if(event.type == Gen4PollerEventTypeRequestDataToWrite) {
|
||||
NfcProtocol protocol = nfc_device_get_protocol(instance->source_dev);
|
||||
event.data->request_data.protocol = protocol;
|
||||
event.data->request_data.data = nfc_device_get_data(instance->source_dev, protocol);
|
||||
} else if(event.type == Gen4PollerEventTypeSuccess) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(event.type == Gen4PollerEventTypeFail) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcMagicCustomEventWorkerFail);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_write_setup_view(NfcMagicApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWrite);
|
||||
uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneWrite);
|
||||
|
||||
if(state == NfcMagicSceneWriteStateCardSearch) {
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
instance->popup, "Apply the\nsame card\nto the back", 128, 32, AlignRight, AlignCenter);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
nfc_magic_scene_write_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
nfc_magic_scene_write_setup_view(instance);
|
||||
|
||||
// Setup and start worker
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateWrite,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_write_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
nfc_magic_app_blink_start(instance);
|
||||
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
instance->gen1a_poller = gen1a_poller_alloc(instance->nfc);
|
||||
gen1a_poller_start(
|
||||
instance->gen1a_poller, nfc_mafic_scene_write_gen1_poller_callback, instance);
|
||||
} else {
|
||||
instance->gen4_poller = gen4_poller_alloc(instance->nfc);
|
||||
gen4_poller_start(
|
||||
instance->gen4_poller, nfc_mafic_scene_write_gen4_poller_callback, instance);
|
||||
}
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_write_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicWorkerEventSuccess) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventFail) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteFail);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventWrongCard) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventCardDetected) {
|
||||
if(event.event == NfcMagicCustomEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardFound);
|
||||
nfc_magic_scene_write_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardFound);
|
||||
nfc_magic_scene_write_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
|
||||
} else if(event.event == NfcMagicCustomEventCardLost) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
nfc_magic_scene_write_setup_view(nfc_magic);
|
||||
instance->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
nfc_magic_scene_write_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerSuccess) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicCustomEventWorkerFail) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWriteFail);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
if(instance->protocol == NfcMagicProtocolGen1) {
|
||||
gen1a_poller_stop(instance->gen1a_poller);
|
||||
gen1a_poller_free(instance->gen1a_poller);
|
||||
} else {
|
||||
gen4_poller_stop(instance->gen4_poller);
|
||||
gen4_poller_free(instance->gen4_poller);
|
||||
}
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
instance->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
popup_reset(instance->popup);
|
||||
|
||||
nfc_magic_blink_stop(nfc_magic);
|
||||
nfc_magic_app_blink_stop(instance);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_write_confirm_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_confirm_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
widget_add_string_element(widget, 3, 0, AlignLeft, AlignTop, FontPrimary, "Risky operation");
|
||||
widget_add_text_box_element(
|
||||
@@ -30,27 +31,23 @@ void nfc_magic_scene_write_confirm_on_enter(void* context) {
|
||||
GuiButtonTypeCenter,
|
||||
"Continue",
|
||||
nfc_magic_scene_write_confirm_widget_callback,
|
||||
nfc_magic);
|
||||
instance);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Back",
|
||||
nfc_magic_scene_write_confirm_widget_callback,
|
||||
nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Back", nfc_magic_scene_write_confirm_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_write_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeCenter) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrite);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWrite);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +55,7 @@ bool nfc_magic_scene_write_confirm_on_event(void* context, SceneManagerEvent eve
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_confirm_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_write_fail_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_fail_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
@@ -29,30 +29,30 @@ void nfc_magic_scene_write_fail_on_enter(void* context) {
|
||||
"Not all sectors\nwere written\ncorrectly.");
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_write_fail_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_write_fail_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_write_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
instance->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_write_fail_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../nfc_magic_app_i.h"
|
||||
|
||||
void nfc_magic_scene_wrong_card_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wrong_card_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
NfcMagicApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
@@ -28,26 +28,26 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) {
|
||||
FontSecondary,
|
||||
"Writing this file is\nnot supported for\nthis magic card.");
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic);
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_wrong_card_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_wrong_card_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
NfcMagicApp* instance = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user