mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-24 05:34:45 -07:00
NFC: Detect Type 4 Tag platform (eg DESFire)
This commit is contained in:
@@ -251,8 +251,7 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
|
|||||||
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
|
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
|
||||||
if(error != MfDesfireErrorNone) break;
|
if(error != MfDesfireErrorNone) break;
|
||||||
|
|
||||||
MfDesfireVersion version = {};
|
error = mf_desfire_poller_read_version(instance, &instance->data->version);
|
||||||
error = mf_desfire_poller_read_version(instance, &version);
|
|
||||||
if(error != MfDesfireErrorNone) break;
|
if(error != MfDesfireErrorNone) break;
|
||||||
|
|
||||||
protocol_detected = true;
|
protocol_detected = true;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "type_4_tag_i.h"
|
#include "type_4_tag_i.h"
|
||||||
|
|
||||||
#define TYPE_4_TAG_PROTOCOL_NAME "Type 4 Tag"
|
#define TYPE_4_TAG_PROTOCOL_NAME "Type 4 Tag"
|
||||||
|
#define TYPE_4_TAG_SHORT_NAME "T4T"
|
||||||
|
|
||||||
const NfcDeviceBase nfc_device_type_4_tag = {
|
const NfcDeviceBase nfc_device_type_4_tag = {
|
||||||
.protocol_name = TYPE_4_TAG_PROTOCOL_NAME,
|
.protocol_name = TYPE_4_TAG_PROTOCOL_NAME,
|
||||||
@@ -21,6 +22,9 @@ const NfcDeviceBase nfc_device_type_4_tag = {
|
|||||||
Type4TagData* type_4_tag_alloc(void) {
|
Type4TagData* type_4_tag_alloc(void) {
|
||||||
Type4TagData* data = malloc(sizeof(Type4TagData));
|
Type4TagData* data = malloc(sizeof(Type4TagData));
|
||||||
data->iso14443_4a_data = iso14443_4a_alloc();
|
data->iso14443_4a_data = iso14443_4a_alloc();
|
||||||
|
data->device_name = furi_string_alloc();
|
||||||
|
data->platform_name_full = furi_string_alloc();
|
||||||
|
data->platform_name_short = furi_string_alloc();
|
||||||
data->ndef_data = simple_array_alloc(&simple_array_config_uint8_t);
|
data->ndef_data = simple_array_alloc(&simple_array_config_uint8_t);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -30,6 +34,9 @@ void type_4_tag_free(Type4TagData* data) {
|
|||||||
|
|
||||||
type_4_tag_reset(data);
|
type_4_tag_reset(data);
|
||||||
simple_array_free(data->ndef_data);
|
simple_array_free(data->ndef_data);
|
||||||
|
furi_string_free(data->platform_name_short);
|
||||||
|
furi_string_free(data->platform_name_full);
|
||||||
|
furi_string_free(data->device_name);
|
||||||
iso14443_4a_free(data->iso14443_4a_data);
|
iso14443_4a_free(data->iso14443_4a_data);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
@@ -40,6 +47,9 @@ void type_4_tag_reset(Type4TagData* data) {
|
|||||||
iso14443_4a_reset(data->iso14443_4a_data);
|
iso14443_4a_reset(data->iso14443_4a_data);
|
||||||
|
|
||||||
data->is_tag_specific = false;
|
data->is_tag_specific = false;
|
||||||
|
furi_string_reset(data->device_name);
|
||||||
|
furi_string_reset(data->platform_name_full);
|
||||||
|
furi_string_reset(data->platform_name_short);
|
||||||
data->t4t_version.value = 0;
|
data->t4t_version.value = 0;
|
||||||
data->chunk_max_read = 0;
|
data->chunk_max_read = 0;
|
||||||
data->chunk_max_write = 0;
|
data->chunk_max_write = 0;
|
||||||
@@ -60,6 +70,9 @@ void type_4_tag_copy(Type4TagData* data, const Type4TagData* other) {
|
|||||||
iso14443_4a_copy(data->iso14443_4a_data, other->iso14443_4a_data);
|
iso14443_4a_copy(data->iso14443_4a_data, other->iso14443_4a_data);
|
||||||
|
|
||||||
data->is_tag_specific = other->is_tag_specific;
|
data->is_tag_specific = other->is_tag_specific;
|
||||||
|
furi_string_set(data->device_name, other->device_name);
|
||||||
|
furi_string_set(data->platform_name_full, other->platform_name_full);
|
||||||
|
furi_string_set(data->platform_name_short, other->platform_name_short);
|
||||||
data->t4t_version.value = other->t4t_version.value;
|
data->t4t_version.value = other->t4t_version.value;
|
||||||
data->chunk_max_read = other->chunk_max_read;
|
data->chunk_max_read = other->chunk_max_read;
|
||||||
data->chunk_max_write = other->chunk_max_write;
|
data->chunk_max_write = other->chunk_max_write;
|
||||||
@@ -137,9 +150,19 @@ bool type_4_tag_is_equal(const Type4TagData* data, const Type4TagData* other) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* type_4_tag_get_device_name(const Type4TagData* data, NfcDeviceNameType name_type) {
|
const char* type_4_tag_get_device_name(const Type4TagData* data, NfcDeviceNameType name_type) {
|
||||||
UNUSED(data);
|
FuriString* platform_name = name_type == NfcDeviceNameTypeFull ? data->platform_name_full :
|
||||||
UNUSED(name_type);
|
data->platform_name_short;
|
||||||
|
if(furi_string_empty(platform_name)) {
|
||||||
return TYPE_4_TAG_PROTOCOL_NAME;
|
return TYPE_4_TAG_PROTOCOL_NAME;
|
||||||
|
}
|
||||||
|
furi_string_printf(
|
||||||
|
data->device_name,
|
||||||
|
"%s%c(%s)",
|
||||||
|
name_type == NfcDeviceNameTypeFull ? TYPE_4_TAG_PROTOCOL_NAME : TYPE_4_TAG_SHORT_NAME,
|
||||||
|
name_type == NfcDeviceNameTypeFull ? '\n' : ' ',
|
||||||
|
furi_string_get_cstr(platform_name));
|
||||||
|
furi_string_replace_str(data->device_name, "Mifare", "MIFARE");
|
||||||
|
return furi_string_get_cstr(data->device_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* type_4_tag_get_uid(const Type4TagData* data, size_t* uid_len) {
|
const uint8_t* type_4_tag_get_uid(const Type4TagData* data, size_t* uid_len) {
|
||||||
|
|||||||
@@ -19,10 +19,20 @@ typedef enum {
|
|||||||
Type4TagErrorCustomCommand,
|
Type4TagErrorCustomCommand,
|
||||||
} Type4TagError;
|
} Type4TagError;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Type4TagPlatformUnknown,
|
||||||
|
Type4TagPlatformNtag4xx,
|
||||||
|
Type4TagPlatformMfDesfire,
|
||||||
|
} Type4TagPlatform;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Iso14443_4aData* iso14443_4a_data;
|
Iso14443_4aData* iso14443_4a_data;
|
||||||
|
FuriString* device_name;
|
||||||
// Tag specific data
|
// Tag specific data
|
||||||
bool is_tag_specific;
|
bool is_tag_specific;
|
||||||
|
Type4TagPlatform platform;
|
||||||
|
FuriString* platform_name_full;
|
||||||
|
FuriString* platform_name_short;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint8_t minor : 4;
|
uint8_t minor : 4;
|
||||||
|
|||||||
@@ -62,10 +62,23 @@ static NfcCommand type_4_tag_poller_handler_request_mode(Type4TagPoller* instanc
|
|||||||
type_4_tag_copy(instance->data, instance->type_4_tag_event.data->poller_mode.data);
|
type_4_tag_copy(instance->data, instance->type_4_tag_event.data->poller_mode.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->state = Type4TagPollerStateSelectApplication;
|
instance->state = Type4TagPollerStateDetectPlatform;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NfcCommand type_4_tag_poller_handler_detect_platform(Type4TagPoller* instance) {
|
||||||
|
instance->error = type_4_tag_poller_detect_platform(instance);
|
||||||
|
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||||
|
if(instance->error == Type4TagErrorNone) {
|
||||||
|
FURI_LOG_D(TAG, "Detect platform success");
|
||||||
|
} else {
|
||||||
|
FURI_LOG_W(TAG, "Failed to detect platform");
|
||||||
|
}
|
||||||
|
instance->state = Type4TagPollerStateSelectApplication;
|
||||||
|
|
||||||
|
return NfcCommandContinue;
|
||||||
|
}
|
||||||
|
|
||||||
static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) {
|
static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) {
|
||||||
instance->error = type_4_tag_poller_select_app(instance);
|
instance->error = type_4_tag_poller_select_app(instance);
|
||||||
if(instance->error == Type4TagErrorNone) {
|
if(instance->error == Type4TagErrorNone) {
|
||||||
@@ -199,6 +212,7 @@ static NfcCommand type_4_tag_poller_handler_success(Type4TagPoller* instance) {
|
|||||||
static const Type4TagPollerReadHandler type_4_tag_poller_read_handler[Type4TagPollerStateNum] = {
|
static const Type4TagPollerReadHandler type_4_tag_poller_read_handler[Type4TagPollerStateNum] = {
|
||||||
[Type4TagPollerStateIdle] = type_4_tag_poller_handler_idle,
|
[Type4TagPollerStateIdle] = type_4_tag_poller_handler_idle,
|
||||||
[Type4TagPollerStateRequestMode] = type_4_tag_poller_handler_request_mode,
|
[Type4TagPollerStateRequestMode] = type_4_tag_poller_handler_request_mode,
|
||||||
|
[Type4TagPollerStateDetectPlatform] = type_4_tag_poller_handler_detect_platform,
|
||||||
[Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app,
|
[Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app,
|
||||||
[Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc,
|
[Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc,
|
||||||
[Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef,
|
[Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef,
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include <bit_lib/bit_lib.h>
|
#include <bit_lib/bit_lib.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc_device.h>
|
||||||
|
#include <nfc/protocols/mf_desfire/mf_desfire_poller_defs.h>
|
||||||
|
|
||||||
#define TAG "Type4TagPoller"
|
#define TAG "Type4TagPoller"
|
||||||
|
|
||||||
Type4TagError type_4_tag_apdu_trx(Type4TagPoller* instance, BitBuffer* tx_buf, BitBuffer* rx_buf) {
|
Type4TagError type_4_tag_apdu_trx(Type4TagPoller* instance, BitBuffer* tx_buf, BitBuffer* rx_buf) {
|
||||||
@@ -178,6 +181,52 @@ static Type4TagError type_5_tag_poller_iso_write(
|
|||||||
return Type4TagErrorNone;
|
return Type4TagErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type4TagError type_4_tag_poller_detect_platform(Type4TagPoller* instance) {
|
||||||
|
furi_check(instance);
|
||||||
|
|
||||||
|
Iso14443_4aPollerEvent iso14443_4a_event = {
|
||||||
|
.type = Iso14443_4aPollerEventTypeReady,
|
||||||
|
.data = NULL,
|
||||||
|
};
|
||||||
|
NfcGenericEvent event = {
|
||||||
|
.protocol = NfcProtocolIso14443_4a,
|
||||||
|
.instance = instance->iso14443_4a_poller,
|
||||||
|
.event_data = &iso14443_4a_event,
|
||||||
|
};
|
||||||
|
|
||||||
|
Type4TagPlatform platform = Type4TagPlatformUnknown;
|
||||||
|
NfcDevice* device = nfc_device_alloc();
|
||||||
|
|
||||||
|
do {
|
||||||
|
FURI_LOG_D(TAG, "Detect DESFire");
|
||||||
|
NfcGenericInstance* mf_des = mf_desfire_poller.alloc(instance->iso14443_4a_poller);
|
||||||
|
if(mf_desfire_poller.detect(event, mf_des)) {
|
||||||
|
platform = Type4TagPlatformMfDesfire;
|
||||||
|
nfc_device_set_data(device, NfcProtocolMfDesfire, mf_desfire_poller.get_data(mf_des));
|
||||||
|
}
|
||||||
|
mf_desfire_poller.free(mf_des);
|
||||||
|
if(platform != Type4TagPlatformUnknown) break;
|
||||||
|
|
||||||
|
// FIXME: detect NTAG4xx
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
if(platform != Type4TagPlatformUnknown) {
|
||||||
|
furi_string_set(
|
||||||
|
instance->data->platform_name_full,
|
||||||
|
nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||||
|
furi_string_set(
|
||||||
|
instance->data->platform_name_short,
|
||||||
|
nfc_device_get_name(device, NfcDeviceNameTypeShort));
|
||||||
|
} else {
|
||||||
|
furi_string_reset(instance->data->platform_name_full);
|
||||||
|
furi_string_reset(instance->data->platform_name_short);
|
||||||
|
}
|
||||||
|
instance->data->platform = platform;
|
||||||
|
nfc_device_free(device);
|
||||||
|
|
||||||
|
return platform != Type4TagPlatformUnknown ? Type4TagErrorNone : Type4TagErrorNotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance) {
|
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance) {
|
||||||
furi_check(instance);
|
furi_check(instance);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ extern "C" {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
Type4TagPollerStateIdle,
|
Type4TagPollerStateIdle,
|
||||||
Type4TagPollerStateRequestMode,
|
Type4TagPollerStateRequestMode,
|
||||||
|
Type4TagPollerStateDetectPlatform,
|
||||||
Type4TagPollerStateSelectApplication,
|
Type4TagPollerStateSelectApplication,
|
||||||
Type4TagPollerStateReadCapabilityContainer,
|
Type4TagPollerStateReadCapabilityContainer,
|
||||||
Type4TagPollerStateReadNdefMessage,
|
Type4TagPollerStateReadNdefMessage,
|
||||||
@@ -41,6 +42,8 @@ struct Type4TagPoller {
|
|||||||
|
|
||||||
const Type4TagData* type_4_tag_poller_get_data(Type4TagPoller* instance);
|
const Type4TagData* type_4_tag_poller_get_data(Type4TagPoller* instance);
|
||||||
|
|
||||||
|
Type4TagError type_4_tag_poller_detect_platform(Type4TagPoller* instance);
|
||||||
|
|
||||||
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance);
|
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance);
|
||||||
|
|
||||||
Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance);
|
Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance);
|
||||||
|
|||||||
Reference in New Issue
Block a user