diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index 06f9ed1a2..2a15c4d4e 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -71,8 +71,8 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_set_font(canvas, FontPrimary); if (settings->sfw_mode) { - canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect me"); - canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to a computer"); + canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect to"); + canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "a device"); } else { canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Plug me"); diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index cf4584d7a..90fcf9f27 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -87,6 +87,13 @@ Nfc* nfc_alloc() { nfc->view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box)); nfc->text_box_store = furi_string_alloc(); + // Variable Item List + nfc->variable_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + nfc->view_dispatcher, + NfcViewVarItemList, + variable_item_list_get_view(nfc->variable_item_list)); + // Custom Widget nfc->widget = widget_alloc(); view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget)); @@ -159,6 +166,10 @@ void nfc_free(Nfc* nfc) { text_box_free(nfc->text_box); furi_string_free(nfc->text_box_store); + // Variable Item List + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewVarItemList); + variable_item_list_free(nfc->variable_item_list); + // Custom Widget view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget); widget_free(nfc->widget); @@ -290,6 +301,11 @@ 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_i.h b/applications/main/nfc/nfc_i.h index f7e489902..a3a62972c 100644 --- a/applications/main/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,7 @@ struct Nfc { TextInput* text_input; ByteInput* byte_input; TextBox* text_box; + VariableItemList* variable_item_list; Widget* widget; DictAttack* dict_attack; DetectReader* detect_reader; @@ -92,6 +94,7 @@ typedef enum { NfcViewTextInput, NfcViewByteInput, NfcViewTextBox, + NfcViewVarItemList, NfcViewWidget, NfcViewDictAttack, NfcViewDetectReader, diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index ce51d000d..045080fea 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -14,6 +14,11 @@ ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) 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, emulate_nfcv, EmulateNfcV) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) @@ -45,6 +50,14 @@ ADD_SCENE(nfc, mf_classic_update_success, MfClassicUpdateSuccess) ADD_SCENE(nfc, mf_classic_wrong_card, MfClassicWrongCard) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) ADD_SCENE(nfc, emv_menu, EmvMenu) +ADD_SCENE(nfc, passport_read, PassportReadSuccess) +ADD_SCENE(nfc, passport_read_auth, PassportReadAuthSuccess) +ADD_SCENE(nfc, passport_menu, PassportMenu) +ADD_SCENE(nfc, passport_auth, PassportAuth) +ADD_SCENE(nfc, passport_auth_save_name, PassportAuthSaveName) +ADD_SCENE(nfc, passport_date, PassportDate) +ADD_SCENE(nfc, passport_docnr, PassportDocNr) +ADD_SCENE(nfc, passport_pace_todo, PassportPaceTodo) ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, device_info, DeviceInfo) ADD_SCENE(nfc, delete, Delete) diff --git a/applications/main/nfc/scenes/nfc_scene_delete_success.c b/applications/main/nfc/scenes/nfc_scene_delete_success.c index faa7fd7bb..1664a9e5b 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_delete_success_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_delete_success_popup_callback(void* context) { void nfc_scene_delete_success_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); - } + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_delete_success_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c new file mode 100644 index 000000000..e6fc60d86 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c @@ -0,0 +1,149 @@ +#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_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c index eec43c92c..7316eebe0 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" #define NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX (200) @@ -37,15 +36,8 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { widget_reset(widget); FuriString* info_str; info_str = furi_string_alloc(); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { - widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); widget_add_string_element(widget, 57, 13, AlignLeft, AlignTop, FontPrimary, "Emulating UID"); if(strcmp(nfc->dev->dev_name, "") != 0) { furi_string_printf(info_str, "%s", nfc->dev->dev_name); @@ -62,7 +54,6 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { widget_add_button_element( widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_uid_widget_callback, nfc); } - free(settings); } void nfc_scene_emulate_uid_on_enter(void* context) { diff --git a/applications/main/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index 717e8efc4..147c89757 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexReadCardType, SubmenuIndexMfClassicKeys, SubmenuIndexMfUltralightUnlock, + SubmenuIndexNfcVUnlock, }; void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) { @@ -34,6 +35,12 @@ 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); } @@ -56,6 +63,9 @@ 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_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index b82bf5521..9b477e301 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -58,7 +58,7 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt // If failed to load user dictionary - try the system dictionary if(!dict) { - FURI_LOG_E(TAG, "User dictionary not found"); + FURI_LOG_E(TAG, "User Dictionary Not Found"); state = DictAttackStateFlipperDictInProgress; } } @@ -67,8 +67,8 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt dict_attack_set_header(nfc->dict_attack, "MF Classic System Dictionary"); dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); if(!dict) { - FURI_LOG_E(TAG, "Flipper dictionary not found"); - // Pass through to let the worker handle the failure + FURI_LOG_E(TAG, "Flipper Dictionary Not Found"); + // Pass through to let worker handle the failure } } // Free previous dictionary diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c index 0fa624ad9..8c0f493e1 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" #define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL) #define NFC_MF_CLASSIC_DATA_CHANGED (1UL) @@ -15,8 +14,6 @@ bool nfc_mf_classic_emulate_worker_callback(NfcWorkerEvent event, void* context) void nfc_scene_mf_classic_emulate_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; @@ -26,12 +23,7 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nClassic"); } - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); // Setup and start worker @@ -43,7 +35,6 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { nfc_mf_classic_emulate_worker_callback, nfc); nfc_blink_emulate_start(nfc); - free(settings); } bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index 8a7dc2c18..8b61904b4 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -28,9 +28,9 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { widget_add_string_element( nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MIFARE Classic Keys"); char temp_str[32]; - snprintf(temp_str, sizeof(temp_str), "System dict: %lu", flipper_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "System Dict: %ld", flipper_dict_keys_total); widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "User dict: %lu", user_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "User Dict: %ld", user_dict_keys_total); widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c index a76a758b6..fef8fd5e9 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c @@ -1,6 +1,5 @@ #include "../nfc_i.h" #include -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_mf_classic_update_success_popup_callback(void* context) { Nfc* nfc = context; @@ -10,18 +9,11 @@ void nfc_scene_mf_classic_update_success_popup_callback(void* context) { void nfc_scene_mf_classic_update_success_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcSave); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Updated!", 11, 20, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); @@ -29,7 +21,6 @@ void nfc_scene_mf_classic_update_success_on_enter(void* context) { popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_mf_classic_update_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c index e425d8c3a..2f2a3beb1 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c @@ -1,6 +1,5 @@ #include "../nfc_i.h" #include -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_mf_classic_write_success_popup_callback(void* context) { Nfc* nfc = context; @@ -10,18 +9,11 @@ void nfc_scene_mf_classic_write_success_popup_callback(void* context) { void nfc_scene_mf_classic_write_success_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcSave); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); @@ -29,7 +21,6 @@ void nfc_scene_mf_classic_write_success_on_enter(void* context) { popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_mf_classic_write_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c index 882dc5fea..afc5f0dee 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -51,18 +51,23 @@ void nfc_scene_mf_desfire_app_on_enter(void* context) { nfc_scene_mf_desfire_app_submenu_callback, nfc); - FuriString* label = furi_string_alloc(); + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; int idx = SubmenuIndexDynamic; for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - furi_string_printf(label, "File %d", file->id); + int size = snprintf(buf, cap, "File %d", file->id); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, + "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; submenu_add_item( - nfc->submenu, - furi_string_get_cstr(label), - idx++, - nfc_scene_mf_desfire_app_submenu_callback, - nfc); + nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); } - furi_string_free(label); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c index c7caee8dc..e619d0377 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c @@ -33,18 +33,21 @@ void nfc_scene_mf_desfire_data_on_enter(void* context) { nfc_scene_mf_desfire_data_submenu_callback, nfc); - FuriString* label = furi_string_alloc(); + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; int idx = SubmenuIndexDynamic; for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - furi_string_printf(label, "App %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - submenu_add_item( - submenu, - furi_string_get_cstr(label), - idx++, - nfc_scene_mf_desfire_data_submenu_callback, - nfc); + int size = snprintf(buf, cap, "App %02x%02x%02x", app->id[0], app->id[1], app->id[2]); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, "Exceeded NFC_TEXT_STORE_SIZE when preparing app id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; + submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_data_submenu_callback, nfc); } - furi_string_free(label); if(state >= MifareDesfireDataStateItem) { submenu_set_selected_item( diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index ca25b48c1..88b6b71d9 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -1,23 +1,103 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" +#include + +#define NFC_SCENE_MF_ULTRALIGHT_EMULATE_LOG_SIZE_MAX (200) #define NFC_MF_UL_DATA_NOT_CHANGED (0UL) #define NFC_MF_UL_DATA_CHANGED (1UL) -bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; +enum { + // View states + NfcSceneMfUltralightEmulateStateWidget, + NfcSceneMfUltralightEmulateStateTextBox, + NfcSceneMfUltralightEmulateStateMax = 0xFF, + // State flags + NfcSceneMfUltralightEmulateStateDataChanged = 1 << 8, + NfcSceneMfUltralightEmulateStateAuthAttempted = 1 << 9, + NfcSceneMfUltralightEmulateStateLogButtonShown = 1 << 10, +}; + +bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* context) { + Nfc* nfc = context; + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + + if(event == NfcWorkerEventSuccess) + state |= NfcSceneMfUltralightEmulateStateDataChanged; + else if(event == NfcWorkerEventMfUltralightPwdAuth) { + // Don't update if we're exiting + if(nfc_worker_get_state(nfc->worker) != NfcWorkerStateStop) { + // Event data is only available for the duration of this callback, so we're updating the + // text box right here + MfUltralightAuth* auth = nfc_worker_get_event_data(nfc->worker); + if(auth != NULL && furi_string_size(nfc->text_box_store) < + NFC_SCENE_MF_ULTRALIGHT_EMULATE_LOG_SIZE_MAX) { + furi_string_cat(nfc->text_box_store, "PWD:"); + for(size_t i = 0; i < sizeof(auth->pwd.raw); ++i) { + furi_string_cat_printf(nfc->text_box_store, " %02X", auth->pwd.raw[i]); + } + furi_string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, furi_string_get_cstr(nfc->text_box_store)); + } + state |= NfcSceneMfUltralightEmulateStateAuthAttempted; + } + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_CHANGED); return true; } +void nfc_scene_mf_ultralight_emulate_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_mf_ultralight_emulate_widget_config(Nfc* nfc, bool auth_attempted) { + 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); + if(strcmp(nfc->dev->dev_name, "")) { + furi_string_printf(info_str, "Emulating\n%s", nfc->dev->dev_name); + } else { + furi_string_printf(info_str, "Emulating\nMf Ultralight"); + } + + widget_add_string_multiline_element( + widget, 56, 31, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(info_str)); + furi_string_free(info_str); + if(auth_attempted) { + widget_add_button_element( + widget, + GuiButtonTypeCenter, + "Log", + nfc_scene_mf_ultralight_emulate_widget_callback, + nfc); + } +} + void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + // Setup Widget + nfc_scene_mf_ultralight_emulate_widget_config(nfc, false); + state &= ~NfcSceneMfUltralightEmulateStateLogButtonShown; + // 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); // Setup view MfUltralightType type = nfc->dev->dev_data.mf_ul_data.type; bool is_ultralight = (type == MfUltralightTypeUL11) || (type == MfUltralightTypeUL21) || @@ -31,16 +111,15 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nNTAG"); } - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); - // Setup and start worker - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + // Set Widget state and view + state = (state & ~NfcSceneMfUltralightEmulateStateMax) | + NfcSceneMfUltralightEmulateStateWidget; + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + // Start worker nfc_worker_start( nfc->worker, NfcWorkerStateMfUltralightEmulate, @@ -48,7 +127,6 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { nfc_mf_ultralight_emulate_worker_callback, nfc); nfc_blink_emulate_start(nfc); - free(settings); } bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent event) { @@ -68,16 +146,28 @@ bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent e nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path)); } } - consumed = false; } return consumed; } void nfc_scene_mf_ultralight_emulate_on_exit(void* context) { Nfc* nfc = context; + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + + // Stop worker + nfc_worker_stop(nfc->worker); + // Check if data changed and save in shadow file + if(state & NfcSceneMfUltralightEmulateStateDataChanged) { + state &= ~NfcSceneMfUltralightEmulateStateDataChanged; + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); + } // Clear view - popup_reset(nfc->popup); + 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_mf_ultralight_key_input.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c index 089187d5b..174d1a406 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c @@ -11,7 +11,7 @@ void nfc_scene_mf_ultralight_key_input_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_header_text(byte_input, "Enter The Password In Hex"); byte_input_set_result_callback( byte_input, nfc_scene_mf_ultralight_key_input_byte_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c index c511e9dcb..ddf30c54a 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -2,7 +2,8 @@ #include enum SubmenuIndex { - SubmenuIndexUnlock, + SubmenuIndexUnlockByReader, + SubmenuIndexUnlockByPassword, SubmenuIndexSave, SubmenuIndexEmulate, SubmenuIndexInfo, @@ -22,8 +23,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { if(!mf_ul_is_full_capture(data)) { submenu_add_item( submenu, - "Unlock", - SubmenuIndexUnlock, + "Unlock With Reader", + SubmenuIndexUnlockByReader, + nfc_scene_mf_ultralight_menu_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Unlock With Password", + SubmenuIndexUnlockByPassword, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); } @@ -63,7 +70,10 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even DOLPHIN_DEED(DolphinDeedNfcEmulate); } consumed = true; - } else if(event.event == SubmenuIndexUnlock) { + } else if(event.event == SubmenuIndexUnlockByReader) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockAuto); + consumed = true; + } else if(event.event == SubmenuIndexUnlockByPassword) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); consumed = true; } else if(event.event == SubmenuIndexInfo) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c index 2ab5e3f3f..8e2dd0c22 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c @@ -24,21 +24,22 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState if(curr_state != state) { if(state == NfcSceneMfUlReadStateDetecting) { popup_reset(nfc->popup); - popup_set_text(nfc->popup, "Apply the\ntarget card", 97, 24, AlignCenter, AlignTop); + popup_set_text( + nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); nfc_blink_read_start(nfc); } else if(state == NfcSceneMfUlReadStateReading) { popup_reset(nfc->popup); popup_set_header( - nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); + nfc->popup, "Reading Card\nDon't Move...", 85, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 12, 23, &A_Loading_24); nfc_blink_detect_start(nfc); } else if(state == NfcSceneMfUlReadStateNotSupportedCard) { popup_reset(nfc->popup); - popup_set_header(nfc->popup, "Wrong type of card!", 64, 3, AlignCenter, AlignTop); + popup_set_header(nfc->popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop); popup_set_text( nfc->popup, - "Only MIFARE\nUltralight & NTAG\nare supported", + "Only MIFARE\nUltralight & NTAG\n Are Supported", 4, 22, AlignLeft, diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c index c59fe3a7d..050f6db1e 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c @@ -31,7 +31,7 @@ void nfc_scene_mf_ultralight_unlock_auto_on_enter(void* context) { nfc_scene_mf_ultralight_unlock_auto_worker_callback, nfc); - nfc_blink_read_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_mf_ultralight_unlock_auto_on_event(void* context, SceneManagerEvent event) { @@ -58,6 +58,7 @@ void nfc_scene_mf_ultralight_unlock_auto_on_exit(void* context) { // Stop worker nfc_worker_stop(nfc->worker); // Clear view + popup_reset(nfc->popup); widget_reset(nfc->widget); nfc_blink_stop(nfc); 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 b44ab7823..372da8860 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -7,6 +7,17 @@ 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; @@ -14,7 +25,8 @@ 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)) { + if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl) || + (protocol == NfcDeviceProtocolNfcV)) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); text_scroll_height = 52; @@ -32,6 +44,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { // Set tag type if(protocol == NfcDeviceProtocolEMV) { furi_string_cat_printf(temp_str, "\e#EMV Bank Card\n"); + } else if(protocol == NfcDeviceProtocolMRTD) { + furi_string_cat_printf(temp_str, "\e#Passport/ID\n"); } else if(protocol == NfcDeviceProtocolMifareUl) { furi_string_cat_printf( temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); @@ -40,19 +54,156 @@ 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.sub_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 - 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]); + 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.sub_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.key_read)); + furi_string_cat_printf( + temp_str, + " Write %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write)); + furi_string_cat_printf( + temp_str, + " Privacy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + 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 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.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + 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 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.slix.key_read)); + furi_string_cat_printf( + temp_str, + " Write %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write)); + furi_string_cat_printf( + temp_str, + " Privacy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + furi_string_cat_printf( + temp_str, + " EAS %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.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); } - 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) { @@ -136,6 +287,9 @@ 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 new file mode 100644 index 000000000..cc53c4dcb --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c @@ -0,0 +1,48 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_nfcv_key_input_byte_input_callback(void* context) { + Nfc* nfc = context; + NfcVSlixData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix; + + 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 new file mode 100644 index 000000000..b30495a05 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c @@ -0,0 +1,63 @@ +#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 new file mode 100644 index 000000000..b52cc0caa --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c @@ -0,0 +1,155 @@ +#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; + NfcVSlixData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix; + + 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 figurine 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, + "%s/SLIX_%02X%02X%02X%02X%02X%02X%02X%02X%s", + NFC_APP_FOLDER, + 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_APP_EXTENSION); + + 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 new file mode 100644 index 000000000..9c4c81fbd --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c @@ -0,0 +1,60 @@ +#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_passport_auth.c b/applications/main/nfc/scenes/nfc_scene_passport_auth.c new file mode 100644 index 000000000..c90c38233 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_auth.c @@ -0,0 +1,194 @@ +#include "../nfc_i.h" + +#define TAG "PassportAuth" + +#define MRTD_AUTH_METHOD_COUNT 4 +// Must match MrtdAuthMethod size (lib/nfc/protocols/mrtd_helpers.h) + +typedef enum { + NfcScenePassportAuthSelectDob, + NfcScenePassportAuthSelectDoe, + NfcScenePassportAuthSelectDocNr, + NfcScenePassportAuthSelectMethod, + NfcScenePassportAuthSelectAuth, + NfcScenePassportAuthSelectSave, + NfcScenePassportAuthSelectLoad, +} NfcScenePassportAuthSelect; + +void nfc_scene_passport_auth_var_list_enter_callback(void* context, uint32_t index) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_passport_auth_method_changed(VariableItem* item) { + Nfc* nfc = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + nfc->dev->dev_data.mrtd_data.auth.method = index; + variable_item_set_current_value_text(item, mrtd_auth_method_string(index)); +} + +bool nfc_scene_passport_auth_load(Nfc* nfc) { + const DialogsFileBrowserOptions browser_options = { + .extension = MRTD_APP_EXTENSION, + .skip_assets = true, + .icon = &I_u2f_10px, + .hide_ext = true, + .item_loader_callback = NULL, + .item_loader_context = NULL, + }; + + FuriString* mrtd_app_folder; + mrtd_app_folder = furi_string_alloc_set(MRTD_APP_FOLDER); + + FuriString* file_path; + file_path = furi_string_alloc(); + + bool res = + dialog_file_browser_show(nfc->dev->dialogs, file_path, mrtd_app_folder, &browser_options); + + furi_string_free(mrtd_app_folder); + + if(res) { + mrtd_auth_params_load( + nfc->dev->storage, + nfc->dev->dialogs, + &nfc->dev->dev_data.mrtd_data.auth, + furi_string_get_cstr(file_path), + true); + + nfc_scene_passport_auth_on_enter(nfc); + variable_item_list_set_selected_item( + nfc->variable_item_list, NfcScenePassportAuthSelectAuth); + } + + return res; +} + +void nfc_scene_passport_auth_on_enter(void* context) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + // By entering the Auth menu, we default to Auth: Any + MrtdAuthMethod* auth_method = &mrtd_data->auth.method; + if(*auth_method == MrtdAuthMethodNone) { + *auth_method = MrtdAuthMethodAny; + } + + VariableItemList* variable_item_list = nfc->variable_item_list; + variable_item_list_reset(variable_item_list); + + VariableItem* item; + uint8_t value_index; + + const size_t temp_str_size = 15; + char temp_str[temp_str_size]; + snprintf( + temp_str, + temp_str_size, + "%02u%02u%02u", + mrtd_data->auth.birth_date.year, + mrtd_data->auth.birth_date.month, + mrtd_data->auth.birth_date.day); + + item = variable_item_list_add(variable_item_list, "Birth Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, temp_str); + + snprintf( + temp_str, + temp_str_size, + "%02u%02u%02u", + mrtd_data->auth.expiry_date.year, + mrtd_data->auth.expiry_date.month, + mrtd_data->auth.expiry_date.day); + + item = variable_item_list_add(variable_item_list, "Expiry Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, temp_str); + + item = variable_item_list_add(variable_item_list, "Document Nr.", 1, NULL, NULL); + + strncpy(temp_str, mrtd_data->auth.doc_number, temp_str_size); + temp_str[temp_str_size -1] = '\x00'; + if(strlen(temp_str) > 8) { + temp_str[8] = '.'; + temp_str[9] = '.'; + temp_str[10] = '.'; + temp_str[11] = '\x00'; + } + variable_item_set_current_value_text(item, temp_str); + + item = variable_item_list_add( + variable_item_list, + "Method", + MRTD_AUTH_METHOD_COUNT, + nfc_scene_passport_auth_method_changed, + nfc); + + value_index = *auth_method; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, mrtd_auth_method_string(value_index)); + + variable_item_list_add(variable_item_list, "Authenticate and read", 1, NULL, NULL); + + variable_item_list_add(variable_item_list, "Save parameters", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Load parameters", 1, NULL, NULL); + + variable_item_list_set_enter_callback( + variable_item_list, nfc_scene_passport_auth_var_list_enter_callback, nfc); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewVarItemList); +} + +bool nfc_scene_passport_auth_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + FURI_LOG_D(TAG, "event.event: %ld", event.event); + switch(event.event) { + case NfcScenePassportAuthSelectLoad: + nfc_scene_passport_auth_load(nfc); + consumed = true; + break; + case NfcScenePassportAuthSelectDob: + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 0); + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate); + consumed = true; + break; + case NfcScenePassportAuthSelectDoe: + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 1); + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate); + consumed = true; + break; + case NfcScenePassportAuthSelectDocNr: + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDocNr); + consumed = true; + break; + case NfcScenePassportAuthSelectMethod: + consumed = true; + break; + case NfcScenePassportAuthSelectAuth: + if(nfc->dev->dev_data.mrtd_data.auth.method == MrtdAuthMethodPace) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportPaceTodo); + } else { + nfc_device_clear(nfc->dev); + scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); + } + consumed = true; + break; + case NfcScenePassportAuthSelectSave: + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuthSaveName); + consumed = true; + break; + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_passport_auth_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + variable_item_list_reset(nfc->variable_item_list); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c b/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c new file mode 100644 index 000000000..65fee0bcf --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c @@ -0,0 +1,82 @@ +#include "../nfc_i.h" +#include +#include +#include + +void nfc_scene_passport_auth_save_name_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_auth_save_name_on_enter(void* context) { + Nfc* nfc = context; + + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + // Setup view + TextInput* text_input = nfc->text_input; + bool docnr_empty = false; + if(!strcmp(mrtd_data->auth.doc_number, "")) { + set_random_name(nfc->text_store, sizeof(nfc->text_store)); + docnr_empty = true; + } else { + nfc_text_store_set(nfc, mrtd_data->auth.doc_number); + } + text_input_set_header_text(text_input, "Name the parameters"); + text_input_set_result_callback( + text_input, + nfc_scene_passport_auth_save_name_text_input_callback, + nfc, + nfc->text_store, + NFC_DEV_NAME_MAX_LEN, + docnr_empty); + + FuriString* folder_path; + folder_path = furi_string_alloc(); + + if(furi_string_end_with(nfc->dev->load_path, NFC_APP_EXTENSION)) { + path_extract_dirname(furi_string_get_cstr(nfc->dev->load_path), folder_path); + } else { + furi_string_set(folder_path, NFC_APP_FOLDER); + } + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, NULL); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); + + furi_string_free(folder_path); +} + +bool nfc_scene_passport_auth_save_name_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + if(mrtd_auth_params_save( + nfc->dev->storage, nfc->dev->dialogs, &mrtd_data->auth, nfc->text_store)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); + consumed = true; + } else { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneStart); + } + } + } + return consumed; +} + +void nfc_scene_passport_auth_save_name_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + void* validator_context = text_input_get_validator_callback_context(nfc->text_input); + text_input_set_validator(nfc->text_input, NULL, NULL); + validator_is_file_free(validator_context); + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_date.c b/applications/main/nfc/scenes/nfc_scene_passport_date.c new file mode 100644 index 000000000..6655bdd59 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_date.c @@ -0,0 +1,126 @@ +#include "../nfc_i.h" +#include "m-string.h" +#include + +#define TAG "PassportDate" + +#define DATE_LENGTH 6 + +//TODO: use types in .h file? also in nfc_scene_passport_bac.c +#define NFC_PASSPORT_DATE_BIRTH 0 +#define NFC_PASSPORT_DATE_EXPIRY 1 + +void nfc_scene_passport_date_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_date_on_enter(void* context) { + Nfc* nfc = context; + + MrtdDate date_value; + + uint32_t date_type = scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportDate); + + //TODO: numbers only + TextInput* text_input = nfc->text_input; + + // TODO: Clean this up because I'm bad + date_value.year = 0; + date_value.month = 0; + date_value.day = 0; + + + switch(date_type) { + case NFC_PASSPORT_DATE_BIRTH: + text_input_set_header_text(text_input, "Birth Date"); + date_value = nfc->dev->dev_data.mrtd_data.auth.birth_date; + break; + case NFC_PASSPORT_DATE_EXPIRY: + text_input_set_header_text(text_input, "Expiry Date"); + date_value = nfc->dev->dev_data.mrtd_data.auth.expiry_date; + break; + } + + bool date_empty = false; + if(date_value.year == 0 || date_value.month == 0 || date_value.day == 0 || + date_value.year > 100 || date_value.month > 13 || date_value.day > 31) { + nfc_text_store_set(nfc, "YYMMDD"); + date_empty = true; + } else { + char temp_str[10]; + snprintf(temp_str, 10, "%02u%02u%02u", date_value.year, date_value.month, date_value.day); + + memcpy(nfc->text_store, temp_str, DATE_LENGTH); + nfc->text_store[DATE_LENGTH] = '\x00'; + } + + text_input_set_result_callback( + text_input, + nfc_scene_passport_date_text_input_callback, + nfc, + nfc->text_store, + DATE_LENGTH + 1, // incl. '\x00' + date_empty); // Use as template + + //TODO: add validator for valid date (YYMMDD) + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); +} + +bool nfc_scene_passport_date_save(Nfc* nfc) { + int year; + int month; + int day; + int ret = sscanf(nfc->text_store, "%02d%02d%02d", &year, &month, &day); + + if(ret != 3) { + FURI_LOG_E(TAG, "Invalid date entered (YYMMDD): %s", nfc->text_store); + return false; + } + + MrtdDate date_value; + date_value.year = year; + date_value.month = month; + date_value.day = day; + + uint32_t date_type = scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportDate); + + //TODO: use types in .h file? also in nfc_scene_passport_bac.c + switch(date_type) { + case NFC_PASSPORT_DATE_BIRTH: + nfc->dev->dev_data.mrtd_data.auth.birth_date = date_value; + break; + case NFC_PASSPORT_DATE_EXPIRY: + nfc->dev->dev_data.mrtd_data.auth.expiry_date = date_value; + break; + } + + return true; +} + +bool nfc_scene_passport_date_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + nfc_scene_passport_date_save(nfc); + //TODO: handle invalid date (returned false) + + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_date_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + // TODO: clear validator + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_docnr.c b/applications/main/nfc/scenes/nfc_scene_passport_docnr.c new file mode 100644 index 000000000..109415759 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_docnr.c @@ -0,0 +1,67 @@ +#include "../nfc_i.h" +#include "m-string.h" +#include + +#define TAG "PassportDocnr" + +void nfc_scene_passport_docnr_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_docnr_on_enter(void* context) { + Nfc* nfc = context; + + TextInput* text_input = nfc->text_input; + text_input_set_header_text(text_input, "Document Nr."); + + char* docnr = nfc->dev->dev_data.mrtd_data.auth.doc_number; + bool docnr_empty = false; + + if(*docnr) { + nfc_text_store_set(nfc, docnr); + docnr_empty = false; + } else { + nfc_text_store_set(nfc, "PA7HJ34M8"); + docnr_empty = true; + } + + text_input_set_result_callback( + text_input, + nfc_scene_passport_docnr_text_input_callback, + nfc, + nfc->text_store, + MRTD_DOCNR_MAX_LENGTH, // incl. '\x00' + docnr_empty); // Use as template + + //TODO: add validator? + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); +} + +bool nfc_scene_passport_docnr_save(Nfc* nfc) { + strncpy(nfc->dev->dev_data.mrtd_data.auth.doc_number, nfc->text_store, MRTD_DOCNR_MAX_LENGTH); + return true; +} + +bool nfc_scene_passport_docnr_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + nfc_scene_passport_docnr_save(nfc); + + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_docnr_on_exit(void* context) { + Nfc* nfc = context; + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_menu.c b/applications/main/nfc/scenes/nfc_scene_passport_menu.c new file mode 100644 index 000000000..27febcb18 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_menu.c @@ -0,0 +1,57 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSave, + SubmenuIndexInfo, +}; + +void nfc_scene_passport_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_passport_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "Save", SubmenuIndexSave, nfc_scene_passport_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_passport_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_passport_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSave) { + //TODO: save more than just UID + nfc->dev->format = NfcDeviceSaveFormatUid; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_passport_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c b/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c new file mode 100644 index 000000000..c6d7d7f6c --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c @@ -0,0 +1,40 @@ +#include "../nfc_i.h" + +void nfc_scene_passport_pace_todo_popup_callback(void* context) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_passport_pace_todo_on_enter(void* context) { + Nfc* nfc = context; + + // Setup view + Popup* popup = nfc->popup; + popup_set_icon(popup, 64, 16, &I_DolphinCommon_56x48); + popup_set_header(popup, "PACE not yet implemented", 4, 4, AlignLeft, AlignTop); + popup_set_timeout(popup, 2000); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_passport_pace_todo_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); +} + +bool nfc_scene_passport_pace_todo_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_pace_todo_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + popup_reset(nfc->popup); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_read.c b/applications/main/nfc/scenes/nfc_scene_passport_read.c new file mode 100644 index 000000000..74f173b52 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_read.c @@ -0,0 +1,90 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_passport_read_widget_callback(GuiButtonType result, InputType type, void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_passport_read_on_enter(void* context) { + Nfc* nfc = context; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + Widget* widget = nfc->widget; + + // Setup Custom Widget view + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_set(temp_str, "\e#Passport\n"); + char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; + + char nfc_type; + switch(data->type) { + case FuriHalNfcTypeA: + nfc_type = 'A'; + break; + case FuriHalNfcTypeB: + nfc_type = 'B'; + break; + default: + nfc_type = '?'; + break; + } + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-%c)\n", iso_type, nfc_type); + furi_string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); + } + furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X\n", data->sak); + + if(mrtd_data->auth.method != MrtdAuthMethodNone && !mrtd_data->auth_success) { + furi_string_cat_printf(temp_str, "Auth failed. Wrong params?"); + } + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_passport_read_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeCenter, "Auth", nfc_scene_passport_read_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_passport_read_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_passport_read_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeCenter) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuth); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_passport_read_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c b/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c new file mode 100644 index 000000000..31a9e8ce1 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c @@ -0,0 +1,142 @@ +#include "../nfc_i.h" +#include + +const char months[13][4] = { + "---", + "JAN", + "FEB", + "MAR", + "APR", + "MAY", + "JUN", + "JUL", + "AUG", + "SEP", + "OCT", + "NOV", + "DEC", +}; + +void nfc_scene_passport_read_auth_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_passport_read_auth_on_enter(void* context) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + Widget* widget = nfc->widget; + + // Setup Custom Widget view + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_set(temp_str, "\e#Passport\n"); + furi_string_cat_printf( + temp_str, "Auth.method: %s\n", mrtd_auth_method_string(mrtd_data->auth_method_used)); + // TODO: indicate BAC / PACE used + + uint16_t lds_version = mrtd_data->files.EF_COM.lds_version; + furi_string_cat_printf(temp_str, "LDS version: %d.%d\n", lds_version / 100, lds_version % 100); + + uint32_t unicode_version = mrtd_data->files.EF_COM.unicode_version; + furi_string_cat_printf( + temp_str, + "Unicode version: %d.%d.%d\n", + (uint8_t)(unicode_version / 10000), + (uint8_t)(unicode_version / 100 % 100), + (uint8_t)(unicode_version % 100)); + + furi_string_cat_printf(temp_str, "Avail.files: "); + for(size_t i = 0; i < MAX_EFCOM_TAGS; ++i) { + uint8_t tag = mrtd_data->files.EF_COM.tag_list[i]; + const EFFile* file = mrtd_tag_to_file(tag); + if(file->tag) { + if(i > 0) furi_string_cat_printf(temp_str, ", "); + furi_string_cat_printf(temp_str, "%s", file->name); + } + } + furi_string_cat_printf(temp_str, "\n"); + + EF_DIR_contents* EF_DIR = &mrtd_data->files.EF_DIR; + if(EF_DIR->applications_count > 0) { + furi_string_cat_printf(temp_str, "Apps:\n"); + for(uint8_t i = 0; i < EF_DIR->applications_count; ++i) { + for(uint8_t n = 0; n < sizeof(AIDValue); ++n) { + furi_string_cat_printf(temp_str, "%02X ", EF_DIR->applications[i][n]); + } + furi_string_cat_printf(temp_str, "\n"); + } + } + + EF_DG1_contents* DG1 = &mrtd_data->files.DG1; + furi_string_cat_printf(temp_str, "\e#DG1\n"); + furi_string_cat_printf(temp_str, "Doc Type: %s\n", DG1->doctype); + furi_string_cat_printf(temp_str, "Issuing State: %s\n", DG1->issuing_state); + furi_string_cat_printf(temp_str, "Name: %s\n", DG1->name); + furi_string_cat_printf(temp_str, "DocNr: %s\n", DG1->docnr); + furi_string_cat_printf(temp_str, "Nationality: %s\n", DG1->nationality); + furi_string_cat_printf( + temp_str, + "Birth Date: %02d %s %02d\n", + DG1->birth_date.day, + months[DG1->birth_date.month], + DG1->birth_date.year); + furi_string_cat_printf(temp_str, "Sex: %s\n", DG1->sex); + furi_string_cat_printf( + temp_str, + "Expiry Date: %02d %s %02d\n", + DG1->expiry_date.day, + months[DG1->expiry_date.month], + DG1->expiry_date.year); + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_passport_read_auth_widget_callback, nfc); + /* + widget_add_button_element( + nfc->widget, GuiButtonTypeCenter, "Auth", nfc_scene_passport_read_auth_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_passport_read_auth_widget_callback, nfc); + */ + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_passport_read_auth_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + nfc->dev->dev_data.mrtd_data.auth_success = false; + nfc->dev->dev_data.mrtd_data.auth.method = MrtdAuthMethodNone; + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeCenter) { + //scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuth); + //consumed = true; + } else if(event.event == GuiButtonTypeRight) { + //scene_manager_next_scene(nfc->scene_manager, NfcScenePassportMenu); + //consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_passport_read_auth_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index 4252883b2..7164a155f 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -25,12 +25,12 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) { if(state == NfcSceneReadStateDetecting) { popup_reset(nfc->popup); popup_set_text( - nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop); + nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); } else if(state == NfcSceneReadStateReading) { popup_reset(nfc->popup); popup_set_header( - nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); + nfc->popup, "Reading Card\nDon't Move...", 85, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 12, 23, &A_Loading_24); } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, state); @@ -68,6 +68,11 @@ 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 @@ -90,6 +95,19 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; + } else if(event.event == NfcWorkerEventReadPassport) { + notification_message(nfc->notifications, &sequence_success); + FURI_LOG_D( + "NFC", + "Read passport, auth: %d, success: %d", + nfc->dev->dev_data.mrtd_data.auth.method, + nfc->dev->dev_data.mrtd_data.auth_success); + if(nfc->dev->dev_data.mrtd_data.auth_success) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportReadAuthSuccess); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportReadSuccess); + } + consumed = true; } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack); diff --git a/applications/main/nfc/scenes/nfc_scene_restore_original.c b/applications/main/nfc/scenes/nfc_scene_restore_original.c index 3709008fd..3ecf5c048 100644 --- a/applications/main/nfc/scenes/nfc_scene_restore_original.c +++ b/applications/main/nfc/scenes/nfc_scene_restore_original.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_restore_original_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_restore_original_popup_callback(void* context) { void nfc_scene_restore_original_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Original file\nrestored", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_restore_original_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c index e0da1317c..d06ee7564 100644 --- a/applications/main/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -1,25 +1,17 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_rpc_on_enter(void* context) { Nfc* nfc = context; Popup* popup = nfc->popup; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61); - } + + popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); notification_message(nfc->notifications, &sequence_display_backlight_on); - free(settings); } static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) { @@ -63,6 +55,13 @@ 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_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index 007274226..8f0e889ec 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -22,7 +22,7 @@ void nfc_scene_save_name_on_enter(void* context) { } else { nfc_text_store_set(nfc, nfc->dev->dev_name); } - text_input_set_header_text(text_input, "Name the card"); + text_input_set_header_text(text_input, "Name The Card"); text_input_set_result_callback( text_input, nfc_scene_save_name_text_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_save_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c index 8e74a55ae..43f2246cd 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_save_success_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_save_success_popup_callback(void* context) { void nfc_scene_save_success_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_save_success_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { @@ -40,6 +31,12 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneSavedMenu); + } 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 c0d3ed5c6..616dc0ef7 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -117,6 +117,8 @@ 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/applications/main/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c index a539e514b..9ee9b1e15 100644 --- a/applications/main/nfc/views/dict_attack.c +++ b/applications/main/nfc/views/dict_attack.c @@ -32,7 +32,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { DictAttackViewModel* m = model; if(m->state == DictAttackStateCardRemoved) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); + canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost The Tag!"); canvas_set_font(canvas, FontSecondary); elements_multiline_text_aligned( canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); @@ -69,7 +69,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { } elements_progress_bar_with_text(canvas, 0, 20, 128, dict_progress, draw_str); canvas_set_font(canvas, FontSecondary); - snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); + snprintf(draw_str, sizeof(draw_str), "Keys Found: %d/%d", m->keys_found, m->keys_total); canvas_draw_str_aligned(canvas, 0, 33, AlignLeft, AlignTop, draw_str); snprintf( draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total); diff --git a/applications/main/u2f/views/u2f_view.c b/applications/main/u2f/views/u2f_view.c index 4f5d382d5..fb5eaac1f 100644 --- a/applications/main/u2f/views/u2f_view.c +++ b/applications/main/u2f/views/u2f_view.c @@ -25,7 +25,7 @@ static void u2f_view_draw_callback(Canvas* canvas, void* _model) { if (model->display_msg == U2fMsgNotConnected) { if (settings->sfw_mode) { canvas_draw_icon(canvas, 22, 15, &I_Connect_me_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connect me to computer"); + canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connect to a device"); } else { canvas_draw_icon(canvas, 22, 15, &I_Connect_me_62x31); diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_0.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_0.png new file mode 100644 index 000000000..7c2add0e9 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_0.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_1.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_1.png new file mode 100644 index 000000000..27664d203 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_1.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_10.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_10.png new file mode 100644 index 000000000..da62ce4cf Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_10.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_11.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_11.png new file mode 100644 index 000000000..7a850b001 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_11.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_12.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_12.png new file mode 100644 index 000000000..b980807c7 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_12.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_13.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_13.png new file mode 100644 index 000000000..bf8a62d42 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_13.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_14.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_14.png new file mode 100644 index 000000000..bd3c0165a Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_14.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_15.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_15.png new file mode 100644 index 000000000..3a04944b1 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_15.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_16.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_16.png new file mode 100644 index 000000000..b08d48e7f Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_16.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_17.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_17.png new file mode 100644 index 000000000..5bdd77c12 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_17.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_18.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_18.png new file mode 100644 index 000000000..94b25dd6b Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_18.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_19.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_19.png new file mode 100644 index 000000000..6531182ba Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_19.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_2.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_2.png new file mode 100644 index 000000000..16de2f5a8 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_2.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_20.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_20.png new file mode 100644 index 000000000..e0bbf11e9 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_20.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_21.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_21.png new file mode 100644 index 000000000..6cd4277bb Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_21.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_22.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_22.png new file mode 100644 index 000000000..c1ace764f Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_22.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_23.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_23.png new file mode 100644 index 000000000..0ad019728 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_23.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_24.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_24.png new file mode 100644 index 000000000..0cc109ea1 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_24.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_25.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_25.png new file mode 100644 index 000000000..6fd18ac98 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_25.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_26.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_26.png new file mode 100644 index 000000000..8e4d322a1 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_26.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_27.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_27.png new file mode 100644 index 000000000..1d6214994 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_27.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_3.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_3.png new file mode 100644 index 000000000..1ee0b55a4 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_3.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_4.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_4.png new file mode 100644 index 000000000..759d3242d Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_4.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_5.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_5.png new file mode 100644 index 000000000..63d2324f2 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_5.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_6.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_6.png new file mode 100644 index 000000000..fbea5c447 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_6.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_7.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_7.png new file mode 100644 index 000000000..b1f48bf49 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_7.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_8.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_8.png new file mode 100644 index 000000000..38b730fd1 Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_8.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_9.png b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_9.png new file mode 100644 index 000000000..e610e30ce Binary files /dev/null and b/assets/dolphin/external/PaxGod_TikTok_Marketing/frame_9.png differ diff --git a/assets/dolphin/external/PaxGod_TikTok_Marketing/meta.txt b/assets/dolphin/external/PaxGod_TikTok_Marketing/meta.txt new file mode 100644 index 000000000..f0fa77e2e --- /dev/null +++ b/assets/dolphin/external/PaxGod_TikTok_Marketing/meta.txt @@ -0,0 +1,13 @@ +Filetype: Flipper Animation +Version: 1 +Width: 128 +Height: 64 +Passive frames: 21 +Active frames: 1 +Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +Active cycles: 1 +Frame rate: 5 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 0 \ No newline at end of file diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 80a6de314..166f85246 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -106,6 +106,13 @@ Min level: 15 Max level: 30 Weight: 7 +Name: PaxGod_TikTok_Marketing +Min butthurt: 0 +Max butthurt: 14 +Min level: 11 +Max level: 30 +Weight: 3 + Name: lvl_16 Min butthurt: 0 Max butthurt: 14 diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_0.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_0.bm new file mode 100644 index 000000000..5401e21b2 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_0.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_1.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_1.bm new file mode 100644 index 000000000..49d9e5135 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_1.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_10.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_10.bm new file mode 100644 index 000000000..9f8e4fb7e Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_10.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_11.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_11.bm new file mode 100644 index 000000000..38c7944ac Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_11.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_12.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_12.bm new file mode 100644 index 000000000..ea234b0df Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_12.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_13.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_13.bm new file mode 100644 index 000000000..a209cd8ff Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_13.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_14.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_14.bm new file mode 100644 index 000000000..2829185a3 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_14.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_15.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_15.bm new file mode 100644 index 000000000..bff1cf3e6 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_15.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_16.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_16.bm new file mode 100644 index 000000000..d234a954f Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_16.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_17.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_17.bm new file mode 100644 index 000000000..30fdc120a Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_17.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_18.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_18.bm new file mode 100644 index 000000000..094707228 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_18.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_19.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_19.bm new file mode 100644 index 000000000..01492a1b4 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_19.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_2.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_2.bm new file mode 100644 index 000000000..100611d9e Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_2.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_20.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_20.bm new file mode 100644 index 000000000..fadf12f27 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_20.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_21.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_21.bm new file mode 100644 index 000000000..ea71be67e Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_21.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_3.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_3.bm new file mode 100644 index 000000000..30b2bf584 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_3.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_4.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_4.bm new file mode 100644 index 000000000..4bcbb83bb Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_4.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_5.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_5.bm new file mode 100644 index 000000000..cebdd493c Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_5.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_6.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_6.bm new file mode 100644 index 000000000..c3b27b3b3 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_6.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_7.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_7.bm new file mode 100644 index 000000000..70fe5f7df Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_7.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_8.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_8.bm new file mode 100644 index 000000000..4ab53bb30 Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_8.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_9.bm b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_9.bm new file mode 100644 index 000000000..aeadd2f0f Binary files /dev/null and b/assets/resources/dolphin/PaxGod_TikTok_Marketing/frame_9.bm differ diff --git a/assets/resources/dolphin/PaxGod_TikTok_Marketing/meta.txt b/assets/resources/dolphin/PaxGod_TikTok_Marketing/meta.txt new file mode 100644 index 000000000..83bee1ed9 --- /dev/null +++ b/assets/resources/dolphin/PaxGod_TikTok_Marketing/meta.txt @@ -0,0 +1,14 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 21 +Active frames: 1 +Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +Active cycles: 1 +Frame rate: 5 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 0 diff --git a/assets/resources/dolphin/manifest.txt b/assets/resources/dolphin/manifest.txt index 41cfe0899..80265a8b8 100644 --- a/assets/resources/dolphin/manifest.txt +++ b/assets/resources/dolphin/manifest.txt @@ -106,6 +106,13 @@ Min level: 15 Max level: 30 Weight: 7 +Name: PaxGod_TikTok_Marketing +Min butthurt: 0 +Max butthurt: 14 +Min level: 11 +Max level: 30 +Weight: 3 + Name: lvl_16 Min butthurt: 0 Max butthurt: 14 diff --git a/assets/resources/subghz/unirf/CVS_Walgreens.txt b/assets/resources/subghz/unirf/CVS_Walgreens.txt index ef3ef0c70..712543d76 100644 --- a/assets/resources/subghz/unirf/CVS_Walgreens.txt +++ b/assets/resources/subghz/unirf/CVS_Walgreens.txt @@ -1,10 +1,10 @@ Filetype: Flipper SubGhz RAW File Version: 1 -UP: /any/subghz/Walgreens/Walgreens_Cough.sub -DOWN: /any/subghz/CVS/CVS_Dental.sub -LEFT: /any/subghz/Walgreens/Walgreens_Skincare.sub -RIGHT: /subghz/Walgreens/Walgreens_Vitamin.sub -OK: /any/subghz/CVS/CVS_Stomach.sub +UP: /any/subghz/Stores/Walgreens/Walgreens_Cough.sub +DOWN: /any/subghz/Stores/CVS/CVS_Dental.sub +LEFT: /any/subghz/Stores/Walgreens/Walgreens_Skincare.sub +RIGHT: /any/subghz/Stores/Walgreens/Walgreens_Vitamin.sub +OK: /any/subghz/Stores/CVS/CVS_Stomach.sub ULABEL: Cough_Wal DLABEL: Dental_CVS LLABEL: Skincare_Wal diff --git a/documentation/readme.md b/documentation/readme.md index ac5b617ab..3a714a593 100644 --- a/documentation/readme.md +++ b/documentation/readme.md @@ -1,5 +1,177 @@ -This documentation is work-in-progress. +

