mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-21 05:04:46 -07:00
NFC: Implement Type 4 Tag writing biolerplate and structure
This commit is contained in:
@@ -14,6 +14,7 @@ typedef enum {
|
||||
Type4TagErrorWrongFormat,
|
||||
Type4TagErrorNotSupported,
|
||||
Type4TagErrorApduFailed,
|
||||
Type4TagErrorCardLocked,
|
||||
Type4TagErrorCustomCommand,
|
||||
} Type4TagError;
|
||||
|
||||
|
||||
@@ -45,10 +45,27 @@ static NfcCommand type_4_tag_poller_handler_idle(Type4TagPoller* instance) {
|
||||
instance->data->iso14443_4a_data,
|
||||
iso14443_4a_poller_get_data(instance->iso14443_4a_poller));
|
||||
|
||||
instance->state = Type4TagPollerStateSelectApplication;
|
||||
instance->state = Type4TagPollerStateRequestMode;
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_request_mode(Type4TagPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
instance->type_4_tag_event.type = Type4TagPollerEventTypeRequestMode;
|
||||
instance->type_4_tag_event.data->poller_mode.mode = Type4TagPollerModeRead;
|
||||
instance->type_4_tag_event.data->poller_mode.data = NULL;
|
||||
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
instance->mode = instance->type_4_tag_event.data->poller_mode.mode;
|
||||
if(instance->mode == Type4TagPollerModeWrite) {
|
||||
type_4_tag_copy(instance->data, instance->type_4_tag_event.data->poller_mode.data);
|
||||
}
|
||||
|
||||
instance->state = Type4TagPollerStateSelectApplication;
|
||||
return command;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_select_app(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
@@ -56,8 +73,12 @@ static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance)
|
||||
instance->state = Type4TagPollerStateReadCapabilityContainer;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to select application");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
instance->state = Type4TagPollerStateReadFailed;
|
||||
if(instance->mode == Type4TagPollerModeWrite &&
|
||||
instance->error == Type4TagErrorApduFailed) {
|
||||
instance->state = Type4TagPollerStateCreateApplication;
|
||||
} else {
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
@@ -67,11 +88,17 @@ static NfcCommand type_4_tag_poller_handler_read_cc(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_read_cc(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Read CC success");
|
||||
instance->state = Type4TagPollerStateReadNdefMessage;
|
||||
instance->state = instance->mode == Type4TagPollerModeRead ?
|
||||
Type4TagPollerStateReadNdefMessage :
|
||||
Type4TagPollerStateWriteNdefMessage;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to read CC");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
instance->state = Type4TagPollerStateReadFailed;
|
||||
if(instance->mode == Type4TagPollerModeWrite &&
|
||||
instance->error == Type4TagErrorApduFailed) {
|
||||
instance->state = Type4TagPollerStateCreateCapabilityContainer;
|
||||
} else {
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
@@ -81,41 +108,115 @@ static NfcCommand type_4_tag_poller_handler_read_ndef(Type4TagPoller* instance)
|
||||
instance->error = type_4_tag_poller_read_ndef(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Read NDEF success");
|
||||
instance->state = Type4TagPollerStateReadSuccess;
|
||||
instance->state = Type4TagPollerStateSuccess;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to read NDEF");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
instance->state = Type4TagPollerStateReadFailed;
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_read_fail(Type4TagPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Read Failed");
|
||||
static NfcCommand type_4_tag_poller_handler_create_app(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_create_app(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Create application success");
|
||||
instance->state = Type4TagPollerStateSelectApplication;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to create application");
|
||||
if(instance->error == Type4TagErrorApduFailed) {
|
||||
instance->error = Type4TagErrorCardLocked;
|
||||
}
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_create_cc(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_create_cc(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Create CC success");
|
||||
instance->state = Type4TagPollerStateReadCapabilityContainer;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to create CC");
|
||||
if(instance->error == Type4TagErrorApduFailed) {
|
||||
instance->error = Type4TagErrorCardLocked;
|
||||
}
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_create_ndef(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_create_ndef(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Create NDEF success");
|
||||
instance->state = Type4TagPollerStateWriteNdefMessage;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to create NDEF");
|
||||
if(instance->error == Type4TagErrorApduFailed) {
|
||||
instance->error = Type4TagErrorCardLocked;
|
||||
}
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_write_ndef(Type4TagPoller* instance) {
|
||||
instance->error = type_4_tag_poller_write_ndef(instance);
|
||||
if(instance->error == Type4TagErrorNone) {
|
||||
FURI_LOG_D(TAG, "Write NDEF success");
|
||||
instance->state = Type4TagPollerStateSuccess;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to write NDEF");
|
||||
if(instance->mode == Type4TagPollerModeWrite &&
|
||||
instance->error == Type4TagErrorApduFailed) {
|
||||
instance->state = Type4TagPollerStateCreateNdefMessage;
|
||||
} else {
|
||||
instance->state = Type4TagPollerStateFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_fail(Type4TagPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Operation Failed");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
instance->type_4_tag_event.type = Type4TagPollerEventTypeReadFailed;
|
||||
instance->type_4_tag_event.type = instance->mode == Type4TagPollerModeRead ?
|
||||
Type4TagPollerEventTypeReadFailed :
|
||||
Type4TagPollerEventTypeWriteFail;
|
||||
instance->type_4_tag_event.data->error = instance->error;
|
||||
NfcCommand command = instance->callback(instance->general_event, instance->context);
|
||||
instance->state = Type4TagPollerStateIdle;
|
||||
return command;
|
||||
}
|
||||
|
||||
static NfcCommand type_4_tag_poller_handler_read_success(Type4TagPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Read success.");
|
||||
static NfcCommand type_4_tag_poller_handler_success(Type4TagPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Operation succeeded");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
instance->type_4_tag_event.type = Type4TagPollerEventTypeReadSuccess;
|
||||
instance->type_4_tag_event.type = instance->mode == Type4TagPollerModeRead ?
|
||||
Type4TagPollerEventTypeReadSuccess :
|
||||
Type4TagPollerEventTypeWriteSuccess;
|
||||
NfcCommand command = instance->callback(instance->general_event, instance->context);
|
||||
return command;
|
||||
}
|
||||
|
||||
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,
|
||||
[Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app,
|
||||
[Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc,
|
||||
[Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef,
|
||||
[Type4TagPollerStateReadFailed] = type_4_tag_poller_handler_read_fail,
|
||||
[Type4TagPollerStateReadSuccess] = type_4_tag_poller_handler_read_success,
|
||||
[Type4TagPollerStateCreateApplication] = type_4_tag_poller_handler_create_app,
|
||||
[Type4TagPollerStateCreateCapabilityContainer] = type_4_tag_poller_handler_create_cc,
|
||||
[Type4TagPollerStateCreateNdefMessage] = type_4_tag_poller_handler_create_ndef,
|
||||
[Type4TagPollerStateWriteNdefMessage] = type_4_tag_poller_handler_write_ndef,
|
||||
[Type4TagPollerStateFailed] = type_4_tag_poller_handler_fail,
|
||||
[Type4TagPollerStateSuccess] = type_4_tag_poller_handler_success,
|
||||
};
|
||||
|
||||
static void type_4_tag_poller_set_callback(
|
||||
|
||||
@@ -15,15 +15,37 @@ typedef struct Type4TagPoller Type4TagPoller;
|
||||
* @brief Enumeration of possible Type4Tag poller event types.
|
||||
*/
|
||||
typedef enum {
|
||||
Type4TagPollerEventTypeRequestMode, /**< Poller requests for operating mode. */
|
||||
Type4TagPollerEventTypeReadSuccess, /**< Card was read successfully. */
|
||||
Type4TagPollerEventTypeReadFailed, /**< Poller failed to read card. */
|
||||
Type4TagPollerEventTypeWriteSuccess, /**< Poller wrote card successfully. */
|
||||
Type4TagPollerEventTypeWriteFail, /**< Poller failed to write card. */
|
||||
} Type4TagPollerEventType;
|
||||
|
||||
/**
|
||||
* @brief Enumeration of possible Type4Tag poller operating modes.
|
||||
*/
|
||||
typedef enum {
|
||||
Type4TagPollerModeRead, /**< Poller will only read card. It's a default mode. */
|
||||
Type4TagPollerModeWrite, /**< Poller will write already saved card to another presented card. */
|
||||
} Type4TagPollerMode;
|
||||
|
||||
/**
|
||||
* @brief Type4Tag poller request mode event data.
|
||||
*
|
||||
* This instance of this structure must be filled on Type4TagPollerEventTypeRequestMode event.
|
||||
*/
|
||||
typedef struct {
|
||||
Type4TagPollerMode mode; /**< Mode to be used by poller. */
|
||||
const Type4TagData* data; /**< Data to be used by poller. */
|
||||
} Type4TagPollerEventDataRequestMode;
|
||||
|
||||
/**
|
||||
* @brief Type4Tag poller event data.
|
||||
*/
|
||||
typedef union {
|
||||
Type4TagError error; /**< Error code indicating card reading fail reason. */
|
||||
Type4TagPollerEventDataRequestMode poller_mode; /**< Poller mode context. */
|
||||
} Type4TagPollerEventData;
|
||||
|
||||
/**
|
||||
|
||||
@@ -198,11 +198,28 @@ Type4TagError type_4_tag_poller_read_ndef(Type4TagPoller* instance) {
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Read NDEF file 0x%04X of %lu bytes",
|
||||
instance->data->ndef_file_id,
|
||||
simple_array_get_count(instance->data->ndef_data));
|
||||
TAG, "Read %hu bytes from NDEF file 0x%04X", ndef_len, instance->data->ndef_file_id);
|
||||
} while(false);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_create_app(Type4TagPoller* instance) {
|
||||
UNUSED(instance);
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_create_cc(Type4TagPoller* instance) {
|
||||
UNUSED(instance);
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_create_ndef(Type4TagPoller* instance) {
|
||||
UNUSED(instance);
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_write_ndef(Type4TagPoller* instance) {
|
||||
UNUSED(instance);
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,16 @@ extern "C" {
|
||||
|
||||
typedef enum {
|
||||
Type4TagPollerStateIdle,
|
||||
Type4TagPollerStateRequestMode,
|
||||
Type4TagPollerStateSelectApplication,
|
||||
Type4TagPollerStateReadCapabilityContainer,
|
||||
Type4TagPollerStateReadNdefMessage,
|
||||
Type4TagPollerStateReadFailed,
|
||||
Type4TagPollerStateReadSuccess,
|
||||
Type4TagPollerStateCreateApplication,
|
||||
Type4TagPollerStateCreateCapabilityContainer,
|
||||
Type4TagPollerStateCreateNdefMessage,
|
||||
Type4TagPollerStateWriteNdefMessage,
|
||||
Type4TagPollerStateFailed,
|
||||
Type4TagPollerStateSuccess,
|
||||
|
||||
Type4TagPollerStateNum,
|
||||
} Type4TagPollerState;
|
||||
@@ -22,6 +27,7 @@ typedef enum {
|
||||
struct Type4TagPoller {
|
||||
Iso14443_4aPoller* iso14443_4a_poller;
|
||||
Type4TagPollerState state;
|
||||
Type4TagPollerMode mode;
|
||||
Type4TagError error;
|
||||
Type4TagData* data;
|
||||
BitBuffer* tx_buffer;
|
||||
@@ -41,6 +47,14 @@ Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance);
|
||||
|
||||
Type4TagError type_4_tag_poller_read_ndef(Type4TagPoller* instance);
|
||||
|
||||
Type4TagError type_4_tag_poller_create_app(Type4TagPoller* instance);
|
||||
|
||||
Type4TagError type_4_tag_poller_create_cc(Type4TagPoller* instance);
|
||||
|
||||
Type4TagError type_4_tag_poller_create_ndef(Type4TagPoller* instance);
|
||||
|
||||
Type4TagError type_4_tag_poller_write_ndef(Type4TagPoller* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user