[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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich