Merge branch 'dev' into cc1101_ext

This commit is contained in:
MX 2023-07-10 17:04:53 +03:00
commit 5fa0706d70
No known key found for this signature in database
GPG key ID: 7CCC66B7DBDD1C83
80 changed files with 1568 additions and 213 deletions

View file

@ -1,11 +1,14 @@
## New changes
* SubGHz: Keeloq: Centurion Nova read and emulate support (+ add manually)
* !!! **Warning! After installing, Desktop settings (Favoutite apps, PIN Code, AutoLock time..) will be resetted to default due to settings changes, Please set your PIN code, Favourite apps again in Settings->Desktop** !!!
* If you have copied any apps manually into `apps` folder - remove `apps` folder or that specific apps you copied on your microSD before installing this release to avoid issues due to OFW API version update! If you using regular builds or extra pack builds (e) without your manually added apps, all included apps will be installed automatically, no extra actions needed!
-----
* SubGHz: **Keeloq: Centurion Nova read and emulate support (+ add manually)**
* SubGHz: FAAC SLH - UI Fixes, Fix sending signals with no seed
* SubGHz: Code cleanup, proper handling of protocols ignore options (by @gid9798 | PR #516)
* SubGHz: Various UI fixes (by @wosk | PR #527)
* NFC: Fixed issue #532 (Mifare classic user dict - delete removes more than selected key)
* Infrared: Updated universal remote assets (by @amec0e | PR #529)
* Plugins: Use correct categories for all plugins (extra pack too)
* Plugins: **Use correct categories (folders) for all plugins (extra pack too)**
* Plugins: Various fixes for uFBT (by @hedger)
* Plugins: Added **NFC Maker** plugin (make tags with URLs, Wifi and other things) [(by Willy-JL)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/external/nfc_maker)
* Plugins: Added JetPack Joyride [(by timstrasser)](https://github.com/timstrasser)
@ -14,7 +17,7 @@
* Plugins: Updated i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools)
* Settings: Change LED and volume settings by 5% steps (by @cokyrain)
* BLE: BadBT fixes and furi_hal_bt cleanup (by @Willy-JL)
* WIP OFW PR 2825: NFC: Improved MFC emulation on some readers (by AloneLiberty)
* WIP OFW PR 2825: **NFC: Improved MFC emulation on some readers (by AloneLiberty)**
* OFW PR 2829: Decode only supported Oregon 3 sensor (by @wosk)
* OFW PR: Update OFW PR 2782
* OFW: SubGhz: add "SubGhz test" external application and the ability to work "SubGhz" as an external application

View file

@ -10,7 +10,7 @@ App(
stack_size=2 * 1024,
order=70,
fap_libs=["assets"],
fap_category="Tools",
fap_category="Bluetooth",
fap_icon="images/badbt_10px.png",
fap_icon_assets="images",
)

View file

@ -21,5 +21,5 @@ App(
fap_author="AloneLiberty",
fap_description="Recover Mifare Classic keys",
fap_weburl="https://github.com/AloneLiberty/FlipperNested",
fap_version="1.5.0"
fap_version="1.5.1"
)

View file

@ -21,7 +21,7 @@
#include <gui/modules/variable_item_list.h>
#include "mifare_nested_icons.h"
#define NESTED_VERSION_APP "1.5.0"
#define NESTED_VERSION_APP "1.5.1"
#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
#define NESTED_NONCE_FORMAT_VERSION "3"

View file

@ -478,9 +478,13 @@ SaveNoncesResult_t* mifare_nested_worker_write_nonces(
for(uint8_t sector = 0; sector < sector_count; sector++) {
for(uint8_t key_type = 0; key_type < 2; key_type++) {
if(nonces->nonces[sector][key_type][tries]->invalid) {
result->invalid++;
if(tries == 0) {
result->invalid++;
}
} else if(nonces->nonces[sector][key_type][tries]->skipped) {
result->skipped++;
if(tries == 0) {
result->skipped++;
}
} else if(nonces->nonces[sector][key_type][tries]->collected) {
if(nonces->nonces[sector][key_type][tries]->hardnested) {
FuriString* hardnested_path = furi_string_alloc();

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -35,9 +35,11 @@ NfcMaker* nfc_maker_alloc() {
view_dispatcher_add_view(
app->view_dispatcher, NfcMakerViewSubmenu, submenu_get_view(app->submenu));
app->text_input = text_input_alloc();
app->text_input = nfc_maker_text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, NfcMakerViewTextInput, text_input_get_view(app->text_input));
app->view_dispatcher,
NfcMakerViewTextInput,
nfc_maker_text_input_get_view(app->text_input));
app->byte_input = byte_input_alloc();
view_dispatcher_add_view(
@ -56,7 +58,7 @@ void nfc_maker_free(NfcMaker* app) {
view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewSubmenu);
submenu_free(app->submenu);
view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewTextInput);
text_input_free(app->text_input);
nfc_maker_text_input_free(app->text_input);
view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewByteInput);
byte_input_free(app->byte_input);
view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewPopup);

View file

@ -8,7 +8,7 @@
#include <gui/scene_manager.h>
#include "nfc_maker_icons.h"
#include <gui/modules/submenu.h>
#include <gui/modules/text_input.h>
#include "nfc_maker_text_input.h"
#include <gui/modules/byte_input.h>
#include <gui/modules/popup.h>
#include "scenes/nfc_maker_scene.h"
@ -42,7 +42,7 @@ typedef struct {
SceneManager* scene_manager;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
TextInput* text_input;
NFCMaker_TextInput* text_input;
ByteInput* byte_input;
Popup* popup;

View file

@ -0,0 +1,762 @@
#include "nfc_maker_text_input.h"
#include <gui/elements.h>
#include "nfc_maker.h"
#include <furi.h>
struct NFCMaker_TextInput {
View* view;
FuriTimer* timer;
};
typedef struct {
const char text;
const uint8_t x;
const uint8_t y;
} NFCMaker_TextInputKey;
typedef struct {
const NFCMaker_TextInputKey* rows[3];
const uint8_t keyboard_index;
} Keyboard;
typedef struct {
const char* header;
char* text_buffer;
size_t text_buffer_size;
size_t minimum_length;
bool clear_default_text;
bool cursor_select;
size_t cursor_pos;
NFCMaker_TextInputCallback callback;
void* callback_context;
uint8_t selected_row;
uint8_t selected_column;
uint8_t selected_keyboard;
NFCMaker_TextInputValidatorCallback validator_callback;
void* validator_callback_context;
FuriString* validator_text;
bool validator_message_visible;
} NFCMaker_TextInputModel;
static const uint8_t keyboard_origin_x = 1;
static const uint8_t keyboard_origin_y = 29;
static const uint8_t keyboard_row_count = 3;
static const uint8_t keyboard_count = 2;
#define ENTER_KEY '\r'
#define BACKSPACE_KEY '\b'
#define SWITCH_KEYBOARD_KEY 0xfe
static const NFCMaker_TextInputKey keyboard_keys_row_1[] = {
{'q', 1, 8},
{'w', 10, 8},
{'e', 19, 8},
{'r', 28, 8},
{'t', 37, 8},
{'y', 46, 8},
{'u', 55, 8},
{'i', 64, 8},
{'o', 73, 8},
{'p', 82, 8},
{'0', 91, 8},
{'1', 100, 8},
{'2', 110, 8},
{'3', 120, 8},
};
static const NFCMaker_TextInputKey keyboard_keys_row_2[] = {
{'a', 1, 20},
{'s', 10, 20},
{'d', 19, 20},
{'f', 28, 20},
{'g', 37, 20},
{'h', 46, 20},
{'j', 55, 20},
{'k', 64, 20},
{'l', 73, 20},
{BACKSPACE_KEY, 82, 12},
{'4', 100, 20},
{'5', 110, 20},
{'6', 120, 20},
};
static const NFCMaker_TextInputKey keyboard_keys_row_3[] = {
{SWITCH_KEYBOARD_KEY, 1, 23},
{'z', 13, 32},
{'x', 21, 32},
{'c', 28, 32},
{'v', 36, 32},
{'b', 44, 32},
{'n', 52, 32},
{'m', 59, 32},
{'_', 67, 32},
{ENTER_KEY, 74, 23},
{'7', 100, 32},
{'8', 110, 32},
{'9', 120, 32},
};
static const NFCMaker_TextInputKey symbol_keyboard_keys_row_1[] = {
{'!', 2, 8},
{'@', 12, 8},
{'#', 22, 8},
{'$', 32, 8},
{'%', 42, 8},
{'^', 52, 8},
{'&', 62, 8},
{'(', 71, 8},
{')', 81, 8},
{'0', 91, 8},
{'1', 100, 8},
{'2', 110, 8},
{'3', 120, 8},
};
static const NFCMaker_TextInputKey symbol_keyboard_keys_row_2[] = {
{'~', 2, 20},
{'+', 12, 20},
{'-', 22, 20},
{'=', 32, 20},
{'[', 42, 20},
{']', 52, 20},
{'{', 62, 20},
{'}', 72, 20},
{BACKSPACE_KEY, 82, 12},
{'4', 100, 20},
{'5', 110, 20},
{'6', 120, 20},
};
static const NFCMaker_TextInputKey symbol_keyboard_keys_row_3[] = {
{SWITCH_KEYBOARD_KEY, 1, 23},
{'.', 15, 32},
{',', 29, 32},
{':', 41, 32},
{'/', 53, 32},
{'\\', 65, 32},
{ENTER_KEY, 74, 23},
{'7', 100, 32},
{'8', 110, 32},
{'9', 120, 32},
};
static const Keyboard keyboard = {
.rows =
{
keyboard_keys_row_1,
keyboard_keys_row_2,
keyboard_keys_row_3,
},
.keyboard_index = 0,
};
static const Keyboard symbol_keyboard = {
.rows =
{
symbol_keyboard_keys_row_1,
symbol_keyboard_keys_row_2,
symbol_keyboard_keys_row_3,
},
.keyboard_index = 1,
};
static const Keyboard* keyboards[] = {
&keyboard,
&symbol_keyboard,
};
static void switch_keyboard(NFCMaker_TextInputModel* model) {
model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count;
}
static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) {
uint8_t row_size = 0;
if(keyboard == &symbol_keyboard) {
switch(row_index + 1) {
case 1:
row_size = COUNT_OF(symbol_keyboard_keys_row_1);
break;
case 2:
row_size = COUNT_OF(symbol_keyboard_keys_row_2);
break;
case 3:
row_size = COUNT_OF(symbol_keyboard_keys_row_3);
break;
default:
furi_crash(NULL);
}
} else {
switch(row_index + 1) {
case 1:
row_size = COUNT_OF(keyboard_keys_row_1);
break;
case 2:
row_size = COUNT_OF(keyboard_keys_row_2);
break;
case 3:
row_size = COUNT_OF(keyboard_keys_row_3);
break;
default:
furi_crash(NULL);
}
}
return row_size;
}
static const NFCMaker_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) {
const NFCMaker_TextInputKey* row = NULL;
if(row_index < 3) {
row = keyboard->rows[row_index];
} else {
furi_crash(NULL);
}
return row;
}
static char get_selected_char(NFCMaker_TextInputModel* model) {
return get_row(
keyboards[model->selected_keyboard], model->selected_row)[model->selected_column]
.text;
}
static bool char_is_lowercase(char letter) {
return (letter >= 0x61 && letter <= 0x7A);
}
static char char_to_uppercase(const char letter) {
if(letter == '_') {
return 0x20;
} else if(char_is_lowercase(letter)) {
return (letter - 0x20);
} else {
return letter;
}
}
static void nfc_maker_text_input_backspace_cb(NFCMaker_TextInputModel* model) {
if(model->clear_default_text) {
model->text_buffer[0] = 0;
model->cursor_pos = 0;
} else if(model->cursor_pos > 0) {
char* move = model->text_buffer + model->cursor_pos;
memmove(move - 1, move, strlen(move) + 1);
model->cursor_pos--;
}
}
static void nfc_maker_text_input_view_draw_callback(Canvas* canvas, void* _model) {
NFCMaker_TextInputModel* model = _model;
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
uint8_t needed_string_width = canvas_width(canvas) - 8;
uint8_t start_pos = 4;
model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos;
size_t cursor_pos = model->cursor_pos;
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_draw_str(canvas, 2, 8, model->header);
elements_slightly_rounded_frame(canvas, 1, 12, 126, 15);
char buf[model->text_buffer_size + 1];
if(model->text_buffer) {
strlcpy(buf, model->text_buffer, sizeof(buf));
}
char* str = buf;
if(model->clear_default_text) {
elements_slightly_rounded_box(
canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10);
canvas_set_color(canvas, ColorWhite);
} else {
char* move = str + cursor_pos;
memmove(move + 1, move, strlen(move) + 1);
str[cursor_pos] = '|';
}
if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) {
canvas_draw_str(canvas, start_pos, 22, "...");
start_pos += 6;
needed_string_width -= 8;
for(uint32_t off = 0;
strlen(str) && canvas_string_width(canvas, str) > needed_string_width &&
off < cursor_pos;
off++) {
str++;
}
}
if(canvas_string_width(canvas, str) > needed_string_width) {
needed_string_width -= 4;
size_t len = strlen(str);
while(len && canvas_string_width(canvas, str) > needed_string_width) {
str[len--] = '\0';
}
strcat(str, "...");
}
canvas_draw_str(canvas, start_pos, 22, str);
canvas_set_font(canvas, FontKeyboard);
for(uint8_t row = 0; row < keyboard_row_count; row++) {
const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row);
const NFCMaker_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row);
for(size_t column = 0; column < column_count; column++) {
bool selected = !model->cursor_select && model->selected_row == row &&
model->selected_column == column;
const Icon* icon = NULL;
if(keys[column].text == ENTER_KEY) {
icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11;
} else if(keys[column].text == SWITCH_KEYBOARD_KEY) {
icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11;
} else if(keys[column].text == BACKSPACE_KEY) {
icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9;
}
canvas_set_color(canvas, ColorBlack);
if(icon != NULL) {
canvas_draw_icon(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
icon);
} else {
if(selected) {
canvas_draw_box(
canvas,
keyboard_origin_x + keys[column].x - 1,
keyboard_origin_y + keys[column].y - 8,
7,
10);
canvas_set_color(canvas, ColorWhite);
}
if(model->clear_default_text || text_length == 0) {
canvas_draw_glyph(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
char_to_uppercase(keys[column].text));
} else {
canvas_draw_glyph(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
keys[column].text);
}
}
}
}
if(model->validator_message_visible) {
canvas_set_font(canvas, FontSecondary);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, 8, 10, 110, 48);
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text));
canvas_set_font(canvas, FontKeyboard);
}
}
static void nfc_maker_text_input_handle_up(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputModel* model) {
UNUSED(nfc_maker_text_input);
if(model->selected_row > 0) {
model->selected_row--;
if(model->selected_row == 0 &&
model->selected_column >
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) {
model->selected_column = model->selected_column + 1;
}
if(model->selected_row == 1 &&
model->selected_keyboard == symbol_keyboard.keyboard_index) {
if(model->selected_column > 5)
model->selected_column += 2;
else if(model->selected_column > 1)
model->selected_column += 1;
}
} else {
model->cursor_select = true;
model->clear_default_text = false;
}
}
static void nfc_maker_text_input_handle_down(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputModel* model) {
UNUSED(nfc_maker_text_input);
if(model->cursor_select) {
model->cursor_select = false;
} else if(model->selected_row < keyboard_row_count - 1) {
model->selected_row++;
if(model->selected_row == 1 &&
model->selected_column >
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) {
model->selected_column = model->selected_column - 1;
}
if(model->selected_row == 2 &&
model->selected_keyboard == symbol_keyboard.keyboard_index) {
if(model->selected_column > 7)
model->selected_column -= 2;
else if(model->selected_column > 1)
model->selected_column -= 1;
}
}
}
static void nfc_maker_text_input_handle_left(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputModel* model) {
UNUSED(nfc_maker_text_input);
if(model->cursor_select) {
if(model->cursor_pos > 0) {
model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u);
}
} else if(model->selected_column > 0) {
model->selected_column--;
} else {
model->selected_column =
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1;
}
}
static void nfc_maker_text_input_handle_right(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputModel* model) {
UNUSED(nfc_maker_text_input);
if(model->cursor_select) {
model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u);
} else if(
model->selected_column <
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) {
model->selected_column++;
} else {
model->selected_column = 0;
}
}
static void nfc_maker_text_input_handle_ok(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputModel* model,
InputType type) {
if(model->cursor_select) return;
bool shift = type == InputTypeLong;
bool repeat = type == InputTypeRepeat;
char selected = get_selected_char(model);
size_t text_length = strlen(model->text_buffer);
if(selected == ENTER_KEY) {
if(model->validator_callback &&
(!model->validator_callback(
model->text_buffer, model->validator_text, model->validator_callback_context))) {
model->validator_message_visible = true;
furi_timer_start(nfc_maker_text_input->timer, furi_kernel_get_tick_frequency() * 4);
} else if(model->callback != 0 && text_length >= model->minimum_length) {
model->callback(model->callback_context);
}
} else if(selected == SWITCH_KEYBOARD_KEY) {
switch_keyboard(model);
} else {
if(selected == BACKSPACE_KEY) {
nfc_maker_text_input_backspace_cb(model);
} else if(!repeat) {
if(model->clear_default_text) {
text_length = 0;
}
if(text_length < (model->text_buffer_size - 1)) {
if(shift != (text_length == 0)) {
selected = char_to_uppercase(selected);
}
if(model->clear_default_text) {
model->text_buffer[0] = selected;
model->text_buffer[1] = '\0';
model->cursor_pos = 1;
} else {
char* move = model->text_buffer + model->cursor_pos;
memmove(move + 1, move, strlen(move) + 1);
model->text_buffer[model->cursor_pos] = selected;
model->cursor_pos++;
}
}
}
model->clear_default_text = false;
}
}
static bool nfc_maker_text_input_view_input_callback(InputEvent* event, void* context) {
NFCMaker_TextInput* nfc_maker_text_input = context;
furi_assert(nfc_maker_text_input);
bool consumed = false;
// Acquire model
NFCMaker_TextInputModel* model = view_get_model(nfc_maker_text_input->view);
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
model->validator_message_visible) {
model->validator_message_visible = false;
consumed = true;
} else if(event->type == InputTypeShort) {
consumed = true;
switch(event->key) {
case InputKeyUp:
nfc_maker_text_input_handle_up(nfc_maker_text_input, model);
break;
case InputKeyDown:
nfc_maker_text_input_handle_down(nfc_maker_text_input, model);
break;
case InputKeyLeft:
nfc_maker_text_input_handle_left(nfc_maker_text_input, model);
break;
case InputKeyRight:
nfc_maker_text_input_handle_right(nfc_maker_text_input, model);
break;
case InputKeyOk:
nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeLong) {
consumed = true;
switch(event->key) {
case InputKeyUp:
nfc_maker_text_input_handle_up(nfc_maker_text_input, model);
break;
case InputKeyDown:
nfc_maker_text_input_handle_down(nfc_maker_text_input, model);
break;
case InputKeyLeft:
nfc_maker_text_input_handle_left(nfc_maker_text_input, model);
break;
case InputKeyRight:
nfc_maker_text_input_handle_right(nfc_maker_text_input, model);
break;
case InputKeyOk:
nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type);
break;
case InputKeyBack:
nfc_maker_text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeRepeat) {
consumed = true;
switch(event->key) {
case InputKeyUp:
nfc_maker_text_input_handle_up(nfc_maker_text_input, model);
break;
case InputKeyDown:
nfc_maker_text_input_handle_down(nfc_maker_text_input, model);
break;
case InputKeyLeft:
nfc_maker_text_input_handle_left(nfc_maker_text_input, model);
break;
case InputKeyRight:
nfc_maker_text_input_handle_right(nfc_maker_text_input, model);
break;
case InputKeyOk:
nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type);
break;
case InputKeyBack:
nfc_maker_text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
}
// Commit model
view_commit_model(nfc_maker_text_input->view, consumed);
return consumed;
}
void nfc_maker_text_input_timer_callback(void* context) {
furi_assert(context);
NFCMaker_TextInput* nfc_maker_text_input = context;
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ model->validator_message_visible = false; },
true);
}
NFCMaker_TextInput* nfc_maker_text_input_alloc() {
NFCMaker_TextInput* nfc_maker_text_input = malloc(sizeof(NFCMaker_TextInput));
nfc_maker_text_input->view = view_alloc();
view_set_context(nfc_maker_text_input->view, nfc_maker_text_input);
view_allocate_model(
nfc_maker_text_input->view, ViewModelTypeLocking, sizeof(NFCMaker_TextInputModel));
view_set_draw_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_draw_callback);
view_set_input_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_input_callback);
nfc_maker_text_input->timer = furi_timer_alloc(
nfc_maker_text_input_timer_callback, FuriTimerTypeOnce, nfc_maker_text_input);
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{
model->validator_text = furi_string_alloc();
model->minimum_length = 1;
model->cursor_pos = 0;
model->cursor_select = false;
},
false);
nfc_maker_text_input_reset(nfc_maker_text_input);
return nfc_maker_text_input;
}
void nfc_maker_text_input_free(NFCMaker_TextInput* nfc_maker_text_input) {
furi_assert(nfc_maker_text_input);
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ furi_string_free(model->validator_text); },
false);
// Send stop command
furi_timer_stop(nfc_maker_text_input->timer);
// Release allocated memory
furi_timer_free(nfc_maker_text_input->timer);
view_free(nfc_maker_text_input->view);
free(nfc_maker_text_input);
}
void nfc_maker_text_input_reset(NFCMaker_TextInput* nfc_maker_text_input) {
furi_assert(nfc_maker_text_input);
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{
model->header = "";
model->selected_row = 0;
model->selected_column = 0;
model->selected_keyboard = 0;
model->minimum_length = 1;
model->clear_default_text = false;
model->cursor_pos = 0;
model->cursor_select = false;
model->text_buffer = NULL;
model->text_buffer_size = 0;
model->callback = NULL;
model->callback_context = NULL;
model->validator_callback = NULL;
model->validator_callback_context = NULL;
furi_string_reset(model->validator_text);
model->validator_message_visible = false;
},
true);
}
View* nfc_maker_text_input_get_view(NFCMaker_TextInput* nfc_maker_text_input) {
furi_assert(nfc_maker_text_input);
return nfc_maker_text_input->view;
}
void nfc_maker_text_input_set_result_callback(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputCallback callback,
void* callback_context,
char* text_buffer,
size_t text_buffer_size,
bool clear_default_text) {
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{
model->callback = callback;
model->callback_context = callback_context;
model->text_buffer = text_buffer;
model->text_buffer_size = text_buffer_size;
model->clear_default_text = clear_default_text;
model->cursor_select = false;
if(text_buffer && text_buffer[0] != '\0') {
model->cursor_pos = strlen(text_buffer);
// Set focus on Save
model->selected_row = 2;
model->selected_column = 9;
model->selected_keyboard = 0;
} else {
model->cursor_pos = 0;
}
},
true);
}
void nfc_maker_text_input_set_minimum_length(
NFCMaker_TextInput* nfc_maker_text_input,
size_t minimum_length) {
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ model->minimum_length = minimum_length; },
true);
}
void nfc_maker_text_input_set_validator(
NFCMaker_TextInput* nfc_maker_text_input,
NFCMaker_TextInputValidatorCallback callback,
void* callback_context) {
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{
model->validator_callback = callback;
model->validator_callback_context = callback_context;
},
true);
}
NFCMaker_TextInputValidatorCallback
nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* nfc_maker_text_input) {
NFCMaker_TextInputValidatorCallback validator_callback = NULL;
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ validator_callback = model->validator_callback; },
false);
return validator_callback;
}
void* nfc_maker_text_input_get_validator_callback_context(
NFCMaker_TextInput* nfc_maker_text_input) {
void* validator_callback_context = NULL;
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ validator_callback_context = model->validator_callback_context; },
false);
return validator_callback_context;
}
void nfc_maker_text_input_set_header_text(
NFCMaker_TextInput* nfc_maker_text_input,
const char* text) {
with_view_model(
nfc_maker_text_input->view,
NFCMaker_TextInputModel * model,
{ model->header = text; },
true);
}

