[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:
parent
7ca89256eb
commit
49af516ec7
84
applications/nfc/gui_widget/gui_element_button.c
Normal file
84
applications/nfc/gui_widget/gui_element_button.c
Normal 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;
|
||||
}
|
24
applications/nfc/gui_widget/gui_element_button.h
Normal file
24
applications/nfc/gui_widget/gui_element_button.h
Normal 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);
|
21
applications/nfc/gui_widget/gui_element_i.h
Normal file
21
applications/nfc/gui_widget/gui_element_i.h
Normal 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;
|
||||
};
|
51
applications/nfc/gui_widget/gui_element_icon.c
Normal file
51
applications/nfc/gui_widget/gui_element_icon.c
Normal 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;
|
||||
}
|
13
applications/nfc/gui_widget/gui_element_icon.h
Normal file
13
applications/nfc/gui_widget/gui_element_icon.h
Normal 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);
|
72
applications/nfc/gui_widget/gui_element_string.c
Executable file
72
applications/nfc/gui_widget/gui_element_string.c
Executable 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;
|
||||
}
|
21
applications/nfc/gui_widget/gui_element_string.h
Executable file
21
applications/nfc/gui_widget/gui_element_string.h
Executable 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);
|
141
applications/nfc/gui_widget/gui_widget.c
Executable file
141
applications/nfc/gui_widget/gui_widget.c
Executable 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);
|
||||
}
|
76
applications/nfc/gui_widget/gui_widget.h
Executable file
76
applications/nfc/gui_widget/gui_widget.h
Executable 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);
|
@ -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);
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
16
applications/nfc/nfc_device_i.h
Normal file
16
applications/nfc/nfc_device_i.h
Normal 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);
|
@ -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();
|
||||
|
@ -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";
|
||||
|
@ -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) {
|
||||
|
@ -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
10
applications/nfc/nfc_worker_i.h
Normal file → Executable 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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
}
|
@ -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) {
|
||||
}
|
@ -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);
|
||||
}
|
@ -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) {
|
||||
}
|
@ -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) {
|
||||
}
|
95
applications/nfc/scenes/nfc_scene_delete.c
Normal file
95
applications/nfc/scenes/nfc_scene_delete.c
Normal 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);
|
||||
}
|
47
applications/nfc/scenes/nfc_scene_delete_success.c
Normal file
47
applications/nfc/scenes/nfc_scene_delete_success.c
Normal 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);
|
||||
}
|
185
applications/nfc/scenes/nfc_scene_device_info.c
Executable file
185
applications/nfc/scenes/nfc_scene_device_info.c
Executable 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);
|
||||
}
|
||||
}
|
60
applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c
Executable file
60
applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c
Executable 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
14
applications/nfc/scenes/nfc_scene_emulate_uid.c
Normal file → Executable 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;
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
54
applications/nfc/scenes/nfc_scene_read_emv_app.c
Executable file
54
applications/nfc/scenes/nfc_scene_read_emv_app.c
Executable 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);
|
||||
}
|
69
applications/nfc/scenes/nfc_scene_read_emv_app_success.c
Executable file
69
applications/nfc/scenes/nfc_scene_read_emv_app_success.c
Executable 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);
|
||||
}
|
57
applications/nfc/scenes/nfc_scene_read_emv_data.c
Normal file
57
applications/nfc/scenes/nfc_scene_read_emv_data.c
Normal 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);
|
||||
}
|
89
applications/nfc/scenes/nfc_scene_read_emv_data_success.c
Executable file
89
applications/nfc/scenes/nfc_scene_read_emv_data_success.c
Executable 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);
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
56
applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c
Executable file
56
applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c
Executable 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);
|
||||
}
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
65
applications/nfc/views/bank_card.c
Executable file
65
applications/nfc/views/bank_card.c
Executable 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);
|
||||
}
|
23
applications/nfc/views/bank_card.h
Normal file
23
applications/nfc/views/bank_card.h
Normal 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);
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user