[FL-1547], [FL-1500] NFC app v1 (#593)

* nfc: remove mifare read debug view and scene
* nfc: change mifare ultralight data structure
* mifare_ultralight: add more commands
* nfc: add emulate mifare ul scene
* nfc: rework data structures, remove debug scenes and views
* nfc: add read emv scenes
* nfc: mifare emulation wip
* nfc cli: increase detecting time
* nfc: save nfc files with new format
* nfc: store Mifare Ultralight
* nfc: start loading mifare ultralight
* nfc: add delete scenes
* nfc: add edit UID and name
* nfc: finish parsing uid and mifare ul data
* nfc: delete success fix
* gui_widget: introduce GuiWidget
* gui_widget: add string element
* gui_widget: add button element
* gui_widget: move free elements into gui_widget
* nfc: rework info scene with GuiWidget
* nfc: rework device info scene
* nfc: rework delete scene gui
* nfc: add compatible script support
* nfc: rework emv reading scenes
* nfc: rework bank card save
* nfc: add bank card custom view
* gui_widget: add icon element
* nfc: add icon to bank card
* nfc: start worker after switching view

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich 2021-07-22 09:05:07 +03:00 committed by GitHub
parent 7ca89256eb
commit 49af516ec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 2188 additions and 1059 deletions

View file

@ -0,0 +1,84 @@
#include "gui_element_i.h"
#include "gui_element_button.h"
#include "gui_widget.h"
#include <gui/elements.h>
#include <m-string.h>
typedef struct {
GuiButtonType button_type;
string_t text;
ButtonCallback callback;
void* context;
} GuiButtonModel;
static void gui_button_draw(Canvas* canvas, GuiElement* element) {
furi_assert(canvas);
furi_assert(element);
GuiButtonModel* model = element->model;
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
if(model->button_type == GuiButtonTypeLeft) {
elements_button_left(canvas, string_get_cstr(model->text));
} else if(model->button_type == GuiButtonTypeRight) {
elements_button_right(canvas, string_get_cstr(model->text));
} else if(model->button_type == GuiButtonTypeCenter) {
elements_button_center(canvas, string_get_cstr(model->text));
}
}
static bool gui_button_input(InputEvent* event, GuiElement* element) {
GuiButtonModel* model = element->model;
bool consumed = false;
if((event->type == InputTypeShort) && model->callback) {
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
model->callback(model->button_type, model->context);
consumed = true;
} else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) {
model->callback(model->button_type, model->context);
consumed = true;
} else if((model->button_type == GuiButtonTypeCenter) && (event->key == InputKeyOk)) {
model->callback(model->button_type, model->context);
consumed = true;
}
}
return consumed;
}
static void gui_button_free(GuiElement* gui_button) {
furi_assert(gui_button);
GuiButtonModel* model = gui_button->model;
if(gui_button->parent != NULL) {
// TODO deattach element
}
string_clear(model->text);
free(gui_button->model);
free(gui_button);
}
GuiElement* gui_button_create(
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context) {
// Allocate and init model
GuiButtonModel* model = furi_alloc(sizeof(GuiButtonModel));
model->button_type = button_type;
model->callback = callback;
model->context = context;
string_init_set_str(model->text, text);
// Allocate and init Element
GuiElement* gui_button = furi_alloc(sizeof(GuiElement));
gui_button->parent = NULL;
gui_button->input = gui_button_input;
gui_button->draw = gui_button_draw;
gui_button->free = gui_button_free;
gui_button->model = model;
return gui_button;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
typedef struct GuiElement GuiElement;
typedef enum {
GuiButtonTypeLeft,
GuiButtonTypeCenter,
GuiButtonTypeRight,
} GuiButtonType;
typedef void (*ButtonCallback)(GuiButtonType button, void* context);
/** Allocate Button Element
* @param button_type GuiButtonType instance
* @param text text on allocated button
* @param callback ButtonCallback instance
* @param context pointer to context
*/
GuiElement* gui_button_create(
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context);

View file

@ -0,0 +1,21 @@
#pragma once
#include <furi.h>
#include <gui/view.h>
typedef struct GuiElement GuiElement;
typedef struct GuiWidget GuiWidget;
struct GuiElement {
// generic draw and input callbacks
void (*draw)(Canvas* canvas, GuiElement* element);
bool (*input)(InputEvent* event, GuiElement* element);
// free callback
void (*free)(GuiElement* element);
// generic model holder
void* model;
// pointer to widget that hold our element
GuiWidget* parent;
};

View file

@ -0,0 +1,51 @@
#include "gui_element_i.h"
#include "gui_element_icon.h"
#include "gui_widget.h"
#include <m-string.h>
typedef struct {
uint8_t x;
uint8_t y;
const Icon* icon;
} GuiIconModel;
static void gui_icon_draw(Canvas* canvas, GuiElement* element) {
furi_assert(canvas);
furi_assert(element);
GuiIconModel* model = element->model;
if(model->icon) {
canvas_draw_icon(canvas, model->x, model->y, model->icon);
}
}
static void gui_icon_free(GuiElement* gui_icon) {
furi_assert(gui_icon);
if(gui_icon->parent != NULL) {
// TODO deattach element
}
free(gui_icon->model);
free(gui_icon);
}
GuiElement* gui_icon_create(uint8_t x, uint8_t y, const Icon* icon) {
furi_assert(icon);
// Allocate and init model
GuiIconModel* model = furi_alloc(sizeof(GuiIconModel));
model->x = x;
model->y = y;
model->icon = icon;
// Allocate and init Element
GuiElement* gui_icon = furi_alloc(sizeof(GuiElement));
gui_icon->parent = NULL;
gui_icon->input = NULL;
gui_icon->draw = gui_icon_draw;
gui_icon->free = gui_icon_free;
gui_icon->model = model;
return gui_icon;
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <gui/canvas.h>
typedef struct GuiElement GuiElement;
/** Allocate GuiElement element
* @param x - x coordinate
* @param y - y coordinate
* @param icon Icon instance
* @return GuiElement instance
*/
GuiElement* gui_icon_create(uint8_t x, uint8_t y, const Icon* icon);

View file

@ -0,0 +1,72 @@
#include "gui_element_i.h"
#include "gui_element_string.h"
#include "gui_widget.h"
#include <m-string.h>
typedef struct {
uint8_t x;
uint8_t y;
Align horizontal;
Align vertical;
Font font;
string_t text;
} GuiStringModel;
static void gui_string_draw(Canvas* canvas, GuiElement* element) {
furi_assert(canvas);
furi_assert(element);
GuiStringModel* model = element->model;
if(string_size(model->text)) {
canvas_set_font(canvas, model->font);
canvas_draw_str_aligned(
canvas,
model->x,
model->y,
model->horizontal,
model->vertical,
string_get_cstr(model->text));
}
}
static void gui_string_free(GuiElement* gui_string) {
furi_assert(gui_string);
GuiStringModel* model = gui_string->model;
if(gui_string->parent != NULL) {
// TODO deattach element
}
string_clear(model->text);
free(gui_string->model);
free(gui_string);
}
GuiElement* gui_string_create(
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text) {
furi_assert(text);
// Allocate and init model
GuiStringModel* model = furi_alloc(sizeof(GuiStringModel));
model->x = x;
model->y = y;
model->horizontal = horizontal;
model->vertical = vertical;
model->font = font;
string_init_set_str(model->text, text);
// Allocate and init Element
GuiElement* gui_string = furi_alloc(sizeof(GuiElement));
gui_string->parent = NULL;
gui_string->input = NULL;
gui_string->draw = gui_string_draw;
gui_string->free = gui_string_free;
gui_string->model = model;
return gui_string;
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <stdint.h>
#include <gui/canvas.h>
typedef struct GuiElement GuiElement;
/** Allocate GuiElement element
* @param x - x coordinate
* @param y - y coordinate
* @param horizontal - Align instance
* @param vertical - Align instance
* @param font Font instance
* @return GuiElement instance
*/
GuiElement* gui_string_create(
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text);

View file

@ -0,0 +1,141 @@
#include <furi.h>
#include "gui_element_i.h"
#include "gui_widget.h"
#define MAX_GUI_ELEMENTS 8
struct GuiWidget {
View* view;
void* context;
};
// TODO rework with M-LIB container
typedef struct {
GuiElement* element[MAX_GUI_ELEMENTS];
} GuiWidgetModel;
static void gui_widget_view_draw_callback(Canvas* canvas, void* _model) {
GuiWidgetModel* model = _model;
canvas_clear(canvas);
for(uint8_t i = 0; i < MAX_GUI_ELEMENTS; i++) {
if(model->element[i] != NULL) {
if(model->element[i]->draw != NULL) {
model->element[i]->draw(canvas, model->element[i]);
}
}
};
}
static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
GuiWidget* gui_widget = context;
bool consumed = false;
with_view_model(
gui_widget->view, (GuiWidgetModel * model) {
for(uint8_t i = 0; i < MAX_GUI_ELEMENTS; i++) {
if(model->element[i] != NULL) {
if(model->element[i]->input != NULL) {
consumed = model->element[i]->input(event, model->element[i]);
}
}
};
return true;
});
return consumed;
}
GuiWidget* gui_widget_alloc() {
GuiWidget* gui_widget = furi_alloc(sizeof(GuiWidget));
gui_widget->view = view_alloc();
view_set_context(gui_widget->view, gui_widget);
view_allocate_model(gui_widget->view, ViewModelTypeLocking, sizeof(GuiWidgetModel));
view_set_draw_callback(gui_widget->view, gui_widget_view_draw_callback);
view_set_input_callback(gui_widget->view, gui_widget_view_input_callback);
with_view_model(
gui_widget->view, (GuiWidgetModel * model) {
for(uint8_t i = 0; i < MAX_GUI_ELEMENTS; i++) {
model->element[i] = NULL;
};
return true;
});
return gui_widget;
}
void gui_widget_free(GuiWidget* gui_widget) {
furi_assert(gui_widget);
gui_widget_clear(gui_widget);
view_free(gui_widget->view);
free(gui_widget);
}
void gui_widget_clear(GuiWidget* gui_widget) {
furi_assert(gui_widget);
with_view_model(
gui_widget->view, (GuiWidgetModel * model) {
for(uint8_t i = 0; i < MAX_GUI_ELEMENTS; i++) {
if(model->element[i]) {
furi_assert(model->element[i]->free);
model->element[i]->free(model->element[i]);
model->element[i] = NULL;
}
};
return true;
});
}
View* gui_widget_get_view(GuiWidget* gui_widget) {
furi_assert(gui_widget);
return gui_widget->view;
}
void gui_widget_add_element(GuiWidget* gui_widget, GuiElement* element) {
furi_assert(gui_widget);
with_view_model(
gui_widget->view, (GuiWidgetModel * model) {
// add element to first null position
for(uint8_t i = 0; i < MAX_GUI_ELEMENTS; i++) {
if(model->element[i] == NULL) {
model->element[i] = element;
element->parent = gui_widget;
break;
}
};
return true;
});
}
void gui_widget_add_string_element(
GuiWidget* gui_widget,
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text) {
furi_assert(gui_widget);
GuiElement* string_element = gui_string_create(x, y, horizontal, vertical, font, text);
gui_widget_add_element(gui_widget, string_element);
}
void gui_widget_add_button_element(
GuiWidget* gui_widget,
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context) {
furi_assert(gui_widget);
GuiElement* button_element = gui_button_create(button_type, text, callback, context);
gui_widget_add_element(gui_widget, button_element);
}
void gui_widget_add_icon_element(GuiWidget* gui_widget, uint8_t x, uint8_t y, const Icon* icon) {
furi_assert(gui_widget);
furi_assert(icon);
GuiElement* icon_element = gui_icon_create(x, y, icon);
gui_widget_add_element(gui_widget, icon_element);
}

View file

@ -0,0 +1,76 @@
#pragma once
#include <gui/view.h>
#include "gui_element_string.h"
#include "gui_element_button.h"
#include "gui_element_icon.h"
typedef struct GuiWidget GuiWidget;
typedef struct GuiElement GuiElement;
/** Allocate Gui Widget that holds Gui Elements
* @return GuiWidget instance
*/
GuiWidget* gui_widget_alloc();
/** Free Gui Widget
* @note this function free Gui Elements
* @param gui_widget GuiWidget instance
*/
void gui_widget_free(GuiWidget* gui_widget);
/** Clear Gui Widget
* @param gui_widget GuiWidget instance
*/
void gui_widget_clear(GuiWidget* gui_widget);
/** Get Gui Widget view
* @param gui_widget GuiWidget instance
* @return View instance
*/
View* gui_widget_get_view(GuiWidget* gui_widget);
/** Add generic Gui Elements to Gui Widget
* @param gui_widget GuiWidget instance
* @param element GuiElement element
*/
void gui_widget_add_element(GuiWidget* gui_widget, GuiElement* element);
/** Add String Element
* @param gui_widget GuiWidget instance
* @param x - x coordinate
* @param y - y coordinate
* @param horizontal - Align instance
* @param vertical - Align instance
* @param font Font instance
* @return GuiElement instance
*/
void gui_widget_add_string_element(
GuiWidget* gui_widget,
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text);
/** Add Button Element
* @param gui_widget GuiWidget instance
* @param button_type GuiButtonType instance
* @param text text on allocated button
* @param callback ButtonCallback instance
* @param context pointer to context
*/
void gui_widget_add_button_element(
GuiWidget* gui_widget,
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context);
/** Add Icon Element
* @param gui_widget GuiWidget instance
* @param x - x coordinate
* @param y - y coordinate
* @param icon Icon instance
*/
void gui_widget_add_icon_element(GuiWidget* gui_widget, uint8_t x, uint8_t y, const Icon* icon);

View file

@ -22,78 +22,61 @@ void nfc_tick_event_callback(void* context) {
Nfc* nfc_alloc() {
Nfc* nfc = furi_alloc(sizeof(Nfc));
nfc->nfc_common.worker = nfc_worker_alloc();
nfc->nfc_common.view_dispatcher = view_dispatcher_alloc();
nfc->worker = nfc_worker_alloc();
nfc->view_dispatcher = view_dispatcher_alloc();
nfc->scene_manager = scene_manager_alloc(&nfc_scene_handlers, nfc);
view_dispatcher_enable_queue(nfc->nfc_common.view_dispatcher);
view_dispatcher_set_event_callback_context(nfc->nfc_common.view_dispatcher, nfc);
view_dispatcher_set_custom_event_callback(
nfc->nfc_common.view_dispatcher, nfc_custom_event_callback);
view_dispatcher_enable_queue(nfc->view_dispatcher);
view_dispatcher_set_event_callback_context(nfc->view_dispatcher, nfc);
view_dispatcher_set_custom_event_callback(nfc->view_dispatcher, nfc_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
nfc->nfc_common.view_dispatcher, nfc_navigation_event_callback);
view_dispatcher_set_tick_event_callback(
nfc->nfc_common.view_dispatcher, nfc_tick_event_callback, 300);
nfc->view_dispatcher, nfc_navigation_event_callback);
view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100);
// Open GUI record
nfc->gui = furi_record_open("gui");
view_dispatcher_attach_to_gui(
nfc->nfc_common.view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
// Open Notification record
nfc->notifications = furi_record_open("notification");
// Submenu
nfc->submenu = submenu_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewMenu, submenu_get_view(nfc->submenu));
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_get_view(nfc->submenu));
// Dialog
nfc->dialog_ex = dialog_ex_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewDialogEx, dialog_ex_get_view(nfc->dialog_ex));
nfc->view_dispatcher, NfcViewDialogEx, dialog_ex_get_view(nfc->dialog_ex));
// Popup
nfc->popup = popup_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewPopup, popup_get_view(nfc->popup));
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewPopup, popup_get_view(nfc->popup));
// Text Input
nfc->text_input = text_input_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewTextInput, text_input_get_view(nfc->text_input));
nfc->view_dispatcher, NfcViewTextInput, text_input_get_view(nfc->text_input));
// Byte Input
nfc->byte_input = byte_input_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewByteInput, byte_input_get_view(nfc->byte_input));
nfc->view_dispatcher, NfcViewByteInput, byte_input_get_view(nfc->byte_input));
// TextBox
nfc->text_box = text_box_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box));
nfc->view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box));
string_init(nfc->text_box_store);
// Detect
nfc->nfc_detect = nfc_detect_alloc(&nfc->nfc_common);
// Custom Widget
nfc->widget = gui_widget_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewDetect, nfc_detect_get_view(nfc->nfc_detect));
nfc->view_dispatcher, NfcViewWidget, gui_widget_get_view(nfc->widget));
// Emulate
nfc->nfc_emulate = nfc_emulate_alloc(&nfc->nfc_common);
// Bank Card
nfc->bank_card = bank_card_alloc();
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewEmulate, nfc_emulate_get_view(nfc->nfc_emulate));
// EMV
nfc->nfc_emv = nfc_emv_alloc(&nfc->nfc_common);
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewEmv, nfc_emv_get_view(nfc->nfc_emv));
// Mifare Ultralight
nfc->nfc_mifare_ul = nfc_mifare_ul_alloc(&nfc->nfc_common);
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher,
NfcViewMifareUl,
nfc_mifare_ul_get_view(nfc->nfc_mifare_ul));
nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card));
return nfc;
}
@ -102,52 +85,44 @@ void nfc_free(Nfc* nfc) {
furi_assert(nfc);
// Submenu
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
submenu_free(nfc->submenu);
// DialogEx
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDialogEx);
dialog_ex_free(nfc->dialog_ex);
// Popup
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewPopup);
popup_free(nfc->popup);
// TextInput
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewTextInput);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewTextInput);
text_input_free(nfc->text_input);
// ByteInput
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewByteInput);
byte_input_free(nfc->byte_input);
// TextBox
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewTextBox);
text_box_free(nfc->text_box);
string_clear(nfc->text_box_store);
// Detect
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewDetect);
nfc_detect_free(nfc->nfc_detect);
// Custom Widget
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
gui_widget_free(nfc->widget);
// Emulate
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewEmulate);
nfc_emulate_free(nfc->nfc_emulate);
// EMV
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewEmv);
nfc_emv_free(nfc->nfc_emv);
// Mifare Ultralight
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewMifareUl);
nfc_mifare_ul_free(nfc->nfc_mifare_ul);
// Bank Card
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard);
bank_card_free(nfc->bank_card);
// Worker
nfc_worker_stop(nfc->nfc_common.worker);
nfc_worker_free(nfc->nfc_common.worker);
nfc_worker_stop(nfc->worker);
nfc_worker_free(nfc->worker);
// View Dispatcher
view_dispatcher_free(nfc->nfc_common.view_dispatcher);
view_dispatcher_free(nfc->view_dispatcher);
// Scene Manager
scene_manager_free(nfc->scene_manager);
@ -167,13 +142,13 @@ int32_t nfc_task(void* p) {
Nfc* nfc = nfc_alloc();
// Check argument and run corresponding scene
if(p && nfc_device_load(&nfc->device, p)) {
if(p && nfc_device_load(&nfc->dev, p)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneStart);
}
view_dispatcher_run(nfc->nfc_common.view_dispatcher);
view_dispatcher_run(nfc->view_dispatcher);
nfc_free(nfc);

View file

@ -24,7 +24,7 @@ void nfc_cli_detect(Cli* cli, string_t args, void* context) {
printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n");
while(!cmd_exit) {
cmd_exit |= cli_cmd_interrupt_received(cli);
cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 200, true);
cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 400, true);
if(dev_cnt > 0) {
printf("Found %d devices\r\n", dev_cnt);
for(uint8_t i = 0; i < dev_cnt; i++) {
@ -56,13 +56,13 @@ void nfc_cli_emulate(Cli* cli, string_t args, void* context) {
printf("Emulating NFC-A Type: T2T UID: CF72D440 SAK: 20 ATQA: 00/04\r\n");
printf("Press Ctrl+C to abort\r\n");
NfcDeviceData params = {
NfcDeviceCommomData params = {
.uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34},
.uid_len = 7,
.atqa = {0x44, 0x00},
.sak = 0x00,
.device = NfcDeviceNfca,
.protocol = NfcDeviceProtocolMfUltralight,
.protocol = NfcDeviceProtocolMifareUl,
};
while(!cli_cmd_interrupt_received(cli)) {

View file

@ -1,13 +1,246 @@
#include "nfc_device.h"
#include "nfc_device_i.h"
#include <file-worker.h>
#include <path.h>
#include <hex.h>
#define NFC_DEVICE_MAX_DATA_LEN 14
static const char* nfc_app_folder = "nfc";
static const char* nfc_app_extension = ".nfc";
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) {
string_strim(str);
uint8_t nibble_high = 0;
uint8_t nibble_low = 0;
bool parsed = true;
for(uint16_t i = 0; i < len; i++) {
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
buff[i] = (nibble_high << 4) | nibble_low;
string_right(str, 3);
} else {
parsed = false;
break;
}
}
return parsed;
}
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
if(dev->format == NfcDeviceSaveFormatUid) {
string_set_str(format_string, "UID\n");
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
string_set_str(format_string, "Bank card\n");
} else if(dev->format == NfcDeviceSaveFormatMifareUl) {
string_set_str(format_string, "Mifare Ultralight\n");
} else {
string_set_str(format_string, "Unknown\n");
}
return string_size(format_string);
}
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
if(string_start_with_str_p(format_string, "UID")) {
dev->format = NfcDeviceSaveFormatUid;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolUnknown;
return true;
} else if(string_start_with_str_p(format_string, "Bank card")) {
dev->format = NfcDeviceSaveFormatBankCard;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolEMV;
return true;
} else if(string_start_with_str_p(format_string, "Mifare Ultralight")) {
dev->format = NfcDeviceSaveFormatMifareUl;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareUl;
return true;
}
return false;
}
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) {
NfcDeviceCommomData* uid_data = &dev->dev_data.nfc_data;
string_printf(uid_string, "UID len: %02X UID: ", dev->dev_data.nfc_data.uid_len);
for(uint8_t i = 0; i < uid_data->uid_len; i++) {
string_cat_printf(uid_string, "%02X ", uid_data->uid[i]);
}
string_cat_printf(
uid_string,
"ATQA: %02X %02X SAK: %02X\n",
uid_data->atqa[0],
uid_data->atqa[1],
uid_data->sak);
return string_size(uid_string);
}
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) {
NfcDeviceCommomData* uid_data = &dev->dev_data.nfc_data;
bool parsed = false;
do {
// strlen("UID len: ") = 9
string_right(uid_string, 9);
if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1)) {
break;
}
// strlen("UID: ") = 5
string_right(uid_string, 5);
if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len)) {
break;
}
// strlen("ATQA: ") = 6
string_right(uid_string, 6);
if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2)) {
break;
}
// strlen("SAK: ") = 5
string_right(uid_string, 5);
if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1)) {
break;
}
parsed = true;
} while(0);
return parsed;
}
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
MifareUlData* data = &dev->dev_data.mf_ul_data;
string_printf(mifare_ul_string, "Signature:");
for(uint8_t i = 0; i < sizeof(data->signature); i++) {
string_cat_printf(mifare_ul_string, " %02X", data->signature[i]);
}
string_cat_printf(mifare_ul_string, "\nVersion:");
uint8_t* version = (uint8_t*)&data->version;
for(uint8_t i = 0; i < sizeof(data->version); i++) {
string_cat_printf(mifare_ul_string, " %02X", version[i]);
}
for(uint8_t i = 0; i < 3; i++) {
string_cat_printf(
mifare_ul_string,
"\nCounter %d: %lu Tearing flag %d: %02X",
i,
data->counter[i],
i,
data->tearing[i]);
}
string_cat_printf(mifare_ul_string, "\nData size: %d\n", data->data_size);
for(uint16_t i = 0; i < data->data_size; i += 4) {
string_cat_printf(
mifare_ul_string,
"%02X %02X %02X %02X\n",
data->data[i],
data->data[i + 1],
data->data[i + 2],
data->data[i + 3]);
}
return string_size(mifare_ul_string);
}
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
MifareUlData* data = &dev->dev_data.mf_ul_data;
uint16_t tearing_tmp = 0;
uint16_t cnt_num = 0;
size_t ws = 0;
int res = 0;
bool parsed = false;
do {
// strlen("Signature: ") = 11
string_right(mifare_ul_string, 11);
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature))) {
break;
}
// strlen("Version: ") = 9
string_right(mifare_ul_string, 9);
if(!nfc_device_read_hex(
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version))) {
break;
}
string_strim(mifare_ul_string);
// Read counters and tearing flags
for(uint8_t i = 0; i < 3; i++) {
res = sscanf(
string_get_cstr(mifare_ul_string),
"Counter %hX: %lu Tearing flag %hX: %02hX",
&cnt_num,
&data->counter[i],
&cnt_num,
&tearing_tmp);
if(res != 4) {
break;
}
data->tearing[i] = tearing_tmp;
ws = string_search_char(mifare_ul_string, '\n');
string_right(mifare_ul_string, ws + 1);
}
// Read data size
res = sscanf(string_get_cstr(mifare_ul_string), "Data size: %hu", &data->data_size);
if(res != 1) {
break;
}
ws = string_search_char(mifare_ul_string, '\n');
string_right(mifare_ul_string, ws + 1);
// Read data
for(uint16_t i = 0; i < data->data_size; i += 4) {
if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4)) {
break;
}
}
parsed = true;
} while(0);
return parsed;
}
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
NfcEmvData* data = &dev->dev_data.emv_data;
string_printf(bank_card_string, "AID len: %d, AID:", data->aid_len);
for(uint8_t i = 0; i < data->aid_len; i++) {
string_cat_printf(bank_card_string, " %02X", data->aid[i]);
}
string_cat_printf(bank_card_string, "\nName: %s\nNumber:", data->name);
for(uint8_t i = 0; i < sizeof(data->number); i++) {
string_cat_printf(bank_card_string, " %02X", data->number[i]);
}
return string_size(bank_card_string);
}
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
NfcEmvData* data = &dev->dev_data.emv_data;
bool parsed = false;
int res = 0;
memset(data, 0, sizeof(NfcEmvData));
do {
res = sscanf(string_get_cstr(bank_card_string), "AID len: %hu", &data->aid_len);
if(res != 1) {
break;
}
// strlen("AID len: ") = 9
string_right(bank_card_string, 9);
size_t ws = string_search_char(bank_card_string, ':');
string_right(bank_card_string, ws + 1);
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len)) {
break;
}
res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name);
if(res != 1) {
break;
}
ws = string_search_char(bank_card_string, '\n');
string_right(bank_card_string, ws + 1);
// strlen("Number: ") = 8
string_right(bank_card_string, 8);
if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number))) {
break;
}
parsed = true;
} while(0);
return parsed;
}
void nfc_device_set_name(NfcDevice* dev, const char* name) {
furi_assert(dev);
@ -19,37 +252,52 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
FileWorker* file_worker = file_worker_alloc(false);
string_t dev_file_name;
string_init(dev_file_name);
string_t temp_str;
string_init(temp_str);
uint16_t string_len = 0;
// Create nfc directory if necessary
if(!file_worker_mkdir(file_worker, nfc_app_folder)) {
return false;
};
// First remove nfc device file if it was saved
string_init_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev_name, nfc_app_extension);
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
string_clear(dev_file_name);
return false;
};
// Prepare buffer to write
uint8_t buff[NFC_DEVICE_MAX_DATA_LEN];
buff[0] = dev->data.uid_len;
memcpy(&buff[1], dev->data.uid, dev->data.uid_len);
memcpy(&buff[dev->data.uid_len + 1], dev->data.atqa, 2);
buff[dev->data.uid_len + 3] = dev->data.sak;
// Save nfc device
bool res = file_worker_open(
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS);
string_clear(dev_file_name);
if(res) {
// Write UID length
if(!file_worker_write_hex(file_worker, buff, dev->data.uid_len + 4)) {
file_worker_close(file_worker);
return false;
do {
// Create nfc directory if necessary
if(!file_worker_mkdir(file_worker, nfc_app_folder)) {
break;
};
// First remove nfc device file if it was saved
string_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev_name, nfc_app_extension);
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
break;
};
// Open file
if(!file_worker_open(
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
break;
}
}
// Prepare and write format name on 1st line
string_len = nfc_device_prepare_format_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
// Prepare and write UID data on 2nd line
string_len = nfc_device_prepare_uid_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
// Save more data if necessary
if(dev->format == NfcDeviceSaveFormatMifareUl) {
string_len = nfc_device_prepare_mifare_ul_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
string_len = nfc_device_prepare_bank_card_string(dev, temp_str);
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
break;
}
}
} while(0);
string_clear(temp_str);
string_clear(dev_file_name);
file_worker_close(file_worker);
file_worker_free(file_worker);
@ -57,34 +305,52 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
}
static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevice* dev) {
// Open key file
if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
return false;
}
string_t temp_string;
string_init(temp_string);
bool parsed = false;
uint8_t buff[NFC_DEVICE_MAX_DATA_LEN] = {};
do {
// Open key file
if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
break;
}
// Read and parse format from 1st line
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
break;
}
if(!nfc_device_parse_format_string(dev, temp_string)) {
break;
}
// Read and parse UID data from 2nd line
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
break;
}
if(!nfc_device_parse_uid_string(dev, temp_string)) {
break;
}
// Parse other data
if(dev->format == NfcDeviceSaveFormatMifareUl) {
// Read until EOF
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
break;
}
if(!nfc_device_parse_mifare_ul_string(dev, temp_string)) {
break;
}
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
// Read until EOF
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
break;
}
if(!nfc_device_parse_bank_card_string(dev, temp_string)) {
break;
}
}
parsed = true;
} while(0);
// Load first byte - UID length
if(!file_worker_read_hex(file_worker, buff, 1)) {
return false;
}
// Read space
uint8_t space = 0;
if(!file_worker_read(file_worker, &space, 1)) {
return false;
}
// Load other data
if(!file_worker_read_hex(file_worker, &buff[1], buff[0] + 3)) {
return false;
}
// Set loaded data
dev->data.uid_len = buff[0];
memcpy(dev->data.uid, &buff[1], dev->data.uid_len);
memcpy(dev->data.atqa, &buff[dev->data.uid_len + 1], 2);
dev->data.sak = buff[dev->data.uid_len + 3];
return true;
string_clear(temp_string);
return parsed;
}
bool nfc_device_load(NfcDevice* dev, const char* file_path) {
@ -137,3 +403,25 @@ bool nfc_file_select(NfcDevice* dev) {
return res;
}
void nfc_device_clear(NfcDevice* dev) {
furi_assert(dev);
memset(&dev->dev_data, 0, sizeof(dev->dev_data));
nfc_device_set_name(dev, "");
dev->format = NfcDeviceSaveFormatUid;
}
bool nfc_device_delete(NfcDevice* dev) {
furi_assert(dev);
bool result = false;
FileWorker* file_worker = file_worker_alloc(false);
string_t file_path;
string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
result = file_worker_remove(file_worker, string_get_cstr(file_path));
string_clear(file_path);
file_worker_close(file_worker);
file_worker_free(file_worker);
return result;
}

View file

@ -3,11 +3,11 @@
#include <stdint.h>
#include <stdbool.h>
#include "mifare_ultralight.h"
#define NFC_DEV_NAME_MAX_LEN 22
#define NFC_FILE_NAME_MAX_LEN 120
#define NFC_MIFARE_UL_MAX_SIZE 256
typedef enum {
NfcDeviceNfca,
NfcDeviceNfcb,
@ -18,9 +18,15 @@ typedef enum {
typedef enum {
NfcDeviceProtocolUnknown,
NfcDeviceProtocolEMV,
NfcDeviceProtocolMfUltralight,
NfcDeviceProtocolMifareUl,
} NfcProtocol;
typedef enum {
NfcDeviceSaveFormatUid,
NfcDeviceSaveFormatBankCard,
NfcDeviceSaveFormatMifareUl,
} NfcDeviceSaveFormat;
typedef struct {
uint8_t uid_len;
uint8_t uid[10];
@ -28,27 +34,31 @@ typedef struct {
uint8_t sak;
NfcDeviceType device;
NfcProtocol protocol;
} NfcDeviceData;
} NfcDeviceCommomData;
typedef struct {
NfcDeviceData nfc_data;
char name[32];
uint8_t aid[16];
uint16_t aid_len;
uint8_t number[8];
uint8_t exp_mon;
uint16_t exp_year;
char cardholder[32];
} NfcEmvData;
typedef struct {
NfcDeviceData nfc_data;
uint8_t full_dump[NFC_MIFARE_UL_MAX_SIZE];
uint16_t dump_size;
// TODO delete with debug view
uint8_t man_block[12];
uint8_t otp[4];
} NfcMifareUlData;
NfcDeviceCommomData nfc_data;
union {
NfcEmvData emv_data;
MifareUlData mf_ul_data;
};
} NfcDeviceData;
typedef struct {
NfcDeviceData data;
NfcDeviceData dev_data;
char dev_name[NFC_DEV_NAME_MAX_LEN];
char file_name[NFC_FILE_NAME_MAX_LEN];
NfcDeviceSaveFormat format;
} NfcDevice;
void nfc_device_set_name(NfcDevice* dev, const char* name);
@ -58,3 +68,7 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name);
bool nfc_device_load(NfcDevice* dev, const char* file_path);
bool nfc_file_select(NfcDevice* dev);
void nfc_device_clear(NfcDevice* dev);
bool nfc_device_delete(NfcDevice* dev);

View file

@ -0,0 +1,16 @@
#pragma once
#include "nfc_device.h"
#include <m-string.h>
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string);
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string);
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string);
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string);
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string);
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string);

