NFC: Add support for Gen4 "ultimate card" in Magic app (#2238)
* NFC: gen4 gtu detect in magic app * NFC: more support for GTU card * NFC: Fix Gen1 in Magic * Allow double UIDs for MFClassic on GTU cards * NFC: Small magic app tweaks * nfc magic: notify card event on wiping * nfc magic: fix power consumption * nfc magic: disable i2c writing and fix wipe loop * NfcMagic: correct formatting in printf * NfcMagic: correct formatting in printf, proper version * nfc_magic: rework card found notification and gen4 wiping Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
77bb997b0b
commit
490447bbd4
175
applications/external/nfc_magic/lib/magic/classic_gen1.c
vendored
Normal file
175
applications/external/nfc_magic/lib/magic/classic_gen1.c
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#include "classic_gen1.h"
|
||||||
|
|
||||||
|
#include <furi_hal_nfc.h>
|
||||||
|
|
||||||
|
#define TAG "Magic"
|
||||||
|
|
||||||
|
#define MAGIC_CMD_WUPA (0x40)
|
||||||
|
#define MAGIC_CMD_WIPE (0x41)
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool magic_gen1_wipe() {
|
||||||
|
bool wipe_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_WIPE;
|
||||||
|
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(2000));
|
||||||
|
|
||||||
|
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||||
|
if(rx_len != 4) break;
|
||||||
|
if(rx_data[0] != MAGIC_ACK) break;
|
||||||
|
|
||||||
|
wipe_success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return wipe_success;
|
||||||
|
}
|
||||||
13
applications/external/nfc_magic/lib/magic/classic_gen1.h
vendored
Normal file
13
applications/external/nfc_magic/lib/magic/classic_gen1.h
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
bool magic_gen1_wipe();
|
||||||
33
applications/external/nfc_magic/lib/magic/common.c
vendored
Normal file
33
applications/external/nfc_magic/lib/magic/common.c
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#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();
|
||||||
|
}
|
||||||
19
applications/external/nfc_magic/lib/magic/common.h
vendored
Normal file
19
applications/external/nfc_magic/lib/magic/common.h
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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
Normal file
199
applications/external/nfc_magic/lib/magic/gen4.c
vendored
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#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
Normal file
48
applications/external/nfc_magic/lib/magic/gen4.h
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#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();
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "magic.h"
|
#include "classic_gen1.h"
|
||||||
|
|
||||||
#include <furi_hal_nfc.h>
|
#include <furi_hal_nfc.h>
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#define MAGIC_BUFFER_SIZE (32)
|
#define MAGIC_BUFFER_SIZE (32)
|
||||||
|
|
||||||
bool magic_wupa() {
|
bool magic_gen1_wupa() {
|
||||||
bool magic_activated = false;
|
bool magic_activated = false;
|
||||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
@ -23,19 +23,6 @@ bool magic_wupa() {
|
|||||||
FuriHalNfcReturn ret = 0;
|
FuriHalNfcReturn ret = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// 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) break;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Start communication
|
// Start communication
|
||||||
tx_data[0] = MAGIC_CMD_WUPA;
|
tx_data[0] = MAGIC_CMD_WUPA;
|
||||||
ret = furi_hal_nfc_ll_txrx_bits(
|
ret = furi_hal_nfc_ll_txrx_bits(
|
||||||
@ -53,15 +40,10 @@ bool magic_wupa() {
|
|||||||
magic_activated = true;
|
magic_activated = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!magic_activated) {
|
|
||||||
furi_hal_nfc_ll_txrx_off();
|
|
||||||
furi_hal_nfc_start_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
return magic_activated;
|
return magic_activated;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool magic_data_access_cmd() {
|
bool magic_gen1_data_access_cmd() {
|
||||||
bool write_cmd_success = false;
|
bool write_cmd_success = false;
|
||||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
@ -86,15 +68,10 @@ bool magic_data_access_cmd() {
|
|||||||
write_cmd_success = true;
|
write_cmd_success = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!write_cmd_success) {
|
|
||||||
furi_hal_nfc_ll_txrx_off();
|
|
||||||
furi_hal_nfc_start_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
return write_cmd_success;
|
return write_cmd_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
|
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||||
furi_assert(data);
|
furi_assert(data);
|
||||||
|
|
||||||
bool read_success = false;
|
bool read_success = false;
|
||||||
@ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
|
|||||||
read_success = true;
|
read_success = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!read_success) {
|
|
||||||
furi_hal_nfc_ll_txrx_off();
|
|
||||||
furi_hal_nfc_start_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
return read_success;
|
return read_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||||
furi_assert(data);
|
furi_assert(data);
|
||||||
|
|
||||||
bool write_success = false;
|
bool write_success = false;
|
||||||
@ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
|||||||
write_success = true;
|
write_success = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!write_success) {
|
|
||||||
furi_hal_nfc_ll_txrx_off();
|
|
||||||
furi_hal_nfc_start_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
return write_success;
|
return write_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool magic_wipe() {
|
bool magic_gen1_wipe() {
|
||||||
bool wipe_success = false;
|
bool wipe_success = false;
|
||||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||||
@ -206,8 +173,3 @@ bool magic_wipe() {
|
|||||||
|
|
||||||
return wipe_success;
|
return wipe_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void magic_deactivate() {
|
|
||||||
furi_hal_nfc_ll_txrx_off();
|
|
||||||
furi_hal_nfc_sleep();
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <lib/nfc/protocols/mifare_classic.h>
|
|
||||||
|
|
||||||
bool magic_wupa();
|
|
||||||
|
|
||||||
bool magic_read_block(uint8_t block_num, MfClassicBlock* data);
|
|
||||||
|
|
||||||
bool magic_data_access_cmd();
|
|
||||||
|
|
||||||
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data);
|
|
||||||
|
|
||||||
bool magic_wipe();
|
|
||||||
|
|
||||||
void magic_deactivate();
|
|
||||||
23
applications/external/nfc_magic/lib/magic/types.c
vendored
Normal file
23
applications/external/nfc_magic/lib/magic/types.c
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#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";
|
||||||
|
}
|
||||||
|
}
|
||||||
5
applications/external/nfc_magic/lib/magic/types.h
vendored
Normal file
5
applications/external/nfc_magic/lib/magic/types.h
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
const char* nfc_magic_type(MagicType type);
|
||||||
20
applications/external/nfc_magic/nfc_magic.c
vendored
20
applications/external/nfc_magic/nfc_magic.c
vendored
@ -48,8 +48,9 @@ NfcMagic* nfc_magic_alloc() {
|
|||||||
nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100);
|
nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100);
|
||||||
|
|
||||||
// Nfc device
|
// Nfc device
|
||||||
nfc_magic->nfc_dev = nfc_device_alloc();
|
nfc_magic->dev = malloc(sizeof(NfcMagicDevice));
|
||||||
furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER);
|
nfc_magic->source_dev = nfc_device_alloc();
|
||||||
|
furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER);
|
||||||
|
|
||||||
// Open GUI record
|
// Open GUI record
|
||||||
nfc_magic->gui = furi_record_open(RECORD_GUI);
|
nfc_magic->gui = furi_record_open(RECORD_GUI);
|
||||||
@ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() {
|
|||||||
NfcMagicViewTextInput,
|
NfcMagicViewTextInput,
|
||||||
text_input_get_view(nfc_magic->text_input));
|
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
|
// Custom Widget
|
||||||
nfc_magic->widget = widget_alloc();
|
nfc_magic->widget = widget_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
|||||||
furi_assert(nfc_magic);
|
furi_assert(nfc_magic);
|
||||||
|
|
||||||
// Nfc device
|
// Nfc device
|
||||||
nfc_device_free(nfc_magic->nfc_dev);
|
free(nfc_magic->dev);
|
||||||
|
nfc_device_free(nfc_magic->source_dev);
|
||||||
|
|
||||||
// Submenu
|
// Submenu
|
||||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||||
@ -111,6 +120,10 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
|||||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput);
|
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput);
|
||||||
text_input_free(nfc_magic->text_input);
|
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
|
// Custom Widget
|
||||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||||
widget_free(nfc_magic->widget);
|
widget_free(nfc_magic->widget);
|
||||||
@ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) {
|
|||||||
|
|
||||||
view_dispatcher_run(nfc_magic->view_dispatcher);
|
view_dispatcher_run(nfc_magic->view_dispatcher);
|
||||||
|
|
||||||
|
magic_deactivate();
|
||||||
nfc_magic_free(nfc_magic);
|
nfc_magic_free(nfc_magic);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
2
applications/external/nfc_magic/nfc_magic.h
vendored
2
applications/external/nfc_magic/nfc_magic.h
vendored
@ -1,3 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct NfcMagicDevice NfcMagicDevice;
|
||||||
|
|
||||||
typedef struct NfcMagic NfcMagic;
|
typedef struct NfcMagic NfcMagic;
|
||||||
|
|||||||
20
applications/external/nfc_magic/nfc_magic_i.h
vendored
20
applications/external/nfc_magic/nfc_magic_i.h
vendored
@ -3,7 +3,10 @@
|
|||||||
#include "nfc_magic.h"
|
#include "nfc_magic.h"
|
||||||
#include "nfc_magic_worker.h"
|
#include "nfc_magic_worker.h"
|
||||||
|
|
||||||
#include "lib/magic/magic.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 <furi.h>
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
@ -15,6 +18,7 @@
|
|||||||
#include <gui/modules/popup.h>
|
#include <gui/modules/popup.h>
|
||||||
#include <gui/modules/loading.h>
|
#include <gui/modules/loading.h>
|
||||||
#include <gui/modules/text_input.h>
|
#include <gui/modules/text_input.h>
|
||||||
|
#include <gui/modules/byte_input.h>
|
||||||
#include <gui/modules/widget.h>
|
#include <gui/modules/widget.h>
|
||||||
|
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
@ -39,14 +43,22 @@ enum NfcMagicCustomEvent {
|
|||||||
NfcMagicCustomEventTextInputDone,
|
NfcMagicCustomEventTextInputDone,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NfcMagicDevice {
|
||||||
|
MagicType type;
|
||||||
|
uint32_t cuid;
|
||||||
|
uint32_t password;
|
||||||
|
};
|
||||||
|
|
||||||
struct NfcMagic {
|
struct NfcMagic {
|
||||||
NfcMagicWorker* worker;
|
NfcMagicWorker* worker;
|
||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
Gui* gui;
|
Gui* gui;
|
||||||
NotificationApp* notifications;
|
NotificationApp* notifications;
|
||||||
SceneManager* scene_manager;
|
SceneManager* scene_manager;
|
||||||
// NfcMagicDevice* dev;
|
struct NfcMagicDevice* dev;
|
||||||
NfcDevice* nfc_dev;
|
NfcDevice* source_dev;
|
||||||
|
|
||||||
|
uint32_t new_password;
|
||||||
|
|
||||||
FuriString* text_box_store;
|
FuriString* text_box_store;
|
||||||
|
|
||||||
@ -55,6 +67,7 @@ struct NfcMagic {
|
|||||||
Popup* popup;
|
Popup* popup;
|
||||||
Loading* loading;
|
Loading* loading;
|
||||||
TextInput* text_input;
|
TextInput* text_input;
|
||||||
|
ByteInput* byte_input;
|
||||||
Widget* widget;
|
Widget* widget;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,6 +76,7 @@ typedef enum {
|
|||||||
NfcMagicViewPopup,
|
NfcMagicViewPopup,
|
||||||
NfcMagicViewLoading,
|
NfcMagicViewLoading,
|
||||||
NfcMagicViewTextInput,
|
NfcMagicViewTextInput,
|
||||||
|
NfcMagicViewByteInput,
|
||||||
NfcMagicViewWidget,
|
NfcMagicViewWidget,
|
||||||
} NfcMagicView;
|
} NfcMagicView;
|
||||||
|
|
||||||
|
|||||||
318
applications/external/nfc_magic/nfc_magic_worker.c
vendored
318
applications/external/nfc_magic/nfc_magic_worker.c
vendored
@ -1,6 +1,9 @@
|
|||||||
#include "nfc_magic_worker_i.h"
|
#include "nfc_magic_worker_i.h"
|
||||||
|
|
||||||
#include "lib/magic/magic.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"
|
#define TAG "NfcMagicWorker"
|
||||||
|
|
||||||
@ -43,15 +46,20 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
|
|||||||
void nfc_magic_worker_start(
|
void nfc_magic_worker_start(
|
||||||
NfcMagicWorker* nfc_magic_worker,
|
NfcMagicWorker* nfc_magic_worker,
|
||||||
NfcMagicWorkerState state,
|
NfcMagicWorkerState state,
|
||||||
|
NfcMagicDevice* magic_dev,
|
||||||
NfcDeviceData* dev_data,
|
NfcDeviceData* dev_data,
|
||||||
|
uint32_t new_password,
|
||||||
NfcMagicWorkerCallback callback,
|
NfcMagicWorkerCallback callback,
|
||||||
void* context) {
|
void* context) {
|
||||||
furi_assert(nfc_magic_worker);
|
furi_assert(nfc_magic_worker);
|
||||||
|
furi_assert(magic_dev);
|
||||||
furi_assert(dev_data);
|
furi_assert(dev_data);
|
||||||
|
|
||||||
nfc_magic_worker->callback = callback;
|
nfc_magic_worker->callback = callback;
|
||||||
nfc_magic_worker->context = context;
|
nfc_magic_worker->context = context;
|
||||||
|
nfc_magic_worker->magic_dev = magic_dev;
|
||||||
nfc_magic_worker->dev_data = dev_data;
|
nfc_magic_worker->dev_data = dev_data;
|
||||||
|
nfc_magic_worker->new_password = new_password;
|
||||||
nfc_magic_worker_change_state(nfc_magic_worker, state);
|
nfc_magic_worker_change_state(nfc_magic_worker, state);
|
||||||
furi_thread_start(nfc_magic_worker->thread);
|
furi_thread_start(nfc_magic_worker->thread);
|
||||||
}
|
}
|
||||||
@ -63,6 +71,8 @@ int32_t nfc_magic_worker_task(void* context) {
|
|||||||
nfc_magic_worker_check(nfc_magic_worker);
|
nfc_magic_worker_check(nfc_magic_worker);
|
||||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||||
nfc_magic_worker_write(nfc_magic_worker);
|
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) {
|
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||||
nfc_magic_worker_wipe(nfc_magic_worker);
|
nfc_magic_worker_wipe(nfc_magic_worker);
|
||||||
}
|
}
|
||||||
@ -74,59 +84,245 @@ int32_t nfc_magic_worker_task(void* context) {
|
|||||||
|
|
||||||
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
|
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
|
||||||
bool card_found_notified = false;
|
bool card_found_notified = false;
|
||||||
|
bool done = false;
|
||||||
FuriHalNfcDevData nfc_data = {};
|
FuriHalNfcDevData nfc_data = {};
|
||||||
MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_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) {
|
while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||||
|
do {
|
||||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||||
|
if(nfc_data.cuid != magic_dev->cuid) break;
|
||||||
if(!card_found_notified) {
|
if(!card_found_notified) {
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||||
card_found_notified = true;
|
card_found_notified = true;
|
||||||
}
|
}
|
||||||
furi_hal_nfc_sleep();
|
furi_hal_nfc_sleep();
|
||||||
if(!magic_wupa()) {
|
|
||||||
FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
|
magic_activate();
|
||||||
|
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||||
|
if(dev_protocol != NfcDeviceProtocolMifareClassic) break;
|
||||||
|
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||||
|
|
||||||
|
if(mfc_data->type != MfClassicType1k) break;
|
||||||
|
if(!magic_gen1_wupa()) {
|
||||||
|
FURI_LOG_E(TAG, "Not Magic card");
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
furi_hal_nfc_sleep();
|
if(!magic_gen1_data_access_cmd()) {
|
||||||
}
|
FURI_LOG_E(TAG, "Not Magic card");
|
||||||
if(magic_wupa()) {
|
|
||||||
if(!magic_data_access_cmd()) {
|
|
||||||
FURI_LOG_E(TAG, "No card response to data access command (not a magic card)");
|
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < 64; i++) {
|
for(size_t i = 0; i < 64; i++) {
|
||||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||||
if(!magic_write_blk(i, &src_data->block[i])) {
|
if(!magic_gen1_write_blk(i, &mfc_data->block[i])) {
|
||||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
nfc_magic_worker->callback(
|
||||||
|
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
|
||||||
|
nfc_magic_worker->callback(
|
||||||
|
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
} else if(magic_dev->type == MagicTypeGen4) {
|
||||||
|
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 {
|
} 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_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) {
|
if(card_found_notified) {
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||||
card_found_notified = false;
|
card_found_notified = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
furi_delay_ms(300);
|
furi_delay_ms(300);
|
||||||
}
|
}
|
||||||
magic_deactivate();
|
magic_deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
||||||
|
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||||
bool card_found_notified = false;
|
bool card_found_notified = false;
|
||||||
|
uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN];
|
||||||
|
|
||||||
while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
|
while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
|
||||||
if(magic_wupa()) {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_nfc_activate_nfca(200, &magic_dev->cuid);
|
||||||
|
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
magic_deactivate();
|
||||||
|
furi_delay_ms(300);
|
||||||
|
magic_activate();
|
||||||
|
|
||||||
|
furi_hal_nfc_activate_nfca(200, &magic_dev->cuid);
|
||||||
|
if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) {
|
||||||
|
magic_dev->type = MagicTypeGen4;
|
||||||
if(!card_found_notified) {
|
if(!card_found_notified) {
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||||
@ -135,12 +331,56 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
|||||||
|
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if(card_found_notified) {
|
if(card_found_notified) {
|
||||||
nfc_magic_worker->callback(
|
nfc_magic_worker->callback(
|
||||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||||
card_found_notified = false;
|
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);
|
furi_delay_ms(300);
|
||||||
}
|
}
|
||||||
@ -148,6 +388,10 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
|
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;
|
MfClassicBlock block;
|
||||||
memset(&block, 0, sizeof(MfClassicBlock));
|
memset(&block, 0, sizeof(MfClassicBlock));
|
||||||
block.value[0] = 0x01;
|
block.value[0] = 0x01;
|
||||||
@ -159,14 +403,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
|
|||||||
block.value[6] = 0x04;
|
block.value[6] = 0x04;
|
||||||
|
|
||||||
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||||
|
do {
|
||||||
magic_deactivate();
|
magic_deactivate();
|
||||||
furi_delay_ms(300);
|
furi_delay_ms(300);
|
||||||
if(!magic_wupa()) continue;
|
if(!magic_activate()) break;
|
||||||
if(!magic_wipe()) continue;
|
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||||
if(!magic_data_access_cmd()) continue;
|
if(!magic_gen1_wupa()) break;
|
||||||
if(!magic_write_blk(0, &block)) continue;
|
if(!card_found_notified) {
|
||||||
|
nfc_magic_worker->callback(
|
||||||
|
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||||
|
card_found_notified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!magic_gen1_wipe()) break;
|
||||||
|
if(!magic_gen1_data_access_cmd()) break;
|
||||||
|
if(!magic_gen1_write_blk(0, &block)) break;
|
||||||
|
|
||||||
|
card_wiped = true;
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||||
break;
|
} 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();
|
magic_deactivate();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <lib/nfc/nfc_device.h>
|
#include <lib/nfc/nfc_device.h>
|
||||||
|
#include "nfc_magic.h"
|
||||||
|
|
||||||
typedef struct NfcMagicWorker NfcMagicWorker;
|
typedef struct NfcMagicWorker NfcMagicWorker;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ typedef enum {
|
|||||||
|
|
||||||
NfcMagicWorkerStateCheck,
|
NfcMagicWorkerStateCheck,
|
||||||
NfcMagicWorkerStateWrite,
|
NfcMagicWorkerStateWrite,
|
||||||
|
NfcMagicWorkerStateRekey,
|
||||||
NfcMagicWorkerStateWipe,
|
NfcMagicWorkerStateWipe,
|
||||||
|
|
||||||
NfcMagicWorkerStateStop,
|
NfcMagicWorkerStateStop,
|
||||||
@ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker);
|
|||||||
void nfc_magic_worker_start(
|
void nfc_magic_worker_start(
|
||||||
NfcMagicWorker* nfc_magic_worker,
|
NfcMagicWorker* nfc_magic_worker,
|
||||||
NfcMagicWorkerState state,
|
NfcMagicWorkerState state,
|
||||||
|
NfcMagicDevice* magic_dev,
|
||||||
NfcDeviceData* dev_data,
|
NfcDeviceData* dev_data,
|
||||||
|
uint32_t new_password,
|
||||||
NfcMagicWorkerCallback callback,
|
NfcMagicWorkerCallback callback,
|
||||||
void* context);
|
void* context);
|
||||||
|
|||||||
@ -3,11 +3,14 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#include "nfc_magic_worker.h"
|
#include "nfc_magic_worker.h"
|
||||||
|
#include "lib/magic/common.h"
|
||||||
|
|
||||||
struct NfcMagicWorker {
|
struct NfcMagicWorker {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
|
NfcMagicDevice* magic_dev;
|
||||||
NfcDeviceData* dev_data;
|
NfcDeviceData* dev_data;
|
||||||
|
uint32_t new_password;
|
||||||
|
|
||||||
NfcMagicWorkerCallback callback;
|
NfcMagicWorkerCallback callback;
|
||||||
void* context;
|
void* context;
|
||||||
@ -21,4 +24,6 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker);
|
|||||||
|
|
||||||
void nfc_magic_worker_write(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);
|
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker);
|
||||||
|
|||||||
50
applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
vendored
Normal file
50
applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
@ -42,7 +42,9 @@ void nfc_magic_scene_check_on_enter(void* context) {
|
|||||||
nfc_magic_worker_start(
|
nfc_magic_worker_start(
|
||||||
nfc_magic->worker,
|
nfc_magic->worker,
|
||||||
NfcMagicWorkerStateCheck,
|
NfcMagicWorkerStateCheck,
|
||||||
&nfc_magic->nfc_dev->dev_data,
|
nfc_magic->dev,
|
||||||
|
&nfc_magic->source_dev->dev_data,
|
||||||
|
nfc_magic->new_password,
|
||||||
nfc_magic_check_worker_callback,
|
nfc_magic_check_worker_callback,
|
||||||
nfc_magic);
|
nfc_magic);
|
||||||
nfc_magic_blink_start(nfc_magic);
|
nfc_magic_blink_start(nfc_magic);
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
ADD_SCENE(nfc_magic, start, Start)
|
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, file_select, FileSelect)
|
||||||
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
|
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
|
||||||
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
|
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
|
||||||
@ -8,5 +12,7 @@ ADD_SCENE(nfc_magic, success, Success)
|
|||||||
ADD_SCENE(nfc_magic, check, Check)
|
ADD_SCENE(nfc_magic, check, Check)
|
||||||
ADD_SCENE(nfc_magic, not_magic, NotMagic)
|
ADD_SCENE(nfc_magic, not_magic, NotMagic)
|
||||||
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
|
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
|
||||||
|
ADD_SCENE(nfc_magic, rekey, Rekey)
|
||||||
|
ADD_SCENE(nfc_magic, rekey_fail, RekeyFail)
|
||||||
ADD_SCENE(nfc_magic, wipe, Wipe)
|
ADD_SCENE(nfc_magic, wipe, Wipe)
|
||||||
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)
|
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)
|
||||||
|
|||||||
@ -1,22 +1,60 @@
|
|||||||
#include "../nfc_magic_i.h"
|
#include "../nfc_magic_i.h"
|
||||||
|
|
||||||
static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) {
|
static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) {
|
||||||
return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) &&
|
NfcDevice* nfc_dev = nfc_magic->source_dev;
|
||||||
(nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) &&
|
if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||||
(nfc_dev->dev_data.nfc_data.uid_len == 4);
|
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 != 4)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_magic_scene_file_select_on_enter(void* context) {
|
void nfc_magic_scene_file_select_on_enter(void* context) {
|
||||||
NfcMagic* nfc_magic = context;
|
NfcMagic* nfc_magic = context;
|
||||||
// Process file_select return
|
// Process file_select return
|
||||||
nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic);
|
nfc_device_set_loading_callback(
|
||||||
|
nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic);
|
||||||
|
|
||||||
if(!furi_string_size(nfc_magic->nfc_dev->load_path)) {
|
if(!furi_string_size(nfc_magic->source_dev->load_path)) {
|
||||||
furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER);
|
furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER);
|
||||||
}
|
}
|
||||||
|
if(nfc_file_select(nfc_magic->source_dev)) {
|
||||||
if(nfc_file_select(nfc_magic->nfc_dev)) {
|
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) {
|
||||||
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) {
|
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard);
|
||||||
@ -34,5 +72,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event
|
|||||||
|
|
||||||
void nfc_magic_scene_file_select_on_exit(void* context) {
|
void nfc_magic_scene_file_select_on_exit(void* context) {
|
||||||
NfcMagic* nfc_magic = context;
|
NfcMagic* nfc_magic = context;
|
||||||
nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic);
|
nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic);
|
||||||
}
|
}
|
||||||
|
|||||||
70
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
vendored
Normal file
70
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
45
applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
vendored
Normal file
45
applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "../nfc_magic_i.h"
|
||||||
|
|
||||||
|
void nfc_magic_scene_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_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_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_magic_scene_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, NfcMagicSceneCheck);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_magic_scene_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,4 +1,5 @@
|
|||||||
#include "../nfc_magic_i.h"
|
#include "../nfc_magic_i.h"
|
||||||
|
#include "../lib/magic/types.h"
|
||||||
|
|
||||||
void nfc_magic_scene_magic_info_widget_callback(
|
void nfc_magic_scene_magic_info_widget_callback(
|
||||||
GuiButtonType result,
|
GuiButtonType result,
|
||||||
@ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback(
|
|||||||
void nfc_magic_scene_magic_info_on_enter(void* context) {
|
void nfc_magic_scene_magic_info_on_enter(void* context) {
|
||||||
NfcMagic* nfc_magic = context;
|
NfcMagic* nfc_magic = context;
|
||||||
Widget* widget = nfc_magic->widget;
|
Widget* widget = nfc_magic->widget;
|
||||||
|
const char* card_type = nfc_magic_type(nfc_magic->dev->type);
|
||||||
|
|
||||||
notification_message(nfc_magic->notifications, &sequence_success);
|
notification_message(nfc_magic->notifications, &sequence_success);
|
||||||
|
|
||||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||||
widget_add_string_element(
|
widget_add_string_element(
|
||||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected");
|
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected");
|
||||||
|
widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type);
|
||||||
widget_add_button_element(
|
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, nfc_magic);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
|
||||||
|
|
||||||
// Setup and start worker
|
// Setup and start worker
|
||||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||||
@ -33,6 +38,15 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event)
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == GuiButtonTypeLeft) {
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
consumed = scene_manager_previous_scene(nfc_magic->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);
|
||||||
|
consumed = true;
|
||||||
|
} else {
|
||||||
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
45
applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
vendored
Normal file
45
applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#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, "");
|
||||||
|
}
|
||||||
95
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
vendored
Normal file
95
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
50
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
vendored
Normal file
50
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#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,8 +1,7 @@
|
|||||||
#include "../nfc_magic_i.h"
|
#include "../nfc_magic_i.h"
|
||||||
enum SubmenuIndex {
|
enum SubmenuIndex {
|
||||||
SubmenuIndexCheck,
|
SubmenuIndexCheck,
|
||||||
SubmenuIndexWriteGen1A,
|
SubmenuIndexAuthenticateGen4,
|
||||||
SubmenuIndexWipe,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) {
|
void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||||
@ -22,12 +21,10 @@ void nfc_magic_scene_start_on_enter(void* context) {
|
|||||||
nfc_magic);
|
nfc_magic);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Write Gen1A",
|
"Authenticate Gen4",
|
||||||
SubmenuIndexWriteGen1A,
|
SubmenuIndexAuthenticateGen4,
|
||||||
nfc_magic_scene_start_submenu_callback,
|
nfc_magic_scene_start_submenu_callback,
|
||||||
nfc_magic);
|
nfc_magic);
|
||||||
submenu_add_item(
|
|
||||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic);
|
|
||||||
|
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart));
|
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart));
|
||||||
@ -40,23 +37,13 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexCheck) {
|
if(event.event == SubmenuIndexCheck) {
|
||||||
|
nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD;
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexWriteGen1A) {
|
} else if(event.event == SubmenuIndexAuthenticateGen4) {
|
||||||
// Explicitly save state in each branch so that the
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput);
|
||||||
// correct option is reselected if the user cancels
|
|
||||||
// loading a file.
|
|
||||||
scene_manager_set_scene_state(
|
|
||||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A);
|
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
|
||||||
consumed = true;
|
|
||||||
} else if(event.event == SubmenuIndexWipe) {
|
|
||||||
scene_manager_set_scene_state(
|
|
||||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe);
|
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
|
||||||
consumed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) {
|
|||||||
if(state == NfcMagicSceneWipeStateCardSearch) {
|
if(state == NfcMagicSceneWipeStateCardSearch) {
|
||||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
popup_set_text(
|
popup_set_text(
|
||||||
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
nfc_magic->popup,
|
||||||
|
"Apply the\nsame card\nto the back",
|
||||||
|
128,
|
||||||
|
32,
|
||||||
|
AlignRight,
|
||||||
|
AlignCenter);
|
||||||
} else {
|
} else {
|
||||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||||
popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||||
@ -42,7 +47,9 @@ void nfc_magic_scene_wipe_on_enter(void* context) {
|
|||||||
nfc_magic_worker_start(
|
nfc_magic_worker_start(
|
||||||
nfc_magic->worker,
|
nfc_magic->worker,
|
||||||
NfcMagicWorkerStateWipe,
|
NfcMagicWorkerStateWipe,
|
||||||
&nfc_magic->nfc_dev->dev_data,
|
nfc_magic->dev,
|
||||||
|
&nfc_magic->source_dev->dev_data,
|
||||||
|
nfc_magic->new_password,
|
||||||
nfc_magic_wipe_worker_callback,
|
nfc_magic_wipe_worker_callback,
|
||||||
nfc_magic);
|
nfc_magic);
|
||||||
nfc_magic_blink_start(nfc_magic);
|
nfc_magic_blink_start(nfc_magic);
|
||||||
|
|||||||
@ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) {
|
|||||||
|
|
||||||
if(state == NfcMagicSceneWriteStateCardSearch) {
|
if(state == NfcMagicSceneWriteStateCardSearch) {
|
||||||
popup_set_text(
|
popup_set_text(
|
||||||
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
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);
|
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
} else {
|
} else {
|
||||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||||
@ -42,7 +47,9 @@ void nfc_magic_scene_write_on_enter(void* context) {
|
|||||||
nfc_magic_worker_start(
|
nfc_magic_worker_start(
|
||||||
nfc_magic->worker,
|
nfc_magic->worker,
|
||||||
NfcMagicWorkerStateWrite,
|
NfcMagicWorkerStateWrite,
|
||||||
&nfc_magic->nfc_dev->dev_data,
|
nfc_magic->dev,
|
||||||
|
&nfc_magic->source_dev->dev_data,
|
||||||
|
nfc_magic->new_password,
|
||||||
nfc_magic_write_worker_callback,
|
nfc_magic_write_worker_callback,
|
||||||
nfc_magic);
|
nfc_magic);
|
||||||
nfc_magic_blink_start(nfc_magic);
|
nfc_magic_blink_start(nfc_magic);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) {
|
|||||||
AlignLeft,
|
AlignLeft,
|
||||||
AlignTop,
|
AlignTop,
|
||||||
FontSecondary,
|
FontSecondary,
|
||||||
"Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k");
|
"Writing this file is\nnot supported for\nthis magic card.");
|
||||||
widget_add_button_element(
|
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, nfc_magic);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user