mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 22:58:36 -07:00
Fixes from code review
This commit is contained in:
@@ -70,6 +70,7 @@ void mf_plus_reset(MfPlusData* data) {
|
|||||||
iso14443_4a_reset(data->iso14443_4a_data);
|
iso14443_4a_reset(data->iso14443_4a_data);
|
||||||
|
|
||||||
memset(&data->version, 0, sizeof(data->version));
|
memset(&data->version, 0, sizeof(data->version));
|
||||||
|
furi_string_reset(data->device_name);
|
||||||
data->type = MfPlusTypeUnknown;
|
data->type = MfPlusTypeUnknown;
|
||||||
data->security_level = MfPlusSecurityLevelUnknown;
|
data->security_level = MfPlusSecurityLevelUnknown;
|
||||||
data->size = MfPlusSizeUnknown;
|
data->size = MfPlusSizeUnknown;
|
||||||
|
|||||||
@@ -8,6 +8,202 @@
|
|||||||
#define MF_PLUS_FFF_CARD_TYPE_KEY "Card Type"
|
#define MF_PLUS_FFF_CARD_TYPE_KEY "Card Type"
|
||||||
#define MF_PLUS_FFF_MEMORY_SIZE_KEY "Memory Size"
|
#define MF_PLUS_FFF_MEMORY_SIZE_KEY "Memory Size"
|
||||||
|
|
||||||
|
#define TAG "MfPlus"
|
||||||
|
|
||||||
|
const uint8_t mf_plus_ats_t1_tk_values[][7] = {
|
||||||
|
{0xC1, 0x05, 0x2F, 0x2F, 0x00, 0x35, 0xC7}, // Mifare Plus S
|
||||||
|
{0xC1, 0x05, 0x2F, 0x2F, 0x01, 0xBC, 0xD6}, // Mifare Plus X
|
||||||
|
{0xC1, 0x05, 0x2F, 0x2F, 0x00, 0xF6, 0xD1}, // Mifare Plus SE
|
||||||
|
{0xC1, 0x05, 0x2F, 0x2F, 0x01, 0xF6, 0xD1}, // Mifare Plus SE
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mf_plus_get_type_from_version(
|
||||||
|
const Iso14443_4aData* iso14443_4a_data,
|
||||||
|
MfPlusData* mf_plus_data) {
|
||||||
|
furi_assert(iso14443_4a_data);
|
||||||
|
furi_assert(mf_plus_data);
|
||||||
|
|
||||||
|
bool detected = false;
|
||||||
|
|
||||||
|
if(mf_plus_data->version.hw_major == 0x02 || mf_plus_data->version.hw_major == 0x82) {
|
||||||
|
detected = true;
|
||||||
|
if(iso14443_4a_data->iso14443_3a_data->sak == 0x10) {
|
||||||
|
// Mifare Plus 2K SL2
|
||||||
|
mf_plus_data->type = MfPlusTypePlus;
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel2;
|
||||||
|
} else if(iso14443_4a_data->iso14443_3a_data->sak == 0x11) {
|
||||||
|
// Mifare Plus 4K SL3
|
||||||
|
mf_plus_data->type = MfPlusTypePlus;
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
||||||
|
} else {
|
||||||
|
// Mifare Plus EV1/EV2
|
||||||
|
|
||||||
|
// Revision
|
||||||
|
switch(mf_plus_data->version.hw_major) {
|
||||||
|
case 0x11:
|
||||||
|
mf_plus_data->type = MfPlusTypeEV1;
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
mf_plus_data->type = MfPlusTypeEV2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mf_plus_data->type = MfPlusTypeUnknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage size
|
||||||
|
switch(mf_plus_data->version.hw_storage) {
|
||||||
|
case 0x16:
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
break;
|
||||||
|
case 0x18:
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mf_plus_data->size = MfPlusSizeUnknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security level
|
||||||
|
if(iso14443_4a_data->iso14443_3a_data->sak == 0x20) {
|
||||||
|
// Mifare Plus EV1/2 SL3
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
||||||
|
} else {
|
||||||
|
// Mifare Plus EV1/2 SL1
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return detected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_plus_get_type_from_iso4(const Iso14443_4aData* iso4_data, MfPlusData* mf_plus_data) {
|
||||||
|
furi_assert(iso4_data);
|
||||||
|
furi_assert(mf_plus_data);
|
||||||
|
|
||||||
|
switch(iso4_data->iso14443_3a_data->sak) {
|
||||||
|
case 0x08:
|
||||||
|
if(memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[0],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus S 2K SL1
|
||||||
|
mf_plus_data->type = MfPlusTypeS;
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus S 2K SL1");
|
||||||
|
return true;
|
||||||
|
} else if(
|
||||||
|
memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[1],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus X 2K SL1
|
||||||
|
mf_plus_data->type = MfPlusTypeX;
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus X 2K SL1");
|
||||||
|
return true;
|
||||||
|
} else if(
|
||||||
|
memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[2],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0 ||
|
||||||
|
memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[3],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus SE 1K SL1
|
||||||
|
mf_plus_data->type = MfPlusTypeSE;
|
||||||
|
mf_plus_data->size = MfPlusSize1K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus SE 1K SL1");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "Sak 08 but no known Mifare Plus type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 0x18:
|
||||||
|
if(memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[0],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus S 4K SL1
|
||||||
|
mf_plus_data->type = MfPlusTypeS;
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus S 4K SL1");
|
||||||
|
return true;
|
||||||
|
} else if(
|
||||||
|
memcmp(
|
||||||
|
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
||||||
|
mf_plus_ats_t1_tk_values[1],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus X 4K SL1
|
||||||
|
mf_plus_data->type = MfPlusTypeX;
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus X 4K SL1");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "Sak 18 but no known Mifare Plus type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 0x20:
|
||||||
|
if(memcmp(
|
||||||
|
iso4_data->ats_data.t1_tk,
|
||||||
|
mf_plus_ats_t1_tk_values[0],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
// Mifare Plus S 2/4K SL3
|
||||||
|
mf_plus_data->type = MfPlusTypeS;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
||||||
|
|
||||||
|
if(iso4_data->iso14443_3a_data->atqa[1] & 0x04) {
|
||||||
|
// Mifare Plus S 2K SL3
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus S 2K SL3");
|
||||||
|
} else if(iso4_data->iso14443_3a_data->atqa[1] & 0x02) {
|
||||||
|
// Mifare Plus S 4K SL3
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus S 4K SL3");
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (S)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if(
|
||||||
|
memcmp(
|
||||||
|
iso4_data->ats_data.t1_tk,
|
||||||
|
mf_plus_ats_t1_tk_values[1],
|
||||||
|
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
||||||
|
mf_plus_data->type = MfPlusTypeX;
|
||||||
|
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
||||||
|
|
||||||
|
// if atqa is 0xXX 0xX4 (other digits are not important)
|
||||||
|
if(iso4_data->iso14443_3a_data->atqa[1] & 0x04) {
|
||||||
|
mf_plus_data->size = MfPlusSize2K;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus X 2K SL3");
|
||||||
|
} else if(iso4_data->iso14443_3a_data->atqa[1] & 0x02) {
|
||||||
|
mf_plus_data->size = MfPlusSize4K;
|
||||||
|
FURI_LOG_D(TAG, "Mifare Plus X 4K SL3");
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (X)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "No known Mifare Plus type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf) {
|
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf) {
|
||||||
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusVersion);
|
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusVersion);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
#define MF_PLUS_FFF_PICC_PREFIX "PICC"
|
#define MF_PLUS_FFF_PICC_PREFIX "PICC"
|
||||||
|
|
||||||
|
bool mf_plus_get_type_from_version(
|
||||||
|
const Iso14443_4aData* iso14443_4a_data,
|
||||||
|
MfPlusData* mf_plus_data);
|
||||||
|
|
||||||
|
bool mf_plus_get_type_from_iso4(const Iso14443_4aData* iso4_data, MfPlusData* mf_plus_data);
|
||||||
|
|
||||||
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf);
|
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf);
|
||||||
|
|
||||||
bool mf_plus_security_level_parse(MfPlusSecurityLevel* data, const BitBuffer* buf);
|
bool mf_plus_security_level_parse(MfPlusSecurityLevel* data, const BitBuffer* buf);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "mf_plus_poller_i.h"
|
#include "mf_plus_poller_i.h"
|
||||||
|
#include "mf_plus_i.h"
|
||||||
|
|
||||||
#include <nfc/protocols/nfc_poller_base.h>
|
#include <nfc/protocols/nfc_poller_base.h>
|
||||||
|
|
||||||
@@ -9,13 +10,6 @@
|
|||||||
#define MF_PLUS_BUF_SIZE (64U)
|
#define MF_PLUS_BUF_SIZE (64U)
|
||||||
#define MF_PLUS_RESULT_BUF_SIZE (512U)
|
#define MF_PLUS_RESULT_BUF_SIZE (512U)
|
||||||
|
|
||||||
const char* mf_plus_ats_t1_tk_values[] = {
|
|
||||||
"\xC1\x05\x2F\x2F\x00\x35\xC7", // Mifare Plus S
|
|
||||||
"\xC1\x05\x2F\x2F\x01\xBC\xD6", // Mifare Plus X
|
|
||||||
"\xC1\x05\x2F\x2F\x00\xF6\xD1", // Mifare Plus SE
|
|
||||||
"\xC1\x05\x2F\x2F\x01\xF6\xD1", // Mifare Plus SE
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef NfcCommand (*MfPlusPollerReadHandler)(MfPlusPoller* instance);
|
typedef NfcCommand (*MfPlusPollerReadHandler)(MfPlusPoller* instance);
|
||||||
|
|
||||||
const MfPlusData* mf_plus_poller_get_data(MfPlusPoller* instance) {
|
const MfPlusData* mf_plus_poller_get_data(MfPlusPoller* instance) {
|
||||||
@@ -24,200 +18,6 @@ const MfPlusData* mf_plus_poller_get_data(MfPlusPoller* instance) {
|
|||||||
return instance->data;
|
return instance->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mf_plus_poller_get_type_from_iso4(const Iso14443_4aData* iso4_data, MfPlusData* mf_plus_data) {
|
|
||||||
furi_assert(iso4_data);
|
|
||||||
furi_assert(mf_plus_data);
|
|
||||||
|
|
||||||
switch(iso4_data->iso14443_3a_data->sak) {
|
|
||||||
case 0x08:
|
|
||||||
if(memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[0],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus S 2K SL1
|
|
||||||
mf_plus_data->type = MfPlusTypeS;
|
|
||||||
mf_plus_data->size = MfPlusSize2K;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus S 2K SL1");
|
|
||||||
return true;
|
|
||||||
} else if(
|
|
||||||
memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[1],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus X 2K SL1
|
|
||||||
mf_plus_data->type = MfPlusTypeX;
|
|
||||||
mf_plus_data->size = MfPlusSize2K;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus X 2K SL1");
|
|
||||||
return true;
|
|
||||||
} else if(
|
|
||||||
memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[2],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0 ||
|
|
||||||
memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[3],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus SE 1K SL1
|
|
||||||
mf_plus_data->type = MfPlusTypeSE;
|
|
||||||
mf_plus_data->size = MfPlusSize1K;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus SE 1K SL1");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Sak 08 but no known Mifare Plus type");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 0x18:
|
|
||||||
if(memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[0],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus S 4K SL1
|
|
||||||
mf_plus_data->type = MfPlusTypeS;
|
|
||||||
mf_plus_data->size = MfPlusSize4K;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus S 4K SL1");
|
|
||||||
return true;
|
|
||||||
} else if(
|
|
||||||
memcmp(
|
|
||||||
simple_array_get_data(iso4_data->ats_data.t1_tk),
|
|
||||||
mf_plus_ats_t1_tk_values[1],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus X 4K SL1
|
|
||||||
mf_plus_data->type = MfPlusTypeX;
|
|
||||||
mf_plus_data->size = MfPlusSize4K;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel1;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus X 4K SL1");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Sak 18 but no known Mifare Plus type");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 0x20:
|
|
||||||
if(memcmp(
|
|
||||||
iso4_data->ats_data.t1_tk,
|
|
||||||
mf_plus_ats_t1_tk_values[0],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
// Mifare Plus S 2/4K SL3
|
|
||||||
mf_plus_data->type = MfPlusTypeS;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
|
||||||
|
|
||||||
if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) {
|
|
||||||
// Mifare Plus S 2K SL3
|
|
||||||
mf_plus_data->size = MfPlusSize2K;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus S 2K SL3");
|
|
||||||
} else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) {
|
|
||||||
// Mifare Plus S 4K SL3
|
|
||||||
mf_plus_data->size = MfPlusSize4K;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus S 4K SL3");
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (S)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if(
|
|
||||||
memcmp(
|
|
||||||
iso4_data->ats_data.t1_tk,
|
|
||||||
mf_plus_ats_t1_tk_values[1],
|
|
||||||
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
|
|
||||||
mf_plus_data->type = MfPlusTypeX;
|
|
||||||
mf_plus_data->security_level = MfPlusSecurityLevel3;
|
|
||||||
|
|
||||||
if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) {
|
|
||||||
mf_plus_data->size = MfPlusSize2K;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus X 2K SL3");
|
|
||||||
} else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) {
|
|
||||||
mf_plus_data->size = MfPlusSize4K;
|
|
||||||
FURI_LOG_D(TAG, "Mifare Plus X 4K SL3");
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (X)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "No known Mifare Plus type");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool mf_plus_poller_detect_type(MfPlusPoller* instance) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
bool detected = false;
|
|
||||||
|
|
||||||
const Iso14443_4aData* iso14443_4a_data =
|
|
||||||
iso14443_4a_poller_get_data(instance->iso14443_4a_poller);
|
|
||||||
const MfPlusError error = mf_plus_poller_read_version(instance, &instance->data->version);
|
|
||||||
if(error == MfPlusErrorNone) {
|
|
||||||
FURI_LOG_D(TAG, "Read version success: %d", error);
|
|
||||||
if(instance->data->version.hw_major == 0x02 || instance->data->version.hw_major == 0x82) {
|
|
||||||
detected = true;
|
|
||||||
if(iso14443_4a_data->iso14443_3a_data->sak == 0x10) {
|
|
||||||
// Mifare Plus 2K SL2
|
|
||||||
instance->data->type = MfPlusTypePlus;
|
|
||||||
instance->data->size = MfPlusSize2K;
|
|
||||||
instance->data->security_level = MfPlusSecurityLevel2;
|
|
||||||
} else if(iso14443_4a_data->iso14443_3a_data->sak == 0x11) {
|
|
||||||
// Mifare Plus 4K SL3
|
|
||||||
instance->data->type = MfPlusTypePlus;
|
|
||||||
instance->data->size = MfPlusSize4K;
|
|
||||||
instance->data->security_level = MfPlusSecurityLevel3;
|
|
||||||
} else {
|
|
||||||
// Mifare Plus EV1/EV2
|
|
||||||
|
|
||||||
// Revision
|
|
||||||
switch(instance->data->version.hw_major) {
|
|
||||||
case 0x11:
|
|
||||||
instance->data->type = MfPlusTypeEV1;
|
|
||||||
break;
|
|
||||||
case 0x22:
|
|
||||||
instance->data->type = MfPlusTypeEV2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
instance->data->type = MfPlusTypeUnknown;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage size
|
|
||||||
switch(instance->data->version.hw_storage) {
|
|
||||||
case 0x16:
|
|
||||||
instance->data->size = MfPlusSize2K;
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
instance->data->size = MfPlusSize4K;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
instance->data->size = MfPlusSizeUnknown;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Security level
|
|
||||||
if(iso14443_4a_data->iso14443_3a_data->sak == 0x20) {
|
|
||||||
// Mifare Plus EV1/2 SL3
|
|
||||||
instance->data->security_level = MfPlusSecurityLevel3;
|
|
||||||
} else {
|
|
||||||
// Mifare Plus EV1/2 SL1
|
|
||||||
instance->data->security_level = MfPlusSecurityLevel1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(TAG, "Read version error: %d", error);
|
|
||||||
detected = mf_plus_poller_get_type_from_iso4(iso14443_4a_data, instance->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return detected;
|
|
||||||
}
|
|
||||||
|
|
||||||
MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) {
|
MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) {
|
||||||
furi_assert(iso14443_4a_poller);
|
furi_assert(iso14443_4a_poller);
|
||||||
|
|
||||||
@@ -259,10 +59,40 @@ static NfcCommand mf_plus_poller_handler_idle(MfPlusPoller* instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NfcCommand mf_plus_poller_handler_read_version(MfPlusPoller* instance) {
|
static NfcCommand mf_plus_poller_handler_read_version(MfPlusPoller* instance) {
|
||||||
bool success = mf_plus_poller_detect_type(instance);
|
MfPlusError error = mf_plus_poller_read_version(instance, &instance->data->version);
|
||||||
if(success) {
|
if(error == MfPlusErrorNone) {
|
||||||
|
instance->state = MfPlusPollerStateParseVersion;
|
||||||
|
} else {
|
||||||
|
instance->state = MfPlusPollerStateParseIso4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NfcCommandContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NfcCommand mf_plus_poller_handler_parse_version(MfPlusPoller* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
MfPlusError error = mf_plus_get_type_from_version(
|
||||||
|
iso14443_4a_poller_get_data(instance->iso14443_4a_poller), instance->data);
|
||||||
|
if(error == MfPlusErrorNone) {
|
||||||
instance->state = MfPlusPollerStateReadSuccess;
|
instance->state = MfPlusPollerStateReadSuccess;
|
||||||
} else {
|
} else {
|
||||||
|
instance->error = error;
|
||||||
|
instance->state = MfPlusPollerStateReadFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NfcCommandContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NfcCommand mf_plus_poller_handler_parse_iso4(MfPlusPoller* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
MfPlusError error = mf_plus_get_type_from_iso4(
|
||||||
|
iso14443_4a_poller_get_data(instance->iso14443_4a_poller), instance->data);
|
||||||
|
if(error == MfPlusErrorNone) {
|
||||||
|
instance->state = MfPlusPollerStateReadSuccess;
|
||||||
|
} else {
|
||||||
|
instance->error = error;
|
||||||
instance->state = MfPlusPollerStateReadFailed;
|
instance->state = MfPlusPollerStateReadFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +121,8 @@ static NfcCommand mf_plus_poller_handler_read_success(MfPlusPoller* instance) {
|
|||||||
static const MfPlusPollerReadHandler mf_plus_poller_read_handler[MfPlusPollerStateNum] = {
|
static const MfPlusPollerReadHandler mf_plus_poller_read_handler[MfPlusPollerStateNum] = {
|
||||||
[MfPlusPollerStateIdle] = mf_plus_poller_handler_idle,
|
[MfPlusPollerStateIdle] = mf_plus_poller_handler_idle,
|
||||||
[MfPlusPollerStateReadVersion] = mf_plus_poller_handler_read_version,
|
[MfPlusPollerStateReadVersion] = mf_plus_poller_handler_read_version,
|
||||||
|
[MfPlusPollerStateParseVersion] = mf_plus_poller_handler_parse_version,
|
||||||
|
[MfPlusPollerStateParseIso4] = mf_plus_poller_handler_parse_iso4,
|
||||||
[MfPlusPollerStateReadFailed] = mf_plus_poller_handler_read_failed,
|
[MfPlusPollerStateReadFailed] = mf_plus_poller_handler_read_failed,
|
||||||
[MfPlusPollerStateReadSuccess] = mf_plus_poller_handler_read_success,
|
[MfPlusPollerStateReadSuccess] = mf_plus_poller_handler_read_success,
|
||||||
};
|
};
|
||||||
@@ -351,7 +183,16 @@ static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) {
|
|||||||
bool detected = false;
|
bool detected = false;
|
||||||
|
|
||||||
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
||||||
detected = mf_plus_poller_detect_type(instance);
|
detected = mf_plus_poller_read_version(instance, &instance->data->version);
|
||||||
|
if(detected) {
|
||||||
|
detected = mf_plus_get_type_from_version(
|
||||||
|
iso14443_4a_poller_get_data(instance->iso14443_4a_poller),
|
||||||
|
instance->data) == MfPlusErrorNone;
|
||||||
|
} else {
|
||||||
|
detected = mf_plus_get_type_from_iso4(
|
||||||
|
iso14443_4a_poller_get_data(instance->iso14443_4a_poller),
|
||||||
|
instance->data) == MfPlusErrorNone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return detected;
|
return detected;
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ MfPlusError mf_plus_process_error(Iso14443_4aError error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MfPlusError
|
MfPlusError mf_plus_poller_send_chunk(
|
||||||
mf_plus_send_chunk(MfPlusPoller* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer) {
|
MfPlusPoller* instance,
|
||||||
|
const BitBuffer* tx_buffer,
|
||||||
|
BitBuffer* rx_buffer) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(instance->iso14443_4a_poller);
|
furi_assert(instance->iso14443_4a_poller);
|
||||||
furi_assert(instance->tx_buffer);
|
furi_assert(instance->tx_buffer);
|
||||||
@@ -43,8 +45,10 @@ MfPlusError
|
|||||||
|
|
||||||
if(bit_buffer_get_size_bytes(instance->rx_buffer) > sizeof(uint8_t)) {
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) > sizeof(uint8_t)) {
|
||||||
bit_buffer_copy_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t));
|
bit_buffer_copy_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t));
|
||||||
|
FURI_LOG_D(TAG, "Received %d bytes", bit_buffer_get_size_bytes(rx_buffer));
|
||||||
} else {
|
} else {
|
||||||
bit_buffer_reset(rx_buffer);
|
bit_buffer_reset(rx_buffer);
|
||||||
|
FURI_LOG_D(TAG, "Received 0 bytes");
|
||||||
}
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
@@ -60,7 +64,8 @@ MfPlusError mf_plus_poller_read_version(MfPlusPoller* instance, MfPlusVersion* d
|
|||||||
MfPlusError error;
|
MfPlusError error;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
error = mf_plus_send_chunk(instance, instance->input_buffer, instance->result_buffer);
|
error =
|
||||||
|
mf_plus_poller_send_chunk(instance, instance->input_buffer, instance->result_buffer);
|
||||||
|
|
||||||
if(error != MfPlusErrorNone) break;
|
if(error != MfPlusErrorNone) break;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
MfPlusPollerStateIdle,
|
MfPlusPollerStateIdle,
|
||||||
MfPlusPollerStateReadVersion,
|
MfPlusPollerStateReadVersion,
|
||||||
|
MfPlusPollerStateParseVersion,
|
||||||
|
MfPlusPollerStateParseIso4,
|
||||||
MfPlusPollerStateReadFailed,
|
MfPlusPollerStateReadFailed,
|
||||||
MfPlusPollerStateReadSuccess,
|
MfPlusPollerStateReadSuccess,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user