mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-07 19:01:54 -07:00
fmt
This commit is contained in:
@@ -114,39 +114,81 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
||||
furi_string_cat_printf(temp_str, "\n");
|
||||
|
||||
switch(dev_data->nfcv_data.type) {
|
||||
case NfcVTypePlain:
|
||||
furi_string_cat_printf(temp_str, "Type: Plain\n");
|
||||
break;
|
||||
case NfcVTypeSlix:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlixS:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX-S\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read));
|
||||
furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write));
|
||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlixL:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX-L\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlix2:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX2\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read));
|
||||
furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write));
|
||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypePlain:
|
||||
furi_string_cat_printf(temp_str, "Type: Plain\n");
|
||||
break;
|
||||
case NfcVTypeSlix:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" EAS %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlixS:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX-S\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Read %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Write %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Privacy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Destroy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" EAS %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlixL:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX-L\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Privacy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Destroy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" EAS %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
case NfcVTypeSlix2:
|
||||
furi_string_cat_printf(temp_str, "Type: SLIX2\n");
|
||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Read %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Write %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Privacy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" Destroy %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy));
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
" EAS %08lX\n",
|
||||
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||
break;
|
||||
default:
|
||||
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
|
||||
break;
|
||||
|
||||
@@ -159,7 +159,7 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
||||
|
||||
NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data;
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
uint8_t *key_data = nfcv_data->sub_data.slix.key_privacy;
|
||||
uint8_t* key_data = nfcv_data->sub_data.slix.key_privacy;
|
||||
uint32_t key = 0;
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
|
||||
+359
-247
@@ -22,8 +22,7 @@ ReturnCode nfcv_inventory(uint8_t* uid) {
|
||||
|
||||
for(int tries = 0; tries < 5; tries++) {
|
||||
/* TODO: needs proper abstraction via fury_hal(_ll)_* */
|
||||
ret = rfalNfcvPollerInventory(
|
||||
RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received);
|
||||
ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received);
|
||||
|
||||
if(ret == ERR_NONE) {
|
||||
break;
|
||||
@@ -39,10 +38,7 @@ ReturnCode nfcv_inventory(uint8_t* uid) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ReturnCode nfcv_read_blocks(
|
||||
NfcVReader* reader,
|
||||
NfcVData* data) {
|
||||
|
||||
ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data) {
|
||||
UNUSED(reader);
|
||||
|
||||
uint16_t received = 0;
|
||||
@@ -53,8 +49,7 @@ ReturnCode nfcv_read_blocks(
|
||||
ReturnCode ret = ERR_NONE;
|
||||
for(int tries = 0; tries < 5; tries++) {
|
||||
ret = rfalNfcvPollerReadSingleBlock(
|
||||
RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block,
|
||||
rxBuf, sizeof(rxBuf), &received);
|
||||
RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block, rxBuf, sizeof(rxBuf), &received);
|
||||
|
||||
if(ret == ERR_NONE) {
|
||||
break;
|
||||
@@ -65,9 +60,13 @@ ReturnCode nfcv_read_blocks(
|
||||
return ret;
|
||||
}
|
||||
memcpy(&(data->data[block * data->block_size]), &rxBuf[1], data->block_size);
|
||||
FURI_LOG_D(TAG, " %02X %02X %02X %02X",
|
||||
data->data[block * data->block_size + 0], data->data[block * data->block_size + 1],
|
||||
data->data[block * data->block_size + 2], data->data[block * data->block_size + 3]);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" %02X %02X %02X %02X",
|
||||
data->data[block * data->block_size + 0],
|
||||
data->data[block * data->block_size + 1],
|
||||
data->data[block * data->block_size + 2],
|
||||
data->data[block * data->block_size + 3]);
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
@@ -102,10 +101,25 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) {
|
||||
data->block_num = rxBuf[12] + 1;
|
||||
data->block_size = rxBuf[13] + 1;
|
||||
data->ic_ref = rxBuf[14];
|
||||
FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
||||
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
||||
FURI_LOG_D(TAG, " DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d", data->dsfid, data->afi, data->block_num, data->block_size, data->ic_ref);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
nfc_data->uid[0],
|
||||
nfc_data->uid[1],
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3],
|
||||
nfc_data->uid[4],
|
||||
nfc_data->uid[5],
|
||||
nfc_data->uid[6],
|
||||
nfc_data->uid[7]);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d",
|
||||
data->dsfid,
|
||||
data->afi,
|
||||
data->block_num,
|
||||
data->block_size,
|
||||
data->ic_ref);
|
||||
return ret;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Failed: %d", ret);
|
||||
@@ -113,10 +127,7 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool nfcv_read_card(
|
||||
NfcVReader* reader,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
NfcVData* nfcv_data) {
|
||||
bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||
furi_assert(reader);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data);
|
||||
@@ -148,15 +159,13 @@ bool nfcv_read_card(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nfcv_crc(uint8_t* data, uint32_t length) {
|
||||
uint32_t reg = 0xFFFF;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
reg = reg ^ ((uint32_t)data[i]);
|
||||
for (size_t j = 0; j < 8; j++) {
|
||||
if (reg & 0x0001) {
|
||||
for(size_t j = 0; j < 8; j++) {
|
||||
if(reg & 0x0001) {
|
||||
reg = (reg >> 1) ^ 0x8408;
|
||||
} else {
|
||||
reg = (reg >> 1);
|
||||
@@ -198,15 +207,18 @@ void nfcv_emu_alloc(NfcVData* data) {
|
||||
/* unmodulated 256/fc signal as building block */
|
||||
data->emu_air.nfcv_resp_unmod_256 = digital_signal_alloc(4);
|
||||
data->emu_air.nfcv_resp_unmod_256->start_level = false;
|
||||
data->emu_air.nfcv_resp_unmod_256->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_unmod_256->edge_timings[0] =
|
||||
(uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_unmod_256->edge_cnt = 1;
|
||||
}
|
||||
if(!data->emu_air.nfcv_resp_pulse_32) {
|
||||
/* modulated fc/32 pulse as building block */
|
||||
data->emu_air.nfcv_resp_pulse_32 = digital_signal_alloc(4);
|
||||
data->emu_air.nfcv_resp_pulse_32->start_level = true;
|
||||
data->emu_air.nfcv_resp_pulse_32->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_pulse_32->edge_timings[1] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_pulse_32->edge_timings[0] =
|
||||
(uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_pulse_32->edge_timings[1] =
|
||||
(uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||
data->emu_air.nfcv_resp_pulse_32->edge_cnt = 2;
|
||||
}
|
||||
if(!data->emu_air.nfcv_resp_one) {
|
||||
@@ -250,16 +262,26 @@ void nfcv_emu_alloc(NfcVData* data) {
|
||||
digital_signal_append(data->emu_air.nfcv_resp_eof, data->emu_air.nfcv_resp_unmod_256);
|
||||
}
|
||||
|
||||
digital_sequence_set_signal(data->emu_air.nfcv_signal, NFCV_SIG_SOF, data->emu_air.nfcv_resp_sof);
|
||||
digital_sequence_set_signal(data->emu_air.nfcv_signal, NFCV_SIG_BIT0, data->emu_air.nfcv_resp_zero);
|
||||
digital_sequence_set_signal(data->emu_air.nfcv_signal, NFCV_SIG_BIT1, data->emu_air.nfcv_resp_one);
|
||||
digital_sequence_set_signal(data->emu_air.nfcv_signal, NFCV_SIG_EOF, data->emu_air.nfcv_resp_eof);
|
||||
digital_sequence_set_signal(
|
||||
data->emu_air.nfcv_signal, NFCV_SIG_SOF, data->emu_air.nfcv_resp_sof);
|
||||
digital_sequence_set_signal(
|
||||
data->emu_air.nfcv_signal, NFCV_SIG_BIT0, data->emu_air.nfcv_resp_zero);
|
||||
digital_sequence_set_signal(
|
||||
data->emu_air.nfcv_signal, NFCV_SIG_BIT1, data->emu_air.nfcv_resp_one);
|
||||
digital_sequence_set_signal(
|
||||
data->emu_air.nfcv_signal, NFCV_SIG_EOF, data->emu_air.nfcv_resp_eof);
|
||||
}
|
||||
|
||||
void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length, NfcVSendFlags flags) {
|
||||
void nfcv_emu_send(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
NfcVData* nfcv,
|
||||
uint8_t* data,
|
||||
uint8_t length,
|
||||
NfcVSendFlags flags) {
|
||||
/* picked default value (0) to match the most common format */
|
||||
if(!flags) {
|
||||
flags = NfcVSendFlagsSof | NfcVSendFlagsCrc | NfcVSendFlagsEof | NfcVSendFlagsOneSubcarrier | NfcVSendFlagsHighRate;
|
||||
flags = NfcVSendFlagsSof | NfcVSendFlagsCrc | NfcVSendFlagsEof |
|
||||
NfcVSendFlagsOneSubcarrier | NfcVSendFlagsHighRate;
|
||||
}
|
||||
|
||||
if(flags & NfcVSendFlagsCrc) {
|
||||
@@ -278,7 +300,8 @@ void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data,
|
||||
uint32_t bit_pos = bit_total % 8;
|
||||
uint8_t bit_val = 0x01 << bit_pos;
|
||||
|
||||
digital_sequence_add(nfcv->emu_air.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0);
|
||||
digital_sequence_add(
|
||||
nfcv->emu_air.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0);
|
||||
}
|
||||
|
||||
if(flags & NfcVSendFlagsEof) {
|
||||
@@ -295,35 +318,40 @@ void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data,
|
||||
}
|
||||
}
|
||||
|
||||
static void nfcv_uidcpy(uint8_t *dst, uint8_t *src) {
|
||||
static void nfcv_uidcpy(uint8_t* dst, uint8_t* src) {
|
||||
for(int pos = 0; pos < 8; pos++) {
|
||||
dst[pos] = src[7-pos];
|
||||
dst[pos] = src[7 - pos];
|
||||
}
|
||||
}
|
||||
|
||||
static int nfcv_uidcmp(uint8_t *dst, uint8_t *src) {
|
||||
static int nfcv_uidcmp(uint8_t* dst, uint8_t* src) {
|
||||
for(int pos = 0; pos < 8; pos++) {
|
||||
if(dst[pos] != src[7-pos]) {
|
||||
if(dst[pos] != src[7 - pos]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in, uint8_t* payload, uint32_t payload_length) {
|
||||
|
||||
void nfcv_emu_handle_packet(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in,
|
||||
uint8_t* payload,
|
||||
uint32_t payload_length) {
|
||||
if(!payload_length) {
|
||||
return;
|
||||
}
|
||||
|
||||
NfcVData* nfcv_data = (NfcVData*)nfcv_data_in;
|
||||
NfcVEmuProtocolCtx* ctx = &nfcv_data->emu_protocol_ctx;
|
||||
|
||||
|
||||
ctx->frame = payload;
|
||||
ctx->frame_length = payload_length;
|
||||
ctx->flags = ctx->frame[0];
|
||||
ctx->command = ctx->frame[1];
|
||||
ctx->addressed = !(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) && (ctx->flags & RFAL_NFCV_REQ_FLAG_ADDRESS);
|
||||
ctx->addressed = !(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) &&
|
||||
(ctx->flags & RFAL_NFCV_REQ_FLAG_ADDRESS);
|
||||
ctx->advanced = (ctx->command >= 0xA0);
|
||||
ctx->address_offset = 2 + (ctx->advanced ? 1 : 0);
|
||||
ctx->payload_offset = ctx->address_offset + (ctx->addressed ? 8 : 0);
|
||||
@@ -340,116 +368,165 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
||||
uint8_t* address = &ctx->frame[ctx->address_offset];
|
||||
if(nfcv_uidcmp(address, nfc_data->uid)) {
|
||||
FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", ctx->command);
|
||||
FURI_LOG_D(TAG, " dest: %02X%02X%02X%02X%02X%02X%02X%02X", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]);
|
||||
FURI_LOG_D(TAG, " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" dest: %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
address[7],
|
||||
address[6],
|
||||
address[5],
|
||||
address[4],
|
||||
address[3],
|
||||
address[2],
|
||||
address[1],
|
||||
address[0]);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" our UID: %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
nfc_data->uid[0],
|
||||
nfc_data->uid[1],
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3],
|
||||
nfc_data->uid[4],
|
||||
nfc_data->uid[5],
|
||||
nfc_data->uid[6],
|
||||
nfc_data->uid[7]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unfortunately our response is quicker than the original NFC tag which causes frame misses */
|
||||
furi_delay_us(270);
|
||||
|
||||
switch(ctx->command) {
|
||||
case ISO15693_INVENTORY: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = nfcv_data->dsfid;
|
||||
nfcv_uidcpy(&ctx->response_buffer[2], nfc_data->uid);
|
||||
case ISO15693_INVENTORY: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = nfcv_data->dsfid;
|
||||
nfcv_uidcpy(&ctx->response_buffer[2], nfc_data->uid);
|
||||
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 10, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
|
||||
break;
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 10, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_STAYQUIET: {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_LOCKBLOCK: {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_SELECT: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_READ_MULTI_BLOCK:
|
||||
case ISO15693_READBLOCK: {
|
||||
uint8_t block = ctx->frame[ctx->payload_offset];
|
||||
uint8_t blocks = 1;
|
||||
|
||||
if(ctx->command == ISO15693_READ_MULTI_BLOCK) {
|
||||
blocks = ctx->frame[ctx->payload_offset + 1] + 1;
|
||||
}
|
||||
|
||||
case ISO15693_STAYQUIET: {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_LOCKBLOCK: {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_SELECT: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
if(block + blocks > nfcv_data->block_num) {
|
||||
ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC;
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
|
||||
break;
|
||||
} else {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
memcpy(
|
||||
&ctx->response_buffer[1],
|
||||
&nfcv_data->data[nfcv_data->block_size * block],
|
||||
nfcv_data->block_size * blocks);
|
||||
nfcv_emu_send(
|
||||
tx_rx,
|
||||
nfcv_data,
|
||||
ctx->response_buffer,
|
||||
1 + nfcv_data->block_size * blocks,
|
||||
ctx->response_flags);
|
||||
}
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block);
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_WRITE_MULTI_BLOCK:
|
||||
case ISO15693_WRITEBLOCK: {
|
||||
uint8_t block = ctx->frame[ctx->payload_offset];
|
||||
uint8_t blocks = 1;
|
||||
uint8_t data_pos = 1;
|
||||
|
||||
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||
blocks = ctx->frame[ctx->payload_offset + 1] + 1;
|
||||
data_pos++;
|
||||
}
|
||||
|
||||
case ISO15693_READ_MULTI_BLOCK:
|
||||
case ISO15693_READBLOCK: {
|
||||
uint8_t block = ctx->frame[ctx->payload_offset];
|
||||
uint8_t blocks = 1;
|
||||
uint8_t* data = &ctx->frame[ctx->payload_offset + data_pos];
|
||||
uint32_t data_len = nfcv_data->block_size * blocks;
|
||||
|
||||
if(ctx->command == ISO15693_READ_MULTI_BLOCK) {
|
||||
blocks = ctx->frame[ctx->payload_offset + 1] + 1;
|
||||
}
|
||||
|
||||
if(block + blocks > nfcv_data->block_num) {
|
||||
ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC;
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
} else {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
memcpy(&ctx->response_buffer[1], &nfcv_data->data[nfcv_data->block_size * block], nfcv_data->block_size * blocks);
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1 + nfcv_data->block_size * blocks, ctx->response_flags);
|
||||
}
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block);
|
||||
break;
|
||||
if(block + blocks > nfcv_data->block_num ||
|
||||
ctx->payload_offset + data_len + 2 > payload_length) {
|
||||
ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC;
|
||||
} else {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
memcpy(
|
||||
&nfcv_data->data[nfcv_data->block_size * block],
|
||||
&ctx->frame[ctx->payload_offset + data_pos],
|
||||
data_len);
|
||||
}
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
|
||||
case ISO15693_WRITE_MULTI_BLOCK:
|
||||
case ISO15693_WRITEBLOCK: {
|
||||
uint8_t block = ctx->frame[ctx->payload_offset];
|
||||
uint8_t blocks = 1;
|
||||
uint8_t data_pos = 1;
|
||||
|
||||
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||
blocks = ctx->frame[ctx->payload_offset + 1] + 1;
|
||||
data_pos++;
|
||||
}
|
||||
|
||||
uint8_t *data = &ctx->frame[ctx->payload_offset + data_pos];
|
||||
uint32_t data_len = nfcv_data->block_size * blocks;
|
||||
|
||||
if(block + blocks > nfcv_data->block_num || ctx->payload_offset + data_len + 2 > payload_length) {
|
||||
ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC;
|
||||
} else {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
memcpy(&nfcv_data->data[nfcv_data->block_size * block], &ctx->frame[ctx->payload_offset + data_pos], data_len);
|
||||
}
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
|
||||
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE MULTI BLOCK %d, %d blocks", block, blocks);
|
||||
} else {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE BLOCK %d <- %02X %02X %02X %02X", block, data[0], data[1], data[2], data[3]);
|
||||
}
|
||||
break;
|
||||
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"WRITE MULTI BLOCK %d, %d blocks",
|
||||
block,
|
||||
blocks);
|
||||
} else {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"WRITE BLOCK %d <- %02X %02X %02X %02X",
|
||||
block,
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
data[3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_GET_SYSTEM_INFO: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = 0x0F;
|
||||
nfcv_uidcpy(&ctx->response_buffer[2], nfc_data->uid);
|
||||
ctx->response_buffer[10] = nfcv_data->dsfid; /* DSFID */
|
||||
ctx->response_buffer[11] = nfcv_data->afi; /* AFI */
|
||||
ctx->response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */
|
||||
ctx->response_buffer[13] = nfcv_data->block_size - 1; /* block size */
|
||||
ctx->response_buffer[14] = nfcv_data->ic_ref; /* IC reference */
|
||||
case ISO15693_GET_SYSTEM_INFO: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = 0x0F;
|
||||
nfcv_uidcpy(&ctx->response_buffer[2], nfc_data->uid);
|
||||
ctx->response_buffer[10] = nfcv_data->dsfid; /* DSFID */
|
||||
ctx->response_buffer[11] = nfcv_data->afi; /* AFI */
|
||||
ctx->response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */
|
||||
ctx->response_buffer[13] = nfcv_data->block_size - 1; /* block size */
|
||||
ctx->response_buffer[14] = nfcv_data->ic_ref; /* IC reference */
|
||||
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 15, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO");
|
||||
break;
|
||||
}
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 15, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "unsupported: %02X", ctx->command);
|
||||
break;
|
||||
default:
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"unsupported: %02X",
|
||||
ctx->command);
|
||||
break;
|
||||
}
|
||||
|
||||
if(strlen(nfcv_data->last_command) > 0) {
|
||||
FURI_LOG_D(TAG, "Received command %s", nfcv_data->last_command);
|
||||
FURI_LOG_D(TAG, "Received command %s", nfcv_data->last_command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,30 +544,38 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||
nfcv_data->emu_protocol_handler = &nfcv_emu_handle_packet;
|
||||
|
||||
FURI_LOG_D(TAG, "Starting NfcV emulation");
|
||||
FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
||||
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
nfc_data->uid[0],
|
||||
nfc_data->uid[1],
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3],
|
||||
nfc_data->uid[4],
|
||||
nfc_data->uid[5],
|
||||
nfc_data->uid[6],
|
||||
nfc_data->uid[7]);
|
||||
|
||||
switch(nfcv_data->type) {
|
||||
case NfcVTypeSlixL:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX-L");
|
||||
slix_l_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlixS:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX-S");
|
||||
slix_s_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlix2:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX2");
|
||||
slix2_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlix:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX");
|
||||
slix_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypePlain:
|
||||
FURI_LOG_D(TAG, " Card type: Plain");
|
||||
break;
|
||||
case NfcVTypeSlixL:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX-L");
|
||||
slix_l_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlixS:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX-S");
|
||||
slix_s_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlix2:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX2");
|
||||
slix2_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypeSlix:
|
||||
FURI_LOG_D(TAG, " Card type: SLIX");
|
||||
slix_prepare(nfcv_data);
|
||||
break;
|
||||
case NfcVTypePlain:
|
||||
FURI_LOG_D(TAG, " Card type: Plain");
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate a 512 edge buffer, more than enough */
|
||||
@@ -510,8 +595,11 @@ void nfcv_emu_deinit(NfcVData* nfcv_data) {
|
||||
pulse_reader_free(nfcv_data->emu_air.reader_signal);
|
||||
}
|
||||
|
||||
bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms) {
|
||||
|
||||
bool nfcv_emu_loop(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
NfcVData* nfcv_data,
|
||||
uint32_t timeout_ms) {
|
||||
bool ret = false;
|
||||
uint32_t frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
uint32_t periods_previous = 0;
|
||||
@@ -523,8 +611,8 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
||||
bool wait_for_pulse = false;
|
||||
|
||||
while(true) {
|
||||
|
||||
uint32_t periods = pulse_reader_receive(nfcv_data->emu_air.reader_signal, timeout_ms * 1000);
|
||||
uint32_t periods =
|
||||
pulse_reader_receive(nfcv_data->emu_air.reader_signal, timeout_ms * 1000);
|
||||
|
||||
if(periods == PULSE_READER_NO_EDGE) {
|
||||
break;
|
||||
@@ -533,113 +621,137 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
||||
if(wait_for_pulse) {
|
||||
wait_for_pulse = false;
|
||||
if(periods != 1) {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected a single low pulse in state %lu, but got %lu", frame_state, periods);
|
||||
snprintf(
|
||||
reset_reason,
|
||||
sizeof(reset_reason),
|
||||
"SOF: Expected a single low pulse in state %lu, but got %lu",
|
||||
frame_state,
|
||||
periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(frame_state) {
|
||||
case NFCV_FRAME_STATE_SOF1:
|
||||
if(periods == 1) {
|
||||
frame_state = NFCV_FRAME_STATE_SOF2;
|
||||
} else {
|
||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
break;
|
||||
}
|
||||
case NFCV_FRAME_STATE_SOF1:
|
||||
if(periods == 1) {
|
||||
frame_state = NFCV_FRAME_STATE_SOF2;
|
||||
} else {
|
||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NFCV_FRAME_STATE_SOF2:
|
||||
/* waiting for the second low period, telling us about coding */
|
||||
if(periods == 6) {
|
||||
frame_state = NFCV_FRAME_STATE_CODING_256;
|
||||
periods_previous = 0;
|
||||
wait_for_pulse = true;
|
||||
} else if(periods == 4) {
|
||||
frame_state = NFCV_FRAME_STATE_CODING_4;
|
||||
periods_previous = 2;
|
||||
wait_for_pulse = true;
|
||||
} else {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected 4/6 periods, got %lu", periods);
|
||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
}
|
||||
break;
|
||||
|
||||
case NFCV_FRAME_STATE_CODING_256:
|
||||
if(periods_previous > periods) {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "1oo256: Missing %lu periods from previous symbol, got %lu", periods_previous, periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
/* previous symbol left us with some pulse periods */
|
||||
periods -= periods_previous;
|
||||
|
||||
if(periods > 512) {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
if(periods == 2) {
|
||||
frame_state = NFCV_FRAME_STATE_EOF;
|
||||
break;
|
||||
}
|
||||
|
||||
periods_previous = 512 - (periods + 1);
|
||||
byte_value = (periods - 1) / 2;
|
||||
frame_payload[frame_pos++] = (uint8_t)byte_value;
|
||||
|
||||
wait_for_pulse = true;
|
||||
|
||||
break;
|
||||
|
||||
case NFCV_FRAME_STATE_CODING_4:
|
||||
if(periods_previous > periods) {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "1oo4: Missing %lu periods from previous symbol, got %lu", periods_previous, periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* previous symbol left us with some pulse periods */
|
||||
periods -= periods_previous;
|
||||
case NFCV_FRAME_STATE_SOF2:
|
||||
/* waiting for the second low period, telling us about coding */
|
||||
if(periods == 6) {
|
||||
frame_state = NFCV_FRAME_STATE_CODING_256;
|
||||
periods_previous = 0;
|
||||
|
||||
byte_value >>= 2;
|
||||
bits_received += 2;
|
||||
|
||||
if(periods == 1) {
|
||||
byte_value |= 0x00 << 6;
|
||||
periods_previous = 6;
|
||||
} else if(periods == 3) {
|
||||
byte_value |= 0x01 << 6;
|
||||
periods_previous = 4;
|
||||
} else if(periods == 5) {
|
||||
byte_value |= 0x02 << 6;
|
||||
periods_previous = 2;
|
||||
} else if(periods == 7) {
|
||||
byte_value |= 0x03 << 6;
|
||||
periods_previous = 0;
|
||||
} else if(periods == 2) {
|
||||
frame_state = NFCV_FRAME_STATE_EOF;
|
||||
break;
|
||||
} else {
|
||||
snprintf(reset_reason, sizeof(reset_reason), "1oo4: Expected 1/3/5/7 low pulses, but got %lu", periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bits_received >= 8) {
|
||||
frame_payload[frame_pos++] = (uint8_t)byte_value;
|
||||
bits_received = 0;
|
||||
}
|
||||
wait_for_pulse = true;
|
||||
} else if(periods == 4) {
|
||||
frame_state = NFCV_FRAME_STATE_CODING_4;
|
||||
periods_previous = 2;
|
||||
wait_for_pulse = true;
|
||||
} else {
|
||||
snprintf(
|
||||
reset_reason,
|
||||
sizeof(reset_reason),
|
||||
"SOF: Expected 4/6 periods, got %lu",
|
||||
periods);
|
||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
}
|
||||
break;
|
||||
|
||||
case NFCV_FRAME_STATE_CODING_256:
|
||||
if(periods_previous > periods) {
|
||||
snprintf(
|
||||
reset_reason,
|
||||
sizeof(reset_reason),
|
||||
"1oo256: Missing %lu periods from previous symbol, got %lu",
|
||||
periods_previous,
|
||||
periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
/* previous symbol left us with some pulse periods */
|
||||
periods -= periods_previous;
|
||||
|
||||
if(periods > 512) {
|
||||
snprintf(
|
||||
reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
if(periods == 2) {
|
||||
frame_state = NFCV_FRAME_STATE_EOF;
|
||||
break;
|
||||
}
|
||||
|
||||
periods_previous = 512 - (periods + 1);
|
||||
byte_value = (periods - 1) / 2;
|
||||
frame_payload[frame_pos++] = (uint8_t)byte_value;
|
||||
|
||||
wait_for_pulse = true;
|
||||
|
||||
break;
|
||||
|
||||
case NFCV_FRAME_STATE_CODING_4:
|
||||
if(periods_previous > periods) {
|
||||
snprintf(
|
||||
reset_reason,
|
||||
sizeof(reset_reason),
|
||||
"1oo4: Missing %lu periods from previous symbol, got %lu",
|
||||
periods_previous,
|
||||
periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* previous symbol left us with some pulse periods */
|
||||
periods -= periods_previous;
|
||||
periods_previous = 0;
|
||||
|
||||
byte_value >>= 2;
|
||||
bits_received += 2;
|
||||
|
||||
if(periods == 1) {
|
||||
byte_value |= 0x00 << 6;
|
||||
periods_previous = 6;
|
||||
} else if(periods == 3) {
|
||||
byte_value |= 0x01 << 6;
|
||||
periods_previous = 4;
|
||||
} else if(periods == 5) {
|
||||
byte_value |= 0x02 << 6;
|
||||
periods_previous = 2;
|
||||
} else if(periods == 7) {
|
||||
byte_value |= 0x03 << 6;
|
||||
periods_previous = 0;
|
||||
} else if(periods == 2) {
|
||||
frame_state = NFCV_FRAME_STATE_EOF;
|
||||
break;
|
||||
} else {
|
||||
snprintf(
|
||||
reset_reason,
|
||||
sizeof(reset_reason),
|
||||
"1oo4: Expected 1/3/5/7 low pulses, but got %lu",
|
||||
periods);
|
||||
frame_state = NFCV_FRAME_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bits_received >= 8) {
|
||||
frame_payload[frame_pos++] = (uint8_t)byte_value;
|
||||
bits_received = 0;
|
||||
}
|
||||
wait_for_pulse = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* post-state-machine cleanup and reset */
|
||||
if(frame_state == NFCV_FRAME_STATE_RESET) {
|
||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||
|
||||
|
||||
FURI_LOG_D(TAG, "Resetting state machine, reason: '%s'", reset_reason);
|
||||
} else if(frame_state == NFCV_FRAME_STATE_EOF) {
|
||||
break;
|
||||
|
||||
+57
-41
@@ -34,33 +34,33 @@
|
||||
#define NFCV_SIG_EOF 3
|
||||
|
||||
/* ISO15693 command codes */
|
||||
#define ISO15693_INVENTORY 0x01
|
||||
#define ISO15693_STAYQUIET 0x02
|
||||
#define ISO15693_READBLOCK 0x20
|
||||
#define ISO15693_WRITEBLOCK 0x21
|
||||
#define ISO15693_LOCKBLOCK 0x22
|
||||
#define ISO15693_READ_MULTI_BLOCK 0x23
|
||||
#define ISO15693_WRITE_MULTI_BLOCK 0x24
|
||||
#define ISO15693_SELECT 0x25
|
||||
#define ISO15693_RESET_TO_READY 0x26
|
||||
#define ISO15693_WRITE_AFI 0x27
|
||||
#define ISO15693_LOCK_AFI 0x28
|
||||
#define ISO15693_WRITE_DSFID 0x29
|
||||
#define ISO15693_LOCK_DSFID 0x2A
|
||||
#define ISO15693_GET_SYSTEM_INFO 0x2B
|
||||
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
|
||||
#define ISO15693_INVENTORY 0x01
|
||||
#define ISO15693_STAYQUIET 0x02
|
||||
#define ISO15693_READBLOCK 0x20
|
||||
#define ISO15693_WRITEBLOCK 0x21
|
||||
#define ISO15693_LOCKBLOCK 0x22
|
||||
#define ISO15693_READ_MULTI_BLOCK 0x23
|
||||
#define ISO15693_WRITE_MULTI_BLOCK 0x24
|
||||
#define ISO15693_SELECT 0x25
|
||||
#define ISO15693_RESET_TO_READY 0x26
|
||||
#define ISO15693_WRITE_AFI 0x27
|
||||
#define ISO15693_LOCK_AFI 0x28
|
||||
#define ISO15693_WRITE_DSFID 0x29
|
||||
#define ISO15693_LOCK_DSFID 0x2A
|
||||
#define ISO15693_GET_SYSTEM_INFO 0x2B
|
||||
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
|
||||
|
||||
/* ISO15693 RESPONSE ERROR CODES */
|
||||
#define ISO15693_NOERROR 0x00
|
||||
#define ISO15693_ERROR_CMD_NOT_SUP 0x01 // Command not supported
|
||||
#define ISO15693_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error)
|
||||
#define ISO15693_ERROR_CMD_OPTION 0x03 // Command option not supported
|
||||
#define ISO15693_ERROR_GENERIC 0x0F // No additional Info about this error
|
||||
#define ISO15693_ERROR_BLOCK_UNAVAILABLE 0x10
|
||||
#define ISO15693_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again
|
||||
#define ISO15693_ERROR_BLOCK_LOCKED 0x12 // cannot be changed
|
||||
#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful
|
||||
#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful
|
||||
#define ISO15693_NOERROR 0x00
|
||||
#define ISO15693_ERROR_CMD_NOT_SUP 0x01 // Command not supported
|
||||
#define ISO15693_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error)
|
||||
#define ISO15693_ERROR_CMD_OPTION 0x03 // Command option not supported
|
||||
#define ISO15693_ERROR_GENERIC 0x0F // No additional Info about this error
|
||||
#define ISO15693_ERROR_BLOCK_UNAVAILABLE 0x10
|
||||
#define ISO15693_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again
|
||||
#define ISO15693_ERROR_BLOCK_LOCKED 0x12 // cannot be changed
|
||||
#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful
|
||||
#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful
|
||||
|
||||
typedef enum {
|
||||
NfcVAuthMethodManual,
|
||||
@@ -113,24 +113,31 @@ typedef struct {
|
||||
DigitalSequence* nfcv_signal;
|
||||
} NfcVEmuAir;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t* frame; /* ISO15693-2 incoming raw data from air layer */
|
||||
uint8_t frame_length; /* ISO15693-2 length of incoming data */
|
||||
uint8_t* frame; /* ISO15693-2 incoming raw data from air layer */
|
||||
uint8_t frame_length; /* ISO15693-2 length of incoming data */
|
||||
|
||||
uint8_t flags; /* ISO15693-3 flags of the header as specified */
|
||||
uint8_t command; /* ISO15693-3 command at offset 1 as specified */
|
||||
bool addressed; /* ISO15693-3 flags: addressed frame */
|
||||
bool advanced; /* ISO15693-3 command: advanced command */
|
||||
uint8_t address_offset; /* ISO15693-3 offset of the address in frame, if addressed is set */
|
||||
uint8_t payload_offset; /* ISO15693-3 offset of the payload in frame */
|
||||
uint8_t flags; /* ISO15693-3 flags of the header as specified */
|
||||
uint8_t command; /* ISO15693-3 command at offset 1 as specified */
|
||||
bool addressed; /* ISO15693-3 flags: addressed frame */
|
||||
bool advanced; /* ISO15693-3 command: advanced command */
|
||||
uint8_t address_offset; /* ISO15693-3 offset of the address in frame, if addressed is set */
|
||||
uint8_t payload_offset; /* ISO15693-3 offset of the payload in frame */
|
||||
|
||||
uint8_t response_buffer[128]; /* pre-allocated response buffer */
|
||||
NfcVSendFlags response_flags; /* flags to use when sending response */
|
||||
uint8_t response_buffer[128]; /* pre-allocated response buffer */
|
||||
NfcVSendFlags response_flags; /* flags to use when sending response */
|
||||
} NfcVEmuProtocolCtx;
|
||||
|
||||
typedef void (*NfcVEmuProtocolHandler) (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data, uint8_t* payload, uint32_t payload_length);
|
||||
typedef bool (*NfcVEmuProtocolFilter) (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data);
|
||||
typedef void (*NfcVEmuProtocolHandler)(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data,
|
||||
uint8_t* payload,
|
||||
uint32_t payload_length);
|
||||
typedef bool (*NfcVEmuProtocolFilter)(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data);
|
||||
|
||||
typedef struct {
|
||||
/* common ISO15693 fields */
|
||||
@@ -161,7 +168,7 @@ typedef struct {
|
||||
int16_t blocks_read;
|
||||
} NfcVReader;
|
||||
|
||||
ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data);
|
||||
ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data);
|
||||
ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data);
|
||||
ReturnCode nfcv_inventory(uint8_t* uid);
|
||||
bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* data);
|
||||
@@ -169,5 +176,14 @@ bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* d
|
||||
void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data);
|
||||
void nfcv_emu_deinit(NfcVData* nfcv_data);
|
||||
|
||||
bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms);
|
||||
void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length, NfcVSendFlags flags);
|
||||
bool nfcv_emu_loop(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
NfcVData* nfcv_data,
|
||||
uint32_t timeout_ms);
|
||||
void nfcv_emu_send(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
NfcVData* nfcv,
|
||||
uint8_t* data,
|
||||
uint8_t length,
|
||||
NfcVSendFlags flags);
|
||||
|
||||
+177
-134
@@ -9,7 +9,7 @@
|
||||
|
||||
#define TAG "SLIX"
|
||||
|
||||
static uint32_t slix_read_be(uint8_t *data, uint32_t length) {
|
||||
static uint32_t slix_read_be(uint8_t* data, uint32_t length) {
|
||||
uint32_t value = 0;
|
||||
|
||||
for(uint32_t pos = 0; pos < length; pos++) {
|
||||
@@ -87,33 +87,32 @@ ReturnCode slix_unlock(NfcVData* data, uint32_t password_id) {
|
||||
|
||||
uint16_t received = 0;
|
||||
uint8_t rxBuf[32];
|
||||
uint8_t cmd_set_pass[] = {
|
||||
password_id,
|
||||
data->sub_data.slix.rand[1],
|
||||
data->sub_data.slix.rand[0],
|
||||
data->sub_data.slix.rand[1],
|
||||
data->sub_data.slix.rand[0]
|
||||
};
|
||||
uint8_t *password = NULL;
|
||||
uint8_t cmd_set_pass[] = {
|
||||
password_id,
|
||||
data->sub_data.slix.rand[1],
|
||||
data->sub_data.slix.rand[0],
|
||||
data->sub_data.slix.rand[1],
|
||||
data->sub_data.slix.rand[0]};
|
||||
uint8_t* password = NULL;
|
||||
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
password = data->sub_data.slix.key_read;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
password = data->sub_data.slix.key_write;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
password = data->sub_data.slix.key_privacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
password = data->sub_data.slix.key_destroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
password = data->sub_data.slix.key_eas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case SLIX_PASS_READ:
|
||||
password = data->sub_data.slix.key_read;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
password = data->sub_data.slix.key_write;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
password = data->sub_data.slix.key_privacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
password = data->sub_data.slix.key_destroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
password = data->sub_data.slix.key_eas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!password) {
|
||||
@@ -138,21 +137,26 @@ ReturnCode slix_unlock(NfcVData* data, uint32_t password_id) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool slix_generic_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in, uint32_t password_supported) {
|
||||
bool slix_generic_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in,
|
||||
uint32_t password_supported) {
|
||||
furi_assert(tx_rx);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
|
||||
NfcVData* nfcv_data = (NfcVData*)nfcv_data_in;
|
||||
NfcVEmuProtocolCtx* ctx = &nfcv_data->emu_protocol_ctx;
|
||||
NfcVSlixData* slix = &nfcv_data->sub_data.slix;
|
||||
|
||||
if(slix->privacy &&
|
||||
ctx->command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||
ctx->command != ISO15693_CMD_NXP_SET_PASSWORD) {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
||||
"command 0x%02X ignored, privacy mode", ctx->command);
|
||||
if(slix->privacy && ctx->command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||
ctx->command != ISO15693_CMD_NXP_SET_PASSWORD) {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"command 0x%02X ignored, privacy mode",
|
||||
ctx->command);
|
||||
FURI_LOG_D(TAG, "%s", nfcv_data->last_command);
|
||||
return true;
|
||||
}
|
||||
@@ -160,115 +164,137 @@ bool slix_generic_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevDa
|
||||
bool handled = false;
|
||||
|
||||
switch(ctx->command) {
|
||||
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: {
|
||||
slix->rand[0] = furi_hal_random_get();
|
||||
slix->rand[1] = furi_hal_random_get();
|
||||
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: {
|
||||
slix->rand[0] = furi_hal_random_get();
|
||||
slix->rand[1] = furi_hal_random_get();
|
||||
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = slix->rand[1];
|
||||
ctx->response_buffer[2] = slix->rand[0];
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
ctx->response_buffer[1] = slix->rand[1];
|
||||
ctx->response_buffer[2] = slix->rand[0];
|
||||
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 3, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
||||
"GET_RANDOM_NUMBER -> 0x%02X%02X", slix->rand[0], slix->rand[1]);
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 3, ctx->response_flags);
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"GET_RANDOM_NUMBER -> 0x%02X%02X",
|
||||
slix->rand[0],
|
||||
slix->rand[1]);
|
||||
|
||||
handled = true;
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_CMD_NXP_SET_PASSWORD: {
|
||||
uint8_t password_id = ctx->frame[ctx->payload_offset];
|
||||
|
||||
if(!(password_id & password_supported)) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_CMD_NXP_SET_PASSWORD: {
|
||||
uint8_t password_id = ctx->frame[ctx->payload_offset];
|
||||
uint8_t* password_xored = &ctx->frame[ctx->payload_offset + 1];
|
||||
uint8_t* rand = slix->rand;
|
||||
uint8_t* password = NULL;
|
||||
uint8_t password_rcv[4];
|
||||
|
||||
if(!(password_id & password_supported)) {
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
password = slix->key_read;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
password = slix->key_write;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
password = slix->key_privacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
password = slix->key_destroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
password = slix->key_eas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for(int pos = 0; pos < 4; pos++) {
|
||||
password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2];
|
||||
}
|
||||
uint32_t pass_expect = slix_read_be(password, 4);
|
||||
uint32_t pass_received = slix_read_be(password_rcv, 4);
|
||||
|
||||
/* if the password is all-zeroes, just accept any password*/
|
||||
if(!pass_expect || pass_expect == pass_received) {
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
slix->privacy = false;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
FURI_LOG_D(TAG, "Pooof! Got destroyed");
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t *password_xored = &ctx->frame[ctx->payload_offset + 1];
|
||||
uint8_t *rand = slix->rand;
|
||||
uint8_t *password = NULL;
|
||||
uint8_t password_rcv[4];
|
||||
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
password = slix->key_read;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
password = slix->key_write;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
password = slix->key_privacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
password = slix->key_destroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
password = slix->key_eas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for(int pos = 0; pos < 4; pos++) {
|
||||
password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2];
|
||||
}
|
||||
uint32_t pass_expect = slix_read_be(password, 4);
|
||||
uint32_t pass_received = slix_read_be(password_rcv, 4);
|
||||
|
||||
/* if the password is all-zeroes, just accept any password*/
|
||||
if(!pass_expect || pass_expect == pass_received) {
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
slix->privacy = false;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
FURI_LOG_D(TAG, "Pooof! Got destroyed");
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
||||
"SET_PASSWORD #%02X 0x%08lX OK", password_id, pass_received);
|
||||
} else {
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
||||
"SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", password_id, pass_received, pass_expect);
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_CMD_NXP_ENABLE_PRIVACY: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
||||
"ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
||||
|
||||
slix->privacy = true;
|
||||
handled = true;
|
||||
break;
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"SET_PASSWORD #%02X 0x%08lX OK",
|
||||
password_id,
|
||||
pass_received);
|
||||
} else {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"SET_PASSWORD #%02X 0x%08lX/%08lX FAIL",
|
||||
password_id,
|
||||
pass_received,
|
||||
pass_expect);
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ISO15693_CMD_NXP_ENABLE_PRIVACY: {
|
||||
ctx->response_buffer[0] = ISO15693_NOERROR;
|
||||
|
||||
nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags);
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
||||
|
||||
slix->privacy = true;
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool slix_l_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) {
|
||||
bool slix_l_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in) {
|
||||
furi_assert(tx_rx);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
|
||||
/* many SLIX share some of the functions, place that in a generic handler */
|
||||
if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)) {
|
||||
if(slix_generic_protocol_filter(
|
||||
tx_rx,
|
||||
nfc_data,
|
||||
nfcv_data_in,
|
||||
SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -276,21 +302,26 @@ bool slix_l_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nf
|
||||
}
|
||||
|
||||
void slix_l_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
|
||||
nfcv_data->emu_protocol_filter = &slix_l_protocol_filter;
|
||||
}
|
||||
|
||||
bool slix_s_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) {
|
||||
bool slix_s_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in) {
|
||||
furi_assert(tx_rx);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
|
||||
/* many SLIX share some of the functions, place that in a generic handler */
|
||||
if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) {
|
||||
return true;
|
||||
@@ -300,21 +331,26 @@ bool slix_s_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nf
|
||||
}
|
||||
|
||||
void slix_s_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
|
||||
nfcv_data->emu_protocol_filter = &slix_s_protocol_filter;
|
||||
}
|
||||
|
||||
bool slix_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) {
|
||||
bool slix_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in) {
|
||||
furi_assert(tx_rx);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
|
||||
/* many SLIX share some of the functions, place that in a generic handler */
|
||||
if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_EASAFI)) {
|
||||
return true;
|
||||
@@ -324,21 +360,26 @@ bool slix_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_
|
||||
}
|
||||
|
||||
void slix_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
|
||||
nfcv_data->emu_protocol_filter = &slix_protocol_filter;
|
||||
}
|
||||
|
||||
bool slix2_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) {
|
||||
bool slix2_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
void* nfcv_data_in) {
|
||||
furi_assert(tx_rx);
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
|
||||
/* many SLIX share some of the functions, place that in a generic handler */
|
||||
if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) {
|
||||
return true;
|
||||
@@ -348,8 +389,10 @@ bool slix2_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
||||
}
|
||||
|
||||
void slix2_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4));
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
|
||||
|
||||
+17
-16
@@ -5,31 +5,32 @@
|
||||
#include "nfc_util.h"
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
#define ISO15693_MANUFACTURER_NXP 0x04
|
||||
#define ISO15693_MANUFACTURER_NXP 0x04
|
||||
|
||||
/* ISO15693-3 CUSTOM NXP COMMANDS */
|
||||
#define ISO15693_CMD_NXP_SET_EAS 0xA2
|
||||
#define ISO15693_CMD_NXP_RESET_EAS 0xA3
|
||||
#define ISO15693_CMD_NXP_LOCK_EAS 0xA4
|
||||
#define ISO15693_CMD_NXP_EAS_ALARM 0xA5
|
||||
#define ISO15693_CMD_NXP_SET_EAS 0xA2
|
||||
#define ISO15693_CMD_NXP_RESET_EAS 0xA3
|
||||
#define ISO15693_CMD_NXP_LOCK_EAS 0xA4
|
||||
#define ISO15693_CMD_NXP_EAS_ALARM 0xA5
|
||||
#define ISO15693_CMD_NXP_PASSWORD_PROTECT_EAS_AFI 0xA6
|
||||
#define ISO15693_CMD_NXP_WRITE_EAS_ID 0xA7
|
||||
#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ 0xB0
|
||||
#define ISO15693_CMD_NXP_WRITE_EAS_ID 0xA7
|
||||
#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ 0xB0
|
||||
#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ_FAST 0xB1
|
||||
#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2
|
||||
#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3
|
||||
#define ISO15693_CMD_NXP_WRITE_PASSWORD 0xB4
|
||||
#define ISO15693_CMD_NXP_DESTROY 0xB9
|
||||
#define ISO15693_CMD_NXP_ENABLE_PRIVACY 0xBA
|
||||
#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2
|
||||
#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3
|
||||
#define ISO15693_CMD_NXP_WRITE_PASSWORD 0xB4
|
||||
#define ISO15693_CMD_NXP_DESTROY 0xB9
|
||||
#define ISO15693_CMD_NXP_ENABLE_PRIVACY 0xBA
|
||||
|
||||
/* available passwords */
|
||||
#define SLIX_PASS_READ 0x01
|
||||
#define SLIX_PASS_WRITE 0x02
|
||||
#define SLIX_PASS_READ 0x01
|
||||
#define SLIX_PASS_WRITE 0x02
|
||||
#define SLIX_PASS_PRIVACY 0x04
|
||||
#define SLIX_PASS_DESTROY 0x08
|
||||
#define SLIX_PASS_EASAFI 0x10
|
||||
#define SLIX_PASS_EASAFI 0x10
|
||||
|
||||
#define SLIX_PASS_ALL (SLIX_PASS_READ|SLIX_PASS_WRITE|SLIX_PASS_PRIVACY|SLIX_PASS_DESTROY|SLIX_PASS_EASAFI)
|
||||
#define SLIX_PASS_ALL \
|
||||
(SLIX_PASS_READ | SLIX_PASS_WRITE | SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)
|
||||
|
||||
bool slix_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||
|
||||
Reference in New Issue
Block a user