mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-16 04:24:45 -07:00
added "Listen NfcV Reader" to sniff traffic from reader to card
This commit is contained in:
@@ -19,6 +19,7 @@ ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu)
|
|||||||
ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput)
|
ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput)
|
||||||
ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock)
|
ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock)
|
||||||
ADD_SCENE(nfc, nfcv_emulate, NfcVEmulate)
|
ADD_SCENE(nfc, nfcv_emulate, NfcVEmulate)
|
||||||
|
ADD_SCENE(nfc, nfcv_sniff, NfcVSniff)
|
||||||
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
|
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
|
||||||
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
|
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
|
||||||
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexMfClassicKeys,
|
SubmenuIndexMfClassicKeys,
|
||||||
SubmenuIndexMfUltralightUnlock,
|
SubmenuIndexMfUltralightUnlock,
|
||||||
SubmenuIndexNfcVUnlock,
|
SubmenuIndexNfcVUnlock,
|
||||||
|
SubmenuIndexNfcVSniff,
|
||||||
};
|
};
|
||||||
|
|
||||||
void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
|
void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
|
||||||
@@ -41,6 +42,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
|||||||
SubmenuIndexNfcVUnlock,
|
SubmenuIndexNfcVUnlock,
|
||||||
nfc_scene_extra_actions_submenu_callback,
|
nfc_scene_extra_actions_submenu_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Listen NfcV Reader",
|
||||||
|
SubmenuIndexNfcVSniff,
|
||||||
|
nfc_scene_extra_actions_submenu_callback,
|
||||||
|
nfc);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +73,9 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
|
|||||||
} else if(event.event == SubmenuIndexNfcVUnlock) {
|
} else if(event.event == SubmenuIndexNfcVUnlock) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlockMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlockMenu);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexNfcVSniff) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVSniff);
|
||||||
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
|
||||||
}
|
}
|
||||||
|
|||||||
155
applications/main/nfc/scenes/nfc_scene_nfcv_sniff.c
Normal file
155
applications/main/nfc/scenes/nfc_scene_nfcv_sniff.c
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#include "../nfc_i.h"
|
||||||
|
|
||||||
|
#define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (200)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NfcSceneNfcVSniffStateWidget,
|
||||||
|
NfcSceneNfcVSniffStateTextBox,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool nfc_scene_nfcv_sniff_worker_callback(NfcWorkerEvent event, void* context) {
|
||||||
|
UNUSED(event);
|
||||||
|
furi_assert(context);
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
switch(event) {
|
||||||
|
case NfcWorkerEventNfcVCommandExecuted:
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventUpdateLog);
|
||||||
|
break;
|
||||||
|
case NfcWorkerEventNfcVContentChanged:
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventSaveShadow);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_nfcv_sniff_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
Nfc* nfc = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_nfcv_sniff_textbox_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
Nfc* nfc = context;
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfc_scene_nfcv_sniff_widget_config(Nfc* nfc, bool data_received) {
|
||||||
|
Widget* widget = nfc->widget;
|
||||||
|
widget_reset(widget);
|
||||||
|
FuriString* info_str;
|
||||||
|
info_str = furi_string_alloc();
|
||||||
|
|
||||||
|
widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||||
|
widget_add_string_element(widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Listen NfcV");
|
||||||
|
furi_string_trim(info_str);
|
||||||
|
widget_add_text_box_element(
|
||||||
|
widget, 56, 43, 70, 21, AlignCenter, AlignTop, furi_string_get_cstr(info_str), true);
|
||||||
|
furi_string_free(info_str);
|
||||||
|
if(data_received) {
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeCenter, "Log", nfc_scene_nfcv_sniff_widget_callback, nfc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_nfcv_sniff_on_enter(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
// Setup Widget
|
||||||
|
nfc_scene_nfcv_sniff_widget_config(nfc, false);
|
||||||
|
// Setup TextBox
|
||||||
|
TextBox* text_box = nfc->text_box;
|
||||||
|
text_box_set_font(text_box, TextBoxFontHex);
|
||||||
|
text_box_set_focus(text_box, TextBoxFocusEnd);
|
||||||
|
text_box_set_text(text_box, "");
|
||||||
|
furi_string_reset(nfc->text_box_store);
|
||||||
|
|
||||||
|
// Set Widget state and view
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneNfcVSniff, NfcSceneNfcVSniffStateWidget);
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
|
// Start worker
|
||||||
|
memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData));
|
||||||
|
nfc_worker_start(
|
||||||
|
nfc->worker,
|
||||||
|
NfcWorkerStateNfcVSniff,
|
||||||
|
&nfc->dev->dev_data,
|
||||||
|
nfc_scene_nfcv_sniff_worker_callback,
|
||||||
|
nfc);
|
||||||
|
|
||||||
|
nfc_blink_emulate_start(nfc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_scene_nfcv_sniff_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data;
|
||||||
|
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVSniff);
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == NfcCustomEventUpdateLog) {
|
||||||
|
// Add data button to widget if data is received for the first time
|
||||||
|
if(strlen(nfcv_data->last_command) > 0) {
|
||||||
|
if(!furi_string_size(nfc->text_box_store)) {
|
||||||
|
nfc_scene_nfcv_sniff_widget_config(nfc, true);
|
||||||
|
}
|
||||||
|
/* use the last n bytes from the log so there's enough space for the new log entry */
|
||||||
|
size_t maxSize =
|
||||||
|
NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX - (strlen(nfcv_data->last_command) + 1);
|
||||||
|
if(furi_string_size(nfc->text_box_store) >= maxSize) {
|
||||||
|
furi_string_right(nfc->text_box_store, (strlen(nfcv_data->last_command) + 1));
|
||||||
|
}
|
||||||
|
furi_string_cat_printf(nfc->text_box_store, "%s", nfcv_data->last_command);
|
||||||
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
|
text_box_set_text(nfc->text_box, furi_string_get_cstr(nfc->text_box_store));
|
||||||
|
|
||||||
|
/* clear previously logged command */
|
||||||
|
strcpy(nfcv_data->last_command, "");
|
||||||
|
}
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == NfcCustomEventSaveShadow) {
|
||||||
|
if(furi_string_size(nfc->dev->load_path)) {
|
||||||
|
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
|
||||||
|
}
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == GuiButtonTypeCenter && state == NfcSceneNfcVSniffStateWidget) {
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneNfcVSniff, NfcSceneNfcVSniffStateTextBox);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == NfcCustomEventViewExit && state == NfcSceneNfcVSniffStateTextBox) {
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneNfcVSniff, NfcSceneNfcVSniffStateWidget);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
if(state == NfcSceneNfcVSniffStateTextBox) {
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneNfcVSniff, NfcSceneNfcVSniffStateWidget);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_nfcv_sniff_on_exit(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
// Stop worker
|
||||||
|
nfc_worker_stop(nfc->worker);
|
||||||
|
|
||||||
|
// Clear view
|
||||||
|
widget_reset(nfc->widget);
|
||||||
|
text_box_reset(nfc->text_box);
|
||||||
|
furi_string_reset(nfc->text_box_store);
|
||||||
|
|
||||||
|
nfc_blink_stop(nfc);
|
||||||
|
}
|
||||||
@@ -885,6 +885,8 @@ static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
case NfcVTypeSlix2:
|
case NfcVTypeSlix2:
|
||||||
saved = nfc_device_save_slix2_data(file, dev);
|
saved = nfc_device_save_slix2_data(file, dev);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
@@ -936,6 +938,8 @@ bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
case NfcVTypeSlix2:
|
case NfcVTypeSlix2:
|
||||||
parsed = nfc_device_load_slix2_data(file, dev);
|
parsed = nfc_device_load_slix2_data(file, dev);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ int32_t nfc_worker_task(void* context) {
|
|||||||
nfc_worker_analyze_reader(nfc_worker);
|
nfc_worker_analyze_reader(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
|
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
|
||||||
nfc_worker_nfcv_emulate(nfc_worker);
|
nfc_worker_nfcv_emulate(nfc_worker);
|
||||||
|
} else if(nfc_worker->state == NfcWorkerStateNfcVSniff) {
|
||||||
|
nfc_worker_nfcv_sniff(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) {
|
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) {
|
||||||
nfc_worker_nfcv_unlock(nfc_worker);
|
nfc_worker_nfcv_unlock(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) {
|
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) {
|
||||||
@@ -180,6 +182,34 @@ void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker) {
|
||||||
|
FuriHalNfcTxRxContext tx_rx = {};
|
||||||
|
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
||||||
|
NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data;
|
||||||
|
|
||||||
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
|
reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true);
|
||||||
|
reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
nfcv_data->sub_type = NfcVTypeSniff;
|
||||||
|
nfcv_emu_init(nfc_data, nfcv_data);
|
||||||
|
|
||||||
|
while(nfc_worker->state == NfcWorkerStateNfcVSniff) {
|
||||||
|
if(nfcv_emu_loop(&tx_rx, nfc_data, nfcv_data, 100)) {
|
||||||
|
if(nfc_worker->callback) {
|
||||||
|
nfc_worker->callback(NfcWorkerEventNfcVCommandExecuted, nfc_worker->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
furi_delay_ms(10);
|
||||||
|
}
|
||||||
|
nfcv_emu_deinit(nfcv_data);
|
||||||
|
|
||||||
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
|
reader_analyzer_stop(nfc_worker->reader_analyzer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
||||||
furi_assert(nfc_worker);
|
furi_assert(nfc_worker);
|
||||||
furi_assert(nfc_worker->callback);
|
furi_assert(nfc_worker->callback);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ typedef enum {
|
|||||||
NfcWorkerStateNfcVEmulate,
|
NfcWorkerStateNfcVEmulate,
|
||||||
NfcWorkerStateNfcVUnlock,
|
NfcWorkerStateNfcVUnlock,
|
||||||
NfcWorkerStateNfcVUnlockAndSave,
|
NfcWorkerStateNfcVUnlockAndSave,
|
||||||
|
NfcWorkerStateNfcVSniff,
|
||||||
// Debug
|
// Debug
|
||||||
NfcWorkerStateEmulateApdu,
|
NfcWorkerStateEmulateApdu,
|
||||||
NfcWorkerStateField,
|
NfcWorkerStateField,
|
||||||
@@ -97,3 +98,4 @@ void nfc_worker_start(
|
|||||||
void nfc_worker_stop(NfcWorker* nfc_worker);
|
void nfc_worker_stop(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker);
|
void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker);
|
||||||
|
void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker);
|
||||||
@@ -732,6 +732,160 @@ void nfcv_emu_handle_packet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nfcv_emu_sniff_packet(
|
||||||
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
|
FuriHalNfcDevData* nfc_data,
|
||||||
|
void* nfcv_data_in) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
if(nfcv_data->frame_length < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the frame data for the upcoming part 3 handling */
|
||||||
|
ctx->flags = nfcv_data->frame[0];
|
||||||
|
ctx->command = nfcv_data->frame[1];
|
||||||
|
ctx->selected = (ctx->flags & RFAL_NFCV_REQ_FLAG_SELECT);
|
||||||
|
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);
|
||||||
|
|
||||||
|
char flags_string[5];
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
flags_string,
|
||||||
|
5,
|
||||||
|
"%c%c%c%d",
|
||||||
|
(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) ?
|
||||||
|
'I' :
|
||||||
|
(ctx->addressed ? 'A' : (ctx->selected ? 'S' : '*')),
|
||||||
|
ctx->advanced ? 'X' : ' ',
|
||||||
|
(ctx->flags & RFAL_NFCV_REQ_FLAG_DATA_RATE) ? 'h' : 'l',
|
||||||
|
(ctx->flags & RFAL_NFCV_REQ_FLAG_SUB_CARRIER) ? 2 : 1);
|
||||||
|
|
||||||
|
switch(ctx->command) {
|
||||||
|
case ISO15693_INVENTORY: {
|
||||||
|
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), "%s STAYQUIET", flags_string);
|
||||||
|
nfcv_data->quiet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_LOCKBLOCK: {
|
||||||
|
uint8_t block = nfcv_data->frame[ctx->payload_offset];
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s LOCK %d",
|
||||||
|
flags_string,
|
||||||
|
block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_SELECT: {
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command, sizeof(nfcv_data->last_command), "%s SELECT", flags_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_RESET_TO_READY: {
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command, sizeof(nfcv_data->last_command), "%s RESET", flags_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_READ_MULTI_BLOCK:
|
||||||
|
case ISO15693_READBLOCK: {
|
||||||
|
uint8_t block = nfcv_data->frame[ctx->payload_offset];
|
||||||
|
uint8_t blocks = 1;
|
||||||
|
|
||||||
|
if(ctx->command == ISO15693_READ_MULTI_BLOCK) {
|
||||||
|
blocks = nfcv_data->frame[ctx->payload_offset + 1] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s READ %d cnt: %d",
|
||||||
|
flags_string,
|
||||||
|
block,
|
||||||
|
blocks);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_WRITE_MULTI_BLOCK:
|
||||||
|
case ISO15693_WRITEBLOCK: {
|
||||||
|
uint8_t block = nfcv_data->frame[ctx->payload_offset];
|
||||||
|
uint8_t blocks = 1;
|
||||||
|
uint8_t data_pos = 1;
|
||||||
|
|
||||||
|
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||||
|
blocks = nfcv_data->frame[ctx->payload_offset + 1] + 1;
|
||||||
|
data_pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* data = &nfcv_data->frame[ctx->payload_offset + data_pos];
|
||||||
|
|
||||||
|
if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) {
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s WRITE %d, cnd %d",
|
||||||
|
flags_string,
|
||||||
|
block,
|
||||||
|
blocks);
|
||||||
|
} else {
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s WRITE %d %02X %02X %02X %02X",
|
||||||
|
flags_string,
|
||||||
|
block,
|
||||||
|
data[0],
|
||||||
|
data[1],
|
||||||
|
data[2],
|
||||||
|
data[3]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_GET_SYSTEM_INFO: {
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s SYSTEMINFO",
|
||||||
|
flags_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"%s unsupported: %02X",
|
||||||
|
flags_string,
|
||||||
|
ctx->command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(nfcv_data->last_command) > 0) {
|
||||||
|
FURI_LOG_D(TAG, "Received command %s", nfcv_data->last_command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||||
furi_assert(nfc_data);
|
furi_assert(nfc_data);
|
||||||
furi_assert(nfcv_data);
|
furi_assert(nfcv_data);
|
||||||
@@ -765,8 +919,12 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
|||||||
/* if not set already, initialize the default protocol handler */
|
/* if not set already, initialize the default protocol handler */
|
||||||
if(!nfcv_data->emu_protocol_ctx) {
|
if(!nfcv_data->emu_protocol_ctx) {
|
||||||
nfcv_data->emu_protocol_ctx = malloc(sizeof(NfcVEmuProtocolCtx));
|
nfcv_data->emu_protocol_ctx = malloc(sizeof(NfcVEmuProtocolCtx));
|
||||||
|
if(nfcv_data->sub_type == NfcVTypeSniff) {
|
||||||
|
nfcv_data->emu_protocol_handler = &nfcv_emu_sniff_packet;
|
||||||
|
} else {
|
||||||
nfcv_data->emu_protocol_handler = &nfcv_emu_handle_packet;
|
nfcv_data->emu_protocol_handler = &nfcv_emu_handle_packet;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Starting NfcV emulation");
|
FURI_LOG_D(TAG, "Starting NfcV emulation");
|
||||||
FURI_LOG_D(
|
FURI_LOG_D(
|
||||||
@@ -801,6 +959,9 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
|||||||
case NfcVTypePlain:
|
case NfcVTypePlain:
|
||||||
FURI_LOG_D(TAG, " Card type: Plain");
|
FURI_LOG_D(TAG, " Card type: Plain");
|
||||||
break;
|
break;
|
||||||
|
case NfcVTypeSniff:
|
||||||
|
FURI_LOG_D(TAG, " Card type: Sniffing");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a 512 edge buffer, more than enough */
|
/* allocate a 512 edge buffer, more than enough */
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ typedef enum {
|
|||||||
NfcVTypeSlixS = 2,
|
NfcVTypeSlixS = 2,
|
||||||
NfcVTypeSlixL = 3,
|
NfcVTypeSlixL = 3,
|
||||||
NfcVTypeSlix2 = 4,
|
NfcVTypeSlix2 = 4,
|
||||||
|
NfcVTypeSniff = 255,
|
||||||
} NfcVSubtype;
|
} NfcVSubtype;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user