Xtreme Firmware Documentation

-For now just read the file names and look for what you need to know. This will be updated to a nice readable document shortly! +

+ +

-- 31.12.2022 ClaraCrazy +

Install:

+ +**NOTE: If you are coming from a different FW, it is recommended to delete / clear your "apps" folder on the SD card prior to updating. This folder houses all the .fap files, which do not update to the correct API versions by default if old ones are present (Thanks flipper devs). This does `NOT` remove any of your saved files!** +

+ +

Web Updater / Mobile App / Automatic qFlipper Update

+ +- Go to the latest release from [The releases tab](https://github.com/ClaraCrazy/Flipper-Xtreme/releases/latest) +- Download the .tgz file +- Run your updater of choice with it + +- Enjoy! +
+ +----- +
+ +

Manual Update (Because qFlipper loves to break every now and then for no reason at all)

+ +- Download the latest release (.zip) from [The releases tab](https://github.com/ClaraCrazy/Flipper-Xtreme/releases/latest) +- Extract the archive. This is now your new Firmware folder +- Open [qFlipper](https://flipperzero.one/update), head to `SD/Update` and simply move the firmware folder there +- On the Flipper, hit the `Arrow Down` button, this will get you to the file menu. Hit `Arrow Left` once, and then simply search for your updates folder +- Inside that folder, select the Firmware you just moved onto it, and run the file thats simply called `Update` + +- Enjoy! + +---- + +
+

Build it yourself:

+ +```bash +To download the needed tools: +$ git clone --recursive https://github.com/ClaraCrazy/Flipper-Xtreme.git +$ cd Flipper-Xtreme/ + +To flash directly to the Flipper (Needs to be connected via USB, qFlipper closed) +$ ./fbt flash_usb + +To just compile firmware +$ ./fbt updater_package + +If building FAPS: +$ ./fbt fap_dist + +If building image assets: +$ ./fbt resources icons dolphin_ext +``` + +
+

Safe for work mode:

+ +**Enable SFW mode with the steps listed below** +
+ +- Navigate to the main screen +- Press the UP button on the Flipper +- Press the 'SFW Mode' toggle + +---- + +
+

Support the project

+ +**If you like Xtreme Firmware and wish to help out, we would love it if you contributed to the project ❤️** +
+ +- [Bunq - My bank](https://bunq.me/ClaraK) +- [Paypal](https://paypal.me/RdX2020) +- [Patreon](https://patreon.com/CynthiaLabs) +- `Monero`: 41kyWeeoVdK4quzQ4M9ikVGs6tCQCLfdx8jLExTNsAu2SF1QAyDqRdjfGM6EL8L9NpXwt89HJeAoGf1aoArk7nDr4AMMV4T + + + +---- + + +
+

Applications we use thanks to the awesome contributers and community ❤️

+ +## GPIO +- [Lightmeter](https://github.com/oleksiikutuzov/flipperzero-lightmeter) +- [Air Mouse](https://github.com/ginkage/FlippAirMouse/) +- [Wifi Marauder](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) +- [Wifi Deauther](https://github.com/Timmotools/flipperzero_esp8266_deautherv2) +- [IFTTT Virtual Button for ESP8266 (By Ferrazzi)](https://github.com/Ferrazzi/FlipperZero_IFTTT_Virtual_Button) +- [Flashlight (By xMasterX)](https://github.com/xMasterX/flipper-flashlight) +- [GPIO Reader 1](https://github.com/biotinker/flipperzero-gpioreader) +- [GPIO Reader 2](https://github.com/aureli1c/flipperzero_GPIO_read) +- [Sentry Safe](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin) +- [Distance Sensor](https://github.com/Sanqui/flipperzero-firmware/tree/59656ca5fb644e0d4484259986b86a0b963f323d/applications/hc_sr04) +- [Temperature Sensor](https://github.com/Mywk/FlipperTemperatureSensor) +- [i2c Tools](https://github.com/NaejEL/flipperzero-i2ctools) +- [GPS](https://github.com/ezod/flipperzero-gps) +- [Mouse Jacker](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker) +- [Sniffer](https://github.com/mothball187/flipperzero-nrf24/tree/main/nrfsniff) +- [Scanner](https://github.com/vad7/nrf24scan) +- [ColecoVision Controller](https://github.com/ezod/flipperzero-rc2014-coleco) + + +## Games +- [2048](https://github.com/eugene-kirzhanov/flipper-zero-2048-game) +- [Arkanoid](https://github.com/DarkFlippers/unleashed-firmware/tree/dev/applications/plugins/arkanoid) +- [BlackJack](https://github.com/teeebor/flipper_games) +- [Doom](https://github.com/p4nic4ttack/doom-flipper-zero/) +- Multi Dice - In-house +- [Flappy Bird](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) +- [Game 15](https://github.com/x27/flipperzero-game15) +- [Game of Life (Updated to work by tgxn) (By itsyourbedtime)](https://github.com/tgxn/flipperzero-firmware/blob/dev/applications/game_of_life/game_of_life.c) +- Heap defense - Author Unknown +- [Mandelbrot Set (By Possibly-Matt)](https://github.com/Possibly-Matt/flipperzero-firmware-wPlugins) +- [Minesweeper](https://github.com/panki27/minesweeper) +- [Snake](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/plugins/snake_game) +- [Solitaire](https://github.com/teeebor/flipper_games) +- [Tetris](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game) +- [Tic Tac Toe](https://github.com/gotnull/flipperzero-firmware-wPlugins/tree/420/applications/plugins/tictactoe_game) +- [Tamagotchi(By GMMan)](https://github.com/GMMan/flipperzero-tamagotch-p1) +- [Video Poker (By PixlEmly)](https://github.com/PixlEmly/flipperzero-firmware-testing/blob/420/applications/VideoPoker/poker.c) +- [Yatzee (By emfleak)](https://github.com/emfleak/flipperzero-yatzee) + + +## Misc +- [Authenticator (TOTP / HOTP)](https://github.com/akopachov/flipper-zero_authenticator) +- [Barcode Generator](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) +- [Caesar Cipher](https://github.com/panki27/caesar-cipher) +- Calculator - In house / notIntense +- [Counter](https://github.com/Krulknul/dolphin-counter) +- [Hex Viewer](https://github.com/QtRoS/flipper-zero-hex-viewer) +- [Mouse Jiggler](https://github.com/Jacob-Tate/flipperzero-firmware/blob/dev/applications/mouse_jiggler/mouse_jiggler.c) +- [Converter](https://github.com/theisolinearchip/flipperzero_stuff/tree/main/applications/multi_converter) +- [Vibrator](https://github.com/qqmajikpp/flipperzero-firmware-wPlugins/tree/420/applications/plugins/orgasmotron) +- [Paint](https://github.com/n-o-T-I-n-s-a-n-e) +- [UART Echo](https://github.com/flipperdevices/flipperzero-firmware/pull/831) +- [USB HID Autofire](https://github.com/pbek/usb_hid_autofire) +- [USB Keyboard & Mouse](https://github.com/huuck/FlipperZeroUSBKeyboard) / (https://github.com/DarkFlippers/unleashed-firmware) +- [Wii EC Analyzer](https://github.com/csBlueChip/FlipperZero_WiiEC) + + +## Music +- [BPM Tapper (By panki27)](https://github.com/panki27/bpm-tapper) +- [Metronome](https://github.com/panki27/Metronome) +- [Morse Code](https://github.com/DarkFlippers/unleashed-firmware/pull/144) +- Music Beeper - Author Unknown +- [Music Player](https://github.com/flipperdevices/flipperzero-firmware/pull/1189) +- [Ocarina](https://github.com/invalidna-me/flipperzero-ocarina) +- [Software Automatic Mouth aka SAM](https://github.com/ctoth/SAM) +- [Tuning Fork](https://github.com/besya/flipperzero-tuning-fork) +- [Music Tracker](https://github.com/DrZlo13/flipper-zero-music-tracker) + + +## Tools +- [Bluetooth Remote](https://github.com/flipperdevices/flipperzero-firmware/pull/1330) +- [Clock](https://github.com/kowalski7cc/flipperzero-firmware/tree/clock-v1) / In house +- [Countdown Timer](https://github.com/0w0mewo/fpz_cntdown_timer) +- [DAP Link](https://github.com/flipperdevices/flipperzero-firmware/pull/1897) +- [DTMF](https://github.com/litui/dtmf_dolphin) +- [Dolphin Backup & Restore](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) +- [iButton Fuzzer](https://github.com/DarkFlippers/unleashed-firmware) +- [NFC Magic](https://github.com/flipperdevices/flipperzero-firmware/pull/1966) +- [POCSAG Pager](https://github.com/xMasterX/flipper-pager) +- [Password Generator](https://github.com/anakod/flipper_passgen) +- [PicoPass](https://github.com/flipperdevices/flipperzero-firmware/pull/1366) +- [RFID Fuzzer](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/245) +- [Spectrum Analyzer](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) +- [Sub-Ghz Bruteforce](https://github.com/derskythe/flipperzero-subbrute/tree/master) +- [Sub-Ghz Playlist](https://github.com/darmiel/flipper-playlist) +- [Protocol Visualizer](https://github.com/antirez/protoview) + + +--- diff --git a/scripts/version.py b/scripts/version.py index 8eb38526f..f003cc256 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -14,7 +14,7 @@ class GitVersion: self.gitlist = [("commit", "rev-parse --short HEAD"), ("branch", "rev-parse --abbrev-ref") , ("branch_num", "rev-list -count HEAD")] def get_version_info(self): - commit = branch = branch_num = "XFW-0036_12282022" + commit = branch = branch_num = "XFW-0036" # We dont use an `or` in commands that we expect to fail. It will serve no function. # We also dont try;exept an entire block of code. This is bad practise. We only try the single part that we expect to fail!