Dev (#55)
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include <gui/modules/text_box.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
|
||||
#include <lib/nfc/nfc_types.h>
|
||||
#include <lib/nfc/nfc_worker.h>
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
#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) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
#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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -1,23 +1,103 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../../../settings/desktop_settings/desktop_settings_app.h"
|
||||
#include <lib/nfc/protocols/mifare_ultralight.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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, "");
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <toolbox/path.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "m-string.h"
|
||||
#include <gui/modules/validators.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "m-string.h"
|
||||
#include <gui/modules/validators.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,177 @@
|
||||
This documentation is work-in-progress.
|
||||
<h1 align="center"><code>Xtreme Firmware Documentation</code></h1>
|
||||
|
||||
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!
|
||||
<p align="center">
|
||||
<img src="https://user-images.githubusercontent.com/55334727/209031152-efbca66c-3fe0-41b5-a860-e0d7522a9279.png">
|
||||
</p>
|
||||
|
||||
- 31.12.2022 ClaraCrazy
|
||||
<h2 align="center">Install:</h2>
|
||||
|
||||
**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!**
|
||||
<br><br>
|
||||
|
||||
<h3> Web Updater / Mobile App / Automatic qFlipper Update</h3>
|
||||
|
||||
- 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!
|
||||
<br>
|
||||
|
||||
-----
|
||||
<br>
|
||||
|
||||
<h3> Manual Update (Because qFlipper loves to break every now and then for no reason at all)</h3>
|
||||
|
||||
- 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!
|
||||
|
||||
----
|
||||
|
||||
<br>
|
||||
<h2 align="center">Build it yourself:</h2>
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
<br>
|
||||
<h2 align="center">Safe for work mode:</h2>
|
||||
|
||||
**Enable SFW mode with the steps listed below**
|
||||
<br>
|
||||
|
||||
- Navigate to the main screen
|
||||
- Press the UP button on the Flipper
|
||||
- Press the 'SFW Mode' toggle
|
||||
|
||||
----
|
||||
|
||||
<br>
|
||||
<h2 align="center">Support the project</h2>
|
||||
|
||||
**If you like Xtreme Firmware and wish to help out, we would love it if you contributed to the project ❤️**
|
||||
<br>
|
||||
|
||||
- [Bunq - My bank](https://bunq.me/ClaraK)
|
||||
- [Paypal](https://paypal.me/RdX2020)
|
||||
- [Patreon](https://patreon.com/CynthiaLabs)
|
||||
- `Monero`: 41kyWeeoVdK4quzQ4M9ikVGs6tCQCLfdx8jLExTNsAu2SF1QAyDqRdjfGM6EL8L9NpXwt89HJeAoGf1aoArk7nDr4AMMV4T
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
<br>
|
||||
<h2 align="center">Applications we use thanks to the awesome contributers and community ❤️</h2>
|
||||
|
||||
## 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)
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -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!
|
||||
|
||||