Merge branch 'ul-dev' into xfw-dev

This commit is contained in:
Willy-JL
2023-03-17 23:52:05 +00:00
171 changed files with 3395 additions and 1252 deletions

4
.gitmodules vendored
View File

@@ -28,6 +28,6 @@
[submodule "lib/cxxheaderparser"]
path = lib/cxxheaderparser
url = https://github.com/robotpy/cxxheaderparser.git
[submodule "applications/plugins/dap_link/lib/free-dap"]
path = applications/plugins/dap_link/lib/free-dap
[submodule "applications/external/dap_link/lib/free-dap"]
path = applications/external/dap_link/lib/free-dap
url = https://github.com/ataradov/free-dap.git

View File

@@ -1 +1 @@
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/external/dap_link/lib/free-dap

View File

@@ -139,34 +139,33 @@ if GetOption("fullenv") or any(
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
distenv.Default(basic_dist)
dist_dir = distenv.GetProjectDirName()
dist_dir_name = distenv.GetProjectDirName()
dist_dir = distenv.Dir(f"#/dist/{dist_dir_name}")
external_apps_artifacts = firmware_env["FW_EXTAPPS"]
external_app_list = external_apps_artifacts.application_map.values()
fap_dist = [
distenv.Install(
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
list(
app_artifact.debug
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
dist_dir.Dir("debug_elf"),
list(app_artifact.debug for app_artifact in external_app_list),
),
*(
distenv.Install(
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
app_artifact.compact[0],
dist_dir.File(dist_entry[1]).dir,
app_artifact.compact,
)
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
for app_artifact in external_app_list
for dist_entry in app_artifact.dist_entries
),
]
Depends(
fap_dist,
list(
app_artifact.validator
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
list(app_artifact.validator for app_artifact in external_app_list),
)
Alias("fap_dist", fap_dist)
# distenv.Default(fap_dist)
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
distenv.Depends(firmware_env["FW_RESOURCES"], external_apps_artifacts.resources_dist)
# Copy all faps to device

View File

@@ -36,15 +36,20 @@ Applications for main Flipper menu.
- `u2f` - U2F Application
## plugins
## External
Extra apps for Plugins & App Loader menus.
External applications deployed to SD Card
- `bt_hid_app` - BT Remote controller
- `clock` - Clock application
- `dap_link` - DAP Link OnChip debugger
- `hid_app` - USB/BT Remote controller
- `music_player` - Music player app (demo)
- `picopass` - Picopass tool
- `nfc_magic` - NFC MFC Magic card application
- `picopass` - Picopass reader / writer
- `signal_generator` - Signal generator app: PWM and clock generator
- `snake_game` - Snake game application
- `spi_mem_manager` - SPI Memory reader / flasher
- `weather_station` - SubGHz weather station
## services

View File

@@ -7,6 +7,6 @@ App(
requires=["gui"],
stack_size=1 * 1024,
order=60,
fap_icon="../../plugins/mousejacker/mouse_10px.png",
fap_icon="../../external/mousejacker/mouse_10px.png",
fap_category="Debug",
)

View File

@@ -1,3 +1,4 @@
# Placeholder
App(
appid="example_apps",
name="Example apps bundle",

View File

@@ -0,0 +1,31 @@
App(
appid="example_plugins",
name="Example: App w/plugin",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_plugins_app",
stack_size=2 * 1024,
fap_category="Examples",
)
App(
appid="example_plugins_multi",
name="Example: App w/plugins",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_plugins_multi_app",
stack_size=2 * 1024,
fap_category="Examples",
)
App(
appid="example_plugin1",
apptype=FlipperAppType.PLUGIN,
entry_point="example_plugin1_ep",
requires=["example_plugins", "example_plugins_multi"],
)
App(
appid="example_plugin2",
apptype=FlipperAppType.PLUGIN,
entry_point="example_plugin2_ep",
requires=["example_plugins_multi"],
)

View File

@@ -0,0 +1,70 @@
/*
* An example of a plugin host application.
* Loads a single plugin and calls its methods.
*/
#include "plugin_interface.h"
#include <furi.h>
#include <flipper_application/flipper_application.h>
#include <loader/firmware_api/firmware_api.h>
#include <storage/storage.h>
#define TAG "example_plugins"
int32_t example_plugins_app(void* p) {
UNUSED(p);
FURI_LOG_I(TAG, "Starting");
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
do {
FlipperApplicationPreloadStatus preload_res =
flipper_application_preload(app, APP_DATA_PATH("plugins/example_plugin1.fal"));
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
FURI_LOG_E(TAG, "Failed to preload plugin");
break;
}
if(!flipper_application_is_plugin(app)) {
FURI_LOG_E(TAG, "Plugin file is not a library");
break;
}
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(app);
if(load_status != FlipperApplicationLoadStatusSuccess) {
FURI_LOG_E(TAG, "Failed to load plugin file");
break;
}
const FlipperAppPluginDescriptor* app_descriptor =
flipper_application_plugin_get_descriptor(app);
FURI_LOG_I(
TAG,
"Loaded plugin for appid '%s', API %lu",
app_descriptor->appid,
app_descriptor->ep_api_version);
furi_check(app_descriptor->ep_api_version == PLUGIN_API_VERSION);
furi_check(strcmp(app_descriptor->appid, PLUGIN_APP_ID) == 0);
const ExamplePlugin* plugin = app_descriptor->entry_point;
FURI_LOG_I(TAG, "Plugin name: %s", plugin->name);
FURI_LOG_I(TAG, "Plugin method1: %d", plugin->method1());
FURI_LOG_I(TAG, "Plugin method2(7,8): %d", plugin->method2(7, 8));
FURI_LOG_I(TAG, "Plugin method2(1337,228): %d", plugin->method2(1337, 228));
} while(false);
flipper_application_free(app);
furi_record_close(RECORD_STORAGE);
FURI_LOG_I(TAG, "Goodbye!");
return 0;
}

View File

@@ -0,0 +1,43 @@
/*
* An example of an advanced plugin host application.
* It uses PluginManager to load all plugins from a directory
*/
#include "plugin_interface.h"
#include <flipper_application/flipper_application.h>
#include <flipper_application/plugins/plugin_manager.h>
#include <loader/firmware_api/firmware_api.h>
#include <furi.h>
#define TAG "example_plugins"
int32_t example_plugins_multi_app(void* p) {
UNUSED(p);
FURI_LOG_I(TAG, "Starting");
PluginManager* manager =
plugin_manager_alloc(PLUGIN_APP_ID, PLUGIN_API_VERSION, firmware_api_interface);
if(plugin_manager_load_all(manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) {
FURI_LOG_E(TAG, "Failed to load all libs");
return 0;
}
uint32_t plugin_count = plugin_manager_get_count(manager);
FURI_LOG_I(TAG, "Loaded %lu plugin(s)", plugin_count);
for(uint32_t i = 0; i < plugin_count; i++) {
const ExamplePlugin* plugin = plugin_manager_get_ep(manager, i);
FURI_LOG_I(TAG, "plugin name: %s", plugin->name);
FURI_LOG_I(TAG, "plugin method1: %d", plugin->method1());
FURI_LOG_I(TAG, "plugin method2(7,8): %d", plugin->method2(7, 8));
}
plugin_manager_free(manager);
FURI_LOG_I(TAG, "Goodbye!");
return 0;
}

View File

@@ -0,0 +1,32 @@
/* A simple plugin implementing example_plugins application's plugin interface */
#include "plugin_interface.h"
#include <flipper_application/flipper_application.h>
static int example_plugin1_method1() {
return 42;
}
static int example_plugin1_method2(int arg1, int arg2) {
return arg1 + arg2;
}
/* Actual implementation of app<>plugin interface */
static const ExamplePlugin example_plugin1 = {
.name = "Demo App Plugin 1",
.method1 = &example_plugin1_method1,
.method2 = &example_plugin1_method2,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor example_plugin1_descriptor = {
.appid = PLUGIN_APP_ID,
.ep_api_version = PLUGIN_API_VERSION,
.entry_point = &example_plugin1,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* example_plugin1_ep() {
return &example_plugin1_descriptor;
}

View File

@@ -0,0 +1,32 @@
/* Second plugin implementing example_plugins application's plugin interface */
#include "plugin_interface.h"
#include <flipper_application/flipper_application.h>
static int example_plugin2_method1() {
return 1337;
}
static int example_plugin2_method2(int arg1, int arg2) {
return arg1 - arg2;
}
/* Actual implementation of app<>plugin interface */
static const ExamplePlugin example_plugin2 = {
.name = "Demo App Plugin 2",
.method1 = &example_plugin2_method1,
.method2 = &example_plugin2_method2,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor example_plugin2_descriptor = {
.appid = PLUGIN_APP_ID,
.ep_api_version = PLUGIN_API_VERSION,
.entry_point = &example_plugin2,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* example_plugin2_ep() {
return &example_plugin2_descriptor;
}

View File

@@ -0,0 +1,12 @@
#pragma once
/* Common interface between a plugin and host applicaion */
#define PLUGIN_APP_ID "example_plugins"
#define PLUGIN_API_VERSION 1
typedef struct {
const char* name;
int (*method1)();
int (*method2)(int, int);
} ExamplePlugin;

View File

@@ -0,0 +1,25 @@
#include "app_api.h"
/* Actual implementation of app's API and its private state */
static uint32_t accumulator = 0;
void app_api_accumulator_set(uint32_t value) {
accumulator = value;
}
uint32_t app_api_accumulator_get() {
return accumulator;
}
void app_api_accumulator_add(uint32_t value) {
accumulator += value;
}
void app_api_accumulator_sub(uint32_t value) {
accumulator -= value;
}
void app_api_accumulator_mul(uint32_t value) {
accumulator *= value;
}

View File

@@ -0,0 +1,25 @@
#pragma once
/*
* This file contains an API that is internally implemented by the application
* It is also exposed to plugins to allow them to use the application's API.
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void app_api_accumulator_set(uint32_t value);
uint32_t app_api_accumulator_get();
void app_api_accumulator_add(uint32_t value);
void app_api_accumulator_sub(uint32_t value);
void app_api_accumulator_mul(uint32_t value);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,9 @@
#pragma once
#include <flipper_application/api_hashtable/api_hashtable.h>
/*
* Resolver interface with private application's symbols.
* Implementation is contained in app_api_table.c
*/
extern const ElfApiInterface* const application_api_interface;

View File

@@ -0,0 +1,27 @@
#include <flipper_application/api_hashtable/api_hashtable.h>
#include <flipper_application/api_hashtable/compilesort.hpp>
/*
* This file contains an implementation of a symbol table
* with private app's symbols. It is used by composite API resolver
* to load plugins that use internal application's APIs.
*/
#include "app_api_table_i.h"
static_assert(!has_hash_collisions(app_api_table), "Detected API method hash collision!");
constexpr HashtableApiInterface applicaton_hashtable_api_interface{
{
.api_version_major = 0,
.api_version_minor = 0,
/* generic resolver using pre-sorted array */
.resolver_callback = &elf_resolve_from_hashtable,
},
/* pointers to application's API table boundaries */
.table_cbegin = app_api_table.cbegin(),
.table_cend = app_api_table.cend(),
};
/* Casting to generic resolver to use in Composite API resolver */
extern "C" const ElfApiInterface* const application_api_interface =
&applicaton_hashtable_api_interface;

View File

@@ -0,0 +1,13 @@
#include "app_api.h"
/*
* A list of app's private functions and objects to expose for plugins.
* It is used to generate a table of symbols for import resolver to use.
* TBD: automatically generate this table from app's header files
*/
static constexpr auto app_api_table = sort(create_array_t<sym_entry>(
API_METHOD(app_api_accumulator_set, void, (uint32_t)),
API_METHOD(app_api_accumulator_get, uint32_t, ()),
API_METHOD(app_api_accumulator_add, void, (uint32_t)),
API_METHOD(app_api_accumulator_sub, void, (uint32_t)),
API_METHOD(app_api_accumulator_mul, void, (uint32_t))));

View File

@@ -0,0 +1,24 @@
App(
appid="example_advanced_plugins",
name="Example: advanced plugins",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_advanced_plugins_app",
stack_size=2 * 1024,
fap_category="Examples",
)
App(
appid="advanced_plugin1",
apptype=FlipperAppType.PLUGIN,
entry_point="advanced_plugin1_ep",
requires=["example_advanced_plugins"],
sources=["plugin1.c"],
)
App(
appid="advanced_plugin2",
apptype=FlipperAppType.PLUGIN,
entry_point="advanced_plugin2_ep",
requires=["example_advanced_plugins"],
sources=["plugin2.c"],
)

View File

@@ -0,0 +1,48 @@
#include "app_api.h"
#include "plugin_interface.h"
#include "app_api_interface.h"
#include <flipper_application/flipper_application.h>
#include <flipper_application/plugins/plugin_manager.h>
#include <flipper_application/plugins/composite_resolver.h>
#include <loader/firmware_api/firmware_api.h>
#define TAG "example_advanced_plugins"
int32_t example_advanced_plugins_app(void* p) {
UNUSED(p);
FURI_LOG_I(TAG, "Starting");
CompositeApiResolver* resolver = composite_api_resolver_alloc();
composite_api_resolver_add(resolver, firmware_api_interface);
composite_api_resolver_add(resolver, application_api_interface);
PluginManager* manager = plugin_manager_alloc(
PLUGIN_APP_ID, PLUGIN_API_VERSION, composite_api_resolver_get(resolver));
do {
if(plugin_manager_load_all(manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) {
FURI_LOG_E(TAG, "Failed to load all libs");
break;
}
uint32_t plugin_count = plugin_manager_get_count(manager);
FURI_LOG_I(TAG, "Loaded libs: %lu", plugin_count);
for(uint32_t i = 0; i < plugin_count; i++) {
const AdvancedPlugin* plugin = plugin_manager_get_ep(manager, i);
FURI_LOG_I(TAG, "plugin name: %s. Calling methods", plugin->name);
plugin->method1(228);
plugin->method2();
FURI_LOG_I(TAG, "Accumulator: %lu", app_api_accumulator_get());
}
} while(0);
plugin_manager_free(manager);
composite_api_resolver_free(resolver);
FURI_LOG_I(TAG, "Goodbye!");
return 0;
}

View File

@@ -0,0 +1,40 @@
/*
* This plugin uses both firmware's API interface and private application headers.
* It can be loaded by a plugin manager that uses CompoundApiInterface,
* which combines both interfaces.
*/
#include "app_api.h"
#include "plugin_interface.h"
#include <flipper_application/flipper_application.h>
#include <furi.h>
static void advanced_plugin1_method1(int arg1) {
/* This function is implemented inside host application */
app_api_accumulator_add(arg1);
}
static void advanced_plugin1_method2() {
/* Accumulator value is stored inside host application */
FURI_LOG_I("TEST", "Plugin 1, accumulator: %lu", app_api_accumulator_get());
}
/* Actual implementation of app<>plugin interface */
static const AdvancedPlugin advanced_plugin1 = {
.name = "Advanced Plugin 1",
.method1 = &advanced_plugin1_method1,
.method2 = &advanced_plugin1_method2,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor advanced_plugin1_descriptor = {
.appid = PLUGIN_APP_ID,
.ep_api_version = PLUGIN_API_VERSION,
.entry_point = &advanced_plugin1,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* advanced_plugin1_ep() {
return &advanced_plugin1_descriptor;
}

View File

@@ -0,0 +1,40 @@
/*
* This plugin uses both firmware's API interface and private application headers.
* It can be loaded by a plugin manager that uses CompoundApiInterface,
* which combines both interfaces.
*/
#include "app_api.h"
#include "plugin_interface.h"
#include <flipper_application/flipper_application.h>
#include <furi.h>
static void advanced_plugin2_method1(int arg1) {
/* This function is implemented inside host application */
app_api_accumulator_mul(arg1);
}
static void advanced_plugin2_method2() {
/* Accumulator value is stored inside host application */
FURI_LOG_I("TEST", "Plugin 2, accumulator: %lu", app_api_accumulator_get());
}
/* Actual implementation of app<>plugin interface */
static const AdvancedPlugin advanced_plugin2 = {
.name = "Advanced Plugin 2",
.method1 = &advanced_plugin2_method1,
.method2 = &advanced_plugin2_method2,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor advanced_plugin2_descriptor = {
.appid = PLUGIN_APP_ID,
.ep_api_version = PLUGIN_API_VERSION,
.entry_point = &advanced_plugin2,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* advanced_plugin2_ep() {
return &advanced_plugin2_descriptor;
}

View File

@@ -0,0 +1,12 @@
#pragma once
/* Common interface between a plugin and host applicaion */
#define PLUGIN_APP_ID "example_plugins_advanced"
#define PLUGIN_API_VERSION 1
typedef struct {
const char* name;
void (*method1)(int);
void (*method2)();
} AdvancedPlugin;

View File

@@ -1,10 +1,6 @@
# Placeholder
App(
appid="basic_plugins",
name="Basic applications for plug-in menu",
appid="external_apps",
name="External apps bundle",
apptype=FlipperAppType.METAPACKAGE,
provides=[
"music_player",
"music_beeper",
"snake_game",
],
)

View File

@@ -3,7 +3,6 @@ App(
name="Arkanoid",
apptype=FlipperAppType.EXTERNAL,
entry_point="arkanoid_game_app",
cdefines=["APP_ARKANOID_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=20,

View File

@@ -3,7 +3,6 @@ App(
name="BlackJack",
apptype=FlipperAppType.EXTERNAL,
entry_point="blackjack_app",
cdefines=["APP_BLACKJACK"],
requires=["gui", "storage", "canvas"],
stack_size=2 * 1024,
order=30,

View File

@@ -3,7 +3,6 @@ App(
name="DOOM",
apptype=FlipperAppType.EXTERNAL,
entry_point="doom_app",
cdefines=["APP_DOOM_GAME"],
requires=[
"gui",
"music_player",

View File

@@ -3,7 +3,6 @@ App(
name="DTMF Dolphin",
apptype=FlipperAppType.EXTERNAL,
entry_point="dtmf_dolphin_app",
cdefines=["DTMF_DOLPHIN"],
requires=[
"storage",
"gui",

View File

@@ -3,7 +3,6 @@ App(
name="[ESP8266] Deauther",
apptype=FlipperAppType.EXTERNAL,
entry_point="esp8266_deauth_app",
cdefines=["APP_ESP8266_deauth"],
requires=["gui"],
stack_size=2 * 1024,
order=20,

View File

@@ -352,7 +352,12 @@ int32_t esp8266_deauth_app(void* p) {
#else
#if ENABLE_MODULE_POWER
app->m_context = Initializing;
furi_hal_power_enable_otg();
uint8_t attempts = 0;
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
furi_delay_ms(200);
#else
app->m_context = ModuleActive;
#endif
@@ -409,7 +414,11 @@ int32_t esp8266_deauth_app(void* p) {
app->m_wifiDeauthModuleAttached = true;
#if ENABLE_MODULE_POWER
app->m_context = Initializing;
furi_hal_power_enable_otg();
uint8_t attempts2 = 0;
while(!furi_hal_power_is_otg_enabled() && attempts2++ < 3) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
#else
app->m_context = ModuleActive;
#endif
@@ -533,7 +542,9 @@ int32_t esp8266_deauth_app(void* p) {
DEAUTH_APP_LOG_I("App freed");
#if ENABLE_MODULE_POWER
furi_hal_power_disable_otg();
if(furi_hal_power_is_otg_enabled()) {
furi_hal_power_disable_otg();
}
#endif
return 0;

View File

@@ -3,7 +3,6 @@ App(
name="Flappy Bird",
apptype=FlipperAppType.EXTERNAL,
entry_point="flappy_game_app",
cdefines=["APP_FLAPPY_GAME"],
requires=["gui"],
stack_size=4 * 1024,
order=100,

View File

@@ -3,7 +3,6 @@ App(
name="RFID Fuzzer",
apptype=FlipperAppType.EXTERNAL,
entry_point="flipfrid_start",
cdefines=["APP_FLIP_FRID"],
requires=["gui", "storage", "dialogs", "input", "notification"],
stack_size=1 * 1024,
order=180,

View File

@@ -3,7 +3,6 @@ App(
name="[GPIO] i2c Tools",
apptype=FlipperAppType.EXTERNAL,
entry_point="i2ctools_app",
cdefines=["APP_I2CTOOLS"],
requires=["gui"],
stack_size=2 * 1024,
order=175,

View File

@@ -3,7 +3,6 @@ App(
name="Game 15",
apptype=FlipperAppType.EXTERNAL,
entry_point="game15_app",
cdefines=["APP_GAME15"],
requires=["gui"],
stack_size=1 * 1024,
fap_icon="game15_10px.png",

View File

@@ -4,7 +4,6 @@ App(
name="2048",
apptype=FlipperAppType.EXTERNAL,
entry_point="game_2048_app",
cdefines=["APP_GAME_2048"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="[NMEA] GPS",
apptype=FlipperAppType.EXTERNAL,
entry_point="gps_app",
cdefines=["APP_GPS"],
requires=["gui"],
stack_size=1 * 1024,
order=35,

View File

@@ -3,7 +3,6 @@ App(
name="[HC-SR] Dist. Sensor",
apptype=FlipperAppType.EXTERNAL,
entry_point="hc_sr04_app",
cdefines=["APP_HC_SR04"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="Hex Viewer",
apptype=FlipperAppType.EXTERNAL,
entry_point="hex_viewer_app",
cdefines=["APP_HEX_VIEWER"],
requires=[
"gui",
"dialogs",

View File

@@ -3,7 +3,6 @@ App(
name="iButton Fuzzer",
apptype=FlipperAppType.EXTERNAL,
entry_point="ibtnfuzzer_start",
cdefines=["APP_IBTN_FUZZ"],
requires=["gui", "storage", "dialogs", "input", "notification"],
stack_size=1 * 1024,
order=15,

View File

@@ -3,7 +3,6 @@ App(
name="[BH1750] Lightmeter",
apptype=FlipperAppType.EXTERNAL,
entry_point="lightmeter_app",
cdefines=["APP_LIGHTMETER"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="Metronome",
apptype=FlipperAppType.EXTERNAL,
entry_point="metronome_app",
cdefines=["APP_METRONOME"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="Minesweeper",
apptype=FlipperAppType.EXTERNAL,
entry_point="minesweeper_app",
cdefines=["APP_MINESWEEPER"],
requires=["gui"],
stack_size=8 * 1024,
fap_category="Games",

View File

@@ -3,7 +3,6 @@ App(
name="Morse Code",
apptype=FlipperAppType.EXTERNAL,
entry_point="morse_code_app",
cdefines=["APP_MORSE_CODE"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="[NRF24] Mouse Jacker",
apptype=FlipperAppType.EXTERNAL,
entry_point="mousejacker_app",
cdefines=["APP_MOUSEJACKER"],
requires=[
"gui",
"dialogs",

View File

@@ -3,7 +3,6 @@ App(
name="Multi Converter",
apptype=FlipperAppType.EXTERNAL,
entry_point="multi_converter_app",
cdefines=["APP_DEC_HEX_CONVERTER"],
requires=["gui"],
stack_size=1 * 1024,
order=160,

View File

@@ -3,7 +3,6 @@ App(
name="Music Player",
apptype=FlipperAppType.EXTERNAL,
entry_point="music_player_app",
cdefines=["APP_MUSIC_PLAYER"],
requires=[
"gui",
"dialogs",
@@ -12,8 +11,8 @@ App(
stack_size=2 * 1024,
order=45,
fap_icon="icons/music_10px.png",
fap_icon_assets="icons",
fap_category="Music",
fap_icon_assets="icons",
)
App(

View File

@@ -3,7 +3,6 @@ App(
name="[NRF24] Sniffer",
apptype=FlipperAppType.EXTERNAL,
entry_point="nrfsniff_app",
cdefines=["APP_NRFSNIFF"],
requires=["gui"],
stack_size=2 * 1024,
order=60,

View File

@@ -5,6 +5,7 @@
#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt")
#define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt")
#define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_standard_dict.txt")
#define TAG "IclassEliteDict"
@@ -25,6 +26,9 @@ bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) {
(storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK);
} else if(dict_type == IclassEliteDictTypeUser) {
dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK);
} else if(dict_type == IclassStandardDictTypeFlipper) {
dict_present =
(storage_common_stat(storage, ICLASS_STANDARD_DICT_FLIPPER_NAME, NULL) == FSE_OK);
}
furi_record_close(RECORD_STORAGE);
@@ -52,6 +56,15 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) {
buffered_file_stream_close(dict->stream);
break;
}
} else if(dict_type == IclassStandardDictTypeFlipper) {
if(!buffered_file_stream_open(
dict->stream,
ICLASS_STANDARD_DICT_FLIPPER_NAME,
FSAM_READ,
FSOM_OPEN_EXISTING)) {
buffered_file_stream_close(dict->stream);
break;
}
}
// Read total amount of keys
@@ -148,4 +161,4 @@ bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key) {
furi_string_free(key_str);
return key_added;
}
}

View File

@@ -9,6 +9,7 @@
typedef enum {
IclassEliteDictTypeUser,
IclassEliteDictTypeFlipper,
IclassStandardDictTypeFlipper,
} IclassEliteDictType;
typedef struct IclassEliteDict IclassEliteDict;
@@ -25,4 +26,4 @@ bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key);
bool iclass_elite_dict_rewind(IclassEliteDict* dict);
bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key);
bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key);

View File

@@ -172,14 +172,18 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) {
return ERR_NONE;
}
static ReturnCode picopass_auth_dict(
uint8_t* csn,
PicopassPacs* pacs,
uint8_t* div_key,
IclassEliteDictType dict_type,
bool elite) {
static ReturnCode
picopass_auth_dict(PicopassWorker* picopass_worker, IclassEliteDictType dict_type) {
rfalPicoPassReadCheckRes rcRes;
rfalPicoPassCheckRes chkRes;
bool elite = (dict_type != IclassStandardDictTypeFlipper);
PicopassDeviceData* dev_data = picopass_worker->dev_data;
PicopassBlock* AA1 = dev_data->AA1;
PicopassPacs* pacs = &dev_data->pacs;
uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data;
uint8_t* div_key = AA1[PICOPASS_KD_BLOCK_INDEX].data;
ReturnCode err = ERR_PARAM;
@@ -204,7 +208,8 @@ static ReturnCode picopass_auth_dict(
while(iclass_elite_dict_get_next_key(dict, key)) {
FURI_LOG_D(
TAG,
"Try to auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x",
"Try to %s auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x",
elite ? "elite" : "standard",
index++,
key[0],
key[1],
@@ -230,6 +235,8 @@ static ReturnCode picopass_auth_dict(
memcpy(pacs->key, key, PICOPASS_BLOCK_LEN);
break;
}
if(picopass_worker->state != PicopassWorkerStateDetect) break;
}
iclass_elite_dict_free(dict);
@@ -237,38 +244,23 @@ static ReturnCode picopass_auth_dict(
return err;
}
ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) {
ReturnCode picopass_auth(PicopassWorker* picopass_worker) {
ReturnCode err;
FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]");
err = picopass_auth_dict(
AA1[PICOPASS_CSN_BLOCK_INDEX].data,
pacs,
AA1[PICOPASS_KD_BLOCK_INDEX].data,
IclassEliteDictTypeFlipper,
false);
err = picopass_auth_dict(picopass_worker, IclassStandardDictTypeFlipper);
if(err == ERR_NONE) {
return ERR_NONE;
}
FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]");
err = picopass_auth_dict(
AA1[PICOPASS_CSN_BLOCK_INDEX].data,
pacs,
AA1[PICOPASS_KD_BLOCK_INDEX].data,
IclassEliteDictTypeUser,
true);
err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeUser);
if(err == ERR_NONE) {
return ERR_NONE;
}
FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]");
err = picopass_auth_dict(
AA1[PICOPASS_CSN_BLOCK_INDEX].data,
pacs,
AA1[PICOPASS_KD_BLOCK_INDEX].data,
IclassEliteDictTypeFlipper,
true);
err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeFlipper);
if(err == ERR_NONE) {
return ERR_NONE;
}
@@ -520,7 +512,7 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) {
}
if(nextState == PicopassWorkerEventSuccess) {
err = picopass_auth(AA1, pacs);
err = picopass_auth(picopass_worker);
if(err != ERR_NONE) {
FURI_LOG_E(TAG, "picopass_try_auth error %d", err);
nextState = PicopassWorkerEventFail;

View File

@@ -3,7 +3,6 @@ App(
name="POCSAG Pager",
apptype=FlipperAppType.EXTERNAL,
entry_point="pocsag_pager_app",
cdefines=["APP_POCSAG_PAGER"],
requires=["gui"],
stack_size=4 * 1024,
order=50,

View File

@@ -124,6 +124,11 @@ POCSAGPagerApp* pocsag_pager_app_alloc() {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();

View File

@@ -169,6 +169,11 @@ ProtoViewApp* protoview_app_alloc() {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();
app->running = 1;

View File

@@ -3,7 +3,6 @@ App(
name="ProtoView",
apptype=FlipperAppType.EXTERNAL,
entry_point="protoview_app_entry",
cdefines=["APP_PROTOVIEW"],
requires=["gui"],
stack_size=8 * 1024,
order=50,

View File

@@ -3,7 +3,6 @@ App(
name="[GPIO] Sentry Safe",
apptype=FlipperAppType.EXTERNAL,
entry_point="sentry_safe_app",
cdefines=["APP_SENTRY_SAFE"],
requires=["gui"],
stack_size=1 * 1024,
order=40,

View File

@@ -3,7 +3,6 @@ App(
name="[GPIO] Signal Generator",
apptype=FlipperAppType.EXTERNAL,
entry_point="signal_gen_app",
cdefines=["APP_SIGNAL_GEN"],
requires=["gui"],
stack_size=1 * 1024,
order=50,

View File

@@ -3,7 +3,6 @@ App(
name="Snake Game",
apptype=FlipperAppType.EXTERNAL,
entry_point="snake_game_app",
cdefines=["APP_SNAKE_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=210,

View File

@@ -3,7 +3,6 @@ App(
name="Solitaire",
apptype=FlipperAppType.EXTERNAL,
entry_point="solitaire_app",
cdefines=["APP_SOLITAIRE"],
requires=["gui", "storage", "canvas"],
stack_size=2 * 1024,
order=30,

View File

@@ -3,7 +3,6 @@ App(
name="Spectrum Analyzer",
apptype=FlipperAppType.EXTERNAL,
entry_point="spectrum_analyzer_app",
cdefines=["APP_SPECTRUM_ANALYZER"],
requires=["gui"],
stack_size=2 * 1024,
order=12,

View File

@@ -405,6 +405,11 @@ int32_t spectrum_analyzer_app(void* p) {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();

1
applications/external/subbrute vendored Submodule

Submodule applications/external/subbrute added at f9a4508e50

View File

@@ -3,7 +3,6 @@ App(
name="Sub-GHz Playlist",
apptype=FlipperAppType.EXTERNAL,
entry_point="playlist_app",
cdefines=["APP_PLAYLIST"],
requires=["storage", "gui", "dialogs", "subghz"],
stack_size=2 * 1024,
order=14,

View File

@@ -713,6 +713,11 @@ int32_t playlist_app(void* p) {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();

View File

@@ -22,6 +22,7 @@
#include <lib/subghz/protocols/alutech_at_4n.h>
#include <lib/subghz/protocols/nice_flor_s.h>
#include <lib/subghz/protocols/somfy_telis.h>
#include <lib/subghz/protocols/secplus_v2.h>
#define SUBREMOTEMAP_FOLDER "/ext/subghz/remote"
#define SUBREMOTEMAP_EXTENSION ".txt"
@@ -491,6 +492,7 @@ void subghz_remote_tx_stop(SubGHzRemote* app) {
alutech_reset_original_btn();
nice_flors_reset_original_btn();
somfy_telis_reset_original_btn();
secplus2_reset_original_btn();
star_line_reset_mfname();
star_line_reset_kl_type();
}
@@ -738,6 +740,11 @@ SubGHzRemote* subghz_remote_alloc(void) {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();

View File

@@ -3,7 +3,6 @@ App(
name="[SWD] Probe",
apptype=FlipperAppType.EXTERNAL,
entry_point="swd_probe_app_main",
cdefines=["APP_SWD_PROBE"],
requires=["notification", "gui", "storage", "dialogs", "cli"],
stack_size=2 * 1024,
order=10,

View File

@@ -3,7 +3,6 @@ App(
name="Tetris",
apptype=FlipperAppType.EXTERNAL,
entry_point="tetris_game_app",
cdefines=["APP_TETRIS_GAME"],
requires=["gui"],
stack_size=2 * 1024,
order=240,

View File

@@ -3,7 +3,6 @@ App(
name="Text Viewer",
apptype=FlipperAppType.EXTERNAL,
entry_point="text_viewer_app",
cdefines=["APP_TEXT_VIEWER"],
requires=[
"gui",
"dialogs",

View File

@@ -3,7 +3,6 @@ App(
name="Tic Tac Toe",
apptype=FlipperAppType.EXTERNAL,
entry_point="tictactoe_game_app",
cdefines=["APP_TICTACTOE_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=250,

View File

@@ -3,7 +3,6 @@ App(
name="Authenticator",
apptype=FlipperAppType.EXTERNAL,
entry_point="totp_app",
cdefines=["APP_TOTP"],
requires=["gui", "cli", "dialogs", "storage", "input", "notification"],
stack_size=2 * 1024,
order=20,

View File

@@ -3,7 +3,6 @@ App(
name="[GPIO] UART Terminal",
apptype=FlipperAppType.EXTERNAL,
entry_point="uart_terminal_app",
cdefines=["APP_UART_TERMINAL"],
requires=["gui"],
stack_size=1 * 1024,
order=90,

View File

@@ -3,7 +3,6 @@ App(
name="[GPIO] Unitemp",
apptype=FlipperAppType.EXTERNAL,
entry_point="unitemp_app",
cdefines=["UNITEMP_APP"],
requires=[
"gui",
],

View File

@@ -3,7 +3,6 @@ App(
name="WAV Player",
apptype=FlipperAppType.EXTERNAL,
entry_point="wav_player_app",
cdefines=["APP_WAV_PLAYER"],
stack_size=4 * 1024,
order=46,
fap_icon="wav_10px.png",

View File

@@ -4,7 +4,6 @@ App(
apptype=FlipperAppType.EXTERNAL,
targets=["f7"],
entry_point="weather_station_app",
cdefines=["APP_WEATHER_STATION"],
requires=["gui"],
stack_size=4 * 1024,
order=50,

View File

@@ -107,6 +107,11 @@ WeatherStationApp* weather_station_app_alloc() {
// Enable power for External CC1101 if it is connected
furi_hal_subghz_enable_ext_power();
// Auto switch to internal radio if external radio is not available
furi_delay_ms(15);
if(!furi_hal_subghz_check_radio()) {
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
}
furi_hal_power_suppress_charge_enter();

View File

@@ -3,7 +3,6 @@ App(
name="[ESP32] WiFi Marauder",
apptype=FlipperAppType.EXTERNAL,
entry_point="wifi_marauder_app",
cdefines=["APP_WIFI_MARAUDER"],
requires=["gui"],
stack_size=1 * 1024,
order=90,

View File

@@ -14,10 +14,26 @@ void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, vo
// Null-terminate buf and append to text box store
buf[len] = '\0';
furi_string_cat_printf(app->text_box_store, "%s", buf);
view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshConsoleOutput);
}
void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len, void* context) {
furi_assert(context);
WifiMarauderApp* app = context;
// If it is a sniff function, open the pcap file for recording
if(strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0 && !app->is_writing) {
app->is_writing = true;
if(!app->capture_file || !storage_file_is_open(app->capture_file)) {
wifi_marauder_create_pcap_file(app);
}
}
if(app->is_writing) {
storage_file_write(app->capture_file, buf, len);
}
}
void wifi_marauder_scene_console_output_on_enter(void* context) {
WifiMarauderApp* app = context;
@@ -33,8 +49,8 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
furi_string_reset(app->text_box_store);
app->text_box_store_strlen = 0;
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
const char* help_msg =
"Marauder companion v0.3.0\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n";
const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION
"\nby @0xchocolate\nmodified by @tcpassos\n";
furi_string_cat_str(app->text_box_store, help_msg);
app->text_box_store_strlen += strlen(help_msg);
}
@@ -54,7 +70,11 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
// Register callback to receive data
wifi_marauder_uart_set_handle_rx_data_cb(
app->uart, wifi_marauder_console_output_handle_rx_data_cb); // setup callback for rx thread
app->uart,
wifi_marauder_console_output_handle_rx_data_cb); // setup callback for general log rx thread
wifi_marauder_uart_set_handle_rx_data_cb(
app->lp_uart,
wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread
// Send command with newline '\n'
if(app->is_command && app->selected_tx_string) {
@@ -84,9 +104,15 @@ void wifi_marauder_scene_console_output_on_exit(void* context) {
// Unregister rx callback
wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL);
wifi_marauder_uart_set_handle_rx_data_cb(app->lp_uart, NULL);
// Automatically stop the scan when exiting view
if(app->is_command) {
wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
}
}
app->is_writing = false;
if(app->capture_file && storage_file_is_open(app->capture_file)) {
storage_file_close(app->capture_file);
}
}

View File

@@ -25,6 +25,9 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
WifiMarauderApp* app = malloc(sizeof(WifiMarauderApp));
app->gui = furi_record_open(RECORD_GUI);
app->dialogs = furi_record_open(RECORD_DIALOGS);
app->storage = furi_record_open(RECORD_STORAGE);
app->capture_file = storage_file_alloc(app->storage);
app->view_dispatcher = view_dispatcher_alloc();
app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app);
@@ -67,6 +70,14 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
return app;
}
void wifi_marauder_make_app_folder(WifiMarauderApp* app) {
furi_assert(app);
if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER)) {
dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder");
}
}
void wifi_marauder_app_free(WifiMarauderApp* app) {
furi_assert(app);
@@ -77,33 +88,47 @@ void wifi_marauder_app_free(WifiMarauderApp* app) {
text_box_free(app->text_box);
furi_string_free(app->text_box_store);
text_input_free(app->text_input);
storage_file_free(app->capture_file);
// View dispatcher
view_dispatcher_free(app->view_dispatcher);
scene_manager_free(app->scene_manager);
wifi_marauder_uart_free(app->uart);
wifi_marauder_uart_free(app->lp_uart);
// Close records
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_STORAGE);
furi_record_close(RECORD_DIALOGS);
free(app);
}
int32_t wifi_marauder_app(void* p) {
UNUSED(p);
furi_hal_power_enable_otg();
furi_delay_ms(300);
uint8_t attempts = 0;
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
furi_delay_ms(200);
WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc();
wifi_marauder_app->uart = wifi_marauder_uart_init(wifi_marauder_app);
wifi_marauder_make_app_folder(wifi_marauder_app);
wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app);
wifi_marauder_app->lp_uart = wifi_marauder_lp_uart_init(wifi_marauder_app);
view_dispatcher_run(wifi_marauder_app->view_dispatcher);
wifi_marauder_app_free(wifi_marauder_app);
furi_hal_power_disable_otg();
if(furi_hal_power_is_otg_enabled()) {
furi_hal_power_disable_otg();
}
return 0;
}

View File

@@ -4,6 +4,8 @@
extern "C" {
#endif
#define WIFI_MARAUDER_APP_VERSION "v0.3.1"
typedef struct WifiMarauderApp WifiMarauderApp;
#ifdef __cplusplus

View File

@@ -6,6 +6,7 @@
#include "scenes/wifi_marauder_scene.h"
#include "wifi_marauder_custom_event.h"
#include "wifi_marauder_uart.h"
#include "wifi_marauder_pcap.h"
#include <gui/gui.h>
#include <gui/view_dispatcher.h>
@@ -14,11 +15,16 @@
#include <gui/modules/text_input.h>
#include <gui/modules/variable_item_list.h>
#include <storage/storage.h>
#include <dialogs/dialogs.h>
#define NUM_MENU_ITEMS (16)
#define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096)
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
#define MARAUDER_APP_FOLDER EXT_PATH("apps_data/marauder")
struct WifiMarauderApp {
Gui* gui;
ViewDispatcher* view_dispatcher;
@@ -29,11 +35,14 @@ struct WifiMarauderApp {
size_t text_box_store_strlen;
TextBox* text_box;
TextInput* text_input;
//Widget* widget;
Storage* storage;
File* capture_file;
DialogsApp* dialogs;
VariableItemList* var_item_list;
WifiMarauderUart* uart;
WifiMarauderUart* lp_uart;
int selected_menu_index;
int selected_option_index[NUM_MENU_ITEMS];
const char* selected_tx_string;
@@ -41,6 +50,7 @@ struct WifiMarauderApp {
bool is_custom_tx_string;
bool focus_console_start;
bool show_stopscan_tip;
bool is_writing;
// For input source and destination MAC in targeted deauth attack
int special_case_input_step;

View File

@@ -0,0 +1,33 @@
#include "wifi_marauder_app_i.h"
#include "wifi_marauder_pcap.h"
void wifi_marauder_get_prefix_from_cmd(char* dest, const char* command) {
int start, end, delta;
start = strlen("sniff");
end = strcspn(command, " ");
delta = end - start;
strncpy(dest, command + start, end - start);
dest[delta] = '\0';
}
void wifi_marauder_create_pcap_file(WifiMarauderApp* app) {
char prefix[10];
char capture_file_path[100];
wifi_marauder_get_prefix_from_cmd(prefix, app->selected_tx_string);
int i = 0;
do {
snprintf(
capture_file_path,
sizeof(capture_file_path),
"%s/%s_%d.pcap",
MARAUDER_APP_FOLDER,
prefix,
i);
i++;
} while(storage_file_exists(app->storage, capture_file_path));
if(!storage_file_open(app->capture_file, capture_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
dialog_message_show_storage_error(app->dialogs, "Cannot open pcap file");
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "furi_hal.h"
/**
* Creates a PCAP file to store incoming packets.
* The file name will have a prefix according to the type of scan being performed by the application (Eg: raw_0.pcap)
*
* @param app Application context
*/
void wifi_marauder_create_pcap_file(WifiMarauderApp* app);

View File

@@ -2,10 +2,12 @@
#include "wifi_marauder_uart.h"
#define UART_CH (FuriHalUartIdUSART1)
#define LP_UART_CH (FuriHalUartIdLPUART1)
#define BAUDRATE (115200)
struct WifiMarauderUart {
WifiMarauderApp* app;
FuriHalUartId channel;
FuriThread* rx_thread;
FuriStreamBuffer* rx_stream;
uint8_t rx_buf[RX_BUF_SIZE + 1];
@@ -60,25 +62,42 @@ void wifi_marauder_uart_tx(uint8_t* data, size_t len) {
furi_hal_uart_tx(UART_CH, data, len);
}
WifiMarauderUart* wifi_marauder_uart_init(WifiMarauderApp* app) {
void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len) {
furi_hal_uart_tx(LP_UART_CH, data, len);
}
WifiMarauderUart*
wifi_marauder_uart_init(WifiMarauderApp* app, FuriHalUartId channel, const char* thread_name) {
WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart));
uart->app = app;
uart->channel = channel;
uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
uart->rx_thread = furi_thread_alloc();
furi_thread_set_name(uart->rx_thread, "WifiMarauderUartRxThread");
furi_thread_set_name(uart->rx_thread, thread_name);
furi_thread_set_stack_size(uart->rx_thread, 1024);
furi_thread_set_context(uart->rx_thread, uart);
furi_thread_set_callback(uart->rx_thread, uart_worker);
furi_thread_start(uart->rx_thread);
furi_hal_console_disable();
furi_hal_uart_set_br(UART_CH, BAUDRATE);
furi_hal_uart_set_irq_cb(UART_CH, wifi_marauder_uart_on_irq_cb, uart);
if(channel == FuriHalUartIdUSART1) {
furi_hal_console_disable();
} else if(channel == FuriHalUartIdLPUART1) {
furi_hal_uart_init(channel, BAUDRATE);
}
furi_hal_uart_set_br(channel, BAUDRATE);
furi_hal_uart_set_irq_cb(channel, wifi_marauder_uart_on_irq_cb, uart);
return uart;
}
WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app) {
return wifi_marauder_uart_init(app, UART_CH, "WifiMarauderUartRxThread");
}
WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app) {
return wifi_marauder_uart_init(app, LP_UART_CH, "WifiMarauderLPUartRxThread");
}
void wifi_marauder_uart_free(WifiMarauderUart* uart) {
furi_assert(uart);
@@ -86,7 +105,7 @@ void wifi_marauder_uart_free(WifiMarauderUart* uart) {
furi_thread_join(uart->rx_thread);
furi_thread_free(uart->rx_thread);
furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL);
furi_hal_console_enable();
free(uart);

View File

@@ -10,5 +10,7 @@ void wifi_marauder_uart_set_handle_rx_data_cb(
WifiMarauderUart* uart,
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
void wifi_marauder_uart_tx(uint8_t* data, size_t len);
WifiMarauderUart* wifi_marauder_uart_init(WifiMarauderApp* app);
void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len);
WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app);
WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app);
void wifi_marauder_uart_free(WifiMarauderUart* uart);

View File

@@ -3,7 +3,6 @@ App(
name="[WiFi] Scanner",
apptype=FlipperAppType.EXTERNAL,
entry_point="wifi_scanner_app",
cdefines=["APP_WIFI_SCANNER"],
requires=["gui"],
stack_size=2 * 1024,
order=70,

View File

@@ -663,7 +663,12 @@ int32_t wifi_scanner_app(void* p) {
#else
app->m_context = Initializing;
#if ENABLE_MODULE_POWER
furi_hal_power_enable_otg();
uint8_t attempts = 0;
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
furi_delay_ms(200);
#endif // ENABLE_MODULE_POWER
#endif // ENABLE_MODULE_DETECTION
@@ -722,7 +727,12 @@ int32_t wifi_scanner_app(void* p) {
app->m_wifiModuleAttached = true;
app->m_context = Initializing;
#if ENABLE_MODULE_POWER
furi_hal_power_enable_otg();
uint8_t attempts2 = 0;
while(!furi_hal_power_is_otg_enabled() && attempts2++ < 3) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
#endif
}
}
@@ -851,7 +861,9 @@ int32_t wifi_scanner_app(void* p) {
WIFI_APP_LOG_I("App freed");
#if ENABLE_MODULE_POWER
furi_hal_power_disable_otg();
if(furi_hal_power_is_otg_enabled()) {
furi_hal_power_disable_otg();
}
#endif
return 0;

View File

@@ -3,7 +3,6 @@ App(
name="Zombiez",
apptype=FlipperAppType.EXTERNAL,
entry_point="zombiez_game_app",
cdefines=["APP_ZOMBIEZ_GAME"],
requires=["gui"],
stack_size=2 * 1024,
order=280,

View File

@@ -7,6 +7,7 @@ App(
requires=[
"gui",
"storage",
"loader",
],
stack_size=int(1.5 * 1024),
icon="A_Plugins_14",

View File

@@ -1,48 +0,0 @@
#include "compilesort.hpp"
#include "elf_hashtable.h"
#include "elf_hashtable_entry.h"
#include "elf_hashtable_checks.hpp"
#include <array>
#include <algorithm>
/* Generated table */
#include <symbols.h>
#define TAG "elf_hashtable"
static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!");
/**
* Get function address by function name
* @param name function name
* @param address output for function address
* @return true if the table contains a function
*/
bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address) {
bool result = false;
uint32_t gnu_sym_hash = elf_gnu_hash(name);
sym_entry key = {
.hash = gnu_sym_hash,
.address = 0,
};
auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key);
if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) {
FURI_LOG_W(TAG, "Can't find symbol '%s' (hash %lx)!", name, gnu_sym_hash);
result = false;
} else {
result = true;
*address = find_res->address;
}
return result;
}
const ElfApiInterface hashtable_api_interface = {
.api_version_major = (elf_api_version >> 16),
.api_version_minor = (elf_api_version & 0xFFFF),
.resolver_callback = &elf_resolve_from_hashtable,
};

View File

@@ -1,14 +0,0 @@
#pragma once
#include <stdint.h>
#include <flipper_application/elf/elf_api_interface.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const ElfApiInterface hashtable_api_interface;
#ifdef __cplusplus
}
#endif

View File

@@ -1,18 +0,0 @@
/**
* Check for multiple entries with the same hash value at compilation time.
*/
#pragma once
#include <array>
#include "elf_hashtable_entry.h"
template <std::size_t N>
constexpr bool has_hash_collisions(const std::array<sym_entry, N> api_methods) {
for(std::size_t i = 0; i < (N - 1); ++i) {
if(api_methods[i].hash == api_methods[i + 1].hash) {
return true;
}
}
return false;
}

View File

@@ -1,41 +0,0 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct sym_entry {
uint32_t hash;
uint32_t address;
};
#ifdef __cplusplus
}
#include <array>
#include <algorithm>
#define API_METHOD(x, ret_type, args_type) \
sym_entry { \
.hash = elf_gnu_hash(#x), .address = (uint32_t)(static_cast<ret_type(*) args_type>(x)) \
}
#define API_VARIABLE(x, var_type) \
sym_entry { \
.hash = elf_gnu_hash(#x), .address = (uint32_t)(&(x)), \
}
constexpr bool operator<(const sym_entry& k1, const sym_entry& k2) {
return k1.hash < k2.hash;
}
constexpr uint32_t elf_gnu_hash(const char* s) {
uint32_t h = 0x1505;
for(unsigned char c = *s; c != '\0'; c = *++s) {
h = (h << 5) + h + c;
}
return h;
}
#endif

View File

@@ -7,7 +7,7 @@
#include <dialogs/dialogs.h>
#include <toolbox/path.h>
#include <flipper_application/flipper_application.h>
#include "elf_cpp/elf_hashtable.h"
#include <loader/firmware_api/firmware_api.h>
#include "fap_loader_app.h"
#define TAG "fap_loader_app"
@@ -27,7 +27,7 @@ bool fap_loader_load_name_and_icon(
Storage* storage,
uint8_t** icon_ptr,
FuriString* item_name) {
FlipperApplication* app = flipper_application_alloc(storage, &hashtable_api_interface);
FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
FlipperApplicationPreloadStatus preload_res =
flipper_application_preload_manifest(app, furi_string_get_cstr(path));
@@ -71,7 +71,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
bool show_error = true;
do {
file_selected = true;
loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
loader->app = flipper_application_alloc(loader->storage, firmware_api_interface);
size_t start = furi_get_tick();
FURI_LOG_I(TAG, "FAP Loader is loading %s", furi_string_get_cstr(loader->fap_path));

View File

@@ -2,6 +2,7 @@
#include <furi_hal.h>
#include <cli/cli.h>
#include <lib/toolbox/args.h>
#include <lib/toolbox/hex.h>
#include <lib/nfc/nfc_types.h>
#include <lib/nfc/nfc_device.h>
@@ -12,6 +13,7 @@ static void nfc_cli_print_usage() {
printf("Cmd list:\r\n");
printf("\tdetect\t - detect nfc device\r\n");
printf("\temulate\t - emulate predefined nfca card\r\n");
printf("\tapdu\t - Send APDU and print response \r\n");
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
printf("\tfield\t - turn field on\r\n");
}
@@ -98,6 +100,67 @@ static void nfc_cli_field(Cli* cli, FuriString* args) {
furi_hal_nfc_sleep();
}
static void nfc_cli_apdu(Cli* cli, FuriString* args) {
UNUSED(cli);
if(furi_hal_nfc_is_busy()) {
printf("Nfc is busy\r\n");
return;
}
furi_hal_nfc_exit_sleep();
FuriString* data = NULL;
data = furi_string_alloc();
FuriHalNfcTxRxContext tx_rx = {};
FuriHalNfcDevData dev_data = {};
uint8_t* req_buffer = NULL;
uint8_t* resp_buffer = NULL;
size_t apdu_size = 0;
size_t resp_size = 0;
do {
if(!args_read_string_and_trim(args, data)) {
printf(
"Use like `nfc apdu 00a404000e325041592e5359532e444446303100 00a4040008a0000003010102` \r\n");
break;
}
printf("detecting tag\r\n");
if(!furi_hal_nfc_detect(&dev_data, 300)) {
printf("Failed to detect tag\r\n");
break;
}
do {
apdu_size = furi_string_size(data) / 2;
req_buffer = malloc(apdu_size);
hex_chars_to_uint8(furi_string_get_cstr(data), req_buffer);
memcpy(tx_rx.tx_data, req_buffer, apdu_size);
tx_rx.tx_bits = apdu_size * 8;
tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault;
printf("Sending APDU:%s to Tag\r\n", furi_string_get_cstr(data));
if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) {
printf("Failed to tx_rx\r\n");
break;
}
resp_size = (tx_rx.rx_bits / 8) * 2;
resp_buffer = malloc(resp_size);
uint8_to_hex_chars(tx_rx.rx_data, resp_buffer, resp_size);
resp_buffer[resp_size] = 0;
printf("Response: %s\r\n", resp_buffer);
free(req_buffer);
free(resp_buffer);
req_buffer = NULL;
resp_buffer = NULL;
} while(args_read_string_and_trim(args, data));
} while(false);
free(req_buffer);
free(resp_buffer);
furi_string_free(data);
furi_hal_nfc_sleep();
}
static void nfc_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(context);
FuriString* cmd;
@@ -117,6 +180,11 @@ static void nfc_cli(Cli* cli, FuriString* args, void* context) {
break;
}
if(furi_string_cmp_str(cmd, "apdu") == 0) {
nfc_cli_apdu(cli, args);
break;
}
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
if(furi_string_cmp_str(cmd, "field") == 0) {
nfc_cli_field(cli, args);

View File

@@ -115,7 +115,8 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
consumed = true;
}
} else if(event.event == NfcWorkerEventAborted) {
if(state == DictAttackStateUserDictInProgress) {
if(state == DictAttackStateUserDictInProgress &&
dict_attack_get_card_state(nfc->dict_attack)) {
nfc_scene_mf_classic_dict_attack_prepare_view(nfc, state);
consumed = true;
} else {

View File

@@ -11,6 +11,7 @@ struct DictAttack {
View* view;
DictAttackCallback callback;
void* context;
bool card_present;
};
typedef struct {
@@ -162,6 +163,7 @@ void dict_attack_set_header(DictAttack* dict_attack, const char* header) {
void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type) {
furi_assert(dict_attack);
dict_attack->card_present = true;
with_view_model(
dict_attack->view,
DictAttackViewModel * model,
@@ -175,6 +177,7 @@ void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type)
void dict_attack_set_card_removed(DictAttack* dict_attack) {
furi_assert(dict_attack);
dict_attack->card_present = false;
with_view_model(
dict_attack->view,
DictAttackViewModel * model,
@@ -182,6 +185,11 @@ void dict_attack_set_card_removed(DictAttack* dict_attack) {
true);
}
bool dict_attack_get_card_state(DictAttack* dict_attack) {
furi_assert(dict_attack);
return dict_attack->card_present;
}
void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) {
furi_assert(dict_attack);
with_view_model(

View File

@@ -25,6 +25,8 @@ void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type);
void dict_attack_set_card_removed(DictAttack* dict_attack);
bool dict_attack_get_card_state(DictAttack* dict_attack);
void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read);
void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found);

View File

@@ -11,7 +11,14 @@ typedef enum {
SubmenuIndexBFTClone,
SubmenuIndexBFTMitto,
SubmenuIndexSomfyTelis,
SubmenuIndexPricenton,
SubmenuIndexBeninca433,
SubmenuIndexBeninca868,
SubmenuIndexIronLogic,
SubmenuIndexElmesElectronic,
SubmenuIndexSommer_FM_434,
SubmenuIndexSommer_FM_868,
SubmenuIndexDTMNeo433,
SubmenuIndexGibidi433,
SubmenuIndexNiceFlo12bit,
SubmenuIndexNiceFlo24bit,
SubmenuIndexNiceFlorS_433_92,
@@ -19,14 +26,19 @@ typedef enum {
SubmenuIndexNiceSmilo_433_92,
SubmenuIndexCAME12bit,
SubmenuIndexCAME24bit,
SubmenuIndexBETT_433,
SubmenuIndexCAME12bit868,
SubmenuIndexCAME24bit868,
SubmenuIndexCAMETwee,
SubmenuIndexCAMESpace,
SubmenuIndexPricenton,
SubmenuIndexPricenton315,
SubmenuIndexBETT_433,
SubmenuIndexLinear_300_00,
SubmenuIndexNeroSketch,
SubmenuIndexNeroRadio,
SubmenuIndexGateTX,
SubmenuIndexDoorHan_315_00,
SubmenuIndexDoorHan_433_92,
SubmenuIndexLinear_300_00,
SubmenuIndexLiftMaster_315_00,
SubmenuIndexLiftMaster_390_00,
SubmenuIndexLiftMaster_433_00,

View File

@@ -37,10 +37,13 @@ const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
static void subghz_scene_ext_module_changed(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
value_index_exm = variable_item_get_current_value_index(item);
UNUSED(subghz);
variable_item_set_current_value_text(item, radio_modules_variables_text[value_index_exm]);
subghz->last_settings->external_module_enabled = value_index_exm == 1;
subghz_last_settings_save(subghz->last_settings);
}
static void subghz_ext_module_start_var_list_enter_callback(void* context, uint32_t index) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
@@ -85,6 +88,7 @@ static void subghz_scene_receiver_config_set_debug_counter(VariableItem* item) {
}
static void subghz_scene_receiver_config_set_ext_mod_power(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, ext_mod_power_text[index]);
@@ -95,6 +99,9 @@ static void subghz_scene_receiver_config_set_ext_mod_power(VariableItem* item) {
} else {
furi_hal_subghz_enable_ext_power();
}
subghz->last_settings->external_module_power_5v_disable = index == 1;
subghz_last_settings_save(subghz->last_settings);
}
void subghz_scene_ext_module_settings_on_enter(void* context) {
@@ -181,7 +188,7 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent
// Check if module is present, if no -> show error
if(!furi_hal_subghz_check_radio()) {
value_index_exm = 0;
furi_hal_subghz_set_radio_type(value_index_exm);
furi_hal_subghz_set_radio_type(SubGhzRadioInternal);
furi_string_set(subghz->error_str, "Please connect\nexternal radio");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
}

View File

@@ -5,6 +5,7 @@
#include <lib/subghz/protocols/alutech_at_4n.h>
#include <lib/subghz/protocols/nice_flor_s.h>
#include <lib/subghz/protocols/somfy_telis.h>
#include <lib/subghz/protocols/secplus_v2.h>
void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) {
furi_assert(context);
@@ -240,6 +241,7 @@ void subghz_scene_receiver_info_on_exit(void* context) {
alutech_reset_original_btn();
nice_flors_reset_original_btn();
somfy_telis_reset_original_btn();
secplus2_reset_original_btn();
star_line_reset_mfname();
star_line_reset_kl_type();
}

View File

@@ -4,6 +4,7 @@
#include <lib/subghz/protocols/alutech_at_4n.h>
#include <lib/subghz/protocols/nice_flor_s.h>
#include <lib/subghz/protocols/somfy_telis.h>
#include <lib/subghz/protocols/secplus_v2.h>
#include "xtreme/assets.h"
@@ -118,6 +119,7 @@ void subghz_scene_rpc_on_exit(void* context) {
alutech_reset_original_btn();
nice_flors_reset_original_btn();
somfy_telis_reset_original_btn();
secplus2_reset_original_btn();
star_line_reset_mfname();
star_line_reset_kl_type();
}

Some files were not shown because too many files have changed in this diff Show More