View file

@ -21,31 +21,27 @@
#include <gui/modules/byte_input.h>
#include <gui/modules/text_box.h>
#include <nfc/scenes/nfc_scene.h>
#include "views/bank_card.h"
#include "views/nfc_detect.h"
#include "views/nfc_emulate.h"
#include "views/nfc_emv.h"
#include "views/nfc_mifare_ul.h"
#include "gui_widget/gui_widget.h"
#include "gui_widget/gui_element_string.h"
#include "gui_widget/gui_element_button.h"
#include <nfc/scenes/nfc_scene.h>
#define NFC_TEXT_STORE_SIZE 128
struct Nfc {
NfcCommon nfc_common;
NfcWorker* worker;
ViewDispatcher* view_dispatcher;
Gui* gui;
NotificationApp* notifications;
SceneManager* scene_manager;
NfcDevice device;
NfcDevice dev;
char text_store[NFC_TEXT_STORE_SIZE + 1];
string_t text_box_store;
// Nfc Views
NfcDetect* nfc_detect;
NfcEmulate* nfc_emulate;
NfcEmv* nfc_emv;
NfcMifareUl* nfc_mifare_ul;
// Common Views
Submenu* submenu;
DialogEx* dialog_ex;
@ -53,6 +49,8 @@ struct Nfc {
TextInput* text_input;
ByteInput* byte_input;
TextBox* text_box;
GuiWidget* widget;
BankCard* bank_card;
};
typedef enum {
@ -62,10 +60,8 @@ typedef enum {
NfcViewTextInput,
NfcViewByteInput,
NfcViewTextBox,
NfcViewDetect,
NfcViewEmulate,
NfcViewEmv,
NfcViewMifareUl,
NfcViewWidget,
NfcViewBankCard,
} NfcView;
Nfc* nfc_alloc();

View file

@ -6,25 +6,6 @@
#include <gui/view_dispatcher.h>
#include "nfc_worker.h"
typedef struct {
NfcWorker* worker;
ViewDispatcher* view_dispatcher;
NfcWorkerResult worker_result;
} NfcCommon;
typedef enum {
NfcEventDetect,
NfcEventEmv,
NfcEventMifareUl,
} NfcEvent;
typedef enum {
NfcSubmenuDetect,
NfcSubmenuEmulate,
NfcSubmenuEMV,
NfcSubmenuMifareUl,
} NfcSubmenu;
static inline const char* nfc_get_dev_type(rfalNfcDevType type) {
if(type == RFAL_NFC_LISTEN_TYPE_NFCA) {
return "NFC-A may be:";
@ -62,7 +43,7 @@ static inline const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type) {
static inline const char* nfc_get_protocol(NfcProtocol protocol) {
if(protocol == NfcDeviceProtocolEMV) {
return "EMV bank card";
} else if(protocol == NfcDeviceProtocolMfUltralight) {
} else if(protocol == NfcDeviceProtocolMifareUl) {
return "Mifare Ultralight";
} else {
return "Unrecognized";

View file

@ -39,26 +39,21 @@ ReturnCode nfc_worker_get_error(NfcWorker* nfc_worker) {
return nfc_worker->error;
}
void nfc_worker_set_emulation_params(NfcWorker* nfc_worker, NfcDeviceData* data) {
furi_assert(nfc_worker);
furi_assert(data);
nfc_worker->emulate_params = *data;
}
void nfc_worker_start(
NfcWorker* nfc_worker,
NfcWorkerState state,
NfcWorkerResult* result_dest,
NfcDeviceData* dev_data,
NfcWorkerCallback callback,
void* context) {
furi_assert(nfc_worker);
furi_assert(nfc_worker->state == NfcWorkerStateReady);
furi_assert(result_dest);
furi_assert(dev_data);
while(nfc_worker->state != NfcWorkerStateReady) {
osDelay(10);
}
nfc_worker->callback = callback;
nfc_worker->context = context;
nfc_worker->last_result = result_dest;
nfc_worker->dev_data = dev_data;
nfc_worker_change_state(nfc_worker, state);
nfc_worker->thread = osThreadNew(nfc_worker_task, nfc_worker, &nfc_worker->thread_attr);
}
@ -88,12 +83,16 @@ void nfc_worker_task(void* context) {
nfc_worker_detect(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulate) {
nfc_worker_emulate(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadEMVApp) {
nfc_worker_read_emv_app(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadEMV) {
nfc_worker_read_emv(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateEMV) {
nfc_worker_emulate_emv(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
nfc_worker_read_mf_ultralight(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMifareUl) {
nfc_worker_read_mifare_ul(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateMifareUl) {
nfc_worker_emulate_mifare_ul(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateField) {
nfc_worker_field(nfc_worker);
}
@ -107,7 +106,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
rfalNfcDevice* dev_list;
rfalNfcDevice* dev;
uint8_t dev_cnt;
NfcDeviceData* result = &nfc_worker->last_result->nfc_detect_data;
NfcDeviceCommomData* result = &nfc_worker->dev_data->nfc_data;
while(nfc_worker->state == NfcWorkerStateDetect) {
if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true)) {
@ -124,11 +123,12 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
dev->dev.nfca.sensRes.anticollisionInfo,
dev->dev.nfca.sensRes.platformInfo,
dev->dev.nfca.selRes.sak)) {
result->protocol = NfcDeviceProtocolMfUltralight;
result->protocol = NfcDeviceProtocolMifareUl;
} else if(dev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) {
result->protocol = NfcDeviceProtocolEMV;
} else {
result->protocol = NfcDeviceProtocolUnknown;
}
} else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCB) {
result->device = NfcDeviceNfcb;
} else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCF) {
@ -147,15 +147,77 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
}
void nfc_worker_emulate(NfcWorker* nfc_worker) {
NfcDeviceData* param = &nfc_worker->emulate_params;
NfcDeviceCommomData* data = &nfc_worker->dev_data->nfc_data;
while(nfc_worker->state == NfcWorkerStateEmulate) {
if(api_hal_nfc_listen(param->uid, param->uid_len, param->atqa, param->sak, 100)) {
if(api_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, 100)) {
FURI_LOG_I(NFC_WORKER_TAG, "Reader detected");
}
osDelay(10);
}
}
void nfc_worker_read_emv_app(NfcWorker* nfc_worker) {
ReturnCode err;
rfalNfcDevice* dev_list;
EmvApplication emv_app = {};
uint8_t dev_cnt = 0;
uint8_t tx_buff[255] = {};
uint16_t tx_len = 0;
uint8_t* rx_buff;
uint16_t* rx_len;
NfcDeviceData* result = nfc_worker->dev_data;
while(nfc_worker->state == NfcWorkerStateReadEMVApp) {
memset(&emv_app, 0, sizeof(emv_app));
if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
// Card was found. Check that it supports EMV
if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) {
result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len;
result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak;
memcpy(
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
result->nfc_data.protocol = NfcDeviceProtocolEMV;
FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command");
tx_len = emv_prepare_select_ppse(tx_buff);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
if(err != ERR_NONE) {
FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err);
api_hal_nfc_deactivate();
continue;
}
FURI_LOG_I(
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
// Notify caller and exit
result->emv_data.aid_len = emv_app.aid_len;
memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len);
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
}
break;
} else {
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
api_hal_nfc_deactivate();
continue;
}
} else {
// Can't find EMV card
FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV");
api_hal_nfc_deactivate();
}
} else {
// Can't find EMV card
FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards");
api_hal_nfc_deactivate();
}
osDelay(20);
}
}
void nfc_worker_read_emv(NfcWorker* nfc_worker) {
ReturnCode err;
rfalNfcDevice* dev_list;
@ -165,13 +227,21 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
uint16_t tx_len = 0;
uint8_t* rx_buff;
uint16_t* rx_len;
NfcEmvData* result = &nfc_worker->last_result->nfc_emv_data;
NfcDeviceData* result = nfc_worker->dev_data;
while(nfc_worker->state == NfcWorkerStateReadEMV) {
memset(&emv_app, 0, sizeof(emv_app));
if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
// Card was found. Check that it supports EMV
if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) {
result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len;
result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak;
memcpy(
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
result->nfc_data.protocol = NfcDeviceProtocolEMV;
FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command");
tx_len = emv_prepare_select_ppse(tx_buff);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
@ -203,7 +273,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
"Select application response received. Start parsing response");
if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) {
FURI_LOG_I(NFC_WORKER_TAG, "Card name: %s", emv_app.name);
memcpy(result->name, emv_app.name, sizeof(emv_app.name));
memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name));
} else {
FURI_LOG_E(NFC_WORKER_TAG, "Can't read card name");
api_hal_nfc_deactivate();
@ -220,7 +290,8 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
}
if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) {
FURI_LOG_I(NFC_WORKER_TAG, "Card number parsed");
memcpy(result->number, emv_app.card_number, sizeof(emv_app.card_number));
memcpy(
result->emv_data.number, emv_app.card_number, sizeof(emv_app.card_number));
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
@ -255,7 +326,10 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
}
if(pan_found) {
FURI_LOG_I(NFC_WORKER_TAG, "Card PAN found");
memcpy(result->number, emv_app.card_number, sizeof(emv_app.card_number));
memcpy(
result->emv_data.number,
emv_app.card_number,
sizeof(emv_app.card_number));
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
@ -286,7 +360,7 @@ void nfc_worker_emulate_emv(NfcWorker* nfc_worker) {
uint16_t tx_len = 0;
uint8_t* rx_buff;
uint16_t* rx_len;
NfcDeviceData params = {
NfcDeviceCommomData params = {
.uid = {0xCF, 0x72, 0xd4, 0x40},
.uid_len = 4,
.atqa = {0x00, 0x04},
@ -343,7 +417,7 @@ void nfc_worker_emulate_emv(NfcWorker* nfc_worker) {
}
}
void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
ReturnCode err;
rfalNfcDevice* dev_list;
uint8_t dev_cnt = 0;
@ -351,21 +425,20 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
uint16_t tx_len = 0;
uint8_t* rx_buff;
uint16_t* rx_len;
MfUltralightRead mf_ul_read;
NfcMifareUlData* result = &nfc_worker->last_result->nfc_mifare_ul_data;
MifareUlDevice mf_ul_read;
NfcDeviceData* result = nfc_worker->dev_data;
while(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
while(nfc_worker->state == NfcWorkerStateReadMifareUl) {
api_hal_nfc_deactivate();
memset(&mf_ul_read, 0, sizeof(mf_ul_read));
if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
if(api_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA &&
mf_ul_check_card_type(
dev_list[0].dev.nfca.sensRes.anticollisionInfo,
dev_list[0].dev.nfca.sensRes.platformInfo,
dev_list[0].dev.nfca.selRes.sak)) {
// Get Mifare Ultralight version
FURI_LOG_I(
NFC_WORKER_TAG, "Found Mifare Ultralight tag. Trying to get tag version");
FURI_LOG_I(NFC_WORKER_TAG, "Found Mifare Ultralight tag. Reading tag version");
tx_len = mf_ul_prepare_get_version(tx_buff);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
if(err == ERR_NONE) {
@ -378,7 +451,7 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
} else if(err == ERR_TIMEOUT) {
FURI_LOG_W(
NFC_WORKER_TAG,
"Card doesn't respond to GET VERSION command. Reinit card and set default read parameters");
"Card doesn't respond to GET VERSION command. Setting default read parameters");
err = ERR_NONE;
mf_ul_set_default_version(&mf_ul_read);
// Reinit device
@ -395,37 +468,58 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
continue;
}
// Dump Mifare Ultralight card
FURI_LOG_I(NFC_WORKER_TAG, "Trying to read pages");
if(mf_ul_read.support_fast_read) {
// Read card with FAST_READ command
FURI_LOG_I(NFC_WORKER_TAG, "Reading pages ...");
tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
if(err == ERR_NONE) {
FURI_LOG_I(
NFC_WORKER_TAG,
"Fast read pages %d - %d succeed",
0,
mf_ul_read.pages_to_read - 1);
memcpy(mf_ul_read.dump, rx_buff, mf_ul_read.pages_to_read * 4);
mf_ul_read.pages_readed = mf_ul_read.pages_to_read;
} else {
FURI_LOG_E(NFC_WORKER_TAG, "Fast read failed");
if(api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
FURI_LOG_E(NFC_WORKER_TAG, "Failed reading pages");
continue;
} else {
mf_ul_parse_fast_read_response(
rx_buff, 0x00, mf_ul_read.pages_to_read - 1, &mf_ul_read);
}
FURI_LOG_I(NFC_WORKER_TAG, "Reading signature ...");
tx_len = mf_ul_prepare_read_signature(tx_buff);
if(api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
FURI_LOG_W(NFC_WORKER_TAG, "Failed reading signature");
memset(mf_ul_read.data.signature, 0, sizeof(mf_ul_read.data.signature));
} else {
mf_ul_parse_read_signature_response(rx_buff, &mf_ul_read);
}
FURI_LOG_I(NFC_WORKER_TAG, "Reading 3 counters ...");
for(uint8_t i = 0; i < 3; i++) {
tx_len = mf_ul_prepare_read_cnt(tx_buff, i);
if(api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
FURI_LOG_W(NFC_WORKER_TAG, "Failed reading Counter %d", i);
mf_ul_read.data.counter[i] = 0;
} else {
mf_ul_parse_read_cnt_response(rx_buff, i, &mf_ul_read);
}
}
FURI_LOG_I(NFC_WORKER_TAG, "Checking tearing flags ...");
for(uint8_t i = 0; i < 3; i++) {
tx_len = mf_ul_prepare_check_tearing(tx_buff, i);
if(api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
FURI_LOG_E(NFC_WORKER_TAG, "Error checking tearing flag %d", i);
mf_ul_read.data.tearing[i] = MF_UL_TEARING_FLAG_DEFAULT;
} else {
mf_ul_parse_check_tearing_response(rx_buff, i, &mf_ul_read);
}
}
} else {
// READ card with READ command (4 pages at a time)
for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) {
FURI_LOG_I(NFC_WORKER_TAG, "Reading pages %d - %d ...", page, page + 3);
tx_len = mf_ul_prepare_read(tx_buff, page);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
if(err == ERR_NONE) {
FURI_LOG_I(
NFC_WORKER_TAG, "Read pages %d - %d succeed", page, page + 3);
memcpy(&mf_ul_read.dump[page * 4], rx_buff, 4 * 4);
mf_ul_read.pages_readed += 4;
} else {
FURI_LOG_W(
if(api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
FURI_LOG_E(
NFC_WORKER_TAG, "Read pages %d - %d failed", page, page + 3);
continue;
} else {
mf_ul_parse_read_response(rx_buff, page, &mf_ul_read);
}
}
}
@ -435,20 +529,11 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak;
result->nfc_data.protocol = NfcDeviceProtocolMifareUl;
memcpy(
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
memcpy(result->man_block, mf_ul_read.dump, 4 * 3);
memcpy(result->otp, &mf_ul_read.dump[4 * 3], 4);
result->dump_size = mf_ul_read.pages_readed * 4;
memcpy(result->full_dump, mf_ul_read.dump, result->dump_size);
result->mf_ul_data = mf_ul_read.data;
for(uint8_t i = 0; i < mf_ul_read.pages_readed * 4; i += 4) {
printf("Page %2d: ", i / 4);
for(uint8_t j = 0; j < 4; j++) {
printf("%02X ", mf_ul_read.dump[i + j]);
}
printf("\r\n");
}
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
@ -464,6 +549,43 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
}
}
void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) {
ReturnCode err;
uint8_t tx_buff[255] = {};
uint16_t tx_len = 0;
uint8_t* rx_buff;
uint16_t* rx_len;
NfcDeviceData* data = nfc_worker->dev_data;
while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) {
if(api_hal_nfc_listen(
data->nfc_data.uid,
data->nfc_data.uid_len,
data->nfc_data.atqa,
data->nfc_data.sak,
1000)) {
FURI_LOG_I(NFC_WORKER_TAG, "Hello my dudes");
// Prepare version answer
tx_len = sizeof(data->mf_ul_data.version);
memcpy(tx_buff, &data->mf_ul_data.version, tx_len);
err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
if(err == ERR_NONE) {
FURI_LOG_I(NFC_WORKER_TAG, "Received 1st message:");
for(uint16_t i = 0; i < *rx_len; i++) {
printf("%02X ", rx_buff[i]);
}
printf("\r\n");
} else {
FURI_LOG_E(NFC_WORKER_TAG, "Error in 1st data exchange: select PPSE");
api_hal_nfc_deactivate();
continue;
}
}
FURI_LOG_W(NFC_WORKER_TAG, "Hello my dudes");
osDelay(10);
}
}
void nfc_worker_field(NfcWorker* nfc_worker) {
api_hal_nfc_field_on();
while(nfc_worker->state == NfcWorkerStateField) {

View file

@ -2,14 +2,6 @@
#include "nfc_device.h"
typedef struct {
union {
NfcDeviceData nfc_detect_data;
NfcEmvData nfc_emv_data;
NfcMifareUlData nfc_mifare_ul_data;
};
} NfcWorkerResult;
typedef struct NfcWorker NfcWorker;
typedef enum {
@ -20,10 +12,12 @@ typedef enum {
// Main worker states
NfcWorkerStateDetect,
NfcWorkerStateEmulate,
NfcWorkerStateReadEMVApp,
NfcWorkerStateReadEMV,
NfcWorkerStateEmulateEMV,
NfcWorkerStateField,
NfcWorkerStateReadMfUltralight,
NfcWorkerStateReadMifareUl,
NfcWorkerStateEmulateMifareUl,
// Transition
NfcWorkerStateStop,
} NfcWorkerState;
@ -36,14 +30,12 @@ NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker);
ReturnCode nfc_worker_get_error(NfcWorker* nfc_worker);
void nfc_worker_set_emulation_params(NfcWorker* nfc_worker, NfcDeviceData* data);
void nfc_worker_free(NfcWorker* nfc_worker);
void nfc_worker_start(
NfcWorker* nfc_worker,
NfcWorkerState state,
NfcWorkerResult* result_dest,
NfcDeviceData* dev_data,
NfcWorkerCallback callback,
void* context);

10
applications/nfc/nfc_worker_i.h Normal file → Executable file
View file

@ -20,10 +20,10 @@ struct NfcWorker {
osThreadAttr_t thread_attr;
osThreadId_t thread;
NfcWorkerResult* last_result;
NfcDeviceData* dev_data;
NfcWorkerCallback callback;
void* context;
NfcDeviceData emulate_params;
NfcWorkerState state;
ReturnCode error;
@ -33,6 +33,8 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state);
void nfc_worker_task(void* context);
void nfc_worker_read_emv_app(NfcWorker* nfc_worker);
void nfc_worker_read_emv(NfcWorker* nfc_worker);
void nfc_worker_emulate_emv(NfcWorker* nfc_worker);
@ -43,4 +45,6 @@ void nfc_worker_emulate(NfcWorker* nfc_worker);
void nfc_worker_field(NfcWorker* nfc_worker);
void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker);
void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker);
void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker);

View file

@ -10,19 +10,21 @@ enum SubmenuIndex {
void nfc_scene_card_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_card_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu,
"Run compatible app",
SubmenuIndexRunApp,
nfc_scene_card_menu_submenu_callback,
nfc);
if(nfc->dev.dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
submenu_add_item(
submenu,
"Run compatible app",
SubmenuIndexRunApp,
nfc_scene_card_menu_submenu_callback,
nfc);
}
submenu_add_item(
submenu,
"Additional reading scripts",
@ -36,7 +38,7 @@ const void nfc_scene_card_menu_on_enter(void* context) {
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneCardMenu));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
@ -46,12 +48,16 @@ const bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event)
if(event.event == SubmenuIndexRunApp) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
} else if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
}
return true;
} else if(event.event == SubmenuIndexChooseScript) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexChooseScript);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu);
return true;
} else if(event.event == SubmenuIndexEmulate) {
scene_manager_set_scene_state(
@ -60,6 +66,7 @@ const bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event)
return true;
} else if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave);
nfc->dev.format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
}

