mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 16:38:35 -07:00
Merge branch 'ofw-dev' into dev
This commit is contained in:
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);
|
||||||
22
applications/external/nfc_magic/nfc_magic.c
vendored
22
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);
|
||||||
@@ -107,10 +116,14 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
|||||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
|
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
|
||||||
loading_free(nfc_magic->loading);
|
loading_free(nfc_magic->loading);
|
||||||
|
|
||||||
// TextInput
|
// Text Input
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
372
applications/external/nfc_magic/nfc_magic_worker.c
vendored
372
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,10 +46,13 @@ 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);
|
||||||
|
|
||||||
furi_hal_nfc_deinit();
|
furi_hal_nfc_deinit();
|
||||||
@@ -54,7 +60,9 @@ void nfc_magic_worker_start(
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -66,6 +74,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);
|
||||||
}
|
}
|
||||||
@@ -77,59 +87,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) {
|
||||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
do {
|
||||||
if(!card_found_notified) {
|
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||||
nfc_magic_worker->callback(
|
if(nfc_data.cuid != magic_dev->cuid) break;
|
||||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
if(!card_found_notified) {
|
||||||
card_found_notified = true;
|
nfc_magic_worker->callback(
|
||||||
}
|
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||||
furi_hal_nfc_sleep();
|
card_found_notified = true;
|
||||||
if(!magic_wupa()) {
|
}
|
||||||
FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
|
furi_hal_nfc_sleep();
|
||||||
nfc_magic_worker->callback(
|
|
||||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
magic_activate();
|
||||||
break;
|
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||||
}
|
if(dev_protocol != NfcDeviceProtocolMifareClassic) break;
|
||||||
furi_hal_nfc_sleep();
|
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||||
}
|
|
||||||
if(magic_wupa()) {
|
if(mfc_data->type != MfClassicType1k) break;
|
||||||
if(!magic_data_access_cmd()) {
|
if(!magic_gen1_wupa()) {
|
||||||
FURI_LOG_E(TAG, "No card response to data access command (not a magic card)");
|
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);
|
||||||
break;
|
done = true;
|
||||||
}
|
break;
|
||||||
for(size_t i = 0; i < 64; i++) {
|
}
|
||||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
if(!magic_gen1_data_access_cmd()) {
|
||||||
if(!magic_write_blk(i, &src_data->block[i])) {
|
FURI_LOG_E(TAG, "Not Magic card");
|
||||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
nfc_magic_worker->callback(
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
nfc_magic_worker->callback(
|
||||||
|
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_magic_worker->callback(
|
||||||
|
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||||
|
done = true;
|
||||||
|
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 {
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
} while(false);
|
||||||
break;
|
|
||||||
} else {
|
if(done) break;
|
||||||
if(card_found_notified) {
|
|
||||||
nfc_magic_worker->callback(
|
if(card_found_notified) {
|
||||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
nfc_magic_worker->callback(
|
||||||
card_found_notified = false;
|
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||||
}
|
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);
|
||||||
@@ -138,12 +334,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) {
|
||||||
|
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) {
|
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;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
@@ -151,6 +391,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;
|
||||||
@@ -162,14 +406,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) {
|
||||||
magic_deactivate();
|
do {
|
||||||
furi_delay_ms(300);
|
magic_deactivate();
|
||||||
if(!magic_wupa()) continue;
|
furi_delay_ms(300);
|
||||||
if(!magic_wipe()) continue;
|
if(!magic_activate()) break;
|
||||||
if(!magic_data_access_cmd()) continue;
|
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||||
if(!magic_write_blk(0, &block)) continue;
|
if(!magic_gen1_wupa()) break;
|
||||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
if(!card_found_notified) {
|
||||||
break;
|
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);
|
||||||
|
} 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);
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,8 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
|
|||||||
|
|
||||||
if(infrared_signal_is_raw(signal)) {
|
if(infrared_signal_is_raw(signal)) {
|
||||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||||
infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
|
infrared_worker_set_raw_signal(
|
||||||
|
infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
|
||||||
} else {
|
} else {
|
||||||
InfraredMessage* message = infrared_signal_get_message(signal);
|
InfraredMessage* message = infrared_signal_get_message(signal);
|
||||||
infrared_worker_set_decoded_signal(infrared->worker, message);
|
infrared_worker_set_decoded_signal(infrared->worker, message);
|
||||||
|
|||||||
@@ -247,6 +247,9 @@ void desktop_lock(Desktop* desktop) {
|
|||||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||||
notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000);
|
notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000);
|
||||||
|
|
||||||
|
DesktopStatus status = {.locked = true};
|
||||||
|
furi_pubsub_publish(desktop->status_pubsub, &status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_unlock(Desktop* desktop) {
|
void desktop_unlock(Desktop* desktop) {
|
||||||
@@ -265,6 +268,9 @@ void desktop_unlock(Desktop* desktop) {
|
|||||||
cli_session_open(cli, &cli_vcp);
|
cli_session_open(cli, &cli_vcp);
|
||||||
furi_record_close(RECORD_CLI);
|
furi_record_close(RECORD_CLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DesktopStatus status = {.locked = false};
|
||||||
|
furi_pubsub_publish(desktop->status_pubsub, &status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
|
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
|
||||||
@@ -415,6 +421,8 @@ Desktop* desktop_alloc() {
|
|||||||
desktop->auto_lock_timer =
|
desktop->auto_lock_timer =
|
||||||
furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop);
|
furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop);
|
||||||
|
|
||||||
|
desktop->status_pubsub = furi_pubsub_alloc();
|
||||||
|
|
||||||
desktop->update_clock_timer =
|
desktop->update_clock_timer =
|
||||||
furi_timer_alloc(desktop_update_clock_timer_callback, FuriTimerTypePeriodic, desktop);
|
furi_timer_alloc(desktop_update_clock_timer_callback, FuriTimerTypePeriodic, desktop);
|
||||||
|
|
||||||
@@ -452,6 +460,11 @@ void desktop_api_unlock(Desktop* instance) {
|
|||||||
view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked);
|
view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
return instance->status_pubsub;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t desktop_srv(void* p) {
|
int32_t desktop_srv(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
typedef struct Desktop Desktop;
|
typedef struct Desktop Desktop;
|
||||||
|
|
||||||
#define RECORD_DESKTOP "desktop"
|
#define RECORD_DESKTOP "desktop"
|
||||||
@@ -7,3 +9,9 @@ typedef struct Desktop Desktop;
|
|||||||
bool desktop_api_is_locked(Desktop* instance);
|
bool desktop_api_is_locked(Desktop* instance);
|
||||||
|
|
||||||
void desktop_api_unlock(Desktop* instance);
|
void desktop_api_unlock(Desktop* instance);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool locked;
|
||||||
|
} DesktopStatus;
|
||||||
|
|
||||||
|
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ struct Desktop {
|
|||||||
FuriTimer* auto_lock_timer;
|
FuriTimer* auto_lock_timer;
|
||||||
FuriTimer* update_clock_timer;
|
FuriTimer* update_clock_timer;
|
||||||
|
|
||||||
|
FuriPubSub* status_pubsub;
|
||||||
uint8_t hour;
|
uint8_t hour;
|
||||||
uint8_t minute;
|
uint8_t minute;
|
||||||
bool clock_type : 1; // true - 24h false - 12h
|
bool clock_type : 1; // true - 24h false - 12h
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
RpcSession* session;
|
RpcSession* session;
|
||||||
Desktop* desktop;
|
Desktop* desktop;
|
||||||
|
FuriPubSub* status_pubsub;
|
||||||
|
FuriPubSubSubscription* status_subscription;
|
||||||
} RpcDesktop;
|
} RpcDesktop;
|
||||||
|
|
||||||
static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) {
|
static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) {
|
||||||
@@ -39,11 +41,63 @@ static void rpc_desktop_on_unlock_request(const PB_Main* request, void* context)
|
|||||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rpc_desktop_on_desktop_pubsub(const void* message, void* context) {
|
||||||
|
RpcDesktop* rpc_desktop = context;
|
||||||
|
RpcSession* session = rpc_desktop->session;
|
||||||
|
const DesktopStatus* status = message;
|
||||||
|
|
||||||
|
PB_Main rpc_message = {
|
||||||
|
.command_id = 0,
|
||||||
|
.command_status = PB_CommandStatus_OK,
|
||||||
|
.has_next = false,
|
||||||
|
.which_content = PB_Main_desktop_status_tag,
|
||||||
|
.content.desktop_status.locked = status->locked,
|
||||||
|
};
|
||||||
|
rpc_send_and_release(session, &rpc_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_desktop_on_status_subscribe_request(const PB_Main* request, void* context) {
|
||||||
|
furi_assert(request);
|
||||||
|
furi_assert(context);
|
||||||
|
furi_assert(request->which_content == PB_Main_desktop_status_subscribe_request_tag);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "StatusSubscribeRequest");
|
||||||
|
RpcDesktop* rpc_desktop = context;
|
||||||
|
RpcSession* session = rpc_desktop->session;
|
||||||
|
|
||||||
|
if(rpc_desktop->status_subscription) {
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR);
|
||||||
|
} else {
|
||||||
|
rpc_desktop->status_subscription = furi_pubsub_subscribe(
|
||||||
|
rpc_desktop->status_pubsub, rpc_desktop_on_desktop_pubsub, rpc_desktop);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_desktop_on_status_unsubscribe_request(const PB_Main* request, void* context) {
|
||||||
|
furi_assert(request);
|
||||||
|
furi_assert(context);
|
||||||
|
furi_assert(request->which_content == PB_Main_desktop_status_unsubscribe_request_tag);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "StatusUnsubscribeRequest");
|
||||||
|
RpcDesktop* rpc_desktop = context;
|
||||||
|
RpcSession* session = rpc_desktop->session;
|
||||||
|
|
||||||
|
if(rpc_desktop->status_subscription) {
|
||||||
|
furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription);
|
||||||
|
rpc_desktop->status_subscription = NULL;
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||||
|
} else {
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* rpc_desktop_alloc(RpcSession* session) {
|
void* rpc_desktop_alloc(RpcSession* session) {
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop));
|
RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop));
|
||||||
rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP);
|
rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP);
|
||||||
|
rpc_desktop->status_pubsub = desktop_api_get_status_pubsub(rpc_desktop->desktop);
|
||||||
rpc_desktop->session = session;
|
rpc_desktop->session = session;
|
||||||
|
|
||||||
RpcHandler rpc_handler = {
|
RpcHandler rpc_handler = {
|
||||||
@@ -58,6 +112,12 @@ void* rpc_desktop_alloc(RpcSession* session) {
|
|||||||
rpc_handler.message_handler = rpc_desktop_on_unlock_request;
|
rpc_handler.message_handler = rpc_desktop_on_unlock_request;
|
||||||
rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler);
|
rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler);
|
||||||
|
|
||||||
|
rpc_handler.message_handler = rpc_desktop_on_status_subscribe_request;
|
||||||
|
rpc_add_handler(session, PB_Main_desktop_status_subscribe_request_tag, &rpc_handler);
|
||||||
|
|
||||||
|
rpc_handler.message_handler = rpc_desktop_on_status_unsubscribe_request;
|
||||||
|
rpc_add_handler(session, PB_Main_desktop_status_unsubscribe_request_tag, &rpc_handler);
|
||||||
|
|
||||||
return rpc_desktop;
|
return rpc_desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +125,10 @@ void rpc_desktop_free(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
RpcDesktop* rpc_desktop = context;
|
RpcDesktop* rpc_desktop = context;
|
||||||
|
|
||||||
|
if(rpc_desktop->status_subscription) {
|
||||||
|
furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription);
|
||||||
|
}
|
||||||
|
|
||||||
furi_assert(rpc_desktop->desktop);
|
furi_assert(rpc_desktop->desktop);
|
||||||
furi_record_close(RECORD_DESKTOP);
|
furi_record_close(RECORD_DESKTOP);
|
||||||
|
|
||||||
|
|||||||
Submodule assets/protobuf updated: a13c5ddd03...f71c4b7f75
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,26.3,,
|
Version,+,27.0,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
|
|||||||
|
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,26.3,,
|
Version,+,27.0,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@@ -1760,7 +1760,7 @@ Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker*
|
|||||||
Function,+,infrared_worker_rx_start,void,InfraredWorker*
|
Function,+,infrared_worker_rx_start,void,InfraredWorker*
|
||||||
Function,+,infrared_worker_rx_stop,void,InfraredWorker*
|
Function,+,infrared_worker_rx_stop,void,InfraredWorker*
|
||||||
Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*"
|
Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*"
|
||||||
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t"
|
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t, uint32_t, float"
|
||||||
Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal*
|
Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal*
|
||||||
Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*"
|
Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*"
|
||||||
Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*"
|
Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*"
|
||||||
|
|||||||
|
@@ -1,7 +1,6 @@
|
|||||||
#include <furi_hal_infrared.h>
|
#include <furi_hal_infrared.h>
|
||||||
#include <core/check.h>
|
#include <core/check.h>
|
||||||
#include "stm32wbxx_ll_dma.h"
|
#include "stm32wbxx_ll_dma.h"
|
||||||
#include "sys/_stdint.h"
|
|
||||||
#include <furi_hal_interrupt.h>
|
#include <furi_hal_interrupt.h>
|
||||||
#include <furi_hal_resources.h>
|
#include <furi_hal_resources.h>
|
||||||
|
|
||||||
@@ -332,8 +331,6 @@ static void furi_hal_infrared_tx_dma_isr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
|
static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
|
||||||
/* LL_DBGMCU_APB2_GRP1_FreezePeriph(LL_DBGMCU_APB2_GRP1_TIM1_STOP); */
|
|
||||||
|
|
||||||
LL_TIM_DisableCounter(TIM1);
|
LL_TIM_DisableCounter(TIM1);
|
||||||
LL_TIM_SetRepetitionCounter(TIM1, 0);
|
LL_TIM_SetRepetitionCounter(TIM1, 0);
|
||||||
LL_TIM_SetCounter(TIM1, 0);
|
LL_TIM_SetCounter(TIM1, 0);
|
||||||
|
|||||||
@@ -40,8 +40,12 @@ struct InfraredWorkerSignal {
|
|||||||
size_t timings_cnt;
|
size_t timings_cnt;
|
||||||
union {
|
union {
|
||||||
InfraredMessage message;
|
InfraredMessage message;
|
||||||
/* +1 is for pause we add at the beginning */
|
struct {
|
||||||
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
|
/* +1 is for pause we add at the beginning */
|
||||||
|
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
|
||||||
|
uint32_t frequency;
|
||||||
|
float duty_cycle;
|
||||||
|
} raw;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,7 +150,7 @@ static void
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) {
|
if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) {
|
||||||
instance->signal.timings[instance->signal.timings_cnt] = duration;
|
instance->signal.raw.timings[instance->signal.timings_cnt] = duration;
|
||||||
++instance->signal.timings_cnt;
|
++instance->signal.timings_cnt;
|
||||||
} else {
|
} else {
|
||||||
uint32_t flags_set = furi_thread_flags_set(
|
uint32_t flags_set = furi_thread_flags_set(
|
||||||
@@ -300,7 +304,7 @@ void infrared_worker_get_raw_signal(
|
|||||||
furi_assert(timings);
|
furi_assert(timings);
|
||||||
furi_assert(timings_cnt);
|
furi_assert(timings_cnt);
|
||||||
|
|
||||||
*timings = signal->timings;
|
*timings = signal->raw.timings;
|
||||||
*timings_cnt = signal->timings_cnt;
|
*timings_cnt = signal->timings_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,8 +394,8 @@ static bool infrared_get_new_signal(InfraredWorker* instance) {
|
|||||||
infrared_get_protocol_duty_cycle(instance->signal.message.protocol);
|
infrared_get_protocol_duty_cycle(instance->signal.message.protocol);
|
||||||
} else {
|
} else {
|
||||||
furi_assert(instance->signal.timings_cnt > 1);
|
furi_assert(instance->signal.timings_cnt > 1);
|
||||||
new_tx_frequency = INFRARED_COMMON_CARRIER_FREQUENCY;
|
new_tx_frequency = instance->signal.raw.frequency;
|
||||||
new_tx_duty_cycle = INFRARED_COMMON_DUTY_CYCLE;
|
new_tx_duty_cycle = instance->signal.raw.duty_cycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->tx.tx_raw_cnt = 0;
|
instance->tx.tx_raw_cnt = 0;
|
||||||
@@ -426,7 +430,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
|
|||||||
if(instance->signal.decoded) {
|
if(instance->signal.decoded) {
|
||||||
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
|
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
|
||||||
} else {
|
} else {
|
||||||
timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt];
|
timing.duration = instance->signal.raw.timings[instance->tx.tx_raw_cnt];
|
||||||
/* raw always starts from Mark, but we fill it with space delay at start */
|
/* raw always starts from Mark, but we fill it with space delay at start */
|
||||||
timing.level = (instance->tx.tx_raw_cnt % 2);
|
timing.level = (instance->tx.tx_raw_cnt % 2);
|
||||||
++instance->tx.tx_raw_cnt;
|
++instance->tx.tx_raw_cnt;
|
||||||
@@ -597,15 +601,21 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
|
|||||||
void infrared_worker_set_raw_signal(
|
void infrared_worker_set_raw_signal(
|
||||||
InfraredWorker* instance,
|
InfraredWorker* instance,
|
||||||
const uint32_t* timings,
|
const uint32_t* timings,
|
||||||
size_t timings_cnt) {
|
size_t timings_cnt,
|
||||||
|
uint32_t frequency,
|
||||||
|
float duty_cycle) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(timings);
|
furi_assert(timings);
|
||||||
furi_assert(timings_cnt > 0);
|
furi_assert(timings_cnt > 0);
|
||||||
size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1;
|
furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY));
|
||||||
|
furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f));
|
||||||
|
size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1;
|
||||||
furi_check(timings_cnt <= max_copy_num);
|
furi_check(timings_cnt <= max_copy_num);
|
||||||
|
|
||||||
instance->signal.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
|
instance->signal.raw.frequency = frequency;
|
||||||
memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t));
|
instance->signal.raw.duty_cycle = duty_cycle;
|
||||||
|
instance->signal.raw.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
|
||||||
|
memcpy(&instance->signal.raw.timings[1], timings, timings_cnt * sizeof(uint32_t));
|
||||||
instance->signal.decoded = false;
|
instance->signal.decoded = false;
|
||||||
instance->signal.timings_cnt = timings_cnt + 1;
|
instance->signal.timings_cnt = timings_cnt + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,9 +130,9 @@ void infrared_worker_tx_set_signal_sent_callback(
|
|||||||
/** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal
|
/** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal
|
||||||
* is steady and will not be changed between infrared_worker start and stop.
|
* is steady and will not be changed between infrared_worker start and stop.
|
||||||
* Before starting transmission, desired steady signal must be set with
|
* Before starting transmission, desired steady signal must be set with
|
||||||
* infrared_worker_make_decoded_signal() or infrared_worker_make_raw_signal().
|
* infrared_worker_set_decoded_signal() or infrared_worker_set_raw_signal().
|
||||||
*
|
*
|
||||||
* This function should not be implicitly called.
|
* This function should not be called directly.
|
||||||
*
|
*
|
||||||
* @param[in] context - context
|
* @param[in] context - context
|
||||||
* @param[out] instance - InfraredWorker instance
|
* @param[out] instance - InfraredWorker instance
|
||||||
@@ -172,11 +172,15 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
|
|||||||
* @param[out] instance - InfraredWorker instance
|
* @param[out] instance - InfraredWorker instance
|
||||||
* @param[in] timings - array of raw timings
|
* @param[in] timings - array of raw timings
|
||||||
* @param[in] timings_cnt - size of array of raw timings
|
* @param[in] timings_cnt - size of array of raw timings
|
||||||
|
* @param[in] frequency - carrier frequency in Hertz
|
||||||
|
* @param[in] duty_cycle - carrier duty cycle (0.0 - 1.0)
|
||||||
*/
|
*/
|
||||||
void infrared_worker_set_raw_signal(
|
void infrared_worker_set_raw_signal(
|
||||||
InfraredWorker* instance,
|
InfraredWorker* instance,
|
||||||
const uint32_t* timings,
|
const uint32_t* timings,
|
||||||
size_t timings_cnt);
|
size_t timings_cnt,
|
||||||
|
uint32_t frequency,
|
||||||
|
float duty_cycle);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user