View file

@ -0,0 +1,85 @@
#pragma once
#include <gui/view.h>
#include "nfc_maker_validators.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Text input anonymous structure */
typedef struct NFCMaker_TextInput NFCMaker_TextInput;
typedef void (*NFCMaker_TextInputCallback)(void* context);
typedef bool (
*NFCMaker_TextInputValidatorCallback)(const char* text, FuriString* error, void* context);
/** Allocate and initialize text input
*
* This text input is used to enter string
*
* @return NFCMaker_TextInput instance
*/
NFCMaker_TextInput* nfc_maker_text_input_alloc();
/** Deinitialize and free text input
*
* @param text_input NFCMaker_TextInput instance
*/
void nfc_maker_text_input_free(NFCMaker_TextInput* text_input);
/** Clean text input view Note: this function does not free memory
*
* @param text_input Text input instance
*/
void nfc_maker_text_input_reset(NFCMaker_TextInput* text_input);
/** Get text input view
*
* @param text_input NFCMaker_TextInput instance
*
* @return View instance that can be used for embedding
*/
View* nfc_maker_text_input_get_view(NFCMaker_TextInput* text_input);
/** Set text input result callback
*
* @param text_input NFCMaker_TextInput instance
* @param callback callback fn
* @param callback_context callback context
* @param text_buffer pointer to YOUR text buffer, that we going
* to modify
* @param text_buffer_size YOUR text buffer size in bytes. Max string
* length will be text_buffer_size-1.
* @param clear_default_text clear text from text_buffer on first OK
* event
*/
void nfc_maker_text_input_set_result_callback(
NFCMaker_TextInput* text_input,
NFCMaker_TextInputCallback callback,
void* callback_context,
char* text_buffer,
size_t text_buffer_size,
bool clear_default_text);
void nfc_maker_text_input_set_validator(
NFCMaker_TextInput* text_input,
NFCMaker_TextInputValidatorCallback callback,
void* callback_context);
void nfc_maker_text_input_set_minimum_length(NFCMaker_TextInput* text_input, size_t minimum_length);
NFCMaker_TextInputValidatorCallback
nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* text_input);
void* nfc_maker_text_input_get_validator_callback_context(NFCMaker_TextInput* text_input);
/** Set text input header text
*
* @param text_input NFCMaker_TextInput instance
* @param text text to be shown
*/
void nfc_maker_text_input_set_header_text(NFCMaker_TextInput* text_input, const char* text);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,57 @@
#include <furi.h>
#include "nfc_maker_validators.h"
#include <storage/storage.h>
struct ValidatorIsFile {
char* app_path_folder;
const char* app_extension;
char* current_name;
};
bool validator_is_file_callback(const char* text, FuriString* error, void* context) {
furi_assert(context);
ValidatorIsFile* instance = context;
if(instance->current_name != NULL) {
if(strcmp(instance->current_name, text) == 0) {
return true;
}
}
bool ret = true;
FuriString* path = furi_string_alloc_printf(
"%s/%s%s", instance->app_path_folder, text, instance->app_extension);
Storage* storage = furi_record_open(RECORD_STORAGE);
if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) {
ret = false;
furi_string_printf(error, "This name\nexists!\nChoose\nanother one.");
} else {
ret = true;
}
furi_string_free(path);
furi_record_close(RECORD_STORAGE);
return ret;
}
ValidatorIsFile* validator_is_file_alloc_init(
const char* app_path_folder,
const char* app_extension,
const char* current_name) {
ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
instance->app_path_folder = strdup(app_path_folder);
instance->app_extension = app_extension;
if(current_name != NULL) {
instance->current_name = strdup(current_name);
}
return instance;
}
void validator_is_file_free(ValidatorIsFile* instance) {
furi_assert(instance);
free(instance->app_path_folder);
free(instance->current_name);
free(instance);
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <core/common_defines.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ValidatorIsFile ValidatorIsFile;
ValidatorIsFile* validator_is_file_alloc_init(
const char* app_path_folder,
const char* app_extension,
const char* current_name);
void validator_is_file_free(ValidatorIsFile* instance);
bool validator_is_file_callback(const char* text, FuriString* error, void* context);
#ifdef __cplusplus
}
#endif

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_https_text_input_callback(void* context) {
void nfc_maker_scene_https_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter HTTPS Link:");
nfc_maker_text_input_set_header_text(text_input, "Enter HTTPS Link:");
strlcpy(app->text_buf, "google.com", TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_https_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_https_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_https_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_mail_text_input_callback(void* context) {
void nfc_maker_scene_mail_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter EMail Address:");
nfc_maker_text_input_set_header_text(text_input, "Enter Email Address:");
strlcpy(app->text_buf, "ben.dover@example.com", TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_mail_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_mail_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_mail_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -22,7 +22,7 @@ void nfc_maker_scene_menu_on_enter(void* context) {
submenu, "HTTPS Link", NfcMakerSceneHttps, nfc_maker_scene_menu_submenu_callback, app);
submenu_add_item(
submenu, "Mail Address", NfcMakerSceneMail, nfc_maker_scene_menu_submenu_callback, app);
submenu, "Email Address", NfcMakerSceneMail, nfc_maker_scene_menu_submenu_callback, app);
submenu_add_item(
submenu, "Phone Number", NfcMakerScenePhone, nfc_maker_scene_menu_submenu_callback, app);

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_name_text_input_callback(void* context) {
void nfc_maker_scene_name_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Name the NFC tag:");
nfc_maker_text_input_set_header_text(text_input, "Name the NFC tag:");
set_random_name(app->name_buf, TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_name_text_input_callback,
app,
@ -28,7 +28,7 @@ void nfc_maker_scene_name_on_enter(void* context) {
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, NULL);
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
nfc_maker_text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput);
}
@ -53,5 +53,5 @@ bool nfc_maker_scene_name_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_name_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_phone_text_input_callback(void* context) {
void nfc_maker_scene_phone_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter Phone Number:");
nfc_maker_text_input_set_header_text(text_input, "Enter Phone Number:");
strlcpy(app->text_buf, "+", TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_phone_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_phone_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_phone_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_text_text_input_callback(void* context) {
void nfc_maker_scene_text_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter Text Note:");
nfc_maker_text_input_set_header_text(text_input, "Enter Text Note:");
strlcpy(app->text_buf, "Lorem ipsum", TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_text_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_text_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_text_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_url_text_input_callback(void* context) {
void nfc_maker_scene_url_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter Plain URL:");
nfc_maker_text_input_set_header_text(text_input, "Enter Plain URL:");
strlcpy(app->text_buf, "https://google.com", TEXT_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_url_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_url_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_url_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_wifi_text_input_callback(void* context) {
void nfc_maker_scene_wifi_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter WiFi SSID:");
nfc_maker_text_input_set_header_text(text_input, "Enter WiFi SSID:");
strlcpy(app->text_buf, "Bill Wi the Science Fi", WIFI_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_wifi_text_input_callback,
app,
@ -51,5 +51,5 @@ bool nfc_maker_scene_wifi_on_event(void* context, SceneManagerEvent event) {
void nfc_maker_scene_wifi_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -12,13 +12,13 @@ static void nfc_maker_scene_wifi_pass_text_input_callback(void* context) {
void nfc_maker_scene_wifi_pass_on_enter(void* context) {
NfcMaker* app = context;
TextInput* text_input = app->text_input;
NFCMaker_TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Enter WiFi Password:");
nfc_maker_text_input_set_header_text(text_input, "Enter WiFi Password:");
strlcpy(app->pass_buf, "244466666", WIFI_INPUT_LEN);
text_input_set_result_callback(
nfc_maker_text_input_set_result_callback(
text_input,
nfc_maker_scene_wifi_pass_text_input_callback,
app,
@ -49,5 +49,5 @@ bool nfc_maker_scene_wifi_pass_on_event(void* context, SceneManagerEvent event)
void nfc_maker_scene_wifi_pass_on_exit(void* context) {
NfcMaker* app = context;
text_input_reset(app->text_input);
nfc_maker_text_input_reset(app->text_input);
}

View file

@ -182,6 +182,11 @@ bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEven
consumed = true;
} else if(event.type == SceneManagerEventTypeTick) {
consumed = true;
} else {
if(app->flash_worker_busy) {
// ignore button presses while flashing
consumed = true;
}
}
return consumed;

View file

@ -1,9 +1,14 @@
#include "../wifi_marauder_app_i.h"
#include "../wifi_marauder_flasher.h"
enum SubmenuIndex {
SubmenuIndexS3Mode,
SubmenuIndexBoot,
SubmenuIndexPart,
SubmenuIndexNvs,
SubmenuIndexBootApp0,
SubmenuIndexApp,
SubmenuIndexCustom,
SubmenuIndexFlash,
};
@ -20,16 +25,33 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
// TODO refactor
switch(index) {
case SubmenuIndexS3Mode:
// toggle S3 mode
app->selected_flash_options[SelectedFlashS3Mode] =
!app->selected_flash_options[SelectedFlashS3Mode];
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexBoot:
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
app->bin_file_path_boot,
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_boot));
app->selected_flash_options[SelectedFlashBoot] =
!app->selected_flash_options[SelectedFlashBoot];
if(app->selected_flash_options[SelectedFlashBoot]) {
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
app->bin_file_path_boot,
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_boot));
}
}
if(app->bin_file_path_boot[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashBoot] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexPart:
app->selected_flash_options[SelectedFlashPart] =
!app->selected_flash_options[SelectedFlashPart];
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
@ -37,8 +59,47 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_part));
}
if(app->bin_file_path_part[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashPart] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexNvs:
app->selected_flash_options[SelectedFlashNvs] =
!app->selected_flash_options[SelectedFlashNvs];
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
app->bin_file_path_nvs,
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_nvs));
}
if(app->bin_file_path_nvs[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashNvs] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexBootApp0:
app->selected_flash_options[SelectedFlashBootApp0] =
!app->selected_flash_options[SelectedFlashBootApp0];
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
app->bin_file_path_boot_app0,
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_boot_app0));
}
if(app->bin_file_path_boot_app0[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashBootApp0] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexApp:
app->selected_flash_options[SelectedFlashApp] =
!app->selected_flash_options[SelectedFlashApp];
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
@ -46,10 +107,42 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_app));
}
if(app->bin_file_path_app[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashApp] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexCustom:
app->selected_flash_options[SelectedFlashCustom] =
!app->selected_flash_options[SelectedFlashCustom];
if(dialog_file_browser_show(
app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
strncpy(
app->bin_file_path_custom,
furi_string_get_cstr(selected_filepath),
sizeof(app->bin_file_path_custom));
}
if(app->bin_file_path_custom[0] == '\0') {
// if user didn't select a file, leave unselected
app->selected_flash_options[SelectedFlashCustom] = false;
}
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu);
break;
case SubmenuIndexFlash:
// TODO error checking
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
// count how many options are selected
app->num_selected_flash_options = 0;
for(bool* option = &app->selected_flash_options[SelectedFlashBoot];
option < &app->selected_flash_options[NUM_FLASH_OPTIONS];
++option) {
if(*option) {
++app->num_selected_flash_options;
}
}
if(app->num_selected_flash_options) {
// only start next scene if at least one option is selected
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
}
break;
}
@ -57,31 +150,112 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
furi_string_free(predefined_filepath);
}
void wifi_marauder_scene_flasher_on_enter(void* context) {
WifiMarauderApp* app = context;
#define STR_SELECT "[x]"
#define STR_UNSELECT "[ ]"
#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")"
#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")"
#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")"
#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")"
#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")"
#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")"
#define STR_CUSTOM "Custom"
#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)"
#define STR_FLASH "[>] FLASH"
static void _refresh_submenu(WifiMarauderApp* app) {
Submenu* submenu = app->submenu;
submenu_reset(app->submenu);
submenu_set_header(submenu, "Browse for files to flash");
submenu_add_item(
submenu, "Bootloader", SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app);
submenu,
app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" :
"[ ] Check if using S3",
SubmenuIndexS3Mode,
wifi_marauder_scene_flasher_callback,
app);
const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT;
if(app->selected_flash_options[SelectedFlashS3Mode]) {
if(app->selected_flash_options[SelectedFlashBoot]) {
strSelectBootloader = STR_SELECT " " STR_BOOT_S3;
} else {
strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3;
}
} else {
if(app->selected_flash_options[SelectedFlashBoot]) {
strSelectBootloader = STR_SELECT " " STR_BOOT;
} else {
strSelectBootloader = STR_UNSELECT " " STR_BOOT;
}
}
submenu_add_item(
submenu, "Partition Table", SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app);
submenu, strSelectBootloader, SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app);
submenu_add_item(
submenu, "Application", SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app);
submenu,
app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART :
STR_UNSELECT " " STR_PART,
SubmenuIndexPart,
wifi_marauder_scene_flasher_callback,
app);
submenu_add_item(
submenu, "[>] FLASH", SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app);
submenu,
app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS :
STR_UNSELECT " " STR_NVS,
SubmenuIndexNvs,
wifi_marauder_scene_flasher_callback,
app);
submenu_add_item(
submenu,
app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 :
STR_UNSELECT " " STR_BOOT_APP0,
SubmenuIndexBootApp0,
wifi_marauder_scene_flasher_callback,
app);
submenu_add_item(
submenu,
app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP :
STR_UNSELECT " " STR_APP,
SubmenuIndexApp,
wifi_marauder_scene_flasher_callback,
app);
// TODO: custom addr
//submenu_add_item(
// submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, wifi_marauder_scene_flasher_callback, app);
submenu_add_item(
submenu,
app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH,
SubmenuIndexFlash,
wifi_marauder_scene_flasher_callback,
app);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher));
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu);
}
void wifi_marauder_scene_flasher_on_enter(void* context) {
WifiMarauderApp* app = context;
memset(app->selected_flash_options, 0, sizeof(app->selected_flash_options));
app->bin_file_path_boot[0] = '\0';
app->bin_file_path_part[0] = '\0';
app->bin_file_path_nvs[0] = '\0';
app->bin_file_path_boot_app0[0] = '\0';
app->bin_file_path_app[0] = '\0';
app->bin_file_path_custom[0] = '\0';
_refresh_submenu(app);
}
bool wifi_marauder_scene_flasher_on_event(void* context, SceneManagerEvent event) {
//WifiMarauderApp* app = context;
UNUSED(context);
UNUSED(event);
WifiMarauderApp* app = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == WifiMarauderEventRefreshSubmenu) {
_refresh_submenu(app);
consumed = true;
}
}
return consumed;
}