View file

@ -16,8 +16,12 @@ ADD_SCENE(nfc, scripts_menu, ScriptsMenu)
ADD_SCENE(nfc, read_mifare_ul, ReadMifareUl)
ADD_SCENE(nfc, read_mifare_ul_success, ReadMifareUlSuccess)
ADD_SCENE(nfc, mifare_ul_menu, MifareUlMenu)
ADD_SCENE(nfc, debug_menu, DebugMenu)
ADD_SCENE(nfc, debug_detect, DebugDetect)
ADD_SCENE(nfc, debug_emulate, DebugEmulate)
ADD_SCENE(nfc, debug_read_emv, DebugReadEmv)
ADD_SCENE(nfc, debug_read_mifare_ul, DebugReadMifareUl)
ADD_SCENE(nfc, emulate_mifare_ul, EmulateMifareUl)
ADD_SCENE(nfc, read_emv_app, ReadEmvApp)
ADD_SCENE(nfc, read_emv_app_success, ReadEmvAppSuccess)
ADD_SCENE(nfc, device_info, DeviceInfo)
ADD_SCENE(nfc, delete, Delete)
ADD_SCENE(nfc, delete_success, DeleteSuccess)
ADD_SCENE(nfc, run_emv_app_confirm, RunEmvAppConfirm)
ADD_SCENE(nfc, read_emv_data, ReadEmvData)
ADD_SCENE(nfc, read_emv_data_success, ReadEmvDataSuccess)

