mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-22 05:14:46 -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);
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
MfDesfireVersion version = {};
|
||||
error = mf_desfire_poller_read_version(instance, &version);
|
||||
error = mf_desfire_poller_read_version(instance, &instance->data->version);
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
protocol_detected = true;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "type_4_tag_i.h"
|
||||
|
||||
#define TYPE_4_TAG_PROTOCOL_NAME "Type 4 Tag"
|
||||
#define TYPE_4_TAG_SHORT_NAME "T4T"
|
||||
|
||||
const NfcDeviceBase nfc_device_type_4_tag = {
|
||||
.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* data = malloc(sizeof(Type4TagData));
|
||||
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);
|
||||
return data;
|
||||
}
|
||||
@@ -30,6 +34,9 @@ void type_4_tag_free(Type4TagData* data) {
|
||||
|
||||
type_4_tag_reset(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);
|
||||
free(data);
|
||||
}
|
||||
@@ -40,6 +47,9 @@ void type_4_tag_reset(Type4TagData* data) {
|
||||
iso14443_4a_reset(data->iso14443_4a_data);
|
||||
|
||||
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->chunk_max_read = 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);
|
||||
|
||||
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->chunk_max_read = other->chunk_max_read;
|
||||
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) {
|
||||
UNUSED(data);
|
||||
UNUSED(name_type);
|
||||
return TYPE_4_TAG_PROTOCOL_NAME;
|
||||
FuriString* platform_name = name_type == NfcDeviceNameTypeFull ? data->platform_name_full :
|
||||
data->platform_name_short;
|
||||
if(furi_string_empty(platform_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) {
|
||||
|
||||
@@ -19,10 +19,20 @@ typedef enum {
|
||||
Type4TagErrorCustomCommand,
|
||||
} Type4TagError;
|
||||
|
||||
typedef enum {
|
||||
Type4TagPlatformUnknown,
|
||||
Type4TagPlatformNtag4xx,
|
||||
Type4TagPlatformMfDesfire,
|
||||
} Type4TagPlatform;
|
||||
|
||||
typedef struct {
|
||||
Iso14443_4aData* iso14443_4a_data;
|
||||
FuriString* device_name;
|
||||
// Tag specific data
|
||||
bool is_tag_specific;
|
||||
Type4TagPlatform platform;
|
||||
FuriString* platform_name_full;
|
||||
FuriString* platform_name_short;
|
||||
union {
|
||||
struct {
|
||||
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);
|
||||
}
|
||||
|
||||
instance->state = Type4TagPollerStateSelectApplication;
|
||||
instance->state = Type4TagPollerStateDetectPlatform;
|
||||
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) {
|
||||
instance->error = type_4_tag_poller_select_app(instance);
|
||||
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] = {
|
||||
[Type4TagPollerStateIdle] = type_4_tag_poller_handler_idle,
|
||||
[Type4TagPollerStateRequestMode] = type_4_tag_poller_handler_request_mode,
|
||||
[Type4TagPollerStateDetectPlatform] = type_4_tag_poller_handler_detect_platform,
|
||||
[Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app,
|
||||
[Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc,
|
||||
[Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef,
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/protocols/mf_desfire/mf_desfire_poller_defs.h>
|
||||
|
||||
#define TAG "Type4TagPoller"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
furi_check(instance);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ extern "C" {
|
||||
typedef enum {
|
||||
Type4TagPollerStateIdle,
|
||||
Type4TagPollerStateRequestMode,
|
||||
Type4TagPollerStateDetectPlatform,
|
||||
Type4TagPollerStateSelectApplication,
|
||||
Type4TagPollerStateReadCapabilityContainer,
|
||||
Type4TagPollerStateReadNdefMessage,
|
||||
@@ -41,6 +42,8 @@ struct Type4TagPoller {
|
||||
|
||||
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_read_cc(Type4TagPoller* instance);
|
||||
|
||||
Reference in New Issue
Block a user