diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index 76d8f8ef8..cff994baf 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -300,11 +300,6 @@ int32_t nfc_app(void* p) { } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); DOLPHIN_DEED(DolphinDeedNfcEmulate); - } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); - DOLPHIN_DEED(DolphinDeedNfcEmulate); - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); DOLPHIN_DEED(DolphinDeedNfcEmulate); diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 676e61b0c..a6475ca68 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -1,23 +1,11 @@ #include #include -#include #include #include -#include -#include -#include -#include -#include -#include #include #include - -#include -#include - - static void nfc_cli_print_usage() { printf("Usage:\r\n"); printf("nfc \r\n"); @@ -110,7 +98,6 @@ static void nfc_cli_field(Cli* cli, FuriString* args) { furi_hal_nfc_sleep(); } - static void nfc_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); FuriString* cmd; diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index ac6d7f928..0bebe35f3 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -12,13 +12,8 @@ ADD_SCENE(nfc, save_name, SaveName) ADD_SCENE(nfc, save_success, SaveSuccess) ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) -ADD_SCENE(nfc, emulate_nfcv, EmulateNfcV) ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess) ADD_SCENE(nfc, nfca_menu, NfcaMenu) -ADD_SCENE(nfc, nfcv_menu, NfcVMenu) -ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu) -ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput) -ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c deleted file mode 100644 index 0b09bb412..000000000 --- a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c +++ /dev/null @@ -1,147 +0,0 @@ -#include "../nfc_i.h" - -#define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (100) - -enum { - NfcSceneEmulateNfcVStateWidget, - NfcSceneEmulateNfcVStateTextBox, -}; - -bool nfc_emulate_nfcv_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - furi_assert(context); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); - return true; -} - -void nfc_scene_emulate_nfcv_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_emulate_nfcv_textbox_callback(void* context) { - furi_assert(context); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); -} - -// Add widget with device name or inform that data received -static void nfc_scene_emulate_nfcv_widget_config(Nfc* nfc, bool data_received) { - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; - 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, "Emulating NfcV"); - if(strcmp(nfc->dev->dev_name, "")) { - furi_string_printf(info_str, "%s", nfc->dev->dev_name); - } else { - for(uint8_t i = 0; i < data->uid_len; i++) { - furi_string_cat_printf(info_str, "%02X ", data->uid[i]); - } - } - 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_emulate_nfcv_widget_callback, nfc); - } -} - -void nfc_scene_emulate_nfcv_on_enter(void* context) { - Nfc* nfc = context; - - // Setup Widget - nfc_scene_emulate_nfcv_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); - furi_string_reset(nfc->text_box_store); - - // Set Widget state and view - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); - 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, - NfcWorkerStateNfcVEmulate, - &nfc->dev->dev_data, - nfc_emulate_nfcv_worker_callback, - nfc); - - nfc_blink_emulate_start(nfc); -} - -bool nfc_scene_emulate_nfcv_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, NfcSceneEmulateNfcV); - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - // Add data button to widget if data is received for the first time - if(!furi_string_size(nfc->text_box_store)) { - nfc_scene_emulate_nfcv_widget_config(nfc, true); - } - if(strlen(nfcv_data->last_command) > 0) { - /* 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 == GuiButtonTypeCenter && state == NfcSceneEmulateNfcVStateWidget) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateTextBox); - consumed = true; - } else if(event.event == NfcCustomEventViewExit && state == NfcSceneEmulateNfcVStateTextBox) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - if(state == NfcSceneEmulateNfcVStateTextBox) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); - consumed = true; - } - } - - return consumed; -} - -void nfc_scene_emulate_nfcv_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); -} diff --git a/applications/main/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index b3eae672f..fc6021d73 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -4,7 +4,6 @@ enum SubmenuIndex { SubmenuIndexReadCardType, SubmenuIndexMfClassicKeys, SubmenuIndexMfUltralightUnlock, - SubmenuIndexNfcVUnlock, }; void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) { @@ -35,12 +34,6 @@ void nfc_scene_extra_actions_on_enter(void* context) { SubmenuIndexMfUltralightUnlock, nfc_scene_extra_actions_submenu_callback, nfc); - submenu_add_item( - submenu, - "Unlock SLIX-L", - SubmenuIndexNfcVUnlock, - nfc_scene_extra_actions_submenu_callback, - nfc); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } @@ -63,9 +56,6 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType); consumed = true; - } else if(event.event == SubmenuIndexNfcVUnlock) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlockMenu); - consumed = true; } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event); } diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c index 6d5f7a1ca..fa73201d0 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -7,17 +7,6 @@ void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType typ } } -uint32_t nfc_scene_nfc_data_info_get_key(uint8_t *data) { - uint32_t value = 0; - - for(uint32_t pos = 0; pos < 4; pos++) { - value <<= 8; - value |= data[pos]; - } - - return value; -} - void nfc_scene_nfc_data_info_on_enter(void* context) { Nfc* nfc = context; Widget* widget = nfc->widget; @@ -25,8 +14,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { NfcDeviceData* dev_data = &nfc->dev->dev_data; NfcProtocol protocol = dev_data->protocol; uint8_t text_scroll_height = 0; - if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl) - || (protocol == NfcDeviceProtocolNfcV)) { + if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); text_scroll_height = 52; @@ -54,113 +42,19 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type)); } else if(protocol == NfcDeviceProtocolMifareDesfire) { furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); - } else if(protocol == NfcDeviceProtocolNfcV) { - switch (dev_data->nfcv_data.type) - { - case NfcVTypePlain: - furi_string_cat_printf(temp_str, "\e#ISO15693\n"); - break; - case NfcVTypeSlix: - furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX\n"); - break; - case NfcVTypeSlixS: - furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-S\n"); - break; - case NfcVTypeSlixL: - furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-L\n"); - break; - case NfcVTypeSlix2: - furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX2\n"); - break; - default: - furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); - break; - } } else { furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); } // Set tag iso data - if(protocol == NfcDeviceProtocolNfcV) { - NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data; - - furi_string_cat_printf(temp_str, "UID:\n"); - for(size_t i = 0; i < nfc_data->uid_len; i++) { - furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); - } - furi_string_cat_printf(temp_str, "\n"); - - furi_string_cat_printf(temp_str, "DSFID: %02X\n", nfcv_data->dsfid); - furi_string_cat_printf(temp_str, "AFI: %02X\n", nfcv_data->afi); - furi_string_cat_printf(temp_str, "IC Ref: %02X\n", nfcv_data->ic_ref); - furi_string_cat_printf(temp_str, "Blocks: %02X\n", nfcv_data->block_num); - furi_string_cat_printf(temp_str, "Blocksize: %02X\n", nfcv_data->block_size); - - furi_string_cat_printf(temp_str, "Data (%d byte)\n", nfcv_data->block_num * nfcv_data->block_size); - - int maxBlocks = nfcv_data->block_num; - if(maxBlocks > 32) { - maxBlocks = 32; - furi_string_cat_printf(temp_str, "(truncated to %d blocks)\n", maxBlocks); - } - - for(int block = 0; block < maxBlocks; block++) { - for(int pos = 0; pos < nfcv_data->block_size; pos++) { - furi_string_cat_printf(temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]); - } - furi_string_cat_printf(temp_str, "\n"); - } - furi_string_cat_printf(temp_str, "\n"); - - switch (dev_data->nfcv_data.type) - { - case NfcVTypePlain: - furi_string_cat_printf(temp_str, "Type: Plain\n"); - break; - case NfcVTypeSlix: - furi_string_cat_printf(temp_str, "Type: SLIX\n"); - furi_string_cat_printf(temp_str, "Keys:\n"); - furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas)); - break; - case NfcVTypeSlixS: - furi_string_cat_printf(temp_str, "Type: SLIX-S\n"); - furi_string_cat_printf(temp_str, "Keys:\n"); - furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_read)); - furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_write)); - furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_privacy)); - furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_destroy)); - furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_eas)); - break; - case NfcVTypeSlixL: - furi_string_cat_printf(temp_str, "Type: SLIX-L\n"); - furi_string_cat_printf(temp_str, "Keys:\n"); - furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_privacy)); - furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_destroy)); - furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_eas)); - break; - case NfcVTypeSlix2: - furi_string_cat_printf(temp_str, "Type: SLIX2\n"); - furi_string_cat_printf(temp_str, "Keys:\n"); - furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_read)); - furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_write)); - furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_privacy)); - furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_destroy)); - furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_eas)); - break; - default: - furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); - break; - } - } else { - char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; - furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); - furi_string_cat_printf(temp_str, "UID:"); - for(size_t i = 0; i < nfc_data->uid_len; i++) { - furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); - } - furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); - furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); + char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + furi_string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } + furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); // Set application specific data if(protocol == NfcDeviceProtocolMifareDesfire) { @@ -242,9 +136,6 @@ bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) { } else if(protocol == NfcDeviceProtocolMifareUl) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData); consumed = true; - } else if(protocol == NfcDeviceProtocolNfcV) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu); - consumed = true; } } } diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c b/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c deleted file mode 100644 index d0e223c15..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "../nfc_i.h" -#include - -void nfc_scene_nfcv_key_input_byte_input_callback(void* context) { - Nfc* nfc = context; - NfcVSlixLData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix_l; - - memcpy(data->key_privacy, nfc->byte_input_store, 4); - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); -} - -void nfc_scene_nfcv_key_input_on_enter(void* context) { - Nfc* nfc = context; - - // Setup view - ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter The Password In Hex"); - byte_input_set_result_callback( - byte_input, - nfc_scene_nfcv_key_input_byte_input_callback, - NULL, - nfc, - nfc->byte_input_store, - 4); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); -} - -bool nfc_scene_nfcv_key_input_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventByteInputDone) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlock); - DOLPHIN_DEED(DolphinDeedNfcRead); - consumed = true; - } - } - return consumed; -} - -void nfc_scene_nfcv_key_input_on_exit(void* context) { - Nfc* nfc = context; - - // Clear view - byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(nfc->byte_input, ""); -} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c deleted file mode 100644 index ee26baf69..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../nfc_i.h" -#include - -enum SubmenuIndex { - SubmenuIndexSave, - SubmenuIndexEmulate, -}; - -void nfc_scene_nfcv_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, index); -} - -void nfc_scene_nfcv_menu_on_enter(void* context) { - Nfc* nfc = context; - Submenu* submenu = nfc->submenu; - - submenu_add_item( - submenu, "Save", SubmenuIndexSave, nfc_scene_nfcv_menu_submenu_callback, nfc); - submenu_add_item( - submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_nfcv_menu_submenu_callback, nfc); - - submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVMenu)); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); -} - -bool nfc_scene_nfcv_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSave) { - nfc->dev->format = NfcDeviceSaveFormatNfcV; - // Clear device name - nfc_device_set_name(nfc->dev, ""); - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - consumed = true; - } else if(event.event == SubmenuIndexEmulate) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) { - DOLPHIN_DEED(DolphinDeedNfcAddEmulate); - } else { - DOLPHIN_DEED(DolphinDeedNfcEmulate); - } - consumed = true; - } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVMenu, event.event); - - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } - - return consumed; -} - -void nfc_scene_nfcv_menu_on_exit(void* context) { - Nfc* nfc = context; - - // Clear view - submenu_reset(nfc->submenu); -} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c deleted file mode 100644 index 96293a7c6..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "../nfc_i.h" -#include - -typedef enum { - NfcSceneNfcVUnlockStateIdle, - NfcSceneNfcVUnlockStateDetecting, - NfcSceneNfcVUnlockStateUnlocked, - NfcSceneNfcVUnlockStateAlreadyUnlocked, - NfcSceneNfcVUnlockStateNotSupportedCard, -} NfcSceneNfcVUnlockState; - -static bool nfc_scene_nfcv_unlock_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = context; - NfcVSlixLData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix_l; - - if(event == NfcWorkerEventNfcVPassKey) { - memcpy(data->key_privacy, nfc->byte_input_store, 4); - } else { - view_dispatcher_send_custom_event(nfc->view_dispatcher, event); - } - return true; -} - -void nfc_scene_nfcv_unlock_popup_callback(void* context) { - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); -} - -void nfc_scene_nfcv_unlock_set_state(Nfc* nfc, NfcSceneNfcVUnlockState state) { - FuriHalNfcDevData* nfc_data = &(nfc->dev->dev_data.nfc_data); - NfcVData* nfcv_data = &(nfc->dev->dev_data.nfcv_data); - - uint32_t curr_state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock); - if(curr_state != state) { - Popup* popup = nfc->popup; - if(state == NfcSceneNfcVUnlockStateDetecting) { - popup_reset(popup); - popup_set_text( - popup, "Put Tonie On\nFlipper's Back", 97, 24, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50); - } else if(state == NfcSceneNfcVUnlockStateUnlocked) { - popup_reset(popup); - - if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) { - nfc_text_store_set(nfc, "SLIX_%02X%02X%02X%02X%02X%02X%02X%02X", - nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], - nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - - nfc->dev->format = NfcDeviceSaveFormatNfcV; - - if(nfc_device_save(nfc->dev, nfc->text_store)) { - popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop); - } else { - popup_set_header(popup, "Unlocked but\nsave failed!", 94, 3, AlignCenter, AlignTop); - } - } else { - popup_set_header(popup, "Successfully\nunlocked", 94, 3, AlignCenter, AlignTop); - } - - notification_message(nfc->notifications, &sequence_single_vibro); - //notification_message(nfc->notifications, &sequence_success); - - popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); - popup_set_context(popup, nfc); - popup_set_callback(popup, nfc_scene_nfcv_unlock_popup_callback); - popup_set_timeout(popup, 1500); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - - } else if(state == NfcSceneNfcVUnlockStateAlreadyUnlocked) { - popup_reset(popup); - - popup_set_header(popup, "Already\nUnlocked!", 94, 3, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); - popup_set_context(popup, nfc); - popup_set_callback(popup, nfc_scene_nfcv_unlock_popup_callback); - popup_set_timeout(popup, 1500); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - } else if(state == NfcSceneNfcVUnlockStateNotSupportedCard) { - popup_reset(popup); - popup_set_header(popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop); - popup_set_text( - popup, - nfcv_data->error, - 4, - 22, - AlignLeft, - AlignTop); - popup_set_icon(popup, 73, 20, &I_DolphinCommon_56x48); - } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock, state); - } -} - -void nfc_scene_nfcv_unlock_on_enter(void* context) { - Nfc* nfc = context; - - nfc_device_clear(nfc->dev); - // Setup view - nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateDetecting); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - - // Start worker - nfc_worker_start( - nfc->worker, - NfcWorkerStateNfcVUnlockAndSave, - &nfc->dev->dev_data, - nfc_scene_nfcv_unlock_worker_callback, - nfc); - - nfc_blink_read_start(nfc); -} - -bool nfc_scene_nfcv_unlock_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcWorkerEventCardDetected) { - nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateUnlocked); - consumed = true; - } else if(event.event == NfcWorkerEventAborted) { - nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateAlreadyUnlocked); - consumed = true; - } else if(event.event == NfcWorkerEventNoCardDetected) { - nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateDetecting); - consumed = true; - } else if(event.event == NfcWorkerEventWrongCardDetected) { - nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateNotSupportedCard); - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneNfcVUnlockMenu); - } - return consumed; -} - -void nfc_scene_nfcv_unlock_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - // Clear view - popup_reset(nfc->popup); - nfc_blink_stop(nfc); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneNfcVUnlock, NfcSceneNfcVUnlockStateIdle); -} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c deleted file mode 100644 index afa19ee41..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "../nfc_i.h" -#include - -enum SubmenuIndex { - SubmenuIndexNfcVUnlockMenuManual, - SubmenuIndexNfcVUnlockMenuTonieBox, -}; - -void nfc_scene_nfcv_unlock_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, index); -} - -void nfc_scene_nfcv_unlock_menu_on_enter(void* context) { - Nfc* nfc = context; - Submenu* submenu = nfc->submenu; - - uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu); - submenu_add_item( - submenu, - "Enter PWD Manually", - SubmenuIndexNfcVUnlockMenuManual, - nfc_scene_nfcv_unlock_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, - "Auth As TonieBox", - SubmenuIndexNfcVUnlockMenuTonieBox, - nfc_scene_nfcv_unlock_menu_submenu_callback, - nfc); - submenu_set_selected_item(submenu, state); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); -} - -bool nfc_scene_nfcv_unlock_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexNfcVUnlockMenuManual) { - nfc->dev->dev_data.nfcv_data.auth_method = NfcVAuthMethodManual; - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVKeyInput); - consumed = true; - } else if(event.event == SubmenuIndexNfcVUnlockMenuTonieBox) { - nfc->dev->dev_data.nfcv_data.auth_method = NfcVAuthMethodTonieBox; - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlock); - DOLPHIN_DEED(DolphinDeedNfcRead); - consumed = true; - } - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneNfcVUnlockMenu, event.event); - } - return consumed; -} - -void nfc_scene_nfcv_unlock_menu_on_exit(void* context) { - Nfc* nfc = context; - - submenu_reset(nfc->submenu); -} diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index 4214d9b5e..7b877d645 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -68,11 +68,6 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; - } else if(event.event == NfcWorkerEventReadNfcV) { - notification_message(nfc->notifications, &sequence_success); - scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); - DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - consumed = true; } else if(event.event == NfcWorkerEventReadMfUltralight) { notification_message(nfc->notifications, &sequence_success); // Set unlock password input to 0xFFFFFFFF only on fresh read diff --git a/applications/main/nfc/scenes/nfc_scene_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c index 1c0e4fa85..e5128a52f 100644 --- a/applications/main/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -55,13 +55,6 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { &nfc->dev->dev_data, nfc_scene_rpc_emulate_callback, nfc); - } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { - nfc_worker_start( - nfc->worker, - NfcWorkerStateNfcVEmulate, - &nfc->dev->dev_data, - nfc_scene_rpc_emulate_callback, - nfc); } else { nfc_worker_start( nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_save_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c index 43f2246cd..bd7c9817e 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -34,9 +34,6 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcScenePassportAuth)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcScenePassportAuth); - } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneNfcDataInfo)) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneNfcDataInfo); } else { consumed = scene_manager_search_and_switch_to_another_scene( nfc->scene_manager, NfcSceneFileSelect); diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index 616dc0ef7..c0d3ed5c6 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -117,8 +117,6 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); - } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 4eb28720a..3924fb4ba 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -688,6 +688,7 @@ Function,-,coshl,long double,long double Function,-,cosl,long double,long double Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" +Function,-,crypto1_bit,uint8_t,"Crypto1*, uint8_t, int" Function,-,crypto1_byte,uint8_t,"Crypto1*, uint8_t, int" Function,-,crypto1_decrypt,void,"Crypto1*, uint8_t*, uint16_t, uint8_t*" Function,-,crypto1_encrypt,void,"Crypto1*, uint8_t*, uint8_t*, uint16_t, uint8_t*, uint8_t*" @@ -725,21 +726,13 @@ Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, u Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*" Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*" Function,-,difftime,double,"time_t, time_t" -Function,-,digital_sequence_add,void,"DigitalSequence*, uint8_t" -Function,-,digital_sequence_alloc,DigitalSequence*,"uint32_t, const GpioPin*" -Function,-,digital_sequence_clear,void,DigitalSequence* -Function,-,digital_sequence_free,void,DigitalSequence* -Function,-,digital_sequence_send,_Bool,DigitalSequence* -Function,-,digital_sequence_set_signal,void,"DigitalSequence*, uint8_t, DigitalSignal*" -Function,-,digital_signal_add,void,"DigitalSignal*, uint32_t" -Function,-,digital_signal_add_pulse,void,"DigitalSignal*, uint32_t, _Bool" Function,-,digital_signal_alloc,DigitalSignal*,uint32_t Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*" Function,-,digital_signal_free,void,DigitalSignal* Function,-,digital_signal_get_edge,uint32_t,"DigitalSignal*, uint32_t" Function,-,digital_signal_get_edges_cnt,uint32_t,DigitalSignal* Function,-,digital_signal_get_start_level,_Bool,DigitalSignal* -Function,-,digital_signal_prepare,void,DigitalSignal* +Function,-,digital_signal_prepare_arr,void,DigitalSignal* Function,-,digital_signal_send,void,"DigitalSignal*, const GpioPin*" Function,-,diprintf,int,"int, const char*, ..." Function,+,dir_walk_alloc,DirWalk*,Storage* @@ -1185,7 +1178,6 @@ Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t Function,+,furi_hal_nfc_exit_sleep,void, Function,+,furi_hal_nfc_field_off,void, Function,+,furi_hal_nfc_field_on,void, -Function,-,furi_hal_nfc_gen_bitstream,void,"FuriHalNfcTxRxContext*, uint8_t*, size_t" Function,-,furi_hal_nfc_init,void, Function,+,furi_hal_nfc_is_busy,_Bool, Function,+,furi_hal_nfc_is_init,_Bool, @@ -1209,7 +1201,6 @@ Function,+,furi_hal_nfc_stop,void, Function,+,furi_hal_nfc_stop_cmd,void, Function,+,furi_hal_nfc_tx_rx,_Bool,"FuriHalNfcTxRxContext*, uint16_t" Function,+,furi_hal_nfc_tx_rx_full,_Bool,FuriHalNfcTxRxContext* -Function,-,furi_hal_nfcv_listen_start,void, Function,-,furi_hal_os_init,void, Function,+,furi_hal_os_tick,void, Function,+,furi_hal_power_check_otg_status,void, @@ -2016,28 +2007,12 @@ Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" Function,+,nfc_device_set_name,void,"NfcDevice*, const char*" Function,+,nfc_file_select,_Bool,NfcDevice* -Function,-,nfc_util_bytes2num,uint64_t,"uint8_t*, uint8_t" -Function,-,nfc_util_even_parity32,uint8_t,uint32_t -Function,-,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*" -Function,-,nfc_util_odd_parity8,uint8_t,uint8_t Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" Function,-,nfca_signal_alloc,NfcaSignal*, Function,-,nfca_signal_encode,void,"NfcaSignal*, uint8_t*, uint16_t, uint8_t*" Function,-,nfca_signal_free,void,NfcaSignal* -Function,-,nfca_trans_rx_continue,void,NfcaTransRxState* -Function,-,nfca_trans_rx_deinit,void,NfcaTransRxState* -Function,-,nfca_trans_rx_init,void,NfcaTransRxState* -Function,-,nfca_trans_rx_loop,_Bool,"NfcaTransRxState*, uint32_t" -Function,-,nfca_trans_rx_pause,void,NfcaTransRxState* -Function,-,nfcv_emu_deinit,void, -Function,-,nfcv_emu_init,void,"FuriHalNfcDevData*, NfcVData*" -Function,-,nfcv_emu_loop,_Bool,"FuriHalNfcDevData*, NfcVData*, uint32_t" -Function,-,nfcv_inventory,ReturnCode,uint8_t* -Function,-,nfcv_read_blocks,ReturnCode,"NfcVReader*, NfcVData*" -Function,-,nfcv_read_card,_Bool,"NfcVReader*, FuriHalNfcDevData*, NfcVData*" -Function,-,nfcv_read_sysinfo,ReturnCode,"FuriHalNfcDevData*, NfcVData*" Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" @@ -2139,14 +2114,6 @@ Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, FuriString*, siz Function,+,protocol_dict_render_data,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" Function,-,pselect,int,"int, fd_set*, fd_set*, fd_set*, const timespec*, const sigset_t*" -Function,-,pulse_reader_alloc,PulseReader*,"const GpioPin*, uint32_t" -Function,-,pulse_reader_free,void,PulseReader* -Function,-,pulse_reader_receive,uint32_t,"PulseReader*, int" -Function,-,pulse_reader_samples,uint32_t,PulseReader* -Function,-,pulse_reader_set_bittime,void,"PulseReader*, uint32_t" -Function,-,pulse_reader_set_timebase,void,"PulseReader*, PulseReaderUnit" -Function,-,pulse_reader_start,void,PulseReader* -Function,-,pulse_reader_stop,void,PulseReader* Function,-,putc,int,"int, FILE*" Function,-,putc_unlocked,int,"int, FILE*" Function,-,putchar,int,int diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index e18fa3819..2d27313ae 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -367,39 +367,6 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) { st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); } -void furi_hal_nfcv_listen_start() { - - furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); - // Clear interrupts - st25r3916ClearInterrupts(); - // Mask all interrupts - st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); - // RESET - st25r3916ExecuteCommand(ST25R3916_CMD_STOP); - // Setup registers - st25r3916WriteRegister( - ST25R3916_REG_OP_CONTROL, - ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | - ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); - st25r3916WriteRegister( - ST25R3916_REG_MODE, - ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om0); - st25r3916WriteRegister( - ST25R3916_REG_PASSIVE_TARGET, - ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 | - ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); - st25r3916WriteRegister(ST25R3916_REG_MASK_RX_TIMER, 0x02); - - // Mask interrupts - uint32_t clear_irq_mask = - (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_A_X | - ST25R3916_IRQ_MASK_WU_A); - st25r3916EnableInterrupts(clear_irq_mask); - - // Go to sense - st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); -} - void rfal_interrupt_callback_handler() { furi_event_flag_set(event, EVENT_FLAG_INTERRUPT); } @@ -523,7 +490,6 @@ bool furi_hal_nfc_emulate_nfca( return true; } - static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx->nfca_signal); @@ -537,8 +503,9 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ // Send signal FURI_CRITICAL_ENTER(); nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); + digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi); FURI_CRITICAL_EXIT(); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); // Configure gpio back to SPI and exit transparent furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); @@ -602,94 +569,6 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ return ret; } -static bool furi_hal_nfc_fully_transparent_raw_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { - furi_assert(tx_rx); - - bool received = false; - - tx_rx->rx_bits = 0; - - if(tx_rx->tx_bits) { - nfca_trans_rx_pause(&tx_rx->nfca_trans_state); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - nfca_trans_rx_continue(&tx_rx->nfca_trans_state); - - if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); - } - } - - if(timeout_ms) { - tx_rx->nfca_trans_state.bits_received = 0; - received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms); - - if(received) { - if(tx_rx->nfca_trans_state.bits_received > 7) { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8; - for(size_t pos = 0; pos < tx_rx->rx_bits/8; pos++) { - tx_rx->rx_data[pos] = tx_rx->nfca_trans_state.frame_data[pos]; - } - } else { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received; - tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits); - } - - if(tx_rx->sniff_rx) { - tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); - } - } - } - - return received; -} - -static bool furi_hal_nfc_fully_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { - furi_assert(tx_rx); - - bool received = false; - - tx_rx->rx_bits = 0; - - if(tx_rx->tx_bits) { - nfca_trans_rx_pause(&tx_rx->nfca_trans_state); - FURI_CRITICAL_ENTER(); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - FURI_CRITICAL_EXIT(); - nfca_trans_rx_continue(&tx_rx->nfca_trans_state); - - if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); - } - } - - if(timeout_ms) { - tx_rx->nfca_trans_state.bits_received = 0; - received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms); - - if(received) { - if(tx_rx->nfca_trans_state.bits_received > 7) { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8; - memcpy(tx_rx->rx_data, tx_rx->nfca_trans_state.frame_data, tx_rx->nfca_trans_state.bits_received/9); - } else { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received; - tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits); - } - - if(tx_rx->sniff_rx) { - tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); - } - } - } - - return received; -} - - static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { uint32_t flags = 0; @@ -763,39 +642,9 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity( return curr_byte * 8; } -static uint8_t furi_hal_nfc_gen_parity(uint8_t value) { - value ^= (value >> 4); - value ^= (value >> 2); - value ^= (value >> 1); - - return (value ^ 1) & 1; -} - -void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len) { - for(size_t pos = 0; pos < len; pos++) { - uint32_t parity_bit_num = pos % 8; - uint8_t bit = furi_hal_nfc_gen_parity(buffer[pos]); - - tx_rx->tx_data[pos] = buffer[pos]; - tx_rx->tx_parity[pos / 8] &= ~(1 << (7 - parity_bit_num)); - tx_rx->tx_parity[pos / 8] |= bit << (7 - parity_bit_num); - } - tx_rx->tx_bits = len * 8; -} - bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx); - if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyRawTransparent) { - return furi_hal_nfc_fully_transparent_raw_tx_rx(tx_rx, timeout_ms); - } - if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) { - return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms); - } - if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { - return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); - } - ReturnCode ret; rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; uint8_t temp_tx_buff[FURI_HAL_NFC_DATA_BUFF_SIZE] = {}; @@ -803,7 +652,9 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { uint8_t* temp_rx_buff = NULL; uint16_t* temp_rx_bits = NULL; - //FURI_LOG_D(TAG, "furi_hal_nfc_tx_rx %u", tx_rx->tx_rx_type); + if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { + return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); + } // Prepare data for FIFO if necessary uint32_t flags = furi_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type); diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 12ce91523..d3f6de602 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -14,7 +14,6 @@ extern "C" { #endif #include #include -#include #define FURI_HAL_NFC_UID_MAX_LEN 10 #define FURI_HAL_NFC_DATA_BUFF_SIZE (512) @@ -47,8 +46,6 @@ typedef enum { FuriHalNfcTxRxTypeRaw, FuriHalNfcTxRxTypeRxRaw, FuriHalNfcTxRxTransparent, - FuriHalNfcTxRxFullyRawTransparent, - FuriHalNfcTxRxFullyTransparent } FuriHalNfcTxRxType; typedef bool (*FuriHalNfcEmulateCallback)( @@ -94,8 +91,6 @@ typedef struct { uint16_t rx_bits; FuriHalNfcTxRxType tx_rx_type; NfcaSignal* nfca_signal; - NfcaTransRxState nfca_trans_state; - bool nfca_trans_initialized; FuriHalNfcTxRxSniffCallback sniff_tx; FuriHalNfcTxRxSniffCallback sniff_rx; @@ -182,12 +177,6 @@ bool furi_hal_nfc_listen( */ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data); -/** Start Target Listen mode - * @note RFAL free implementation - * - */ -void furi_hal_nfcv_listen_start(); - /** Read data in Target Listen mode * @note Must be called only after furi_hal_nfc_listen_start() * @@ -430,9 +419,6 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( void furi_hal_nfc_ll_poll(); - -void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len); - #ifdef __cplusplus } #endif diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index c5ffbf454..31be7fff0 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -23,33 +23,18 @@ extern "C" { #define FURI_IS_ISR() (FURI_IS_IRQ_MODE() || FURI_IS_IRQ_MASKED()) #endif -#ifndef FURI_CRITICAL_DEFINE -#define FURI_CRITICAL_DEFINE() \ - uint32_t __isrm = 0; \ - bool __from_isr = false; \ - bool __kernel_running = false; -#endif - -#ifndef FURI_CRITICAL_ENTER_ADV -#define FURI_CRITICAL_ENTER_ADV() \ - do { \ - __isrm = 0; \ - __from_isr = FURI_IS_ISR(); \ - __kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); \ - if(__from_isr) { \ - __isrm = taskENTER_CRITICAL_FROM_ISR(); \ - } else if(__kernel_running) { \ - taskENTER_CRITICAL(); \ - } else { \ - __disable_irq(); \ - } \ - } while(0) -#endif - #ifndef FURI_CRITICAL_ENTER -#define FURI_CRITICAL_ENTER() \ - FURI_CRITICAL_DEFINE(); \ - FURI_CRITICAL_ENTER_ADV(); +#define FURI_CRITICAL_ENTER() \ + uint32_t __isrm = 0; \ + bool __from_isr = FURI_IS_ISR(); \ + bool __kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); \ + if(__from_isr) { \ + __isrm = taskENTER_CRITICAL_FROM_ISR(); \ + } else if(__kernel_running) { \ + taskENTER_CRITICAL(); \ + } else { \ + __disable_irq(); \ + } #endif #ifndef FURI_CRITICAL_EXIT diff --git a/lib/SConscript b/lib/SConscript index 27979bc5c..7cc0acf2d 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -4,7 +4,6 @@ env.Append( LINT_SOURCES=[ Dir("app-scened-template"), Dir("digital_signal"), - Dir("pulse_reader"), Dir("drivers"), Dir("flipper_format"), Dir("infrared"), diff --git a/lib/digital_signal/digital_signal.c b/lib/digital_signal/digital_signal.c index c7e8bbca5..46ca307a7 100644 --- a/lib/digital_signal/digital_signal.c +++ b/lib/digital_signal/digital_signal.c @@ -1,46 +1,23 @@ #include "digital_signal.h" #include -#include +#include +#include #include -#define TAG "DigitalSignal" - - -#define F_TIM (64000000.0) -#define T_TIM 1562 /* 15.625 ns *100 */ -#define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */ +#pragma GCC optimize("O3,unroll-loops,Ofast") +#define F_TIM (64000000.0) +#define T_TIM 1562 //15.625 ns *100 +#define T_TIM_DIV2 781 //15.625 ns / 2 *100 DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) { DigitalSignal* signal = malloc(sizeof(DigitalSignal)); signal->start_level = true; signal->edges_max_cnt = max_edges_cnt; - signal->edge_timings = malloc(signal->edges_max_cnt * sizeof(uint32_t)); + signal->edge_timings = malloc(max_edges_cnt * sizeof(uint32_t)); + signal->reload_reg_buff = malloc(max_edges_cnt * sizeof(uint32_t)); signal->edge_cnt = 0; - signal->reload_reg_buff = malloc(signal->edges_max_cnt * sizeof(uint32_t)); - signal->reload_reg_entries = 0; - signal->reload_reg_remainder = 0; - - signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; - signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_gpio.NbData = 2; - signal->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; - signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; - - signal->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) &(TIM2->ARR); - signal->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; - signal->dma_config_timer.Mode = LL_DMA_MODE_NORMAL; - signal->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; - signal->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH; return signal; } @@ -60,10 +37,7 @@ bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b) { if(signal_a->edges_max_cnt < signal_a->edge_cnt + signal_b->edge_cnt) { return false; } - /* in case there are no edges in our target signal, the signal to append makes the rules */ - if(!signal_a->edge_cnt) { - signal_a->start_level = signal_b->start_level; - } + bool end_level = signal_a->start_level; if(signal_a->edge_cnt) { end_level = signal_a->start_level ^ !(signal_a->edge_cnt % 2); @@ -98,32 +72,6 @@ uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal) { return signal->edge_cnt; } -void digital_signal_add(DigitalSignal* signal, uint32_t ticks) { - furi_assert(signal); - furi_assert(signal->edge_cnt < signal->edges_max_cnt); - - signal->edge_timings[signal->edge_cnt++] = ticks; -} - -void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level) { - furi_assert(signal); - furi_assert(signal->edge_cnt < signal->edges_max_cnt); - - /* virgin signal? add it as the only level */ - if(signal->edge_cnt == 0) { - signal->start_level = level; - signal->edge_timings[signal->edge_cnt++] = ticks; - } else { - bool end_level = signal->start_level ^ !(signal->edge_cnt % 2); - - if(level != end_level) { - signal->edge_timings[signal->edge_cnt++] = ticks; - } else { - signal->edge_timings[signal->edge_cnt - 1] += ticks; - } - } -} - uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) { furi_assert(signal); furi_assert(edge_num < signal->edge_cnt); @@ -131,76 +79,76 @@ uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) { return signal->edge_timings[edge_num]; } -void digital_signal_prepare(DigitalSignal* signal) { - furi_assert(signal); - furi_assert(signal->gpio); - furi_assert(signal->gpio->pin); - - /* set up signal polarities */ - uint32_t bit_set = signal->gpio->pin; - uint32_t bit_reset = signal->gpio->pin << 16; +void digital_signal_prepare_arr(DigitalSignal* signal) { + uint32_t t_signal_rest = signal->edge_timings[0]; + uint32_t r_count_tick_arr = 0; + uint32_t r_rest_div = 0; - if(signal->start_level) { - signal->gpio_buff[0] = bit_set; - signal->gpio_buff[1] = bit_reset; - } else { - signal->gpio_buff[0] = bit_reset; - signal->gpio_buff[1] = bit_set; - } + for(size_t i = 0; i < signal->edge_cnt - 1; i++) { + r_count_tick_arr = t_signal_rest / T_TIM; + r_rest_div = t_signal_rest % T_TIM; + t_signal_rest = signal->edge_timings[i + 1] + r_rest_div; - /* set up edge timings */ - signal->reload_reg_entries = 0; - - for(size_t pos = 0; pos < signal->edge_cnt; pos++) { - uint32_t pulse_duration = signal->edge_timings[pos] + signal->reload_reg_remainder; - uint32_t pulse_ticks = (pulse_duration + T_TIM_DIV2) / T_TIM; - signal->reload_reg_remainder = pulse_duration - (pulse_ticks * T_TIM); - - if(pulse_ticks > 1) { - signal->reload_reg_buff[signal->reload_reg_entries++] = pulse_ticks - 1; + if(r_rest_div < T_TIM_DIV2) { + signal->reload_reg_buff[i] = r_count_tick_arr - 1; + } else { + signal->reload_reg_buff[i] = r_count_tick_arr; + t_signal_rest -= T_TIM; } } } -static void digital_signal_stop_dma() { - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); - LL_DMA_ClearFlag_TC1(DMA1); - LL_DMA_ClearFlag_TC2(DMA1); -} - -static void digital_signal_stop_timer() { - LL_TIM_DisableCounter(TIM2); - LL_TIM_SetCounter(TIM2, 0); -} - -static bool digital_signal_setup_dma(DigitalSignal* signal) { +void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) { furi_assert(signal); + furi_assert(gpio); - if(!signal->reload_reg_entries) { - return false; + // Configure gpio as output + furi_hal_gpio_init(gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + + // Init gpio buffer and DMA channel + uint16_t gpio_reg = gpio->port->ODR; + uint16_t gpio_buff[2]; + if(signal->start_level) { + gpio_buff[0] = gpio_reg | gpio->pin; + gpio_buff[1] = gpio_reg & ~(gpio->pin); + } else { + gpio_buff[0] = gpio_reg & ~(gpio->pin); + gpio_buff[1] = gpio_reg | gpio->pin; } - - signal->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t) signal->gpio_buff; - signal->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) &(signal->gpio->port->BSRR); - signal->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff; - signal->dma_config_timer.NbData = signal->reload_reg_entries; - - /* set up DMA channel 1 and 2 for GPIO and timer copy operations */ - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &signal->dma_config_gpio); - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &signal->dma_config_timer); - - /* enable both DMA channels */ + LL_DMA_InitTypeDef dma_config = {}; + dma_config.MemoryOrM2MDstAddress = (uint32_t)gpio_buff; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->ODR); + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_CIRCULAR; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD; + dma_config.NbData = 2; + dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH; + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 2); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + + // Init timer arr register buffer and DMA channel + digital_signal_prepare_arr(signal); + dma_config.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR); + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + dma_config.NbData = signal->edge_cnt - 2; + dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + dma_config.Priority = LL_DMA_PRIORITY_HIGH; + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, signal->edge_cnt - 2); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); - return true; -} - -static void digital_signal_setup_timer() { - - digital_signal_stop_timer(); - + // Set up timer LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP); LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1); LL_TIM_SetPrescaler(TIM2, 0); @@ -208,267 +156,18 @@ static void digital_signal_setup_timer() { LL_TIM_SetCounter(TIM2, 0); LL_TIM_EnableUpdateEvent(TIM2); LL_TIM_EnableDMAReq_UPDATE(TIM2); -} -static void digital_signal_start_timer() { - LL_TIM_GenerateEvent_UPDATE(TIM2); + // Start transactions + LL_TIM_GenerateEvent_UPDATE(TIM2); // Do we really need it? LL_TIM_EnableCounter(TIM2); -} -void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) { - furi_assert(signal); - - if(!signal->edge_cnt) { - return; - } - - /* Configure gpio as output */ - signal->gpio = gpio; - furi_hal_gpio_init(signal->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - - /* single signal, add a temporary, terminating edge at the end */ - signal->edge_timings[signal->edge_cnt++] = 10; - digital_signal_prepare(signal); - - digital_signal_setup_dma(signal); - digital_signal_setup_timer(); - digital_signal_start_timer(); - - while(!LL_DMA_IsActiveFlag_TC2(DMA1)) { - } - - digital_signal_stop_timer(); - digital_signal_stop_dma(); - - signal->edge_cnt--; -} - -void digital_sequence_alloc_signals(DigitalSequence* sequence, uint32_t size) { - sequence->signals_size = size; - sequence->signals = malloc(sequence->signals_size * sizeof(DigitalSignal*)); - sequence->signals_prolonged = malloc(sequence->signals_size * sizeof(bool)); -} - -void digital_sequence_alloc_sequence(DigitalSequence* sequence, uint32_t size) { - sequence->sequence_used = 0; - sequence->sequence_size = size; - sequence->sequence = malloc(sequence->sequence_size); -} - -DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) { - - DigitalSequence* sequence = malloc(sizeof(DigitalSequence)); - - sequence->gpio = gpio; - sequence->bake = false; - - digital_sequence_alloc_signals(sequence, 32); - digital_sequence_alloc_sequence(sequence, size); - - return sequence; -} - -void digital_sequence_free(DigitalSequence* sequence) { - furi_assert(sequence); - - free(sequence->signals); - free(sequence->sequence); - free(sequence); -} - -void digital_sequence_set_signal(DigitalSequence* sequence, uint8_t signal_index, DigitalSignal* signal) { - furi_assert(sequence); - furi_assert(signal); - furi_assert(signal_index < sequence->signals_size); - - sequence->signals[signal_index] = signal; - signal->gpio = sequence->gpio; - signal->reload_reg_remainder = 0; - - digital_signal_prepare(signal); -} - -void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) { - furi_assert(sequence); - furi_assert(signal_index < sequence->signals_size); - - if(sequence->sequence_used >= sequence->sequence_size) { - sequence->sequence_size += 256; - sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); - } - - sequence->sequence[sequence->sequence_used++] = signal_index; -} - -void digital_signal_update_dma(DigitalSignal* signal) { - - volatile uint32_t dma1_data[] = { - /* R6 */ (uint32_t)&(DMA1_Channel1->CCR), - /* R7 */ DMA1_Channel1->CCR & ~DMA_CCR_EN, - /* R8 */ 2, - /* R9 */ (uint32_t)&(signal->gpio->port->BSRR), - /* R10 */ (uint32_t)signal->gpio_buff, - /* R11 */ DMA1_Channel1->CCR | DMA_CCR_EN }; - - volatile uint32_t dma2_data[] = { - /* R0 */ (uint32_t)&(DMA1_Channel2->CCR), - /* R1 */ DMA1_Channel2->CCR & ~DMA_CCR_EN, - /* R2 */ (uint32_t)signal->reload_reg_entries, - /* R3 */ (uint32_t)&(TIM2->ARR), - /* R4 */ (uint32_t)signal->reload_reg_buff, - /* R5 */ DMA1_Channel2->CCR | DMA_CCR_EN }; - - - /* hurry when setting up next transfer */ - asm volatile("\t" - "MOV r6, %[data1]\n\t" - "MOV r7, %[data2]\n\t" - - "PUSH {r0-r12}\n\t" - - "LDM r7, {r0-r5}\n\t" - "LDM r6, {r6-r11}\n\t" - - "loop:\n\t" - "LDR r12, [r0, #4]\n\t" - "CMP r12, #0\n\t" - "BNE loop\n\t" - - "STM r6, {r7-r10}\n\t" /* disable channel and set up new parameters */ - "STR r11, [r6, #0]\n\t" /* enable channel again */ - "STM r0, {r1-r4}\n\t" /* disable channel and set up new parameters */ - "STR r5, [r0, #0]\n\t" /* enable channel again */ - - "POP {r0-r12}\n\t" - - : /* no outputs*/ - : /* inputs */ - [data1] "r" (dma1_data), - [data2] "r" (dma2_data) - : "r6", "r7" ); - + while(!LL_DMA_IsActiveFlag_TC2(DMA1)) + ; LL_DMA_ClearFlag_TC1(DMA1); LL_DMA_ClearFlag_TC2(DMA1); -} - -static bool digital_sequence_send_signal(DigitalSignal* signal) { - furi_assert(signal); - - /* the first iteration has to set up the whole machinery */ - if(!LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1)) { - if(!digital_signal_setup_dma(signal)) { - FURI_LOG_D(TAG, "digital_sequence_send_signal: Signal has no entries, aborting"); - return false; - } - digital_signal_setup_timer(); - digital_signal_start_timer(); - } else { - /* configure next polarities and timings */ - digital_signal_update_dma(signal); - } - - return true; -} - -DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) { - - uint32_t edges = 0; - - for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) { - uint8_t signal_index = sequence->sequence[pos]; - DigitalSignal *sig = sequence->signals[signal_index]; - - edges += sig->edge_cnt; - } - - DigitalSignal* ret = digital_signal_alloc(edges); - - for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) { - uint8_t signal_index = sequence->sequence[pos]; - DigitalSignal *sig = sequence->signals[signal_index]; - - digital_signal_append(ret, sig); - } - - return ret; -} - -bool digital_sequence_send(DigitalSequence* sequence) { - furi_assert(sequence); - - furi_hal_gpio_init(sequence->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - - if(sequence->bake) { - DigitalSignal* sig = digital_sequence_bake(sequence); - - digital_signal_send(sig, sequence->gpio); - digital_signal_free(sig); - return true; - } - - int32_t remainder = 0; - FURI_CRITICAL_ENTER(); - - for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) { - uint8_t signal_index = sequence->sequence[pos]; - DigitalSignal *sig = sequence->signals[signal_index]; - - if(!sig) { - FURI_LOG_D(TAG, "digital_sequence_send: Signal at index %u, used at pos %lu is NULL, aborting", signal_index, pos); - break; - } - - /* when we are too late more than half a tick, make the first edge temporarily longer */ - bool needs_prolongation = false; - - if(remainder >= T_TIM_DIV2) { - remainder -= T_TIM; - needs_prolongation = true; - } - - /* update the total remainder */ - remainder += sig->reload_reg_remainder; - - /* do we need to update the prolongation? */ - if(needs_prolongation != sequence->signals_prolonged[signal_index]) { - if(needs_prolongation) { - sig->edge_timings[0]++; - } else { - sig->edge_timings[0]--; - } - sequence->signals_prolonged[signal_index] = needs_prolongation; - } - - bool success = digital_sequence_send_signal(sig); - - if(!success) { - break; - } - } - FURI_CRITICAL_EXIT(); - - while(LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2)) { - } - - digital_signal_stop_timer(); - digital_signal_stop_dma(); - - /* undo previously prolonged edges */ - for(uint32_t pos = 0; pos < sequence->signals_size; pos++) { - DigitalSignal *sig = sequence->signals[pos]; - - if(sig && sequence->signals_prolonged[pos]) { - sig->edge_timings[0]--; - sequence->signals_prolonged[pos] = false; - } - } - - return true; -} - -void digital_sequence_clear(DigitalSequence* sequence) { - furi_assert(sequence); - - sequence->sequence_used = 0; + LL_TIM_DisableCounter(TIM2); + LL_TIM_SetCounter(TIM2, 0); + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); } diff --git a/lib/digital_signal/digital_signal.h b/lib/digital_signal/digital_signal.h index 4d25b90c2..90905d74b 100644 --- a/lib/digital_signal/digital_signal.h +++ b/lib/digital_signal/digital_signal.h @@ -5,67 +5,35 @@ #include #include -#include -#include #ifdef __cplusplus extern "C" { #endif -/* helper for easier signal generation */ -#define DIGITAL_SIGNAL_MS(x) (x*100000000UL) -#define DIGITAL_SIGNAL_US(x) (x*100000UL) -#define DIGITAL_SIGNAL_NS(x) (x*100UL) -#define DIGITAL_SIGNAL_PS(x) (x/10UL) - - typedef struct { bool start_level; uint32_t edge_cnt; uint32_t edges_max_cnt; uint32_t* edge_timings; uint32_t* reload_reg_buff; - uint32_t reload_reg_entries; - uint32_t reload_reg_remainder; - uint32_t gpio_buff[2]; - const GpioPin* gpio; - LL_DMA_InitTypeDef dma_config_gpio; - LL_DMA_InitTypeDef dma_config_timer; } DigitalSignal; -typedef struct { - uint8_t signals_size; - bool bake; - uint32_t sequence_used; - uint32_t sequence_size; - DigitalSignal** signals; - bool* signals_prolonged; - uint8_t* sequence; - const GpioPin* gpio; -} DigitalSequence; - - DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt); + void digital_signal_free(DigitalSignal* signal); -void digital_signal_add(DigitalSignal* signal, uint32_t ticks); -void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level); + bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b); -void digital_signal_prepare(DigitalSignal* signal); + +void digital_signal_prepare_arr(DigitalSignal* signal); + bool digital_signal_get_start_level(DigitalSignal* signal); + uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal); + uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num); + void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio); - -DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio); -void digital_sequence_free(DigitalSequence* sequence); -void digital_sequence_set_signal(DigitalSequence* sequence, uint8_t signal_index, DigitalSignal* signal); -void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index); -bool digital_sequence_send(DigitalSequence* sequence); -void digital_sequence_clear(DigitalSequence* sequence); - - - #ifdef __cplusplus } #endif diff --git a/lib/misc.scons b/lib/misc.scons index 1f951000e..91ad276a0 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -3,7 +3,6 @@ Import("env") env.Append( CPPPATH=[ "#/lib/digital_signal", - "#/lib/pulse_reader", "#/lib/fnv1a_hash", "#/lib/heatshrink", "#/lib/micro-ecc", @@ -26,7 +25,6 @@ sources = [] libs_recurse = [ "digital_signal", - "pulse_reader", "micro-ecc", "one_wire", "u8g2", diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 67c0bc072..d80187b09 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -51,8 +51,6 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_ furi_string_set(format_string, "Mifare Classic"); } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { furi_string_set(format_string, "Mifare DESFire"); - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - furi_string_set(format_string, "ISO15693"); } else { furi_string_set(format_string, "Unknown"); } @@ -88,11 +86,6 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_st dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; return true; } - if(furi_string_start_with_str(format_string, "ISO15693")) { - dev->format = NfcDeviceSaveFormatNfcV; - dev->dev_data.protocol = NfcDeviceProtocolNfcV; - return true; - } return false; } @@ -650,258 +643,6 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { return parsed; } -static bool nfc_device_save_slix_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX specific data")) break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex( - file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix_s_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixSData* data = &dev->dev_data.nfcv_data.sub_data.slix_s; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX-S specific data")) break; - if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break; - if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break; - if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break; - if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixSData* data = &dev->dev_data.nfcv_data.sub_data.slix_s; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex( - file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_read_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex( - file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixLData* data = &dev->dev_data.nfcv_data.sub_data.slix_l; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break; - if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break; - if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixLData* data = &dev->dev_data.nfcv_data.sub_data.slix_l; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex( - file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix2_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlix2Data* data = &dev->dev_data.nfcv_data.sub_data.slix2; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX2 specific data")) break; - if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break; - if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break; - if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break; - if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlix2Data* data = &dev->dev_data.nfcv_data.sub_data.slix2; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex( - file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_read_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex( - file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVData* data = &dev->dev_data.nfcv_data; - - do { - uint32_t temp_uint32 = 0; - uint8_t temp_uint8 = 0; - - if(!flipper_format_write_comment_cstr(file, "Data Storage Format Identifier")) break; - if(!flipper_format_write_hex(file, "DSFID", &(data->dsfid), 1)) break; - if(!flipper_format_write_comment_cstr(file, "Application Family Identifier")) break; - if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break; - if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break; - temp_uint32 = data->block_num; - if(!flipper_format_write_comment_cstr(file, "Number of memory blocks, usually 0 to 256")) break; - if(!flipper_format_write_uint32(file, "Block Count", &temp_uint32, 1)) break; - if(!flipper_format_write_comment_cstr(file, "Size of a single memory block, usually 4")) break; - if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break; - if(!flipper_format_write_hex(file, "Data Content", data->data, data->block_num * data->block_size)) break; - if(!flipper_format_write_comment_cstr(file, "Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)")) break; - temp_uint8 = (uint8_t)data->type; - if(!flipper_format_write_hex(file, "Subtype", &temp_uint8, 1)) break; - - switch(data->type) { - case NfcVTypePlain: - if(!flipper_format_write_comment_cstr(file, "End of ISO15693 parameters")) break; - saved = true; - break; - case NfcVTypeSlix: - saved = nfc_device_save_slix_data(file, dev); - break; - case NfcVTypeSlixS: - saved = nfc_device_save_slix_s_data(file, dev); - break; - case NfcVTypeSlixL: - saved = nfc_device_save_slix_l_data(file, dev); - break; - case NfcVTypeSlix2: - saved = nfc_device_save_slix2_data(file, dev); - break; - } - } while(false); - - return saved; -} - -bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVData* data = &dev->dev_data.nfcv_data; - - memset(data, 0, sizeof(NfcVData)); - - do { - uint32_t temp_uint32 = 0; - uint8_t temp_value = 0; - - if(!flipper_format_read_hex(file, "DSFID", &(data->dsfid), 1)) break; - if(!flipper_format_read_hex(file, "AFI", &(data->afi), 1)) break; - if(!flipper_format_read_hex(file, "IC Reference", &(data->ic_ref), 1)) break; - if(!flipper_format_read_uint32(file, "Block Count", &temp_uint32, 1)) break; - data->block_num = temp_uint32; - if(!flipper_format_read_hex(file, "Block Size", &(data->block_size), 1)) break; - if(!flipper_format_read_hex( - file, "Data Content", data->data, data->block_num * data->block_size)) - break; - if(!flipper_format_read_hex(file, "Subtype", &temp_value, 1)) break; - data->type = temp_value; - - switch(data->type) { - case NfcVTypePlain: - parsed = true; - break; - case NfcVTypeSlix: - parsed = nfc_device_load_slix_data(file, dev); - break; - case NfcVTypeSlixS: - parsed = nfc_device_load_slix_s_data(file, dev); - break; - case NfcVTypeSlixL: - parsed = nfc_device_load_slix_l_data(file, dev); - break; - case NfcVTypeSlix2: - parsed = nfc_device_load_slix2_data(file, dev); - break; - } - } while(false); - - return parsed; -} - static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; EmvData* data = &dev->dev_data.emv_data; @@ -1320,29 +1061,21 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) { if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; // Write nfc device type if(!flipper_format_write_comment_cstr( - file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic or ISO15693")) + file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card")) break; nfc_device_prepare_format_string(dev, temp_str); if(!flipper_format_write_string(file, "Device type", temp_str)) break; - // Write UID - if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) + // Write UID, ATQA, SAK + if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats")) break; if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break; - - if(dev->format != NfcDeviceSaveFormatNfcV) { - // Write ATQA, SAK - if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) - break; - if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break; - if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; - } + if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break; + if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; // Save more data if necessary if(dev->format == NfcDeviceSaveFormatMifareUl) { if(!nfc_device_save_mifare_ul_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { if(!nfc_device_save_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - if(!nfc_device_save_nfcv_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { if(!nfc_device_save_bank_card_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { @@ -1413,13 +1146,11 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia if(!nfc_device_parse_format_string(dev, temp_str)) break; // Read and parse UID, ATQA and SAK if(!flipper_format_get_value_count(file, "UID", &data_cnt)) break; - if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break; + if(!(data_cnt == 4 || data_cnt == 7)) break; data->uid_len = data_cnt; if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; - if(dev->format != NfcDeviceSaveFormatNfcV) { - if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; - if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; - } + if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; + if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; // Load CUID uint8_t* cuid_start = data->uid; if(data->uid_len == 7) { @@ -1434,8 +1165,6 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia if(!nfc_device_load_mifare_classic_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { if(!nfc_device_load_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - if(!nfc_device_load_nfcv_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { if(!nfc_device_load_bank_card_data(file, dev)) break; } diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 5ad6c4761..f4726fe39 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -12,7 +12,6 @@ #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -35,7 +34,6 @@ typedef enum { NfcDeviceProtocolMifareUl, NfcDeviceProtocolMifareClassic, NfcDeviceProtocolMifareDesfire, - NfcDeviceProtocolNfcV } NfcProtocol; typedef enum { @@ -44,7 +42,6 @@ typedef enum { NfcDeviceSaveFormatMifareUl, NfcDeviceSaveFormatMifareClassic, NfcDeviceSaveFormatMifareDesfire, - NfcDeviceSaveFormatNfcV, } NfcDeviceSaveFormat; typedef struct { @@ -80,7 +77,6 @@ typedef struct { MfUltralightData mf_ul_data; MfClassicData mf_classic_data; MifareDesfireData mf_df_data; - NfcVData nfcv_data; }; FuriString* parsed_data; } NfcDeviceData; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index a1a85b8eb..3355385b4 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -6,7 +6,6 @@ #define TAG "NfcWorker" - /***************************** NFC Worker API *******************************/ NfcWorker* nfc_worker_alloc() { @@ -99,8 +98,6 @@ int32_t nfc_worker_task(void* context) { } } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { nfc_worker_emulate_uid(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - nfc_worker_emulate_nfcv(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { nfc_worker_emulate_apdu(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { @@ -117,10 +114,6 @@ int32_t nfc_worker_task(void* context) { nfc_worker_mf_classic_dict_attack(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { nfc_worker_analyze_reader(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) { - nfc_worker_nfcv_unlock(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { - nfc_worker_nfcv_unlock(nfc_worker); } furi_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); @@ -128,180 +121,6 @@ int32_t nfc_worker_task(void* context) { return 0; } -static bool nfc_worker_read_nfcv_content(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - bool read_success = false; - NfcVReader reader = {}; - - 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, false); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - do { - if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; - if(!nfcv_read_card(&reader, nfc_data, nfcv_data)) break; - - read_success = true; - } while(false); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } - - return read_success; -} - -void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - furi_assert(nfc_worker->callback); - - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - FuriHalNfcTxRxContext tx_rx = {}; - uint8_t *key_data = nfcv_data->sub_data.slix_l.key_privacy; - uint32_t key = 0; - - 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); - } - - furi_hal_nfc_sleep(); - - - while((nfc_worker->state == NfcWorkerStateNfcVUnlock) || - (nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave)) { - - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - if(furi_hal_nfc_ll_set_mode(FuriHalNfcModePollNfcv, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48) != FuriHalNfcReturnOk) { - break; - } - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCV_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCV_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCV); - - furi_hal_console_printf("Detect presence\r\n"); - ReturnCode ret = slix_l_get_random(nfcv_data); - - if(ret == ERR_NONE) { - /* there is some chip, responding with a RAND */ - nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV; - furi_hal_console_printf(" Chip detected. In privacy?\r\n"); - ret = nfcv_inventory(NULL); - - if(ret == ERR_NONE) { - /* chip is also visible, so no action required, just save */ - if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { - NfcVReader reader = {}; - - if(!nfcv_read_card(&reader, &nfc_worker->dev_data->nfc_data, nfcv_data)) { - furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n"); - snprintf(nfcv_data->error, sizeof(nfcv_data->error), "Read card\nfailed"); - nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); - } else { - furi_hal_console_printf(" => success, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - } - } else { - furi_hal_console_printf(" => success, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - } - - while(slix_l_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - - furi_hal_console_printf(" => chip is already visible, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); - while(slix_l_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - - key_data[0] = 0; - key_data[1] = 0; - key_data[2] = 0; - key_data[3] = 0; - - } else { - /* chip is invisible, try to unlock */ - furi_hal_console_printf(" chip is invisible, unlocking\r\n"); - - if(nfcv_data->auth_method == NfcVAuthMethodManual) { - - key |= key_data[0] << 24; - key |= key_data[1] << 16; - key |= key_data[2] << 8; - key |= key_data[3] << 0; - - ret = slix_l_unlock(nfcv_data, 4); - } else { - key = 0x7FFD6E5B; - key_data[0] = key >> 24; - key_data[1] = key >> 16; - key_data[2] = key >> 8; - key_data[3] = key >> 0; - ret = slix_l_unlock(nfcv_data, 4); - - if(ret != ERR_NONE) { - /* main key failed, trying second one */ - furi_hal_console_printf(" trying second key after resetting\r\n"); - - /* reset chip */ - furi_hal_nfc_ll_txrx_off(); - furi_delay_ms(20); - furi_hal_nfc_ll_txrx_on(); - - if(slix_l_get_random(nfcv_data) != ERR_NONE) { - furi_hal_console_printf(" reset failed\r\n"); - } - - key = 0x0F0F0F0F; - key_data[0] = key >> 24; - key_data[1] = key >> 16; - key_data[2] = key >> 8; - key_data[3] = key >> 0; - ret = slix_l_unlock(nfcv_data, 4); - } - } - if(ret != ERR_NONE) { - /* unlock failed */ - furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n"); - snprintf(nfcv_data->error, sizeof(nfcv_data->error), "Passwords not\naccepted"); - nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); - - /* reset chip */ - furi_hal_nfc_ll_txrx_off(); - furi_delay_ms(20); - furi_hal_nfc_ll_txrx_on(); - - /* wait for disappearing */ - while(slix_l_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - } - } - } else { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - } - - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); - furi_delay_ms(100); - } - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } -} - - - static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { bool read_success = false; MfUltralightReader reader = {}; @@ -598,20 +417,6 @@ static bool nfc_worker_read_nfcb(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t return card_read; } -static bool nfc_worker_read_nfcv(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - furi_assert(nfc_worker); - furi_assert(tx_rx); - - bool card_read = false; - furi_hal_nfc_sleep(); - - /* until here the UID field is reversed from the reader IC. - we will read it here again and it will get placed in the right order. */ - card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx); - - return card_read; -} - void nfc_worker_read(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -669,14 +474,7 @@ void nfc_worker_read(NfcWorker* nfc_worker) { event = NfcWorkerEventReadUidNfcF; break; } else if(nfc_data->type == FuriHalNfcTypeV) { - FURI_LOG_I(TAG, "NfcV detected"); - nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV; - if(nfc_worker_read_nfcv(nfc_worker, &tx_rx)) { - FURI_LOG_I(TAG, "nfc_worker_read_nfcv success"); - //event = NfcWorkerEventReadNfcV; - //break; - } - event = NfcWorkerEventReadNfcV; + event = NfcWorkerEventReadUidNfcV; break; } } else { @@ -794,22 +592,6 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { } } -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker) { - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - - nfcv_emu_init(nfc_data, nfcv_data); - while(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - if(nfcv_emu_loop(nfc_data, nfcv_data, 50)) { - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - furi_delay_ms(0); - } - nfcv_emu_deinit(); -} - void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData params = { @@ -1054,7 +836,6 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { } void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; MfClassicEmulator emulator = { @@ -1068,67 +849,11 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { rfal_platform_spi_acquire(); furi_hal_nfc_listen_start(nfc_data); - nfca_trans_rx_init(&tx_rx.nfca_trans_state); - - tx_rx.tx_rx_type = FuriHalNfcTxRxFullyTransparent; - - uint8_t tx_buffer_aticoll[32]; - memcpy(tx_buffer_aticoll, &nfc_data->uid, 4); - nfca_append_crc16(tx_buffer_aticoll, 4); - - uint8_t tx_buffer_ack[8]; - tx_buffer_ack[0] = nfc_data->sak; - nfca_append_crc16(tx_buffer_ack, 1); - while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { - tx_rx.tx_bits = 0; - tx_rx.rx_bits = 0; - if(furi_hal_nfc_tx_rx(&tx_rx, 300)) { - FURI_LOG_D(TAG, "Command: %02X", tx_rx.rx_data[0]); - - if(tx_rx.rx_bits == 7) { - switch(tx_rx.rx_data[0]) { - /* MAGIC WUPC1 */ - case 0x40: - continue; - - /* WUPA */ - case 0x52: - furi_hal_nfc_gen_bitstream(&tx_rx, nfc_data->atqa, 2); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - } - } - - if(tx_rx.rx_bits >= 16) { - switch(tx_rx.rx_data[0]) { - /* SELECT */ - case 0x93: - switch(tx_rx.rx_data[1]) { - /* ANTICOLL */ - case 0x20: - furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_aticoll, 6); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - - /* SELECT UID */ - case 0x70: - furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_ack, 3); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - } - break; - - /* HALS */ - case 0x50: - continue; - } - } - + if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { mf_classic_emulator(&emulator, &tx_rx); } } - if(emulator.data_changed) { nfc_worker->dev_data->mf_classic_data = emulator.data; if(nfc_worker->callback) { @@ -1137,12 +862,9 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { emulator.data_changed = false; } - nfca_trans_rx_deinit(&tx_rx.nfca_trans_state); + nfca_signal_free(nfca_signal); rfal_platform_spi_release(); - - - nfca_signal_free(nfca_signal); } void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index 60f993dd5..7d8264ef5 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -18,9 +18,6 @@ typedef enum { NfcWorkerStateReadMfUltralightReadAuth, NfcWorkerStateMfClassicDictAttack, NfcWorkerStateAnalyzeReader, - NfcWorkerStateNfcVEmulate, - NfcWorkerStateNfcVUnlock, - NfcWorkerStateNfcVUnlockAndSave, // Debug NfcWorkerStateEmulateApdu, NfcWorkerStateField, @@ -42,7 +39,6 @@ typedef enum { NfcWorkerEventReadMfClassicDone, NfcWorkerEventReadMfClassicLoadKeyCache, NfcWorkerEventReadMfClassicDictAttackRequired, - NfcWorkerEventReadNfcV, NfcWorkerEventReadBankCard, NfcWorkerEventReadPassport, @@ -72,7 +68,6 @@ typedef enum { // Mifare Ultralight events NfcWorkerEventMfUltralightPassKey, // NFC worker requesting manual key NfcWorkerEventMfUltralightPwdAuth, // Reader sent auth command - NfcWorkerEventNfcVPassKey, // NFC worker requesting manual key } NfcWorkerEvent; @@ -94,5 +89,3 @@ void nfc_worker_start( void* context); void nfc_worker_stop(NfcWorker* nfc_worker); -void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker); diff --git a/lib/nfc/nfc_worker_i.h b/lib/nfc/nfc_worker_i.h index a80a6011a..f827ae981 100644 --- a/lib/nfc/nfc_worker_i.h +++ b/lib/nfc/nfc_worker_i.h @@ -13,9 +13,6 @@ #include #include #include -#include -#include -#include #include struct NfcWorker { diff --git a/lib/nfc/protocols/crypto1.c b/lib/nfc/protocols/crypto1.c index 453b08a22..2ac0ff081 100644 --- a/lib/nfc/protocols/crypto1.c +++ b/lib/nfc/protocols/crypto1.c @@ -36,7 +36,7 @@ uint32_t crypto1_filter(uint32_t in) { return FURI_BIT(0xEC57E80A, out); } -static inline uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { furi_assert(crypto1); uint8_t out = crypto1_filter(crypto1->odd); uint32_t feed = out & (!!is_encrypted); @@ -58,15 +58,6 @@ uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) { return out; } -static inline uint8_t crypto1_byte_inline(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = 0; - for(uint8_t i = 0; i < 8; i++) { - out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i; - } - return out; -} - uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { furi_assert(crypto1); uint32_t out = 0; @@ -101,7 +92,7 @@ void crypto1_decrypt( decrypted_data[0] = decrypted_byte; } else { for(size_t i = 0; i < encrypted_data_bits / 8; i++) { - decrypted_data[i] = crypto1_byte_inline(crypto, 0, 0) ^ encrypted_data[i]; + decrypted_data[i] = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i]; } } } @@ -126,7 +117,7 @@ void crypto1_encrypt( } else { memset(encrypted_parity, 0, plain_data_bits / 8 + 1); for(uint8_t i = 0; i < plain_data_bits / 8; i++) { - encrypted_data[i] = crypto1_byte_inline(crypto, keystream ? keystream[i] : 0, 0) ^ + encrypted_data[i] = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^ plain_data[i]; encrypted_parity[i / 8] |= (((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_data[i])) & 0x01) diff --git a/lib/nfc/protocols/crypto1.h b/lib/nfc/protocols/crypto1.h index 5b1402549..450d1534e 100644 --- a/lib/nfc/protocols/crypto1.h +++ b/lib/nfc/protocols/crypto1.h @@ -12,7 +12,7 @@ void crypto1_reset(Crypto1* crypto1); void crypto1_init(Crypto1* crypto1, uint64_t key); -//uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted); diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index cf4e6be9b..b7a52bc01 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -763,39 +763,26 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ uint8_t plain_data[MF_CLASSIC_MAX_DATA_SIZE]; MfClassicKey access_key = MfClassicKeyA; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; - - FURI_LOG_D(TAG, "Starting mf_classic_emulator"); - // Read command while(!command_processed) { if(!is_encrypted) { crypto1_reset(&emulator->crypto); memcpy(plain_data, tx_rx->rx_data, tx_rx->rx_bits / 8); } else { - tx_rx->rx_bits = 0; if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { FURI_LOG_D( TAG, - "Error in tx rx. Tx :%d bits, Rx: %d bits. Received:", + "Error in tx rx. Tx :%d bits, Rx: %d bits", tx_rx->tx_bits, tx_rx->rx_bits); - - FURI_LOG_D(TAG,"Sent:"); - for(int pos = 0; pos < tx_rx->tx_bits/8; pos++) { - FURI_LOG_D(TAG," %02X", tx_rx->tx_data[pos]); - } - FURI_LOG_D(TAG,"Received:"); - for(int pos = 0; pos < tx_rx->rx_bits/8; pos++) { - FURI_LOG_D(TAG," %02X", tx_rx->rx_data[pos]); - } break; } crypto1_decrypt(&emulator->crypto, tx_rx->rx_data, tx_rx->rx_bits, plain_data); } if(plain_data[0] == 0x50 && plain_data[1] == 0x00) { - //furi_hal_nfc_listen_sleep(); + FURI_LOG_T(TAG, "Halt received"); + furi_hal_nfc_listen_sleep(); command_processed = true; break; } else if(plain_data[0] == 0x60 || plain_data[0] == 0x61) { @@ -812,7 +799,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ access_key = MfClassicKeyB; } - uint32_t nonce = prng_successor(DWT->CYCCNT, 2) ^ 0xAA; + uint32_t nonce = prng_successor(DWT->CYCCNT, 32) ^ 0xAA; uint8_t nt[4]; uint8_t nt_keystream[4]; nfc_util_num2bytes(nonce, 4, nt); @@ -820,15 +807,13 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ crypto1_init(&emulator->crypto, key); if(!is_encrypted) { crypto1_word(&emulator->crypto, emulator->cuid ^ nonce, 0); - for(size_t pos = 0; pos < sizeof(nt); pos++) { - tx_rx->tx_data[pos] = nt[pos]; - } + memcpy(tx_rx->tx_data, nt, sizeof(nt)); tx_rx->tx_parity[0] = 0; for(size_t i = 0; i < sizeof(nt); i++) { tx_rx->tx_parity[0] |= nfc_util_odd_parity8(nt[i]) << (7 - i); } tx_rx->tx_bits = sizeof(nt) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } else { crypto1_encrypt( &emulator->crypto, @@ -838,10 +823,10 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = sizeof(nt) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } if(!furi_hal_nfc_tx_rx(tx_rx, 500)) { - FURI_LOG_E(TAG, "Error in NT exchange?"); + FURI_LOG_E(TAG, "Error in NT exchange"); command_processed = true; break; } @@ -854,7 +839,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4); uint32_t ar = nfc_util_bytes2num(&tx_rx->rx_data[4], 4); -/* + FURI_LOG_D( TAG, "%08lx key%c block %d nt/nr/ar: %08lx %08lx %08lx", @@ -864,7 +849,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ nonce, nr, ar); -*/ + crypto1_word(&emulator->crypto, nr, 1); uint32_t cardRr = ar ^ crypto1_word(&emulator->crypto, 0, 0); if(cardRr != prng_successor(nonce, 64)) { @@ -885,7 +870,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = sizeof(responce) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; is_encrypted = true; } else if(is_encrypted && plain_data[0] == 0x30) { @@ -916,7 +901,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ } else { tx_rx->tx_data[0] = nack; } - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); break; @@ -932,7 +917,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = 18 * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } else if(is_encrypted && plain_data[0] == 0xA0) { uint8_t block = plain_data[1]; if(block > mf_classic_get_total_block_num(emulator->data.type)) { @@ -941,7 +926,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ // Send ACK uint8_t ack = 0x0A; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; @@ -976,10 +961,9 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ // Send ACK ack = 0x0A; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; } else { - FURI_LOG_T(TAG, "%02X unknown received", plain_data[0]); // Unknown command break; } @@ -993,7 +977,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ } else { tx_rx->tx_data[0] = nack; } - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); } diff --git a/lib/nfc/protocols/nfca.c b/lib/nfc/protocols/nfca.c index 328db012b..c401f8cc5 100644 --- a/lib/nfc/protocols/nfca.c +++ b/lib/nfc/protocols/nfca.c @@ -2,27 +2,19 @@ #include #include #include -#include -#include #define NFCA_CMD_RATS (0xE0U) #define NFCA_CRC_INIT (0x6363) -#define NFCA_F_SIG (13560000.0) /* [Hz] NFC frequency */ -#define NFCA_F_SUB (NFCA_F_SIG/16) /* [Hz] NFC subcarrier frequency fs/16 (847500 Hz) */ -#define T_SUB (1000000000000.0f / NFCA_F_SUB) /* [ps] subcarrier period = 1/NFCA_F_SUB (1.18 µs) */ -#define T_SUB_PHASE (T_SUB/2) /* [ps] a single subcarrier phase (590 µs) */ +#define NFCA_F_SIG (13560000.0) +#define T_SIG 7374 //73.746ns*100 +#define T_SIG_x8 58992 //T_SIG*8 +#define T_SIG_x8_x8 471936 //T_SIG*8*8 +#define T_SIG_x8_x9 530928 //T_SIG*8*9 #define NFCA_SIGNAL_MAX_EDGES (1350) -#define SEQ_SOF 0 -#define SEQ_BIT0 1 -#define SEQ_BIT1 2 -#define SEQ_EOF 3 -#define SEQ_IDLE 4 - - typedef struct { uint8_t cmd; uint8_t param; @@ -71,69 +63,46 @@ bool nfca_emulation_handler( return sleep; } +static void nfca_add_bit(DigitalSignal* signal, bool bit) { + if(bit) { + signal->start_level = true; + for(size_t i = 0; i < 7; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_timings[7] = T_SIG_x8_x9; + signal->edge_cnt = 8; + } else { + signal->start_level = false; + signal->edge_timings[0] = T_SIG_x8_x8; + for(size_t i = 1; i < 9; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_cnt = 9; + } +} + static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) { for(uint8_t i = 0; i < 8; i++) { if(byte & (1 << i)) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } if(parity) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); - } -} - -static void nfca_add_modulation(DigitalSignal* signal, size_t phases) { - for(size_t i = 0; i < phases; i++) { - signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(T_SUB_PHASE); - } -} - -static void nfca_add_silence(DigitalSignal* signal, size_t phases) { - bool end_level = signal->start_level ^ ((signal->edge_cnt % 2) == 0); - - if((signal->edge_cnt == 0) || end_level) { - signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE); - } else { - signal->edge_timings[signal->edge_cnt - 1] += DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } NfcaSignal* nfca_signal_alloc() { NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal)); - - /* ISO14443-2 defines 3 sequences for type A communication */ - nfca_signal->seq_d = digital_signal_alloc(10); - nfca_signal->seq_e = digital_signal_alloc(10); - nfca_signal->seq_f = digital_signal_alloc(10); - - /* SEQ D has the first half modulated, used as SOF */ - nfca_signal->seq_d->start_level = true; - nfca_add_modulation(nfca_signal->seq_d, 8); - nfca_add_silence(nfca_signal->seq_d, 8); - - /* SEQ E has the second half modulated */ - nfca_signal->seq_e->start_level = false; - nfca_add_silence(nfca_signal->seq_e, 8); - nfca_add_modulation(nfca_signal->seq_e, 8); - - /* SEQ F is just no modulation, used as EOF */ - nfca_signal->seq_f->start_level = false; - nfca_add_silence(nfca_signal->seq_f, 16); - - nfca_signal->tx_signal = digital_sequence_alloc(NFCA_SIGNAL_MAX_EDGES, &gpio_spi_r_mosi); - - /* we are dealing with shorter sequences, enable bake-before-sending */ - //nfca_signal->tx_signal->bake = true; - - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_SOF, nfca_signal->seq_d); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT0, nfca_signal->seq_e); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT1, nfca_signal->seq_d); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_EOF, nfca_signal->seq_f); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_IDLE, nfca_signal->seq_f); + nfca_signal->one = digital_signal_alloc(10); + nfca_signal->zero = digital_signal_alloc(10); + nfca_add_bit(nfca_signal->one, true); + nfca_add_bit(nfca_signal->zero, false); + nfca_signal->tx_signal = digital_signal_alloc(NFCA_SIGNAL_MAX_EDGES); return nfca_signal; } @@ -141,10 +110,9 @@ NfcaSignal* nfca_signal_alloc() { void nfca_signal_free(NfcaSignal* nfca_signal) { furi_assert(nfca_signal); - digital_signal_free(nfca_signal->seq_d); - digital_signal_free(nfca_signal->seq_e); - digital_signal_free(nfca_signal->seq_f); - digital_sequence_free(nfca_signal->tx_signal); + digital_signal_free(nfca_signal->one); + digital_signal_free(nfca_signal->zero); + digital_signal_free(nfca_signal->tx_signal); free(nfca_signal); } @@ -153,18 +121,17 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u furi_assert(data); furi_assert(parity); - digital_sequence_clear(nfca_signal->tx_signal); - - /* add some idle bit times before SOF in case the GPIO was active */ - digital_sequence_add(nfca_signal->tx_signal, SEQ_IDLE); - digital_sequence_add(nfca_signal->tx_signal, SEQ_SOF); + nfca_signal->tx_signal->edge_cnt = 0; + nfca_signal->tx_signal->start_level = true; + // Start of frame + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); if(bits < 8) { for(size_t i = 0; i < bits; i++) { if(FURI_BIT(data[0], i)) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } } else { @@ -172,6 +139,4 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07)))); } } - - digital_sequence_add(nfca_signal->tx_signal, SEQ_EOF); } diff --git a/lib/nfc/protocols/nfca.h b/lib/nfc/protocols/nfca.h index a4928a3eb..498ef2843 100644 --- a/lib/nfc/protocols/nfca.h +++ b/lib/nfc/protocols/nfca.h @@ -6,10 +6,9 @@ #include typedef struct { - DigitalSignal* seq_d; /* sequence D, modulation with subcarrier during first half */ - DigitalSignal* seq_e; /* sequence E, modulation with subcarrier during second half */ - DigitalSignal* seq_f; /* sequence F, no modulation at all */ - DigitalSequence* tx_signal; + DigitalSignal* one; + DigitalSignal* zero; + DigitalSignal* tx_signal; } NfcaSignal; uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len); @@ -27,4 +26,3 @@ NfcaSignal* nfca_signal_alloc(); void nfca_signal_free(NfcaSignal* nfca_signal); void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, uint8_t* parity); - diff --git a/lib/nfc/protocols/nfca_trans_rx.c b/lib/nfc/protocols/nfca_trans_rx.c deleted file mode 100644 index 3f8047272..000000000 --- a/lib/nfc/protocols/nfca_trans_rx.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfca_trans_rx.h" - -#define TAG "NfcA-trans-rx" - - -void nfca_trans_rx_init(NfcaTransRxState *state) { - FURI_LOG_D(TAG, "Starting NfcA transparent rx"); - - st25r3916ExecuteCommand(ST25R3916_CMD_STOP); - st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, 0xC3); - st25r3916WriteRegister(ST25R3916_REG_MODE, 0x88); - st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); - - furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); - - /* allocate a 512 edge buffer, more than enough */ - state->reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); - /* timebase shall be 1 ns */ - pulse_reader_set_timebase(state->reader_signal, PulseReaderUnitNanosecond); - - pulse_reader_start(state->reader_signal); - - /* set start values */ - state->bits_received = 0; - state->have_sof = false; - state->valid_frame = false; -} - -void nfca_trans_rx_deinit(NfcaTransRxState *state) { - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); - pulse_reader_free(state->reader_signal); -} - -void nfca_trans_rx_pause(NfcaTransRxState *state) { - pulse_reader_stop(state->reader_signal); -} - -void nfca_trans_rx_continue(NfcaTransRxState *state) { - pulse_reader_start(state->reader_signal); -} - -static void nfca_bit_received(NfcaTransRxState *state, uint8_t bit) { - - /* According to ISO14443-3 short frames have 7 bits and standard 9 bits per byte, - where the 9th bit is odd parity. Data is transmitted LSB first. */ - uint32_t byte_num = (state->bits_received / 9); - uint32_t bit_num = (state->bits_received % 9); - - if(byte_num >= NFCA_FRAME_LENGTH) { - return; - } - - if(bit_num == 8) { - uint32_t parity_value = 1 << (state->bits_received / 9); - state->parity_bits &= ~parity_value; - state->parity_bits |= bit ? parity_value : 0; - } else { - uint32_t bit_value = 1 << bit_num; - state->frame_data[byte_num] &= ~bit_value; - state->frame_data[byte_num] |= bit ? bit_value : 0; - } - - state->bits_received++; -} - - -bool nfca_trans_rx_loop(NfcaTransRxState *state, uint32_t timeout_ms) { - furi_assert(state); - - state->valid_frame = false; - state->have_sof = false; - state->bits_received = 0; - - bool done = false; - - uint32_t timeout_us = timeout_ms * 1000; - - while(!done) { - uint32_t nsec = pulse_reader_receive(state->reader_signal, timeout_us); - - bool eof = state->have_sof && (nsec >= (2 * NFCA_TB)); - bool lost_pulse = false; - - if(state->have_sof && nsec == PULSE_READER_LOST_EDGE) { - nsec = NFCA_T1; - lost_pulse = true; - } else if(nsec == PULSE_READER_NO_EDGE) { - done = true; - } - - if(IS_T1(nsec) || eof) { - timeout_us = (3 * NFCA_TB) / 1000; - if(!state->have_sof) { - state->frame_time = -(NFCA_TB - nsec); - state->have_sof = true; - state->valid_frame = false; - state->bits_received = 0; - state->debug_pos = 0; - if(lost_pulse) { - state->frame_time -= nsec; - } - continue; - } - - if(state->frame_time > NFCA_TB_MIN) { - state->frame_time -= NFCA_TB; - nfca_bit_received(state, 0); - } - - if(IS_ZERO(state->frame_time)) { - state->frame_time = -(NFCA_TB - nsec); - nfca_bit_received(state, 0); - } else if(IS_TX(state->frame_time)) { - state->frame_time = -(NFCA_TX - nsec); - nfca_bit_received(state, 1); - } else { - if(eof) { - state->have_sof = false; - state->valid_frame = true; - done = true; - } else { - } - } - } else { - if(!state->have_sof) { - if(IS_TB(nsec)) { - state->frame_time = 0; - state->have_sof = true; - state->valid_frame = false; - state->bits_received = 0; - state->debug_pos = 0; - if(lost_pulse) { - state->frame_time -= nsec; - } - continue; - } else { - state->frame_time = 0; - } - } else { - state->frame_time += nsec; - } - } - - if(lost_pulse) { - state->frame_time -= nsec; - } - } - - if(state->valid_frame) { - if(state->bits_received > 7) { - /* a last 0-bit will look like a missing bit */ - if((state->bits_received % 9) == 8) { - nfca_bit_received(state, 0); - state->bits_received++; - } - } - } - - return state->valid_frame; -} diff --git a/lib/nfc/protocols/nfca_trans_rx.h b/lib/nfc/protocols/nfca_trans_rx.h deleted file mode 100644 index d9c5f9513..000000000 --- a/lib/nfc/protocols/nfca_trans_rx.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -#include "nfc_util.h" - -/* assume fc/128 */ -#define NFCA_FC (13560000.0f) /* MHz */ -#define NFCA_FC_K ((uint32_t)(NFCA_FC/1000)) /* kHz */ -#define NFCA_T1 (28.0f / NFCA_FC * 1000000000) -#define NFCA_T1_MIN (24.0f / NFCA_FC * 1000000000) -#define NFCA_T1_MAX (41.0f / NFCA_FC * 1000000000) -#define NFCA_TX (64.0f / NFCA_FC * 1000000000) /* 4.7198 µs */ -#define NFCA_TX_MIN (0.90f * NFCA_TX) -#define NFCA_TX_MAX (1.10f * NFCA_TX) -#define NFCA_TB (128.0f / NFCA_FC * 1000000000) /* 9.4395 µs */ -#define NFCA_TB_MIN (0.80f * NFCA_TB) -#define NFCA_TB_MAX (1.20f * NFCA_TB) - -#define IS_T1(x) ((x)>=NFCA_T1_MIN && (x)<=NFCA_T1_MAX) -#define IS_TX(x) ((x)>=NFCA_TX_MIN && (x)<=NFCA_TX_MAX) -#define IS_TB(x) ((x)>=NFCA_TB_MIN && (x)<=NFCA_TB_MAX) -#define IS_ZERO(x) ((x)>=-NFCA_T1_MIN/2 && (x)<=NFCA_T1_MIN/2) - -#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f) -#define DIGITAL_SIGNAL_UNIT_US (100000.0f) - -#define NFCA_FRAME_LENGTH 32 -#define NFCA_DEBUG_LENGTH 128 - - -typedef struct { - bool have_sof; - bool valid_frame; - int32_t frame_time; - size_t bits_received; - uint8_t frame_data[NFCA_FRAME_LENGTH]; - uint32_t debug_buffer[NFCA_DEBUG_LENGTH]; - size_t debug_pos; - uint32_t parity_bits; - PulseReader *reader_signal; -} NfcaTransRxState; - -bool nfca_trans_rx_loop(NfcaTransRxState *state, uint32_t timeout_ms); -void nfca_trans_rx_deinit(NfcaTransRxState *state); -void nfca_trans_rx_init(NfcaTransRxState *state); - -void nfca_trans_rx_pause(NfcaTransRxState *state); -void nfca_trans_rx_continue(NfcaTransRxState *state); \ No newline at end of file diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c deleted file mode 100644 index ead20cba3..000000000 --- a/lib/nfc/protocols/nfcv.c +++ /dev/null @@ -1,747 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfcv.h" -#include "nfc_util.h" -#include "slix.h" - -#define TAG "NfcV" - -ReturnCode nfcv_inventory(uint8_t* uid) { - uint16_t received = 0; - rfalNfcvInventoryRes res; - ReturnCode ret = ERR_NONE; - - for(int tries = 0; tries < 5; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ - ret = rfalNfcvPollerInventory( - RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received); - - if(ret == ERR_NONE) { - break; - } - } - - if(ret == ERR_NONE) { - if(uid != NULL) { - memcpy(uid, res.UID, 8); - } - } - - return ret; -} - -ReturnCode nfcv_read_blocks( - NfcVReader* reader, - NfcVData* data) { - - UNUSED(reader); - - uint16_t received = 0; - for(size_t block = 0; block < data->block_num; block++) { - uint8_t rxBuf[32]; - FURI_LOG_D(TAG, "Reading block %d/%d", block, (data->block_num - 1)); - - ReturnCode ret = ERR_NONE; - for(int tries = 0; tries < 5; tries++) { - ret = rfalNfcvPollerReadSingleBlock( - RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block, - rxBuf, sizeof(rxBuf), &received); - - if(ret == ERR_NONE) { - break; - } - } - if(ret != ERR_NONE) { - FURI_LOG_D(TAG, "failed to read: %d", ret); - return ret; - } - memcpy(&(data->data[block * data->block_size]), &rxBuf[1], data->block_size); - FURI_LOG_D(TAG, " %02X %02X %02X %02X", - data->data[block * data->block_size + 0], data->data[block * data->block_size + 1], - data->data[block * data->block_size + 2], data->data[block * data->block_size + 3]); - } - - return ERR_NONE; -} - -ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) { - uint8_t rxBuf[32]; - uint16_t received = 0; - ReturnCode ret = ERR_NONE; - - FURI_LOG_D(TAG, "Read SYSTEM INFORMATION..."); - - for(int tries = 0; tries < 5; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ - ret = rfalNfcvPollerGetSystemInformation( - RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, rxBuf, sizeof(rxBuf), &received); - - if(ret == ERR_NONE) { - break; - } - } - - if(ret == ERR_NONE) { - nfc_data->type = FuriHalNfcTypeV; - nfc_data->uid_len = 8; - /* UID is stored reversed in this response */ - for(int pos = 0; pos < nfc_data->uid_len; pos++) { - nfc_data->uid[pos] = rxBuf[2 + (7 - pos)]; - } - data->dsfid = rxBuf[10]; - data->afi = rxBuf[11]; - data->block_num = rxBuf[12] + 1; - data->block_size = rxBuf[13] + 1; - data->ic_ref = rxBuf[14]; - FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X", - nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], - nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - FURI_LOG_D(TAG, " DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d", data->dsfid, data->afi, data->block_num, data->block_size, data->ic_ref); - return ret; - } - FURI_LOG_D(TAG, "Failed: %d", ret); - - return ret; -} - -bool nfcv_read_card( - NfcVReader* reader, - FuriHalNfcDevData* nfc_data, - NfcVData* nfcv_data) { - furi_assert(reader); - furi_assert(nfc_data); - furi_assert(nfcv_data); - - if(nfcv_read_sysinfo(nfc_data, nfcv_data) != ERR_NONE) { - return false; - } - - if(nfcv_read_blocks(reader, nfcv_data) != ERR_NONE) { - return false; - } - - if(slix_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX detected"); - nfcv_data->type = NfcVTypeSlix; - } else if(slix2_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX2 detected"); - nfcv_data->type = NfcVTypeSlix2; - } else if(slix_s_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX-S detected"); - nfcv_data->type = NfcVTypeSlixS; - } else if(slix_l_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX-L detected"); - nfcv_data->type = NfcVTypeSlixL; - } else { - nfcv_data->type = NfcVTypePlain; - } - - return true; -} - -/* emulation part */ -PulseReader *reader_signal = NULL; - -DigitalSignal* nfcv_resp_pulse_32 = NULL; -DigitalSignal* nfcv_resp_unmod = NULL; -DigitalSignal* nfcv_resp_one = NULL; -DigitalSignal* nfcv_resp_zero = NULL; -DigitalSignal* nfcv_resp_sof = NULL; -DigitalSignal* nfcv_resp_eof = NULL; -DigitalSignal* nfcv_resp_unmod_256 = NULL; -DigitalSignal* nfcv_resp_unmod_768 = NULL; - -//const GpioPin* nfcv_out_io = &gpio_ext_pb2; -const GpioPin* nfcv_out_io = &gpio_spi_r_mosi; - -DigitalSequence* nfcv_signal = NULL; - -#define SIG_SOF 0 -#define SIG_BIT0 1 -#define SIG_BIT1 2 -#define SIG_EOF 3 - - -void nfcv_crc(uint8_t* data, uint32_t length, uint8_t* out) { - uint32_t reg = 0xFFFF; - uint32_t i = 0; - uint32_t j = 0; - - for (i = 0; i < length; i++) { - reg = reg ^ ((uint32_t)data[i]); - for (j = 0; j < 8; j++) { - if (reg & 0x0001) { - reg = (reg >> 1) ^ 0x8408; - } else { - reg = (reg >> 1); - } - } - } - - uint16_t crc = ~(uint16_t)(reg & 0xffff); - - out[0] = crc & 0xFF; - out[1] = crc >> 8; -} - -void nfcv_emu_free() { - digital_sequence_free(nfcv_signal); - digital_signal_free(nfcv_resp_unmod_256); - digital_signal_free(nfcv_resp_pulse_32); - digital_signal_free(nfcv_resp_one); - digital_signal_free(nfcv_resp_zero); - digital_signal_free(nfcv_resp_sof); - digital_signal_free(nfcv_resp_eof); - - nfcv_signal = NULL; - nfcv_resp_unmod_256 = NULL; - nfcv_resp_pulse_32 = NULL; - nfcv_resp_one = NULL; - nfcv_resp_zero = NULL; - nfcv_resp_sof = NULL; - nfcv_resp_eof = NULL; -} - -void nfcv_emu_alloc() { - - if(!nfcv_signal) { - /* assuming max frame length is 255 bytes */ - nfcv_signal = digital_sequence_alloc(8 * 255 + 2, nfcv_out_io); - } - - if(!nfcv_resp_unmod_256) { - /* unmodulated 256/fc signal as building block */ - nfcv_resp_unmod_256 = digital_signal_alloc(4); - nfcv_resp_unmod_256->start_level = false; - nfcv_resp_unmod_256->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_unmod_256->edge_cnt = 1; - } - if(!nfcv_resp_pulse_32) { - /* modulated fc/32 pulse as building block */ - nfcv_resp_pulse_32 = digital_signal_alloc(4); - nfcv_resp_pulse_32->start_level = true; - nfcv_resp_pulse_32->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_pulse_32->edge_timings[1] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_pulse_32->edge_cnt = 2; - } - if(!nfcv_resp_one) { - /* logical one: 256/fc unmodulated then 8 pulses fc/32 */ - nfcv_resp_one = digital_signal_alloc(24); - digital_signal_append(nfcv_resp_one, nfcv_resp_unmod_256); - for(size_t i = 0; i < 8; i++) { - digital_signal_append(nfcv_resp_one, nfcv_resp_pulse_32); - } - } - if(!nfcv_resp_zero) { - /* logical zero: 8 pulses fc/32 then 256/fc unmodulated */ - nfcv_resp_zero = digital_signal_alloc(24); - for(size_t i = 0; i < 8; i++) { - digital_signal_append(nfcv_resp_zero, nfcv_resp_pulse_32); - } - digital_signal_append(nfcv_resp_zero, nfcv_resp_unmod_256); - } - if(!nfcv_resp_sof) { - /* SOF: unmodulated 768/fc, 24 pulses fc/32, logic 1 */ - nfcv_resp_sof = digital_signal_alloc(128); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); - for(size_t i = 0; i < 24; i++) { - digital_signal_append(nfcv_resp_sof, nfcv_resp_pulse_32); - } - digital_signal_append(nfcv_resp_sof, nfcv_resp_one); - } - if(!nfcv_resp_eof) { - /* EOF: logic 0, 24 pulses fc/32, unmodulated 768/fc */ - nfcv_resp_eof = digital_signal_alloc(128); - digital_signal_append(nfcv_resp_eof, nfcv_resp_zero); - for(size_t i = 0; i < 24; i++) { - digital_signal_append(nfcv_resp_eof, nfcv_resp_pulse_32); - } - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - /* add extra silence */ - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - } - - digital_sequence_set_signal(nfcv_signal, SIG_SOF, nfcv_resp_sof); - digital_sequence_set_signal(nfcv_signal, SIG_BIT0, nfcv_resp_zero); - digital_sequence_set_signal(nfcv_signal, SIG_BIT1, nfcv_resp_one); - digital_sequence_set_signal(nfcv_signal, SIG_EOF, nfcv_resp_eof); -} - - -void nfcv_emu_send_raw(uint8_t* data, uint8_t length) { - - digital_sequence_clear(nfcv_signal); - digital_sequence_add(nfcv_signal, SIG_SOF); - - for(int bit_total = 0; bit_total < length * 8; bit_total++) { - uint32_t byte_pos = bit_total / 8; - uint32_t bit_pos = bit_total % 8; - uint8_t bit_val = 0x01 << bit_pos; - - digital_sequence_add(nfcv_signal, (data[byte_pos] & bit_val) ? SIG_BIT1 : SIG_BIT0); - } - - digital_sequence_add(nfcv_signal, SIG_EOF); - - FURI_CRITICAL_ENTER(); - digital_sequence_send(nfcv_signal); - FURI_CRITICAL_EXIT(); - furi_hal_gpio_write(nfcv_out_io, false); -} - -void nfcv_emu_send(uint8_t* data, uint8_t length) { - uint8_t buffer[64]; - - if(length + 2 > (uint8_t)sizeof(buffer)) { - return; - } - - memcpy(buffer, data, length); - nfcv_crc(buffer, length, &buffer[length]); - nfcv_emu_send_raw(buffer, length + 2); -} - - -void nfcv_uidcpy(uint8_t *dst, uint8_t *src) { - for(int pos = 0; pos < 8; pos++) { - dst[pos] = src[7-pos]; - } -} - -int nfcv_uidcmp(uint8_t *dst, uint8_t *src) { - for(int pos = 0; pos < 8; pos++) { - if(dst[pos] != src[7-pos]) { - return 1; - } - } - return 0; -} - -uint32_t nfcv_read_le(uint8_t *data, uint32_t length) { - uint32_t value = 0; - - for(uint32_t pos = 0; pos < length; pos++) { - value |= data[pos] << ((int)pos * 8); - } - - return value; -} - -uint32_t nfcv_read_be(uint8_t *data, uint32_t length) { - uint32_t value = 0; - - for(uint32_t pos = 0; pos < length; pos++) { - value <<= 8; - value |= data[pos]; - } - - return value; -} - -void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint8_t* payload, uint32_t payload_length) { - - if(!payload_length) { - return; - } - - uint8_t flags = payload[0]; - uint8_t command = payload[1]; - bool addressed = !(flags & RFAL_NFCV_REQ_FLAG_INVENTORY) && (flags & RFAL_NFCV_REQ_FLAG_ADDRESS); - bool advanced = (command >= 0xA0); - uint8_t address_offset = 2 + (advanced ? 1 : 0); - uint8_t payload_offset = address_offset + (addressed ? 8 : 0); - uint8_t *address = &payload[address_offset]; - - if(addressed && nfcv_uidcmp(address, nfc_data->uid)) { - FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", command); - FURI_LOG_D(TAG, " dest: %02X%02X%02X%02X%02X%02X%02X%02X", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]); - FURI_LOG_D(TAG, " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - return; - } - - uint8_t response_buffer[32]; - - switch(nfcv_data->type) { - case NfcVTypeSlixL: - if(nfcv_data->sub_data.slix_l.privacy && - command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER && - command != ISO15693_CMD_NXP_SET_PASSWORD) { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "command 0x%02X ignored, privacy mode", command); - FURI_LOG_D(TAG, "%s", nfcv_data->last_command); - return; - } - break; - - default: - break; - } - - /* unfortunately the response is quicker than the original NFC tag which causes frame misses */ - furi_delay_us(270); - - switch(command) { - - case ISO15693_INVENTORY: - { - response_buffer[0] = ISO15693_NOERROR; - response_buffer[1] = nfcv_data->dsfid; - nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - - nfcv_emu_send(response_buffer, 10); - 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), "STAYQUIET"); - break; - } - - case ISO15693_LOCKBLOCK: - { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK"); - break; - } - - case ISO15693_READ_MULTI_BLOCK: - { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ_MULTI_BLOCK"); - break; - } - - case ISO15693_WRITE_MULTI_BLOCK: - { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_MULTI_BLOCK"); - break; - } - - case ISO15693_SELECT: - { - response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(response_buffer, 1); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); - break; - } - - case ISO15693_READBLOCK: - { - uint8_t block = payload[payload_offset]; - - if(block >= nfcv_data->block_num) { - response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - nfcv_emu_send(response_buffer, 1); - } else { - response_buffer[0] = ISO15693_NOERROR; - memcpy(&response_buffer[1], &nfcv_data->data[nfcv_data->block_size * block], nfcv_data->block_size); - nfcv_emu_send(response_buffer, 1 + nfcv_data->block_size); - } - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block); - break; - } - - case ISO15693_WRITEBLOCK: - { - uint8_t block = payload[payload_offset]; - uint8_t *data = &payload[payload_offset + 1]; - - if(block >= nfcv_data->block_num) { - response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - } else { - response_buffer[0] = ISO15693_NOERROR; - memcpy(&nfcv_data->data[nfcv_data->block_size * block], &response_buffer[1], nfcv_data->block_size); - } - nfcv_emu_send(response_buffer, 1); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE BLOCK %d <- %02X %02X %02X %02X", block, data[0], data[1], data[2], data[3]); - break; - } - - case ISO15693_GET_SYSTEM_INFO: - { - response_buffer[0] = ISO15693_NOERROR; - response_buffer[1] = 0x0F; - nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - response_buffer[10] = nfcv_data->dsfid; /* DSFID */ - response_buffer[11] = nfcv_data->afi; /* AFI */ - response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */ - response_buffer[13] = nfcv_data->block_size - 1; /* block size */ - response_buffer[14] = nfcv_data->ic_ref; /* IC reference */ - - nfcv_emu_send(response_buffer, 15); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO"); - - break; - } - - case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: - { - nfcv_data->sub_data.slix_l.rand[0] = furi_hal_random_get(); - nfcv_data->sub_data.slix_l.rand[1] = furi_hal_random_get(); - - response_buffer[0] = ISO15693_NOERROR; - response_buffer[1] = nfcv_data->sub_data.slix_l.rand[1]; - response_buffer[2] = nfcv_data->sub_data.slix_l.rand[0]; - - nfcv_emu_send(response_buffer, 3); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), - "GET_RANDOM_NUMBER -> 0x%02X%02X", - nfcv_data->sub_data.slix_l.rand[0], - nfcv_data->sub_data.slix_l.rand[1]); - break; - } - - case ISO15693_CMD_NXP_SET_PASSWORD: - { - uint8_t password_id = payload[payload_offset]; - uint8_t *password_xored = &payload[payload_offset + 1]; - uint8_t *rand = nfcv_data->sub_data.slix_l.rand; - uint8_t *password = NULL; - uint8_t password_rcv[4]; - - switch(password_id) { - case 4: - password = nfcv_data->sub_data.slix_l.key_privacy; - break; - case 8: - password = nfcv_data->sub_data.slix_l.key_destroy; - break; - case 10: - password = nfcv_data->sub_data.slix_l.key_eas; - break; - default: - break; - } - - for(int pos = 0; pos < 4; pos++) { - password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2]; - } - uint32_t pass_expect = nfcv_read_be(password, 4); - uint32_t pass_received = nfcv_read_be(password_rcv, 4); - - if(pass_expect == pass_received) { - nfcv_data->sub_data.slix_l.privacy = false; - response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(response_buffer, 1); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX OK", password_id, pass_received); - } else { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", password_id, pass_received, pass_expect); - } - break; - } - - case ISO15693_CMD_NXP_ENABLE_PRIVACY: - { - response_buffer[0] = ISO15693_NOERROR; - - nfcv_emu_send(response_buffer, 1); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY"); - - nfcv_data->sub_data.slix_l.privacy = true; - break; - } - - default: - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "unsupported: %02X", 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) { - nfcv_emu_alloc(); - rfal_platform_spi_acquire(); - - st25r3916ExecuteCommand(ST25R3916_CMD_STOP); - st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, 0xC3); - st25r3916WriteRegister(ST25R3916_REG_MODE, 0x88); - st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); - - furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); - - FURI_LOG_D(TAG, "Starting NfcV emulation"); - FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X", - nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], - nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - FURI_LOG_D(TAG, " Card type: %d", nfcv_data->type); - FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_privacy, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix_l.privacy ? "ON" : "OFF"); - - /* allocate a 512 edge buffer, more than enough */ - reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); - /* timebase shall be 1 ns */ - pulse_reader_set_timebase(reader_signal, PulseReaderUnitNanosecond); - /* and configure to already calculate the number of bits */ - pulse_reader_set_bittime(reader_signal, PULSE_DURATION_NS); - pulse_reader_start(reader_signal); -} - -void nfcv_emu_deinit() { - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); - rfal_platform_spi_release(); - nfcv_emu_free(); - - pulse_reader_free(reader_signal); -} - -bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms) { - - bool ret = false; - uint32_t frame_state = NFCV_FRAME_STATE_SOF1; - uint32_t periods_previous = 0; - uint8_t frame_payload[128]; - uint32_t frame_pos = 0; - uint32_t byte_value = 0; - uint32_t bits_received = 0; - char reset_reason[128]; - bool wait_for_pulse = false; - - while(true) { - - uint32_t periods = pulse_reader_receive(reader_signal, timeout_ms * 1000); - - if(periods == PULSE_READER_NO_EDGE) { - break; - } - - if(wait_for_pulse) { - wait_for_pulse = false; - if(periods != 1) { - snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected a single low pulse in state %lu, but got %lu", frame_state, periods); - frame_state = NFCV_FRAME_STATE_RESET; - } - continue; - } - - switch(frame_state) { - case NFCV_FRAME_STATE_SOF1: - if(periods == 1) { - frame_state = NFCV_FRAME_STATE_SOF2; - } else { - frame_state = NFCV_FRAME_STATE_SOF1; - break; - } - break; - - case NFCV_FRAME_STATE_SOF2: - /* waiting for the second low period, telling us about coding */ - if(periods == 6) { - frame_state = NFCV_FRAME_STATE_CODING_256; - periods_previous = 0; - wait_for_pulse = true; - } else if(periods == 4) { - frame_state = NFCV_FRAME_STATE_CODING_4; - periods_previous = 2; - wait_for_pulse = true; - } else { - snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected 4/6 periods, got %lu", periods); - frame_state = NFCV_FRAME_STATE_SOF1; - } - break; - - case NFCV_FRAME_STATE_CODING_256: - if(periods_previous > periods) { - snprintf(reset_reason, sizeof(reset_reason), "1oo256: Missing %lu periods from previous symbol, got %lu", periods_previous, periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - - if(periods > 512) { - snprintf(reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - if(periods == 2) { - frame_state = NFCV_FRAME_STATE_EOF; - break; - } - - periods_previous = 512 - (periods + 1); - byte_value = (periods - 1) / 2; - frame_payload[frame_pos++] = (uint8_t)byte_value; - - wait_for_pulse = true; - - break; - - case NFCV_FRAME_STATE_CODING_4: - if(periods_previous > periods) { - snprintf(reset_reason, sizeof(reset_reason), "1oo4: Missing %lu periods from previous symbol, got %lu", periods_previous, periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - periods_previous = 0; - - byte_value >>= 2; - bits_received += 2; - - if(periods == 1) { - byte_value |= 0x00 << 6; - periods_previous = 6; - } else if(periods == 3) { - byte_value |= 0x01 << 6; - periods_previous = 4; - } else if(periods == 5) { - byte_value |= 0x02 << 6; - periods_previous = 2; - } else if(periods == 7) { - byte_value |= 0x03 << 6; - periods_previous = 0; - } else if(periods == 2) { - frame_state = NFCV_FRAME_STATE_EOF; - break; - } else { - snprintf(reset_reason, sizeof(reset_reason), "1oo4: Expected 1/3/5/7 low pulses, but got %lu", periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - if(bits_received >= 8) { - frame_payload[frame_pos++] = (uint8_t)byte_value; - bits_received = 0; - } - wait_for_pulse = true; - break; - } - - /* post-state-machine cleanup and reset */ - if(frame_state == NFCV_FRAME_STATE_RESET) { - frame_state = NFCV_FRAME_STATE_SOF1; - - FURI_LOG_D(TAG, "Resetting state machine, reason: '%s'", reset_reason); - } else if(frame_state == NFCV_FRAME_STATE_EOF) { - break; - } - } - - if(frame_state == NFCV_FRAME_STATE_EOF) { - /* we know that this code uses TIM2, so stop pulse reader */ - pulse_reader_stop(reader_signal); - nfcv_emu_handle_packet(nfc_data, nfcv_data, frame_payload, frame_pos); - pulse_reader_start(reader_signal); - ret = true; - } - - return ret; -} diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h deleted file mode 100644 index 6253fa1a6..000000000 --- a/lib/nfc/protocols/nfcv.h +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include "nfc_util.h" -#include - - - - -#define NFCV_FC (13560000.0f) /* MHz */ -#define NFCV_RESP_SUBC1_PULSE_32 (1.0f / (NFCV_FC/32) / 2.0f) /* 1.1799 µs */ -#define NFCV_RESP_SUBC1_UNMOD_256 (256.0f / NFCV_FC) /* 18.8791 µs */ - -#define PULSE_DURATION_NS (128.0f * 1000000000.0f / NFCV_FC) /* ns */ - -#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f) -#define DIGITAL_SIGNAL_UNIT_US (100000.0f) - -#define NFCV_TOTAL_BLOCKS_MAX 256 -#define NFCV_BLOCK_SIZE 4 -#define NFCV_MAX_DUMP_SIZE (NFCV_BLOCK_SIZE*NFCV_TOTAL_BLOCKS_MAX) - - -#define NFCV_FRAME_STATE_SOF1 0 -#define NFCV_FRAME_STATE_SOF2 1 -#define NFCV_FRAME_STATE_CODING_4 2 -#define NFCV_FRAME_STATE_CODING_256 3 -#define NFCV_FRAME_STATE_EOF 4 -#define NFCV_FRAME_STATE_RESET 5 - -/* */ -#define ISO15693_INVENTORY 0x01 -#define ISO15693_STAYQUIET 0x02 -#define ISO15693_READBLOCK 0x20 -#define ISO15693_WRITEBLOCK 0x21 -#define ISO15693_LOCKBLOCK 0x22 -#define ISO15693_READ_MULTI_BLOCK 0x23 -#define ISO15693_WRITE_MULTI_BLOCK 0x24 -#define ISO15693_SELECT 0x25 -#define ISO15693_RESET_TO_READY 0x26 -#define ISO15693_WRITE_AFI 0x27 -#define ISO15693_LOCK_AFI 0x28 -#define ISO15693_WRITE_DSFID 0x29 -#define ISO15693_LOCK_DSFID 0x2A -#define ISO15693_GET_SYSTEM_INFO 0x2B -#define ISO15693_READ_MULTI_SECSTATUS 0x2C - -// ISO15693 MANUFACTURER CODES -#define ISO15693_MANUFACTURER_NXP 0x04 - -// ISO15693-3 CUSTOM NXP COMMANDS -#define ISO15693_CMD_NXP_SET_EAS 0xA2 -#define ISO15693_CMD_NXP_RESET_EAS 0xA3 -#define ISO15693_CMD_NXP_LOCK_EAS 0xA4 -#define ISO15693_CMD_NXP_EAS_ALARM 0xA5 -#define ISO15693_CMD_NXP_PASSWORD_PROTECT_EAS_AFI 0xA6 -#define ISO15693_CMD_NXP_WRITE_EAS_ID 0xA7 -#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ 0xB0 -#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ_FAST 0xB1 -#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2 -#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3 -#define ISO15693_CMD_NXP_WRITE_PASSWORD 0xB4 -#define ISO15693_CMD_NXP_DESTROY 0xB9 -#define ISO15693_CMD_NXP_ENABLE_PRIVACY 0xBA - -// ISO15693 RESPONSE ERROR CODES -#define ISO15693_NOERROR 0x00 -#define ISO15693_ERROR_CMD_NOT_SUP 0x01 // Command not supported -#define ISO15693_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error) -#define ISO15693_ERROR_CMD_OPTION 0x03 // Command option not supported -#define ISO15693_ERROR_GENERIC 0x0F // No additional Info about this error -#define ISO15693_ERROR_BLOCK_UNAVAILABLE 0x10 -#define ISO15693_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again -#define ISO15693_ERROR_BLOCK_LOCKED 0x12 // cannot be changed -#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful -#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful - - -typedef enum { - NfcVAuthMethodManual, - NfcVAuthMethodTonieBox, -} NfcVAuthMethod; - -typedef enum { - NfcVTypePlain = 0, - NfcVTypeSlix = 1, - NfcVTypeSlixS = 2, - NfcVTypeSlixL = 3, - NfcVTypeSlix2 = 4, -} NfcVType; - -typedef struct { - uint8_t key_eas[4]; - uint8_t rand[2]; -} NfcVSlixData; - -typedef struct { - uint8_t key_read[4]; - uint8_t key_write[4]; - uint8_t key_privacy[4]; - uint8_t key_destroy[4]; - uint8_t key_eas[4]; - uint8_t rand[2]; - bool privacy; -} NfcVSlix2Data; - -typedef struct { - uint8_t key_read[4]; - uint8_t key_write[4]; - uint8_t key_privacy[4]; - uint8_t key_destroy[4]; - uint8_t key_eas[4]; - uint8_t rand[2]; - bool privacy; -} NfcVSlixSData; - -typedef struct { - uint8_t key_privacy[4]; - uint8_t key_destroy[4]; - uint8_t key_eas[4]; - uint8_t rand[2]; - bool privacy; -} NfcVSlixLData; - -typedef union { - NfcVSlixData slix; - NfcVSlix2Data slix2; - NfcVSlixSData slix_s; - NfcVSlixLData slix_l; -} NfcVSubtypeData; - -typedef struct { - /* common ISO15693 fields */ - uint8_t dsfid; - uint8_t afi; - uint8_t ic_ref; - uint16_t block_num; - uint8_t block_size; - uint8_t data[NFCV_MAX_DUMP_SIZE]; - - /* specfic variant infos */ - NfcVType type; - NfcVSubtypeData sub_data; - - /* runtime data */ - char last_command[128]; - char error[32]; - NfcVAuthMethod auth_method; - bool auth_success; -} NfcVData; - -typedef struct { - uint16_t blocks_to_read; - int16_t blocks_read; -} NfcVReader; - -ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data); -ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data); -ReturnCode nfcv_inventory(uint8_t* uid); -bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* data); - -void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data); -void nfcv_emu_deinit(); -bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms); diff --git a/lib/nfc/protocols/slix.c b/lib/nfc/protocols/slix.c deleted file mode 100644 index ca3ebcd67..000000000 --- a/lib/nfc/protocols/slix.c +++ /dev/null @@ -1,125 +0,0 @@ - -#include -#include "nfcv.h" -#include "slix.h" -#include "nfc_util.h" -#include -#include "furi_hal_nfc.h" - - -bool slix_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x01) - && (((nfc_data->uid[3] >> 4) & 3) == 2)) { - return true; - } - return false; -} - -bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x01) - && (((nfc_data->uid[3] >> 4) & 3) == 1)) { - return true; - } - return false; -} - -bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x02)) { - return true; - } - return false; -} - -bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x03)) { - return true; - } - return false; -} - - -ReturnCode slix_l_get_random(NfcVData* data) { - uint16_t received = 0; - uint8_t rxBuf[32]; - - ReturnCode ret = rfalNfcvPollerTransceiveReq( - ISO15693_CMD_NXP_GET_RANDOM_NUMBER, - RFAL_NFCV_REQ_FLAG_DEFAULT, - ISO15693_MANUFACTURER_NXP, - NULL, - NULL, - 0, - rxBuf, - sizeof(rxBuf), - &received); - - if(ret == ERR_NONE) { - if(received != 3) { - return ERR_PROTO; - } - if(data != NULL) { - data->sub_data.slix_l.rand[0] = rxBuf[2]; - data->sub_data.slix_l.rand[1] = rxBuf[1]; - } - } - - return ret; -} - -ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id) { - furi_assert(rand); - - uint16_t received = 0; - uint8_t rxBuf[32]; - uint8_t cmd_set_pass[] = { - password_id, - data->sub_data.slix_l.rand[1], - data->sub_data.slix_l.rand[0], - data->sub_data.slix_l.rand[1], - data->sub_data.slix_l.rand[0] - }; - uint8_t *password = NULL; - - switch(password_id) { - case 4: - password = data->sub_data.slix_l.key_privacy; - break; - case 8: - password = data->sub_data.slix_l.key_destroy; - break; - case 10: - password = data->sub_data.slix_l.key_eas; - break; - default: - break; - } - - if(!password) { - return ERR_NOTSUPP; - } - - for(int pos = 0; pos < 4; pos++) { - cmd_set_pass[1 + pos] ^= password[3 - pos]; - } - - ReturnCode ret = rfalNfcvPollerTransceiveReq( - ISO15693_CMD_NXP_SET_PASSWORD, - RFAL_NFCV_REQ_FLAG_DATA_RATE, - ISO15693_MANUFACTURER_NXP, - NULL, - cmd_set_pass, - sizeof(cmd_set_pass), - rxBuf, - sizeof(rxBuf), - &received); - - return ret; -} diff --git a/lib/nfc/protocols/slix.h b/lib/nfc/protocols/slix.h deleted file mode 100644 index b95a27abd..000000000 --- a/lib/nfc/protocols/slix.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include -#include "nfc_util.h" -#include - -#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2 -#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3 -#define ISO15693_MANUFACTURER_NXP 0x04 - - -bool slix_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix2_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data); -ReturnCode slix_l_get_random(NfcVData* data); -ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id); - diff --git a/lib/pulse_reader/pulse_reader.c b/lib/pulse_reader/pulse_reader.c deleted file mode 100644 index f829bf831..000000000 --- a/lib/pulse_reader/pulse_reader.c +++ /dev/null @@ -1,205 +0,0 @@ -#include -#include -#include -#include - -#include "pulse_reader.h" - - -#define GPIO_PIN_MAP(pin, prefix) \ - (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ - ((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \ - ((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \ - ((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \ - ((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \ - ((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \ - ((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \ - ((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \ - ((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \ - ((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \ - ((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \ - ((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \ - ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ - ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ - ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ - prefix##15) - -#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE) - - - -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) { - - PulseReader* signal = malloc(sizeof(PulseReader)); - signal->timer_buffer = malloc(size * sizeof(uint32_t)); - signal->gpio_buffer = malloc(size * sizeof(uint32_t)); - signal->dma_channel = LL_DMA_CHANNEL_4; - signal->gpio = gpio; - signal->size = size; - signal->timer_value = 0; - signal->pos = 0; - - pulse_reader_set_timebase(signal, PulseReaderUnit64MHz); - pulse_reader_set_bittime(signal, 1); - - signal->dma_config_timer.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) &(TIM2->CNT); - signal->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t) signal->timer_buffer; - signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_timer.Priority = LL_DMA_PRIORITY_VERYHIGH; - - signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; - - return signal; -} - -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit) { - switch(unit) { - case PulseReaderUnit64MHz: - signal->unit_multiplier = 1; - signal->unit_divider = 1; - break; - case PulseReaderUnitPicosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1; - break; - case PulseReaderUnitNanosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000; - break; - case PulseReaderUnitMicrosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000000; - break; - } -} - -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time) { - signal->bit_time = bit_time; -} - -void pulse_reader_free(PulseReader* signal) { - free(signal->timer_buffer); - free(signal->gpio_buffer); - free(signal); -} - -uint32_t pulse_reader_samples(PulseReader* signal) { - uint32_t dma_pos = signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - return ((signal->pos + signal->size) - dma_pos) % signal->size; -} - -void pulse_reader_stop(PulseReader* signal) { - LL_DMA_DisableChannel(DMA1, signal->dma_channel); - LL_DMA_DisableChannel(DMA1, signal->dma_channel+1); - LL_DMAMUX_DisableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - LL_TIM_DisableCounter(TIM2); -} - -void pulse_reader_start(PulseReader* signal) { - /* configure DMA to read from a timer peripheral */ - signal->dma_config_timer.NbData = signal->size; - - signal->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) &(signal->gpio->port->IDR); - signal->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t) signal->gpio_buffer; - signal->dma_config_gpio.NbData = signal->size; - - /* start counter */ - LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP); - LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1); - LL_TIM_SetPrescaler(TIM2, 0); - LL_TIM_SetAutoReload(TIM2, 0xFFFFFFFF); - LL_TIM_SetCounter(TIM2, 0); - LL_TIM_EnableCounter(TIM2); - - /* generator 0 gets fed by EXTI_LINEn */ - LL_DMAMUX_SetRequestSignalID(NULL, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(signal->gpio->pin)); - /* trigger on rising edge of the interrupt */ - LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING); - /* now enable request generation again */ - LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - - /* we need the EXTI to be configured as interrupt generating line, but no ISR registered */ - furi_hal_gpio_init_ex(signal->gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); - - /* capture current timer */ - signal->pos = 0; - signal->start_level = furi_hal_gpio_read(signal->gpio); - signal->timer_value = TIM2->CNT; - signal->gpio_mask = signal->gpio->pin; - - /* now set up DMA with these settings */ - LL_DMA_Init(DMA1, signal->dma_channel, &signal->dma_config_timer); - LL_DMA_Init(DMA1, signal->dma_channel+1, &signal->dma_config_gpio); - LL_DMA_EnableChannel(DMA1, signal->dma_channel); - LL_DMA_EnableChannel(DMA1, signal->dma_channel+1); -} - -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) { - - uint32_t start_time = DWT->CYCCNT; - uint32_t timeout_ticks = timeout_us * (F_TIM2/1000000); - - do { - /* get the DMA's next write position by reading "remaining length" register */ - uint32_t dma_pos = signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - /* the DMA has advanced in the ringbuffer */ - if(dma_pos != signal->pos) { - - uint32_t delta = signal->timer_buffer[signal->pos] - signal->timer_value; - uint32_t last_gpio_value = signal->gpio_value; - - signal->gpio_value = signal->gpio_buffer[signal->pos]; - - /* check if the GPIO really toggled. if not, we lost an edge :( */ - if(((last_gpio_value ^ signal->gpio_value) & signal->gpio_mask) != signal->gpio_mask) { - signal->gpio_value ^= signal->gpio_mask; - return PULSE_READER_LOST_EDGE; - } - signal->timer_value = signal->timer_buffer[signal->pos]; - - signal->pos++; - signal->pos %= signal->size; - - uint32_t delta_unit = 0; - - /* probably larger values, so choose a wider data type */ - if(signal->unit_divider > 1) { - delta_unit = (uint32_t)((uint64_t)delta * (uint64_t)signal->unit_multiplier / signal->unit_divider); - } else { - delta_unit = delta * signal->unit_multiplier; - } - - /* if to be scaled to bit times, save a few instructions. should be faster */ - if(signal->bit_time > 1) { - return (delta_unit + signal->bit_time / 2) / signal->bit_time; - } - - return delta_unit; - } - - /* check for timeout */ - uint32_t elapsed = DWT->CYCCNT - start_time; - - if(elapsed > timeout_ticks) { - return PULSE_READER_NO_EDGE; - } - - //furi_delay_ms(0); - - } while(true); -} diff --git a/lib/pulse_reader/pulse_reader.h b/lib/pulse_reader/pulse_reader.h deleted file mode 100644 index 886c9d9e7..000000000 --- a/lib/pulse_reader/pulse_reader.h +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PULSE_READER_NO_EDGE 0xFFFFFFFFUL -#define PULSE_READER_LOST_EDGE 0xFFFFFFFEUL -#define F_TIM2 64000000UL - -/** - * unit of the edge durations to return - */ -typedef enum { - PulseReaderUnit64MHz, - PulseReaderUnitPicosecond, - PulseReaderUnitNanosecond, - PulseReaderUnitMicrosecond, -} PulseReaderUnit; - - -typedef struct { - bool start_level; - uint32_t* timer_buffer; - uint32_t* gpio_buffer; - uint32_t size; - uint32_t pos; - uint32_t timer_value; - uint32_t gpio_value; - uint32_t gpio_mask; - uint32_t unit_multiplier; - uint32_t unit_divider; - uint32_t bit_time; - uint32_t dma_channel; - const GpioPin* gpio; - LL_DMA_InitTypeDef dma_config_timer; - LL_DMA_InitTypeDef dma_config_gpio; -} PulseReader; - - -/** Allocate a PulseReader object - * - * Allocates memory for a ringbuffer and initalizes the object - * - * @param[in] gpio the GPIO to use. will get configured as input. - * @param[in] size number of edges to buffer - */ -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size); - - -/** Free a PulseReader object - * - * Frees all memory of the given object - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_free(PulseReader* signal); - - -/** Start signal capturing - * - * Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_start(PulseReader* signal); - -/** Stop signal capturing - * - * Frees DMA1, TIM2 and DMAMUX_REQ_GEN_0 - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_stop(PulseReader* signal); - - -/** Recevie a sample from ringbuffer - * - * Waits for the specified time until a new edge gets detected. - * If not configured otherwise, the pulse duration will be in picosecond resolution. - * If a bittime was configured, the return value will contain the properly rounded - * number of bit times measured. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] timeout_us time to wait for a signal [µs] - * - * @returns the scaled value of the pulse duration - */ -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us); - - -/** Get available samples - * - * Get the number of available samples in the ringbuffer - * - * @param[in] signal previously allocated PulseReader object. - * - * @returns the number of samples in buffer - */ -uint32_t pulse_reader_samples(PulseReader* signal); - - -/** Set timebase - * - * Set the timebase to be used when returning pulse duration. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] unit PulseReaderUnit64MHz or PulseReaderUnitPicosecond - */ -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit); - - - -/** Set bit time - * - * Set the number of timebase units per bit. - * When set, the pulse_reader_receive() will return an already rounded - * bit count value instead of the raw duration. - * - * Set to 1 to return duration again. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] bit_time - */ -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time); - - -#ifdef __cplusplus -} -#endif