View file

@ -1,14 +0,0 @@
#include "../nfc_i.h"
const void nfc_scene_debug_detect_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDetect);
}
const bool nfc_scene_debug_detect_on_event(void* context, SceneManagerEvent event) {
return false;
}
const void nfc_scene_debug_detect_on_exit(void* context) {
}

View file

@ -1,14 +0,0 @@
#include "../nfc_i.h"
const void nfc_scene_debug_emulate_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmulate);
}
const bool nfc_scene_debug_emulate_on_event(void* context, SceneManagerEvent event) {
return false;
}
const void nfc_scene_debug_emulate_on_exit(void* context) {
}

View file

@ -1,72 +0,0 @@
#include "../nfc_i.h"
enum SubmenuIndex {
SubmenuIndexDetect,
SubmenuIndexEmulate,
SubmenuIndexReadEmv,
SubmenuIndexReadMifareUl,
};
void nfc_scene_debug_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
}
const void nfc_scene_debug_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu, "Detect", SubmenuIndexDetect, nfc_scene_debug_menu_submenu_callback, nfc);
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_debug_menu_submenu_callback, nfc);
submenu_add_item(
submenu, "Read EMV", SubmenuIndexReadEmv, nfc_scene_debug_menu_submenu_callback, nfc);
submenu_add_item(
submenu,
"Read Mifare Ultralight",
SubmenuIndexReadMifareUl,
nfc_scene_debug_menu_submenu_callback,
nfc);
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDebugMenu));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_debug_menu_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexDetect) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexDetect);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugDetect);
return true;
} else if(event.event == SubmenuIndexEmulate) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexEmulate);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugEmulate);
return true;
} else if(event.event == SubmenuIndexReadEmv) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexReadEmv);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugReadEmv);
return true;
} else if(event.event == SubmenuIndexReadMifareUl) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexReadMifareUl);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugReadMifareUl);
return true;
}
}
return false;
}
const void nfc_scene_debug_menu_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
submenu_clean(nfc->submenu);
}

View file

@ -1,14 +0,0 @@
#include "../nfc_i.h"
const void nfc_scene_debug_read_emv_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmv);
}
const bool nfc_scene_debug_read_emv_on_event(void* context, SceneManagerEvent event) {
return false;
}
const void nfc_scene_debug_read_emv_on_exit(void* context) {
}

View file

@ -1,14 +0,0 @@
#include "../nfc_i.h"
const void nfc_scene_debug_read_mifare_ul_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMifareUl);
}
const bool nfc_scene_debug_read_mifare_ul_on_event(void* context, SceneManagerEvent event) {
return false;
}
const void nfc_scene_debug_read_mifare_ul_on_exit(void* context) {
}

View file

@ -0,0 +1,95 @@
#include "../nfc_i.h"
void nfc_scene_delete_widget_callback(GuiButtonType result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_delete_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup Custom Widget view
char delete_str[64];
snprintf(delete_str, sizeof(delete_str), "Delete %s", nfc->dev.dev_name);
gui_widget_add_string_element(
nfc->widget, 64, 6, AlignCenter, AlignTop, FontPrimary, delete_str);
gui_widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
gui_widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
char uid_str[32];
NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data;
if(data->uid_len == 4) {
snprintf(
uid_str,
sizeof(uid_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(
uid_str,
sizeof(uid_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]);
}
gui_widget_add_string_element(
nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, uid_str);
if(data->protocol > NfcDeviceProtocolUnknown) {
gui_widget_add_string_element(
nfc->widget,
10,
32,
AlignLeft,
AlignTop,
FontSecondary,
nfc_get_protocol(data->protocol));
}
// TODO change dinamically
gui_widget_add_string_element(
nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A");
char sak_str[16];
snprintf(sak_str, sizeof(sak_str), "SAK: %02X", data->sak);
gui_widget_add_string_element(
nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, sak_str);
char atqa_str[16];
snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
gui_widget_add_string_element(
nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
const bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == GuiButtonTypeRight) {
if(nfc_device_delete(&nfc->dev)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
} else {
scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
}
return true;
}
}
return false;
}
const void nfc_scene_delete_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
gui_widget_clear(nfc->widget);
}

View file

@ -0,0 +1,47 @@
#include "../nfc_i.h"
#define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL)
void nfc_scene_delete_success_popup_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT);
}
const void nfc_scene_delete_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)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_timeout(popup, 1500);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_delete_success_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
const bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
}
}
return false;
}
const void nfc_scene_delete_success_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
popup_set_callback(popup, NULL);
popup_set_context(popup, NULL);
popup_set_timeout(popup, 0);
popup_disable_timeout(popup);
}

View file

@ -0,0 +1,185 @@
#include "../nfc_i.h"
#define NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT (0UL)
enum {
NfcSceneDeviceInfoUid,
NfcSceneDeviceInfoData,
};
void nfc_scene_device_info_widget_callback(GuiButtonType result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_device_info_text_box_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(
nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT);
}
void nfc_scene_device_info_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup Custom Widget view
gui_widget_add_string_element(
nfc->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_name);
gui_widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
gui_widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
char uid_str[32];
NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data;
if(data->uid_len == 4) {
snprintf(
uid_str,
sizeof(uid_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(
uid_str,
sizeof(uid_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]);
}
gui_widget_add_string_element(
nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, uid_str);
if(data->protocol > NfcDeviceProtocolUnknown) {
gui_widget_add_string_element(
nfc->widget,
10,
32,
AlignLeft,
AlignTop,
FontSecondary,
nfc_get_protocol(data->protocol));
}
// TODO change dinamically
gui_widget_add_string_element(
nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A");
char sak_str[16];
snprintf(sak_str, sizeof(sak_str), "SAK: %02X", data->sak);
gui_widget_add_string_element(
nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, sak_str);
char atqa_str[16];
snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
gui_widget_add_string_element(
nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_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) {
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
TextBox* text_box = nfc->text_box;
text_box_set_context(text_box, nfc);
text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback);
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));
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
NfcEmvData* 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);
if(!strcmp(emv_data->name, "")) {
bank_card_set_cardholder_name(bank_card, emv_data->cardholder);
}
if(emv_data->exp_mon) {
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
}
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
const bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
Nfc* 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(state == NfcSceneDeviceInfoData) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
consumed = true;
}
}
return consumed;
}
const void nfc_scene_device_info_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Clear Custom Widget
gui_widget_clear(nfc->widget);
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
// Clear Dialog
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, NULL);
dialog_ex_set_right_button_text(dialog_ex, NULL);
dialog_ex_set_center_button_text(dialog_ex, NULL);
dialog_ex_set_result_callback(dialog_ex, NULL);
dialog_ex_set_context(dialog_ex, NULL);
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
// Clear TextBox
text_box_clean(nfc->text_box);
string_clean(nfc->text_box_store);
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
// Clear Bank Card
bank_card_clear(nfc->bank_card);
}
}

View file

@ -0,0 +1,60 @@
#include "../nfc_i.h"
const void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup view
Popup* popup = nfc->popup;
NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data;
if(strcmp(nfc->dev.dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
} else if(data->uid_len == 4) {
nfc_text_store_set(
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
} else if(data->uid_len == 7) {
nfc_text_store_set(
nfc,
"%02X %02X %02X %02X\n%02X %02X %02X",
data->uid[0],
data->uid[1],
data->uid[2],
data->uid[3],
data->uid[4],
data->uid[5],
data->uid[6]);
}
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
popup_set_header(popup, "Emulating Mf Ul", 56, 31, AlignLeft, AlignTop);
popup_set_text(popup, nfc->text_store, 56, 43, AlignLeft, AlignTop);
// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateMifareUl, &nfc->dev.dev_data, NULL, nfc);
}
const bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
bool consumed = false;
if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
consumed = true;
}
return consumed;
}
const void nfc_scene_emulate_mifare_ul_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
}

14
applications/nfc/scenes/nfc_scene_emulate_uid.c Normal file → Executable file
View file

@ -5,10 +5,10 @@ const void nfc_scene_emulate_uid_on_enter(void* context) {
// Setup view
Popup* popup = nfc->popup;
NfcDeviceData* data = &nfc->device.data;
NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data;
if(strcmp(nfc->device.dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->device.dev_name);
if(strcmp(nfc->dev.dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
} else if(data->uid_len == 4) {
nfc_text_store_set(
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
@ -31,10 +31,8 @@ const void nfc_scene_emulate_uid_on_enter(void* context) {
// Setup and start worker
nfc_worker_set_emulation_params(nfc->nfc_common.worker, data);
nfc_worker_start(
nfc->nfc_common.worker, NfcWorkerStateEmulate, &nfc->nfc_common.worker_result, NULL, nfc);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev.dev_data, NULL, nfc);
}
const bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) {
@ -51,7 +49,7 @@ const void nfc_scene_emulate_uid_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->nfc_common.worker);
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;

View file

@ -3,7 +3,7 @@
const void nfc_scene_file_select_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Process file_select return
if(nfc_file_select(&nfc->device)) {
if(nfc_file_select(&nfc->dev)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
} else {
scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);

View file

@ -8,7 +8,7 @@ enum SubmenuIndex {
void nfc_scene_mifare_ul_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_mifare_ul_menu_on_enter(void* context) {
@ -22,7 +22,7 @@ const void nfc_scene_mifare_ul_menu_on_enter(void* context) {
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareUlMenu));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
@ -32,7 +32,8 @@ const bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent ev
if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
nfc->dev.format = NfcDeviceSaveFormatMifareUl;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
} else if(event.event == SubmenuIndexEmulate) {
scene_manager_set_scene_state(

View file

@ -3,7 +3,7 @@
void nfc_scene_not_implemented_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, result);
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
const void nfc_scene_not_implemented_on_enter(void* context) {
@ -16,7 +16,7 @@ const void nfc_scene_not_implemented_on_enter(void* context) {
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_not_implemented_dialog_callback);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
const bool nfc_scene_not_implemented_on_event(void* context, SceneManagerEvent event) {

View file

@ -1,8 +1,10 @@
#include "../nfc_i.h"
#define NFC_READ_CARD_CUSTOM_EVENT (0UL)
void nfc_read_card_worker_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, NfcEventDetect);
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_CARD_CUSTOM_EVENT);
}
const void nfc_scene_read_card_on_enter(void* context) {
@ -14,21 +16,16 @@ const void nfc_scene_read_card_on_enter(void* context) {
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
// Start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(
nfc->nfc_common.worker,
NfcWorkerStateDetect,
&nfc->nfc_common.worker_result,
nfc_read_card_worker_callback,
nfc);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
nfc->worker, NfcWorkerStateDetect, &nfc->dev.dev_data, nfc_read_card_worker_callback, nfc);
}
const bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcEventDetect) {
nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
if(event.event == NFC_READ_CARD_CUSTOM_EVENT) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
return true;
}
@ -43,7 +40,7 @@ const void nfc_scene_read_card_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->nfc_common.worker);
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;

View file

@ -5,20 +5,20 @@
void nfc_scene_read_card_success_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, result);
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
const void nfc_scene_read_card_success_on_enter(void* context) {
void nfc_scene_read_card_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Clear device name
nfc_device_set_name(&nfc->device, "");
nfc_device_set_name(&nfc->dev, "");
// Send notification
notification_message(nfc->notifications, &sequence_success);
// Setup view
NfcDeviceData* data = (NfcDeviceData*)&nfc->nfc_common.worker_result;
NfcDeviceCommomData* data = (NfcDeviceCommomData*)&nfc->dev.dev_data.nfc_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "More");
@ -60,7 +60,7 @@ const void nfc_scene_read_card_success_on_enter(void* context) {
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_card_success_dialog_callback);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
const bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event) {

View file

@ -0,0 +1,54 @@
#include "../nfc_i.h"
#define NFC_READ_EMV_APP_CUSTOM_EVENT (0UL)
void nfc_read_emv_app_worker_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_EMV_APP_CUSTOM_EVENT);
}
const void nfc_scene_read_emv_app_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup view
Popup* popup = nfc->popup;
popup_set_header(popup, "Reading\nbank card", 70, 34, AlignLeft, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
// Start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadEMVApp,
&nfc->dev.dev_data,
nfc_read_emv_app_worker_callback,
nfc);
}
const bool nfc_scene_read_emv_app_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NFC_READ_EMV_APP_CUSTOM_EVENT) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvAppSuccess);
return true;
}
} else if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
return true;
}
return false;
}
const void nfc_scene_read_emv_app_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
}

View file

@ -0,0 +1,69 @@
#include "../nfc_i.h"
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
void nfc_scene_read_emv_app_success_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_read_emv_app_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup view
NfcDeviceCommomData* nfc_data = &nfc->dev.dev_data.nfc_data;
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "Run app");
dialog_ex_set_header(dialog_ex, "Found EMV App", 36, 8, AlignLeft, AlignCenter);
dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
// Display UID and AID
string_t aid;
string_init_printf(aid, "AID:");
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
string_cat_printf(aid, " %02X", emv_data->aid[i]);
}
nfc_text_store_set(
nfc,
NFC_SCENE_READ_SUCCESS_SHIFT "UID: %02X %02X %02X %02X \n\n%s",
nfc_data->uid[0],
nfc_data->uid[1],
nfc_data->uid[2],
nfc_data->uid[3],
string_get_cstr(aid));
string_clear(aid);
dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 16, AlignLeft, AlignTop);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_emv_app_success_dialog_callback);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
const bool nfc_scene_read_emv_app_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DialogExResultLeft) {
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == DialogExResultRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneRunEmvAppConfirm);
return true;
}
}
return false;
}
const void nfc_scene_read_emv_app_success_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, NULL);
dialog_ex_set_right_button_text(dialog_ex, NULL);
dialog_ex_set_result_callback(dialog_ex, NULL);
dialog_ex_set_context(dialog_ex, NULL);
}

View file

@ -0,0 +1,57 @@
#include "../nfc_i.h"
#define NFC_READ_EMV_DATA_CUSTOM_EVENT (0UL)
void nfc_read_emv_data_worker_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_EMV_DATA_CUSTOM_EVENT);
}
const void nfc_scene_read_emv_data_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Setup view
Popup* popup = nfc->popup;
popup_set_header(popup, "Reading\nbank card", 70, 34, AlignLeft, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
// Start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadEMV,
&nfc->dev.dev_data,
nfc_read_emv_data_worker_callback,
nfc);
}
const bool nfc_scene_read_emv_data_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NFC_READ_EMV_DATA_CUSTOM_EVENT) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvDataSuccess);
return true;
}
} else if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
return true;
}
return false;
}
const void nfc_scene_read_emv_data_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->worker);
// Send notification
notification_message(nfc->notifications, &sequence_success);
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
}

View file

@ -0,0 +1,89 @@
#include "../nfc_i.h"
void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_read_emv_data_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
NfcDeviceCommomData* nfc_data = &nfc->dev.dev_data.nfc_data;
// Clear device name
nfc_device_set_name(&nfc->dev, "");
// Setup Custom Widget view
gui_widget_add_button_element(
nfc->widget,
GuiButtonTypeLeft,
"Back",
nfc_scene_read_emv_data_success_widget_callback,
nfc);
gui_widget_add_button_element(
nfc->widget,
GuiButtonTypeRight,
"Save",
nfc_scene_read_emv_data_success_widget_callback,
nfc);
gui_widget_add_string_element(
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name);
char pan_str[32];
snprintf(
pan_str,
sizeof(pan_str),
"%02X%02X %02X%02X %02X%02X %02X%02X",
emv_data->number[0],
emv_data->number[1],
emv_data->number[2],
emv_data->number[3],
emv_data->number[4],
emv_data->number[5],
emv_data->number[6],
emv_data->number[7]);
gui_widget_add_string_element(
nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, pan_str);
char atqa_str[16];
snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]);
gui_widget_add_string_element(
nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, atqa_str);
char uid_str[32];
snprintf(
uid_str,
sizeof(uid_str),
"UID: %02X %02X %02X %02X",
nfc_data->uid[0],
nfc_data->uid[1],
nfc_data->uid[2],
nfc_data->uid[3]);
gui_widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, uid_str);
char sak_str[16];
snprintf(sak_str, sizeof(sak_str), "SAK: %02X", nfc_data->sak);
gui_widget_add_string_element(
nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, sak_str);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
const bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
return scene_manager_search_previous_scene(
nfc->scene_manager, NfcSceneReadEmvAppSuccess);
} else if(event.event == GuiButtonTypeRight) {
nfc->dev.format = NfcDeviceSaveFormatBankCard;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
}
}
return false;
}
const void nfc_scene_read_emv_data_success_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
gui_widget_clear(nfc->widget);
}

View file

@ -1,8 +1,10 @@
#include "../nfc_i.h"
#define NFC_READ_MIFARE_UL_CUSTOM_EVENT (0UL)
void nfc_read_mifare_ul_worker_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, NfcEventMifareUl);
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_MIFARE_UL_CUSTOM_EVENT);
}
const void nfc_scene_read_mifare_ul_on_enter(void* context) {
@ -13,22 +15,21 @@ const void nfc_scene_read_mifare_ul_on_enter(void* context) {
popup_set_header(popup, "Detecting\nultralight", 70, 34, AlignLeft, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
// Start worker
nfc_worker_start(
nfc->nfc_common.worker,
NfcWorkerStateReadMfUltralight,
&nfc->nfc_common.worker_result,
nfc->worker,
NfcWorkerStateReadMifareUl,
&nfc->dev.dev_data,
nfc_read_mifare_ul_worker_callback,
nfc);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
}
const bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcEventMifareUl) {
nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
if(event.event == NFC_READ_MIFARE_UL_CUSTOM_EVENT) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUlSuccess);
return true;
}
@ -43,7 +44,7 @@ const void nfc_scene_read_mifare_ul_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->nfc_common.worker);
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;

View file

@ -11,28 +11,26 @@ enum {
void nfc_scene_read_mifare_ul_success_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, result);
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_read_mifare_ul_success_text_box_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(
nfc->nfc_common.view_dispatcher, NFC_SCENE_READ_MF_UL_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_READ_MF_UL_CUSTOM_EVENT);
}
const void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
// Clear device name
nfc_device_set_name(&nfc->device, "");
nfc_device_set_name(&nfc->dev, "");
// Send notification
notification_message(nfc->notifications, &sequence_success);
// Setup dialog view
NfcDeviceData* data =
(NfcDeviceData*)&nfc->nfc_common.worker_result.nfc_mifare_ul_data.nfc_data;
NfcDeviceCommomData* data = (NfcDeviceCommomData*)&nfc->dev.dev_data.nfc_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "More");
@ -59,27 +57,23 @@ const void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback);
// Setup TextBox view
NfcMifareUlData* mf_ul_data =
(NfcMifareUlData*)&nfc->nfc_common.worker_result.nfc_mifare_ul_data;
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
TextBox* text_box = nfc->text_box;
text_box_set_context(text_box, nfc);
text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);
text_box_set_font(text_box, TextBoxFontHex);
for(uint16_t i = 0; i < mf_ul_data->dump_size; i += 2) {
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->full_dump[i],
mf_ul_data->full_dump[i + 1]);
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, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
const bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent event) {
@ -101,7 +95,7 @@ const bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManager
(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
ReadMifareUlStateShowUID) &&
(event.event == DialogExResultCenter)) {
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowData);
return true;
@ -109,7 +103,7 @@ const bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManager
(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
ReadMifareUlStateShowData) &&
(event.event == NFC_SCENE_READ_MF_UL_CUSTOM_EVENT)) {
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID);
return true;

View file

@ -0,0 +1,56 @@
#include "../nfc_i.h"
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
void nfc_scene_run_emv_app_confirm_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_run_emv_app_confirm_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Back");
dialog_ex_set_right_button_text(dialog_ex, "Run");
dialog_ex_set_header(dialog_ex, "Run EMV app?", 64, 8, AlignCenter, AlignCenter);
dialog_ex_set_text(
dialog_ex,
"It will try to run card's app\nand detect unencrypred\ndata",
64,
18,
AlignCenter,
AlignTop);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_run_emv_app_confirm_dialog_callback);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
const bool nfc_scene_run_emv_app_confirm_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DialogExResultLeft) {
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == DialogExResultRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvData);
return true;
}
}
return false;
}
const void nfc_scene_run_emv_app_confirm_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, NULL);
dialog_ex_set_right_button_text(dialog_ex, NULL);
dialog_ex_set_result_callback(dialog_ex, NULL);
dialog_ex_set_context(dialog_ex, NULL);
}

View file

@ -5,8 +5,7 @@
void nfc_scene_save_name_text_input_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(
nfc->nfc_common.view_dispatcher, SCENE_SAVE_NAME_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_NAME_CUSTOM_EVENT);
}
const void nfc_scene_save_name_on_enter(void* context) {
@ -14,7 +13,10 @@ const void nfc_scene_save_name_on_enter(void* context) {
// Setup view
TextInput* text_input = nfc->text_input;
nfc_text_store_clear(nfc);
if(nfc->dev.dev_name) {
nfc_device_delete(&nfc->dev);
}
nfc_text_store_set(nfc, nfc->dev.dev_name);
text_input_set_header_text(text_input, "Name the card");
text_input_set_result_callback(
text_input,
@ -22,7 +24,7 @@ const void nfc_scene_save_name_on_enter(void* context) {
nfc,
nfc->text_store,
sizeof(nfc->text_store));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextInput);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
}
const bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
@ -30,8 +32,8 @@ const bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event)
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
memcpy(&nfc->device.dev_name, nfc->text_store, strlen(nfc->text_store));
if(nfc_device_save(&nfc->device, nfc->text_store)) {
memcpy(&nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store));
if(nfc_device_save(&nfc->dev, nfc->text_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
return true;
} else {

View file

@ -4,8 +4,7 @@
void nfc_scene_save_success_popup_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(
nfc->nfc_common.view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT);
}
const void nfc_scene_save_success_on_enter(void* context) {
@ -19,7 +18,7 @@ const void nfc_scene_save_success_on_enter(void* context) {
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_save_success_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
const bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {

View file

@ -10,15 +10,17 @@ enum SubmenuIndex {
void nfc_scene_saved_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_saved_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
if(nfc->dev.format != NfcDeviceSaveFormatBankCard) {
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
}
submenu_add_item(
submenu, "Edit UID and name", SubmenuIndexEdit, nfc_scene_saved_menu_submenu_callback, nfc);
submenu_add_item(
@ -28,7 +30,7 @@ const void nfc_scene_saved_menu_on_enter(void* context) {
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
@ -42,16 +44,16 @@ const bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event)
return true;
} else if(event.event == SubmenuIndexEdit) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexEdit);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
return true;
} else if(event.event == SubmenuIndexDelete) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexDelete);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
return true;
} else if(event.event == SubmenuIndexInfo) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexInfo);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
return true;
}
}

View file

@ -8,7 +8,7 @@ enum SubmenuIndex {
void nfc_scene_scripts_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_scripts_menu_on_enter(void* context) {
@ -29,7 +29,7 @@ const void nfc_scene_scripts_menu_on_enter(void* context) {
nfc);
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneScriptsMenu));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent event) {
@ -39,7 +39,7 @@ const bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent even
if(event.event == SubmenuIndexBankCard) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexBankCard);
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
return true;
} else if(event.event == SubmenuIndexMifareUltralight) {
scene_manager_set_scene_state(

View file

@ -5,8 +5,7 @@
void nfc_scene_set_atqa_byte_input_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(
nfc->nfc_common.view_dispatcher, SCENE_SET_ATQA_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_ATQA_CUSTOM_EVENT);
}
const void nfc_scene_set_atqa_on_enter(void* context) {
@ -16,8 +15,13 @@ const void nfc_scene_set_atqa_on_enter(void* context) {
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter atqa in hex");
byte_input_set_result_callback(
byte_input, nfc_scene_set_atqa_byte_input_callback, NULL, nfc, nfc->device.data.atqa, 2);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
byte_input,
nfc_scene_set_atqa_byte_input_callback,
NULL,
nfc,
nfc->dev.dev_data.nfc_data.atqa,
2);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}
const bool nfc_scene_set_atqa_on_event(void* context, SceneManagerEvent event) {

View file

@ -5,7 +5,7 @@
void nfc_scene_set_sak_byte_input_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, SCENE_SET_SAK_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_SAK_CUSTOM_EVENT);
}
const void nfc_scene_set_sak_on_enter(void* context) {
@ -15,8 +15,13 @@ const void nfc_scene_set_sak_on_enter(void* context) {
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter SAK in hex");
byte_input_set_result_callback(
byte_input, nfc_scene_set_sak_byte_input_callback, NULL, nfc, &nfc->device.data.sak, 1);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
byte_input,
nfc_scene_set_sak_byte_input_callback,
NULL,
nfc,
&nfc->dev.dev_data.nfc_data.sak,
1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}
const bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) {

View file

@ -8,7 +8,7 @@ enum SubmenuIndex {
void nfc_scene_set_type_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_set_type_on_enter(void* context) {
@ -19,7 +19,7 @@ const void nfc_scene_set_type_on_enter(void* context) {
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
submenu_add_item(
submenu, "NFC-A 4-bytes UID", SubmenuIndexNFCA4, nfc_scene_set_type_submenu_callback, nfc);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
@ -27,11 +27,13 @@ const bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexNFCA7) {
nfc->device.data.uid_len = 7;
nfc->dev.dev_data.nfc_data.uid_len = 7;
nfc->dev.format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
return true;
} else if(event.event == SubmenuIndexNFCA4) {
nfc->device.data.uid_len = 4;
nfc->dev.dev_data.nfc_data.uid_len = 4;
nfc->dev.format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
return true;
}

View file

@ -5,7 +5,7 @@
void nfc_scene_set_uid_byte_input_callback(void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, SCENE_SET_UID_CUSTOM_EVENT);
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_UID_CUSTOM_EVENT);
}
const void nfc_scene_set_uid_on_enter(void* context) {
@ -19,9 +19,9 @@ const void nfc_scene_set_uid_on_enter(void* context) {
nfc_scene_set_uid_byte_input_callback,
NULL,
nfc,
nfc->device.data.uid,
nfc->device.data.uid_len);
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
nfc->dev.dev_data.nfc_data.uid,
nfc->dev.dev_data.nfc_data.uid_len);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}
const bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {

View file

@ -5,13 +5,12 @@ enum SubmenuIndex {
SubmenuIndexRunScript,
SubmenuIndexSaved,
SubmenuIndexAddManualy,
SubmenuIndexDebug,
};
void nfc_scene_start_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index);
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
const void nfc_scene_start_on_enter(void* context) {
@ -30,11 +29,11 @@ const void nfc_scene_start_on_enter(void* context) {
submenu, "Saved cards", SubmenuIndexSaved, nfc_scene_start_submenu_callback, nfc);
submenu_add_item(
submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc);
submenu_add_item(submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
nfc_device_clear(&nfc->dev);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
const bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
@ -59,10 +58,6 @@ const bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManualy);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
return true;
} else if(event.event == SubmenuIndexDebug) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugMenu);
return true;
}
}
return false;

View file

@ -0,0 +1,65 @@
#include "bank_card.h"
#include "../gui_widget/gui_widget.h"
#include <m-string.h>
struct BankCard {
GuiWidget* widget;
};
BankCard* bank_card_alloc() {
BankCard* bank_card = furi_alloc(sizeof(BankCard));
bank_card->widget = gui_widget_alloc();
return bank_card;
}
void bank_card_free(BankCard* bank_card) {
furi_assert(bank_card);
gui_widget_free(bank_card->widget);
free(bank_card);
}
View* bank_card_get_view(BankCard* bank_card) {
furi_assert(bank_card);
return gui_widget_get_view(bank_card->widget);
}
void bank_card_clear(BankCard* bank_card) {
furi_assert(bank_card);
gui_widget_clear(bank_card->widget);
}
void bank_card_set_name(BankCard* bank_card, char* name) {
furi_assert(bank_card);
furi_assert(name);
gui_widget_add_string_element(
bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name);
}
void bank_card_set_number(BankCard* bank_card, uint8_t* number) {
furi_assert(bank_card);
furi_assert(number);
string_t num_str;
string_init(num_str);
for(uint8_t i = 0; i < 8; i += 2) {
string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]);
}
gui_widget_add_string_element(
bank_card->widget, 25, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(num_str));
gui_widget_add_icon_element(bank_card->widget, 6, 20, &I_EMV_Chip_14x11);
string_clear(num_str);
}
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint16_t year) {
furi_assert(bank_card);
char exp_date_str[16];
snprintf(exp_date_str, sizeof(exp_date_str), "Exp: %02d/%02d", mon, year % 100);
gui_widget_add_string_element(
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
}
void bank_card_set_cardholder_name(BankCard* bank_card, char* name) {
furi_assert(bank_card);
furi_assert(name);
gui_widget_add_string_element(
bank_card->widget, 6, 37, AlignLeft, AlignTop, FontSecondary, name);
}

View file

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include <gui/view.h>
typedef struct BankCard BankCard;
typedef void (*BankCardBackCallback)(void);
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_name(BankCard* bank_card, char* name);
void bank_card_set_number(BankCard* bank_card, uint8_t* number);
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint16_t year);
void bank_card_set_cardholder_name(BankCard* bank_card, char* name);

View file

@ -1,142 +0,0 @@
#include "nfc_detect.h"
#include <furi.h>
#include <api-hal.h>
#include <input/input.h>
#include "../nfc_i.h"
struct NfcDetect {
NfcCommon* nfc_common;
View* view;
};
typedef struct {
bool found;
NfcDeviceData data;
} NfcDetectModel;
void nfc_detect_draw(Canvas* canvas, NfcDetectModel* model) {
char buffer[32];
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
if(model->found) {
canvas_draw_str(canvas, 0, 12, "Found");
canvas_draw_str(canvas, 32, 12, nfc_get_dev_type(model->data.device));
canvas_set_font(canvas, FontSecondary);
if(model->data.protocol != NfcDeviceProtocolUnknown) {
canvas_draw_str(canvas, 0, 22, nfc_get_protocol(model->data.protocol));
}
// Display UID
for(uint8_t i = 0; i < model->data.uid_len; i++) {
snprintf(buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", model->data.uid[i]);
buffer[model->data.uid_len * 2] = 0;
}
canvas_draw_str(canvas, 0, 32, "UID: ");
canvas_draw_str(canvas, 22, 32, buffer);
// Display ATQA and SAK
snprintf(
buffer,
sizeof(buffer),
"ATQA: %02X %02X SAK: %02X",
model->data.atqa[1],
model->data.atqa[0],
model->data.sak);
canvas_draw_str(canvas, 0, 42, buffer);
} else {
canvas_draw_str(canvas, 0, 12, "Searching");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Place card to the back");
}
}
bool nfc_detect_input(InputEvent* event, void* context) {
if(event->key == InputKeyBack) {
return false;
}
return true;
}
void nfc_detect_worker_callback(void* context) {
furi_assert(context);
NfcDetect* nfc_detect = (NfcDetect*)context;
view_dispatcher_send_custom_event(nfc_detect->nfc_common->view_dispatcher, NfcEventDetect);
}
bool nfc_detect_view_custom(uint32_t event, void* context) {
furi_assert(context);
NfcDetect* nfc_detect = (NfcDetect*)context;
if(event == NfcEventDetect) {
NfcDeviceData* data = (NfcDeviceData*)&nfc_detect->nfc_common->worker_result;
with_view_model(
nfc_detect->view, (NfcDetectModel * model) {
model->found = true;
model->data = *data;
return true;
});
// TODO add and configure next view model
return false;
}
return false;
}
void nfc_detect_enter(void* context) {
furi_assert(context);
NfcDetect* nfc_detect = (NfcDetect*)context;
with_view_model(
nfc_detect->view, (NfcDetectModel * model) {
model->found = false;
model->data.protocol = NfcDeviceProtocolUnknown;
return true;
});
nfc_worker_start(
nfc_detect->nfc_common->worker,
NfcWorkerStateDetect,
&nfc_detect->nfc_common->worker_result,
nfc_detect_worker_callback,
nfc_detect);
}
void nfc_detect_exit(void* context) {
furi_assert(context);
NfcDetect* nfc_detect = (NfcDetect*)context;
nfc_worker_stop(nfc_detect->nfc_common->worker);
}
NfcDetect* nfc_detect_alloc(NfcCommon* nfc_common) {
furi_assert(nfc_common);
NfcDetect* nfc_detect = furi_alloc(sizeof(NfcDetect));
nfc_detect->nfc_common = nfc_common;
// View allocation and configuration
nfc_detect->view = view_alloc();
view_allocate_model(nfc_detect->view, ViewModelTypeLockFree, sizeof(NfcDetectModel));
view_set_context(nfc_detect->view, nfc_detect);
view_set_draw_callback(nfc_detect->view, (ViewDrawCallback)nfc_detect_draw);
view_set_input_callback(nfc_detect->view, nfc_detect_input);
view_set_custom_callback(nfc_detect->view, nfc_detect_view_custom);
view_set_enter_callback(nfc_detect->view, nfc_detect_enter);
view_set_exit_callback(nfc_detect->view, nfc_detect_exit);
return nfc_detect;
}
void nfc_detect_free(NfcDetect* nfc_detect) {
furi_assert(nfc_detect);
view_free(nfc_detect->view);
free(nfc_detect);
}
View* nfc_detect_get_view(NfcDetect* nfc_detect) {
furi_assert(nfc_detect);
return nfc_detect->view;
}

View file

@ -1,12 +0,0 @@
#pragma once
#include <gui/view.h>
#include "../nfc_types.h"
typedef struct NfcDetect NfcDetect;
NfcDetect* nfc_detect_alloc(NfcCommon* nfc_common);
void nfc_detect_free(NfcDetect* nfc_detect);
View* nfc_detect_get_view(NfcDetect* nfc_detect);

View file

@ -1,79 +0,0 @@
#include "nfc_emulate.h"
#include <furi.h>
#include <api-hal.h>
#include <input/input.h>
#include "../nfc_i.h"
struct NfcEmulate {
NfcCommon* nfc_common;
View* view;
};
void nfc_emulate_draw(Canvas* canvas, void* model) {
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 0, 12, "Emulating NFC-A");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Type: T2T");
canvas_draw_str(canvas, 2, 32, "UID length: 7");
canvas_draw_str(canvas, 2, 42, "UID: 36 9C E7 B1 0A C1 34");
canvas_draw_str(canvas, 2, 52, "SAK: 00 ATQA: 00/44");
}
bool nfc_emulate_input(InputEvent* event, void* context) {
if(event->key == InputKeyBack) {
return false;
}
return true;
}
void nfc_emulate_enter(void* context) {
furi_assert(context);
NfcEmulate* nfc_emulate = (NfcEmulate*)context;
nfc_worker_start(
nfc_emulate->nfc_common->worker,
NfcWorkerStateEmulate,
&nfc_emulate->nfc_common->worker_result,
NULL,
NULL);
}
void nfc_emulate_exit(void* context) {
furi_assert(context);
NfcEmulate* nfc_emulate = (NfcEmulate*)context;
nfc_worker_stop(nfc_emulate->nfc_common->worker);
}
NfcEmulate* nfc_emulate_alloc(NfcCommon* nfc_common) {
furi_assert(nfc_common);
NfcEmulate* nfc_emulate = furi_alloc(sizeof(NfcEmulate));
nfc_emulate->nfc_common = nfc_common;
// View allocation and configuration
nfc_emulate->view = view_alloc();
view_set_context(nfc_emulate->view, nfc_emulate);
view_set_draw_callback(nfc_emulate->view, (ViewDrawCallback)nfc_emulate_draw);
view_set_input_callback(nfc_emulate->view, nfc_emulate_input);
view_set_enter_callback(nfc_emulate->view, nfc_emulate_enter);
view_set_exit_callback(nfc_emulate->view, nfc_emulate_exit);
return nfc_emulate;
}
void nfc_emulate_free(NfcEmulate* nfc_emulate) {
furi_assert(nfc_emulate);
view_free(nfc_emulate->view);
free(nfc_emulate);
}
View* nfc_emulate_get_view(NfcEmulate* nfc_emulate) {
furi_assert(nfc_emulate);
return nfc_emulate->view;
}

View file

@ -1,12 +0,0 @@
#pragma once
#include <gui/view.h>
#include "../nfc_types.h"
typedef struct NfcEmulate NfcEmulate;
NfcEmulate* nfc_emulate_alloc(NfcCommon* nfc_common);
void nfc_emulate_free(NfcEmulate* nfc_emulate);
View* nfc_emulate_get_view(NfcEmulate* nfc_emulate);

View file

