mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2025-02-17 13:58:32 +00:00
Merge remote-tracking branch 'upstream/dev' into feat/unirf-protocols
This commit is contained in:
commit
9eb9a44ee4
177 changed files with 3247 additions and 1397 deletions
|
@ -1,7 +1,10 @@
|
|||
### New changes
|
||||
* Fix qFlipper and other apps causes flipper crash while trying to interact with files - see commit `b2bd13`
|
||||
* NRF24 Sniffer update
|
||||
* Other fixes
|
||||
* Wifi Marauder app update (by @0xchocolate)
|
||||
* Updated Universal remote assets (by @Amec0e)
|
||||
* Fixed music player
|
||||
* Fixed typos in subghz encoders
|
||||
* OFW: New NFC info screens
|
||||
* OFW: U2F fixes
|
||||
|
||||
**Note: Prefer installing using web updater or by self update package, all needed assets will be installed**
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ See changelog in releases for latest updates!
|
|||
|
||||
## [- BadUSB: how to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||
|
||||
## [- How to change Flipper name](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||
|
||||
### **Plugins**
|
||||
|
||||
## [- Configure UniversalRF Remix App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/UniRFRemix.md)
|
||||
|
@ -121,7 +123,7 @@ See changelog in releases for latest updates!
|
|||
# Where I can find IR, SubGhz, ... files, DBs, and other stuff?
|
||||
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
||||
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
||||
## [CAME, NICE, PT-2240, PT-2262 - SubGHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
|
||||
## [CAME-12bit, NICE-12bit, Linear-10bit, PT-2240 - SubGHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <gui/modules/empty_screen.h>
|
||||
#include <m-string.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_region.h>
|
||||
#include <furi_hal_bt.h>
|
||||
|
||||
typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message);
|
||||
|
@ -114,12 +115,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage*
|
|||
|
||||
string_cat_printf(
|
||||
buffer,
|
||||
"%d.F%dB%dC%d %s %s\n",
|
||||
"%d.F%dB%dC%d %s:%s %s\n",
|
||||
furi_hal_version_get_hw_version(),
|
||||
furi_hal_version_get_hw_target(),
|
||||
furi_hal_version_get_hw_body(),
|
||||
furi_hal_version_get_hw_connect(),
|
||||
furi_hal_version_get_hw_region_name(),
|
||||
furi_hal_region_get_name(),
|
||||
my_name ? my_name : "Unknown");
|
||||
|
||||
string_cat_printf(buffer, "Serial Number:\n");
|
||||
|
|
|
@ -32,14 +32,14 @@ void AccessorApp::run(void) {
|
|||
}
|
||||
|
||||
AccessorApp::AccessorApp() {
|
||||
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||
onewire_host = onewire_host_alloc();
|
||||
furi_hal_power_enable_otg();
|
||||
}
|
||||
|
||||
AccessorApp::~AccessorApp() {
|
||||
furi_hal_power_disable_otg();
|
||||
furi_record_close("notification");
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
onewire_host_free(onewire_host);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ AccessorAppViewManager::AccessorAppViewManager() {
|
|||
popup = popup_alloc();
|
||||
add_view(ViewType::Popup, popup_get_view(popup));
|
||||
|
||||
gui = static_cast<Gui*>(furi_record_open("gui"));
|
||||
gui = static_cast<Gui*>(furi_record_open(RECORD_GUI));
|
||||
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// set previous view callback for all views
|
||||
|
@ -31,6 +31,7 @@ AccessorAppViewManager::~AccessorAppViewManager() {
|
|||
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup));
|
||||
|
||||
// free view modules
|
||||
furi_record_close(RECORD_GUI);
|
||||
submenu_free(submenu);
|
||||
popup_free(popup);
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ typedef struct {
|
|||
|
||||
typedef void (*FlipperOnStartHook)(void);
|
||||
|
||||
extern const char* FLIPPER_AUTORUN_APP_NAME;
|
||||
|
||||
/* Services list
|
||||
* Spawned on startup
|
||||
*/
|
||||
|
|
|
@ -64,7 +64,7 @@ uint16_t archive_favorites_count(void* context) {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue; // Skip empty lines
|
||||
}
|
||||
++lines;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ static bool archive_favourites_rescan() {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, "/app:") == 0) {
|
||||
|
@ -152,7 +152,7 @@ bool archive_favorites_read(void* context) {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, "/app:") == 0) {
|
||||
|
@ -215,7 +215,7 @@ bool archive_favorites_delete(const char* format, ...) {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(string_search(buffer, filename)) {
|
||||
|
@ -259,7 +259,7 @@ bool archive_is_favorite(const char* format, ...) {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(!string_search(buffer, filename)) {
|
||||
found = true;
|
||||
|
@ -299,7 +299,7 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
|||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
archive_file_append(
|
||||
|
|
|
@ -423,7 +423,7 @@ int32_t barcode_UPCA_generator_app(void* p) {
|
|||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
PluginEvent event;
|
||||
|
@ -537,7 +537,7 @@ int32_t barcode_UPCA_generator_app(void* p) {
|
|||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(last);
|
||||
printf("%-24s: %s\r\n", key, value);
|
||||
printf("%-30s: %s\r\n", key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -96,7 +96,7 @@ int32_t clock_app(void* p) {
|
|||
furi_timer_start(timer, furi_kernel_get_tick_frequency());
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
// Main loop
|
||||
|
@ -137,7 +137,7 @@ int32_t clock_app(void* p) {
|
|||
furi_timer_free(timer);
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
|
|
|
@ -333,7 +333,7 @@ int32_t dec_hex_converter_app(void* p) {
|
|||
view_port_input_callback_set(view_port, dec_hex_converter_input_callback, event_queue);
|
||||
|
||||
// open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
dec_hex_converter_init(dec_hex_converter_state);
|
||||
|
@ -394,7 +394,7 @@ int32_t dec_hex_converter_app(void* p) {
|
|||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
|
|
|
@ -36,12 +36,13 @@ void desktop_debug_render(Canvas* canvas, void* model) {
|
|||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"%d.F%dB%dC%d %s %s",
|
||||
"%d.F%dB%dC%d %s:%s %s",
|
||||
furi_hal_version_get_hw_version(),
|
||||
furi_hal_version_get_hw_target(),
|
||||
furi_hal_version_get_hw_body(),
|
||||
furi_hal_version_get_hw_connect(),
|
||||
furi_hal_version_get_hw_region_name(),
|
||||
furi_hal_region_get_name(),
|
||||
my_name ? my_name : "Unknown");
|
||||
canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer);
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ int32_t esp8266_deauth_app(void* p) {
|
|||
view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
//notification_message(app->notification, &sequence_set_only_blue_255);
|
||||
|
@ -511,7 +511,7 @@ int32_t esp8266_deauth_app(void* p) {
|
|||
gui_remove_view_port(gui, view_port);
|
||||
|
||||
// Close gui record
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close("notification");
|
||||
app->m_gui = NULL;
|
||||
|
||||
|
|
|
@ -162,6 +162,19 @@ void widget_add_text_box_element(
|
|||
widget_add_element(widget, text_box_element);
|
||||
}
|
||||
|
||||
void widget_add_text_scroll_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text) {
|
||||
furi_assert(widget);
|
||||
WidgetElement* text_scroll_element =
|
||||
widget_element_text_scroll_create(x, y, width, height, text);
|
||||
widget_add_element(widget, text_scroll_element);
|
||||
}
|
||||
|
||||
void widget_add_button_element(
|
||||
Widget* widget,
|
||||
GuiButtonType button_type,
|
||||
|
|
|
@ -105,6 +105,27 @@ void widget_add_text_box_element(
|
|||
const char* text,
|
||||
bool strip_to_dots);
|
||||
|
||||
/** Add Text Scroll Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x x coordinate
|
||||
* @param y y coordinate
|
||||
* @param width width to fit text
|
||||
* @param height height to fit text
|
||||
* @param[in] text Formatted text. Default format: align left, Secondary font.
|
||||
* The following formats are available:
|
||||
* "\e#Bold text" - sets bold font before until next '\n' symbol
|
||||
* "\ecBold text" - sets center horizontal align before until next '\n' symbol
|
||||
* "\erBold text" - sets right horizontal align before until next '\n' symbol
|
||||
*/
|
||||
void widget_add_text_scroll_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text);
|
||||
|
||||
/** Add Button Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
|
|
|
@ -29,6 +29,7 @@ struct WidgetElement {
|
|||
|
||||
// generic model holder
|
||||
void* model;
|
||||
FuriMutex* model_mutex;
|
||||
|
||||
// pointer to widget that hold our element
|
||||
Widget* parent;
|
||||
|
@ -80,3 +81,10 @@ WidgetElement* widget_element_frame_create(
|
|||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
||||
|
||||
WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text);
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
#include "widget_element_i.h"
|
||||
#include <m-string.h>
|
||||
#include <gui/elements.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET (4)
|
||||
|
||||
typedef struct {
|
||||
Font font;
|
||||
Align horizontal;
|
||||
string_t text;
|
||||
} TextScrollLineArray;
|
||||
|
||||
ARRAY_DEF(TextScrollLineArray, TextScrollLineArray, M_POD_OPLIST)
|
||||
|
||||
typedef struct {
|
||||
TextScrollLineArray_t line_array;
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
string_t text;
|
||||
uint8_t scroll_pos_total;
|
||||
uint8_t scroll_pos_current;
|
||||
bool text_formatted;
|
||||
} WidgetElementTextScrollModel;
|
||||
|
||||
static bool
|
||||
widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, string_t text) {
|
||||
bool processed = false;
|
||||
|
||||
do {
|
||||
if(string_get_char(text, 0) != '\e') break;
|
||||
char ctrl_symbol = string_get_char(text, 1);
|
||||
if(ctrl_symbol == 'c') {
|
||||
line->horizontal = AlignCenter;
|
||||
} else if(ctrl_symbol == 'r') {
|
||||
line->horizontal = AlignRight;
|
||||
} else if(ctrl_symbol == '#') {
|
||||
line->font = FontPrimary;
|
||||
}
|
||||
string_right(text, 2);
|
||||
processed = true;
|
||||
} while(false);
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void widget_element_text_scroll_add_line(WidgetElement* element, TextScrollLineArray* line) {
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
TextScrollLineArray new_line;
|
||||
new_line.font = line->font;
|
||||
new_line.horizontal = line->horizontal;
|
||||
string_init_set(new_line.text, line->text);
|
||||
TextScrollLineArray_push_back(model->line_array, new_line);
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* element) {
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
TextScrollLineArray line_tmp;
|
||||
bool all_text_processed = false;
|
||||
string_init(line_tmp.text);
|
||||
bool reached_new_line = true;
|
||||
uint16_t total_height = 0;
|
||||
|
||||
while(!all_text_processed) {
|
||||
if(reached_new_line) {
|
||||
// Set default line properties
|
||||
line_tmp.font = FontSecondary;
|
||||
line_tmp.horizontal = AlignLeft;
|
||||
string_reset(line_tmp.text);
|
||||
// Process control symbols
|
||||
while(widget_element_text_scroll_process_ctrl_symbols(&line_tmp, model->text))
|
||||
;
|
||||
}
|
||||
// Set canvas font
|
||||
canvas_set_font(canvas, line_tmp.font);
|
||||
CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font);
|
||||
total_height += params->height;
|
||||
if(total_height > model->height) {
|
||||
model->scroll_pos_total++;
|
||||
}
|
||||
|
||||
uint8_t line_width = 0;
|
||||
uint16_t char_i = 0;
|
||||
while(true) {
|
||||
char next_char = string_get_char(model->text, char_i++);
|
||||
if(next_char == '\0') {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
total_height += params->leading_default - params->height;
|
||||
all_text_processed = true;
|
||||
break;
|
||||
} else if(next_char == '\n') {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
string_right(model->text, char_i);
|
||||
total_height += params->leading_default - params->height;
|
||||
reached_new_line = true;
|
||||
break;
|
||||
} else {
|
||||
line_width += canvas_glyph_width(canvas, next_char);
|
||||
if(line_width > model->width) {
|
||||
string_push_back(line_tmp.text, '\0');
|
||||
widget_element_text_scroll_add_line(element, &line_tmp);
|
||||
string_right(model->text, char_i - 1);
|
||||
string_reset(line_tmp.text);
|
||||
total_height += params->leading_default - params->height;
|
||||
reached_new_line = false;
|
||||
break;
|
||||
} else {
|
||||
string_push_back(line_tmp.text, next_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(line_tmp.text);
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
|
||||
furi_mutex_acquire(element->model_mutex, FuriWaitForever);
|
||||
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
if(!model->text_formatted) {
|
||||
widget_element_text_scroll_fill_lines(canvas, element);
|
||||
model->text_formatted = true;
|
||||
}
|
||||
|
||||
uint8_t y = model->y;
|
||||
uint8_t x = model->x;
|
||||
uint16_t curr_line = 0;
|
||||
if(TextScrollLineArray_size(model->line_array)) {
|
||||
TextScrollLineArray_it_t it;
|
||||
for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it);
|
||||
TextScrollLineArray_next(it), curr_line++) {
|
||||
if(curr_line < model->scroll_pos_current) continue;
|
||||
TextScrollLineArray* line = TextScrollLineArray_ref(it);
|
||||
CanvasFontParameters* params = canvas_get_font_params(canvas, line->font);
|
||||
if(y + params->descender > model->y + model->height) break;
|
||||
canvas_set_font(canvas, line->font);
|
||||
if(line->horizontal == AlignLeft) {
|
||||
x = model->x;
|
||||
} else if(line->horizontal == AlignCenter) {
|
||||
x = (model->x + model->width) / 2;
|
||||
} else if(line->horizontal == AlignRight) {
|
||||
x = model->x + model->width;
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, x, y, line->horizontal, AlignTop, string_get_cstr(line->text));
|
||||
y += params->leading_default;
|
||||
}
|
||||
// Draw scroll bar
|
||||
if(model->scroll_pos_total > 1) {
|
||||
elements_scrollbar_pos(
|
||||
canvas,
|
||||
model->x + model->width + WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET,
|
||||
model->y,
|
||||
model->height,
|
||||
model->scroll_pos_current,
|
||||
model->scroll_pos_total);
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(element->model_mutex);
|
||||
}
|
||||
|
||||
static bool widget_element_text_scroll_input(InputEvent* event, WidgetElement* element) {
|
||||
furi_assert(event);
|
||||
furi_assert(element);
|
||||
|
||||
furi_mutex_acquire(element->model_mutex, FuriWaitForever);
|
||||
|
||||
WidgetElementTextScrollModel* model = element->model;
|
||||
bool consumed = false;
|
||||
|
||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||
if(event->key == InputKeyUp) {
|
||||
if(model->scroll_pos_current > 0) {
|
||||
model->scroll_pos_current--;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if((model->scroll_pos_total > 1) &&
|
||||
(model->scroll_pos_current < model->scroll_pos_total - 1)) {
|
||||
model->scroll_pos_current++;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(element->model_mutex);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void widget_element_text_scroll_free(WidgetElement* text_scroll) {
|
||||
furi_assert(text_scroll);
|
||||
|
||||
WidgetElementTextScrollModel* model = text_scroll->model;
|
||||
TextScrollLineArray_it_t it;
|
||||
for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it);
|
||||
TextScrollLineArray_next(it)) {
|
||||
TextScrollLineArray* line = TextScrollLineArray_ref(it);
|
||||
string_clear(line->text);
|
||||
}
|
||||
TextScrollLineArray_clear(model->line_array);
|
||||
string_clear(model->text);
|
||||
free(text_scroll->model);
|
||||
furi_mutex_free(text_scroll->model_mutex);
|
||||
free(text_scroll);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
const char* text) {
|
||||
furi_assert(text);
|
||||
|
||||
// Allocate and init model
|
||||
WidgetElementTextScrollModel* model = malloc(sizeof(WidgetElementTextScrollModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->width = width - WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET;
|
||||
model->height = height;
|
||||
model->scroll_pos_current = 0;
|
||||
model->scroll_pos_total = 1;
|
||||
TextScrollLineArray_init(model->line_array);
|
||||
string_init_set_str(model->text, text);
|
||||
|
||||
WidgetElement* text_scroll = malloc(sizeof(WidgetElement));
|
||||
text_scroll->parent = NULL;
|
||||
text_scroll->draw = widget_element_text_scroll_draw;
|
||||
text_scroll->input = widget_element_text_scroll_input;
|
||||
text_scroll->free = widget_element_text_scroll_free;
|
||||
text_scroll->model = model;
|
||||
text_scroll->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
return text_scroll;
|
||||
}
|
|
@ -16,6 +16,7 @@ HIDApp::~HIDApp() {
|
|||
void HIDApp::run(void* _args) {
|
||||
UNUSED(_args);
|
||||
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Read, new HIDAppSceneRead());
|
||||
scene_controller.add_scene(SceneType::ReadSuccess, new HIDAppSceneReadSuccess());
|
||||
scene_controller.process(100, SceneType::Read);
|
||||
|
|
|
@ -87,6 +87,8 @@ static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context)
|
|||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(
|
||||
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||
ibutton->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
||||
} else if(event == RpcAppEventLoadFile) {
|
||||
|
|
|
@ -29,7 +29,7 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
if(event.event == iButtonCustomEventRpcLoad) {
|
||||
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
|
||||
bool result = false;
|
||||
if(arg) {
|
||||
if(arg && (string_empty_p(ibutton->file_path))) {
|
||||
string_set_str(ibutton->file_path, arg);
|
||||
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
||||
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
|
||||
|
@ -51,17 +51,17 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
string_clear(key_name);
|
||||
result = true;
|
||||
} else {
|
||||
string_reset(ibutton->file_path);
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
} else if(event.event == iButtonCustomEventRpcExit) {
|
||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true);
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||
scene_manager_stop(ibutton->scene_manager);
|
||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||
ibutton->rpc_ctx = NULL;
|
||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||
scene_manager_stop(ibutton->scene_manager);
|
||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context
|
|||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
|
||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||
infrared->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
|
||||
|
@ -293,6 +295,13 @@ bool infrared_rename_current_remote(Infrared* infrared, const char* name) {
|
|||
}
|
||||
|
||||
void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
|
||||
if(infrared->app_state.is_transmitting) {
|
||||
FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already active");
|
||||
return;
|
||||
} else {
|
||||
infrared->app_state.is_transmitting = true;
|
||||
}
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
|
||||
|
@ -302,8 +311,11 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
|
|||
}
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedIrSend);
|
||||
infrared_worker_tx_start(infrared->worker);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||
infrared_worker_tx_start(infrared->worker);
|
||||
}
|
||||
|
||||
void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
|
||||
|
@ -322,7 +334,16 @@ void infrared_tx_start_received(Infrared* infrared) {
|
|||
}
|
||||
|
||||
void infrared_tx_stop(Infrared* infrared) {
|
||||
if(!infrared->app_state.is_transmitting) {
|
||||
FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already stopped");
|
||||
return;
|
||||
} else {
|
||||
infrared->app_state.is_transmitting = false;
|
||||
}
|
||||
|
||||
infrared_worker_tx_stop(infrared->worker);
|
||||
infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
|
||||
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#define INFRARED_APP_EXTENSION ".ir"
|
||||
|
||||
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
||||
#define INFRARED_LOG_TAG "InfraredApp"
|
||||
|
||||
typedef enum {
|
||||
InfraredButtonIndexNone = -1,
|
||||
|
@ -63,6 +64,7 @@ typedef enum {
|
|||
typedef struct {
|
||||
bool is_learning_new_remote;
|
||||
bool is_debug_enabled;
|
||||
bool is_transmitting;
|
||||
InfraredEditTarget edit_target : 8;
|
||||
InfraredEditMode edit_mode : 8;
|
||||
int32_t current_button_index;
|
||||
|
|
|
@ -2,11 +2,6 @@
|
|||
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
typedef enum {
|
||||
InfraredSceneLearnSuccessStateIdle = 0,
|
||||
InfraredSceneLearnSuccessStateSending = 1,
|
||||
} InfraredSceneLearnSuccessState;
|
||||
|
||||
static void
|
||||
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
|
||||
Infrared* infrared = context;
|
||||
|
@ -21,9 +16,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
|
|||
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
||||
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, context);
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter);
|
||||
|
@ -63,57 +55,42 @@ void infrared_scene_learn_success_on_enter(void* context) {
|
|||
dialog_ex_set_context(dialog_ex, context);
|
||||
dialog_ex_enable_extended_events(dialog_ex);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
|
||||
}
|
||||
|
||||
bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
uint32_t scene_state = scene_manager_get_scene_state(scene_manager, InfraredSceneLearnSuccess);
|
||||
const bool is_transmitter_idle = !infrared->app_state.is_transmitting;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
||||
if(is_transmitter_idle) {
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
||||
if(is_transmitter_idle) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneAskBack);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultLeft) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
||||
if(is_transmitter_idle) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneAskRetry);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExResultRight) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
||||
if(is_transmitter_idle) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExPressCenter) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
||||
scene_manager_set_scene_state(
|
||||
scene_manager,
|
||||
InfraredSceneLearnSuccess,
|
||||
InfraredSceneLearnSuccessStateSending);
|
||||
infrared_tx_start_received(infrared);
|
||||
infrared_play_notification_message(
|
||||
infrared, InfraredNotificationMessageBlinkStartSend);
|
||||
}
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||
infrared_tx_start_received(infrared);
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExReleaseCenter) {
|
||||
if(scene_state == InfraredSceneLearnSuccessStateSending) {
|
||||
scene_manager_set_scene_state(
|
||||
scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
|
||||
infrared_tx_stop(infrared);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||
}
|
||||
infrared_tx_stop(infrared);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
@ -123,9 +100,6 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
|
|||
|
||||
void infrared_scene_learn_success_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
InfraredWorker* worker = infrared->worker;
|
||||
dialog_ex_reset(infrared->dialog_ex);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||
infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -31,9 +31,6 @@ void infrared_scene_remote_on_enter(void* context) {
|
|||
ButtonMenu* button_menu = infrared->button_menu;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||
|
||||
size_t button_count = infrared_remote_get_button_count(remote);
|
||||
for(size_t i = 0; i < button_count; ++i) {
|
||||
InfraredRemoteButton* button = infrared_remote_get_button(remote, i);
|
||||
|
@ -73,12 +70,17 @@ void infrared_scene_remote_on_enter(void* context) {
|
|||
bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
const bool is_transmitter_idle = !infrared->app_state.is_transmitting;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
if(is_transmitter_idle) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
} else {
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
const uint16_t custom_type = infrared_custom_event_get_type(event.event);
|
||||
const int16_t button_index = infrared_custom_event_get_value(event.event);
|
||||
|
@ -92,14 +94,19 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
|||
consumed = true;
|
||||
} else if(custom_type == InfraredCustomEventTypeMenuSelected) {
|
||||
furi_assert(button_index < 0);
|
||||
scene_manager_set_scene_state(
|
||||
scene_manager, InfraredSceneRemote, (unsigned)button_index);
|
||||
if(button_index == ButtonIndexPlus) {
|
||||
infrared->app_state.is_learning_new_remote = false;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
||||
consumed = true;
|
||||
} else if(button_index == ButtonIndexEdit) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEdit);
|
||||
if(is_transmitter_idle) {
|
||||
scene_manager_set_scene_state(
|
||||
scene_manager, InfraredSceneRemote, (unsigned)button_index);
|
||||
if(button_index == ButtonIndexPlus) {
|
||||
infrared->app_state.is_learning_new_remote = false;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
||||
consumed = true;
|
||||
} else if(button_index == ButtonIndexEdit) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEdit);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +117,5 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
void infrared_scene_remote_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
infrared_tx_stop(infrared);
|
||||
infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
|
||||
button_menu_reset(infrared->button_menu);
|
||||
}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "gui/canvas.h"
|
||||
|
||||
typedef enum {
|
||||
InfraredRpcStateIdle,
|
||||
InfraredRpcStateLoaded,
|
||||
InfraredRpcStateSending,
|
||||
} InfraredRpcState;
|
||||
|
||||
void infrared_scene_rpc_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
|
||||
popup_set_header(popup, "Infrared", 82, 28, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_header(popup, "Infrared", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
popup_set_context(popup, context);
|
||||
popup_set_callback(popup, infrared_popup_closed_callback);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
|
||||
|
||||
scene_manager_set_scene_state(infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateIdle);
|
||||
|
||||
notification_message(infrared->notifications, &sequence_display_backlight_on);
|
||||
}
|
||||
|
||||
|
@ -24,6 +32,8 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
InfraredRpcState state =
|
||||
scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc);
|
||||
if(event.event == InfraredCustomEventTypeBackPressed) {
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
|
@ -31,39 +41,49 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
} else if(event.event == InfraredCustomEventTypeRpcLoad) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||
if(arg) {
|
||||
if(arg && (state == InfraredRpcStateIdle)) {
|
||||
string_set_str(infrared->file_path, arg);
|
||||
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
||||
infrared_worker_tx_set_get_signal_callback(
|
||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||
if(result) {
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||
}
|
||||
}
|
||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||
|
||||
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
||||
popup_set_text(
|
||||
infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop);
|
||||
infrared->popup, infrared->text_store[0], 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||
if(arg) {
|
||||
if(arg && (state == InfraredRpcStateLoaded)) {
|
||||
size_t button_index = 0;
|
||||
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
||||
infrared_tx_start_button_index(infrared, button_index);
|
||||
result = true;
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending);
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
|
||||
infrared_tx_stop(infrared);
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true);
|
||||
bool result = false;
|
||||
if(state == InfraredRpcStateSending) {
|
||||
infrared_tx_stop(infrared);
|
||||
result = true;
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||
}
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcExit) {
|
||||
scene_manager_stop(infrared->scene_manager);
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
|
||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||
infrared->rpc_ctx = NULL;
|
||||
scene_manager_stop(infrared->scene_manager);
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +92,9 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
void infrared_scene_rpc_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
infrared_tx_stop(infrared);
|
||||
if(scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc) ==
|
||||
InfraredRpcStateSending) {
|
||||
infrared_tx_stop(infrared);
|
||||
}
|
||||
popup_reset(infrared->popup);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ void infrared_scene_universal_audio_on_enter(void* context) {
|
|||
|
||||
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/audio.ir"));
|
||||
//TODO Improve Audio universal remote
|
||||
button_panel_reserve(button_panel, 2, 1);
|
||||
button_panel_reserve(button_panel, 2, 2);
|
||||
uint32_t i = 0;
|
||||
button_panel_add_item(
|
||||
button_panel,
|
||||
|
@ -37,8 +37,33 @@ void infrared_scene_universal_audio_on_enter(void* context) {
|
|||
infrared_scene_universal_common_item_callback,
|
||||
context);
|
||||
infrared_brute_force_add_record(brute_force, i++, "MUTE");
|
||||
button_panel_add_item(
|
||||
button_panel,
|
||||
i,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
64,
|
||||
&I_Vol_up_25x27,
|
||||
&I_Vol_up_hvr_25x27,
|
||||
infrared_scene_universal_common_item_callback,
|
||||
context);
|
||||
infrared_brute_force_add_record(brute_force, i++, "VOL+");
|
||||
button_panel_add_item(
|
||||
button_panel,
|
||||
i,
|
||||
1,
|
||||
1,
|
||||
36,
|
||||
64,
|
||||
&I_Vol_down_25x27,
|
||||
&I_Vol_down_hvr_25x27,
|
||||
infrared_scene_universal_common_item_callback,
|
||||
context);
|
||||
infrared_brute_force_add_record(brute_force, i++, "VOL-");
|
||||
|
||||
button_panel_add_label(button_panel, 4, 11, FontSecondary, "Audio remote");
|
||||
button_panel_add_label(button_panel, 5, 11, FontSecondary, "Audio remote");
|
||||
button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume");
|
||||
|
||||
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
|
||||
|
|
|
@ -56,6 +56,9 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
|||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::RpcSessionClose;
|
||||
app->view_controller.send_event(&event);
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
} else if(rpc_event == RpcAppEventAppExit) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Exit;
|
||||
|
@ -80,16 +83,19 @@ void LfRfidApp::run(void* _args) {
|
|||
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
||||
rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
|
||||
rpc_system_app_send_started(rpc_ctx);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeDesktop);
|
||||
scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
|
||||
scene_controller.process(100, SceneType::Rpc);
|
||||
} else {
|
||||
string_set_str(file_path, args);
|
||||
load_key_data(file_path, &worker.key, true);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||
scene_controller.process(100, SceneType::Emulate);
|
||||
}
|
||||
|
||||
} else {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
||||
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
|
||||
|
|
|
@ -101,5 +101,4 @@ public:
|
|||
bool save_key_data(string_t path, RfidKey* key);
|
||||
|
||||
void make_app_folder();
|
||||
//bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context);
|
||||
};
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("LF RFID", 89, 30, AlignCenter, AlignTop);
|
||||
popup->set_text("RPC mode", 89, 43, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom);
|
||||
popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
|
||||
|
@ -27,33 +27,25 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||
app->view_controller.send_event(&view_event);
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
|
||||
consumed = true;
|
||||
LfRfidApp::Event view_event;
|
||||
view_event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&view_event);
|
||||
} else if(event->type == LfRfidApp::EventType::EmulateStart) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
consumed = true;
|
||||
emulating = true;
|
||||
|
||||
app->text_store.set("emulating\n%s", app->worker.key.get_name());
|
||||
popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
|
||||
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||
consumed = true;
|
||||
bool result = false;
|
||||
if(arg) {
|
||||
if(arg && !emulating) {
|
||||
string_set_str(app->file_path, arg);
|
||||
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::EmulateStart;
|
||||
app->view_controller.send_event(&event);
|
||||
app->worker.start_emulate();
|
||||
emulating = true;
|
||||
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
app->text_store.set("emulating\n%s", app->worker.key.get_name());
|
||||
popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||
case RfidWorker::WriteResult::NotWritable:
|
||||
if(!card_not_supported) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
popup->set_icon(72, 14, &I_DolphinFirstStart8_56x51);
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
"Make sure this\ncard is writable\nand not\nprotected.",
|
||||
|
|
|
@ -10,6 +10,7 @@ LfRfidDebugApp::~LfRfidDebugApp() {
|
|||
}
|
||||
|
||||
void LfRfidDebugApp::run() {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
|
||||
scene_controller.process(100);
|
||||
|
|
|
@ -5,6 +5,6 @@ App(
|
|||
entry_point="loader_srv",
|
||||
cdefines=["SRV_LOADER"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
stack_size=2 * 1024,
|
||||
order=90,
|
||||
)
|
||||
|
|
|
@ -503,9 +503,9 @@ int32_t loader_srv(void* p) {
|
|||
|
||||
furi_record_create(RECORD_LOADER, loader_instance);
|
||||
|
||||
#ifdef LOADER_AUTOSTART
|
||||
loader_start(loader_instance, LOADER_AUTOSTART, NULL);
|
||||
#endif
|
||||
if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) {
|
||||
loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
uint32_t flags =
|
||||
|
|
|
@ -240,10 +240,10 @@ int32_t mousejacker_app(void* p) {
|
|||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
Storage* storage = furi_record_open("storage");
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_common_mkdir(storage, MOUSEJACKER_APP_PATH_FOLDER);
|
||||
Stream* file_stream = file_stream_alloc(storage);
|
||||
|
||||
|
@ -329,8 +329,8 @@ int32_t mousejacker_app(void* p) {
|
|||
furi_hal_spi_release(nrf24_HANDLE);
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close("storage");
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
MusicPlayerModel* model;
|
||||
FuriMutex* model_mutex;
|
||||
FuriMutex** model_mutex;
|
||||
|
||||
FuriMessageQueue* input_queue;
|
||||
|
||||
|
@ -256,7 +256,7 @@ MusicPlayer* music_player_alloc() {
|
|||
instance->model = malloc(sizeof(MusicPlayerModel));
|
||||
memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
||||
memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
||||
instance->model->volume = 1;
|
||||
instance->model->volume = 3;
|
||||
|
||||
instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ static int32_t music_player_worker_thread_callback(void* context) {
|
|||
furi_hal_speaker_stop();
|
||||
furi_hal_speaker_start(frequency, volume);
|
||||
while(instance->should_work && furi_get_tick() < next_tick) {
|
||||
volume *= 1.0000000;
|
||||
volume *= 0.9945679;
|
||||
furi_hal_speaker_set_volume(volume);
|
||||
furi_delay_ms(2);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
|||
|
||||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
|
||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||
nfc->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
} else if(event == RpcAppEventLoadFile) {
|
||||
|
@ -87,11 +89,6 @@ Nfc* nfc_alloc() {
|
|||
nfc->widget = widget_alloc();
|
||||
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget));
|
||||
|
||||
// Bank Card
|
||||
nfc->bank_card = bank_card_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card));
|
||||
|
||||
// Mifare Classic Dict Attack
|
||||
nfc->dict_attack = dict_attack_alloc();
|
||||
view_dispatcher_add_view(
|
||||
|
@ -157,10 +154,6 @@ void nfc_free(Nfc* nfc) {
|
|||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
widget_free(nfc->widget);
|
||||
|
||||
// Bank Card
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard);
|
||||
bank_card_free(nfc->bank_card);
|
||||
|
||||
// Mifare Classic Dict Attack
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack);
|
||||
dict_attack_free(nfc->dict_attack);
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#include <lib/nfc/nfc_worker.h>
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||
#include <lib/nfc/parsers/nfc_supported_card.h>
|
||||
|
||||
#include "views/bank_card.h"
|
||||
#include "views/dict_attack.h"
|
||||
|
||||
#include <nfc/scenes/nfc_scene.h>
|
||||
|
@ -70,7 +70,6 @@ struct Nfc {
|
|||
ByteInput* byte_input;
|
||||
TextBox* text_box;
|
||||
Widget* widget;
|
||||
BankCard* bank_card;
|
||||
DictAttack* dict_attack;
|
||||
|
||||
const NfcGenerator* generator;
|
||||
|
@ -85,7 +84,6 @@ typedef enum {
|
|||
NfcViewByteInput,
|
||||
NfcViewTextBox,
|
||||
NfcViewWidget,
|
||||
NfcViewBankCard,
|
||||
NfcViewDictAttack,
|
||||
} NfcView;
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ ADD_SCENE(nfc, save_name, SaveName)
|
|||
ADD_SCENE(nfc, save_success, SaveSuccess)
|
||||
ADD_SCENE(nfc, file_select, FileSelect)
|
||||
ADD_SCENE(nfc, emulate_uid, EmulateUid)
|
||||
ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess)
|
||||
ADD_SCENE(nfc, nfca_menu, NfcaMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
|
||||
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
|
||||
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate)
|
||||
ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth)
|
||||
|
@ -25,13 +28,13 @@ ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu)
|
|||
ADD_SCENE(nfc, mf_desfire_data, MfDesfireData)
|
||||
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
||||
ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess)
|
||||
ADD_SCENE(nfc, mf_classic_info, MfClassicInfo)
|
||||
ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
|
||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
||||
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
||||
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
||||
ADD_SCENE(nfc, device_info, DeviceInfo)
|
||||
ADD_SCENE(nfc, delete, Delete)
|
||||
|
@ -45,3 +48,4 @@ ADD_SCENE(nfc, rpc, Rpc)
|
|||
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
||||
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
||||
ADD_SCENE(nfc, detect_reader, DetectReader)
|
||||
ADD_SCENE(nfc, nfc_data_info, NfcDataInfo)
|
||||
|
|
|
@ -9,58 +9,43 @@ void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void
|
|||
|
||||
void nfc_scene_delete_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
|
||||
// Setup Custom Widget view
|
||||
char temp_str[64];
|
||||
snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name);
|
||||
widget_add_text_box_element(
|
||||
nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false);
|
||||
nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, string_get_cstr(temp_str), false);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
|
||||
nfc->widget, GuiButtonTypeLeft, "Cancel", nfc_scene_delete_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3]);
|
||||
} else if(data->uid_len == 7) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
}
|
||||
widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, temp_str);
|
||||
|
||||
const char* protocol_name = NULL;
|
||||
string_set_str(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
if(protocol == NfcDeviceProtocolEMV) {
|
||||
protocol_name = nfc_guess_protocol(protocol);
|
||||
string_set_str(temp_str, "EMV bank card");
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false);
|
||||
string_set_str(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true));
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_set_str(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type));
|
||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
string_set_str(temp_str, "MIFARE DESFire");
|
||||
} else {
|
||||
string_set_str(temp_str, "Unknown ISO tag");
|
||||
}
|
||||
if(protocol_name) {
|
||||
widget_add_string_element(
|
||||
nfc->widget, 10, 33, AlignLeft, AlignTop, FontSecondary, protocol_name);
|
||||
}
|
||||
// TODO change dinamically
|
||||
widget_add_string_element(nfc->widget, 118, 33, AlignRight, AlignTop, FontSecondary, "NFC-A");
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak);
|
||||
widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||
widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A");
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
@ -71,7 +56,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
return scene_manager_previous_scene(nfc->scene_manager);
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
if(nfc_device_delete(nfc->dev, true)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||
|
|
|
@ -26,7 +26,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
|||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
nfc->scene_manager, NfcSceneFileSelect);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
enum {
|
||||
NfcSceneDeviceInfoUid,
|
||||
NfcSceneDeviceInfoData,
|
||||
};
|
||||
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
|
@ -13,197 +8,65 @@ void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type,
|
|||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(result == DialogExResultLeft) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) {
|
||||
UNUSED(result);
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
|
||||
bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatMifareUl) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatBankCard);
|
||||
// Setup Custom Widget view
|
||||
widget_add_text_box_element(
|
||||
nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name, false);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
|
||||
if(data_display_supported) {
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
|
||||
}
|
||||
char temp_str[32];
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3]);
|
||||
} else if(data->uid_len == 7) {
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X %02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
}
|
||||
widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, temp_str);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
const char* protocol_name = NULL;
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
protocol_name = nfc_guess_protocol(protocol);
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false);
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type);
|
||||
}
|
||||
if(protocol_name) {
|
||||
widget_add_string_element(
|
||||
nfc->widget, 10, 32, AlignLeft, AlignTop, FontSecondary, protocol_name);
|
||||
}
|
||||
// TODO change dinamically
|
||||
widget_add_string_element(nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A");
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak);
|
||||
widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
|
||||
// Setup Data View
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Back");
|
||||
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(
|
||||
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
|
||||
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
EmvData* emv_data = &dev_data->emv_data;
|
||||
string_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
||||
string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data;
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = mf_df_data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
"%d application%s, %d file%s",
|
||||
n_apps,
|
||||
n_apps == 1 ? "" : "s",
|
||||
n_files,
|
||||
n_files == 1 ? "" : "s");
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
BankCard* bank_card = nfc->bank_card;
|
||||
bank_card_set_name(bank_card, emv_data->name);
|
||||
bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
|
||||
bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc);
|
||||
string_strim(temp_str);
|
||||
|
||||
// Add expiration date
|
||||
if(emv_data->exp_mon) {
|
||||
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
|
||||
string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
string_t display_str;
|
||||
string_init(display_str);
|
||||
if(emv_data->country_code) {
|
||||
// Parse currency code
|
||||
if((emv_data->currency_code)) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
// Parse country code
|
||||
if((emv_data->country_code)) {
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(
|
||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_printf(display_str, "Reg:%s", string_get_cstr(country_name));
|
||||
bank_card_set_country_name(bank_card, string_get_cstr(display_str));
|
||||
string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name));
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
if(emv_data->currency_code) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->country_code, currency_name)) {
|
||||
string_printf(display_str, "Cur:%s", string_get_cstr(currency_name));
|
||||
bank_card_set_currency_name(bank_card, string_get_cstr(display_str));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
string_clear(display_str);
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
|
||||
widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "More", nfc_scene_device_info_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
|
||||
consumed = true;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == NfcSceneDeviceInfoData) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
@ -215,12 +78,4 @@ void nfc_scene_device_info_on_exit(void* context) {
|
|||
|
||||
// Clear views
|
||||
widget_reset(nfc->widget);
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
bank_card_clear(nfc->bank_card);
|
||||
}
|
||||
}
|
||||
|
|
54
applications/nfc/scenes/nfc_scene_emv_menu.c
Normal file
54
applications/nfc/scenes/nfc_scene_emv_menu.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_emv_menu_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_emv_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_emv_menu_submenu_callback, nfc);
|
||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_emv_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_emv_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneEmvMenu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_emv_menu_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
|
@ -15,85 +15,48 @@ void nfc_scene_emv_read_success_widget_callback(
|
|||
void nfc_scene_emv_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup Custom Widget view
|
||||
// Add frame
|
||||
widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6);
|
||||
// Add buttons
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
// Add card name
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name);
|
||||
// Add card number
|
||||
string_t pan_str;
|
||||
string_init(pan_str);
|
||||
nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
||||
string_cat_printf(pan_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||
}
|
||||
string_strim(pan_str);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, string_get_cstr(pan_str));
|
||||
string_clear(pan_str);
|
||||
// Parse country code
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if((emv_data->country_code) &&
|
||||
nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country));
|
||||
string_clear(disp_country);
|
||||
}
|
||||
string_clear(country_name);
|
||||
// Parse currency code
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if((emv_data->currency_code) &&
|
||||
nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget,
|
||||
121,
|
||||
23,
|
||||
AlignRight,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_currency));
|
||||
string_clear(disp_currency);
|
||||
}
|
||||
string_clear(currency_name);
|
||||
char temp_str[32];
|
||||
// Add ATQA
|
||||
snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
// Add UID
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"UID: %02X %02X %02X %02X",
|
||||
nfc_data->uid[0],
|
||||
nfc_data->uid[1],
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3]);
|
||||
widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
// Add SAK
|
||||
snprintf(temp_str, sizeof(temp_str), "SAK: %02X", nfc_data->sak);
|
||||
widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, temp_str);
|
||||
string_strim(temp_str);
|
||||
|
||||
// Add expiration date
|
||||
if(emv_data->exp_mon) {
|
||||
char exp_str[16];
|
||||
snprintf(
|
||||
exp_str, sizeof(exp_str), "Exp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str);
|
||||
string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
// Parse currency code
|
||||
if((emv_data->currency_code)) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
// Parse country code
|
||||
if((emv_data->country_code)) {
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(
|
||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name));
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
|
||||
widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
@ -107,10 +70,7 @@ bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event)
|
|||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
|
|
|
@ -6,6 +6,7 @@ void nfc_scene_file_select_on_enter(void* context) {
|
|||
// Process file_select return
|
||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
||||
if(nfc_file_select(nfc->dev)) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_classic_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
Nfc* nfc = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
string_t str_tmp;
|
||||
string_init(str_tmp);
|
||||
|
||||
// Setup view
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, mf_classic_get_type_str(mf_data->type));
|
||||
widget_add_string_element(
|
||||
widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)");
|
||||
string_printf(str_tmp, "UID:");
|
||||
for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) {
|
||||
string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(
|
||||
str_tmp,
|
||||
"ATQA: %02X %02X SAK: %02X",
|
||||
dev_data->nfc_data.atqa[0],
|
||||
dev_data->nfc_data.atqa[1],
|
||||
dev_data->nfc_data.sak);
|
||||
widget_add_string_element(
|
||||
widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
||||
string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 55, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
|
||||
string_clear(str_tmp);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_classic_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_classic_info_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(nfc->widget);
|
||||
}
|
|
@ -34,6 +34,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
|||
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
||||
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event)
|
|||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
|
|
|
@ -17,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
|||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||
string_t str_tmp;
|
||||
string_init(str_tmp);
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
|
@ -29,48 +27,27 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
|||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc);
|
||||
|
||||
string_t temp_str;
|
||||
if(string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
widget_add_text_box_element(
|
||||
nfc->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
32,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
string_get_cstr(nfc->dev->dev_data.parsed_data),
|
||||
true);
|
||||
string_init_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
widget_add_string_element(
|
||||
widget,
|
||||
0,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
mf_classic_get_type_str(mf_data->type));
|
||||
widget_add_string_element(
|
||||
widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)");
|
||||
string_printf(str_tmp, "UID:");
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) {
|
||||
string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
||||
string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total);
|
||||
widget_add_string_element(
|
||||
widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp));
|
||||
string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total);
|
||||
string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total);
|
||||
}
|
||||
|
||||
string_clear(str_tmp);
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulateUid,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) {
|
||||
|
@ -16,6 +18,15 @@ void nfc_scene_mf_desfire_menu_on_enter(void* context) {
|
|||
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate UID",
|
||||
SubmenuIndexEmulateUid,
|
||||
nfc_scene_mf_desfire_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_desfire_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu));
|
||||
|
||||
|
@ -35,6 +46,12 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event)
|
|||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulateUid) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,90 +1,85 @@
|
|||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
|
||||
|
||||
enum {
|
||||
MfDesfireReadSuccessStateShowUID,
|
||||
MfDesfireReadSuccessStateShowData,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) {
|
||||
void nfc_scene_mf_desfire_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_center_button_text(dialog_ex, "Data");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||
dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21);
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
// Prepare string for data display
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
|
||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
string_cat_printf(temp_str, "\n%d", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
string_push_back(temp_str, '+');
|
||||
}
|
||||
string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
|
||||
// TODO rework info view
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
NFC_SCENE_READ_SUCCESS_SHIFT "Mifare DESFire\n" NFC_SCENE_READ_SUCCESS_SHIFT
|
||||
"%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n"
|
||||
"%d application%s, %d file%s",
|
||||
1 << (data->version.sw_storage >> 1),
|
||||
(data->version.sw_storage & 1) ? "+" : "",
|
||||
data->free_memory ? data->free_memory->bytes : 0,
|
||||
n_apps,
|
||||
n_apps == 1 ? "" : "s",
|
||||
n_files,
|
||||
n_files == 1 ? "" : "s");
|
||||
dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_desfire_read_success_dialog_callback);
|
||||
// Add text scroll element
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
// Add button elements
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_desfire_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_desfire_read_success_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData);
|
||||
consumed = true;
|
||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) {
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == MfDesfireReadSuccessStateShowData) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager,
|
||||
NfcSceneMfDesfireReadSuccess,
|
||||
MfDesfireReadSuccessStateShowUID);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
@ -94,5 +89,5 @@ void nfc_scene_mf_desfire_read_success_on_exit(void* context) {
|
|||
Nfc* nfc = context;
|
||||
|
||||
// Clean dialog
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
widget_reset(nfc->widget);
|
||||
}
|
||||
|
|
32
applications/nfc/scenes/nfc_scene_mf_ultralight_data.c
Normal file
32
applications/nfc/scenes/nfc_scene_mf_ultralight_data.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_data_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_data_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_data_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean view
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
}
|
|
@ -4,6 +4,7 @@ enum SubmenuIndex {
|
|||
SubmenuIndexUnlock,
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) {
|
||||
|
@ -33,6 +34,9 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
|
|||
SubmenuIndexEmulate,
|
||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||
nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu));
|
||||
|
||||
|
@ -56,6 +60,9 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even
|
|||
} else if(event.event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, event.event);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
|
|||
22,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
popup_set_icon(nfc->popup, 73, 17, &I_DolphinFirstStart8_56x51);
|
||||
popup_set_icon(nfc->popup, 73, 20, &I_DolphinCommon_56x48);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth, state);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum {
|
||||
ReadMifareUlStateShowInfo,
|
||||
ReadMifareUlStateShowData,
|
||||
};
|
||||
|
||||
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
|
@ -31,12 +26,6 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
|||
"Retry",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeCenter,
|
||||
"Data",
|
||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
|
@ -44,71 +33,38 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
|||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||
nfc);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_t data_str;
|
||||
string_init_printf(data_str, "UID:");
|
||||
string_t temp_str;
|
||||
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(data_str, " %02X", data->uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
widget_add_string_element(
|
||||
widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
string_printf(
|
||||
data_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
widget_add_string_element(
|
||||
widget, 0, 24, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||
widget_add_string_element(
|
||||
widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-protected pages!");
|
||||
string_cat_printf(temp_str, "\nPassword-protected pages!");
|
||||
}
|
||||
string_clear(data_str);
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
// Setup TextBox view
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_font(text_box, TextBoxFontHex);
|
||||
for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) {
|
||||
if(!(i % 8) && i) {
|
||||
string_push_back(nfc->text_box_store, '\n');
|
||||
}
|
||||
string_cat_printf(
|
||||
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) {
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
|
||||
consumed = true;
|
||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeCenter) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(state == ReadMifareUlStateShowData) {
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
@ -117,8 +73,6 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv
|
|||
void nfc_scene_mf_ultralight_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clean views
|
||||
// Clean view
|
||||
widget_reset(nfc->widget);
|
||||
text_box_reset(nfc->text_box);
|
||||
string_reset(nfc->text_box_store);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ void nfc_scene_mf_ultralight_unlock_warn_on_enter(void* context) {
|
|||
dialog_ex_set_header(dialog_ex, "Risky function!", 64, 4, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Wrong password\ncan block your\ncard.", 4, 18, AlignLeft, AlignTop);
|
||||
dialog_ex_set_icon(dialog_ex, 73, 17, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 73, 20, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
|
|
133
applications/nfc/scenes/nfc_scene_nfc_data_info.c
Normal file
133
applications/nfc/scenes/nfc_scene_nfc_data_info.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_nfc_data_info_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Widget* widget = nfc->widget;
|
||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
NfcProtocol protocol = dev_data->protocol;
|
||||
uint8_t text_scroll_height = 0;
|
||||
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
||||
text_scroll_height = 52;
|
||||
} else {
|
||||
text_scroll_height = 64;
|
||||
}
|
||||
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
// Set name if present
|
||||
if(nfc->dev->dev_name[0] != '\0') {
|
||||
string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name);
|
||||
}
|
||||
|
||||
// Set tag type
|
||||
if(protocol == NfcDeviceProtocolEMV) {
|
||||
string_cat_printf(temp_str, "\e#EMV Bank Card\n");
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
string_cat_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true));
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type));
|
||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||
} else {
|
||||
string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
|
||||
}
|
||||
|
||||
// Set tag iso data
|
||||
char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3';
|
||||
string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
|
||||
string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
|
||||
|
||||
// Set application specific data
|
||||
if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
MifareDesfireData* data = &dev_data->mf_df_data;
|
||||
uint32_t bytes_total = 1 << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
string_cat_printf(temp_str, "\n%d", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
string_push_back(temp_str, '+');
|
||||
}
|
||||
string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
string_push_back(temp_str, 's');
|
||||
}
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* data = &dev_data->mf_ul_data;
|
||||
string_cat_printf(
|
||||
temp_str, "\nPages Read %d/%d", data->data_read / 4, data->data_size / 4);
|
||||
if(data->data_size > data->data_read) {
|
||||
string_cat_printf(temp_str, "\nPassword-protected");
|
||||
}
|
||||
} else if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
MfClassicData* data = &dev_data->mf_classic_data;
|
||||
uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type);
|
||||
uint8_t keys_total = sectors_total * 2;
|
||||
uint8_t keys_found = 0;
|
||||
uint8_t sectors_read = 0;
|
||||
mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found);
|
||||
string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total);
|
||||
string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total);
|
||||
}
|
||||
|
||||
// Add text scroll widget
|
||||
widget_add_text_scroll_element(
|
||||
widget, 0, 0, 128, text_scroll_height, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireApp);
|
||||
consumed = true;
|
||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfc_data_info_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
widget_reset(nfc->widget);
|
||||
}
|
62
applications/nfc/scenes/nfc_scene_nfca_menu.c
Normal file
62
applications/nfc/scenes/nfc_scene_nfca_menu.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "../nfc_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexSaveUid,
|
||||
SubmenuIndexEmulateUid,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
|
||||
void nfc_scene_nfca_menu_submenu_callback(void* context, uint32_t index) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_menu_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "Save UID", SubmenuIndexSaveUid, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Emulate UID", SubmenuIndexEmulateUid, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfca_menu_submenu_callback, nfc);
|
||||
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcaMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSaveUid) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulateUid) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcaMenu, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_menu_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
submenu_reset(nfc->submenu);
|
||||
}
|
72
applications/nfc/scenes/nfc_scene_nfca_read_success.c
Normal file
72
applications/nfc/scenes/nfc_scene_nfca_read_success.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include "../nfc_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void nfc_scene_nfca_read_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
furi_assert(context);
|
||||
Nfc* nfc = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_read_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
string_t temp_str;
|
||||
string_init_set_str(temp_str, "\e#Unknown ISO tag\n");
|
||||
|
||||
char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3';
|
||||
string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
|
||||
string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]);
|
||||
string_cat_printf(temp_str, " SAK: %02X", data->sak);
|
||||
|
||||
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfca_read_success_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfca_read_success_widget_callback, nfc);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_nfca_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||
consumed = true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaMenu);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_nfca_read_success_on_exit(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(nfc->widget);
|
||||
}
|
|
@ -59,11 +59,14 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
|
|||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if((event.event == NfcWorkerEventReadUidNfcB) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcF) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcV) ||
|
||||
(event.event == NfcWorkerEventReadUidNfcA)) {
|
||||
(event.event == NfcWorkerEventReadUidNfcV)) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadUidNfcA) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcWorkerEventReadMfUltralight) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
||||
|
|
|
@ -16,44 +16,26 @@ void nfc_scene_read_card_success_widget_callback(
|
|||
void nfc_scene_read_card_success_on_enter(void* context) {
|
||||
Nfc* nfc = context;
|
||||
|
||||
string_t data_str;
|
||||
string_t uid_str;
|
||||
string_init(data_str);
|
||||
string_init(uid_str);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||
Widget* widget = nfc->widget;
|
||||
string_set_str(data_str, nfc_get_dev_type(data->type));
|
||||
string_set_str(uid_str, "UID:");
|
||||
string_set_str(temp_str, nfc_get_dev_type(data->type));
|
||||
widget_add_string_element(
|
||||
widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(temp_str));
|
||||
string_set_str(temp_str, "UID:");
|
||||
for(uint8_t i = 0; i < data->uid_len; i++) {
|
||||
string_cat_printf(uid_str, " %02X", data->uid[i]);
|
||||
string_cat_printf(temp_str, " %02X", data->uid[i]);
|
||||
}
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(temp_str));
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc);
|
||||
if(data->type == FuriHalNfcTypeA) {
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "Save", nfc_scene_read_card_success_widget_callback, nfc);
|
||||
widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21);
|
||||
widget_add_string_element(
|
||||
widget, 37, 12, AlignLeft, AlignBottom, FontPrimary, string_get_cstr(data_str));
|
||||
string_printf(
|
||||
data_str, "ATQA: %02X%02X\nSAK: %02X", data->atqa[0], data->atqa[1], data->sak);
|
||||
widget_add_string_multiline_element(
|
||||
widget, 37, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, string_get_cstr(uid_str));
|
||||
} else {
|
||||
widget_add_string_element(
|
||||
widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(data_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(uid_str));
|
||||
}
|
||||
|
||||
string_clear(data_str);
|
||||
string_clear(uid_str);
|
||||
string_clear(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
@ -65,11 +47,6 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event
|
|||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
|
|
@ -4,10 +4,10 @@ void nfc_scene_rpc_on_enter(void* context) {
|
|||
Nfc* nfc = context;
|
||||
Popup* popup = nfc->popup;
|
||||
|
||||
popup_set_header(popup, "NFC", 82, 28, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
|
||||
|
@ -31,13 +31,11 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
consumed = true;
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
|
||||
scene_manager_stop(nfc->scene_manager);
|
||||
view_dispatcher_stop(nfc->view_dispatcher);
|
||||
nfc_blink_stop(nfc);
|
||||
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||
nfc->rpc_ctx = NULL;
|
||||
scene_manager_stop(nfc->scene_manager);
|
||||
view_dispatcher_stop(nfc->view_dispatcher);
|
||||
nfc_blink_stop(nfc);
|
||||
} else if(event.event == NfcCustomEventRpcLoad) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(nfc->rpc_ctx);
|
||||
|
@ -66,7 +64,7 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
nfc_blink_start(nfc);
|
||||
nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
|
||||
popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, nfc->text_store, 89, 44, AlignCenter, AlignTop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,6 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
|||
}
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
if(nfc->dev->shadow_file_exist) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
|
@ -58,12 +56,15 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
|||
submenu, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = context;
|
||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
|
@ -87,7 +88,18 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
|||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
bool application_info_present = false;
|
||||
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
application_info_present = true;
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
|
||||
}
|
||||
|
||||
if(application_info_present) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm);
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
#include "bank_card.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
#include <m-string.h>
|
||||
|
||||
struct BankCard {
|
||||
Widget* widget;
|
||||
};
|
||||
|
||||
BankCard* bank_card_alloc() {
|
||||
BankCard* bank_card = malloc(sizeof(BankCard));
|
||||
bank_card->widget = widget_alloc();
|
||||
return bank_card;
|
||||
}
|
||||
|
||||
void bank_card_free(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
widget_free(bank_card->widget);
|
||||
free(bank_card);
|
||||
}
|
||||
|
||||
View* bank_card_get_view(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
return widget_get_view(bank_card->widget);
|
||||
}
|
||||
|
||||
void bank_card_clear(BankCard* bank_card) {
|
||||
furi_assert(bank_card);
|
||||
widget_reset(bank_card->widget);
|
||||
}
|
||||
|
||||
void bank_card_set_name(BankCard* bank_card, char* name) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name);
|
||||
}
|
||||
|
||||
void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(number);
|
||||
string_t num_str;
|
||||
string_init(num_str);
|
||||
for(uint8_t i = 0; i < len; i += 2) {
|
||||
string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]);
|
||||
}
|
||||
// Add number
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str));
|
||||
string_clear(num_str);
|
||||
// Add icon
|
||||
widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13);
|
||||
// Add frame
|
||||
widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6);
|
||||
}
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(callback);
|
||||
widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context);
|
||||
}
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
|
||||
furi_assert(bank_card);
|
||||
char exp_date_str[16];
|
||||
snprintf(exp_date_str, sizeof(exp_date_str), "Exp: %02X/%02X", mon, year);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
|
||||
}
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name) {
|
||||
furi_assert(bank_card);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name);
|
||||
}
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) {
|
||||
furi_assert(bank_card);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
typedef struct BankCard BankCard;
|
||||
|
||||
BankCard* bank_card_alloc();
|
||||
|
||||
void bank_card_free(BankCard* bank_card);
|
||||
|
||||
void bank_card_clear(BankCard* bank_card);
|
||||
|
||||
View* bank_card_get_view(BankCard* bank_card);
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context);
|
||||
|
||||
void bank_card_set_name(BankCard* bank_card, char* name);
|
||||
|
||||
void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len);
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name);
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name);
|
|
@ -297,36 +297,44 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
|
|||
const char* path = request->content.storage_read_request.path;
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
bool result = false;
|
||||
bool fs_operation_success = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(fs_operation_success) {
|
||||
size_t size_left = storage_file_size(file);
|
||||
do {
|
||||
response->command_id = request->command_id;
|
||||
response->which_content = PB_Main_storage_read_response_tag;
|
||||
response->command_status = PB_CommandStatus_OK;
|
||||
response->content.storage_read_response.has_file = true;
|
||||
response->content.storage_read_response.file.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(MIN(size_left, MAX_DATA_SIZE)));
|
||||
uint8_t* buffer = response->content.storage_read_response.file.data->bytes;
|
||||
uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size;
|
||||
|
||||
size_t read_size = MIN(size_left, MAX_DATA_SIZE);
|
||||
*read_size_msg = storage_file_read(file, buffer, read_size);
|
||||
size_left -= read_size;
|
||||
result = (*read_size_msg == read_size);
|
||||
if(read_size) {
|
||||
response->content.storage_read_response.has_file = true;
|
||||
response->content.storage_read_response.file.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(read_size));
|
||||
uint8_t* buffer = &response->content.storage_read_response.file.data->bytes[0];
|
||||
uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size;
|
||||
|
||||
if(result) {
|
||||
response->has_next = (size_left > 0);
|
||||
*read_size_msg = storage_file_read(file, buffer, read_size);
|
||||
size_left -= *read_size_msg;
|
||||
fs_operation_success = (*read_size_msg == read_size);
|
||||
|
||||
response->has_next = fs_operation_success && (size_left > 0);
|
||||
} else {
|
||||
response->content.storage_read_response.file.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(0));
|
||||
response->content.storage_read_response.file.data->size = 0;
|
||||
response->content.storage_read_response.has_file = true;
|
||||
response->has_next = false;
|
||||
fs_operation_success = true;
|
||||
}
|
||||
|
||||
if(fs_operation_success) {
|
||||
rpc_send_and_release(session, response);
|
||||
}
|
||||
} while((size_left != 0) && result);
|
||||
} while((size_left != 0) && fs_operation_success);
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
rpc_send_and_release_empty(
|
||||
session, request->command_id, rpc_system_storage_get_file_error(file));
|
||||
}
|
||||
} else {
|
||||
if(!fs_operation_success) {
|
||||
rpc_send_and_release_empty(
|
||||
session, request->command_id, rpc_system_storage_get_file_error(file));
|
||||
}
|
||||
|
@ -349,7 +357,7 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
|||
RpcSession* session = rpc_storage->session;
|
||||
furi_assert(session);
|
||||
|
||||
bool result = true;
|
||||
bool fs_operation_success = true;
|
||||
|
||||
if(!path_contains_only_ascii(request->content.storage_write_request.path)) {
|
||||
rpc_storage->current_command_id = request->command_id;
|
||||
|
@ -370,28 +378,34 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
|||
rpc_storage->current_command_id = request->command_id;
|
||||
rpc_storage->state = RpcStorageStateWriting;
|
||||
const char* path = request->content.storage_write_request.path;
|
||||
result = storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
fs_operation_success =
|
||||
storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
}
|
||||
|
||||
File* file = rpc_storage->file;
|
||||
bool send_response = false;
|
||||
|
||||
if(result) {
|
||||
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
|
||||
size_t buffer_size = request->content.storage_write_request.file.data->size;
|
||||
|
||||
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
||||
result = (written_size == buffer_size);
|
||||
|
||||
if(result && !request->has_next) {
|
||||
rpc_send_and_release_empty(
|
||||
session, rpc_storage->current_command_id, PB_CommandStatus_OK);
|
||||
rpc_system_storage_reset_state(rpc_storage, session, false);
|
||||
if(fs_operation_success) {
|
||||
if(request->content.storage_write_request.has_file &&
|
||||
request->content.storage_write_request.file.data &&
|
||||
request->content.storage_write_request.file.data->size) {
|
||||
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
|
||||
size_t buffer_size = request->content.storage_write_request.file.data->size;
|
||||
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
||||
fs_operation_success = (written_size == buffer_size);
|
||||
}
|
||||
|
||||
send_response = !request->has_next;
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
rpc_send_and_release_empty(
|
||||
session, rpc_storage->current_command_id, rpc_system_storage_get_file_error(file));
|
||||
PB_CommandStatus command_status = PB_CommandStatus_OK;
|
||||
if(!fs_operation_success) {
|
||||
send_response = true;
|
||||
command_status = rpc_system_storage_get_file_error(file);
|
||||
}
|
||||
|
||||
if(send_response) {
|
||||
rpc_send_and_release_empty(session, rpc_storage->current_command_id, command_status);
|
||||
rpc_system_storage_reset_state(rpc_storage, session, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ int32_t sentry_safe_app(void* p) {
|
|||
view_port_input_callback_set(view_port, sentry_safe_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
Event event;
|
||||
|
@ -156,7 +156,7 @@ int32_t sentry_safe_app(void* p) {
|
|||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
|
|
|
@ -369,7 +369,7 @@ SpectrumAnalyzer* spectrum_analyzer_alloc() {
|
|||
view_port_input_callback_set(instance->view_port, spectrum_analyzer_input_callback, instance);
|
||||
|
||||
// Open GUI and register view_port
|
||||
instance->gui = furi_record_open("gui");
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
|
||||
|
||||
return instance;
|
||||
|
@ -378,7 +378,7 @@ SpectrumAnalyzer* spectrum_analyzer_alloc() {
|
|||
void spectrum_analyzer_free(SpectrumAnalyzer* instance) {
|
||||
// view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(instance->gui, instance->view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(instance->view_port);
|
||||
|
||||
spectrum_analyzer_worker_free(instance->worker);
|
||||
|
|
|
@ -274,24 +274,26 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) {
|
|||
if(parsed_count == EOF || parsed_count != 1) {
|
||||
storage_cli_print_usage();
|
||||
} else if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
uint8_t* data = malloc(buffer_size);
|
||||
uint64_t file_size = storage_file_size(file);
|
||||
|
||||
printf("Size: %lu\r\n", (uint32_t)file_size);
|
||||
|
||||
while(file_size > 0) {
|
||||
printf("\r\nReady?\r\n");
|
||||
cli_getc(cli);
|
||||
if(buffer_size) {
|
||||
uint8_t* data = malloc(buffer_size);
|
||||
while(file_size > 0) {
|
||||
printf("\r\nReady?\r\n");
|
||||
cli_getc(cli);
|
||||
|
||||
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
||||
for(uint16_t i = 0; i < read_size; i++) {
|
||||
putchar(data[i]);
|
||||
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
||||
for(uint16_t i = 0; i < read_size; i++) {
|
||||
putchar(data[i]);
|
||||
}
|
||||
file_size -= read_size;
|
||||
}
|
||||
file_size -= read_size;
|
||||
free(data);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
free(data);
|
||||
} else {
|
||||
storage_cli_print_error(storage_file_get_error(file));
|
||||
}
|
||||
|
@ -315,19 +317,21 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) {
|
|||
if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
printf("Ready\r\n");
|
||||
|
||||
uint8_t* buffer = malloc(buffer_size);
|
||||
if(buffer_size) {
|
||||
uint8_t* buffer = malloc(buffer_size);
|
||||
|
||||
for(uint32_t i = 0; i < buffer_size; i++) {
|
||||
buffer[i] = cli_getc(cli);
|
||||
for(uint32_t i = 0; i < buffer_size; i++) {
|
||||
buffer[i] = cli_getc(cli);
|
||||
}
|
||||
|
||||
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
||||
|
||||
if(written_size != buffer_size) {
|
||||
storage_cli_print_error(storage_file_get_error(file));
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
||||
|
||||
if(written_size != buffer_size) {
|
||||
storage_cli_print_error(storage_file_get_error(file));
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
} else {
|
||||
storage_cli_print_error(storage_file_get_error(file));
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ void storage_settings_scene_benchmark_on_enter(void* context) {
|
|||
view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx);
|
||||
|
||||
if(sd_status != FSE_OK) {
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
||||
|
|
|
@ -14,7 +14,7 @@ void storage_settings_scene_format_confirm_on_enter(void* context) {
|
|||
FS_Error sd_status = storage_sd_status(app->fs_api);
|
||||
|
||||
if(sd_status == FSE_NOT_READY) {
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
||||
|
|
|
@ -47,7 +47,7 @@ void storage_settings_scene_formatting_on_enter(void* context) {
|
|||
dialog_ex_set_text(
|
||||
dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter);
|
||||
} else {
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_header(dialog_ex, "Format\ncomplete!", 14, 15, AlignLeft, AlignTop);
|
||||
}
|
||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||
|
|
|
@ -18,7 +18,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) {
|
|||
dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_sd_info_dialog_callback);
|
||||
|
||||
if(sd_status != FSE_OK) {
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
||||
|
|
|
@ -14,7 +14,7 @@ void storage_settings_scene_unmount_confirm_on_enter(void* context) {
|
|||
FS_Error sd_status = storage_sd_status(app->fs_api);
|
||||
|
||||
if(sd_status == FSE_NOT_READY) {
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
||||
|
|
|
@ -13,7 +13,7 @@ void storage_settings_scene_unmounted_on_enter(void* context) {
|
|||
DialogEx* dialog_ex = app->dialog_ex;
|
||||
|
||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48);
|
||||
|
||||
if(error == FSE_OK) {
|
||||
dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop);
|
||||
|
|
|
@ -16,7 +16,7 @@ void subghz_scene_need_saving_on_enter(void* context) {
|
|||
SubGhz* subghz = context;
|
||||
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-Ghz menu?");
|
||||
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-GHz menu?");
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget,
|
||||
64,
|
||||
|
|
|
@ -100,7 +100,7 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
|
|||
subghz_setting_get_preset_data_size(subghz->setting, index));
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) {
|
||||
static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) {
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
|
@ -176,7 +176,7 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
|||
subghz->variable_item_list,
|
||||
"Hopping:",
|
||||
HOPPING_COUNT,
|
||||
subghz_scene_receiver_config_set_hopping_runing,
|
||||
subghz_scene_receiver_config_set_hopping_running,
|
||||
subghz);
|
||||
value_index = subghz_scene_receiver_config_hopper_value_index(
|
||||
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
|
||||
|
|
|
@ -101,7 +101,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
|
|||
subghz);
|
||||
}
|
||||
} else {
|
||||
widget_add_icon_element(subghz->widget, 32, 12, &I_DolphinFirstStart7_61x51);
|
||||
widget_add_icon_element(subghz->widget, 37, 15, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse.");
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
#include "../subghz_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubGhzRpcStateIdle,
|
||||
SubGhzRpcStateLoaded,
|
||||
} SubGhzRpcState;
|
||||
|
||||
void subghz_scene_rpc_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
Popup* popup = subghz->popup;
|
||||
|
||||
popup_set_header(popup, "Sub-GHz", 82, 28, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_header(popup, "Sub-GHz", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdPopup);
|
||||
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateIdle);
|
||||
|
||||
notification_message(subghz->notifications, &sequence_display_backlight_on);
|
||||
}
|
||||
|
||||
|
@ -18,28 +25,21 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
SubGhz* subghz = context;
|
||||
Popup* popup = subghz->popup;
|
||||
bool consumed = false;
|
||||
SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == SubGhzCustomEventSceneExit) {
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
scene_manager_stop(subghz->scene_manager);
|
||||
view_dispatcher_stop(subghz->view_dispatcher);
|
||||
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event.event == SubGhzCustomEventSceneRpcSessionClose) {
|
||||
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
||||
subghz->rpc_ctx = NULL;
|
||||
subghz_blink_stop(subghz);
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
||||
scene_manager_stop(subghz->scene_manager);
|
||||
view_dispatcher_stop(subghz->view_dispatcher);
|
||||
} else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
|
||||
bool result = false;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) &&
|
||||
(state == SubGhzRpcStateLoaded)) {
|
||||
subghz_blink_start(subghz);
|
||||
result = subghz_tx_start(subghz, subghz->txrx->fff_data);
|
||||
result = true;
|
||||
|
@ -57,8 +57,10 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
|
||||
bool result = false;
|
||||
const char* arg = rpc_system_app_get_data(subghz->rpc_ctx);
|
||||
if(arg) {
|
||||
if(arg && (state == SubGhzRpcStateIdle)) {
|
||||
if(subghz_key_load(subghz, arg, false)) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded);
|
||||
string_set_str(subghz->file_path, arg);
|
||||
result = true;
|
||||
string_t file_name;
|
||||
|
@ -70,7 +72,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
SUBGHZ_MAX_LEN_NAME,
|
||||
"loaded\n%s",
|
||||
string_get_cstr(file_name));
|
||||
popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, subghz->file_name_tmp, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
string_clear(file_name);
|
||||
}
|
||||
|
@ -83,6 +85,13 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
void subghz_scene_rpc_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep(subghz);
|
||||
subghz_blink_stop(subghz);
|
||||
}
|
||||
|
||||
Popup* popup = subghz->popup;
|
||||
|
||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||
|
|
|
@ -11,7 +11,7 @@ void subghz_scene_show_error_sub_on_enter(void* context) {
|
|||
|
||||
// Setup view
|
||||
Popup* popup = subghz->popup;
|
||||
popup_set_icon(popup, 72, 14, &I_DolphinFirstStart8_56x51);
|
||||
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
popup_set_header(popup, string_get_cstr(subghz->error_str), 14, 15, AlignLeft, AlignTop);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, subghz);
|
||||
|
|
|
@ -11,9 +11,14 @@ void subghz_scene_show_only_rx_on_enter(void* context) {
|
|||
|
||||
// Setup view
|
||||
Popup* popup = subghz->popup;
|
||||
popup_set_icon(popup, 67, 12, &I_DolphinFirstStart7_61x51);
|
||||
popup_set_text(
|
||||
popup, "This frequency is\noutside of default\nrange", 38, 40, AlignCenter, AlignBottom);
|
||||
|
||||
const char* header_text = "Transmission is blocked";
|
||||
const char* message_text = "This frequency is\noutside of default\nrange";
|
||||
|
||||
popup_set_header(popup, header_text, 63, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, message_text, 0, 17, AlignLeft, AlignTop);
|
||||
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, subghz);
|
||||
popup_set_callback(popup, subghz_scene_show_only_rx_popup_callback);
|
||||
|
|
|
@ -32,6 +32,8 @@ static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context)
|
|||
if(event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose);
|
||||
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
||||
subghz->rpc_ctx = NULL;
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
||||
} else if(event == RpcAppEventLoadFile) {
|
||||
|
|
|
@ -219,17 +219,13 @@ void subghz_dialog_message_show_only_rx(SubGhz* subghz) {
|
|||
DialogsApp* dialogs = subghz->dialogs;
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
|
||||
dialog_message_set_header(message, "Transmission is blocked", 63, 3, AlignCenter, AlignTop);
|
||||
const char* header_text = "Transmission is blocked";
|
||||
const char* message_text = "Frequency\nis outside of\ndefault range.\nCheck docs.";
|
||||
|
||||
dialog_message_set_text(
|
||||
message,
|
||||
"Frequency\nis outside of\ndefault range.\nCheck docs.",
|
||||
3,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
dialog_message_set_header(message, header_text, 63, 3, AlignCenter, AlignTop);
|
||||
dialog_message_set_text(message, message_text, 0, 17, AlignLeft, AlignTop);
|
||||
|
||||
dialog_message_set_icon(message, &I_DolphinFirstStart8_56x51, 72, 14);
|
||||
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
|
||||
|
||||
dialog_message_show(dialogs, message);
|
||||
dialog_message_free(message);
|
||||
|
@ -296,7 +292,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) {
|
|||
|
||||
if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
|
||||
//Todo add Custom_preset_module
|
||||
//delete peset if it already exists
|
||||
//delete preset if it already exists
|
||||
subghz_setting_delete_custom_preset(
|
||||
subghz->setting, string_get_cstr(subghz->txrx->preset->name));
|
||||
//load custom preset from file
|
||||
|
|
|
@ -373,7 +373,7 @@ int32_t tetris_game_app() {
|
|||
view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
tetris_state->timer =
|
||||
|
@ -460,7 +460,7 @@ int32_t tetris_game_app() {
|
|||
furi_timer_free(tetris_state->timer);
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
|
|
|
@ -327,7 +327,7 @@ int32_t tictactoe_game_app(void* p) {
|
|||
tictactoe_state_init(tictactoe_state);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
GameEvent event;
|
||||
|
@ -373,7 +373,7 @@ int32_t tictactoe_game_app(void* p) {
|
|||
furi_timer_free(tictactoe_state->timer);
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "u2f_data.h"
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <littlefs/lfs_util.h> // for lfs_tobe32
|
||||
|
||||
#include "toolbox/sha256.h"
|
||||
#include "toolbox/hmac_sha256.h"
|
||||
|
@ -256,6 +257,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
|||
uint8_t flags = 0;
|
||||
uint8_t hash[32];
|
||||
uint8_t signature[64];
|
||||
uint32_t be_u2f_counter;
|
||||
|
||||
if(u2f_data_check(false) == false) {
|
||||
U2F->ready = false;
|
||||
|
@ -275,11 +277,14 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
|||
}
|
||||
U2F->user_present = false;
|
||||
|
||||
// The 4 byte counter is represented in big endian. Increment it before use
|
||||
be_u2f_counter = lfs_tobe32(U2F->counter + 1);
|
||||
|
||||
// Generate hash
|
||||
sha256_start(&sha_ctx);
|
||||
sha256_update(&sha_ctx, req->app_id, 32);
|
||||
sha256_update(&sha_ctx, &flags, 1);
|
||||
sha256_update(&sha_ctx, (uint8_t*)&(U2F->counter), 4);
|
||||
sha256_update(&sha_ctx, (uint8_t*)&(be_u2f_counter), 4);
|
||||
sha256_update(&sha_ctx, req->challenge, 32);
|
||||
sha256_finish(&sha_ctx, hash);
|
||||
|
||||
|
@ -309,12 +314,12 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
|||
uECC_sign(priv_key, hash, 32, signature, U2F->p_curve);
|
||||
|
||||
resp->user_present = flags;
|
||||
resp->counter = U2F->counter;
|
||||
resp->counter = be_u2f_counter;
|
||||
uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature);
|
||||
memcpy(resp->signature + signature_len, state_no_error, 2);
|
||||
|
||||
FURI_LOG_D(TAG, "Counter: %lu", U2F->counter);
|
||||
U2F->counter++;
|
||||
FURI_LOG_D(TAG, "Counter: %lu", U2F->counter);
|
||||
u2f_data_cnt_write(U2F->counter);
|
||||
|
||||
if(U2F->callback != NULL) U2F->callback(U2fNotifyAuthSuccess, U2F->context);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <furi.h>
|
||||
#include "u2f_hid.h"
|
||||
#include "u2f_data.h"
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <furi_hal_random.h>
|
||||
|
@ -28,7 +28,8 @@
|
|||
#define U2F_DEVICE_KEY_VERSION 1
|
||||
|
||||
#define U2F_COUNTER_FILE_TYPE "Flipper U2F Counter File"
|
||||
#define U2F_COUNTER_VERSION 1
|
||||
#define U2F_COUNTER_VERSION 2
|
||||
#define U2F_COUNTER_VERSION_OLD 1
|
||||
|
||||
#define U2F_COUNTER_CONTROL_VAL 0xAA5500FF
|
||||
|
||||
|
@ -359,6 +360,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) {
|
|||
furi_assert(cnt_val);
|
||||
|
||||
bool state = false;
|
||||
bool old_counter = false;
|
||||
uint8_t iv[16];
|
||||
U2fCounterData cnt;
|
||||
uint8_t cnt_encr[48];
|
||||
|
@ -376,9 +378,16 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) {
|
|||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0 ||
|
||||
version != U2F_COUNTER_VERSION) {
|
||||
FURI_LOG_E(TAG, "Type or version mismatch");
|
||||
if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) {
|
||||
FURI_LOG_E(TAG, "Type mismatch");
|
||||
break;
|
||||
}
|
||||
if(version == U2F_COUNTER_VERSION_OLD) {
|
||||
// Counter is from previous U2F app version with endianness bug
|
||||
FURI_LOG_W(TAG, "Counter from old version");
|
||||
old_counter = true;
|
||||
} else if(version != U2F_COUNTER_VERSION) {
|
||||
FURI_LOG_E(TAG, "Version mismatch");
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_read_hex(flipper_format, "IV", iv, 16)) {
|
||||
|
@ -409,6 +418,13 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) {
|
|||
flipper_format_free(flipper_format);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
string_clear(filetype);
|
||||
|
||||
if(old_counter && state) {
|
||||
// Change counter endianness and rewrite counter file
|
||||
*cnt_val = __REV(cnt.counter);
|
||||
state = u2f_data_cnt_write(*cnt_val);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
#define TEST_RANDOM_COUNT_PARSE 158
|
||||
#define TEST_RANDOM_COUNT_PARSE 188
|
||||
#define TEST_TIMEOUT 10000
|
||||
|
||||
static SubGhzEnvironment* environment_handler;
|
||||
|
@ -404,6 +404,14 @@ MU_TEST(subghz_decoder_phoenix_v2_test) {
|
|||
"Test decoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_honeywell_wdb_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/honeywell_wdb_raw.sub"),
|
||||
SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
//test encoders
|
||||
MU_TEST(subghz_encoder_princeton_test) {
|
||||
mu_assert(
|
||||
|
@ -501,6 +509,12 @@ MU_TEST(subghz_encoder_phoenix_v2_test) {
|
|||
"Test encoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_honeywell_wdb_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/honeywell_wdb.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_random_test) {
|
||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||
}
|
||||
|
@ -537,6 +551,7 @@ MU_TEST_SUITE(subghz) {
|
|||
MU_RUN_TEST(subghz_decoder_bett_test);
|
||||
MU_RUN_TEST(subghz_decoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_decoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_decoder_honeywell_wdb_test);
|
||||
|
||||
MU_RUN_TEST(subghz_encoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_test);
|
||||
|
@ -554,6 +569,7 @@ MU_TEST_SUITE(subghz) {
|
|||
MU_RUN_TEST(subghz_encoder_bett_test);
|
||||
MU_RUN_TEST(subghz_encoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
|
||||
|
||||
MU_RUN_TEST(subghz_random_test);
|
||||
subghz_test_deinit();
|
||||
|
|
|
@ -96,7 +96,7 @@ static WavPlayerApp* app_alloc() {
|
|||
WavPlayerApp* app = malloc(sizeof(WavPlayerApp));
|
||||
app->samples_count_half = 1024 * 4;
|
||||
app->samples_count = app->samples_count_half * 2;
|
||||
app->storage = furi_record_open("storage");
|
||||
app->storage = furi_record_open(RECORD_STORAGE);
|
||||
app->stream = file_stream_alloc(app->storage);
|
||||
app->parser = wav_parser_alloc();
|
||||
app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count);
|
||||
|
@ -106,7 +106,7 @@ static WavPlayerApp* app_alloc() {
|
|||
app->volume = 10.0f;
|
||||
app->play = true;
|
||||
|
||||
app->gui = furi_record_open("gui");
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->view = wav_player_view_alloc();
|
||||
|
||||
|
@ -124,14 +124,14 @@ static void app_free(WavPlayerApp* app) {
|
|||
view_dispatcher_remove_view(app->view_dispatcher, 0);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
wav_player_view_free(app->view);
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
furi_message_queue_free(app->queue);
|
||||
free(app->tmp_buffer);
|
||||
free(app->sample_buffer);
|
||||
wav_parser_free(app->parser);
|
||||
stream_free(app->stream);
|
||||
furi_record_close("storage");
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
notification_message(app->notification, &sequence_display_backlight_enforce_auto);
|
||||
furi_record_close("notification");
|
||||
|
@ -296,11 +296,11 @@ int32_t wav_player_app(void* p) {
|
|||
UNUSED(p);
|
||||
WavPlayerApp* app = app_alloc();
|
||||
|
||||
Storage* storage = furi_record_open("storage");
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(!storage_simply_mkdir(storage, WAVPLAYER_FOLDER)) {
|
||||
FURI_LOG_E(TAG, "Could not create folder %s", WAVPLAYER_FOLDER);
|
||||
}
|
||||
furi_record_close("storage");
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
app_run(app);
|
||||
app_free(app);
|
||||
|
|
|
@ -8,7 +8,7 @@ void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, vo
|
|||
app->text_box_store_strlen += len;
|
||||
if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) {
|
||||
string_right(app->text_box_store, app->text_box_store_strlen / 2);
|
||||
app->text_box_store_strlen = string_size(app->text_box_store);
|
||||
app->text_box_store_strlen = string_size(app->text_box_store) + len;
|
||||
}
|
||||
|
||||
// Null-terminate buf and append to text box store
|
||||
|
@ -32,10 +32,23 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
|
|||
if(app->is_command) {
|
||||
string_reset(app->text_box_store);
|
||||
app->text_box_store_strlen = 0;
|
||||
} else { // "View Log" menu action
|
||||
text_box_set_text(app->text_box, string_get_cstr(app->text_box_store));
|
||||
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
|
||||
const char* help_msg =
|
||||
"For app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n";
|
||||
string_cat_str(app->text_box_store, help_msg);
|
||||
app->text_box_store_strlen += strlen(help_msg);
|
||||
}
|
||||
|
||||
if(app->show_stopscan_tip) {
|
||||
const char* help_msg = "Press BACK to send stopscan\n";
|
||||
string_cat_str(app->text_box_store, help_msg);
|
||||
app->text_box_store_strlen += strlen(help_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting text - for "View Log", this will just be what was already in the text box store
|
||||
text_box_set_text(app->text_box, string_get_cstr(app->text_box_store));
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput);
|
||||
|
||||
|
|
|
@ -1,67 +1,138 @@
|
|||
#include "../wifi_marauder_app_i.h"
|
||||
|
||||
#define NUM_MENU_ITEMS (29)
|
||||
|
||||
// For each command, define whether additional arguments are needed
|
||||
// (enabling text input to fill them out), and whether the console
|
||||
// text box should focus at the start of the output or the end
|
||||
#define INPUT_ARGS (true)
|
||||
#define NO_ARGS (false)
|
||||
#define FOCUS_CONSOLE_START (true)
|
||||
#define FOCUS_CONSOLE_END (false)
|
||||
struct WifiMarauderItem {
|
||||
const char* item_string;
|
||||
bool needs_keyboard;
|
||||
bool focus_console_start;
|
||||
};
|
||||
typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs;
|
||||
|
||||
const struct WifiMarauderItem items[NUM_MENU_ITEMS] = {
|
||||
{"View Log (start)", NO_ARGS, FOCUS_CONSOLE_START},
|
||||
{"View Log (end)", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t beacon -l", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t beacon -r", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t beacon -a", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t deauth", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t probe", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"attack -t rickroll", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"channel", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"channel -s", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"clearlist -a", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"clearlist -s", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"help", NO_ARGS, FOCUS_CONSOLE_START},
|
||||
{"list -a", NO_ARGS, FOCUS_CONSOLE_START},
|
||||
{"list -s", NO_ARGS, FOCUS_CONSOLE_START},
|
||||
{"reboot", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"scanap", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"select -a", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"select -s", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffbeacon", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffdeauth", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffesp", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffpmkid", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffpmkid -c", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"sniffpwn", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
{"ssid -a -g", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"ssid -a -n", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"ssid -r", INPUT_ARGS, FOCUS_CONSOLE_END},
|
||||
{"update -w", NO_ARGS, FOCUS_CONSOLE_END},
|
||||
typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole;
|
||||
|
||||
#define SHOW_STOPSCAN_TIP (true)
|
||||
#define NO_TIP (false)
|
||||
|
||||
#define MAX_OPTIONS (6)
|
||||
typedef struct {
|
||||
const char* item_string;
|
||||
const char* options_menu[MAX_OPTIONS];
|
||||
int num_options_menu;
|
||||
const char* actual_commands[MAX_OPTIONS];
|
||||
InputArgs needs_keyboard;
|
||||
FocusConsole focus_console;
|
||||
bool show_stopscan_tip;
|
||||
} WifiMarauderItem;
|
||||
|
||||
// NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it!
|
||||
const WifiMarauderItem items[NUM_MENU_ITEMS] = {
|
||||
{"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP},
|
||||
{"Scan AP", {""}, 1, {"scanap"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP},
|
||||
{"SSID",
|
||||
{"add random", "add name", "remove"},
|
||||
3,
|
||||
{"ssid -a -g", "ssid -a -n", "ssid -r"},
|
||||
INPUT_ARGS,
|
||||
FOCUS_CONSOLE_START,
|
||||
NO_TIP},
|
||||
{"List", {"ap", "ssid"}, 2, {"list -a", "list -s"}, NO_ARGS, FOCUS_CONSOLE_START, NO_TIP},
|
||||
{"Select", {"ap", "ssid"}, 2, {"select -a", "select -s"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Clear List",
|
||||
{"ap", "ssid"},
|
||||
2,
|
||||
{"clearlist -a", "clearlist -s"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Attack",
|
||||
{"deauth", "probe", "rickroll"},
|
||||
3,
|
||||
{"attack -t deauth", "attack -t probe", "attack -t rickroll"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Beacon Spam",
|
||||
{"ap list", "ssid list", "random"},
|
||||
3,
|
||||
{"attack -t beacon -a", "attack -t beacon -l", "attack -t beacon -r"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Sniff",
|
||||
{"beacon", "deauth", "esp", "pmkid", "pwn"},
|
||||
5,
|
||||
{"sniffbeacon", "sniffdeauth", "sniffesp", "sniffpmkid", "sniffpwn"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Sniff PMKID on channel",
|
||||
{""},
|
||||
1,
|
||||
{"sniffpmkid -c"},
|
||||
INPUT_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Channel",
|
||||
{"get", "set"},
|
||||
2,
|
||||
{"channel", "channel -s"},
|
||||
TOGGLE_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Settings",
|
||||
{"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "other"},
|
||||
6,
|
||||
{"settings",
|
||||
"settings -r",
|
||||
"settings -s ForcePMKID enable",
|
||||
"settings -s ForceProbe enable",
|
||||
"settings -s SavePCAP enable",
|
||||
"settings -s"},
|
||||
TOGGLE_ARGS,
|
||||
FOCUS_CONSOLE_START,
|
||||
NO_TIP},
|
||||
{"Update", {""}, 1, {"update -w"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
|
||||
};
|
||||
|
||||
static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
WifiMarauderApp* app = context;
|
||||
app->selected_tx_string = items[index].item_string;
|
||||
app->is_command = (2 <= index);
|
||||
|
||||
furi_assert(index < NUM_MENU_ITEMS);
|
||||
const WifiMarauderItem* item = &items[index];
|
||||
|
||||
const int selected_option_index = app->selected_option_index[index];
|
||||
furi_assert(selected_option_index < item->num_options_menu);
|
||||
app->selected_tx_string = item->actual_commands[selected_option_index];
|
||||
app->is_command = (1 <= index);
|
||||
app->is_custom_tx_string = false;
|
||||
app->selected_menu_index = index;
|
||||
app->focus_console_start = items[index].focus_console_start;
|
||||
if(items[index].needs_keyboard) {
|
||||
app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ?
|
||||
(selected_option_index == 0) :
|
||||
item->focus_console;
|
||||
app->show_stopscan_tip = item->show_stopscan_tip;
|
||||
|
||||
bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) :
|
||||
item->needs_keyboard;
|
||||
if(needs_keyboard) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartKeyboard);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole);
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_marauder_scene_start_var_list_change_callback(VariableItem* item) {
|
||||
furi_assert(item);
|
||||
|
||||
WifiMarauderApp* app = variable_item_get_context(item);
|
||||
furi_assert(app);
|
||||
|
||||
const WifiMarauderItem* menu_item = &items[app->selected_menu_index];
|
||||
uint8_t item_index = variable_item_get_current_value_index(item);
|
||||
furi_assert(item_index < menu_item->num_options_menu);
|
||||
variable_item_set_current_value_text(item, menu_item->options_menu[item_index]);
|
||||
app->selected_option_index[app->selected_menu_index] = item_index;
|
||||
}
|
||||
|
||||
void wifi_marauder_scene_start_on_enter(void* context) {
|
||||
WifiMarauderApp* app = context;
|
||||
VariableItemList* var_item_list = app->var_item_list;
|
||||
|
@ -69,9 +140,17 @@ void wifi_marauder_scene_start_on_enter(void* context) {
|
|||
variable_item_list_set_enter_callback(
|
||||
var_item_list, wifi_marauder_scene_start_var_list_enter_callback, app);
|
||||
|
||||
// TODO: organize menu
|
||||
VariableItem* item;
|
||||
for(int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
variable_item_list_add(var_item_list, items[i].item_string, 0, NULL, NULL);
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
items[i].item_string,
|
||||
items[i].num_options_menu,
|
||||
wifi_marauder_scene_start_var_list_change_callback,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, app->selected_option_index[i]);
|
||||
variable_item_set_current_value_text(
|
||||
item, items[i].options_menu[app->selected_option_index[i]]);
|
||||
}
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
|
@ -96,6 +175,9 @@ bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event)
|
|||
scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
|
|
@ -24,7 +24,20 @@ void wifi_marauder_scene_text_input_on_enter(void* context) {
|
|||
|
||||
// Setup view
|
||||
TextInput* text_input = app->text_input;
|
||||
text_input_set_header_text(text_input, "Add command arguments");
|
||||
// Add help message to header
|
||||
if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) {
|
||||
text_input_set_header_text(text_input, "Enter # SSIDs to generate");
|
||||
} else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) {
|
||||
text_input_set_header_text(text_input, "Enter SSID name to add");
|
||||
} else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) {
|
||||
text_input_set_header_text(text_input, "Remove target from SSID list");
|
||||
} else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) {
|
||||
text_input_set_header_text(text_input, "Add target from AP list");
|
||||
} else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) {
|
||||
text_input_set_header_text(text_input, "Add target from SSID list");
|
||||
} else {
|
||||
text_input_set_header_text(text_input, "Add command arguments");
|
||||
}
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
wifi_marauder_scene_text_input_callback,
|
||||
|
|
|
@ -24,7 +24,7 @@ static void wifi_marauder_app_tick_event_callback(void* context) {
|
|||
WifiMarauderApp* wifi_marauder_app_alloc() {
|
||||
WifiMarauderApp* app = malloc(sizeof(WifiMarauderApp));
|
||||
|
||||
app->gui = furi_record_open("gui");
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app);
|
||||
|
@ -46,6 +46,10 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
|
|||
WifiMarauderAppViewVarItemList,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
for(int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
app->selected_option_index[i] = 0;
|
||||
}
|
||||
|
||||
app->text_box = text_box_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box));
|
||||
|
@ -79,7 +83,7 @@ void wifi_marauder_app_free(WifiMarauderApp* app) {
|
|||
wifi_marauder_uart_free(app->uart);
|
||||
|
||||
// Close records
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
|
||||
#define NUM_MENU_ITEMS (15)
|
||||
|
||||
#define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096)
|
||||
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
|
||||
|
||||
|
@ -31,10 +33,12 @@ struct WifiMarauderApp {
|
|||
|
||||
WifiMarauderUart* uart;
|
||||
int selected_menu_index;
|
||||
int selected_option_index[NUM_MENU_ITEMS];
|
||||
const char* selected_tx_string;
|
||||
bool is_command;
|
||||
bool is_custom_tx_string;
|
||||
bool focus_console_start;
|
||||
bool show_stopscan_tip;
|
||||
};
|
||||
|
||||
// Supported commands:
|
||||
|
|
|
@ -685,7 +685,7 @@ int32_t wifi_scanner_app(void* p) {
|
|||
view_port_input_callback_set(view_port, wifi_module_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
//notification_message(app->notification, &sequence_set_only_blue_255);
|
||||
|
@ -831,7 +831,7 @@ int32_t wifi_scanner_app(void* p) {
|
|||
gui_remove_view_port(gui, view_port);
|
||||
|
||||
// Close gui record
|
||||
furi_record_close("gui");
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close("notification");
|
||||
app->m_gui = NULL;
|
||||
|
||||
|
|
BIN
assets/icons/Dolphin/DolphinCommon_56x48.png
Normal file
BIN
assets/icons/Dolphin/DolphinCommon_56x48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 544 B |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
BIN
assets/icons/NFC/Keychain.png
Normal file
BIN
assets/icons/NFC/Keychain.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit cc5918dc488ac3617012ce5377114e086b447324
|
||||
Subproject commit 6727eaf287db077dcd28719cd764f5804712223e
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue