mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 13:09:49 +04:00
Merge remote-tracking branch 'upstream/dev' into feat/unirf-protocols
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
### New changes
|
### New changes
|
||||||
* Fix qFlipper and other apps causes flipper crash while trying to interact with files - see commit `b2bd13`
|
* Wifi Marauder app update (by @0xchocolate)
|
||||||
* NRF24 Sniffer update
|
* Updated Universal remote assets (by @Amec0e)
|
||||||
* Other fixes
|
* 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**
|
**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)
|
## [- 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**
|
### **Plugins**
|
||||||
|
|
||||||
## [- Configure UniversalRF Remix App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/UniRFRemix.md)
|
## [- 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?
|
# Where I can find IR, SubGhz, ... files, DBs, and other stuff?
|
||||||
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
||||||
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
## [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>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <gui/modules/empty_screen.h>
|
#include <gui/modules/empty_screen.h>
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
#include <furi_hal_version.h>
|
#include <furi_hal_version.h>
|
||||||
|
#include <furi_hal_region.h>
|
||||||
#include <furi_hal_bt.h>
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message);
|
typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message);
|
||||||
@@ -114,12 +115,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage*
|
|||||||
|
|
||||||
string_cat_printf(
|
string_cat_printf(
|
||||||
buffer,
|
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_version(),
|
||||||
furi_hal_version_get_hw_target(),
|
furi_hal_version_get_hw_target(),
|
||||||
furi_hal_version_get_hw_body(),
|
furi_hal_version_get_hw_body(),
|
||||||
furi_hal_version_get_hw_connect(),
|
furi_hal_version_get_hw_connect(),
|
||||||
furi_hal_version_get_hw_region_name(),
|
furi_hal_version_get_hw_region_name(),
|
||||||
|
furi_hal_region_get_name(),
|
||||||
my_name ? my_name : "Unknown");
|
my_name ? my_name : "Unknown");
|
||||||
|
|
||||||
string_cat_printf(buffer, "Serial Number:\n");
|
string_cat_printf(buffer, "Serial Number:\n");
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ void AccessorApp::run(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AccessorApp::AccessorApp() {
|
AccessorApp::AccessorApp() {
|
||||||
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||||
onewire_host = onewire_host_alloc();
|
onewire_host = onewire_host_alloc();
|
||||||
furi_hal_power_enable_otg();
|
furi_hal_power_enable_otg();
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessorApp::~AccessorApp() {
|
AccessorApp::~AccessorApp() {
|
||||||
furi_hal_power_disable_otg();
|
furi_hal_power_disable_otg();
|
||||||
furi_record_close("notification");
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
onewire_host_free(onewire_host);
|
onewire_host_free(onewire_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ AccessorAppViewManager::AccessorAppViewManager() {
|
|||||||
popup = popup_alloc();
|
popup = popup_alloc();
|
||||||
add_view(ViewType::Popup, popup_get_view(popup));
|
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);
|
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
// set previous view callback for all views
|
// set previous view callback for all views
|
||||||
@@ -31,6 +31,7 @@ AccessorAppViewManager::~AccessorAppViewManager() {
|
|||||||
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup));
|
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup));
|
||||||
|
|
||||||
// free view modules
|
// free view modules
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
submenu_free(submenu);
|
submenu_free(submenu);
|
||||||
popup_free(popup);
|
popup_free(popup);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef void (*FlipperOnStartHook)(void);
|
typedef void (*FlipperOnStartHook)(void);
|
||||||
|
|
||||||
|
extern const char* FLIPPER_AUTORUN_APP_NAME;
|
||||||
|
|
||||||
/* Services list
|
/* Services list
|
||||||
* Spawned on startup
|
* Spawned on startup
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ uint16_t archive_favorites_count(void* context) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue; // Skip empty lines
|
||||||
}
|
}
|
||||||
++lines;
|
++lines;
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ static bool archive_favourites_rescan() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(string_search(buffer, "/app:") == 0) {
|
if(string_search(buffer, "/app:") == 0) {
|
||||||
@@ -152,7 +152,7 @@ bool archive_favorites_read(void* context) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(string_search(buffer, "/app:") == 0) {
|
if(string_search(buffer, "/app:") == 0) {
|
||||||
@@ -215,7 +215,7 @@ bool archive_favorites_delete(const char* format, ...) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(string_search(buffer, filename)) {
|
if(string_search(buffer, filename)) {
|
||||||
@@ -259,7 +259,7 @@ bool archive_is_favorite(const char* format, ...) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if(!string_search(buffer, filename)) {
|
if(!string_search(buffer, filename)) {
|
||||||
found = true;
|
found = true;
|
||||||
@@ -299,7 +299,7 @@ bool archive_favorites_rename(const char* src, const char* dst) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!string_size(buffer)) {
|
if(!string_size(buffer)) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
archive_file_append(
|
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);
|
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
PluginEvent event;
|
PluginEvent event;
|
||||||
@@ -537,7 +537,7 @@ int32_t barcode_UPCA_generator_app(void* p) {
|
|||||||
|
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
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) {
|
void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
UNUSED(last);
|
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());
|
furi_timer_start(timer, furi_kernel_get_tick_frequency());
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
@@ -137,7 +137,7 @@ int32_t clock_app(void* p) {
|
|||||||
furi_timer_free(timer);
|
furi_timer_free(timer);
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
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);
|
view_port_input_callback_set(view_port, dec_hex_converter_input_callback, event_queue);
|
||||||
|
|
||||||
// open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
dec_hex_converter_init(dec_hex_converter_state);
|
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);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
delete_mutex(&state_mutex);
|
||||||
|
|||||||
@@ -36,12 +36,13 @@ void desktop_debug_render(Canvas* canvas, void* model) {
|
|||||||
snprintf(
|
snprintf(
|
||||||
buffer,
|
buffer,
|
||||||
sizeof(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_version(),
|
||||||
furi_hal_version_get_hw_target(),
|
furi_hal_version_get_hw_target(),
|
||||||
furi_hal_version_get_hw_body(),
|
furi_hal_version_get_hw_body(),
|
||||||
furi_hal_version_get_hw_connect(),
|
furi_hal_version_get_hw_connect(),
|
||||||
furi_hal_version_get_hw_region_name(),
|
furi_hal_version_get_hw_region_name(),
|
||||||
|
furi_hal_region_get_name(),
|
||||||
my_name ? my_name : "Unknown");
|
my_name ? my_name : "Unknown");
|
||||||
canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer);
|
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);
|
view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
//notification_message(app->notification, &sequence_set_only_blue_255);
|
//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);
|
gui_remove_view_port(gui, view_port);
|
||||||
|
|
||||||
// Close gui record
|
// Close gui record
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
app->m_gui = NULL;
|
app->m_gui = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,19 @@ void widget_add_text_box_element(
|
|||||||
widget_add_element(widget, 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(
|
void widget_add_button_element(
|
||||||
Widget* widget,
|
Widget* widget,
|
||||||
GuiButtonType button_type,
|
GuiButtonType button_type,
|
||||||
|
|||||||
@@ -105,6 +105,27 @@ void widget_add_text_box_element(
|
|||||||
const char* text,
|
const char* text,
|
||||||
bool strip_to_dots);
|
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
|
/** Add Button Element
|
||||||
*
|
*
|
||||||
* @param widget Widget instance
|
* @param widget Widget instance
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct WidgetElement {
|
|||||||
|
|
||||||
// generic model holder
|
// generic model holder
|
||||||
void* model;
|
void* model;
|
||||||
|
FuriMutex* model_mutex;
|
||||||
|
|
||||||
// pointer to widget that hold our element
|
// pointer to widget that hold our element
|
||||||
Widget* parent;
|
Widget* parent;
|
||||||
@@ -80,3 +81,10 @@ WidgetElement* widget_element_frame_create(
|
|||||||
uint8_t width,
|
uint8_t width,
|
||||||
uint8_t height,
|
uint8_t height,
|
||||||
uint8_t radius);
|
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) {
|
void HIDApp::run(void* _args) {
|
||||||
UNUSED(_args);
|
UNUSED(_args);
|
||||||
|
|
||||||
|
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||||
scene_controller.add_scene(SceneType::Read, new HIDAppSceneRead());
|
scene_controller.add_scene(SceneType::Read, new HIDAppSceneRead());
|
||||||
scene_controller.add_scene(SceneType::ReadSuccess, new HIDAppSceneReadSuccess());
|
scene_controller.add_scene(SceneType::ReadSuccess, new HIDAppSceneReadSuccess());
|
||||||
scene_controller.process(100, SceneType::Read);
|
scene_controller.process(100, SceneType::Read);
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context)
|
|||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
||||||
|
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||||
|
ibutton->rpc_ctx = NULL;
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == iButtonCustomEventRpcLoad) {
|
if(event.event == iButtonCustomEventRpcLoad) {
|
||||||
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
|
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if(arg) {
|
if(arg && (string_empty_p(ibutton->file_path))) {
|
||||||
string_set_str(ibutton->file_path, arg);
|
string_set_str(ibutton->file_path, arg);
|
||||||
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
||||||
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
|
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);
|
string_clear(key_name);
|
||||||
result = true;
|
result = true;
|
||||||
|
} else {
|
||||||
|
string_reset(ibutton->file_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
|
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
} else if(event.event == iButtonCustomEventRpcExit) {
|
} else if(event.event == iButtonCustomEventRpcExit) {
|
||||||
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true);
|
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);
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
||||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
scene_manager_stop(ibutton->scene_manager);
|
||||||
ibutton->rpc_ctx = NULL;
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
|
||||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context
|
|||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
|
||||||
|
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||||
|
infrared->rpc_ctx = NULL;
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
|
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) {
|
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)) {
|
if(infrared_signal_is_raw(signal)) {
|
||||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||||
infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
|
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);
|
DOLPHIN_DEED(DolphinDeedIrSend);
|
||||||
infrared_worker_tx_start(infrared->worker);
|
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
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) {
|
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) {
|
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_stop(infrared->worker);
|
||||||
|
infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
|
||||||
|
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#define INFRARED_APP_EXTENSION ".ir"
|
#define INFRARED_APP_EXTENSION ".ir"
|
||||||
|
|
||||||
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
||||||
|
#define INFRARED_LOG_TAG "InfraredApp"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
InfraredButtonIndexNone = -1,
|
InfraredButtonIndexNone = -1,
|
||||||
@@ -63,6 +64,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
bool is_learning_new_remote;
|
bool is_learning_new_remote;
|
||||||
bool is_debug_enabled;
|
bool is_debug_enabled;
|
||||||
|
bool is_transmitting;
|
||||||
InfraredEditTarget edit_target : 8;
|
InfraredEditTarget edit_target : 8;
|
||||||
InfraredEditMode edit_mode : 8;
|
InfraredEditMode edit_mode : 8;
|
||||||
int32_t current_button_index;
|
int32_t current_button_index;
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
InfraredSceneLearnSuccessStateIdle = 0,
|
|
||||||
InfraredSceneLearnSuccessStateSending = 1,
|
|
||||||
} InfraredSceneLearnSuccessState;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
|
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
@@ -21,9 +16,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
|
|||||||
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
|
DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
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)) {
|
if(infrared_signal_is_raw(signal)) {
|
||||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||||
dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter);
|
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_set_context(dialog_ex, context);
|
||||||
dialog_ex_enable_extended_events(dialog_ex);
|
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);
|
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
|
bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
SceneManager* scene_manager = infrared->scene_manager;
|
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;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeTick) {
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
if(is_transmitter_idle) {
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
if(is_transmitter_idle) {
|
||||||
scene_manager_next_scene(scene_manager, InfraredSceneAskBack);
|
scene_manager_next_scene(scene_manager, InfraredSceneAskBack);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == DialogExResultLeft) {
|
if(event.event == DialogExResultLeft) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
if(is_transmitter_idle) {
|
||||||
scene_manager_next_scene(scene_manager, InfraredSceneAskRetry);
|
scene_manager_next_scene(scene_manager, InfraredSceneAskRetry);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == DialogExResultRight) {
|
} else if(event.event == DialogExResultRight) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
if(is_transmitter_idle) {
|
||||||
scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName);
|
scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == DialogExPressCenter) {
|
} else if(event.event == DialogExPressCenter) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateIdle) {
|
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
||||||
scene_manager_set_scene_state(
|
infrared_tx_start_received(infrared);
|
||||||
scene_manager,
|
|
||||||
InfraredSceneLearnSuccess,
|
|
||||||
InfraredSceneLearnSuccessStateSending);
|
|
||||||
infrared_tx_start_received(infrared);
|
|
||||||
infrared_play_notification_message(
|
|
||||||
infrared, InfraredNotificationMessageBlinkStartSend);
|
|
||||||
}
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == DialogExReleaseCenter) {
|
} else if(event.event == DialogExReleaseCenter) {
|
||||||
if(scene_state == InfraredSceneLearnSuccessStateSending) {
|
infrared_tx_stop(infrared);
|
||||||
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);
|
|
||||||
}
|
|
||||||
consumed = true;
|
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) {
|
void infrared_scene_learn_success_on_exit(void* context) {
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
InfraredWorker* worker = infrared->worker;
|
|
||||||
dialog_ex_reset(infrared->dialog_ex);
|
dialog_ex_reset(infrared->dialog_ex);
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
|
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;
|
ButtonMenu* button_menu = infrared->button_menu;
|
||||||
SceneManager* scene_manager = infrared->scene_manager;
|
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);
|
size_t button_count = infrared_remote_get_button_count(remote);
|
||||||
for(size_t i = 0; i < button_count; ++i) {
|
for(size_t i = 0; i < button_count; ++i) {
|
||||||
InfraredRemoteButton* button = infrared_remote_get_button(remote, 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) {
|
bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
SceneManager* scene_manager = infrared->scene_manager;
|
SceneManager* scene_manager = infrared->scene_manager;
|
||||||
|
const bool is_transmitter_idle = !infrared->app_state.is_transmitting;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeBack) {
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
if(is_transmitter_idle) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
|
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
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) {
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
const uint16_t custom_type = infrared_custom_event_get_type(event.event);
|
const uint16_t custom_type = infrared_custom_event_get_type(event.event);
|
||||||
const int16_t button_index = infrared_custom_event_get_value(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;
|
consumed = true;
|
||||||
} else if(custom_type == InfraredCustomEventTypeMenuSelected) {
|
} else if(custom_type == InfraredCustomEventTypeMenuSelected) {
|
||||||
furi_assert(button_index < 0);
|
furi_assert(button_index < 0);
|
||||||
scene_manager_set_scene_state(
|
if(is_transmitter_idle) {
|
||||||
scene_manager, InfraredSceneRemote, (unsigned)button_index);
|
scene_manager_set_scene_state(
|
||||||
if(button_index == ButtonIndexPlus) {
|
scene_manager, InfraredSceneRemote, (unsigned)button_index);
|
||||||
infrared->app_state.is_learning_new_remote = false;
|
if(button_index == ButtonIndexPlus) {
|
||||||
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
infrared->app_state.is_learning_new_remote = false;
|
||||||
consumed = true;
|
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
||||||
} else if(button_index == ButtonIndexEdit) {
|
consumed = true;
|
||||||
scene_manager_next_scene(scene_manager, InfraredSceneEdit);
|
} else if(button_index == ButtonIndexEdit) {
|
||||||
|
scene_manager_next_scene(scene_manager, InfraredSceneEdit);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +117,5 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
void infrared_scene_remote_on_exit(void* context) {
|
void infrared_scene_remote_on_exit(void* context) {
|
||||||
Infrared* infrared = 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);
|
button_menu_reset(infrared->button_menu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
#include "../infrared_i.h"
|
#include "../infrared_i.h"
|
||||||
#include "gui/canvas.h"
|
#include "gui/canvas.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
InfraredRpcStateIdle,
|
||||||
|
InfraredRpcStateLoaded,
|
||||||
|
InfraredRpcStateSending,
|
||||||
|
} InfraredRpcState;
|
||||||
|
|
||||||
void infrared_scene_rpc_on_enter(void* context) {
|
void infrared_scene_rpc_on_enter(void* context) {
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
Popup* popup = infrared->popup;
|
Popup* popup = infrared->popup;
|
||||||
|
|
||||||
popup_set_header(popup, "Infrared", 82, 28, AlignCenter, AlignBottom);
|
popup_set_header(popup, "Infrared", 89, 42, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
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_context(popup, context);
|
||||||
popup_set_callback(popup, infrared_popup_closed_callback);
|
popup_set_callback(popup, infrared_popup_closed_callback);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
|
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);
|
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) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
InfraredRpcState state =
|
||||||
|
scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc);
|
||||||
if(event.event == InfraredCustomEventTypeBackPressed) {
|
if(event.event == InfraredCustomEventTypeBackPressed) {
|
||||||
view_dispatcher_stop(infrared->view_dispatcher);
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||||
@@ -31,39 +41,49 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
} else if(event.event == InfraredCustomEventTypeRpcLoad) {
|
} else if(event.event == InfraredCustomEventTypeRpcLoad) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||||
if(arg) {
|
if(arg && (state == InfraredRpcStateIdle)) {
|
||||||
string_set_str(infrared->file_path, arg);
|
string_set_str(infrared->file_path, arg);
|
||||||
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
||||||
infrared_worker_tx_set_get_signal_callback(
|
if(result) {
|
||||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
scene_manager_set_scene_state(
|
||||||
|
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||||
|
|
||||||
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
||||||
popup_set_text(
|
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);
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
} else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
|
} else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||||
if(arg) {
|
if(arg && (state == InfraredRpcStateLoaded)) {
|
||||||
size_t button_index = 0;
|
size_t button_index = 0;
|
||||||
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
||||||
infrared_tx_start_button_index(infrared, button_index);
|
infrared_tx_start_button_index(infrared, button_index);
|
||||||
result = true;
|
result = true;
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||||
} else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
|
} else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
|
||||||
infrared_tx_stop(infrared);
|
bool result = false;
|
||||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true);
|
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) {
|
} else if(event.event == InfraredCustomEventTypeRpcExit) {
|
||||||
|
scene_manager_stop(infrared->scene_manager);
|
||||||
view_dispatcher_stop(infrared->view_dispatcher);
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
} else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
|
} else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
|
||||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
scene_manager_stop(infrared->scene_manager);
|
||||||
infrared->rpc_ctx = NULL;
|
|
||||||
view_dispatcher_stop(infrared->view_dispatcher);
|
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) {
|
void infrared_scene_rpc_on_exit(void* context) {
|
||||||
Infrared* infrared = 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);
|
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"));
|
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/audio.ir"));
|
||||||
//TODO Improve Audio universal remote
|
//TODO Improve Audio universal remote
|
||||||
button_panel_reserve(button_panel, 2, 1);
|
button_panel_reserve(button_panel, 2, 2);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
button_panel_add_item(
|
button_panel_add_item(
|
||||||
button_panel,
|
button_panel,
|
||||||
@@ -37,8 +37,33 @@ void infrared_scene_universal_audio_on_enter(void* context) {
|
|||||||
infrared_scene_universal_common_item_callback,
|
infrared_scene_universal_common_item_callback,
|
||||||
context);
|
context);
|
||||||
infrared_brute_force_add_record(brute_force, i++, "MUTE");
|
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_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
|
||||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
|
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;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::RpcSessionClose;
|
event.type = LfRfidApp::EventType::RpcSessionClose;
|
||||||
app->view_controller.send_event(&event);
|
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) {
|
} else if(rpc_event == RpcAppEventAppExit) {
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::Exit;
|
event.type = LfRfidApp::EventType::Exit;
|
||||||
@@ -80,16 +83,19 @@ void LfRfidApp::run(void* _args) {
|
|||||||
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
||||||
rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
|
rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
|
||||||
rpc_system_app_send_started(rpc_ctx);
|
rpc_system_app_send_started(rpc_ctx);
|
||||||
|
view_controller.attach_to_gui(ViewDispatcherTypeDesktop);
|
||||||
scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
|
scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
|
||||||
scene_controller.process(100, SceneType::Rpc);
|
scene_controller.process(100, SceneType::Rpc);
|
||||||
} else {
|
} else {
|
||||||
string_set_str(file_path, args);
|
string_set_str(file_path, args);
|
||||||
load_key_data(file_path, &worker.key, true);
|
load_key_data(file_path, &worker.key, true);
|
||||||
|
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||||
scene_controller.process(100, SceneType::Emulate);
|
scene_controller.process(100, SceneType::Emulate);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||||
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
||||||
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
||||||
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
|
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
|
||||||
|
|||||||
@@ -101,5 +101,4 @@ public:
|
|||||||
bool save_key_data(string_t path, RfidKey* key);
|
bool save_key_data(string_t path, RfidKey* key);
|
||||||
|
|
||||||
void make_app_folder();
|
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 */) {
|
void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||||
auto popup = app->view_controller.get<PopupVM>();
|
auto popup = app->view_controller.get<PopupVM>();
|
||||||
|
|
||||||
popup->set_header("LF RFID", 89, 30, AlignCenter, AlignTop);
|
popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom);
|
||||||
popup->set_text("RPC mode", 89, 43, AlignCenter, AlignTop);
|
popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61);
|
||||||
|
|
||||||
app->view_controller.switch_to<PopupVM>();
|
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);
|
app->view_controller.send_event(&view_event);
|
||||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
} else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
|
} 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;
|
consumed = true;
|
||||||
LfRfidApp::Event view_event;
|
LfRfidApp::Event view_event;
|
||||||
view_event.type = LfRfidApp::EventType::Back;
|
view_event.type = LfRfidApp::EventType::Back;
|
||||||
app->view_controller.send_event(&view_event);
|
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) {
|
} else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
|
||||||
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||||
|
consumed = true;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if(arg) {
|
if(arg && !emulating) {
|
||||||
string_set_str(app->file_path, arg);
|
string_set_str(app->file_path, arg);
|
||||||
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
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();
|
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;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||||||
case RfidWorker::WriteResult::NotWritable:
|
case RfidWorker::WriteResult::NotWritable:
|
||||||
if(!card_not_supported) {
|
if(!card_not_supported) {
|
||||||
auto popup = app->view_controller.get<PopupVM>();
|
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_header("Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||||
popup->set_text(
|
popup->set_text(
|
||||||
"Make sure this\ncard is writable\nand not\nprotected.",
|
"Make sure this\ncard is writable\nand not\nprotected.",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ LfRfidDebugApp::~LfRfidDebugApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LfRfidDebugApp::run() {
|
void LfRfidDebugApp::run() {
|
||||||
|
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||||
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
|
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
|
||||||
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
|
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
|
||||||
scene_controller.process(100);
|
scene_controller.process(100);
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ App(
|
|||||||
entry_point="loader_srv",
|
entry_point="loader_srv",
|
||||||
cdefines=["SRV_LOADER"],
|
cdefines=["SRV_LOADER"],
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=2 * 1024,
|
||||||
order=90,
|
order=90,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -503,9 +503,9 @@ int32_t loader_srv(void* p) {
|
|||||||
|
|
||||||
furi_record_create(RECORD_LOADER, loader_instance);
|
furi_record_create(RECORD_LOADER, loader_instance);
|
||||||
|
|
||||||
#ifdef LOADER_AUTOSTART
|
if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) {
|
||||||
loader_start(loader_instance, LOADER_AUTOSTART, NULL);
|
loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
uint32_t flags =
|
uint32_t flags =
|
||||||
|
|||||||
@@ -240,10 +240,10 @@ int32_t mousejacker_app(void* p) {
|
|||||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
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);
|
storage_common_mkdir(storage, MOUSEJACKER_APP_PATH_FOLDER);
|
||||||
Stream* file_stream = file_stream_alloc(storage);
|
Stream* file_stream = file_stream_alloc(storage);
|
||||||
|
|
||||||
@@ -329,8 +329,8 @@ int32_t mousejacker_app(void* p) {
|
|||||||
furi_hal_spi_release(nrf24_HANDLE);
|
furi_hal_spi_release(nrf24_HANDLE);
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
furi_record_close("storage");
|
furi_record_close(RECORD_STORAGE);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MusicPlayerModel* model;
|
MusicPlayerModel* model;
|
||||||
FuriMutex* model_mutex;
|
FuriMutex** model_mutex;
|
||||||
|
|
||||||
FuriMessageQueue* input_queue;
|
FuriMessageQueue* input_queue;
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ MusicPlayer* music_player_alloc() {
|
|||||||
instance->model = malloc(sizeof(MusicPlayerModel));
|
instance->model = malloc(sizeof(MusicPlayerModel));
|
||||||
memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE);
|
||||||
memset(instance->model->semitone_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);
|
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_stop();
|
||||||
furi_hal_speaker_start(frequency, volume);
|
furi_hal_speaker_start(frequency, volume);
|
||||||
while(instance->should_work && furi_get_tick() < next_tick) {
|
while(instance->should_work && furi_get_tick() < next_tick) {
|
||||||
volume *= 1.0000000;
|
volume *= 0.9945679;
|
||||||
furi_hal_speaker_set_volume(volume);
|
furi_hal_speaker_set_volume(volume);
|
||||||
furi_delay_ms(2);
|
furi_delay_ms(2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
|||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
|
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) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
@@ -87,11 +89,6 @@ Nfc* nfc_alloc() {
|
|||||||
nfc->widget = widget_alloc();
|
nfc->widget = widget_alloc();
|
||||||
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget));
|
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
|
// Mifare Classic Dict Attack
|
||||||
nfc->dict_attack = dict_attack_alloc();
|
nfc->dict_attack = dict_attack_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@@ -157,10 +154,6 @@ void nfc_free(Nfc* nfc) {
|
|||||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
|
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
widget_free(nfc->widget);
|
widget_free(nfc->widget);
|
||||||
|
|
||||||
// Bank Card
|
|
||||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard);
|
|
||||||
bank_card_free(nfc->bank_card);
|
|
||||||
|
|
||||||
// Mifare Classic Dict Attack
|
// Mifare Classic Dict Attack
|
||||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack);
|
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack);
|
||||||
dict_attack_free(nfc->dict_attack);
|
dict_attack_free(nfc->dict_attack);
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
#include <lib/nfc/nfc_worker.h>
|
#include <lib/nfc/nfc_worker.h>
|
||||||
#include <lib/nfc/nfc_device.h>
|
#include <lib/nfc/nfc_device.h>
|
||||||
#include <lib/nfc/helpers/mf_classic_dict.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 "views/dict_attack.h"
|
||||||
|
|
||||||
#include <nfc/scenes/nfc_scene.h>
|
#include <nfc/scenes/nfc_scene.h>
|
||||||
@@ -70,7 +70,6 @@ struct Nfc {
|
|||||||
ByteInput* byte_input;
|
ByteInput* byte_input;
|
||||||
TextBox* text_box;
|
TextBox* text_box;
|
||||||
Widget* widget;
|
Widget* widget;
|
||||||
BankCard* bank_card;
|
|
||||||
DictAttack* dict_attack;
|
DictAttack* dict_attack;
|
||||||
|
|
||||||
const NfcGenerator* generator;
|
const NfcGenerator* generator;
|
||||||
@@ -85,7 +84,6 @@ typedef enum {
|
|||||||
NfcViewByteInput,
|
NfcViewByteInput,
|
||||||
NfcViewTextBox,
|
NfcViewTextBox,
|
||||||
NfcViewWidget,
|
NfcViewWidget,
|
||||||
NfcViewBankCard,
|
|
||||||
NfcViewDictAttack,
|
NfcViewDictAttack,
|
||||||
} NfcView;
|
} NfcView;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ ADD_SCENE(nfc, save_name, SaveName)
|
|||||||
ADD_SCENE(nfc, save_success, SaveSuccess)
|
ADD_SCENE(nfc, save_success, SaveSuccess)
|
||||||
ADD_SCENE(nfc, file_select, FileSelect)
|
ADD_SCENE(nfc, file_select, FileSelect)
|
||||||
ADD_SCENE(nfc, emulate_uid, EmulateUid)
|
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_read_success, MfUltralightReadSuccess)
|
||||||
|
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
|
||||||
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
|
||||||
ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate)
|
ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate)
|
||||||
ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth)
|
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_data, MfDesfireData)
|
||||||
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
|
||||||
ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess)
|
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_menu, MfClassicMenu)
|
||||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||||
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
||||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||||
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
||||||
|
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
||||||
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
||||||
ADD_SCENE(nfc, device_info, DeviceInfo)
|
ADD_SCENE(nfc, device_info, DeviceInfo)
|
||||||
ADD_SCENE(nfc, delete, Delete)
|
ADD_SCENE(nfc, delete, Delete)
|
||||||
@@ -45,3 +48,4 @@ ADD_SCENE(nfc, rpc, Rpc)
|
|||||||
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
||||||
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
||||||
ADD_SCENE(nfc, detect_reader, DetectReader)
|
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) {
|
void nfc_scene_delete_on_enter(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||||
|
|
||||||
// Setup Custom Widget view
|
// Setup Custom Widget view
|
||||||
char temp_str[64];
|
string_t temp_str;
|
||||||
snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name);
|
string_init(temp_str);
|
||||||
|
|
||||||
|
string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name);
|
||||||
widget_add_text_box_element(
|
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(
|
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(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
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;
|
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
||||||
if(protocol == NfcDeviceProtocolEMV) {
|
if(protocol == NfcDeviceProtocolEMV) {
|
||||||
protocol_name = nfc_guess_protocol(protocol);
|
string_set_str(temp_str, "EMV bank card");
|
||||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
} 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(
|
||||||
widget_add_string_element(
|
nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str));
|
||||||
nfc->widget, 10, 33, AlignLeft, AlignTop, FontSecondary, protocol_name);
|
widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A");
|
||||||
}
|
string_clear(temp_str);
|
||||||
// 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);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == GuiButtonTypeLeft) {
|
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) {
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
if(nfc_device_delete(nfc->dev, true)) {
|
if(nfc_device_delete(nfc->dev, true)) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneStart);
|
nfc->scene_manager, NfcSceneFileSelect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
#include "../nfc_i.h"
|
#include "../nfc_i.h"
|
||||||
#include "../helpers/nfc_emv_parser.h"
|
#include "../helpers/nfc_emv_parser.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
NfcSceneDeviceInfoUid,
|
|
||||||
NfcSceneDeviceInfoData,
|
|
||||||
};
|
|
||||||
|
|
||||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
if(type == InputTypeShort) {
|
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) {
|
void nfc_scene_device_info_on_enter(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||||
|
|
||||||
bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) ||
|
string_t temp_str;
|
||||||
(nfc->dev->format == NfcDeviceSaveFormatMifareUl) ||
|
string_init(temp_str);
|
||||||
(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);
|
|
||||||
|
|
||||||
const char* protocol_name = NULL;
|
if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||||
NfcProtocol protocol = nfc->dev->dev_data.protocol;
|
EmvData* emv_data = &dev_data->emv_data;
|
||||||
if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) {
|
string_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||||
protocol_name = nfc_guess_protocol(protocol);
|
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
||||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
string_strim(temp_str);
|
||||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
|
||||||
MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data;
|
// Add expiration date
|
||||||
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);
|
|
||||||
if(emv_data->exp_mon) {
|
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;
|
// Parse currency code
|
||||||
string_init(display_str);
|
if((emv_data->currency_code)) {
|
||||||
if(emv_data->country_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_t country_name;
|
||||||
string_init(country_name);
|
string_init(country_name);
|
||||||
if(nfc_emv_parser_get_country_name(
|
if(nfc_emv_parser_get_country_name(
|
||||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||||
string_printf(display_str, "Reg:%s", string_get_cstr(country_name));
|
string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name));
|
||||||
bank_card_set_country_name(bank_card, string_get_cstr(display_str));
|
|
||||||
}
|
}
|
||||||
string_clear(country_name);
|
string_clear(country_name);
|
||||||
}
|
}
|
||||||
if(emv_data->currency_code) {
|
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||||
string_t currency_name;
|
string_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo);
|
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
|
if(event.event == GuiButtonTypeRight) {
|
||||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||||
} 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);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,12 +78,4 @@ void nfc_scene_device_info_on_exit(void* context) {
|
|||||||
|
|
||||||
// Clear views
|
// Clear views
|
||||||
widget_reset(nfc->widget);
|
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) {
|
void nfc_scene_emv_read_success_on_enter(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
EmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
|
||||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||||
|
|
||||||
// Setup Custom Widget view
|
// Setup Custom Widget view
|
||||||
// Add frame
|
|
||||||
widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6);
|
|
||||||
// Add buttons
|
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc);
|
||||||
// Add card name
|
|
||||||
widget_add_string_element(
|
string_t temp_str;
|
||||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name);
|
string_init_printf(temp_str, "\e#%s\n", emv_data->name);
|
||||||
// Add card number
|
|
||||||
string_t pan_str;
|
|
||||||
string_init(pan_str);
|
|
||||||
for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
|
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);
|
string_strim(temp_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);
|
|
||||||
// Add expiration date
|
// Add expiration date
|
||||||
if(emv_data->exp_mon) {
|
if(emv_data->exp_mon) {
|
||||||
char exp_str[16];
|
string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
// 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);
|
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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == GuiButtonTypeRight) {
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
// Clear device name
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvMenu);
|
||||||
nfc_device_set_name(nfc->dev, "");
|
|
||||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ void nfc_scene_file_select_on_enter(void* context) {
|
|||||||
// Process file_select return
|
// Process file_select return
|
||||||
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
|
||||||
if(nfc_file_select(nfc->dev)) {
|
if(nfc_file_select(nfc->dev)) {
|
||||||
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
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_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
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);
|
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) {
|
} else if(event.event == SubmenuIndexInfo) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo);
|
nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||||
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
MfClassicData* mf_data = &dev_data->mf_classic_data;
|
||||||
string_t str_tmp;
|
|
||||||
string_init(str_tmp);
|
|
||||||
|
|
||||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||||
|
|
||||||
@@ -29,48 +27,27 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
|
|||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc);
|
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)) {
|
if(string_size(nfc->dev->dev_data.parsed_data)) {
|
||||||
widget_add_text_box_element(
|
string_init_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||||
nfc->widget,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
128,
|
|
||||||
32,
|
|
||||||
AlignLeft,
|
|
||||||
AlignTop,
|
|
||||||
string_get_cstr(nfc->dev->dev_data.parsed_data),
|
|
||||||
true);
|
|
||||||
} else {
|
} else {
|
||||||
widget_add_string_element(
|
string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type));
|
||||||
widget,
|
string_cat_printf(temp_str, "UID:");
|
||||||
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++) {
|
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 sectors_total = mf_classic_get_total_sectors_num(mf_data->type);
|
||||||
uint8_t keys_total = sectors_total * 2;
|
uint8_t keys_total = sectors_total * 2;
|
||||||
uint8_t keys_found = 0;
|
uint8_t keys_found = 0;
|
||||||
uint8_t sectors_read = 0;
|
uint8_t sectors_read = 0;
|
||||||
mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found);
|
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);
|
string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total);
|
||||||
widget_add_string_element(
|
string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total);
|
||||||
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_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);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
enum SubmenuIndex {
|
enum SubmenuIndex {
|
||||||
SubmenuIndexSave,
|
SubmenuIndexSave,
|
||||||
|
SubmenuIndexEmulateUid,
|
||||||
|
SubmenuIndexInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) {
|
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_add_item(
|
||||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc);
|
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(
|
submenu_set_selected_item(
|
||||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu));
|
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, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||||
consumed = true;
|
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 "../nfc_i.h"
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
|
void nfc_scene_mf_desfire_read_success_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
enum {
|
InputType type,
|
||||||
MfDesfireReadSuccessStateShowUID,
|
void* context) {
|
||||||
MfDesfireReadSuccessStateShowData,
|
|
||||||
};
|
|
||||||
|
|
||||||
void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) {
|
|
||||||
Nfc* nfc = 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) {
|
void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||||
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
|
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
|
||||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
Widget* widget = nfc->widget;
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
|
||||||
dialog_ex_set_center_button_text(dialog_ex, "Data");
|
// Prepare string for data display
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
string_t temp_str;
|
||||||
dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21);
|
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_apps = 0;
|
||||||
uint16_t n_files = 0;
|
uint16_t n_files = 0;
|
||||||
|
|
||||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||||
n_apps++;
|
n_apps++;
|
||||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||||
n_files++;
|
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
|
// Add text scroll element
|
||||||
nfc_text_store_set(
|
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
|
||||||
nfc,
|
string_clear(temp_str);
|
||||||
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);
|
|
||||||
|
|
||||||
scene_manager_set_scene_state(
|
// Add button elements
|
||||||
nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID);
|
widget_add_button_element(
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
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) {
|
bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
uint32_t state =
|
|
||||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess);
|
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) {
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) {
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData);
|
|
||||||
consumed = true;
|
|
||||||
} else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) {
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
if(state == MfDesfireReadSuccessStateShowData) {
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
consumed = true;
|
||||||
scene_manager_set_scene_state(
|
|
||||||
nfc->scene_manager,
|
|
||||||
NfcSceneMfDesfireReadSuccess,
|
|
||||||
MfDesfireReadSuccessStateShowUID);
|
|
||||||
consumed = true;
|
|
||||||
} else {
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
@@ -94,5 +89,5 @@ void nfc_scene_mf_desfire_read_success_on_exit(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
// Clean dialog
|
// 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,
|
SubmenuIndexUnlock,
|
||||||
SubmenuIndexSave,
|
SubmenuIndexSave,
|
||||||
SubmenuIndexEmulate,
|
SubmenuIndexEmulate,
|
||||||
|
SubmenuIndexInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) {
|
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,
|
SubmenuIndexEmulate,
|
||||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||||
|
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu));
|
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) {
|
} else if(event.event == SubmenuIndexUnlock) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||||
consumed = true;
|
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);
|
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,
|
22,
|
||||||
AlignLeft,
|
AlignLeft,
|
||||||
AlignTop);
|
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);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth, state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
#include "../nfc_i.h"
|
#include "../nfc_i.h"
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
enum {
|
|
||||||
ReadMifareUlStateShowInfo,
|
|
||||||
ReadMifareUlStateShowData,
|
|
||||||
};
|
|
||||||
|
|
||||||
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
void nfc_scene_mf_ultralight_read_success_widget_callback(
|
||||||
GuiButtonType result,
|
GuiButtonType result,
|
||||||
InputType type,
|
InputType type,
|
||||||
@@ -31,12 +26,6 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
|
|||||||
"Retry",
|
"Retry",
|
||||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
nfc_scene_mf_ultralight_read_success_widget_callback,
|
||||||
nfc);
|
nfc);
|
||||||
widget_add_button_element(
|
|
||||||
widget,
|
|
||||||
GuiButtonTypeCenter,
|
|
||||||
"Data",
|
|
||||||
nfc_scene_mf_ultralight_read_success_widget_callback,
|
|
||||||
nfc);
|
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget,
|
widget,
|
||||||
GuiButtonTypeRight,
|
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_scene_mf_ultralight_read_success_widget_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
|
||||||
widget_add_string_element(
|
string_t temp_str;
|
||||||
widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true));
|
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
|
||||||
string_t data_str;
|
string_cat_printf(temp_str, "UID:");
|
||||||
string_init_printf(data_str, "UID:");
|
|
||||||
for(size_t i = 0; i < data->uid_len; i++) {
|
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(
|
string_cat_printf(
|
||||||
widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str));
|
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
|
||||||
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));
|
|
||||||
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
if(mf_ul_data->data_read != mf_ul_data->data_size) {
|
||||||
widget_add_string_element(
|
string_cat_printf(temp_str, "\nPassword-protected pages!");
|
||||||
widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-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);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) {
|
bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
uint32_t state =
|
|
||||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) {
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) {
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
|
||||||
consumed = true;
|
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) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
if(state == ReadMifareUlStateShowData) {
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
consumed = true;
|
||||||
scene_manager_set_scene_state(
|
|
||||||
nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo);
|
|
||||||
consumed = true;
|
|
||||||
} else {
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
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) {
|
void nfc_scene_mf_ultralight_read_success_on_exit(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
// Clean views
|
// Clean view
|
||||||
widget_reset(nfc->widget);
|
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_header(dialog_ex, "Risky function!", 64, 4, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "Wrong password\ncan block your\ncard.", 4, 18, AlignLeft, AlignTop);
|
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");
|
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if((event.event == NfcWorkerEventReadUidNfcB) ||
|
if((event.event == NfcWorkerEventReadUidNfcB) ||
|
||||||
(event.event == NfcWorkerEventReadUidNfcF) ||
|
(event.event == NfcWorkerEventReadUidNfcF) ||
|
||||||
(event.event == NfcWorkerEventReadUidNfcV) ||
|
(event.event == NfcWorkerEventReadUidNfcV)) {
|
||||||
(event.event == NfcWorkerEventReadUidNfcA)) {
|
|
||||||
notification_message(nfc->notifications, &sequence_success);
|
notification_message(nfc->notifications, &sequence_success);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
|
||||||
consumed = true;
|
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) {
|
} else if(event.event == NfcWorkerEventReadMfUltralight) {
|
||||||
notification_message(nfc->notifications, &sequence_success);
|
notification_message(nfc->notifications, &sequence_success);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess);
|
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) {
|
void nfc_scene_read_card_success_on_enter(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
string_t data_str;
|
string_t temp_str;
|
||||||
string_t uid_str;
|
string_init(temp_str);
|
||||||
string_init(data_str);
|
|
||||||
string_init(uid_str);
|
|
||||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
|
||||||
Widget* widget = nfc->widget;
|
Widget* widget = nfc->widget;
|
||||||
string_set_str(data_str, nfc_get_dev_type(data->type));
|
string_set_str(temp_str, nfc_get_dev_type(data->type));
|
||||||
string_set_str(uid_str, "UID:");
|
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++) {
|
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_add_button_element(
|
||||||
widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc);
|
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(temp_str);
|
||||||
string_clear(uid_str);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == GuiButtonTypeLeft) {
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
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;
|
return consumed;
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ void nfc_scene_rpc_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
Popup* popup = nfc->popup;
|
Popup* popup = nfc->popup;
|
||||||
|
|
||||||
popup_set_header(popup, "NFC", 82, 28, AlignCenter, AlignBottom);
|
popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
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);
|
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;
|
consumed = true;
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
|
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
scene_manager_stop(nfc->scene_manager);
|
||||||
view_dispatcher_stop(nfc->view_dispatcher);
|
view_dispatcher_stop(nfc->view_dispatcher);
|
||||||
nfc_blink_stop(nfc);
|
|
||||||
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
||||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
scene_manager_stop(nfc->scene_manager);
|
||||||
nfc->rpc_ctx = NULL;
|
|
||||||
view_dispatcher_stop(nfc->view_dispatcher);
|
view_dispatcher_stop(nfc->view_dispatcher);
|
||||||
nfc_blink_stop(nfc);
|
|
||||||
} else if(event.event == NfcCustomEventRpcLoad) {
|
} else if(event.event == NfcCustomEventRpcLoad) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const char* arg = rpc_system_app_get_data(nfc->rpc_ctx);
|
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_blink_start(nfc);
|
||||||
nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
|
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_add_item(
|
||||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
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) {
|
if(nfc->dev->shadow_file_exist) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
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, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
|
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);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
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);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexInfo) {
|
} 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;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm);
|
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;
|
const char* path = request->content.storage_read_request.path;
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
File* file = storage_file_alloc(fs_api);
|
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);
|
size_t size_left = storage_file_size(file);
|
||||||
do {
|
do {
|
||||||
response->command_id = request->command_id;
|
response->command_id = request->command_id;
|
||||||
response->which_content = PB_Main_storage_read_response_tag;
|
response->which_content = PB_Main_storage_read_response_tag;
|
||||||
response->command_status = PB_CommandStatus_OK;
|
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);
|
size_t read_size = MIN(size_left, MAX_DATA_SIZE);
|
||||||
*read_size_msg = storage_file_read(file, buffer, read_size);
|
if(read_size) {
|
||||||
size_left -= read_size;
|
response->content.storage_read_response.has_file = true;
|
||||||
result = (*read_size_msg == read_size);
|
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) {
|
*read_size_msg = storage_file_read(file, buffer, read_size);
|
||||||
response->has_next = (size_left > 0);
|
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);
|
rpc_send_and_release(session, response);
|
||||||
}
|
}
|
||||||
} while((size_left != 0) && result);
|
} while((size_left != 0) && fs_operation_success);
|
||||||
|
}
|
||||||
|
|
||||||
if(!result) {
|
if(!fs_operation_success) {
|
||||||
rpc_send_and_release_empty(
|
|
||||||
session, request->command_id, rpc_system_storage_get_file_error(file));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rpc_send_and_release_empty(
|
rpc_send_and_release_empty(
|
||||||
session, request->command_id, rpc_system_storage_get_file_error(file));
|
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;
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
bool result = true;
|
bool fs_operation_success = true;
|
||||||
|
|
||||||
if(!path_contains_only_ascii(request->content.storage_write_request.path)) {
|
if(!path_contains_only_ascii(request->content.storage_write_request.path)) {
|
||||||
rpc_storage->current_command_id = request->command_id;
|
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->current_command_id = request->command_id;
|
||||||
rpc_storage->state = RpcStorageStateWriting;
|
rpc_storage->state = RpcStorageStateWriting;
|
||||||
const char* path = request->content.storage_write_request.path;
|
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;
|
File* file = rpc_storage->file;
|
||||||
|
bool send_response = false;
|
||||||
|
|
||||||
if(result) {
|
if(fs_operation_success) {
|
||||||
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
|
if(request->content.storage_write_request.has_file &&
|
||||||
size_t buffer_size = request->content.storage_write_request.file.data->size;
|
request->content.storage_write_request.file.data &&
|
||||||
|
request->content.storage_write_request.file.data->size) {
|
||||||
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
|
||||||
result = (written_size == buffer_size);
|
size_t buffer_size = request->content.storage_write_request.file.data->size;
|
||||||
|
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
|
||||||
if(result && !request->has_next) {
|
fs_operation_success = (written_size == buffer_size);
|
||||||
rpc_send_and_release_empty(
|
|
||||||
session, rpc_storage->current_command_id, PB_CommandStatus_OK);
|
|
||||||
rpc_system_storage_reset_state(rpc_storage, session, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send_response = !request->has_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!result) {
|
PB_CommandStatus command_status = PB_CommandStatus_OK;
|
||||||
rpc_send_and_release_empty(
|
if(!fs_operation_success) {
|
||||||
session, rpc_storage->current_command_id, rpc_system_storage_get_file_error(file));
|
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);
|
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);
|
view_port_input_callback_set(view_port, sentry_safe_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
Event event;
|
Event event;
|
||||||
@@ -156,7 +156,7 @@ int32_t sentry_safe_app(void* p) {
|
|||||||
|
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
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);
|
view_port_input_callback_set(instance->view_port, spectrum_analyzer_input_callback, instance);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
@@ -378,7 +378,7 @@ SpectrumAnalyzer* spectrum_analyzer_alloc() {
|
|||||||
void spectrum_analyzer_free(SpectrumAnalyzer* instance) {
|
void spectrum_analyzer_free(SpectrumAnalyzer* instance) {
|
||||||
// view_port_enabled_set(view_port, false);
|
// view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(instance->gui, instance->view_port);
|
gui_remove_view_port(instance->gui, instance->view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(instance->view_port);
|
view_port_free(instance->view_port);
|
||||||
|
|
||||||
spectrum_analyzer_worker_free(instance->worker);
|
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) {
|
if(parsed_count == EOF || parsed_count != 1) {
|
||||||
storage_cli_print_usage();
|
storage_cli_print_usage();
|
||||||
} else if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
} 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);
|
uint64_t file_size = storage_file_size(file);
|
||||||
|
|
||||||
printf("Size: %lu\r\n", (uint32_t)file_size);
|
printf("Size: %lu\r\n", (uint32_t)file_size);
|
||||||
|
|
||||||
while(file_size > 0) {
|
if(buffer_size) {
|
||||||
printf("\r\nReady?\r\n");
|
uint8_t* data = malloc(buffer_size);
|
||||||
cli_getc(cli);
|
while(file_size > 0) {
|
||||||
|
printf("\r\nReady?\r\n");
|
||||||
|
cli_getc(cli);
|
||||||
|
|
||||||
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
||||||
for(uint16_t i = 0; i < read_size; i++) {
|
for(uint16_t i = 0; i < read_size; i++) {
|
||||||
putchar(data[i]);
|
putchar(data[i]);
|
||||||
|
}
|
||||||
|
file_size -= read_size;
|
||||||
}
|
}
|
||||||
file_size -= read_size;
|
free(data);
|
||||||
}
|
}
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
|
|
||||||
free(data);
|
|
||||||
} else {
|
} else {
|
||||||
storage_cli_print_error(storage_file_get_error(file));
|
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)) {
|
if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||||
printf("Ready\r\n");
|
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++) {
|
for(uint32_t i = 0; i < buffer_size; i++) {
|
||||||
buffer[i] = cli_getc(cli);
|
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 {
|
} else {
|
||||||
storage_cli_print_error(storage_file_get_error(file));
|
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);
|
view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx);
|
||||||
|
|
||||||
if(sd_status != FSE_OK) {
|
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_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
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);
|
FS_Error sd_status = storage_sd_status(app->fs_api);
|
||||||
|
|
||||||
if(sd_status == FSE_NOT_READY) {
|
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_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
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_set_text(
|
||||||
dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter);
|
dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter);
|
||||||
} else {
|
} 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_header(dialog_ex, "Format\ncomplete!", 14, 15, AlignLeft, AlignTop);
|
||||||
}
|
}
|
||||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
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);
|
dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_sd_info_dialog_callback);
|
||||||
|
|
||||||
if(sd_status != FSE_OK) {
|
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_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
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);
|
FS_Error sd_status = storage_sd_status(app->fs_api);
|
||||||
|
|
||||||
if(sd_status == FSE_NOT_READY) {
|
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_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
|
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;
|
DialogEx* dialog_ex = app->dialog_ex;
|
||||||
|
|
||||||
dialog_ex_set_center_button_text(dialog_ex, "OK");
|
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) {
|
if(error == FSE_OK) {
|
||||||
dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop);
|
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;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
widget_add_string_multiline_element(
|
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(
|
widget_add_string_multiline_element(
|
||||||
subghz->widget,
|
subghz->widget,
|
||||||
64,
|
64,
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
|
|||||||
subghz_setting_get_preset_data_size(subghz->setting, index));
|
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);
|
SubGhz* subghz = variable_item_get_context(item);
|
||||||
uint8_t index = variable_item_get_current_value_index(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,
|
subghz->variable_item_list,
|
||||||
"Hopping:",
|
"Hopping:",
|
||||||
HOPPING_COUNT,
|
HOPPING_COUNT,
|
||||||
subghz_scene_receiver_config_set_hopping_runing,
|
subghz_scene_receiver_config_set_hopping_running,
|
||||||
subghz);
|
subghz);
|
||||||
value_index = subghz_scene_receiver_config_hopper_value_index(
|
value_index = subghz_scene_receiver_config_hopper_value_index(
|
||||||
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
|
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
|
|||||||
subghz);
|
subghz);
|
||||||
}
|
}
|
||||||
} else {
|
} 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(
|
widget_add_string_element(
|
||||||
subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse.");
|
subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubGhzRpcStateIdle,
|
||||||
|
SubGhzRpcStateLoaded,
|
||||||
|
} SubGhzRpcState;
|
||||||
|
|
||||||
void subghz_scene_rpc_on_enter(void* context) {
|
void subghz_scene_rpc_on_enter(void* context) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
Popup* popup = subghz->popup;
|
Popup* popup = subghz->popup;
|
||||||
|
|
||||||
popup_set_header(popup, "Sub-GHz", 82, 28, AlignCenter, AlignBottom);
|
popup_set_header(popup, "Sub-GHz", 89, 42, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop);
|
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);
|
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);
|
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;
|
SubGhz* subghz = context;
|
||||||
Popup* popup = subghz->popup;
|
Popup* popup = subghz->popup;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc);
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == SubGhzCustomEventSceneExit) {
|
if(event.event == SubGhzCustomEventSceneExit) {
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
scene_manager_stop(subghz->scene_manager);
|
||||||
subghz_tx_stop(subghz);
|
|
||||||
subghz_sleep(subghz);
|
|
||||||
}
|
|
||||||
view_dispatcher_stop(subghz->view_dispatcher);
|
view_dispatcher_stop(subghz->view_dispatcher);
|
||||||
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true);
|
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
} else if(event.event == SubGhzCustomEventSceneRpcSessionClose) {
|
} else if(event.event == SubGhzCustomEventSceneRpcSessionClose) {
|
||||||
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
scene_manager_stop(subghz->scene_manager);
|
||||||
subghz->rpc_ctx = NULL;
|
view_dispatcher_stop(subghz->view_dispatcher);
|
||||||
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);
|
|
||||||
} else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
|
} else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
|
if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) &&
|
||||||
|
(state == SubGhzRpcStateLoaded)) {
|
||||||
subghz_blink_start(subghz);
|
subghz_blink_start(subghz);
|
||||||
result = subghz_tx_start(subghz, subghz->txrx->fff_data);
|
result = subghz_tx_start(subghz, subghz->txrx->fff_data);
|
||||||
result = true;
|
result = true;
|
||||||
@@ -57,8 +57,10 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
|
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const char* arg = rpc_system_app_get_data(subghz->rpc_ctx);
|
const char* arg = rpc_system_app_get_data(subghz->rpc_ctx);
|
||||||
if(arg) {
|
if(arg && (state == SubGhzRpcStateIdle)) {
|
||||||
if(subghz_key_load(subghz, arg, false)) {
|
if(subghz_key_load(subghz, arg, false)) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded);
|
||||||
string_set_str(subghz->file_path, arg);
|
string_set_str(subghz->file_path, arg);
|
||||||
result = true;
|
result = true;
|
||||||
string_t file_name;
|
string_t file_name;
|
||||||
@@ -70,7 +72,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
SUBGHZ_MAX_LEN_NAME,
|
SUBGHZ_MAX_LEN_NAME,
|
||||||
"loaded\n%s",
|
"loaded\n%s",
|
||||||
string_get_cstr(file_name));
|
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);
|
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) {
|
void subghz_scene_rpc_on_exit(void* context) {
|
||||||
SubGhz* subghz = 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* popup = subghz->popup;
|
||||||
|
|
||||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
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
|
// Setup view
|
||||||
Popup* popup = subghz->popup;
|
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_header(popup, string_get_cstr(subghz->error_str), 14, 15, AlignLeft, AlignTop);
|
||||||
popup_set_timeout(popup, 1500);
|
popup_set_timeout(popup, 1500);
|
||||||
popup_set_context(popup, subghz);
|
popup_set_context(popup, subghz);
|
||||||
|
|||||||
@@ -11,9 +11,14 @@ void subghz_scene_show_only_rx_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
Popup* popup = subghz->popup;
|
Popup* popup = subghz->popup;
|
||||||
popup_set_icon(popup, 67, 12, &I_DolphinFirstStart7_61x51);
|
|
||||||
popup_set_text(
|
const char* header_text = "Transmission is blocked";
|
||||||
popup, "This frequency is\noutside of default\nrange", 38, 40, AlignCenter, AlignBottom);
|
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_timeout(popup, 1500);
|
||||||
popup_set_context(popup, subghz);
|
popup_set_context(popup, subghz);
|
||||||
popup_set_callback(popup, subghz_scene_show_only_rx_popup_callback);
|
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) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose);
|
subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose);
|
||||||
|
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
||||||
|
subghz->rpc_ctx = NULL;
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
|
|||||||
@@ -219,17 +219,13 @@ void subghz_dialog_message_show_only_rx(SubGhz* subghz) {
|
|||||||
DialogsApp* dialogs = subghz->dialogs;
|
DialogsApp* dialogs = subghz->dialogs;
|
||||||
DialogMessage* message = dialog_message_alloc();
|
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(
|
dialog_message_set_header(message, header_text, 63, 3, AlignCenter, AlignTop);
|
||||||
message,
|
dialog_message_set_text(message, message_text, 0, 17, AlignLeft, AlignTop);
|
||||||
"Frequency\nis outside of\ndefault range.\nCheck docs.",
|
|
||||||
3,
|
|
||||||
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_show(dialogs, message);
|
||||||
dialog_message_free(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")) {
|
if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
|
||||||
//Todo add Custom_preset_module
|
//Todo add Custom_preset_module
|
||||||
//delete peset if it already exists
|
//delete preset if it already exists
|
||||||
subghz_setting_delete_custom_preset(
|
subghz_setting_delete_custom_preset(
|
||||||
subghz->setting, string_get_cstr(subghz->txrx->preset->name));
|
subghz->setting, string_get_cstr(subghz->txrx->preset->name));
|
||||||
//load custom preset from file
|
//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);
|
view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
tetris_state->timer =
|
tetris_state->timer =
|
||||||
@@ -460,7 +460,7 @@ int32_t tetris_game_app() {
|
|||||||
furi_timer_free(tetris_state->timer);
|
furi_timer_free(tetris_state->timer);
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
delete_mutex(&state_mutex);
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ int32_t tictactoe_game_app(void* p) {
|
|||||||
tictactoe_state_init(tictactoe_state);
|
tictactoe_state_init(tictactoe_state);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
GameEvent event;
|
GameEvent event;
|
||||||
@@ -373,7 +373,7 @@ int32_t tictactoe_game_app(void* p) {
|
|||||||
furi_timer_free(tictactoe_state->timer);
|
furi_timer_free(tictactoe_state->timer);
|
||||||
view_port_enabled_set(view_port, false);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
delete_mutex(&state_mutex);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "u2f_data.h"
|
#include "u2f_data.h"
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <furi_hal_random.h>
|
#include <furi_hal_random.h>
|
||||||
|
#include <littlefs/lfs_util.h> // for lfs_tobe32
|
||||||
|
|
||||||
#include "toolbox/sha256.h"
|
#include "toolbox/sha256.h"
|
||||||
#include "toolbox/hmac_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 flags = 0;
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
uint8_t signature[64];
|
uint8_t signature[64];
|
||||||
|
uint32_t be_u2f_counter;
|
||||||
|
|
||||||
if(u2f_data_check(false) == false) {
|
if(u2f_data_check(false) == false) {
|
||||||
U2F->ready = false;
|
U2F->ready = false;
|
||||||
@@ -275,11 +277,14 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
|||||||
}
|
}
|
||||||
U2F->user_present = false;
|
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
|
// Generate hash
|
||||||
sha256_start(&sha_ctx);
|
sha256_start(&sha_ctx);
|
||||||
sha256_update(&sha_ctx, req->app_id, 32);
|
sha256_update(&sha_ctx, req->app_id, 32);
|
||||||
sha256_update(&sha_ctx, &flags, 1);
|
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_update(&sha_ctx, req->challenge, 32);
|
||||||
sha256_finish(&sha_ctx, hash);
|
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);
|
uECC_sign(priv_key, hash, 32, signature, U2F->p_curve);
|
||||||
|
|
||||||
resp->user_present = flags;
|
resp->user_present = flags;
|
||||||
resp->counter = U2F->counter;
|
resp->counter = be_u2f_counter;
|
||||||
uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature);
|
uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature);
|
||||||
memcpy(resp->signature + signature_len, state_no_error, 2);
|
memcpy(resp->signature + signature_len, state_no_error, 2);
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Counter: %lu", U2F->counter);
|
|
||||||
U2F->counter++;
|
U2F->counter++;
|
||||||
|
FURI_LOG_D(TAG, "Counter: %lu", U2F->counter);
|
||||||
u2f_data_cnt_write(U2F->counter);
|
u2f_data_cnt_write(U2F->counter);
|
||||||
|
|
||||||
if(U2F->callback != NULL) U2F->callback(U2fNotifyAuthSuccess, U2F->context);
|
if(U2F->callback != NULL) U2F->callback(U2fNotifyAuthSuccess, U2F->context);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "u2f_hid.h"
|
#include "u2f_data.h"
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <furi_hal_random.h>
|
#include <furi_hal_random.h>
|
||||||
@@ -28,7 +28,8 @@
|
|||||||
#define U2F_DEVICE_KEY_VERSION 1
|
#define U2F_DEVICE_KEY_VERSION 1
|
||||||
|
|
||||||
#define U2F_COUNTER_FILE_TYPE "Flipper U2F Counter File"
|
#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
|
#define U2F_COUNTER_CONTROL_VAL 0xAA5500FF
|
||||||
|
|
||||||
@@ -359,6 +360,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) {
|
|||||||
furi_assert(cnt_val);
|
furi_assert(cnt_val);
|
||||||
|
|
||||||
bool state = false;
|
bool state = false;
|
||||||
|
bool old_counter = false;
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
U2fCounterData cnt;
|
U2fCounterData cnt;
|
||||||
uint8_t cnt_encr[48];
|
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");
|
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0 ||
|
if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) {
|
||||||
version != U2F_COUNTER_VERSION) {
|
FURI_LOG_E(TAG, "Type mismatch");
|
||||||
FURI_LOG_E(TAG, "Type or version 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;
|
break;
|
||||||
}
|
}
|
||||||
if(!flipper_format_read_hex(flipper_format, "IV", iv, 16)) {
|
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);
|
flipper_format_free(flipper_format);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
string_clear(filetype);
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
#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 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_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
|
#define TEST_TIMEOUT 10000
|
||||||
|
|
||||||
static SubGhzEnvironment* environment_handler;
|
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");
|
"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
|
//test encoders
|
||||||
MU_TEST(subghz_encoder_princeton_test) {
|
MU_TEST(subghz_encoder_princeton_test) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
@@ -501,6 +509,12 @@ MU_TEST(subghz_encoder_phoenix_v2_test) {
|
|||||||
"Test encoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
|
"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_TEST(subghz_random_test) {
|
||||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
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_bett_test);
|
||||||
MU_RUN_TEST(subghz_decoder_doitrand_test);
|
MU_RUN_TEST(subghz_decoder_doitrand_test);
|
||||||
MU_RUN_TEST(subghz_decoder_phoenix_v2_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_princeton_test);
|
||||||
MU_RUN_TEST(subghz_encoder_came_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_bett_test);
|
||||||
MU_RUN_TEST(subghz_encoder_doitrand_test);
|
MU_RUN_TEST(subghz_encoder_doitrand_test);
|
||||||
MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
|
MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
|
||||||
|
MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
|
||||||
|
|
||||||
MU_RUN_TEST(subghz_random_test);
|
MU_RUN_TEST(subghz_random_test);
|
||||||
subghz_test_deinit();
|
subghz_test_deinit();
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ static WavPlayerApp* app_alloc() {
|
|||||||
WavPlayerApp* app = malloc(sizeof(WavPlayerApp));
|
WavPlayerApp* app = malloc(sizeof(WavPlayerApp));
|
||||||
app->samples_count_half = 1024 * 4;
|
app->samples_count_half = 1024 * 4;
|
||||||
app->samples_count = app->samples_count_half * 2;
|
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->stream = file_stream_alloc(app->storage);
|
||||||
app->parser = wav_parser_alloc();
|
app->parser = wav_parser_alloc();
|
||||||
app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count);
|
app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count);
|
||||||
@@ -106,7 +106,7 @@ static WavPlayerApp* app_alloc() {
|
|||||||
app->volume = 10.0f;
|
app->volume = 10.0f;
|
||||||
app->play = true;
|
app->play = true;
|
||||||
|
|
||||||
app->gui = furi_record_open("gui");
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
app->view_dispatcher = view_dispatcher_alloc();
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
app->view = wav_player_view_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_remove_view(app->view_dispatcher, 0);
|
||||||
view_dispatcher_free(app->view_dispatcher);
|
view_dispatcher_free(app->view_dispatcher);
|
||||||
wav_player_view_free(app->view);
|
wav_player_view_free(app->view);
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
furi_message_queue_free(app->queue);
|
furi_message_queue_free(app->queue);
|
||||||
free(app->tmp_buffer);
|
free(app->tmp_buffer);
|
||||||
free(app->sample_buffer);
|
free(app->sample_buffer);
|
||||||
wav_parser_free(app->parser);
|
wav_parser_free(app->parser);
|
||||||
stream_free(app->stream);
|
stream_free(app->stream);
|
||||||
furi_record_close("storage");
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
notification_message(app->notification, &sequence_display_backlight_enforce_auto);
|
notification_message(app->notification, &sequence_display_backlight_enforce_auto);
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
@@ -296,11 +296,11 @@ int32_t wav_player_app(void* p) {
|
|||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
WavPlayerApp* app = app_alloc();
|
WavPlayerApp* app = app_alloc();
|
||||||
|
|
||||||
Storage* storage = furi_record_open("storage");
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
if(!storage_simply_mkdir(storage, WAVPLAYER_FOLDER)) {
|
if(!storage_simply_mkdir(storage, WAVPLAYER_FOLDER)) {
|
||||||
FURI_LOG_E(TAG, "Could not create folder %s", 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_run(app);
|
||||||
app_free(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;
|
app->text_box_store_strlen += len;
|
||||||
if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) {
|
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);
|
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
|
// 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) {
|
if(app->is_command) {
|
||||||
string_reset(app->text_box_store);
|
string_reset(app->text_box_store);
|
||||||
app->text_box_store_strlen = 0;
|
app->text_box_store_strlen = 0;
|
||||||
} else { // "View Log" menu action
|
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
|
||||||
text_box_set_text(app->text_box, string_get_cstr(app->text_box_store));
|
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);
|
scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0);
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput);
|
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput);
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +1,138 @@
|
|||||||
#include "../wifi_marauder_app_i.h"
|
#include "../wifi_marauder_app_i.h"
|
||||||
|
|
||||||
#define NUM_MENU_ITEMS (29)
|
|
||||||
|
|
||||||
// For each command, define whether additional arguments are needed
|
// For each command, define whether additional arguments are needed
|
||||||
// (enabling text input to fill them out), and whether the console
|
// (enabling text input to fill them out), and whether the console
|
||||||
// text box should focus at the start of the output or the end
|
// text box should focus at the start of the output or the end
|
||||||
#define INPUT_ARGS (true)
|
typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs;
|
||||||
#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;
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct WifiMarauderItem items[NUM_MENU_ITEMS] = {
|
typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole;
|
||||||
{"View Log (start)", NO_ARGS, FOCUS_CONSOLE_START},
|
|
||||||
{"View Log (end)", NO_ARGS, FOCUS_CONSOLE_END},
|
#define SHOW_STOPSCAN_TIP (true)
|
||||||
{"attack -t beacon -l", NO_ARGS, FOCUS_CONSOLE_END},
|
#define NO_TIP (false)
|
||||||
{"attack -t beacon -r", NO_ARGS, FOCUS_CONSOLE_END},
|
|
||||||
{"attack -t beacon -a", NO_ARGS, FOCUS_CONSOLE_END},
|
#define MAX_OPTIONS (6)
|
||||||
{"attack -t deauth", NO_ARGS, FOCUS_CONSOLE_END},
|
typedef struct {
|
||||||
{"attack -t probe", NO_ARGS, FOCUS_CONSOLE_END},
|
const char* item_string;
|
||||||
{"attack -t rickroll", NO_ARGS, FOCUS_CONSOLE_END},
|
const char* options_menu[MAX_OPTIONS];
|
||||||
{"channel", NO_ARGS, FOCUS_CONSOLE_END},
|
int num_options_menu;
|
||||||
{"channel -s", INPUT_ARGS, FOCUS_CONSOLE_END},
|
const char* actual_commands[MAX_OPTIONS];
|
||||||
{"clearlist -a", NO_ARGS, FOCUS_CONSOLE_END},
|
InputArgs needs_keyboard;
|
||||||
{"clearlist -s", NO_ARGS, FOCUS_CONSOLE_END},
|
FocusConsole focus_console;
|
||||||
{"help", NO_ARGS, FOCUS_CONSOLE_START},
|
bool show_stopscan_tip;
|
||||||
{"list -a", NO_ARGS, FOCUS_CONSOLE_START},
|
} WifiMarauderItem;
|
||||||
{"list -s", NO_ARGS, FOCUS_CONSOLE_START},
|
|
||||||
{"reboot", NO_ARGS, FOCUS_CONSOLE_END},
|
// NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it!
|
||||||
{"scanap", NO_ARGS, FOCUS_CONSOLE_END},
|
const WifiMarauderItem items[NUM_MENU_ITEMS] = {
|
||||||
{"select -a", INPUT_ARGS, FOCUS_CONSOLE_END},
|
{"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP},
|
||||||
{"select -s", INPUT_ARGS, FOCUS_CONSOLE_END},
|
{"Scan AP", {""}, 1, {"scanap"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP},
|
||||||
{"sniffbeacon", NO_ARGS, FOCUS_CONSOLE_END},
|
{"SSID",
|
||||||
{"sniffdeauth", NO_ARGS, FOCUS_CONSOLE_END},
|
{"add random", "add name", "remove"},
|
||||||
{"sniffesp", NO_ARGS, FOCUS_CONSOLE_END},
|
3,
|
||||||
{"sniffpmkid", NO_ARGS, FOCUS_CONSOLE_END},
|
{"ssid -a -g", "ssid -a -n", "ssid -r"},
|
||||||
{"sniffpmkid -c", INPUT_ARGS, FOCUS_CONSOLE_END},
|
INPUT_ARGS,
|
||||||
{"sniffpwn", NO_ARGS, FOCUS_CONSOLE_END},
|
FOCUS_CONSOLE_START,
|
||||||
{"ssid -a -g", INPUT_ARGS, FOCUS_CONSOLE_END},
|
NO_TIP},
|
||||||
{"ssid -a -n", INPUT_ARGS, FOCUS_CONSOLE_END},
|
{"List", {"ap", "ssid"}, 2, {"list -a", "list -s"}, NO_ARGS, FOCUS_CONSOLE_START, NO_TIP},
|
||||||
{"ssid -r", INPUT_ARGS, FOCUS_CONSOLE_END},
|
{"Select", {"ap", "ssid"}, 2, {"select -a", "select -s"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||||
{"update -w", NO_ARGS, FOCUS_CONSOLE_END},
|
{"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) {
|
static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
WifiMarauderApp* app = 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->is_custom_tx_string = false;
|
||||||
app->selected_menu_index = index;
|
app->selected_menu_index = index;
|
||||||
app->focus_console_start = items[index].focus_console_start;
|
app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ?
|
||||||
if(items[index].needs_keyboard) {
|
(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);
|
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartKeyboard);
|
||||||
} else {
|
} else {
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole);
|
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) {
|
void wifi_marauder_scene_start_on_enter(void* context) {
|
||||||
WifiMarauderApp* app = context;
|
WifiMarauderApp* app = context;
|
||||||
VariableItemList* var_item_list = app->var_item_list;
|
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(
|
variable_item_list_set_enter_callback(
|
||||||
var_item_list, wifi_marauder_scene_start_var_list_enter_callback, app);
|
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) {
|
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(
|
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);
|
scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput);
|
||||||
}
|
}
|
||||||
consumed = true;
|
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;
|
return consumed;
|
||||||
|
|||||||
@@ -24,7 +24,20 @@ void wifi_marauder_scene_text_input_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
TextInput* text_input = app->text_input;
|
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_set_result_callback(
|
||||||
text_input,
|
text_input,
|
||||||
wifi_marauder_scene_text_input_callback,
|
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* wifi_marauder_app_alloc() {
|
||||||
WifiMarauderApp* app = malloc(sizeof(WifiMarauderApp));
|
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->view_dispatcher = view_dispatcher_alloc();
|
||||||
app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app);
|
app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app);
|
||||||
@@ -46,6 +46,10 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
|
|||||||
WifiMarauderAppViewVarItemList,
|
WifiMarauderAppViewVarItemList,
|
||||||
variable_item_list_get_view(app->var_item_list));
|
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();
|
app->text_box = text_box_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box));
|
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);
|
wifi_marauder_uart_free(app->uart);
|
||||||
|
|
||||||
// Close records
|
// Close records
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
free(app);
|
free(app);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <gui/modules/text_input.h>
|
#include <gui/modules/text_input.h>
|
||||||
#include <gui/modules/variable_item_list.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_BOX_STORE_SIZE (4096)
|
||||||
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
|
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
|
||||||
|
|
||||||
@@ -31,10 +33,12 @@ struct WifiMarauderApp {
|
|||||||
|
|
||||||
WifiMarauderUart* uart;
|
WifiMarauderUart* uart;
|
||||||
int selected_menu_index;
|
int selected_menu_index;
|
||||||
|
int selected_option_index[NUM_MENU_ITEMS];
|
||||||
const char* selected_tx_string;
|
const char* selected_tx_string;
|
||||||
bool is_command;
|
bool is_command;
|
||||||
bool is_custom_tx_string;
|
bool is_custom_tx_string;
|
||||||
bool focus_console_start;
|
bool focus_console_start;
|
||||||
|
bool show_stopscan_tip;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Supported commands:
|
// 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);
|
view_port_input_callback_set(view_port, wifi_module_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// 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);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
//notification_message(app->notification, &sequence_set_only_blue_255);
|
//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);
|
gui_remove_view_port(gui, view_port);
|
||||||
|
|
||||||
// Close gui record
|
// Close gui record
|
||||||
furi_record_close("gui");
|
furi_record_close(RECORD_GUI);
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
app->m_gui = NULL;
|
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 |
Submodule assets/protobuf updated: cc5918dc48...6727eaf287
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user