mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 17:48:35 -07:00
Merge remote-tracking branch 'upstream/dev' into nfc-washcity
This commit is contained in:
@@ -155,6 +155,15 @@ App(
|
||||
sources=["plugins/supported_cards/zolotaya_korona.c"],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="hid_parser",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="hid_plugin_ep",
|
||||
targets=["f7"],
|
||||
requires=["nfc"],
|
||||
sources=["plugins/supported_cards/hid.c"],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="nfc_start",
|
||||
targets=["f7"],
|
||||
|
||||
@@ -52,9 +52,15 @@ static NfcCommand
|
||||
if(mf_ultralight_event->type == MfUltralightPollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
|
||||
const MfUltralightData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
uint32_t event = (data->pages_read == data->pages_total) ? NfcCustomEventPollerSuccess :
|
||||
NfcCustomEventPollerIncomplete;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, event);
|
||||
return NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
|
||||
const MfUltralightData* data =
|
||||
@@ -90,10 +96,55 @@ static NfcCommand
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
enum {
|
||||
NfcSceneMfUltralightReadMenuStateCardSearch,
|
||||
NfcSceneMfUltralightReadMenuStateCardFound,
|
||||
};
|
||||
|
||||
static void nfc_scene_read_setup_view(NfcApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcSceneRead);
|
||||
|
||||
if(state == NfcSceneMfUltralightReadMenuStateCardSearch) {
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_header(instance->popup, "Unlocking", 97, 15, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
instance->popup, "Apply card to\nFlipper's back", 97, 27, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup_set_header(instance->popup, "Don't move", 85, 27, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 12, 20, &A_Loading_24);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
bool unlocking =
|
||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneMfUltralightUnlockWarn);
|
||||
|
||||
uint32_t state = unlocking ? NfcSceneMfUltralightReadMenuStateCardSearch :
|
||||
NfcSceneMfUltralightReadMenuStateCardFound;
|
||||
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneRead, state);
|
||||
|
||||
nfc_scene_read_setup_view(instance);
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_ultralight, instance);
|
||||
}
|
||||
|
||||
bool nfc_scene_read_on_event_mf_ultralight(NfcApp* instance, uint32_t event) {
|
||||
if(event == NfcCustomEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneRead, NfcSceneMfUltralightReadMenuStateCardFound);
|
||||
nfc_scene_read_setup_view(instance);
|
||||
} else if((event == NfcCustomEventPollerIncomplete)) {
|
||||
notification_message(instance->notifications, &sequence_semi_success);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
|
||||
@@ -179,7 +230,7 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
.on_event = nfc_scene_read_on_event_mf_ultralight,
|
||||
},
|
||||
.scene_read_menu =
|
||||
{
|
||||
|
||||
@@ -146,8 +146,7 @@ static void nfc_protocol_support_scene_more_info_on_exit(NfcApp* instance) {
|
||||
|
||||
// SceneRead
|
||||
static void nfc_protocol_support_scene_read_on_enter(NfcApp* instance) {
|
||||
popup_set_header(
|
||||
instance->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop);
|
||||
popup_set_header(instance->popup, "Don't move", 85, 27, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 12, 23, &A_Loading_24);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
@@ -162,7 +161,7 @@ static void nfc_protocol_support_scene_read_on_enter(NfcApp* instance) {
|
||||
// Start poller with the appropriate callback
|
||||
nfc_protocol_support[protocol]->scene_read.on_enter(instance);
|
||||
|
||||
nfc_blink_detect_start(instance);
|
||||
nfc_blink_read_start(instance);
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
@@ -200,6 +199,10 @@ static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneMana
|
||||
instance->scene_manager, NfcSceneDetect);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventCardDetected) {
|
||||
const NfcProtocol protocol =
|
||||
instance->protocols_detected[instance->protocols_detected_selected_idx];
|
||||
consumed = nfc_protocol_support[protocol]->scene_read.on_event(instance, event.event);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
|
||||
@@ -223,7 +223,7 @@ void nfc_text_store_clear(NfcApp* nfc) {
|
||||
}
|
||||
|
||||
void nfc_blink_read_start(NfcApp* nfc) {
|
||||
notification_message(nfc->notifications, &sequence_blink_start_cyan);
|
||||
notification_message(nfc->notifications, &sequence_blink_start_yellow);
|
||||
}
|
||||
|
||||
void nfc_blink_emulate_start(NfcApp* nfc) {
|
||||
@@ -231,7 +231,7 @@ void nfc_blink_emulate_start(NfcApp* nfc) {
|
||||
}
|
||||
|
||||
void nfc_blink_detect_start(NfcApp* nfc) {
|
||||
notification_message(nfc->notifications, &sequence_blink_start_yellow);
|
||||
notification_message(nfc->notifications, &sequence_blink_start_cyan);
|
||||
}
|
||||
|
||||
void nfc_blink_stop(NfcApp* nfc) {
|
||||
|
||||
153
applications/main/nfc/plugins/supported_cards/hid.c
Normal file
153
applications/main/nfc/plugins/supported_cards/hid.c
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#define TAG "HID"
|
||||
|
||||
static const uint64_t hid_key = 0x484944204953;
|
||||
|
||||
bool hid_verify(Nfc* nfc) {
|
||||
bool verified = false;
|
||||
|
||||
do {
|
||||
const uint8_t verify_sector = 1;
|
||||
uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector);
|
||||
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);
|
||||
|
||||
MfClassicKey key = {};
|
||||
nfc_util_num2bytes(hid_key, COUNT_OF(key.data), key.data);
|
||||
|
||||
MfClassicAuthContext auth_ctx = {};
|
||||
MfClassicError error =
|
||||
mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
|
||||
|
||||
if(error != MfClassicErrorNone) {
|
||||
FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
|
||||
break;
|
||||
}
|
||||
|
||||
verified = true;
|
||||
} while(false);
|
||||
|
||||
return verified;
|
||||
}
|
||||
|
||||
static bool hid_read(Nfc* nfc, NfcDevice* device) {
|
||||
furi_assert(nfc);
|
||||
furi_assert(device);
|
||||
|
||||
bool is_read = false;
|
||||
|
||||
MfClassicData* data = mf_classic_alloc();
|
||||
nfc_device_copy_data(device, NfcProtocolMfClassic, data);
|
||||
|
||||
do {
|
||||
MfClassicType type = MfClassicType1k;
|
||||
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
|
||||
if(error != MfClassicErrorNone) break;
|
||||
|
||||
data->type = type;
|
||||
MfClassicDeviceKeys keys = {};
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
FURI_BIT_SET(keys.key_a_mask, i);
|
||||
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
FURI_BIT_SET(keys.key_b_mask, i);
|
||||
}
|
||||
|
||||
error = mf_classic_poller_sync_read(nfc, &keys, data);
|
||||
if(error != MfClassicErrorNone) {
|
||||
FURI_LOG_W(TAG, "Failed to read data");
|
||||
break;
|
||||
}
|
||||
|
||||
nfc_device_set_data(device, NfcProtocolMfClassic, data);
|
||||
|
||||
is_read = true;
|
||||
} while(false);
|
||||
|
||||
mf_classic_free(data);
|
||||
|
||||
return is_read;
|
||||
}
|
||||
|
||||
static uint8_t get_bit_length(const uint8_t* half_block) {
|
||||
uint8_t bitLength = 0;
|
||||
uint32_t* halves = (uint32_t*)half_block;
|
||||
if(halves[0] == 0) {
|
||||
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
|
||||
bitLength = 31 - leading0s;
|
||||
} else {
|
||||
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[0]));
|
||||
bitLength = 63 - leading0s;
|
||||
}
|
||||
|
||||
return bitLength;
|
||||
}
|
||||
|
||||
static uint64_t get_pacs_bits(const uint8_t* block, uint8_t bitLength) {
|
||||
// Remove sentinel bit from credential. Byteswapping to handle array of bytes vs 64bit value
|
||||
uint64_t sentinel = __builtin_bswap64(1ULL << bitLength);
|
||||
uint64_t swapped = 0;
|
||||
memcpy(&swapped, block, sizeof(uint64_t));
|
||||
swapped = __builtin_bswap64(swapped ^ sentinel);
|
||||
FURI_LOG_D(TAG, "PACS: (%d) %016llx", bitLength, swapped);
|
||||
return swapped;
|
||||
}
|
||||
|
||||
static bool hid_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
furi_assert(device);
|
||||
|
||||
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
||||
|
||||
bool parsed = false;
|
||||
|
||||
do {
|
||||
// verify key
|
||||
const uint8_t verify_sector = 1;
|
||||
MfClassicSectorTrailer* sec_tr =
|
||||
mf_classic_get_sector_trailer_by_sector(data, verify_sector);
|
||||
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
|
||||
if(key != hid_key) break;
|
||||
|
||||
// Currently doesn't support bit length > 63
|
||||
const uint8_t* credential_block = data->block[5].data + 8;
|
||||
|
||||
uint8_t bitLength = get_bit_length(credential_block);
|
||||
if(bitLength == 0) break;
|
||||
|
||||
uint64_t credential = get_pacs_bits(credential_block, bitLength);
|
||||
if(credential == 0) break;
|
||||
|
||||
furi_string_printf(parsed_data, "\e#HID Card\n%dbit\n%llx", bitLength, credential);
|
||||
|
||||
parsed = true;
|
||||
|
||||
} while(false);
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/* Actual implementation of app<>plugin interface */
|
||||
static const NfcSupportedCardsPlugin hid_plugin = {
|
||||
.protocol = NfcProtocolMfClassic,
|
||||
.verify = hid_verify,
|
||||
.read = hid_read,
|
||||
.parse = hid_parse,
|
||||
};
|
||||
|
||||
/* Plugin descriptor to comply with basic plugin specification */
|
||||
static const FlipperAppPluginDescriptor hid_plugin_descriptor = {
|
||||
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
|
||||
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
|
||||
.entry_point = &hid_plugin,
|
||||
};
|
||||
|
||||
/* Plugin entry point - must return a pointer to const descriptor */
|
||||
const FlipperAppPluginDescriptor* hid_plugin_ep() {
|
||||
return &hid_plugin_descriptor;
|
||||
}
|
||||
@@ -27,8 +27,7 @@
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Kazan"
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TAG "Metromoney"
|
||||
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Umarsh"
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TAG "Zolotaya Korona"
|
||||
|
||||
|
||||
@@ -3831,3 +3831,37 @@ ADC169F922CB
|
||||
# Volgograd (Russia) Volna transport cards keys
|
||||
2B787A063D5D
|
||||
D37C8F1793F7
|
||||
# Bandai Namco Passport [fka Banapassport] / Sega Aime Card
|
||||
6090D00632F5
|
||||
019761AA8082
|
||||
574343467632
|
||||
A99164400748
|
||||
62742819AD7C
|
||||
CC5075E42BA1
|
||||
B9DF35A0814C
|
||||
8AF9C718F23D
|
||||
58CD5C3673CB
|
||||
FC80E88EB88C
|
||||
7A3CDAD7C023
|
||||
30424C029001
|
||||
024E4E44001F
|
||||
ECBBFA57C6AD
|
||||
4757698143BD
|
||||
1D30972E6485
|
||||
F8526D1A8D6D
|
||||
1300EC8C7E80
|
||||
F80A65A87FFA
|
||||
DEB06ED4AF8E
|
||||
4AD96BF28190
|
||||
000390014D41
|
||||
0800F9917CB0
|
||||
730050555253
|
||||
4146D4A956C4
|
||||
131157FBB126
|
||||
E69DD9015A43
|
||||
337237F254D5
|
||||
9A8389F32FBF
|
||||
7B8FB4A7100B
|
||||
C8382A233993
|
||||
7B304F2A12A6
|
||||
FC9418BF788B
|
||||
|
||||
@@ -10,8 +10,8 @@ void nfc_scene_delete_success_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
||||
popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
|
||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_119x62);
|
||||
popup_set_header(popup, "Deleted", 80, 19, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, nfc);
|
||||
popup_set_callback(popup, nfc_scene_delete_success_popup_callback);
|
||||
|
||||
@@ -17,8 +17,9 @@ void nfc_scene_detect_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
popup_reset(instance->popup);
|
||||
popup_set_header(instance->popup, "Reading", 97, 15, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
instance->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
|
||||
instance->popup, "Apply card to\nFlipper's back", 97, 27, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@ void nfc_scene_exit_confirm_on_enter(void* context) {
|
||||
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Exit");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Stay");
|
||||
dialog_ex_set_header(dialog_ex, "Exit to NFC Menu?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Exit to NFC Menu?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(dialog_ex, "All unsaved data will be lost", 64, 12, AlignCenter, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_exit_confirm_dialog_callback);
|
||||
|
||||
|
||||
@@ -175,6 +175,16 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) {
|
||||
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_mf_classic_dict_attack_notify_read(NfcApp* instance) {
|
||||
const MfClassicData* mfc_data = nfc_poller_get_data(instance->poller);
|
||||
bool is_card_fully_read = mf_classic_is_card_read(mfc_data);
|
||||
if(is_card_fully_read) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
} else {
|
||||
notification_message(instance->notifications, &sequence_semi_success);
|
||||
}
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* instance = context;
|
||||
bool consumed = false;
|
||||
@@ -196,7 +206,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance);
|
||||
consumed = true;
|
||||
} else {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
nfc_scene_mf_classic_dict_attack_notify_read(instance);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
@@ -225,13 +235,13 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
|
||||
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance);
|
||||
} else {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
nfc_scene_mf_classic_dict_attack_notify_read(instance);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(state == DictAttackStateSystemDictInProgress) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
nfc_scene_mf_classic_dict_attack_notify_read(instance);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
|
||||
dolphin_deed(DolphinDeedNfcReadSuccess);
|
||||
consumed = true;
|
||||
|
||||
@@ -11,7 +11,7 @@ void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48);
|
||||
popup_set_icon(popup, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
popup,
|
||||
|
||||
@@ -12,8 +12,8 @@ void nfc_scene_mf_classic_update_initial_success_on_enter(void* context) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Updated!", 11, 20, AlignLeft, AlignBottom);
|
||||
popup_set_icon(popup, 48, 6, &I_DolphinDone_80x58);
|
||||
popup_set_header(popup, "Updated", 11, 20, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_scene_mf_classic_update_initial_success_popup_callback);
|
||||
|
||||
@@ -16,7 +16,7 @@ void nfc_scene_mf_classic_write_initial_fail_on_enter(void* context) {
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
|
||||
widget_add_string_multiline_element(
|
||||
|
||||
@@ -12,8 +12,8 @@ void nfc_scene_mf_classic_write_initial_success_on_enter(void* context) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_header(popup, "Success!", 75, 10, AlignLeft, AlignTop);
|
||||
popup_set_icon(popup, 0, 9, &I_DolphinSuccess_91x55);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_scene_mf_classic_write_initial_success_popup_callback);
|
||||
|
||||
@@ -16,7 +16,7 @@ void nfc_scene_mf_classic_wrong_card_on_enter(void* context) {
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
|
||||
widget_add_string_multiline_element(
|
||||
|
||||
@@ -40,7 +40,7 @@ void nfc_scene_mf_ultralight_unlock_warn_on_enter(void* context) {
|
||||
dialog_ex_set_header(dialog_ex, "Risky function!", 64, 4, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Wrong password\ncan block your\ncard.", 4, 18, AlignLeft, AlignTop);
|
||||
dialog_ex_set_icon(dialog_ex, 73, 20, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_icon(dialog_ex, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ void nfc_scene_mf_ultralight_write_fail_on_enter(void* context) {
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
|
||||
widget_add_string_multiline_element(
|
||||
|
||||
@@ -12,8 +12,8 @@ void nfc_scene_mf_ultralight_write_success_on_enter(void* context) {
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_icon(popup, 48, 6, &I_DolphinDone_80x58);
|
||||
popup_set_header(popup, "Successfully\nwritten", 5, 22, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_scene_mf_ultralight_write_success_popup_callback);
|
||||
|
||||
@@ -16,7 +16,7 @@ void nfc_scene_mf_ultralight_wrong_card_on_enter(void* context) {
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
|
||||
widget_add_string_multiline_element(
|
||||
|
||||
@@ -10,8 +10,8 @@ void nfc_scene_restore_original_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Original file\nrestored", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_icon(popup, 48, 6, &I_DolphinDone_80x58);
|
||||
popup_set_header(popup, "Original file\nrestored", 5, 22, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, nfc);
|
||||
popup_set_callback(popup, nfc_scene_restore_original_popup_callback);
|
||||
|
||||
@@ -12,9 +12,8 @@ void nfc_scene_retry_confirm_on_enter(void* context) {
|
||||
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Stay");
|
||||
dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(dialog_ex, "All unsaved data will be lost", 64, 12, AlignCenter, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback);
|
||||
|
||||
@@ -29,7 +28,11 @@ bool nfc_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == DialogExResultRight) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == DialogExResultLeft) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneDetect)) {
|
||||
if(scene_manager_has_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfUltralightUnlockWarn)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneDetect)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneDetect);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneRead)) {
|
||||
|
||||
@@ -10,8 +10,8 @@ void nfc_scene_save_success_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_icon(popup, 36, 5, &I_DolphinSaved_92x58);
|
||||
popup_set_header(popup, "Saved", 15, 19, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, nfc);
|
||||
popup_set_callback(popup, nfc_scene_save_success_popup_callback);
|
||||
|
||||
@@ -50,6 +50,7 @@ static void detect_reader_draw_callback(Canvas* canvas, void* model) {
|
||||
if(m->state == DetectReaderStateDone) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!");
|
||||
canvas_draw_icon(canvas, 20, 23, &I_check_big_20x17);
|
||||
} else {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting...");
|
||||
|
||||
Reference in New Issue
Block a user