@ -1,133 +0,0 @@
#include "nfc_emv.h"
#include <furi.h>
#include <api-hal.h>
#include <input/input.h>
#include "../nfc_i.h"
struct NfcEmv {
NfcCommon* nfc_common;
View* view;
};
typedef struct {
bool found;
NfcEmvData emv_data;
} NfcEmvModel;
void nfc_emv_draw(Canvas* canvas, NfcEmvModel* model) {
char buffer[32];
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
if(model->found) {
canvas_draw_str(canvas, 0, 12, "Found EMV card");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Type:");
snprintf(buffer, sizeof(buffer), "%s", model->emv_data.name);
canvas_draw_str(canvas, 2, 32, buffer);
snprintf(buffer, sizeof(buffer), "Number:\n");
canvas_draw_str(canvas, 2, 42, buffer);
uint8_t card_num_len = sizeof(model->emv_data.number);
for(uint8_t i = 0; i < card_num_len; i++) {
snprintf(
buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", model->emv_data.number[i]);
}
buffer[card_num_len * 2] = 0;
canvas_draw_str(canvas, 2, 52, buffer);
} else {
canvas_draw_str(canvas, 0, 12, "Searching");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Place card to the back");
}
}
bool nfc_emv_input(InputEvent* event, void* context) {
if(event->key == InputKeyBack) {
return false;
}
return true;
}
void nfc_emv_worker_callback(void* context) {
furi_assert(context);
NfcEmv* nfc_emv = (NfcEmv*)context;
view_dispatcher_send_custom_event(nfc_emv->nfc_common->view_dispatcher, NfcEventEmv);
}
bool nfc_emv_custom(uint32_t event, void* context) {
furi_assert(context);
NfcEmv* nfc_emv = (NfcEmv*)context;
if(event == NfcEventEmv) {
NfcEmvData* data = (NfcEmvData*)&nfc_emv->nfc_common->worker_result;
with_view_model(
nfc_emv->view, (NfcEmvModel * model) {
model->found = true;
model->emv_data = *data;
return true;
});
// TODO add and configure next view model
return true;
}
return false;
}
void nfc_emv_enter(void* context) {
furi_assert(context);
NfcEmv* nfc_emv = (NfcEmv*)context;
with_view_model(
nfc_emv->view, (NfcEmvModel * model) {
model->found = false;
return true;
});
nfc_worker_start(
nfc_emv->nfc_common->worker,
NfcWorkerStateReadEMV,
&nfc_emv->nfc_common->worker_result,
nfc_emv_worker_callback,
nfc_emv);
}
void nfc_emv_exit(void* context) {
furi_assert(context);
NfcEmv* nfc_emv = (NfcEmv*)context;
nfc_worker_stop(nfc_emv->nfc_common->worker);
}
NfcEmv* nfc_emv_alloc(NfcCommon* nfc_common) {
furi_assert(nfc_common);
NfcEmv* nfc_emv = furi_alloc(sizeof(NfcEmv));
nfc_emv->nfc_common = nfc_common;
// View allocation and configuration
nfc_emv->view = view_alloc();
view_allocate_model(nfc_emv->view, ViewModelTypeLockFree, sizeof(NfcEmvModel));
view_set_context(nfc_emv->view, nfc_emv);
view_set_draw_callback(nfc_emv->view, (ViewDrawCallback)nfc_emv_draw);
view_set_input_callback(nfc_emv->view, nfc_emv_input);
view_set_custom_callback(nfc_emv->view, nfc_emv_custom);
view_set_enter_callback(nfc_emv->view, nfc_emv_enter);
view_set_exit_callback(nfc_emv->view, nfc_emv_exit);
return nfc_emv;
}
void nfc_emv_free(NfcEmv* nfc_emv) {
furi_assert(nfc_emv);
view_free(nfc_emv->view);
free(nfc_emv);
}
View* nfc_emv_get_view(NfcEmv* nfc_emv) {
furi_assert(nfc_emv);
return nfc_emv->view;
}

View file

@ -1,12 +0,0 @@
#pragma once
#include <gui/view.h>
#include "../nfc_types.h"
typedef struct NfcEmv NfcEmv;
NfcEmv* nfc_emv_alloc(NfcCommon* nfc_common);
void nfc_emv_free(NfcEmv* nfc_emv);
View* nfc_emv_get_view(NfcEmv* nfc_emv);

View file

@ -1,162 +0,0 @@
#include "nfc_mifare_ul.h"
#include <furi.h>
#include <api-hal.h>
#include <input/input.h>
#include "../nfc_i.h"
struct NfcMifareUl {
NfcCommon* nfc_common;
View* view;
};
typedef struct {
bool found;
NfcMifareUlData nfc_mf_ul_data;
} NfcMifareUlModel;
void nfc_mifare_ul_draw(Canvas* canvas, NfcMifareUlModel* model) {
char buffer[32];
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
if(model->found) {
canvas_draw_str(canvas, 0, 12, "Found Mifare Ultralight");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "UID:");
for(uint8_t i = 0; i < model->nfc_mf_ul_data.nfc_data.uid_len; i++) {
snprintf(
buffer + (i * 2),
sizeof(buffer) - (i * 2),
"%02X",
model->nfc_mf_ul_data.nfc_data.uid[i]);
}
buffer[model->nfc_mf_ul_data.nfc_data.uid_len * 2] = 0;
canvas_draw_str(canvas, 18, 22, buffer);
uint8_t man_bl_size = sizeof(model->nfc_mf_ul_data.man_block);
canvas_draw_str(canvas, 2, 32, "Manufacturer block:");
for(uint8_t i = 0; i < man_bl_size / 2; i++) {
snprintf(
buffer + (i * 2),
sizeof(buffer) - (i * 2),
"%02X",
model->nfc_mf_ul_data.man_block[i]);
}
buffer[man_bl_size] = 0;
canvas_draw_str(canvas, 2, 42, buffer);
for(uint8_t i = 0; i < man_bl_size / 2; i++) {
snprintf(
buffer + (i * 2),
sizeof(buffer) - (i * 2),
"%02X",
model->nfc_mf_ul_data.man_block[man_bl_size / 2 + i]);
}
buffer[man_bl_size] = 0;
canvas_draw_str(canvas, 2, 52, buffer);
canvas_draw_str(canvas, 2, 62, "OTP: ");
for(uint8_t i = 0; i < sizeof(model->nfc_mf_ul_data.otp); i++) {
snprintf(
buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", model->nfc_mf_ul_data.otp[i]);
}
buffer[sizeof(model->nfc_mf_ul_data.otp) * 2] = 0;
canvas_draw_str(canvas, 22, 62, buffer);
} else {
canvas_draw_str(canvas, 0, 12, "Searching");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Place card to the back");
}
}
bool nfc_mifare_ul_input(InputEvent* event, void* context) {
if(event->key == InputKeyBack) {
return false;
}
return true;
}
void nfc_mifare_ul_worker_callback(void* context) {
furi_assert(context);
NfcMifareUl* nfc_mifare_ul = (NfcMifareUl*)context;
view_dispatcher_send_custom_event(
nfc_mifare_ul->nfc_common->view_dispatcher, NfcEventMifareUl);
}
bool nfc_mifare_ul_custom(uint32_t event, void* context) {
furi_assert(context);
NfcMifareUl* nfc_mifare_ul = (NfcMifareUl*)context;
if(event == NfcEventMifareUl) {
NfcMifareUlData* data = (NfcMifareUlData*)&nfc_mifare_ul->nfc_common->worker_result;
with_view_model(
nfc_mifare_ul->view, (NfcMifareUlModel * model) {
model->found = true;
model->nfc_mf_ul_data = *data;
return true;
});
// TODO add and configure next view model
return true;
}
return false;
}
void nfc_mifare_ul_enter(void* context) {
furi_assert(context);
NfcMifareUl* nfc_mifare_ul = (NfcMifareUl*)context;
with_view_model(
nfc_mifare_ul->view, (NfcMifareUlModel * m) {
m->found = false;
return true;
});
nfc_worker_start(
nfc_mifare_ul->nfc_common->worker,
NfcWorkerStateReadMfUltralight,
&nfc_mifare_ul->nfc_common->worker_result,
nfc_mifare_ul_worker_callback,
nfc_mifare_ul);
}
void nfc_mifare_ul_exit(void* context) {
furi_assert(context);
NfcMifareUl* nfc_mifare_ul = (NfcMifareUl*)context;
nfc_worker_stop(nfc_mifare_ul->nfc_common->worker);
}
NfcMifareUl* nfc_mifare_ul_alloc(NfcCommon* nfc_common) {
furi_assert(nfc_common);
NfcMifareUl* nfc_mifare_ul = furi_alloc(sizeof(NfcMifareUl));
nfc_mifare_ul->nfc_common = nfc_common;
// View allocation and configuration
nfc_mifare_ul->view = view_alloc();
view_allocate_model(nfc_mifare_ul->view, ViewModelTypeLockFree, sizeof(NfcMifareUlModel));
view_set_context(nfc_mifare_ul->view, nfc_mifare_ul);
view_set_draw_callback(nfc_mifare_ul->view, (ViewDrawCallback)nfc_mifare_ul_draw);
view_set_input_callback(nfc_mifare_ul->view, nfc_mifare_ul_input);
view_set_custom_callback(nfc_mifare_ul->view, nfc_mifare_ul_custom);
view_set_enter_callback(nfc_mifare_ul->view, nfc_mifare_ul_enter);
view_set_exit_callback(nfc_mifare_ul->view, nfc_mifare_ul_exit);
return nfc_mifare_ul;
}
void nfc_mifare_ul_free(NfcMifareUl* nfc_mifare_ul) {
furi_assert(nfc_mifare_ul);
view_free(nfc_mifare_ul->view);
free(nfc_mifare_ul);
}
View* nfc_mifare_ul_get_view(NfcMifareUl* nfc_mifare_ul) {
furi_assert(nfc_mifare_ul);
return nfc_mifare_ul->view;
}

View file

@ -1,12 +0,0 @@
#pragma once
#include <gui/view.h>
#include "../nfc_types.h"
typedef struct NfcMifareUl NfcMifareUl;
NfcMifareUl* nfc_mifare_ul_alloc(NfcCommon* nfc_common);
void nfc_mifare_ul_free(NfcMifareUl* nfc_mifare_ul);
View* nfc_mifare_ul_get_view(NfcMifareUl* nfc_mifare_ul);

View file

@ -12,8 +12,9 @@ uint16_t mf_ul_prepare_get_version(uint8_t* dest) {
return 1;
}
void mf_ul_parse_get_version_response(uint8_t* buff, MfUltralightRead* mf_ul_read) {
void mf_ul_parse_get_version_response(uint8_t* buff, MifareUlDevice* mf_ul_read) {
MfUltralightVersion* version = (MfUltralightVersion*) buff;
memcpy(&mf_ul_read->data.version, version, sizeof(MfUltralightVersion));
if(version->storage_size == 0x0B || version->storage_size == 0x00) {
mf_ul_read->type = MfUltralightTypeUL11;
mf_ul_read->pages_to_read = 20;
@ -39,9 +40,9 @@ void mf_ul_parse_get_version_response(uint8_t* buff, MfUltralightRead* mf_ul_rea
}
}
void mf_ul_set_default_version(MfUltralightRead* mf_ul_read) {
void mf_ul_set_default_version(MifareUlDevice* mf_ul_read) {
mf_ul_read->type = MfUltralightTypeUnknown;
mf_ul_read->pages_to_read = 20;
mf_ul_read->pages_to_read = 16;
mf_ul_read->support_fast_read = false;
}
@ -51,9 +52,88 @@ uint16_t mf_ul_prepare_read(uint8_t* dest, uint8_t start_page) {
return 2;
}
void mf_ul_parse_read_response(uint8_t* buff, uint16_t page_addr, MifareUlDevice* mf_ul_read) {
mf_ul_read->pages_readed += 4;
mf_ul_read->data.data_size = mf_ul_read->pages_readed * 4;
memcpy(&mf_ul_read->data.data[page_addr * 4], buff, 16);
}
uint16_t mf_ul_prepare_fast_read(uint8_t* dest, uint8_t start_page, uint8_t end_page) {
dest[0] = MF_UL_FAST_READ_CMD;
dest[1] = start_page;
dest[2] = end_page;
return 3;
}
void mf_ul_parse_fast_read_response(uint8_t* buff, uint8_t start_page, uint8_t end_page, MifareUlDevice* mf_ul_read) {
mf_ul_read->pages_readed = end_page - start_page + 1;
mf_ul_read->data.data_size = mf_ul_read->pages_readed * 4;
memcpy(mf_ul_read->data.data, buff, mf_ul_read->data.data_size);
}
uint16_t mf_ul_prepare_read_signature(uint8_t* dest) {
dest[0] = MF_UL_CHECK_TEARING;
dest[1] = 0;
return 2;
}
void mf_ul_parse_read_signature_response(uint8_t* buff, MifareUlDevice* mf_ul_read) {
memcpy(mf_ul_read->data.signature, buff, sizeof(mf_ul_read->data.signature));
}
uint16_t mf_ul_prepare_read_cnt(uint8_t* dest, uint8_t cnt_index) {
if(cnt_index > 2) {
return 0;
}
dest[0] = MF_UL_READ_CNT;
dest[1] = cnt_index;
return 2;
}
void mf_ul_parse_read_cnt_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read) {
// Reverse LSB sequence
if(cnt_index < 3) {
mf_ul_read->data.counter[cnt_index] = (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}
}
uint16_t mf_ul_prepare_inc_cnt(uint8_t* dest, uint8_t cnt_index, uint32_t value) {
if(cnt_index > 2) {
return 0;
}
dest[0] = MF_UL_INC_CNT;
dest[1] = cnt_index;
dest[2] = (uint8_t) value;
dest[3] = (uint8_t) (value >> 8);
dest[4] = (uint8_t) (value >> 16);
dest[5] = 0;
return 6;
}
uint16_t mf_ul_prepare_check_tearing(uint8_t* dest, uint8_t cnt_index) {
if(cnt_index > 2) {
return 0;
}
dest[0] = MF_UL_CHECK_TEARING;
dest[1] = cnt_index;
return 2;
}
void mf_ul_parse_check_tearing_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read) {
if(cnt_index < 2) {
mf_ul_read->data.tearing[cnt_index] = buff[0];
}
}
uint16_t mf_ul_prepare_write(uint8_t* dest, uint16_t page_addr, uint32_t data) {
if(page_addr < 2) {
return 0;
}
dest[0] = MF_UL_WRITE;
dest[1] = page_addr;
dest[2] = (uint8_t) (data >> 24);
dest[3] = (uint8_t) (data >> 16);
dest[4] = (uint8_t) (data >> 8);
dest[5] = (uint8_t) data;
return 6;
}

View file

@ -4,9 +4,22 @@
#include <stdbool.h>
#include <string.h>
#define MF_UL_MAX_DUMP_SIZE 255
#define MF_UL_TEARING_FLAG_DEFAULT (0xBD)
#define MF_UL_GET_VERSION_CMD (0x60)
#define MF_UL_READ_CMD (0x30)
#define MF_UL_FAST_READ_CMD (0x3A)
#define MF_UL_WRITE (0xA2)
#define MF_UL_COMP_WRITE (0xA0)
#define MF_UL_READ_CNT (0x39)
#define MF_UL_INC_CNT (0xA5)
#define MF_UL_AUTH (0x1B)
#define MF_UL_READ_SIG (0x3C)
#define MF_UL_CHECK_TEARING (0x3E)
#define MF_UL_READ_VCSL (0x4B)
typedef enum {
MfUltralightTypeUnknown,
@ -38,19 +51,45 @@ typedef struct {
uint8_t otp[4];
} MfUltralightManufacturerBlock;
typedef struct {
MfUltralightVersion version;
uint8_t signature[32];
uint32_t counter[3];
uint8_t tearing[3];
uint16_t data_size;
uint8_t data[MF_UL_MAX_DUMP_SIZE];
} MifareUlData;
typedef struct {
MfUltralightType type;
uint8_t pages_to_read;
uint8_t pages_readed;
bool support_fast_read;
uint8_t dump[255];
} MfUltralightRead;
MifareUlData data;
} MifareUlDevice;
bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
uint16_t mf_ul_prepare_get_version(uint8_t* dest);
void mf_ul_parse_get_version_response(uint8_t* buff, MfUltralightRead* mf_ul_read);
void mf_ul_set_default_version(MfUltralightRead* mf_ul_read);
void mf_ul_parse_get_version_response(uint8_t* buff, MifareUlDevice* mf_ul_read);
void mf_ul_set_default_version(MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_read_signature(uint8_t* dest);
void mf_ul_parse_read_signature_response(uint8_t* buff, MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_read_cnt(uint8_t* dest, uint8_t cnt_index);
void mf_ul_parse_read_cnt_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_inc_cnt(uint8_t* dest, uint8_t cnt_index, uint32_t value);
uint16_t mf_ul_prepare_check_tearing(uint8_t* dest, uint8_t cnt_index);
void mf_ul_parse_check_tearing_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_read(uint8_t* dest, uint8_t start_page);
void mf_ul_parse_read_response(uint8_t* buff, uint16_t page_addr, MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_fast_read(uint8_t* dest, uint8_t start_page, uint8_t end_page);
void mf_ul_parse_fast_read_response(uint8_t* buff, uint8_t start_page, uint8_t end_page, MifareUlDevice* mf_ul_read);
uint16_t mf_ul_prepare_write(uint8_t* dest, uint16_t page_addr, uint32_t data);