View file

@ -243,7 +243,6 @@ void wifi_marauder_scene_start_on_enter(void* context) {
}
bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
WifiMarauderApp* app = context;
bool consumed = false;

View file

@ -87,6 +87,7 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu));
app->flash_mode = false;
app->flash_worker_busy = false;
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart);

View file

@ -4,7 +4,7 @@
extern "C" {
#endif
#define WIFI_MARAUDER_APP_VERSION "v0.5.0"
#define WIFI_MARAUDER_APP_VERSION "v0.5.1"
typedef struct WifiMarauderApp WifiMarauderApp;

View file

@ -48,6 +48,17 @@ typedef enum WifiMarauderUserInputType {
WifiMarauderUserInputTypeFileName
} WifiMarauderUserInputType;
typedef enum SelectedFlashOptions {
SelectedFlashS3Mode,
SelectedFlashBoot,
SelectedFlashPart,
SelectedFlashNvs,
SelectedFlashBootApp0,
SelectedFlashApp,
SelectedFlashCustom,
NUM_FLASH_OPTIONS
} SelectedFlashOptions;
struct WifiMarauderApp {
Gui* gui;
ViewDispatcher* view_dispatcher;
@ -115,10 +126,16 @@ struct WifiMarauderApp {
char special_case_input_dst_addr[20];
// For flashing - TODO: put into its own struct?
bool selected_flash_options[NUM_FLASH_OPTIONS];
int num_selected_flash_options;
char bin_file_path_boot[100];
char bin_file_path_part[100];
char bin_file_path_nvs[100];
char bin_file_path_boot_app0[100];
char bin_file_path_app[100];
char bin_file_path_custom[100];
FuriThread* flash_worker;
bool flash_worker_busy;
bool flash_mode;
};

View file

@ -10,5 +10,6 @@ typedef enum {
WifiMarauderEventStartLogViewer,
WifiMarauderEventStartScriptSelect,
WifiMarauderEventStartSniffPmkidOptions,
WifiMarauderEventStartFlasher
WifiMarauderEventStartFlasher,
WifiMarauderEventRefreshSubmenu
} WifiMarauderCustomEvent;

View file

@ -18,6 +18,8 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint
static uint8_t payload[1024];
File* bin_file = storage_file_alloc(app->storage);
char user_msg[256];
// open file
if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) {
storage_file_close(bin_file);
@ -28,48 +30,34 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint
uint64_t size = storage_file_size(bin_file);
/*
// TODO packet drops with higher BR?
err = esp_loader_change_transmission_rate(230400);
if (err != ESP_LOADER_SUCCESS) {
char err_msg[256];
snprintf(
err_msg,
sizeof(err_msg),
"Cannot change transmission rate. Error: %u\n",
err);
storage_file_close(bin_file);
storage_file_free(bin_file);
loader_port_debug_print(err_msg);
return;
}
furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
// TODO remember to change BR back!
*/
loader_port_debug_print("Erasing flash...this may take a while\n");
err = esp_loader_flash_start(addr, size, sizeof(payload));
if(err != ESP_LOADER_SUCCESS) {
storage_file_close(bin_file);
storage_file_free(bin_file);
char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Erasing flash failed with error %d\n", err);
loader_port_debug_print(err_msg);
snprintf(user_msg, sizeof(user_msg), "Erasing flash failed with error %d\n", err);
loader_port_debug_print(user_msg);
return err;
}
loader_port_debug_print("Start programming\n");
uint64_t last_updated = size;
while(size > 0) {
if((last_updated - size) > 50000) {
// inform user every 50k bytes
// TODO: draw a progress bar next update
snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size);
loader_port_debug_print(user_msg);
last_updated = size;
}
size_t to_read = MIN(size, sizeof(payload));
uint16_t num_bytes = storage_file_read(bin_file, payload, to_read);
err = esp_loader_flash_write(payload, num_bytes);
if(err != ESP_LOADER_SUCCESS) {
char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Packet could not be written! Error: %u\n", err);
snprintf(user_msg, sizeof(user_msg), "Packet could not be written! Error: %u\n", err);
storage_file_close(bin_file);
storage_file_free(bin_file);
loader_port_debug_print(err_msg);
loader_port_debug_print(user_msg);
return err;
}
@ -86,10 +74,59 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint
return ESP_LOADER_SUCCESS;
}
typedef struct {
SelectedFlashOptions selected;
const char* description;
char* path;
uint32_t addr;
} FlashItem;
static void _flash_all_files(WifiMarauderApp* app) {
esp_loader_error_t err;
const int num_steps = app->num_selected_flash_options;
#define NUM_FLASH_ITEMS 6
FlashItem items[NUM_FLASH_ITEMS] = {
{SelectedFlashBoot,
"bootloader",
app->bin_file_path_boot,
app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT},
{SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART},
{SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS},
{SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0},
{SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP},
{SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0},
/* if you add more entries, update NUM_FLASH_ITEMS above! */
};
char user_msg[256];
int current_step = 1;
for(FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) {
if(app->selected_flash_options[item->selected]) {
snprintf(
user_msg,
sizeof(user_msg),
"Flashing %s (%d/%d) to address 0x%lx\n",
item->description,
current_step++,
num_steps,
item->addr);
loader_port_debug_print(user_msg);
err = _flash_file(app, item->path, item->addr);
if(err) {
break;
}
}
}
}
static int32_t wifi_marauder_flash_bin(void* context) {
WifiMarauderApp* app = (void*)context;
esp_loader_error_t err;
app->flash_worker_busy = true;
// alloc global objects
flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
@ -103,22 +140,36 @@ static int32_t wifi_marauder_flash_bin(void* context) {
loader_port_debug_print(err_msg);
}
#if 0 // still getting packet drops with this
// higher BR
if(!err) {
loader_port_debug_print("Increasing speed for faster flash\n");
err = esp_loader_change_transmission_rate(230400);
if (err != ESP_LOADER_SUCCESS) {
char err_msg[256];
snprintf(
err_msg,
sizeof(err_msg),
"Cannot change transmission rate. Error: %u\n",
err);
loader_port_debug_print(err_msg);
}
furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
}
#endif
if(!err) {
loader_port_debug_print("Connected\n");
loader_port_debug_print("Flashing bootloader (1/3)\n");
err = _flash_file(app, app->bin_file_path_boot, 0x1000);
}
if(!err) {
loader_port_debug_print("Flashing partition table (2/3)\n");
err = _flash_file(app, app->bin_file_path_part, 0x8000);
}
if(!err) {
loader_port_debug_print("Flashing app (3/3)\n");
err = _flash_file(app, app->bin_file_path_app, 0x10000);
_flash_all_files(app);
#if 0
loader_port_debug_print("Restoring transmission rate\n");
furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
#endif
loader_port_debug_print("Done flashing. Please reset the board manually.\n");
}
// done
app->flash_worker_busy = false;
// cleanup
furi_stream_buffer_free(flash_rx_stream);

View file

@ -5,6 +5,13 @@
#define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
#include "esp_loader_io.h"
#define ESP_ADDR_BOOT_S3 0x0
#define ESP_ADDR_BOOT 0x1000
#define ESP_ADDR_PART 0x8000
#define ESP_ADDR_NVS 0x9000
#define ESP_ADDR_BOOT_APP0 0xE000
#define ESP_ADDR_APP 0x10000
void wifi_marauder_flash_start_thread(WifiMarauderApp* app);
void wifi_marauder_flash_stop_thread(WifiMarauderApp* app);
void wifi_marauder_flash_handle_rx_data_cb(uint8_t* buf, size_t len, void* context);

View file

@ -4,7 +4,6 @@ App(
apptype=FlipperAppType.METAPACKAGE,
provides=[
"gpio",
"onewire",
"ibutton",
"infrared",
"lfrfid",
@ -15,23 +14,20 @@ App(
"archive",
"clock",
"subghz_remote",
"main_apps_on_start",
],
)
# Enable apps that you need in DEBUG firmware here:
App(
appid="main_apps_default",
name="Basic applications for main menu",
appid="main_apps_on_start",
name="On start hooks",
apptype=FlipperAppType.METAPACKAGE,
provides=[
# "gpio",
# "ibutton",
# "infrared",
"lfrfid",
# "nfc",
"subghz",
# "bad_usb",
# "u2f",
"archive",
"ibutton_start",
"onewire_start",
"subghz_start",
"infrared_start",
"lfrfid_start",
"nfc_start",
],
)

View file

@ -5,13 +5,14 @@
#include "../helpers/archive_browser.h"
#include "../views/archive_browser_view.h"
#include "archive/scenes/archive_scene.h"
#include <applications.h>
#define TAG "ArchiveSceneBrowser"
#define SCENE_STATE_DEFAULT (0)
#define SCENE_STATE_NEED_REFRESH (1)
const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
switch(file_type) {
case ArchiveFileTypeIButton:
return "iButton";

View file

@ -1,15 +1,12 @@
App(
appid="bad_usb",
name="Bad USB",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
entry_point="bad_usb_app",
cdefines=["APP_BAD_USB"],
requires=[
"gui",
"dialogs",
],
stack_size=2 * 1024,
icon="A_BadUsb_14",
order=70,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="USB",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

View file

@ -1,12 +1,12 @@
App(
appid="gpio",
name="GPIO",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
entry_point="gpio_app",
cdefines=["APP_GPIO"],
requires=["gui"],
stack_size=1 * 1024,
icon="A_GPIO_14",
order=50,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="GPIO",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,25 +1,21 @@
App(
appid="ibutton",
name="iButton",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
targets=["f7"],
entry_point="ibutton_app",
cdefines=["APP_IBUTTON"],
requires=[
"gui",
"dialogs",
],
provides=["ibutton_start"],
icon="A_iButton_14",
stack_size=2 * 1024,
order=60,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="iButton",
)
App(
appid="ibutton_start",
apptype=FlipperAppType.STARTUP,
targets=["f7"],
entry_point="ibutton_on_system_start",
requires=["ibutton"],
order=60,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

View file

@ -1,25 +1,21 @@
App(
appid="infrared",
name="Infrared",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
entry_point="infrared_app",
targets=["f7"],
cdefines=["APP_INFRARED"],
requires=[
"gui",
"dialogs",
],
provides=["infrared_start"],
icon="A_Infrared_14",
stack_size=3 * 1024,
order=40,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="Infrared",
)
App(
appid="infrared_start",
apptype=FlipperAppType.STARTUP,
targets=["f7"],
entry_point="infrared_on_system_start",
requires=["infrared"],
order=20,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

View file

@ -1,27 +1,21 @@
App(
appid="lfrfid",
name="125 kHz RFID",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
targets=["f7"],
entry_point="lfrfid_app",
cdefines=["APP_LF_RFID"],
requires=[
"gui",
"dialogs",
],
provides=[
"lfrfid_start",
],
icon="A_125khz_14",
stack_size=2 * 1024,
order=20,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="RFID",
)
App(
appid="lfrfid_start",
targets=["f7"],
apptype=FlipperAppType.STARTUP,
entry_point="lfrfid_on_system_start",
requires=["lfrfid"],
order=50,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

View file

@ -1,24 +1,21 @@
App(
appid="nfc",
name="NFC",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
targets=["f7"],
entry_point="nfc_app",
cdefines=["APP_NFC"],
requires=[
"gui",
"dialogs",
],
provides=["nfc_start"],
icon="A_NFC_14",
stack_size=5 * 1024,
order=30,
fap_libs=["assets"],
fap_icon="icon.png",
fap_category="NFC",
)
App(
appid="nfc_start",
targets=["f7"],
apptype=FlipperAppType.STARTUP,
entry_point="nfc_on_system_start",
requires=["nfc"],
order=30,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

View file

@ -1,14 +1,6 @@
App(
appid="onewire",
name="1-Wire",
apptype=FlipperAppType.METAPACKAGE,
provides=["onewire_start"],
)
App(
appid="onewire_start",
apptype=FlipperAppType.STARTUP,
entry_point="onewire_on_system_start",
requires=["onewire"],
order=60,
)

View file

@ -1,10 +1,9 @@
App(
appid="subghz",
name="Sub-GHz",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
targets=["f7"],
entry_point="subghz_app",
cdefines=["APP_SUBGHZ"],
requires=[
"gui",
"cli",
@ -17,13 +16,16 @@ App(
icon="A_Sub1ghz_14",
stack_size=3 * 1024,
order=10,
fap_libs=["assets", "hwdrivers"],
fap_icon="icon.png",
fap_category="Sub-GHz",
)
App(
appid="subghz_start",
targets=["f7"],
apptype=FlipperAppType.STARTUP,
entry_point="subghz_on_system_start",
requires=["subghz"],
order=40,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

View file

@ -1,15 +1,12 @@
App(
appid="u2f",
name="U2F",
apptype=FlipperAppType.APP,
apptype=FlipperAppType.MENUEXTERNAL,
entry_point="u2f_app",
cdefines=["APP_U2F"],
requires=[
"gui",
"dialogs",
],
stack_size=2 * 1024,
icon="A_U2F_14",
order=80,
fap_libs=["assets"],
fap_category="USB",
fap_icon="icon.png",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

View file

@ -17,6 +17,12 @@ typedef struct {
const FlipperInternalApplicationFlag flags;
} FlipperInternalApplication;
typedef struct {
const char* name;
const Icon* icon;
const char* path;
} FlipperExternalApplication;
typedef void (*FlipperInternalOnStartHook)(void);
extern const char* FLIPPER_AUTORUN_APP_NAME;
@ -52,3 +58,9 @@ extern const FlipperInternalApplication FLIPPER_ARCHIVE;
*/
extern const FlipperInternalApplication FLIPPER_SETTINGS_APPS[];
extern const size_t FLIPPER_SETTINGS_APPS_COUNT;
/* External Menu Apps list
* Spawned by loader
*/
extern const FlipperExternalApplication FLIPPER_EXTERNAL_APPS[];
extern const size_t FLIPPER_EXTERNAL_APPS_COUNT;

View file

@ -170,6 +170,16 @@ static const FlipperInternalApplication* loader_find_application_by_name(const c
return application;
}
static const char* loader_find_external_application_by_name(const char* app_name) {
for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
if(strcmp(FLIPPER_EXTERNAL_APPS[i].name, app_name) == 0) {
return FLIPPER_EXTERNAL_APPS[i].path;
}
}
return NULL;
}
static void loader_start_app_thread(Loader* loader, FlipperInternalApplicationFlag flags) {
// setup heap trace
FuriHalRtcHeapTrackMode mode = furi_hal_rtc_get_heap_track_mode();
@ -411,6 +421,14 @@ static LoaderStatus loader_do_start_by_name(
break;
}
// check External Applications
{
const char* path = loader_find_external_application_by_name(name);
if(path) {
name = path;
}
}
// check external apps
{
Storage* storage = furi_record_open(RECORD_STORAGE);

View file

@ -52,12 +52,18 @@ static void loader_menu_start(const char* name) {
furi_record_close(RECORD_LOADER);
}
static void loader_menu_callback(void* context, uint32_t index) {
static void loader_menu_apps_callback(void* context, uint32_t index) {
UNUSED(context);
const char* name = FLIPPER_APPS[index].name;
loader_menu_start(name);
}
static void loader_menu_external_apps_callback(void* context, uint32_t index) {
UNUSED(context);
const char* path = FLIPPER_EXTERNAL_APPS[index].path;
loader_menu_start(path);
}
static void loader_menu_applications_callback(void* context, uint32_t index) {
UNUSED(index);
UNUSED(context);
@ -89,13 +95,24 @@ static uint32_t loader_menu_exit(void* context) {
static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) {
size_t i;
for(i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
menu_add_item(
app->primary_menu,
FLIPPER_EXTERNAL_APPS[i].name,
FLIPPER_EXTERNAL_APPS[i].icon,
i,
loader_menu_external_apps_callback,
(void*)menu);
}
for(i = 0; i < FLIPPER_APPS_COUNT; i++) {
menu_add_item(
app->primary_menu,
FLIPPER_APPS[i].name,
FLIPPER_APPS[i].icon,
i,
loader_menu_callback,
loader_menu_apps_callback,
(void*)menu);
}
menu_add_item(

View file

@ -113,7 +113,9 @@ static DialogMessageButton icon1_screen(DialogsApp* dialogs, DialogMessage* mess
static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* message) {
DialogMessageButton result;
dialog_message_set_icon(message, &I_Certification2_98x33, 15, 10);
dialog_message_set_icon(message, &I_Certification2_46x33, 15, 10);
dialog_message_set_text(
message, furi_hal_version_get_mic_id(), 63, 27, AlignLeft, AlignCenter);
result = dialog_message_show(dialogs, message);
dialog_message_set_icon(message, NULL, 0, 0);

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,33.1,,
Version,+,34.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -1262,6 +1262,7 @@ Function,+,furi_hal_version_get_hw_target,uint8_t,
Function,+,furi_hal_version_get_hw_timestamp,uint32_t,
Function,+,furi_hal_version_get_hw_version,uint8_t,
Function,+,furi_hal_version_get_ic_id,const char*,
Function,+,furi_hal_version_get_mic_id,const char*,
Function,+,furi_hal_version_get_model_code,const char*,
Function,+,furi_hal_version_get_model_name,const char*,
Function,+,furi_hal_version_get_name_ptr,const char*,

1 entry status name type params
2 Version + 33.1 34.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
1262 Function + furi_hal_version_get_hw_timestamp uint32_t
1263 Function + furi_hal_version_get_hw_version uint8_t
1264 Function + furi_hal_version_get_ic_id const char*
1265 Function + furi_hal_version_get_mic_id const char*
1266 Function + furi_hal_version_get_model_code const char*
1267 Function + furi_hal_version_get_model_name const char*
1268 Function + furi_hal_version_get_name_ptr const char*

View file

@ -5,17 +5,21 @@ bool furi_hal_version_do_i_belong_here() {
}
const char* furi_hal_version_get_model_name() {
return "Komi";
return "Flipper Nano";
}
const char* furi_hal_version_get_model_code() {
return "N/A";
return "FN.1";
}
const char* furi_hal_version_get_fcc_id() {
return "N/A";
return "Pending";
}
const char* furi_hal_version_get_ic_id() {
return "N/A";
return "Pending";
}
const char* furi_hal_version_get_mic_id() {
return "Pending";
}

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,33.1,,
Version,+,34.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -147,7 +147,12 @@ Header,+,lib/mlib/m-rbtree.h,,
Header,+,lib/mlib/m-tuple.h,,
Header,+,lib/mlib/m-variant.h,,
Header,+,lib/music_worker/music_worker.h,,
Header,+,lib/nfc/helpers/mfkey32.h,,
Header,+,lib/nfc/helpers/nfc_generators.h,,
Header,+,lib/nfc/nfc_device.h,,
Header,+,lib/nfc/nfc_types.h,,
Header,+,lib/nfc/nfc_worker.h,,
Header,+,lib/nfc/parsers/nfc_supported_card.h,,
Header,+,lib/nfc/protocols/nfc_util.h,,
Header,+,lib/one_wire/maxim_crc.h,,
Header,+,lib/one_wire/one_wire_host.h,,
@ -1456,6 +1461,7 @@ Function,+,furi_hal_version_get_hw_target,uint8_t,
Function,+,furi_hal_version_get_hw_timestamp,uint32_t,
Function,+,furi_hal_version_get_hw_version,uint8_t,
Function,+,furi_hal_version_get_ic_id,const char*,
Function,+,furi_hal_version_get_mic_id,const char*,
Function,+,furi_hal_version_get_model_code,const char*,
Function,+,furi_hal_version_get_model_name,const char*,
Function,+,furi_hal_version_get_name_ptr,const char*,
@ -1967,40 +1973,40 @@ Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint6
Function,-,mf_classic_authenticate_skip_activate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t"
Function,-,mf_classic_block_to_value,_Bool,"const uint8_t*, int32_t*, uint8_t*"
Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*"
Function,+,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType
Function,-,mf_classic_dict_check_presence,_Bool,MfClassicDictType
Function,-,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t"
Function,+,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType
Function,+,mf_classic_dict_check_presence,_Bool,MfClassicDictType
Function,+,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t"
Function,-,mf_classic_dict_find_index,_Bool,"MfClassicDict*, uint8_t*, uint32_t*"
Function,-,mf_classic_dict_find_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t*"
Function,-,mf_classic_dict_free,void,MfClassicDict*
Function,+,mf_classic_dict_free,void,MfClassicDict*
Function,-,mf_classic_dict_get_key_at_index,_Bool,"MfClassicDict*, uint64_t*, uint32_t"
Function,-,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t"
Function,+,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t"
Function,-,mf_classic_dict_get_next_key,_Bool,"MfClassicDict*, uint64_t*"
Function,-,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict*
Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*"
Function,+,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,+,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict*
Function,+,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict*
Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool"
Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t"
Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*"
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
Function,+,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*"
Function,+,mf_classic_get_sector_by_block,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
Function,+,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
Function,+,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
Function,-,mf_classic_get_type_str,const char*,MfClassicType
Function,-,mf_classic_halt,void,"FuriHalNfcTxRxContext*, Crypto1*"
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_card_read,_Bool,MfClassicData*
Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey"
Function,+,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t"
Function,+,mf_classic_is_card_read,_Bool,MfClassicData*
Function,+,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey"
Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t
Function,+,mf_classic_is_sector_trailer,_Bool,uint8_t
Function,-,mf_classic_is_value_block,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_read_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*"
Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*"
@ -2018,10 +2024,10 @@ Function,-,mf_classic_value_to_block,void,"int32_t, uint8_t, uint8_t*"
Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*"
Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t"
Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*"
Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*"
Function,-,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*"
Function,+,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*"
Function,+,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*"
Function,-,mf_df_cat_data,void,"MifareDesfireData*, FuriString*"
Function,-,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*"
Function,+,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*"
Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*"
Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*"
Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*"
@ -2051,8 +2057,8 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin
Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]"
Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*"
Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData*
Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData*
Function,+,mf_ul_emulation_supported,_Bool,MfUltralightData*
Function,+,mf_ul_is_full_capture,_Bool,MfUltralightData*
Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*"
Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*"
Function,-,mf_ul_pwdgen_amiibo,uint32_t,FuriHalNfcDevData*
@ -2062,13 +2068,18 @@ Function,-,mf_ul_reset,void,MfUltralightData*
Function,-,mf_ul_reset_emulation,void,"MfUltralightEmulator*, _Bool"
Function,-,mf_ultralight_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint32_t, uint16_t*"
Function,-,mf_ultralight_fast_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData*
Function,+,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData*
Function,-,mf_ultralight_read_counters,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mf_ultralight_read_pages_direct,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint8_t*"
Function,-,mf_ultralight_read_signature,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_tearing_flags,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_version,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mfkey32_alloc,Mfkey32*,uint32_t
Function,-,mfkey32_free,void,Mfkey32*
Function,+,mfkey32_get_auth_sectors,uint16_t,FuriString*
Function,-,mfkey32_process_data,void,"Mfkey32*, uint8_t*, uint16_t, _Bool, _Bool"
Function,-,mfkey32_set_callback,void,"Mfkey32*, Mfkey32ParseDataCallback, void*"
Function,-,mkdtemp,char*,char*
Function,-,mkostemp,int,"char*, int"
Function,-,mkostemps,int,"char*, int, int"
@ -2117,11 +2128,25 @@ Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*"
Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*"
Function,+,nfc_device_set_name,void,"NfcDevice*, const char*"
Function,+,nfc_file_select,_Bool,NfcDevice*
Function,-,nfc_generate_mf_classic,void,"NfcDeviceData*, uint8_t, MfClassicType"
Function,+,nfc_get_dev_type,const char*,FuriHalNfcType
Function,-,nfc_guess_protocol,const char*,NfcProtocol
Function,+,nfc_mf_classic_type,const char*,MfClassicType
Function,+,nfc_mf_ul_type,const char*,"MfUltralightType, _Bool"
Function,+,nfc_supported_card_verify_and_parse,_Bool,NfcDeviceData*
Function,+,nfc_util_bytes2num,uint64_t,"const uint8_t*, uint8_t"
Function,+,nfc_util_even_parity32,uint8_t,uint32_t
Function,+,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*"
Function,+,nfc_util_odd_parity,void,"const uint8_t*, uint8_t*, uint8_t"
Function,+,nfc_util_odd_parity8,uint8_t,uint8_t
Function,+,nfc_worker_alloc,NfcWorker*,
Function,+,nfc_worker_free,void,NfcWorker*
Function,+,nfc_worker_get_state,NfcWorkerState,NfcWorker*
Function,-,nfc_worker_nfcv_emulate,void,NfcWorker*
Function,-,nfc_worker_nfcv_sniff,void,NfcWorker*
Function,-,nfc_worker_nfcv_unlock,void,NfcWorker*
Function,+,nfc_worker_start,void,"NfcWorker*, NfcWorkerState, NfcDeviceData*, NfcWorkerCallback, void*"
Function,+,nfc_worker_stop,void,NfcWorker*
Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t"
Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*"
Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t"
@ -2699,6 +2724,7 @@ Function,-,strupr,char*,char*
Function,-,strverscmp,int,"const char*, const char*"
Function,-,strxfrm,size_t,"char*, const char*, size_t"
Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t"
Function,-,stub_parser_verify_read,_Bool,"NfcWorker*, FuriHalNfcTxRxContext*"
Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*"
Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t"
Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*"
@ -3401,6 +3427,8 @@ Variable,+,message_red_255,const NotificationMessage,
Variable,+,message_sound_off,const NotificationMessage,
Variable,+,message_vibro_off,const NotificationMessage,
Variable,+,message_vibro_on,const NotificationMessage,
Variable,+,nfc_generators,const NfcGenerator*[],
Variable,-,nfc_supported_card,NfcSupportedCard[NfcSupportedCardTypeEnd],
Variable,+,sequence_audiovisual_alert,const NotificationSequence,
Variable,+,sequence_blink_blue_10,const NotificationSequence,
Variable,+,sequence_blink_blue_100,const NotificationSequence,

1 entry status name type params
2 Version + 33.1 34.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
147 Header + lib/mlib/m-tuple.h
148 Header + lib/mlib/m-variant.h
149 Header + lib/music_worker/music_worker.h
150 Header + lib/nfc/helpers/mfkey32.h
151 Header + lib/nfc/helpers/nfc_generators.h
152 Header + lib/nfc/nfc_device.h
153 Header + lib/nfc/nfc_types.h
154 Header + lib/nfc/nfc_worker.h
155 Header + lib/nfc/parsers/nfc_supported_card.h
156 Header + lib/nfc/protocols/nfc_util.h
157 Header + lib/one_wire/maxim_crc.h
158 Header + lib/one_wire/one_wire_host.h
1461 Function + furi_hal_version_get_hw_timestamp uint32_t
1462 Function + furi_hal_version_get_hw_version uint8_t
1463 Function + furi_hal_version_get_ic_id const char*
1464 Function + furi_hal_version_get_mic_id const char*
1465 Function + furi_hal_version_get_model_code const char*
1466 Function + furi_hal_version_get_model_name const char*
1467 Function + furi_hal_version_get_name_ptr const char*
1973 Function - mf_classic_authenticate_skip_activate _Bool FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t
1974 Function - mf_classic_block_to_value _Bool const uint8_t*, int32_t*, uint8_t*
1975 Function - mf_classic_check_card_type _Bool uint8_t, uint8_t, uint8_t
1976 Function - + mf_classic_dict_add_key _Bool MfClassicDict*, uint8_t*
1977 Function - mf_classic_dict_add_key_str _Bool MfClassicDict*, FuriString*
1978 Function - + mf_classic_dict_alloc MfClassicDict* MfClassicDictType
1979 Function - + mf_classic_dict_check_presence _Bool MfClassicDictType
1980 Function - + mf_classic_dict_delete_index _Bool MfClassicDict*, uint32_t
1981 Function - mf_classic_dict_find_index _Bool MfClassicDict*, uint8_t*, uint32_t*
1982 Function - mf_classic_dict_find_index_str _Bool MfClassicDict*, FuriString*, uint32_t*
1983 Function - + mf_classic_dict_free void MfClassicDict*
1984 Function - mf_classic_dict_get_key_at_index _Bool MfClassicDict*, uint64_t*, uint32_t
1985 Function - + mf_classic_dict_get_key_at_index_str _Bool MfClassicDict*, FuriString*, uint32_t
1986 Function - mf_classic_dict_get_next_key _Bool MfClassicDict*, uint64_t*
1987 Function - + mf_classic_dict_get_next_key_str _Bool MfClassicDict*, FuriString*
1988 Function - + mf_classic_dict_get_total_keys uint32_t MfClassicDict*
1989 Function - + mf_classic_dict_is_key_present _Bool MfClassicDict*, uint8_t*
1990 Function - mf_classic_dict_is_key_present_str _Bool MfClassicDict*, FuriString*
1991 Function - mf_classic_dict_rewind _Bool MfClassicDict*
1992 Function - mf_classic_emulator _Bool MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool
1993 Function - mf_classic_get_classic_type MfClassicType uint8_t, uint8_t, uint8_t
1994 Function - + mf_classic_get_read_sectors_and_keys void MfClassicData*, uint8_t*, uint8_t*
1995 Function - + mf_classic_get_sector_by_block uint8_t uint8_t
1996 Function - mf_classic_get_sector_trailer_block_num_by_sector uint8_t uint8_t
1997 Function - + mf_classic_get_sector_trailer_by_sector MfClassicSectorTrailer* MfClassicData*, uint8_t
1998 Function - mf_classic_get_total_block_num uint16_t MfClassicType
1999 Function - + mf_classic_get_total_sectors_num uint8_t MfClassicType
2000 Function - mf_classic_get_type_str const char* MfClassicType
2001 Function - mf_classic_halt void FuriHalNfcTxRxContext*, Crypto1*
2002 Function - mf_classic_is_allowed_access_data_block _Bool MfClassicData*, uint8_t, MfClassicKey, MfClassicAction
2003 Function - mf_classic_is_allowed_access_sector_trailer _Bool MfClassicData*, uint8_t, MfClassicKey, MfClassicAction
2004 Function - + mf_classic_is_block_read _Bool MfClassicData*, uint8_t
2005 Function - + mf_classic_is_card_read _Bool MfClassicData*
2006 Function - + mf_classic_is_key_found _Bool MfClassicData*, uint8_t, MfClassicKey
2007 Function - mf_classic_is_sector_data_read _Bool MfClassicData*, uint8_t
2008 Function - mf_classic_is_sector_read _Bool MfClassicData*, uint8_t
2009 Function - + mf_classic_is_sector_trailer _Bool uint8_t
2010 Function - mf_classic_is_value_block _Bool MfClassicData*, uint8_t
2011 Function - mf_classic_read_block _Bool FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*
2012 Function - mf_classic_read_card uint8_t FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*
2024 Function - mf_classic_write_block _Bool FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*
2025 Function - mf_classic_write_sector _Bool FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t
2026 Function - mf_df_cat_application void MifareDesfireApplication*, FuriString*
2027 Function - + mf_df_cat_application_info void MifareDesfireApplication*, FuriString*
2028 Function - + mf_df_cat_card_info void MifareDesfireData*, FuriString*
2029 Function - mf_df_cat_data void MifareDesfireData*, FuriString*
2030 Function - + mf_df_cat_file void MifareDesfireFile*, FuriString*
2031 Function - mf_df_cat_free_mem void MifareDesfireFreeMemory*, FuriString*
2032 Function - mf_df_cat_key_settings void MifareDesfireKeySettings*, FuriString*
2033 Function - mf_df_cat_version void MifareDesfireVersion*, FuriString*
2057 Function - mf_df_prepare_select_application uint16_t uint8_t*, uint8_t[3]
2058 Function - mf_df_read_card _Bool FuriHalNfcTxRxContext*, MifareDesfireData*
2059 Function - mf_ul_check_card_type _Bool uint8_t, uint8_t, uint8_t
2060 Function - + mf_ul_emulation_supported _Bool MfUltralightData*
2061 Function - + mf_ul_is_full_capture _Bool MfUltralightData*
2062 Function - mf_ul_prepare_emulation void MfUltralightEmulator*, MfUltralightData*
2063 Function - mf_ul_prepare_emulation_response _Bool uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*
2064 Function - mf_ul_pwdgen_amiibo uint32_t FuriHalNfcDevData*
2068 Function - mf_ul_reset_emulation void MfUltralightEmulator*, _Bool
2069 Function - mf_ultralight_authenticate _Bool FuriHalNfcTxRxContext*, uint32_t, uint16_t*
2070 Function - mf_ultralight_fast_read_pages _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
2071 Function - + mf_ultralight_get_config_pages MfUltralightConfigPages* MfUltralightData*
2072 Function - mf_ultralight_read_counters _Bool FuriHalNfcTxRxContext*, MfUltralightData*
2073 Function - mf_ultralight_read_pages _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
2074 Function - mf_ultralight_read_pages_direct _Bool FuriHalNfcTxRxContext*, uint8_t, uint8_t*
2075 Function - mf_ultralight_read_signature _Bool FuriHalNfcTxRxContext*, MfUltralightData*
2076 Function - mf_ultralight_read_tearing_flags _Bool FuriHalNfcTxRxContext*, MfUltralightData*
2077 Function - mf_ultralight_read_version _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
2078 Function - mfkey32_alloc Mfkey32* uint32_t
2079 Function - mfkey32_free void Mfkey32*
2080 Function + mfkey32_get_auth_sectors uint16_t FuriString*
2081 Function - mfkey32_process_data void Mfkey32*, uint8_t*, uint16_t, _Bool, _Bool
2082 Function - mfkey32_set_callback void Mfkey32*, Mfkey32ParseDataCallback, void*
2083 Function - mkdtemp char* char*
2084 Function - mkostemp int char*, int
2085 Function - mkostemps int char*, int, int
2128 Function + nfc_device_set_loading_callback void NfcDevice*, NfcLoadingCallback, void*
2129 Function + nfc_device_set_name void NfcDevice*, const char*
2130 Function + nfc_file_select _Bool NfcDevice*
2131 Function - nfc_generate_mf_classic void NfcDeviceData*, uint8_t, MfClassicType
2132 Function + nfc_get_dev_type const char* FuriHalNfcType
2133 Function - nfc_guess_protocol const char* NfcProtocol
2134 Function + nfc_mf_classic_type const char* MfClassicType
2135 Function + nfc_mf_ul_type const char* MfUltralightType, _Bool
2136 Function + nfc_supported_card_verify_and_parse _Bool NfcDeviceData*
2137 Function + nfc_util_bytes2num uint64_t const uint8_t*, uint8_t
2138 Function + nfc_util_even_parity32 uint8_t uint32_t
2139 Function + nfc_util_num2bytes void uint64_t, uint8_t, uint8_t*
2140 Function + nfc_util_odd_parity void const uint8_t*, uint8_t*, uint8_t
2141 Function + nfc_util_odd_parity8 uint8_t uint8_t
2142 Function + nfc_worker_alloc NfcWorker*
2143 Function + nfc_worker_free void NfcWorker*
2144 Function + nfc_worker_get_state NfcWorkerState NfcWorker*
2145 Function - nfc_worker_nfcv_emulate void NfcWorker*
2146 Function - nfc_worker_nfcv_sniff void NfcWorker*
2147 Function - nfc_worker_nfcv_unlock void NfcWorker*
2148 Function + nfc_worker_start void NfcWorker*, NfcWorkerState, NfcDeviceData*, NfcWorkerCallback, void*
2149 Function + nfc_worker_stop void NfcWorker*
2150 Function - nfca_append_crc16 void uint8_t*, uint16_t
2151 Function - nfca_emulation_handler _Bool uint8_t*, uint16_t, uint8_t*, uint16_t*
2152 Function - nfca_get_crc16 uint16_t uint8_t*, uint16_t
2724 Function - strverscmp int const char*, const char*
2725 Function - strxfrm size_t char*, const char*, size_t
2726 Function - strxfrm_l size_t char*, const char*, size_t, locale_t
2727 Function - stub_parser_verify_read _Bool NfcWorker*, FuriHalNfcTxRxContext*
2728 Function + subghz_block_generic_deserialize SubGhzProtocolStatus SubGhzBlockGeneric*, FlipperFormat*
2729 Function + subghz_block_generic_deserialize_check_count_bit SubGhzProtocolStatus SubGhzBlockGeneric*, FlipperFormat*, uint16_t
2730 Function + subghz_block_generic_get_preset_name void const char*, FuriString*
3427 Variable + message_sound_off const NotificationMessage
3428 Variable + message_vibro_off const NotificationMessage
3429 Variable + message_vibro_on const NotificationMessage
3430 Variable + nfc_generators const NfcGenerator*[]
3431 Variable - nfc_supported_card NfcSupportedCard[NfcSupportedCardTypeEnd]
3432 Variable + sequence_audiovisual_alert const NotificationSequence
3433 Variable + sequence_blink_blue_10 const NotificationSequence
3434 Variable + sequence_blink_blue_100 const NotificationSequence

View file

@ -19,3 +19,7 @@ const char* furi_hal_version_get_fcc_id() {
const char* furi_hal_version_get_ic_id() {
return "27624-FZ";
}
const char* furi_hal_version_get_mic_id() {
return "210-175991";
}

View file

@ -87,6 +87,12 @@ const char* furi_hal_version_get_fcc_id();
*/
const char* furi_hal_version_get_ic_id();
/** Get MIC id
*
* @return MIC id as C-string
*/
const char* furi_hal_version_get_mic_id();
/** Get OTP version
*
* @return OTP Version

View file

@ -6,6 +6,11 @@ env.Append(
],
SDK_HEADERS=[
File("nfc_device.h"),
File("nfc_worker.h"),
File("nfc_types.h"),
File("helpers/mfkey32.h"),
File("parsers/nfc_supported_card.h"),
File("helpers/nfc_generators.h"),
File("protocols/nfc_util.h"),
],
)

View file

@ -6,6 +6,10 @@
#include <lib/toolbox/stream/file_stream.h>
#include <lib/toolbox/stream/buffered_file_stream.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MfClassicDictTypeUser,
MfClassicDictTypeSystem,
@ -97,3 +101,7 @@ bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32
* @return true on success
*/
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);
#ifdef __cplusplus
}
#endif

View file

@ -2,6 +2,10 @@
#include <lib/nfc/protocols/mifare_classic.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Mfkey32 Mfkey32;
typedef enum {
@ -24,3 +28,7 @@ void mfkey32_process_data(
void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context);
uint16_t mfkey32_get_auth_sectors(FuriString* string);
#ifdef __cplusplus
}
#endif

View file

@ -2,6 +2,10 @@
#include "nfc_device.h"
#ifdef __cplusplus
extern "C" {
#endif
const char* nfc_get_dev_type(FuriHalNfcType type);
const char* nfc_guess_protocol(NfcProtocol protocol);
@ -9,3 +13,7 @@ const char* nfc_guess_protocol(NfcProtocol protocol);
const char* nfc_mf_ul_type(MfUltralightType type, bool full_name);
const char* nfc_mf_classic_type(MfClassicType type);
#ifdef __cplusplus
}
#endif

View file

@ -2,6 +2,10 @@
#include "nfc_device.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct NfcWorker NfcWorker;
typedef enum {
@ -98,4 +102,8 @@ void nfc_worker_start(
void nfc_worker_stop(NfcWorker* nfc_worker);
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker);
void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker);
void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker);
#ifdef __cplusplus
}
#endif

View file

@ -4,6 +4,10 @@
#include "../nfc_worker.h"
#include "../nfc_device.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
NfcSupportedCardTypePlantain,
NfcSupportedCardTypeTroika,
@ -37,3 +41,7 @@ bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data);
// support the card. This is needed for DESFire card parsers which can't
// provide keys, and only use NfcSupportedCard->parse.
bool stub_parser_verify_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
#ifdef __cplusplus
}
#endif

View file

@ -3,6 +3,10 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t odd;
uint32_t even;
@ -35,3 +39,7 @@ void crypto1_encrypt(
uint16_t plain_data_bits,
uint8_t* encrypted_data,
uint8_t* encrypted_parity);
#ifdef __cplusplus
}
#endif

View file

@ -4,6 +4,10 @@
#include "crypto1.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MF_CLASSIC_BLOCK_SIZE (16)
#define MF_CLASSIC_TOTAL_BLOCKS_MAX (256)
#define MF_MINI_TOTAL_SECTORS_NUM (5)
@ -241,3 +245,7 @@ bool mf_classic_write_sector(
MfClassicData* dest_data,
MfClassicData* src_data,
uint8_t sec_num);
#ifdef __cplusplus
}
#endif

View file

@ -5,6 +5,10 @@
#include <furi_hal_nfc.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MF_DF_GET_VERSION (0x60)
#define MF_DF_GET_FREE_MEMORY (0x6E)
#define MF_DF_GET_KEY_SETTINGS (0x45)
@ -169,3 +173,7 @@ uint16_t mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t off
bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out);
bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data);
#ifdef __cplusplus
}
#endif

View file

@ -2,6 +2,10 @@
#include <furi_hal_nfc.h>
#ifdef __cplusplus
extern "C" {
#endif
// Largest tag is NTAG I2C Plus 2K, both data sectors plus SRAM
#define MF_UL_MAX_DUMP_SIZE ((238 + 256 + 16) * 4)
@ -259,3 +263,7 @@ uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data);
uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data);
bool mf_ul_is_full_capture(MfUltralightData* data);
#ifdef __cplusplus
}
#endif

View file

@ -18,6 +18,7 @@ class FlipperAppType(Enum):
SETTINGS = "Settings"
STARTUP = "StartupHook"
EXTERNAL = "External"
MENUEXTERNAL = "MenuExternal"
METAPACKAGE = "Package"
PLUGIN = "Plugin"
@ -213,7 +214,7 @@ class AppBuildset:
appmgr: AppManager,
appnames: List[str],
hw_target: str,
message_writer: Callable = None,
message_writer: Callable | None = None,
):
self.appmgr = appmgr
self.appnames = set(appnames)
@ -367,6 +368,11 @@ class ApplicationsCGenerator:
),
}
APP_EXTERNAL_TYPE = (
"FlipperExternalApplication",
"FLIPPER_EXTERNAL_APPS",
)
def __init__(self, buildset: AppBuildset, autorun_app: str = ""):
self.buildset = buildset
self.autorun = autorun_app
@ -387,6 +393,17 @@ class ApplicationsCGenerator:
.icon = {f"&{app.icon}" if app.icon else "NULL"},
.flags = {'|'.join(f"FlipperInternalApplicationFlag{flag}" for flag in app.flags)} }}"""
def get_external_app_descr(self, app: FlipperApplication):
app_path = "/ext/apps"
if app.fap_category:
app_path += f"/{app.fap_category}"
app_path += f"/{app.appid}.fap"
return f"""
{{
.name = "{app.name}",
.icon = {f"&{app.icon}" if app.icon else "NULL"},
.path = "{app_path}" }}"""
def generate(self):
contents = [
'#include "applications.h"',
@ -418,4 +435,11 @@ class ApplicationsCGenerator:
]
)
entry_type, entry_block = self.APP_EXTERNAL_TYPE
external_apps = self.buildset.get_apps_of_type(FlipperAppType.MENUEXTERNAL)
contents.append(f"const {entry_type} {entry_block}[] = {{")
contents.append(",\n".join(map(self.get_external_app_descr, external_apps)))
contents.append("};")
contents.append(f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});")
return "\n".join(contents)

View file

@ -423,7 +423,10 @@ def AddAppLaunchTarget(env, appname, launch_target_name):
host_app = env["APPMGR"].get(artifacts_app_to_run.app.requires[0])
if host_app:
if host_app.apptype == FlipperAppType.EXTERNAL:
if host_app.apptype in [
FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL,
]:
_add_host_app_to_targets(host_app)
else:
# host app is a built-in app

View file

@ -262,6 +262,7 @@ apps_artifacts = appenv["EXT_APPS"]
apps_to_build_as_faps = [
FlipperAppType.PLUGIN,
FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL,
]
known_extapps = [

View file

@ -67,6 +67,7 @@ class FlipperExtAppBuildArtifacts:
apps_to_build_as_faps = [
FlipperAppType.PLUGIN,
FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL,
FlipperAppType.DEBUG,
]