[FL-2714] New NFC info screens (#1605)
* nfc: add scroll element for info * widget: format lines for scroll text element * widget: fix new line generation * widget: finish element text scroll * nfc: rework ultralight and NTAG info scenes * nfc: rework mf classic info screens * nfc: rework nfca info scenes * nfc: fix mf ultralight navigation * widget: add documentation * nfc: rework bank card infO * nfc: rework device info scene * nfc: fix incorrect atqa order * mf ultralight: remove unused function * widget: add mutex for model protection * widget: fix memory leak * nfc: rework delete scene * nfc: fix selected item in saved menu scene * widget: fix naming in text scroll element * nfc: fix navigation from delete success * nfc: add dictionary icon * widget: fix memory leak
This commit is contained in:
parent
b3d7583f9b
commit
560ea5f995
@ -162,6 +162,19 @@ void widget_add_text_box_element(
|
||||
widget_add_element(widget, text_box_element);
|
||||
}
|
||||
|
||||
void widget_add_text_scroll_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text) {
|
||||
furi_assert(widget);
|
||||
WidgetElement* text_scroll_element =
|
||||
widget_element_text_scroll_create(x, y, width, height, text);
|
||||
widget_add_element(widget, text_scroll_element);
|
||||
}
|
||||
|
||||
void widget_add_button_element(
|
||||
Widget* widget,
|
||||
GuiButtonType button_type,
|
||||
|
@ -105,6 +105,27 @@ void widget_add_text_box_element(
|
||||
const char* text,
|
||||
bool strip_to_dots);
|
||||
|
||||
/** Add Text Scroll Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x x coordinate
|
||||
* @param y y coordinate
|
||||
* @param width width to fit text
|
||||
* @param height height to fit text
|
||||
* @param[in] text Formatted text. Default format: align left, Secondary font.
|
||||
* The following formats are available:
|
||||
* "\e#Bold text" - sets bold font before until next '\n' symbol
|
||||
* "\ecBold text" - sets center horizontal align before until next '\n' symbol
|
||||
* "\erBold text" - sets right horizontal align before until next '\n' symbol
|
||||
*/
|
||||
void widget_add_text_scroll_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text);
|
||||
|
||||
/** Add Button Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
|
@ -29,6 +29,7 @@ struct WidgetElement {
|
||||
|
||||
// generic model holder
|
||||
void* model;
|
||||
FuriMutex* model_mutex;
|
||||
|
||||
// pointer to widget that hold our element
|
||||
Widget* parent;
|
||||
@ -80,3 +81,10 @@ WidgetElement* widget_element_frame_create(
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
||||
|
||||
WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text);
|
||||
|
@ -0,0 +1,245 @@
|
||||
#include "widget_element_i.h"
|
||||
#include <m-string.h>
|
||||
#include <gui/elements.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET (4)
|
||||
|
||||
typedef struct {
|
||||
Font font;
|
||||
Align horizontal;
|
||||
string_t text;
|
||||
} TextScrollLineArray;
|
||||
|
||||
ARRAY_DEF(TextScrollLineArray, TextScrollLineArray, M_POD_OPLIST)
|
||||
|
||||
typedef struct {
|
||||
TextScrollLineArray_t line_array;
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
string_t text;
|
||||
uint8_t scroll_pos_total;
|
||||
uint8_t scroll_pos_current;
|
||||
bool text_formatted;
|
||||
} WidgetElementTextScrollModel;
|
||||
|
||||
static bool
|
||||
widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, string_t text) {
|
||||
bool processed = false;
|
||||
|
||||
do {
|
||||
if(string_get_char(text, 0) != '\e') break;
|
||||
char ctrl_symbol = string_get_char(text, 1);
|
||||
if(ctrl_symbol == 'c') {
|
||||
line->horizontal = AlignCenter;
|
||||
} else if(ctrl_symbol == 'r') {
|
||||
line->horizontal = AlignRight;
|
||||
} else if(ctrl_symbol == '#') {
|
||||
line->font = FontPrimary;
|
||||
}
|
||||
string_right(text, 2);
|
||||
processed = true;
|
||||
} while(false);
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void widget_element_text_scroll_add_line(WidgetElement* element, TextScrollLineArray* line) {
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
TextScrollLineArray new_line;
|
||||
new_line.font = line->font;
|
||||
new_line.horizontal = line->horizontal;
|
||||
string_init_set(new_line.text, line->text);
|
||||
TextScrollLineArray_push_back(model->line_array, new_line);
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* element) {
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
TextScrollLineArray line_tmp;
|
||||
bool all_text_processed = false;
|
||||
string_init(line_tmp.text);
|
||||
bool reached_new_line = true;
|
||||
uint16_t total_height = 0;
|
||||
|
||||
while(!all_text_processed) {
|
||||
if(reached_new_line) {
|
||||
// Set default line properties
|
||||
line_tmp.font = FontSecondary;
|
||||
line_tmp.horizontal = AlignLeft;
|
||||
string_reset(line_tmp.text);
|
||||
// Process control symbols
|
||||
while(widget_element_text_scroll_process_ctrl_symbols(&line_tmp, model->text))
|
||||
;
|
||||
}
|
||||
// Set canvas font
|
||||
canvas_set_font(canvas, line_tmp.font);
|
||||
CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font);
|
||||
total_height += params->height;
|
||||
if(total_height > model->height) {
|
||||
model->scroll_pos_total++;
|
||||
}
|
||||
|
||||
uint8_t line_width = 0;
|
||||
uint16_t char_i = 0;
|
||||
while(true) {
|
||||
char next_char = string_get_char(model->text, char_i++);
|
||||
if(next_char == '\0') {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
total_height += params->leading_default - params->height;
|
||||
all_text_processed = true;
|
||||
break;
|
||||
} else if(next_char == '\n') {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
string_right(model->text, char_i);
|
||||
total_height += params->leading_default - params->height;
|
||||
reached_new_line = true;
|
||||
break;
|
||||
} else {
|
||||
line_width += canvas_glyph_width(canvas, next_char);
|
||||
if(line_width > model->width) {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
string_right(model->text, char_i - 1);
|
||||
string_reset(line_tmp.text);
|
||||
total_height += params->leading_default - params->height;
|
||||
reached_new_line = false;
|
||||
break;
|
||||
} else {
|
||||
string_push_back(line_tmp.text, next_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(line_tmp.text);
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
|
||||
furi_mutex_acquire(element->model_mutex, FuriWaitForever);
|
||||
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
if(!model->text_formatted) {
|
||||
widget_element_text_scroll_fill_lines(canvas, element);
|
||||
model->text_formatted = true;
|
||||
}
|
||||
|
||||
uint8_t y = model->y;
|
||||
uint8_t x = model->x;
|
||||
uint16_t curr_line = 0;
|
||||
if(TextScrollLineArray_size(model->line_array)) {
|
||||
TextScrollLineArray_it_t it;
|
||||
for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it);
|
||||
TextScrollLineArray_next(it), curr_line++) {
|
||||
if(curr_line < model->scroll_pos_current) continue;
|
||||
TextScrollLineArray* line = TextScrollLineArray_ref(it);
|
||||
CanvasFontParameters* params = canvas_get_font_params(canvas, line->font);
|
||||
if(y + params->descender > model->y + model->height) break;
|
||||
canvas_set_font(canvas, line->font);
|
||||
if(line->horizontal == AlignLeft) {
|
||||
x = model->x;
|
||||
} else if(line->horizontal == AlignCenter) {
|
||||
x = (model->x + model->width) / 2;
|
||||
} else if(line->horizontal == AlignRight) {
|
||||
x = model->x + model->width;
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, x, y, line->horizontal, AlignTop, string_get_cstr(line->text));
|
||||
y += params->leading_default;
|
||||
}
|
||||
// Draw scroll bar
|
||||
if(model->scroll_pos_total > 1) {
|
||||
elements_scrollbar_pos(
|
||||
canvas,
|
||||
model->x + model->width + WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET,
|
||||
model->y,
|
||||
model->height,
|
||||
model->scroll_pos_current,
|
||||
model->scroll_pos_total);
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(element->model_mutex);
|
||||
}
|
||||
|
||||
static bool widget_element_text_scroll_input(InputEvent* event, WidgetElement* element) {
|
||||
furi_assert(event);
|
||||
furi_assert(element);
|
||||
|
||||
furi_mutex_acquire(element->model_mutex, FuriWaitForever);
|
||||
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
bool consumed = false;
|
||||
|
||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||
if(event->key == InputKeyUp) {
|
||||
if(model->scroll_pos_current > 0) {
|
||||
model->scroll_pos_current--;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if((model->scroll_pos_total > 1) &&
|
||||
(model->scroll_pos_current < model->scroll_pos_total - 1)) {
|
||||
model->scroll_pos_current++;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(element->model_mutex);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_free(WidgetElement* text_scroll) {
|
||||
furi_assert(text_scroll);
|
||||
|
||||
WidgetElementTextScrollModel* model = text_scroll->model;
|
||||
TextScrollLineArray_it_t it;
|
||||
for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it);
|
||||
TextScrollLineArray_next(it)) {
|
||||
TextScrollLineArray* line = TextScrollLineArray_ref(it);
|
||||
string_clear(line->text);
|
||||
}
|
||||
TextScrollLineArray_clear(model->line_array);
|
||||
string_clear(model->text);
|
||||
free(text_scroll->model);
|
||||
furi_mutex_free(text_scroll->model_mutex);
|
||||
free(text_scroll);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text) {
|
||||
furi_assert(text);
|
||||
|
||||
// Allocate and init model
|
||||
WidgetElementTextScrollModel* model = malloc(sizeof(WidgetElementTextScrollModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->width = width - WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET;
|
||||
model->height = height;
|
||||
model->scroll_pos_current = 0;
|
||||
model->scroll_pos_total = 1;
|
||||
TextScrollLineArray_init(model->line_array);
|
||||
string_init_set_str(model->text, text);
|
||||
|
||||
WidgetElement* text_scroll = malloc(sizeof(WidgetElement));
|
||||
text_scroll->parent = NULL;
|
||||
text_scroll->draw = widget_element_text_scroll_draw;
|
||||
text_scroll->input = widget_element_text_scroll_input;
|
||||
text_scroll->free = widget_element_text_scroll_free;
|
||||
text_scroll->model = model;
|
||||
text_scroll->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
return text_scroll;
|
||||
}
|
@ -89,11 +89,6 @@ Nfc* nfc_alloc() {
|
||||
nfc->widget = widget_alloc();
|
||||
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget));
|
||||
|
||||
// Bank Card
|
||||
nfc->bank_card = bank_card_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card));
|
||||
|
||||
// Mifare Classic Dict Attack
|
||||
nfc->dict_attack = dict_attack_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -159,10 +154,6 @@ void nfc_free(Nfc* nfc) {
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
widget_free(nfc->widget);
|
||||
|
||||
// Bank Card
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard);
|
||||
bank_card_free(nfc->bank_card);
|
||||
|
||||
// Mifare Classic Dict Attack
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack);
|
||||
dict_attack_free(nfc->dict_attack);
|
||||
|
@ -25,8 +25,8 @@
|
||||
#include <lib/nfc/nfc_worker.h>
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||
#include <lib/nfc/parsers/nfc_supported_card.h>
|
||||
|
||||
#include "views/bank_card.h"
|
||||
#include "views/dict_attack.h"
|
||||
|
||||
#include <nfc/scenes/nfc_scene.h>
|
||||
@ -70,7 +70,6 @@ struct Nfc {
|
||||
ByteInput* byte_input;
|
||||
TextBox* text_box;
|
||||
Widget* widget;
|
||||
BankCard* bank_card;
|
||||
DictAttack* dict_attack;
|
||||
|
||||
const NfcGenerator* generator;
|
||||
@ -85,7 +84,6 @@ typedef enum {
|
||||
NfcViewByteInput,
|
||||
NfcViewTextBox,
|
||||
NfcViewWidget,
|
||||
NfcViewBankCard,
|
||||
NfcViewDictAttack,
|
||||
} NfcView;
|
||||
|
||||
|
@ -12,7 +12,10 @@ ADD_SCENE(nfc, save_name, SaveName)
|
||||
ADD_SCENE(nfc, save_success, SaveSuccess)
|
||||
ADD_SCENE(nfc, file_select, FileSelect)
|
||||
ADD_SCENE(nfc, emulate_uid, EmulateUid)
|
||||
ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess)
|
||||
ADD_SCENE(nfc, nfca_menu, NfcaMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
|
||||
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
|
||||
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth)
|
||||
@ -25,13 +28,13 @@ ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu)
|
||||
ADD_SCENE(nfc, mf_desfire_data, MfDesfireData)
|
||||
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
||||
ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess)
|
||||
ADD_SCENE(nfc, mf_classic_info, MfClassicInfo)
|
||||
ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
|
||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
||||
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
||||
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
||||
ADD_SCENE(nfc, device_info, DeviceInfo)
|
||||
ADD_SCENE(nfc, delete, Delete)
|
||||
@ -45,3 +48,4 @@ ADD_SCENE(nfc, rpc, Rpc)
|
||||
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
||||
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
||||
ADD_SCENE(nfc, detect_reader, DetectReader)
|
||||
ADD_SCENE(nfc, nfc_data_info, NfcDataInfo)
|
||||
|
@ -9,58 +9,43 @@ void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void
|
||||
|
||||
void nfc_scene_delete_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
|
||||
// Setup Custom Widget view
|
||||
char temp_str[64];
|
||||
snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name);
|
||||
widget_add_text_box_element(
|
||||
nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false);
|
||||
nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, string_get_cstr(temp_str), false);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
|
||||
nfc->widget, GuiButtonTypeLeft, "Cancel", nfc_scene_delete_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3]);
|
||||
} else if(data->uid_len == 7) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
}
|
||||
widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, temp_str);
|
||||
|
||||
const char* protocol_name = NULL;
|
||||
string_set_str(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
if(protocol == NfcDeviceProtocolEMV) {
|
||||
protocol_name = nfc_guess_protocol(protocol);
|
||||
string_set_str(temp_str, "EMV bank card");
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false);
|
||||
string_set_str(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true));
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_set_str(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type));
|
||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
string_set_str(temp_str, "MIFARE DESFire");
|
||||
} else {
|
||||
string_set_str(temp_str, "Unknown ISO tag");
|
||||
}
|
||||
if(protocol_name) {
|
||||
widget_add_string_element(
|
||||
nfc->widget, 10, 33, AlignLeft, AlignTop, FontSecondary, protocol_name);
|
||||
}
|
||||
// TODO change dinamically
|
||||
widget_add_string_element(nfc->widget, 118, 33, AlignRight, AlignTop, FontSecondary, "NFC-A");
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak);
|
||||
widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A");
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
@ -71,7 +56,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
return scene_manager_previous_scene(nfc->scene_manager);
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
if(nfc_device_delete(nfc->dev, true)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||
|
@ -26,7 +26,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
nfc->scene_manager, NfcSceneFileSelect);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
@ -1,11 +1,6 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
enum {
|
||||
NfcSceneDeviceInfoUid,
|
||||
NfcSceneDeviceInfoData,
|
||||
};
|
||||
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
@ -13,197 +8,65 @@ void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type,
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(result == DialogExResultLeft) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) {
|
||||
UNUSED(result);
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
|
||||
bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatMifareUl) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatBankCard);
|
||||
// Setup Custom Widget view
|
||||
widget_add_text_box_element(
|
||||
nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name, false);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
|
||||
if(data_display_supported) {
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
|
||||
}
|
||||
char temp_str[32];
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3]);
|
||||
} else if(data->uid_len == 7) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
}
|
||||
widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, temp_str);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
const char* protocol_name = NULL;
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
protocol_name = nfc_guess_protocol(protocol);
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false);
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type);
|
||||
}
|
||||
if(protocol_name) {
|
||||
widget_add_string_element(
|
||||
nfc->widget, 10, 32, AlignLeft, AlignTop, FontSecondary, protocol_name);
|
||||
}
|
||||
// TODO change dinamically
|
||||
widget_add_string_element(nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A");
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak);
|
||||
widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
|
||||
// Setup Data View
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Back");
|
||||
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(
|
||||
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
|
||||
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
EmvData* emv_data = &dev_data->emv_data;
|
||||
string_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
||||
string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data;
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = mf_df_data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
"%d application%s, %d file%s",
|
||||
n_apps,
|
||||
n_apps == 1 ? "" : "s",
|
||||
n_files,
|
||||
n_files == 1 ? "" : "s");
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
BankCard* bank_card = nfc->bank_card;
|
||||
bank_card_set_name(bank_card, emv_data->name);
|
||||
bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
|
||||
bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc);
|
||||
string_strim(temp_str);
|
||||
|
||||
// Add expiration date
|
||||
if(emv_data->exp_mon) {
|
||||
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
|
||||
string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
string_t display_str;
|
||||
string_init(display_str);
|
||||
if(emv_data->country_code) {
|
||||
// Parse currency code
|
||||
if((emv_data->currency_code)) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
// Parse country code
|
||||
if((emv_data->country_code)) {
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(
|
||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_printf(display_str, "Reg:%s", string_get_cstr(country_name));
|
||||
bank_card_set_country_name(bank_card, string_get_cstr(display_str));
|
||||
string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name));
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
if(emv_data->currency_code) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->country_code, currency_name)) {
|
||||
string_printf(display_str, "Cur:%s", string_get_cstr(currency_name));
|
||||
bank_card_set_currency_name(bank_card, string_get_cstr(display_str));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
string_clear(display_str);
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
|
||||
widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "More", nfc_scene_device_info_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == NfcSceneDeviceInfoData) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
@ -215,12 +78,4 @@ void nfc_scene_device_info_on_exit(void* context) {
|
||||
|
||||
// Clear views
|
||||
widget_reset(nfc->widget);
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
bank_card_clear(nfc->bank_card);
|
||||
}
|
||||
}
|
||||
|
54
applications/nfc/scenes/nfc_scene_emv_menu.c
Normal file
54
applications/nfc/scenes/nfc_scene_emv_menu.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_emv_menu_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_emv_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_emv_menu_submenu_callback, nfc);
|
||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_emv_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_emv_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||
// 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, NfcSceneEmvMenu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_emv_menu_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
@ -15,85 +15,48 @@ void nfc_scene_emv_read_success_widget_callback(
|
||||
void nfc_scene_emv_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup Custom Widget view
|
||||
// Add frame
|
||||
widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6);
|
||||
// Add buttons
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
// Add card name
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name);
|
||||
// Add card number
|
||||
string_t pan_str;
|
||||
string_init(pan_str);
|
||||
nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
||||
string_cat_printf(pan_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
}
|
||||
string_strim(pan_str);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, string_get_cstr(pan_str));
|
||||
string_clear(pan_str);
|
||||
// Parse country code
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if((emv_data->country_code) &&
|
||||
nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country));
|
||||
string_clear(disp_country);
|
||||
}
|
||||
string_clear(country_name);
|
||||
// Parse currency code
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if((emv_data->currency_code) &&
|
||||
nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget,
|
||||
121,
|
||||
23,
|
||||
AlignRight,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_currency));
|
||||
string_clear(disp_currency);
|
||||
}
|
||||
string_clear(currency_name);
|
||||
char temp_str[32];
|
||||
// Add ATQA
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
// Add UID
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
nfc_data->uid[0],
|
||||
nfc_data->uid[1],
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3]);
|
||||
widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
// Add SAK
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", nfc_data->sak);
|
||||
widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
string_strim(temp_str);
|
||||
|
||||
// Add expiration date
|
||||
if(emv_data->exp_mon) {
|
||||
char exp_str[16];
|
||||
snprintf(
|
||||
exp_str, sizeof(exp_str), "Exp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str);
|
||||
string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
// Parse currency code
|
||||
if((emv_data->currency_code)) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
// Parse country code
|
||||
if((emv_data->country_code)) {
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(
|
||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name));
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
|
||||
widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
@ -107,10 +70,7 @@ bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event)
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
|
@ -6,6 +6,7 @@ void nfc_scene_file_select_on_enter(void* context) {
|
||||
// Process file_select return
|
||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
||||
if(nfc_file_select(nfc->dev)) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
||||
|
@ -1,72 +0,0 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_classic_info_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_classic_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
string_t str_tmp;
|
||||
string_init(str_tmp);
|
||||
|
||||
// Setup view
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, mf_classic_get_type_str(mf_data->type));
|
||||
widget_add_string_element(
|
||||
widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)");
|
||||
string_printf(str_tmp, "UID:");
|
||||
for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) {
|
||||
string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(
|
||||
str_tmp,
|
||||
"ATQA: %02X %02X SAK: %02X",
|
||||
dev_data->nfc_data.atqa[0],
|
||||
dev_data->nfc_data.atqa[1],
|
||||
dev_data->nfc_data.sak);
|
||||
widget_add_string_element(
|
||||
widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
||||
string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 55, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
|
||||
string_clear(str_tmp);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_info_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(nfc->widget);
|
||||
}
|
@ -34,6 +34,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
||||
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);
|
||||
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
|
@ -17,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
string_t str_tmp;
|
||||
string_init(str_tmp);
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
@ -29,48 +27,27 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc);
|
||||
|
||||
string_t temp_str;
|
||||
if(string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
widget_add_text_box_element(
|
||||
nfc->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
32,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
string_get_cstr(nfc->dev->dev_data.parsed_data),
|
||||
true);
|
||||
string_init_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
widget_add_string_element(
|
||||
widget,
|
||||
0,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
mf_classic_get_type_str(mf_data->type));
|
||||
widget_add_string_element(
|
||||
widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)");
|
||||
string_printf(str_tmp, "UID:");
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) {
|
||||
string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
||||
string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total);
|
||||
string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total);
|
||||
}
|
||||
|
||||
string_clear(str_tmp);
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulateUid,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) {
|
||||
@ -16,6 +18,15 @@ void nfc_scene_mf_desfire_menu_on_enter(void* context) {
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate UID",
|
||||
SubmenuIndexEmulateUid,
|
||||
nfc_scene_mf_desfire_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_desfire_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu));
|
||||
|
||||
@ -35,6 +46,12 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event)
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulateUid) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,90 +1,85 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
|
||||
|
||||
enum {
|
||||
MfDesfireReadSuccessStateShowUID,
|
||||
MfDesfireReadSuccessStateShowData,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) {
|
||||
void nfc_scene_mf_desfire_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_center_button_text(dialog_ex, "Data");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||
dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21);
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
// Prepare string for data display
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
|
||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
string_cat_printf(temp_str, "\n%d", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
string_push_back(temp_str, '+');
|
||||
}
|
||||
string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
|
||||
// TODO rework info view
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
NFC_SCENE_READ_SUCCESS_SHIFT "Mifare DESFire\n" NFC_SCENE_READ_SUCCESS_SHIFT
|
||||
"%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n"
|
||||
"%d application%s, %d file%s",
|
||||
1 << (data->version.sw_storage >> 1),
|
||||
(data->version.sw_storage & 1) ? "+" : "",
|
||||
data->free_memory ? data->free_memory->bytes : 0,
|
||||
n_apps,
|
||||
n_apps == 1 ? "" : "s",
|
||||
n_files,
|
||||
n_files == 1 ? "" : "s");
|
||||
dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_desfire_read_success_dialog_callback);
|
||||
// Add text scroll element
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
// Add button elements
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_desfire_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_desfire_read_success_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData);
|
||||
consumed = true;
|
||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) {
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == MfDesfireReadSuccessStateShowData) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager,
|
||||
NfcSceneMfDesfireReadSuccess,
|
||||
MfDesfireReadSuccessStateShowUID);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
@ -94,5 +89,5 @@ void nfc_scene_mf_desfire_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean dialog
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
widget_reset(nfc->widget);
|
||||
}
|
||||
|
32
applications/nfc/scenes/nfc_scene_mf_ultralight_data.c
Normal file
32
applications/nfc/scenes/nfc_scene_mf_ultralight_data.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_data_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_data_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_data_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean view
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
}
|
@ -4,6 +4,7 @@ enum SubmenuIndex {
|
||||
SubmenuIndexUnlock,
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) {
|
||||
@ -33,6 +34,9 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
|
||||
SubmenuIndexEmulate,
|
||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu));
|
||||
|
||||
@ -56,6 +60,9 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even
|
||||
} else if(event.event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
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, NfcSceneMfUltralightMenu, event.event);
|
||||
|
||||
|
@ -1,11 +1,6 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum {
|
||||
ReadMifareUlStateShowInfo,
|
||||
ReadMifareUlStateShowData,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
@ -31,12 +26,6 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
"Retry",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeCenter,
|
||||
"Data",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
@ -44,71 +33,38 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_t data_str;
|
||||
string_init_printf(data_str, "UID:");
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(data_str, " %02X", data->uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
string_printf(
|
||||
data_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
widget_add_string_element(
|
||||
widget, 0, 24, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||
widget_add_string_element(
|
||||
widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-protected pages!");
|
||||
string_cat_printf(temp_str, "\nPassword-protected pages!");
|
||||
}
|
||||
string_clear(data_str);
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
// Setup TextBox view
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(
|
||||
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) {
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeCenter) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == ReadMifareUlStateShowData) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
@ -117,8 +73,6 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv
|
||||
void nfc_scene_mf_ultralight_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean views
|
||||
// Clean view
|
||||
widget_reset(nfc->widget);
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
}
|
||||
|
133
applications/nfc/scenes/nfc_scene_nfc_data_info.c
Normal file
133
applications/nfc/scenes/nfc_scene_nfc_data_info.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_nfc_data_info_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_nfc_data_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Widget* widget = nfc->widget;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
NfcProtocol protocol = dev_data->protocol;
|
||||
uint8_t text_scroll_height = 0;
|
||||
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
||||
text_scroll_height = 52;
|
||||
} else {
|
||||
text_scroll_height = 64;
|
||||
}
|
||||
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
// Set name if present
|
||||
if(nfc->dev->dev_name[0] != '\0') {
|
||||
string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name);
|
||||
}
|
||||
|
||||
// Set tag type
|
||||
if(protocol == NfcDeviceProtocolEMV) {
|
||||
string_cat_printf(temp_str, "\e#EMV Bank Card\n");
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
string_cat_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true));
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type));
|
||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||
} else {
|
||||
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';
|
||||
string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
|
||||
string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
|
||||
|
||||
// Set application specific data
|
||||
if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
MifareDesfireData* data = &dev_data->mf_df_data;
|
||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
string_cat_printf(temp_str, "\n%d", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
string_push_back(temp_str, '+');
|
||||
}
|
||||
string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* data = &dev_data->mf_ul_data;
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read %d/%d", data->data_read / 4, data->data_size / 4);
|
||||
if(data->data_size > data->data_read) {
|
||||
string_cat_printf(temp_str, "\nPassword-protected");
|
||||
}
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
MfClassicData* data = &dev_data->mf_classic_data;
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found);
|
||||
string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total);
|
||||
string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total);
|
||||
}
|
||||
|
||||
// Add text scroll widget
|
||||
widget_add_text_scroll_element(
|
||||
widget, 0, 0, 128, text_scroll_height, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireApp);
|
||||
consumed = true;
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfc_data_info_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
widget_reset(nfc->widget);
|
||||
}
|
62
applications/nfc/scenes/nfc_scene_nfca_menu.c
Normal file
62
applications/nfc/scenes/nfc_scene_nfca_menu.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSaveUid,
|
||||
SubmenuIndexEmulateUid,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_nfca_menu_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "Save UID", SubmenuIndexSaveUid, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Emulate UID", SubmenuIndexEmulateUid, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcaMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSaveUid) {
|
||||
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 == SubmenuIndexEmulateUid) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
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, NfcSceneNfcaMenu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_menu_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
72
applications/nfc/scenes/nfc_scene_nfca_read_success.c
Normal file
72
applications/nfc/scenes/nfc_scene_nfca_read_success.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_nfca_read_success_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_nfca_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
string_t temp_str;
|
||||
string_init_set_str(temp_str, "\e#Unknown ISO tag\n");
|
||||
|
||||
char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3';
|
||||
string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]);
|
||||
string_cat_printf(temp_str, " SAK: %02X", data->sak);
|
||||
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfca_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfca_read_success_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfca_read_success_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 == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(nfc->widget);
|
||||
}
|
@ -59,11 +59,14 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if((event.event == NfcWorkerEventReadUidNfcB) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcF) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcV) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcA)) {
|
||||
(event.event == NfcWorkerEventReadUidNfcV)) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadUidNfcA) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfUltralight) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
|
@ -16,44 +16,26 @@ void nfc_scene_read_card_success_widget_callback(
|
||||
void nfc_scene_read_card_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
string_t data_str;
|
||||
string_t uid_str;
|
||||
string_init(data_str);
|
||||
string_init(uid_str);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
Widget* widget = nfc->widget;
|
||||
string_set_str(data_str, nfc_get_dev_type(data->type));
|
||||
string_set_str(uid_str, "UID:");
|
||||
string_set_str(temp_str, nfc_get_dev_type(data->type));
|
||||
widget_add_string_element(
|
||||
widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(temp_str));
|
||||
string_set_str(temp_str, "UID:");
|
||||
for(uint8_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(uid_str, " %02X", data->uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(temp_str));
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc);
|
||||
if(data->type == FuriHalNfcTypeA) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "Save", nfc_scene_read_card_success_widget_callback, nfc);
|
||||
widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21);
|
||||
widget_add_string_element(
|
||||
widget, 37, 12, AlignLeft, AlignBottom, FontPrimary, string_get_cstr(data_str));
|
||||
string_printf(
|
||||
data_str, "ATQA: %02X%02X\nSAK: %02X", data->atqa[0], data->atqa[1], data->sak);
|
||||
widget_add_string_multiline_element(
|
||||
widget, 37, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, string_get_cstr(uid_str));
|
||||
} else {
|
||||
widget_add_string_element(
|
||||
widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(data_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(uid_str));
|
||||
}
|
||||
|
||||
string_clear(data_str);
|
||||
string_clear(uid_str);
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
@ -65,11 +47,6 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
@ -44,8 +44,6 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
if(nfc->dev->shadow_file_exist) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@ -58,12 +56,15 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
submenu, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
@ -87,7 +88,18 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
bool application_info_present = false;
|
||||
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
application_info_present = true;
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
|
||||
}
|
||||
|
||||
if(application_info_present) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm);
|
||||
|
@ -1,80 +0,0 @@
|
||||
#include "bank_card.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
#include <m-string.h>
|
||||
|
||||
struct BankCard {
|
||||
Widget* widget;
|
||||
};
|
||||
|
||||
BankCard* bank_card_alloc() {
|
||||
BankCard* bank_card = malloc(sizeof(BankCard));
|
||||
bank_card->widget = widget_alloc();
|
||||
return bank_card;
|
||||
}
|
||||
|
||||
void bank_card_free(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
widget_free(bank_card->widget);
|
||||
free(bank_card);
|
||||
}
|
||||
|
||||
View* bank_card_get_view(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
return widget_get_view(bank_card->widget);
|
||||
}
|
||||
|
||||
void bank_card_clear(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
widget_reset(bank_card->widget);
|
||||
}
|
||||
|
||||
void bank_card_set_name(BankCard* bank_card, char* name) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name);
|
||||
}
|
||||
|
||||
void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(number);
|
||||
string_t num_str;
|
||||
string_init(num_str);
|
||||
for(uint8_t i = 0; i < len; i += 2) {
|
||||
string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]);
|
||||
}
|
||||
// Add number
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str));
|
||||
string_clear(num_str);
|
||||
// Add icon
|
||||
widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13);
|
||||
// Add frame
|
||||
widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6);
|
||||
}
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(callback);
|
||||
widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context);
|
||||
}
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
|
||||
furi_assert(bank_card);
|
||||
char exp_date_str[16];
|
||||
snprintf(exp_date_str, sizeof(exp_date_str), "Exp: %02X/%02X", mon, year);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
|
||||
}
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name) {
|
||||
furi_assert(bank_card);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name);
|
||||
}
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) {
|
||||
furi_assert(bank_card);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
typedef struct BankCard BankCard;
|
||||
|
||||
BankCard* bank_card_alloc();
|
||||
|
||||
void bank_card_free(BankCard* bank_card);
|
||||
|
||||
void bank_card_clear(BankCard* bank_card);
|
||||
|
||||
View* bank_card_get_view(BankCard* bank_card);
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context);
|
||||
|
||||
void bank_card_set_name(BankCard* bank_card, char* name);
|
||||
|
||||
void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len);
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name);
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name);
|
BIN
assets/icons/NFC/Keychain.png
Normal file
BIN
assets/icons/NFC/Keychain.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -1217,6 +1217,7 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) {
|
||||
void nfc_device_clear(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
|
||||
nfc_device_set_name(dev, "");
|
||||
nfc_device_data_clear(&dev->dev_data);
|
||||
dev->format = NfcDeviceSaveFormatUid;
|
||||
string_reset(dev->load_path);
|
||||
|
@ -143,7 +143,7 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FuriHalNfcTxRxCont
|
||||
if(nfc_supported_card[i].verify(nfc_worker, tx_rx)) {
|
||||
if(nfc_supported_card[i].read(nfc_worker, tx_rx)) {
|
||||
read_success = true;
|
||||
nfc_supported_card[i].parse(nfc_worker);
|
||||
nfc_supported_card[i].parse(nfc_worker->dev_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,17 @@ NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = {
|
||||
.parse = troyka_parser_parse,
|
||||
},
|
||||
};
|
||||
|
||||
bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data) {
|
||||
furi_assert(dev_data);
|
||||
|
||||
bool card_parsed = false;
|
||||
for(size_t i = 0; i < COUNT_OF(nfc_supported_card); i++) {
|
||||
if(nfc_supported_card[i].parse(dev_data)) {
|
||||
card_parsed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return card_parsed;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
#include "../nfc_worker.h"
|
||||
#include "../nfc_device.h"
|
||||
|
||||
#include <m-string.h>
|
||||
|
||||
@ -15,7 +16,7 @@ typedef bool (*NfcSupportedCardVerify)(NfcWorker* nfc_worker, FuriHalNfcTxRxCont
|
||||
|
||||
typedef bool (*NfcSupportedCardRead)(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
|
||||
|
||||
typedef bool (*NfcSupportedCardParse)(NfcWorker* nfc_worker);
|
||||
typedef bool (*NfcSupportedCardParse)(NfcDeviceData* dev_data);
|
||||
|
||||
typedef struct {
|
||||
NfcProtocol protocol;
|
||||
@ -25,3 +26,5 @@ typedef struct {
|
||||
} NfcSupportedCard;
|
||||
|
||||
extern NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd];
|
||||
|
||||
bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data);
|
||||
|
@ -49,23 +49,31 @@ bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
|
||||
return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16;
|
||||
}
|
||||
|
||||
bool troyka_parser_parse(NfcWorker* nfc_worker) {
|
||||
MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
|
||||
uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5];
|
||||
uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25;
|
||||
temp_ptr = &data->block[8 * 4].value[3];
|
||||
uint32_t number = 0;
|
||||
for(size_t i = 0; i < 4; i++) {
|
||||
number <<= 8;
|
||||
number |= temp_ptr[i];
|
||||
}
|
||||
number >>= 4;
|
||||
bool troyka_parser_parse(NfcDeviceData* dev_data) {
|
||||
MfClassicData* data = &dev_data->mf_classic_data;
|
||||
bool troyka_parsed = false;
|
||||
|
||||
string_printf(
|
||||
nfc_worker->dev_data->parsed_data,
|
||||
"Troyka Transport card\nNumber: %ld\nBalance: %d rub",
|
||||
number,
|
||||
balance);
|
||||
do {
|
||||
// Verify key
|
||||
MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8);
|
||||
uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6);
|
||||
if(key != troyka_keys[8].key_a) break;
|
||||
|
||||
return true;
|
||||
// Parse data
|
||||
uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5];
|
||||
uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25;
|
||||
temp_ptr = &data->block[8 * 4].value[3];
|
||||
uint32_t number = 0;
|
||||
for(size_t i = 0; i < 4; i++) {
|
||||
number <<= 8;
|
||||
number |= temp_ptr[i];
|
||||
}
|
||||
number >>= 4;
|
||||
|
||||
string_printf(
|
||||
dev_data->parsed_data, "\e#Troyka\nNum: %ld\nBalance: %d rur.", number, balance);
|
||||
troyka_parsed = true;
|
||||
} while(false);
|
||||
|
||||
return troyka_parsed;
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
|
||||
|
||||
bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
|
||||
|
||||
bool troyka_parser_parse(NfcWorker* nfc_worker);
|
||||
bool troyka_parser_parse(NfcDeviceData* dev_data);
|
||||
|
@ -191,7 +191,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint
|
||||
}
|
||||
|
||||
if(pack != NULL) {
|
||||
*pack = (tx_rx->rx_data[0] << 8) | tx_rx->rx_data[1];
|
||||
*pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0];
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Auth success. Password: %08X. PACK: %04X", key, *pack);
|
||||
@ -697,48 +697,6 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData*
|
||||
return counter_read == (is_single_counter ? 1 : 3);
|
||||
}
|
||||
|
||||
int16_t mf_ultralight_get_authlim(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
MfUltralightReader* reader,
|
||||
MfUltralightData* data) {
|
||||
mf_ultralight_read_version(tx_rx, reader, data);
|
||||
if(!(reader->supported_features & MfUltralightSupportAuth)) {
|
||||
// No authentication
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint8_t config_pages_index;
|
||||
if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) {
|
||||
config_pages_index = reader->pages_to_read - 4;
|
||||
} else if(
|
||||
data->type >= MfUltralightTypeNTAGI2CPlus1K &&
|
||||
data->type <= MfUltralightTypeNTAGI2CPlus1K) {
|
||||
config_pages_index = 0xe3;
|
||||
} else {
|
||||
// No config pages
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(!mf_ultralight_read_pages_direct(tx_rx, config_pages_index, data->data)) {
|
||||
// Config pages are not readable due to protection
|
||||
return -1;
|
||||
}
|
||||
|
||||
MfUltralightConfigPages* config_pages = (MfUltralightConfigPages*)&data->data;
|
||||
if(config_pages->auth0 >= reader->pages_to_read) {
|
||||
// Authentication is not configured
|
||||
return -2;
|
||||
}
|
||||
|
||||
int16_t authlim = config_pages->access.authlim;
|
||||
if(authlim > 0 && data->type >= MfUltralightTypeNTAGI2CPlus1K &&
|
||||
data->type <= MfUltralightTypeNTAGI2CPlus2K) {
|
||||
authlim = 1 << authlim;
|
||||
}
|
||||
|
||||
return authlim;
|
||||
}
|
||||
|
||||
bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) {
|
||||
uint8_t flag_read = 0;
|
||||
|
||||
|
@ -56,13 +56,6 @@ typedef enum {
|
||||
MfUltralightTypeNum,
|
||||
} MfUltralightType;
|
||||
|
||||
typedef enum {
|
||||
MfUltralightAuthLimitUnknown,
|
||||
MfUltralightAuthLimitNotSupported,
|
||||
MfUltralightAuthLimitConfigured,
|
||||
MfUltralightAuthLimitNotConfigured,
|
||||
} MfUltralightAuthLimit;
|
||||
|
||||
typedef enum {
|
||||
MfUltralightSupportNone = 0,
|
||||
MfUltralightSupportFastRead = 1 << 0,
|
||||
@ -245,11 +238,6 @@ bool mf_ul_prepare_emulation_response(
|
||||
uint32_t* data_type,
|
||||
void* context);
|
||||
|
||||
int16_t mf_ultralight_get_authlim(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
MfUltralightReader* reader,
|
||||
MfUltralightData* data);
|
||||
|
||||
uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data);
|
||||
|
||||
uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data);
|
||||
|
Loading…
Reference in New Issue
Block a user