Merge remote-tracking branch 'origin/dev' into release-candidate

This commit is contained in:
Aleksandr Kutuzov 2022-10-15 03:27:47 +09:00
commit cfde6350a6
582 changed files with 10018 additions and 6226 deletions

View File

@ -62,6 +62,8 @@ jobs:
- name: 'Download build artifacts' - name: 'Download build artifacts'
run: | run: |
mkdir -p ~/.ssh
ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
chmod 600 ./deploy_key; chmod 600 ./deploy_key;
rsync -avzP \ rsync -avzP \
@ -97,3 +99,4 @@ jobs:
${{ secrets.AMAP_MARIADB_PORT }} \ ${{ secrets.AMAP_MARIADB_PORT }} \
${{ secrets.AMAP_MARIADB_DATABASE }} \ ${{ secrets.AMAP_MARIADB_DATABASE }} \
artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all

View File

@ -56,14 +56,14 @@ jobs:
- name: 'Bundle scripts' - name: 'Bundle scripts'
if: ${{ !github.event.pull_request.head.repo.fork }} if: ${{ !github.event.pull_request.head.repo.fork }}
run: | run: |
tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts debug
- name: 'Build the firmware' - name: 'Build the firmware'
run: | run: |
set -e set -e
for TARGET in ${TARGETS}; do for TARGET in ${TARGETS}; do
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ FBT_TOOLCHAIN_PATH=/runner/_work ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} copro_dist updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
done done
- name: 'Move upload files' - name: 'Move upload files'
@ -74,17 +74,6 @@ jobs:
mv dist/${TARGET}-*/* artifacts/ mv dist/${TARGET}-*/* artifacts/
done done
- name: 'Bundle self-update package'
if: ${{ !github.event.pull_request.head.repo.fork }}
run: |
set -e
for UPDATEBUNDLE in artifacts/*/; do
BUNDLE_NAME="$(echo "$UPDATEBUNDLE" | cut -d'/' -f2)"
echo Packaging "${BUNDLE_NAME}"
tar czpf "artifacts/flipper-z-${BUNDLE_NAME}.tgz" -C artifacts "${BUNDLE_NAME}"
rm -rf "artifacts/${BUNDLE_NAME}"
done
- name: "Check for uncommitted changes" - name: "Check for uncommitted changes"
run: | run: |
git diff --exit-code git diff --exit-code
@ -97,8 +86,7 @@ jobs:
- name: 'Bundle core2 firmware' - name: 'Bundle core2 firmware'
if: ${{ !github.event.pull_request.head.repo.fork }} if: ${{ !github.event.pull_request.head.repo.fork }}
run: | run: |
FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz"
tar czpf "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" -C assets core2_firmware
- name: 'Copy .map file' - name: 'Copy .map file'
run: | run: |
@ -107,6 +95,8 @@ jobs:
- name: 'Upload artifacts to update server' - name: 'Upload artifacts to update server'
if: ${{ !github.event.pull_request.head.repo.fork }} if: ${{ !github.event.pull_request.head.repo.fork }}
run: | run: |
mkdir -p ~/.ssh
ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
chmod 600 ./deploy_key; chmod 600 ./deploy_key;
rsync -avzP --delete --mkpath \ rsync -avzP --delete --mkpath \
@ -137,7 +127,7 @@ jobs:
**Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:** **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:**
- [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz) - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz)
- [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu) - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu)
- [☁️ Web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}}) - [☁️ Web/App updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}})
edit-mode: replace edit-mode: replace
compact: compact:
@ -174,6 +164,6 @@ jobs:
run: | run: |
set -e set -e
for TARGET in ${TARGETS}; do for TARGET in ${TARGETS}; do
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ FBT_TOOLCHAIN_PATH=/runner/_work ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
updater_package DEBUG=0 COMPACT=1 updater_package DEBUG=0 COMPACT=1
done done

View File

@ -27,6 +27,7 @@ jobs:
- name: 'Check protobuf branch' - name: 'Check protobuf branch'
run: | run: |
git submodule update --init
SUB_PATH="assets/protobuf"; SUB_PATH="assets/protobuf";
SUB_BRANCH="dev"; SUB_BRANCH="dev";
SUB_COMMITS_MIN=40; SUB_COMMITS_MIN=40;

View File

@ -30,7 +30,7 @@ jobs:
- name: 'Check code formatting' - name: 'Check code formatting'
id: syntax_check id: syntax_check
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/runner/_work ./fbt lint
- name: Report code formatting errors - name: Report code formatting errors
if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request

View File

@ -26,4 +26,4 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: 'Check code formatting' - name: 'Check code formatting'
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint_py run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/runner/_work ./fbt lint_py

View File

@ -57,14 +57,15 @@ jobs:
- name: 'Generate compile_comands.json' - name: 'Generate compile_comands.json'
run: | run: |
FBT_TOOLCHAIN_PATH=/opt ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking FBT_TOOLCHAIN_PATH=/runner/_work ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking
- name: 'Static code analysis' - name: 'Static code analysis'
run: | run: |
FBT_TOOLCHAIN_PATH=/opt source scripts/toolchain/fbtenv.sh FBT_TOOLCHAIN_PATH=/runner/_work source scripts/toolchain/fbtenv.sh
pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }}
pvs-studio-analyzer analyze \ pvs-studio-analyzer analyze \
@.pvsoptions \ @.pvsoptions \
--disableLicenseExpirationCheck \
-j$(grep -c processor /proc/cpuinfo) \ -j$(grep -c processor /proc/cpuinfo) \
-f build/f7-firmware-DC/compile_commands.json \ -f build/f7-firmware-DC/compile_commands.json \
-o PVS-Studio.log -o PVS-Studio.log
@ -75,6 +76,8 @@ jobs:
- name: 'Upload artifacts to update server' - name: 'Upload artifacts to update server'
if: ${{ !github.event.pull_request.head.repo.fork }} if: ${{ !github.event.pull_request.head.repo.fork }}
run: | run: |
mkdir -p ~/.ssh
ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
chmod 600 ./deploy_key; chmod 600 ./deploy_key;
rsync -avrzP --mkpath \ rsync -avrzP --mkpath \

View File

@ -7,7 +7,6 @@
# construction of certain targets behind command-line options. # construction of certain targets behind command-line options.
import os import os
import subprocess
DefaultEnvironment(tools=[]) DefaultEnvironment(tools=[])
@ -15,17 +14,22 @@ EnsurePythonVersion(3, 8)
# Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15)
# This environment is created only for loading options & validating file/dir existence # This environment is created only for loading options & validating file/dir existence
fbt_variables = SConscript("site_scons/commandline.scons") fbt_variables = SConscript("site_scons/commandline.scons")
cmd_environment = Environment(tools=[], variables=fbt_variables) cmd_environment = Environment(
Help(fbt_variables.GenerateHelpText(cmd_environment)) toolpath=["#/scripts/fbt_tools"],
tools=[
("fbt_help", {"vars": fbt_variables}),
],
variables=fbt_variables,
)
# Building basic environment - tools, utility methods, cross-compilation # Building basic environment - tools, utility methods, cross-compilation
# settings, gcc flags for Cortex-M4, basic builders and more # settings, gcc flags for Cortex-M4, basic builders and more
coreenv = SConscript( coreenv = SConscript(
"site_scons/environ.scons", "site_scons/environ.scons",
exports={"VAR_ENV": cmd_environment}, exports={"VAR_ENV": cmd_environment},
toolpath=["#/scripts/fbt_tools"],
) )
SConscript("site_scons/cc.scons", exports={"ENV": coreenv}) SConscript("site_scons/cc.scons", exports={"ENV": coreenv})
@ -35,41 +39,13 @@ coreenv["ROOT_DIR"] = Dir(".")
# Create a separate "dist" environment and add construction envs to it # Create a separate "dist" environment and add construction envs to it
distenv = coreenv.Clone( distenv = coreenv.Clone(
tools=["fbt_dist", "openocd", "blackmagic", "jflash"], tools=[
OPENOCD_GDB_PIPE=[ "fbt_dist",
"|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" "fbt_debugopts",
"openocd",
"blackmagic",
"jflash",
], ],
GDBOPTS_BASE=[
"-ex",
"target extended-remote ${GDBREMOTE}",
"-ex",
"set confirm off",
"-ex",
"set pagination off",
],
GDBOPTS_BLACKMAGIC=[
"-ex",
"monitor swdp_scan",
"-ex",
"monitor debug_bmp enable",
"-ex",
"attach 1",
"-ex",
"set mem inaccessible-by-default off",
],
GDBPYOPTS=[
"-ex",
"source debug/FreeRTOS/FreeRTOS.py",
"-ex",
"source debug/flipperapps.py",
"-ex",
"source debug/PyCortexMDebug/PyCortexMDebug.py",
"-ex",
"svd_load ${SVD_FILE}",
"-ex",
"compare-sections",
],
JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash",
ENV=os.environ, ENV=os.environ,
) )
@ -166,7 +142,7 @@ basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
distenv.Default(basic_dist) distenv.Default(basic_dist)
dist_dir = distenv.GetProjetDirName() dist_dir = distenv.GetProjetDirName()
plugin_dist = [ fap_dist = [
distenv.Install( distenv.Install(
f"#/dist/{dist_dir}/apps/debug_elf", f"#/dist/{dist_dir}/apps/debug_elf",
firmware_env["FW_EXTAPPS"]["debug"].values(), firmware_env["FW_EXTAPPS"]["debug"].values(),
@ -176,9 +152,9 @@ plugin_dist = [
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values() for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
), ),
] ]
Depends(plugin_dist, firmware_env["FW_EXTAPPS"]["validators"].values()) Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
Alias("plugin_dist", plugin_dist) Alias("fap_dist", fap_dist)
# distenv.Default(plugin_dist) # distenv.Default(fap_dist)
plugin_resources_dist = list( plugin_resources_dist = list(
distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1]) distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1])
@ -189,9 +165,10 @@ distenv.Depends(firmware_env["FW_RESOURCES"], plugin_resources_dist)
# Target for bundling core2 package for qFlipper # Target for bundling core2 package for qFlipper
copro_dist = distenv.CoproBuilder( copro_dist = distenv.CoproBuilder(
distenv.Dir("assets/core2_firmware"), "#/build/core2_firmware.tgz",
[], [],
) )
distenv.AlwaysBuild(copro_dist)
distenv.Alias("copro_dist", copro_dist) distenv.Alias("copro_dist", copro_dist)
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)

View File

@ -3,14 +3,13 @@
#include <gui/canvas.h> #include <gui/canvas.h>
#include <gui/elements.h> #include <gui/elements.h>
#include <m-array.h> #include <m-array.h>
#include <m-string.h>
#include <furi.h> #include <furi.h>
#include <stdint.h> #include <stdint.h>
struct BtTestParam { struct BtTestParam {
const char* label; const char* label;
uint8_t current_value_index; uint8_t current_value_index;
string_t current_value_text; FuriString* current_value_text;
uint8_t values_count; uint8_t values_count;
BtTestParamChangeCallback change_callback; BtTestParamChangeCallback change_callback;
void* context; void* context;
@ -85,7 +84,8 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str(canvas, 50, param_text_y, "<"); canvas_draw_str(canvas, 50, param_text_y, "<");
} }
canvas_draw_str(canvas, 61, param_text_y, string_get_cstr(param->current_value_text)); canvas_draw_str(
canvas, 61, param_text_y, furi_string_get_cstr(param->current_value_text));
if(param->current_value_index < (param->values_count - 1)) { if(param->current_value_index < (param->values_count - 1)) {
canvas_draw_str(canvas, 113, param_text_y, ">"); canvas_draw_str(canvas, 113, param_text_y, ">");
@ -154,7 +154,9 @@ static bool bt_test_input_callback(InputEvent* event, void* context) {
void bt_test_process_up(BtTest* bt_test) { void bt_test_process_up(BtTest* bt_test) {
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
uint8_t params_on_screen = 3; uint8_t params_on_screen = 3;
if(model->position > 0) { if(model->position > 0) {
model->position--; model->position--;
@ -168,13 +170,15 @@ void bt_test_process_up(BtTest* bt_test) {
model->window_position = model->position - (params_on_screen - 1); model->window_position = model->position - (params_on_screen - 1);
} }
} }
return true; },
}); true);
} }
void bt_test_process_down(BtTest* bt_test) { void bt_test_process_down(BtTest* bt_test) {
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
uint8_t params_on_screen = 3; uint8_t params_on_screen = 3;
if(model->position < (BtTestParamArray_size(model->params) - 1)) { if(model->position < (BtTestParamArray_size(model->params) - 1)) {
model->position++; model->position++;
@ -187,8 +191,8 @@ void bt_test_process_down(BtTest* bt_test) {
model->position = 0; model->position = 0;
model->window_position = 0; model->window_position = 0;
} }
return true; },
}); true);
} }
BtTestParam* bt_test_get_selected_param(BtTestModel* model) { BtTestParam* bt_test_get_selected_param(BtTestModel* model) {
@ -213,7 +217,9 @@ BtTestParam* bt_test_get_selected_param(BtTestModel* model) {
void bt_test_process_left(BtTest* bt_test) { void bt_test_process_left(BtTest* bt_test) {
BtTestParam* param; BtTestParam* param;
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
param = bt_test_get_selected_param(model); param = bt_test_get_selected_param(model);
if(param->current_value_index > 0) { if(param->current_value_index > 0) {
param->current_value_index--; param->current_value_index--;
@ -225,8 +231,8 @@ void bt_test_process_left(BtTest* bt_test) {
model->packets_num_tx = 0; model->packets_num_tx = 0;
} }
} }
return true; },
}); true);
if(param->change_callback) { if(param->change_callback) {
param->change_callback(param); param->change_callback(param);
} }
@ -235,7 +241,9 @@ void bt_test_process_left(BtTest* bt_test) {
void bt_test_process_right(BtTest* bt_test) { void bt_test_process_right(BtTest* bt_test) {
BtTestParam* param; BtTestParam* param;
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
param = bt_test_get_selected_param(model); param = bt_test_get_selected_param(model);
if(param->current_value_index < (param->values_count - 1)) { if(param->current_value_index < (param->values_count - 1)) {
param->current_value_index++; param->current_value_index++;
@ -247,8 +255,8 @@ void bt_test_process_right(BtTest* bt_test) {
model->packets_num_tx = 0; model->packets_num_tx = 0;
} }
} }
return true; },
}); true);
if(param->change_callback) { if(param->change_callback) {
param->change_callback(param); param->change_callback(param);
} }
@ -257,7 +265,9 @@ void bt_test_process_right(BtTest* bt_test) {
void bt_test_process_ok(BtTest* bt_test) { void bt_test_process_ok(BtTest* bt_test) {
BtTestState state; BtTestState state;
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
if(model->state == BtTestStateStarted) { if(model->state == BtTestStateStarted) {
model->state = BtTestStateStopped; model->state = BtTestStateStopped;
model->message = BT_TEST_START_MESSAGE; model->message = BT_TEST_START_MESSAGE;
@ -269,8 +279,8 @@ void bt_test_process_ok(BtTest* bt_test) {
model->message = BT_TEST_STOP_MESSAGE; model->message = BT_TEST_STOP_MESSAGE;
} }
state = model->state; state = model->state;
return true; },
}); true);
if(bt_test->change_state_callback) { if(bt_test->change_state_callback) {
bt_test->change_state_callback(state, bt_test->context); bt_test->change_state_callback(state, bt_test->context);
} }
@ -278,13 +288,15 @@ void bt_test_process_ok(BtTest* bt_test) {
void bt_test_process_back(BtTest* bt_test) { void bt_test_process_back(BtTest* bt_test) {
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
model->state = BtTestStateStopped; model->state = BtTestStateStopped;
model->rssi = 0.0f; model->rssi = 0.0f;
model->packets_num_rx = 0; model->packets_num_rx = 0;
model->packets_num_tx = 0; model->packets_num_tx = 0;
return false; },
}); false);
if(bt_test->back_callback) { if(bt_test->back_callback) {
bt_test->back_callback(bt_test->context); bt_test->back_callback(bt_test->context);
} }
@ -299,7 +311,9 @@ BtTest* bt_test_alloc() {
view_set_input_callback(bt_test->view, bt_test_input_callback); view_set_input_callback(bt_test->view, bt_test_input_callback);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
model->state = BtTestStateStopped; model->state = BtTestStateStopped;
model->message = "Ok - Start"; model->message = "Ok - Start";
BtTestParamArray_init(model->params); BtTestParamArray_init(model->params);
@ -308,8 +322,8 @@ BtTest* bt_test_alloc() {
model->rssi = 0.0f; model->rssi = 0.0f;
model->packets_num_tx = 0; model->packets_num_tx = 0;
model->packets_num_rx = 0; model->packets_num_rx = 0;
return true; },
}); true);
return bt_test; return bt_test;
} }
@ -318,15 +332,17 @@ void bt_test_free(BtTest* bt_test) {
furi_assert(bt_test); furi_assert(bt_test);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
BtTestParamArray_it_t it; BtTestParamArray_it_t it;
for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it); for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it);
BtTestParamArray_next(it)) { BtTestParamArray_next(it)) {
string_clear(BtTestParamArray_ref(it)->current_value_text); furi_string_free(BtTestParamArray_ref(it)->current_value_text);
} }
BtTestParamArray_clear(model->params); BtTestParamArray_clear(model->params);
return false; },
}); false);
view_free(bt_test->view); view_free(bt_test->view);
free(bt_test); free(bt_test);
} }
@ -347,16 +363,18 @@ BtTestParam* bt_test_param_add(
furi_assert(bt_test); furi_assert(bt_test);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view,
BtTestModel * model,
{
param = BtTestParamArray_push_new(model->params); param = BtTestParamArray_push_new(model->params);
param->label = label; param->label = label;
param->values_count = values_count; param->values_count = values_count;
param->change_callback = change_callback; param->change_callback = change_callback;
param->context = context; param->context = context;
param->current_value_index = 0; param->current_value_index = 0;
string_init(param->current_value_text); param->current_value_text = furi_string_alloc();
return true; },
}); true);
return param; return param;
} }
@ -364,28 +382,19 @@ BtTestParam* bt_test_param_add(
void bt_test_set_rssi(BtTest* bt_test, float rssi) { void bt_test_set_rssi(BtTest* bt_test, float rssi) {
furi_assert(bt_test); furi_assert(bt_test);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
model->rssi = rssi;
return true;
});
} }
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) { void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
furi_assert(bt_test); furi_assert(bt_test);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view, BtTestModel * model, { model->packets_num_tx = packets_num; }, true);
model->packets_num_tx = packets_num;
return true;
});
} }
void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) { void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) {
furi_assert(bt_test); furi_assert(bt_test);
with_view_model( with_view_model(
bt_test->view, (BtTestModel * model) { bt_test->view, BtTestModel * model, { model->packets_num_rx = packets_num; }, true);
model->packets_num_rx = packets_num;
return true;
});
} }
void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback) { void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback) {
@ -410,7 +419,7 @@ void bt_test_set_current_value_index(BtTestParam* param, uint8_t current_value_i
} }
void bt_test_set_current_value_text(BtTestParam* param, const char* current_value_text) { void bt_test_set_current_value_text(BtTestParam* param, const char* current_value_text) {
string_set_str(param->current_value_text, current_value_text); furi_string_set(param->current_value_text, current_value_text);
} }
uint8_t bt_test_get_current_value_index(BtTestParam* param) { uint8_t bt_test_get_current_value_index(BtTestParam* param) {

View File

@ -113,11 +113,11 @@ static void display_config_set_regulation_ratio(VariableItem* item) {
static void display_config_set_contrast(VariableItem* item) { static void display_config_set_contrast(VariableItem* item) {
DisplayTest* instance = variable_item_get_context(item); DisplayTest* instance = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);
string_t temp; FuriString* temp;
string_init(temp); temp = furi_string_alloc();
string_cat_printf(temp, "%d", index); furi_string_cat_printf(temp, "%d", index);
variable_item_set_current_value_text(item, string_get_cstr(temp)); variable_item_set_current_value_text(item, furi_string_get_cstr(temp));
string_clear(temp); furi_string_free(temp);
instance->config_contrast = index; instance->config_contrast = index;
display_test_reload_config(instance); display_test_reload_config(instance);
} }

View File

@ -110,7 +110,9 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) {
bool consumed = false; bool consumed = false;
if(event->type == InputTypeShort || event->type == InputTypeRepeat) { if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
with_view_model( with_view_model(
instance->view, (ViewDisplayTestModel * model) { instance->view,
ViewDisplayTestModel * model,
{
if(event->key == InputKeyLeft && model->test > 0) { if(event->key == InputKeyLeft && model->test > 0) {
model->test--; model->test--;
consumed = true; consumed = true;
@ -129,8 +131,8 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) {
model->flip_flop = !model->flip_flop; model->flip_flop = !model->flip_flop;
consumed = true; consumed = true;
} }
return consumed; },
}); consumed);
} }
return consumed; return consumed;
@ -149,10 +151,7 @@ static void view_display_test_exit(void* context) {
static void view_display_test_timer_callback(void* context) { static void view_display_test_timer_callback(void* context) {
ViewDisplayTest* instance = context; ViewDisplayTest* instance = context;
with_view_model( with_view_model(
instance->view, (ViewDisplayTestModel * model) { instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
model->counter++;
return true;
});
} }
ViewDisplayTest* view_display_test_alloc() { ViewDisplayTest* view_display_test_alloc() {

View File

@ -1,7 +1,6 @@
#include "assets_icons.h" #include "assets_icons.h"
#include "file_browser_app_i.h" #include "file_browser_app_i.h"
#include "gui/modules/file_browser.h" #include "gui/modules/file_browser.h"
#include "m-string.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <storage/storage.h> #include <storage/storage.h>
@ -47,7 +46,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) {
app->widget = widget_alloc(); app->widget = widget_alloc();
string_init(app->file_path); app->file_path = furi_string_alloc();
app->file_browser = file_browser_alloc(app->file_path); app->file_browser = file_browser_alloc(app->file_path);
file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true); file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true);
@ -84,7 +83,7 @@ void file_browser_app_free(FileBrowserApp* app) {
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_DIALOGS);
string_clear(app->file_path); furi_string_free(app->file_path);
free(app); free(app);
} }

View File

@ -22,7 +22,7 @@ struct FileBrowserApp {
Widget* widget; Widget* widget;
FileBrowser* file_browser; FileBrowser* file_browser;
string_t file_path; FuriString* file_path;
}; };
typedef enum { typedef enum {

View File

@ -1,8 +1,5 @@
#include "../file_browser_app_i.h" #include "../file_browser_app_i.h"
#include <core/check.h> #include <furi.h>
#include <core/log.h>
#include "furi_hal.h"
#include "m-string.h"
#define DEFAULT_PATH "/" #define DEFAULT_PATH "/"
#define EXTENSION "*" #define EXTENSION "*"

View File

@ -1,6 +1,5 @@
#include "../file_browser_app_i.h" #include "../file_browser_app_i.h"
#include "furi_hal.h" #include <furi.h>
#include "m-string.h"
void file_browser_scene_result_ok_callback(InputType type, void* context) { void file_browser_scene_result_ok_callback(InputType type, void* context) {
furi_assert(context); furi_assert(context);
@ -24,7 +23,13 @@ void file_browser_scene_result_on_enter(void* context) {
FileBrowserApp* app = context; FileBrowserApp* app = context;
widget_add_string_multiline_element( widget_add_string_multiline_element(
app->widget, 64, 10, AlignCenter, AlignTop, FontSecondary, string_get_cstr(app->file_path)); app->widget,
64,
10,
AlignCenter,
AlignTop,
FontSecondary,
furi_string_get_cstr(app->file_path));
view_dispatcher_switch_to_view(app->view_dispatcher, FileBrowserAppViewResult); view_dispatcher_switch_to_view(app->view_dispatcher, FileBrowserAppViewResult);
} }

View File

@ -19,7 +19,7 @@ bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) {
bool consumed = false; bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
string_set_str(app->file_path, ANY_PATH("badusb/demo_windows.txt")); furi_string_set(app->file_path, ANY_PATH("badusb/demo_windows.txt"));
scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser); scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser);
consumed = true; consumed = true;
} else if(event.type == SceneManagerEventTypeTick) { } else if(event.type == SceneManagerEventTypeTick) {

View File

@ -52,23 +52,29 @@ static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
static void lfrfid_debug_view_tune_button_up(LfRfidTuneView* tune_view) { static void lfrfid_debug_view_tune_button_up(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
if(model->pos > 0) model->pos--; if(model->pos > 0) model->pos--;
return true; },
}); true);
} }
static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) { static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
if(model->pos < 1) model->pos++; if(model->pos < 1) model->pos++;
return true; },
}); true);
} }
static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) { static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
if(model->pos == 0) { if(model->pos == 0) {
if(model->fine) { if(model->fine) {
model->ARR -= 1; model->ARR -= 1;
@ -84,13 +90,15 @@ static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) {
} }
model->dirty = true; model->dirty = true;
return true; },
}); true);
} }
static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) { static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
if(model->pos == 0) { if(model->pos == 0) {
if(model->fine) { if(model->fine) {
model->ARR += 1; model->ARR += 1;
@ -106,16 +114,13 @@ static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) {
} }
model->dirty = true; model->dirty = true;
return true; },
}); true);
} }
static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) { static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view, LfRfidTuneViewModel * model, { model->fine = !model->fine; }, true);
model->fine = !model->fine;
return true;
});
} }
static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* context) { static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* context) {
@ -158,14 +163,16 @@ LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel)); view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
model->dirty = true; model->dirty = true;
model->fine = false; model->fine = false;
model->ARR = 511; model->ARR = 511;
model->CCR = 255; model->CCR = 255;
model->pos = 0; model->pos = 0;
return true; },
}); true);
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback); view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback); view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
@ -184,24 +191,28 @@ View* lfrfid_debug_view_tune_get_view(LfRfidTuneView* tune_view) {
void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) { void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
model->dirty = true; model->dirty = true;
model->fine = false; model->fine = false;
model->ARR = 511; model->ARR = 511;
model->CCR = 255; model->CCR = 255;
model->pos = 0; model->pos = 0;
return true; },
}); true);
} }
bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) { bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
bool result = false; bool result = false;
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view,
LfRfidTuneViewModel * model,
{
result = model->dirty; result = model->dirty;
model->dirty = false; model->dirty = false;
return false; },
}); false);
return result; return result;
} }
@ -209,10 +220,7 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) { uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
uint32_t result = false; uint32_t result = false;
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
result = model->ARR;
return false;
});
return result; return result;
} }
@ -220,10 +228,7 @@ uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) { uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
uint32_t result = false; uint32_t result = false;
with_view_model( with_view_model(
tune_view->view, (LfRfidTuneViewModel * model) { tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
result = model->CCR;
return false;
});
return result; return result;
} }

View File

@ -1,10 +1,8 @@
#include <furi.h> #include <furi.h>
#include <m-string.h>
#include <gui/gui.h> #include <gui/gui.h>
#include <notification/notification.h> #include <notification/notification.h>
#include <notification/notification_messages.h> #include <notification/notification_messages.h>
#include <gui/elements.h> #include <gui/elements.h>
#include <stream_buffer.h>
#include <furi_hal_uart.h> #include <furi_hal_uart.h>
#include <furi_hal_console.h> #include <furi_hal_console.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
@ -21,11 +19,11 @@ typedef struct {
ViewDispatcher* view_dispatcher; ViewDispatcher* view_dispatcher;
View* view; View* view;
FuriThread* worker_thread; FuriThread* worker_thread;
StreamBufferHandle_t rx_stream; FuriStreamBuffer* rx_stream;
} UartEchoApp; } UartEchoApp;
typedef struct { typedef struct {
string_t text; FuriString* text;
} ListElement; } ListElement;
struct UartDumpModel { struct UartDumpModel {
@ -64,10 +62,11 @@ static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) {
canvas, canvas,
0, 0,
(i + 1) * (canvas_current_font_height(canvas) - 1), (i + 1) * (canvas_current_font_height(canvas) - 1),
string_get_cstr(model->list[i]->text)); furi_string_get_cstr(model->list[i]->text));
if(i == model->line) { if(i == model->line) {
uint8_t width = canvas_string_width(canvas, string_get_cstr(model->list[i]->text)); uint8_t width =
canvas_string_width(canvas, furi_string_get_cstr(model->list[i]->text));
canvas_draw_box( canvas_draw_box(
canvas, canvas,
@ -92,13 +91,11 @@ static uint32_t uart_echo_exit(void* context) {
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
furi_assert(context); furi_assert(context);
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
UartEchoApp* app = context; UartEchoApp* app = context;
if(ev == UartIrqEventRXNE) { if(ev == UartIrqEventRXNE) {
xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken); furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} }
} }
@ -113,7 +110,7 @@ static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
model->escape = true; model->escape = true;
} else if((data >= ' ' && data <= '~') || (data == '\n' || data == '\r')) { } else if((data >= ' ' && data <= '~') || (data == '\n' || data == '\r')) {
bool new_string_needed = false; bool new_string_needed = false;
if(string_size(model->list[model->line]->text) >= COLUMNS_ON_SCREEN) { if(furi_string_size(model->list[model->line]->text) >= COLUMNS_ON_SCREEN) {
new_string_needed = true; new_string_needed = true;
} else if((data == '\n' || data == '\r')) { } else if((data == '\n' || data == '\r')) {
// pack line breaks // pack line breaks
@ -132,13 +129,13 @@ static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
model->list[i - 1] = model->list[i]; model->list[i - 1] = model->list[i];
} }
string_reset(first->text); furi_string_reset(first->text);
model->list[model->line] = first; model->list[model->line] = first;
} }
} }
if(data != '\n' && data != '\r') { if(data != '\n' && data != '\r') {
string_push_back(model->list[model->line]->text, data); furi_string_push_back(model->list[model->line]->text, data);
} }
} }
model->last_char = data; model->last_char = data;
@ -158,25 +155,24 @@ static int32_t uart_echo_worker(void* context) {
size_t length = 0; size_t length = 0;
do { do {
uint8_t data[64]; uint8_t data[64];
length = xStreamBufferReceive(app->rx_stream, data, 64, 0); length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
if(length > 0) { if(length > 0) {
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
with_view_model( with_view_model(
app->view, (UartDumpModel * model) { app->view,
UartDumpModel * model,
{
for(size_t i = 0; i < length; i++) { for(size_t i = 0; i < length; i++) {
uart_echo_push_to_list(model, data[i]); uart_echo_push_to_list(model, data[i]);
} }
return false; },
}); false);
} }
} while(length > 0); } while(length > 0);
notification_message(app->notification, &sequence_notification); notification_message(app->notification, &sequence_notification);
with_view_model( with_view_model(
app->view, (UartDumpModel * model) { app->view, UartDumpModel * model, { UNUSED(model); }, true);
UNUSED(model);
return true;
});
} }
} }
@ -186,7 +182,7 @@ static int32_t uart_echo_worker(void* context) {
static UartEchoApp* uart_echo_app_alloc() { static UartEchoApp* uart_echo_app_alloc() {
UartEchoApp* app = malloc(sizeof(UartEchoApp)); UartEchoApp* app = malloc(sizeof(UartEchoApp));
app->rx_stream = xStreamBufferCreate(2048, 1); app->rx_stream = furi_stream_buffer_alloc(2048, 1);
// Gui // Gui
app->gui = furi_record_open(RECORD_GUI); app->gui = furi_record_open(RECORD_GUI);
@ -203,15 +199,17 @@ static UartEchoApp* uart_echo_app_alloc() {
view_set_input_callback(app->view, uart_echo_view_input_callback); view_set_input_callback(app->view, uart_echo_view_input_callback);
view_allocate_model(app->view, ViewModelTypeLocking, sizeof(UartDumpModel)); view_allocate_model(app->view, ViewModelTypeLocking, sizeof(UartDumpModel));
with_view_model( with_view_model(
app->view, (UartDumpModel * model) { app->view,
UartDumpModel * model,
{
for(size_t i = 0; i < LINES_ON_SCREEN; i++) { for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
model->line = 0; model->line = 0;
model->escape = false; model->escape = false;
model->list[i] = malloc(sizeof(ListElement)); model->list[i] = malloc(sizeof(ListElement));
string_init(model->list[i]->text); model->list[i]->text = furi_string_alloc();
} }
return true; },
}); true);
view_set_previous_callback(app->view, uart_echo_exit); view_set_previous_callback(app->view, uart_echo_exit);
view_dispatcher_add_view(app->view_dispatcher, 0, app->view); view_dispatcher_add_view(app->view_dispatcher, 0, app->view);
@ -245,13 +243,15 @@ static void uart_echo_app_free(UartEchoApp* app) {
view_dispatcher_remove_view(app->view_dispatcher, 0); view_dispatcher_remove_view(app->view_dispatcher, 0);
with_view_model( with_view_model(
app->view, (UartDumpModel * model) { app->view,
UartDumpModel * model,
{
for(size_t i = 0; i < LINES_ON_SCREEN; i++) { for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
string_clear(model->list[i]->text); furi_string_free(model->list[i]->text);
free(model->list[i]); free(model->list[i]);
} }
return true; },
}); true);
view_free(app->view); view_free(app->view);
view_dispatcher_free(app->view_dispatcher); view_dispatcher_free(app->view_dispatcher);
@ -260,7 +260,7 @@ static void uart_echo_app_free(UartEchoApp* app) {
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
app->gui = NULL; app->gui = NULL;
vStreamBufferDelete(app->rx_stream); furi_stream_buffer_free(app->rx_stream);
// Free rest // Free rest
free(app); free(app);

View File

@ -58,7 +58,7 @@ static const char* test_data_win = "Filetype: Flipper Format test\r\n"
#define ARRAY_W_BSIZE(x) (x), (sizeof(x)) #define ARRAY_W_BSIZE(x) (x), (sizeof(x))
MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) { MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
string_t tmpstr; FuriString* tmpstr;
uint32_t version; uint32_t version;
uint32_t uint32_data[COUNT_OF(test_uint_data)]; uint32_t uint32_data[COUNT_OF(test_uint_data)];
int32_t int32_data[COUNT_OF(test_int_data)]; int32_t int32_data[COUNT_OF(test_int_data)];
@ -101,14 +101,14 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format))); mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
// read test // read test
string_init(tmpstr); tmpstr = furi_string_alloc();
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version)); mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr)); mu_assert_string_eq(test_filetype, furi_string_get_cstr(tmpstr));
mu_assert_int_eq(test_version, version); mu_assert_int_eq(test_version, version);
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr)); mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
mu_assert_string_eq(test_string_data, string_get_cstr(tmpstr)); mu_assert_string_eq(test_string_data, furi_string_get_cstr(tmpstr));
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count)); mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
mu_assert_int_eq(COUNT_OF(test_int_data), count); mu_assert_int_eq(COUNT_OF(test_int_data), count);
@ -133,7 +133,7 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr)); mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
string_clear(tmpstr); furi_string_free(tmpstr);
// update data // update data
mu_check(flipper_format_rewind(flipper_format)); mu_check(flipper_format_rewind(flipper_format));
@ -155,14 +155,14 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
uint8_t hex_updated_data[COUNT_OF(test_hex_updated_data)]; uint8_t hex_updated_data[COUNT_OF(test_hex_updated_data)];
mu_check(flipper_format_rewind(flipper_format)); mu_check(flipper_format_rewind(flipper_format));
string_init(tmpstr); tmpstr = furi_string_alloc();
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version)); mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr)); mu_assert_string_eq(test_filetype, furi_string_get_cstr(tmpstr));
mu_assert_int_eq(test_version, version); mu_assert_int_eq(test_version, version);
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr)); mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
mu_assert_string_eq(test_string_updated_data, string_get_cstr(tmpstr)); mu_assert_string_eq(test_string_updated_data, furi_string_get_cstr(tmpstr));
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count)); mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
mu_assert_int_eq(COUNT_OF(test_int_updated_data), count); mu_assert_int_eq(COUNT_OF(test_int_updated_data), count);
@ -190,7 +190,7 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr)); mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
string_clear(tmpstr); furi_string_free(tmpstr);
// update data // update data
mu_check(flipper_format_rewind(flipper_format)); mu_check(flipper_format_rewind(flipper_format));
@ -214,14 +214,14 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
uint8_t hex_new_data[COUNT_OF(test_hex_new_data)]; uint8_t hex_new_data[COUNT_OF(test_hex_new_data)];
mu_check(flipper_format_rewind(flipper_format)); mu_check(flipper_format_rewind(flipper_format));
string_init(tmpstr); tmpstr = furi_string_alloc();
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version)); mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr)); mu_assert_string_eq(test_filetype, furi_string_get_cstr(tmpstr));
mu_assert_int_eq(test_version, version); mu_assert_int_eq(test_version, version);
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr)); mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
mu_assert_string_eq(test_string_updated_2_data, string_get_cstr(tmpstr)); mu_assert_string_eq(test_string_updated_2_data, furi_string_get_cstr(tmpstr));
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count)); mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
mu_assert_int_eq(COUNT_OF(test_int_updated_2_data), count); mu_assert_int_eq(COUNT_OF(test_int_updated_2_data), count);
@ -255,7 +255,7 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr)); mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
string_clear(tmpstr); furi_string_free(tmpstr);
// delete key test // delete key test
mu_check(flipper_format_rewind(flipper_format)); mu_check(flipper_format_rewind(flipper_format));

View File

@ -57,6 +57,23 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n"
"Hex data: DE AD BE"; "Hex data: DE AD BE";
#define READ_TEST_FLP "ff_flp.test" #define READ_TEST_FLP "ff_flp.test"
#define READ_TEST_ODD "ff_oddities.test"
static const char* test_data_odd = "Filetype: Flipper File test\n"
// Tabs before newline
"Version: 666\t\t\n"
"# This is comment\n"
// Windows newline in a UNIX file
"String data: String\r\n"
// Trailing whitespace
"Int32 data: 1234 -6345 7813 0 \n"
// Extra whitespace
"Uint32 data: 1234 0 5678 9098 7654321 \n"
// Mixed whitespace
"Float data: 1.5\t \t1000.0\n"
// Leading tabs after key
"Bool data:\t\ttrue false\n"
// Mixed trailing whitespace
"Hex data: DE AD BE\t ";
// data created by user on linux machine // data created by user on linux machine
static const char* test_file_linux = TEST_DIR READ_TEST_NIX; static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
@ -64,6 +81,8 @@ static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
static const char* test_file_windows = TEST_DIR READ_TEST_WIN; static const char* test_file_windows = TEST_DIR READ_TEST_WIN;
// data created by flipper itself // data created by flipper itself
static const char* test_file_flipper = TEST_DIR READ_TEST_FLP; static const char* test_file_flipper = TEST_DIR READ_TEST_FLP;
// data containing odd user input
static const char* test_file_oddities = TEST_DIR READ_TEST_ODD;
static bool storage_write_string(const char* path, const char* data) { static bool storage_write_string(const char* path, const char* data) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
@ -102,8 +121,8 @@ static bool test_read(const char* file_name) {
bool result = false; bool result = false;
FlipperFormat* file = flipper_format_file_alloc(storage); FlipperFormat* file = flipper_format_file_alloc(storage);
string_t string_value; FuriString* string_value;
string_init(string_value); string_value = furi_string_alloc();
uint32_t uint32_value; uint32_t uint32_value;
void* scratchpad = malloc(512); void* scratchpad = malloc(512);
@ -111,11 +130,11 @@ static bool test_read(const char* file_name) {
if(!flipper_format_file_open_existing(file, file_name)) break; if(!flipper_format_file_open_existing(file, file_name)) break;
if(!flipper_format_read_header(file, string_value, &uint32_value)) break; if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
if(string_cmp_str(string_value, test_filetype) != 0) break; if(furi_string_cmp_str(string_value, test_filetype) != 0) break;
if(uint32_value != test_version) break; if(uint32_value != test_version) break;
if(!flipper_format_read_string(file, test_string_key, string_value)) break; if(!flipper_format_read_string(file, test_string_key, string_value)) break;
if(string_cmp_str(string_value, test_string_data) != 0) break; if(furi_string_cmp_str(string_value, test_string_data) != 0) break;
if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break; if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_int_data)) break; if(uint32_value != COUNT_OF(test_int_data)) break;
@ -150,7 +169,7 @@ static bool test_read(const char* file_name) {
} while(false); } while(false);
free(scratchpad); free(scratchpad);
string_clear(string_value); furi_string_free(string_value);
flipper_format_free(file); flipper_format_free(file);
@ -164,8 +183,8 @@ static bool test_read_updated(const char* file_name) {
bool result = false; bool result = false;
FlipperFormat* file = flipper_format_file_alloc(storage); FlipperFormat* file = flipper_format_file_alloc(storage);
string_t string_value; FuriString* string_value;
string_init(string_value); string_value = furi_string_alloc();
uint32_t uint32_value; uint32_t uint32_value;
void* scratchpad = malloc(512); void* scratchpad = malloc(512);
@ -173,11 +192,11 @@ static bool test_read_updated(const char* file_name) {
if(!flipper_format_file_open_existing(file, file_name)) break; if(!flipper_format_file_open_existing(file, file_name)) break;
if(!flipper_format_read_header(file, string_value, &uint32_value)) break; if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
if(string_cmp_str(string_value, test_filetype) != 0) break; if(furi_string_cmp_str(string_value, test_filetype) != 0) break;
if(uint32_value != test_version) break; if(uint32_value != test_version) break;
if(!flipper_format_read_string(file, test_string_key, string_value)) break; if(!flipper_format_read_string(file, test_string_key, string_value)) break;
if(string_cmp_str(string_value, test_string_updated_data) != 0) break; if(furi_string_cmp_str(string_value, test_string_updated_data) != 0) break;
if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break; if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_int_updated_data)) break; if(uint32_value != COUNT_OF(test_int_updated_data)) break;
@ -228,7 +247,7 @@ static bool test_read_updated(const char* file_name) {
} while(false); } while(false);
free(scratchpad); free(scratchpad);
string_clear(string_value); furi_string_free(string_value);
flipper_format_free(file); flipper_format_free(file);
@ -401,14 +420,14 @@ static bool test_read_multikey(const char* file_name) {
bool result = false; bool result = false;
FlipperFormat* file = flipper_format_file_alloc(storage); FlipperFormat* file = flipper_format_file_alloc(storage);
string_t string_value; FuriString* string_value;
string_init(string_value); string_value = furi_string_alloc();
uint32_t uint32_value; uint32_t uint32_value;
do { do {
if(!flipper_format_file_open_existing(file, file_name)) break; if(!flipper_format_file_open_existing(file, file_name)) break;
if(!flipper_format_read_header(file, string_value, &uint32_value)) break; if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
if(string_cmp_str(string_value, test_filetype) != 0) break; if(furi_string_cmp_str(string_value, test_filetype) != 0) break;
if(uint32_value != test_version) break; if(uint32_value != test_version) break;
bool error = false; bool error = false;
@ -429,7 +448,7 @@ static bool test_read_multikey(const char* file_name) {
result = true; result = true;
} while(false); } while(false);
string_clear(string_value); furi_string_free(string_value);
flipper_format_free(file); flipper_format_free(file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
@ -503,6 +522,12 @@ MU_TEST(flipper_format_multikey_test) {
mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error"); mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error");
} }
MU_TEST(flipper_format_oddities_test) {
mu_assert(
storage_write_string(test_file_oddities, test_data_odd), "Write test error [Oddities]");
mu_assert(test_read(test_file_linux), "Read test error [Oddities]");
}
MU_TEST_SUITE(flipper_format) { MU_TEST_SUITE(flipper_format) {
tests_setup(); tests_setup();
MU_RUN_TEST(flipper_format_write_test); MU_RUN_TEST(flipper_format_write_test);
@ -516,6 +541,7 @@ MU_TEST_SUITE(flipper_format) {
MU_RUN_TEST(flipper_format_update_2_test); MU_RUN_TEST(flipper_format_update_2_test);
MU_RUN_TEST(flipper_format_update_2_result_test); MU_RUN_TEST(flipper_format_update_2_result_test);
MU_RUN_TEST(flipper_format_multikey_test); MU_RUN_TEST(flipper_format_multikey_test);
MU_RUN_TEST(flipper_format_oddities_test);
tests_teardown(); tests_teardown();
} }

View File

@ -0,0 +1,469 @@
#include <furi.h>
#include "../minunit.h"
static void test_setup(void) {
}
static void test_teardown(void) {
}
static FuriString* furi_string_alloc_vprintf_test(const char format[], ...) {
va_list args;
va_start(args, format);
FuriString* string = furi_string_alloc_vprintf(format, args);
va_end(args);
return string;
}
MU_TEST(mu_test_furi_string_alloc_free) {
FuriString* tmp;
FuriString* string;
// test alloc and free
string = furi_string_alloc();
mu_check(string != NULL);
mu_check(furi_string_empty(string));
furi_string_free(string);
// test furi_string_alloc_set_str and free
string = furi_string_alloc_set_str("test");
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
mu_check(furi_string_cmp(string, "test") == 0);
furi_string_free(string);
// test furi_string_alloc_set and free
tmp = furi_string_alloc_set("more");
string = furi_string_alloc_set(tmp);
furi_string_free(tmp);
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
mu_check(furi_string_cmp(string, "more") == 0);
furi_string_free(string);
// test alloc_printf and free
string = furi_string_alloc_printf("test %d %s %c 0x%02x", 1, "two", '3', 0x04);
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
mu_check(furi_string_cmp(string, "test 1 two 3 0x04") == 0);
furi_string_free(string);
// test alloc_vprintf and free
string = furi_string_alloc_vprintf_test("test %d %s %c 0x%02x", 4, "five", '6', 0x07);
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
mu_check(furi_string_cmp(string, "test 4 five 6 0x07") == 0);
furi_string_free(string);
// test alloc_move and free
tmp = furi_string_alloc_set("move");
string = furi_string_alloc_move(tmp);
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
mu_check(furi_string_cmp(string, "move") == 0);
furi_string_free(string);
}
MU_TEST(mu_test_furi_string_mem) {
FuriString* string = furi_string_alloc_set("test");
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
// TODO: how to test furi_string_reserve?
// test furi_string_reset
furi_string_reset(string);
mu_check(furi_string_empty(string));
// test furi_string_swap
furi_string_set(string, "test");
FuriString* swap_string = furi_string_alloc_set("swap");
furi_string_swap(string, swap_string);
mu_check(furi_string_cmp(string, "swap") == 0);
mu_check(furi_string_cmp(swap_string, "test") == 0);
furi_string_free(swap_string);
// test furi_string_move
FuriString* move_string = furi_string_alloc_set("move");
furi_string_move(string, move_string);
mu_check(furi_string_cmp(string, "move") == 0);
// move_string is now empty
// and tested by leaked memory check at the end of the tests
furi_string_set(string, "abracadabra");
// test furi_string_hash
mu_assert_int_eq(0xc3bc16d7, furi_string_hash(string));
// test furi_string_size
mu_assert_int_eq(11, furi_string_size(string));
// test furi_string_empty
mu_check(!furi_string_empty(string));
furi_string_reset(string);
mu_check(furi_string_empty(string));
furi_string_free(string);
}
MU_TEST(mu_test_furi_string_getters) {
FuriString* string = furi_string_alloc_set("test");
// test furi_string_get_char
mu_check(furi_string_get_char(string, 0) == 't');
mu_check(furi_string_get_char(string, 1) == 'e');
mu_check(furi_string_get_char(string, 2) == 's');
mu_check(furi_string_get_char(string, 3) == 't');
// test furi_string_get_cstr
mu_assert_string_eq("test", furi_string_get_cstr(string));
furi_string_free(string);
}
static FuriString* furi_string_vprintf_test(FuriString* string, const char format[], ...) {
va_list args;
va_start(args, format);
furi_string_vprintf(string, format, args);
va_end(args);
return string;
}
MU_TEST(mu_test_furi_string_setters) {
FuriString* tmp;
FuriString* string = furi_string_alloc();
// test furi_string_set_str
furi_string_set_str(string, "test");
mu_assert_string_eq("test", furi_string_get_cstr(string));
// test furi_string_set
tmp = furi_string_alloc_set("more");
furi_string_set(string, tmp);
furi_string_free(tmp);
mu_assert_string_eq("more", furi_string_get_cstr(string));
// test furi_string_set_strn
furi_string_set_strn(string, "test", 2);
mu_assert_string_eq("te", furi_string_get_cstr(string));
// test furi_string_set_char
furi_string_set_char(string, 0, 'a');
furi_string_set_char(string, 1, 'b');
mu_assert_string_eq("ab", furi_string_get_cstr(string));
// test furi_string_set_n
tmp = furi_string_alloc_set("dodecahedron");
furi_string_set_n(string, tmp, 4, 5);
furi_string_free(tmp);
mu_assert_string_eq("cahed", furi_string_get_cstr(string));
// test furi_string_printf
furi_string_printf(string, "test %d %s %c 0x%02x", 1, "two", '3', 0x04);
mu_assert_string_eq("test 1 two 3 0x04", furi_string_get_cstr(string));
// test furi_string_vprintf
furi_string_vprintf_test(string, "test %d %s %c 0x%02x", 4, "five", '6', 0x07);
mu_assert_string_eq("test 4 five 6 0x07", furi_string_get_cstr(string));
furi_string_free(string);
}
static FuriString* furi_string_cat_vprintf_test(FuriString* string, const char format[], ...) {
va_list args;
va_start(args, format);
furi_string_cat_vprintf(string, format, args);
va_end(args);
return string;
}
MU_TEST(mu_test_furi_string_appends) {
FuriString* tmp;
FuriString* string = furi_string_alloc();
// test furi_string_push_back
furi_string_push_back(string, 't');
furi_string_push_back(string, 'e');
furi_string_push_back(string, 's');
furi_string_push_back(string, 't');
mu_assert_string_eq("test", furi_string_get_cstr(string));
furi_string_push_back(string, '!');
mu_assert_string_eq("test!", furi_string_get_cstr(string));
// test furi_string_cat_str
furi_string_cat_str(string, "test");
mu_assert_string_eq("test!test", furi_string_get_cstr(string));
// test furi_string_cat
tmp = furi_string_alloc_set("more");
furi_string_cat(string, tmp);
furi_string_free(tmp);
mu_assert_string_eq("test!testmore", furi_string_get_cstr(string));
// test furi_string_cat_printf
furi_string_cat_printf(string, "test %d %s %c 0x%02x", 1, "two", '3', 0x04);
mu_assert_string_eq("test!testmoretest 1 two 3 0x04", furi_string_get_cstr(string));
// test furi_string_cat_vprintf
furi_string_cat_vprintf_test(string, "test %d %s %c 0x%02x", 4, "five", '6', 0x07);
mu_assert_string_eq(
"test!testmoretest 1 two 3 0x04test 4 five 6 0x07", furi_string_get_cstr(string));
furi_string_free(string);
}
MU_TEST(mu_test_furi_string_compare) {
FuriString* string_1 = furi_string_alloc_set("string_1");
FuriString* string_2 = furi_string_alloc_set("string_2");
// test furi_string_cmp
mu_assert_int_eq(0, furi_string_cmp(string_1, string_1));
mu_assert_int_eq(0, furi_string_cmp(string_2, string_2));
mu_assert_int_eq(-1, furi_string_cmp(string_1, string_2));
mu_assert_int_eq(1, furi_string_cmp(string_2, string_1));
// test furi_string_cmp_str
mu_assert_int_eq(0, furi_string_cmp_str(string_1, "string_1"));
mu_assert_int_eq(0, furi_string_cmp_str(string_2, "string_2"));
mu_assert_int_eq(-1, furi_string_cmp_str(string_1, "string_2"));
mu_assert_int_eq(1, furi_string_cmp_str(string_2, "string_1"));
// test furi_string_cmpi
furi_string_set(string_1, "string");
furi_string_set(string_2, "StrIng");
mu_assert_int_eq(0, furi_string_cmpi(string_1, string_1));
mu_assert_int_eq(0, furi_string_cmpi(string_2, string_2));
mu_assert_int_eq(0, furi_string_cmpi(string_1, string_2));
mu_assert_int_eq(0, furi_string_cmpi(string_2, string_1));
furi_string_set(string_1, "string_1");
furi_string_set(string_2, "StrIng_2");
mu_assert_int_eq(32, furi_string_cmp(string_1, string_2));
mu_assert_int_eq(-32, furi_string_cmp(string_2, string_1));
mu_assert_int_eq(-1, furi_string_cmpi(string_1, string_2));
mu_assert_int_eq(1, furi_string_cmpi(string_2, string_1));
// test furi_string_cmpi_str
furi_string_set(string_1, "string");
mu_assert_int_eq(0, furi_string_cmp_str(string_1, "string"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "String"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "STring"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "STRing"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "STRIng"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "STRINg"));
mu_assert_int_eq(32, furi_string_cmp_str(string_1, "STRING"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "string"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "String"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "STring"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "STRing"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "STRIng"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "STRINg"));
mu_assert_int_eq(0, furi_string_cmpi_str(string_1, "STRING"));
furi_string_free(string_1);
furi_string_free(string_2);
}
MU_TEST(mu_test_furi_string_search) {
// 012345678901234567
FuriString* haystack = furi_string_alloc_set("test321test123test");
FuriString* needle = furi_string_alloc_set("test");
// test furi_string_search
mu_assert_int_eq(0, furi_string_search(haystack, needle));
mu_assert_int_eq(7, furi_string_search(haystack, needle, 1));
mu_assert_int_eq(14, furi_string_search(haystack, needle, 8));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search(haystack, needle, 15));
FuriString* tmp = furi_string_alloc_set("testnone");
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search(haystack, tmp));
furi_string_free(tmp);
// test furi_string_search_str
mu_assert_int_eq(0, furi_string_search_str(haystack, "test"));
mu_assert_int_eq(7, furi_string_search_str(haystack, "test", 1));
mu_assert_int_eq(14, furi_string_search_str(haystack, "test", 8));
mu_assert_int_eq(4, furi_string_search_str(haystack, "321"));
mu_assert_int_eq(11, furi_string_search_str(haystack, "123"));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search_str(haystack, "testnone"));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search_str(haystack, "test", 15));
// test furi_string_search_char
mu_assert_int_eq(0, furi_string_search_char(haystack, 't'));
mu_assert_int_eq(1, furi_string_search_char(haystack, 'e'));
mu_assert_int_eq(2, furi_string_search_char(haystack, 's'));
mu_assert_int_eq(3, furi_string_search_char(haystack, 't', 1));
mu_assert_int_eq(7, furi_string_search_char(haystack, 't', 4));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search_char(haystack, 'x'));
// test furi_string_search_rchar
mu_assert_int_eq(17, furi_string_search_rchar(haystack, 't'));
mu_assert_int_eq(15, furi_string_search_rchar(haystack, 'e'));
mu_assert_int_eq(16, furi_string_search_rchar(haystack, 's'));
mu_assert_int_eq(13, furi_string_search_rchar(haystack, '3'));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search_rchar(haystack, '3', 14));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_search_rchar(haystack, 'x'));
furi_string_free(haystack);
furi_string_free(needle);
}
MU_TEST(mu_test_furi_string_equality) {
FuriString* string = furi_string_alloc_set("test");
FuriString* string_eq = furi_string_alloc_set("test");
FuriString* string_neq = furi_string_alloc_set("test2");
// test furi_string_equal
mu_check(furi_string_equal(string, string_eq));
mu_check(!furi_string_equal(string, string_neq));
// test furi_string_equal_str
mu_check(furi_string_equal_str(string, "test"));
mu_check(!furi_string_equal_str(string, "test2"));
mu_check(furi_string_equal_str(string_neq, "test2"));
mu_check(!furi_string_equal_str(string_neq, "test"));
furi_string_free(string);
furi_string_free(string_eq);
furi_string_free(string_neq);
}
MU_TEST(mu_test_furi_string_replace) {
FuriString* needle = furi_string_alloc_set("test");
FuriString* replace = furi_string_alloc_set("replace");
FuriString* string = furi_string_alloc_set("test123test");
// test furi_string_replace_at
furi_string_replace_at(string, 4, 3, "!biglongword!");
mu_assert_string_eq("test!biglongword!test", furi_string_get_cstr(string));
// test furi_string_replace
mu_assert_int_eq(17, furi_string_replace(string, needle, replace, 1));
mu_assert_string_eq("test!biglongword!replace", furi_string_get_cstr(string));
mu_assert_int_eq(0, furi_string_replace(string, needle, replace));
mu_assert_string_eq("replace!biglongword!replace", furi_string_get_cstr(string));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_replace(string, needle, replace));
mu_assert_string_eq("replace!biglongword!replace", furi_string_get_cstr(string));
// test furi_string_replace_str
mu_assert_int_eq(20, furi_string_replace_str(string, "replace", "test", 1));
mu_assert_string_eq("replace!biglongword!test", furi_string_get_cstr(string));
mu_assert_int_eq(0, furi_string_replace_str(string, "replace", "test"));
mu_assert_string_eq("test!biglongword!test", furi_string_get_cstr(string));
mu_assert_int_eq(FURI_STRING_FAILURE, furi_string_replace_str(string, "replace", "test"));
mu_assert_string_eq("test!biglongword!test", furi_string_get_cstr(string));
// test furi_string_replace_all
furi_string_replace_all(string, needle, replace);
mu_assert_string_eq("replace!biglongword!replace", furi_string_get_cstr(string));
// test furi_string_replace_all_str
furi_string_replace_all_str(string, "replace", "test");
mu_assert_string_eq("test!biglongword!test", furi_string_get_cstr(string));
furi_string_free(string);
furi_string_free(needle);
furi_string_free(replace);
}
MU_TEST(mu_test_furi_string_start_end) {
FuriString* string = furi_string_alloc_set("start_end");
FuriString* start = furi_string_alloc_set("start");
FuriString* end = furi_string_alloc_set("end");
// test furi_string_start_with
mu_check(furi_string_start_with(string, start));
mu_check(!furi_string_start_with(string, end));
// test furi_string_start_with_str
mu_check(furi_string_start_with_str(string, "start"));
mu_check(!furi_string_start_with_str(string, "end"));
// test furi_string_end_with
mu_check(furi_string_end_with(string, end));
mu_check(!furi_string_end_with(string, start));
// test furi_string_end_with_str
mu_check(furi_string_end_with_str(string, "end"));
mu_check(!furi_string_end_with_str(string, "start"));
furi_string_free(string);
furi_string_free(start);
furi_string_free(end);
}
MU_TEST(mu_test_furi_string_trim) {
FuriString* string = furi_string_alloc_set("biglongstring");
// test furi_string_left
furi_string_left(string, 7);
mu_assert_string_eq("biglong", furi_string_get_cstr(string));
// test furi_string_right
furi_string_right(string, 3);
mu_assert_string_eq("long", furi_string_get_cstr(string));
// test furi_string_mid
furi_string_mid(string, 1, 2);
mu_assert_string_eq("on", furi_string_get_cstr(string));
// test furi_string_trim
furi_string_set(string, " \n\r\tbiglongstring \n\r\t ");
furi_string_trim(string);
mu_assert_string_eq("biglongstring", furi_string_get_cstr(string));
furi_string_set(string, "aaaabaaaabbaaabaaaabbtestaaaaaabbaaabaababaa");
furi_string_trim(string, "ab");
mu_assert_string_eq("test", furi_string_get_cstr(string));
furi_string_free(string);
}
MU_TEST(mu_test_furi_string_utf8) {
FuriString* utf8_string = furi_string_alloc_set("イルカ");
// test furi_string_utf8_length
mu_assert_int_eq(9, furi_string_size(utf8_string));
mu_assert_int_eq(3, furi_string_utf8_length(utf8_string));
// test furi_string_utf8_decode
const uint8_t dolphin_emoji_array[4] = {0xF0, 0x9F, 0x90, 0xAC};
FuriStringUTF8State state = FuriStringUTF8StateStarting;
FuriStringUnicodeValue value = 0;
furi_string_utf8_decode(dolphin_emoji_array[0], &state, &value);
mu_assert_int_eq(FuriStringUTF8StateDecoding3, state);
furi_string_utf8_decode(dolphin_emoji_array[1], &state, &value);
mu_assert_int_eq(FuriStringUTF8StateDecoding2, state);
furi_string_utf8_decode(dolphin_emoji_array[2], &state, &value);
mu_assert_int_eq(FuriStringUTF8StateDecoding1, state);
furi_string_utf8_decode(dolphin_emoji_array[3], &state, &value);
mu_assert_int_eq(FuriStringUTF8StateStarting, state);
mu_assert_int_eq(0x1F42C, value);
// test furi_string_utf8_push
furi_string_set(utf8_string, "");
furi_string_utf8_push(utf8_string, value);
mu_assert_string_eq("🐬", furi_string_get_cstr(utf8_string));
furi_string_free(utf8_string);
}
MU_TEST_SUITE(test_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(mu_test_furi_string_alloc_free);
MU_RUN_TEST(mu_test_furi_string_mem);
MU_RUN_TEST(mu_test_furi_string_getters);
MU_RUN_TEST(mu_test_furi_string_setters);
MU_RUN_TEST(mu_test_furi_string_appends);
MU_RUN_TEST(mu_test_furi_string_compare);
MU_RUN_TEST(mu_test_furi_string_search);
MU_RUN_TEST(mu_test_furi_string_equality);
MU_RUN_TEST(mu_test_furi_string_replace);
MU_RUN_TEST(mu_test_furi_string_start_end);
MU_RUN_TEST(mu_test_furi_string_trim);
MU_RUN_TEST(mu_test_furi_string_utf8);
}
int run_minunit_test_furi_string() {
MU_RUN_SUITE(test_suite);
return MU_EXIT_CODE;
}

View File

@ -11,7 +11,7 @@
typedef struct { typedef struct {
InfraredDecoderHandler* decoder_handler; InfraredDecoderHandler* decoder_handler;
InfraredEncoderHandler* encoder_handler; InfraredEncoderHandler* encoder_handler;
string_t file_path; FuriString* file_path;
FlipperFormat* ff; FlipperFormat* ff;
} InfraredTest; } InfraredTest;
@ -23,7 +23,7 @@ static void infrared_test_alloc() {
test->decoder_handler = infrared_alloc_decoder(); test->decoder_handler = infrared_alloc_decoder();
test->encoder_handler = infrared_alloc_encoder(); test->encoder_handler = infrared_alloc_encoder();
test->ff = flipper_format_buffered_file_alloc(storage); test->ff = flipper_format_buffered_file_alloc(storage);
string_init(test->file_path); test->file_path = furi_string_alloc();
} }
static void infrared_test_free() { static void infrared_test_free() {
@ -31,18 +31,18 @@ static void infrared_test_free() {
infrared_free_decoder(test->decoder_handler); infrared_free_decoder(test->decoder_handler);
infrared_free_encoder(test->encoder_handler); infrared_free_encoder(test->encoder_handler);
flipper_format_free(test->ff); flipper_format_free(test->ff);
string_clear(test->file_path); furi_string_free(test->file_path);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
free(test); free(test);
test = NULL; test = NULL;
} }
static bool infrared_test_prepare_file(const char* protocol_name) { static bool infrared_test_prepare_file(const char* protocol_name) {
string_t file_type; FuriString* file_type;
string_init(file_type); file_type = furi_string_alloc();
bool success = false; bool success = false;
string_printf( furi_string_printf(
test->file_path, test->file_path,
"%s%s%s%s", "%s%s%s%s",
IR_TEST_FILES_DIR, IR_TEST_FILES_DIR,
@ -52,14 +52,15 @@ static bool infrared_test_prepare_file(const char* protocol_name) {
do { do {
uint32_t format_version; uint32_t format_version;
if(!flipper_format_buffered_file_open_existing(test->ff, string_get_cstr(test->file_path))) if(!flipper_format_buffered_file_open_existing(
test->ff, furi_string_get_cstr(test->file_path)))
break; break;
if(!flipper_format_read_header(test->ff, file_type, &format_version)) break; if(!flipper_format_read_header(test->ff, file_type, &format_version)) break;
if(string_cmp_str(file_type, "IR tests file") || format_version != 1) break; if(furi_string_cmp_str(file_type, "IR tests file") || format_version != 1) break;
success = true; success = true;
} while(false); } while(false);
string_clear(file_type); furi_string_free(file_type);
return success; return success;
} }
@ -68,18 +69,18 @@ static bool infrared_test_load_raw_signal(
const char* signal_name, const char* signal_name,
uint32_t** timings, uint32_t** timings,
uint32_t* timings_count) { uint32_t* timings_count) {
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
bool success = false; bool success = false;
do { do {
bool is_name_found = false; bool is_name_found = false;
for(; !is_name_found && flipper_format_read_string(ff, "name", buf); for(; !is_name_found && flipper_format_read_string(ff, "name", buf);
is_name_found = !string_cmp_str(buf, signal_name)) is_name_found = !furi_string_cmp(buf, signal_name))
; ;
if(!is_name_found) break; if(!is_name_found) break;
if(!flipper_format_read_string(ff, "type", buf) || string_cmp_str(buf, "raw")) break; if(!flipper_format_read_string(ff, "type", buf) || furi_string_cmp_str(buf, "raw")) break;
if(!flipper_format_get_value_count(ff, "data", timings_count)) break; if(!flipper_format_get_value_count(ff, "data", timings_count)) break;
if(!*timings_count) break; if(!*timings_count) break;
@ -91,18 +92,18 @@ static bool infrared_test_load_raw_signal(
success = true; success = true;
} while(false); } while(false);
string_clear(buf); furi_string_free(buf);
return success; return success;
} }
static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* message) { static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* message) {
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
bool success = false; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "protocol", buf)) break; if(!flipper_format_read_string(ff, "protocol", buf)) break;
message->protocol = infrared_get_protocol_by_name(string_get_cstr(buf)); message->protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
if(!infrared_is_protocol_valid(message->protocol)) break; if(!infrared_is_protocol_valid(message->protocol)) break;
if(!flipper_format_read_hex(ff, "address", (uint8_t*)&message->address, sizeof(uint32_t))) if(!flipper_format_read_hex(ff, "address", (uint8_t*)&message->address, sizeof(uint32_t)))
break; break;
@ -112,7 +113,7 @@ static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* messa
success = true; success = true;
} while(false); } while(false);
string_clear(buf); furi_string_free(buf);
return success; return success;
} }
@ -121,18 +122,19 @@ static bool infrared_test_load_messages(
const char* signal_name, const char* signal_name,
InfraredMessage** messages, InfraredMessage** messages,
uint32_t* messages_count) { uint32_t* messages_count) {
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
bool success = false; bool success = false;
do { do {
bool is_name_found = false; bool is_name_found = false;
for(; !is_name_found && flipper_format_read_string(ff, "name", buf); for(; !is_name_found && flipper_format_read_string(ff, "name", buf);
is_name_found = !string_cmp_str(buf, signal_name)) is_name_found = !furi_string_cmp(buf, signal_name))
; ;
if(!is_name_found) break; if(!is_name_found) break;
if(!flipper_format_read_string(ff, "type", buf) || string_cmp_str(buf, "parsed_array")) if(!flipper_format_read_string(ff, "type", buf) ||
furi_string_cmp_str(buf, "parsed_array"))
break; break;
if(!flipper_format_read_uint32(ff, "count", messages_count, 1)) break; if(!flipper_format_read_uint32(ff, "count", messages_count, 1)) break;
if(!*messages_count) break; if(!*messages_count) break;
@ -151,7 +153,7 @@ static bool infrared_test_load_messages(
success = true; success = true;
} while(false); } while(false);
string_clear(buf); furi_string_free(buf);
return success; return success;
} }
@ -213,26 +215,26 @@ static void infrared_test_run_encoder(InfraredProtocol protocol, uint32_t test_i
InfraredMessage* input_messages; InfraredMessage* input_messages;
uint32_t input_messages_count; uint32_t input_messages_count;
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
const char* protocol_name = infrared_get_protocol_name(protocol); const char* protocol_name = infrared_get_protocol_name(protocol);
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file"); mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
string_printf(buf, "encoder_input%d", test_index); furi_string_printf(buf, "encoder_input%ld", test_index);
mu_assert( mu_assert(
infrared_test_load_messages( infrared_test_load_messages(
test->ff, string_get_cstr(buf), &input_messages, &input_messages_count), test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
"Failed to load messages from file"); "Failed to load messages from file");
string_printf(buf, "encoder_expected%d", test_index); furi_string_printf(buf, "encoder_expected%ld", test_index);
mu_assert( mu_assert(
infrared_test_load_raw_signal( infrared_test_load_raw_signal(
test->ff, string_get_cstr(buf), &expected_timings, &expected_timings_count), test->ff, furi_string_get_cstr(buf), &expected_timings, &expected_timings_count),
"Failed to load raw signal from file"); "Failed to load raw signal from file");
flipper_format_buffered_file_close(test->ff); flipper_format_buffered_file_close(test->ff);
string_clear(buf); furi_string_free(buf);
uint32_t j = 0; uint32_t j = 0;
timings = malloc(sizeof(uint32_t) * timings_count); timings = malloc(sizeof(uint32_t) * timings_count);
@ -267,22 +269,22 @@ static void infrared_test_run_encoder_decoder(InfraredProtocol protocol, uint32_
uint32_t input_messages_count; uint32_t input_messages_count;
bool level = false; bool level = false;
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
timings = malloc(sizeof(uint32_t) * timings_count); timings = malloc(sizeof(uint32_t) * timings_count);
const char* protocol_name = infrared_get_protocol_name(protocol); const char* protocol_name = infrared_get_protocol_name(protocol);
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file"); mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
string_printf(buf, "encoder_decoder_input%d", test_index); furi_string_printf(buf, "encoder_decoder_input%ld", test_index);
mu_assert( mu_assert(
infrared_test_load_messages( infrared_test_load_messages(
test->ff, string_get_cstr(buf), &input_messages, &input_messages_count), test->ff, furi_string_get_cstr(buf), &input_messages, &input_messages_count),
"Failed to load messages from file"); "Failed to load messages from file");
flipper_format_buffered_file_close(test->ff); flipper_format_buffered_file_close(test->ff);
string_clear(buf); furi_string_free(buf);
for(uint32_t message_counter = 0; message_counter < input_messages_count; ++message_counter) { for(uint32_t message_counter = 0; message_counter < input_messages_count; ++message_counter) {
const InfraredMessage* message_encoded = &input_messages[message_counter]; const InfraredMessage* message_encoded = &input_messages[message_counter];
@ -327,25 +329,27 @@ static void infrared_test_run_decoder(InfraredProtocol protocol, uint32_t test_i
InfraredMessage* messages; InfraredMessage* messages;
uint32_t messages_count; uint32_t messages_count;
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
mu_assert( mu_assert(
infrared_test_prepare_file(infrared_get_protocol_name(protocol)), infrared_test_prepare_file(infrared_get_protocol_name(protocol)),
"Failed to prepare test file"); "Failed to prepare test file");
string_printf(buf, "decoder_input%d", test_index); furi_string_printf(buf, "decoder_input%ld", test_index);
mu_assert( mu_assert(
infrared_test_load_raw_signal(test->ff, string_get_cstr(buf), &timings, &timings_count), infrared_test_load_raw_signal(
test->ff, furi_string_get_cstr(buf), &timings, &timings_count),
"Failed to load raw signal from file"); "Failed to load raw signal from file");
string_printf(buf, "decoder_expected%d", test_index); furi_string_printf(buf, "decoder_expected%ld", test_index);
mu_assert( mu_assert(
infrared_test_load_messages(test->ff, string_get_cstr(buf), &messages, &messages_count), infrared_test_load_messages(
test->ff, furi_string_get_cstr(buf), &messages, &messages_count),
"Failed to load messages from file"); "Failed to load messages from file");
flipper_format_buffered_file_close(test->ff); flipper_format_buffered_file_close(test->ff);
string_clear(buf); furi_string_free(buf);
InfraredMessage message_decoded_check_local; InfraredMessage message_decoded_check_local;
bool level = 0; bool level = 0;

View File

@ -53,14 +53,15 @@ static bool nfc_test_read_signal_from_file(const char* file_name) {
bool success = false; bool success = false;
FlipperFormat* file = flipper_format_file_alloc(nfc_test->storage); FlipperFormat* file = flipper_format_file_alloc(nfc_test->storage);
string_t file_type; FuriString* file_type;
string_init(file_type); file_type = furi_string_alloc();
uint32_t file_version = 0; uint32_t file_version = 0;
do { do {
if(!flipper_format_file_open_existing(file, file_name)) break; if(!flipper_format_file_open_existing(file, file_name)) break;
if(!flipper_format_read_header(file, file_type, &file_version)) break; if(!flipper_format_read_header(file, file_type, &file_version)) break;
if(string_cmp_str(file_type, nfc_test_file_type) || file_version != nfc_test_file_version) if(furi_string_cmp_str(file_type, nfc_test_file_type) ||
file_version != nfc_test_file_version)
break; break;
if(!flipper_format_read_uint32(file, "Data length", &nfc_test->test_data_len, 1)) break; if(!flipper_format_read_uint32(file, "Data length", &nfc_test->test_data_len, 1)) break;
if(nfc_test->test_data_len > NFC_TEST_DATA_MAX_LEN) break; if(nfc_test->test_data_len > NFC_TEST_DATA_MAX_LEN) break;
@ -76,7 +77,7 @@ static bool nfc_test_read_signal_from_file(const char* file_name) {
success = true; success = true;
} while(false); } while(false);
string_clear(file_type); furi_string_free(file_type);
flipper_format_free(file); flipper_format_free(file);
return success; return success;
@ -111,7 +112,7 @@ static bool nfc_test_digital_signal_test_encode(
// Check timings // Check timings
if(time > encode_max_time) { if(time > encode_max_time) {
FURI_LOG_E( FURI_LOG_E(
TAG, "Encoding time: %d us while accepted value: %d us", time, encode_max_time); TAG, "Encoding time: %ld us while accepted value: %ld us", time, encode_max_time);
break; break;
} }
@ -131,7 +132,7 @@ static bool nfc_test_digital_signal_test_encode(
ref_timings_sum += ref[i]; ref_timings_sum += ref[i];
if(timings_diff > timing_tolerance) { if(timings_diff > timing_tolerance) {
FURI_LOG_E( FURI_LOG_E(
TAG, "Too big differece in %d timings. Ref: %d, DUT: %d", i, ref[i], dut[i]); TAG, "Too big differece in %d timings. Ref: %ld, DUT: %ld", i, ref[i], dut[i]);
timing_check_success = false; timing_check_success = false;
break; break;
} }
@ -142,16 +143,16 @@ static bool nfc_test_digital_signal_test_encode(
if(sum_diff > timings_sum_tolerance) { if(sum_diff > timings_sum_tolerance) {
FURI_LOG_E( FURI_LOG_E(
TAG, TAG,
"Too big difference in timings sum. Ref: %d, DUT: %d", "Too big difference in timings sum. Ref: %ld, DUT: %ld",
ref_timings_sum, ref_timings_sum,
dut_timings_sum); dut_timings_sum);
break; break;
} }
FURI_LOG_I(TAG, "Encoding time: %d us. Acceptable time: %d us", time, encode_max_time); FURI_LOG_I(TAG, "Encoding time: %ld us. Acceptable time: %ld us", time, encode_max_time);
FURI_LOG_I( FURI_LOG_I(
TAG, TAG,
"Timings sum difference: %d [1/64MHZ]. Acceptable difference: %d [1/64MHz]", "Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]",
sum_diff, sum_diff,
timings_sum_tolerance); timings_sum_tolerance);
success = true; success = true;
@ -174,8 +175,8 @@ MU_TEST(nfc_digital_signal_test) {
MU_TEST(mf_classic_dict_test) { MU_TEST(mf_classic_dict_test) {
MfClassicDict* instance = NULL; MfClassicDict* instance = NULL;
uint64_t key = 0; uint64_t key = 0;
string_t temp_str; FuriString* temp_str;
string_init(temp_str); temp_str = furi_string_alloc();
instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest); instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n"); mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
@ -184,7 +185,7 @@ MU_TEST(mf_classic_dict_test) {
mf_classic_dict_get_total_keys(instance) == 0, mf_classic_dict_get_total_keys(instance) == 0,
"mf_classic_dict_get_total_keys == 0 assert failed\r\n"); "mf_classic_dict_get_total_keys == 0 assert failed\r\n");
string_set(temp_str, "2196FAD8115B"); furi_string_set(temp_str, "2196FAD8115B");
mu_assert( mu_assert(
mf_classic_dict_add_key_str(instance, temp_str), mf_classic_dict_add_key_str(instance, temp_str),
"mf_classic_dict_add_key == true assert failed\r\n"); "mf_classic_dict_add_key == true assert failed\r\n");
@ -199,7 +200,7 @@ MU_TEST(mf_classic_dict_test) {
mf_classic_dict_get_key_at_index_str(instance, temp_str, 0), mf_classic_dict_get_key_at_index_str(instance, temp_str, 0),
"mf_classic_dict_get_key_at_index_str == true assert failed\r\n"); "mf_classic_dict_get_key_at_index_str == true assert failed\r\n");
mu_assert( mu_assert(
string_cmp(temp_str, "2196FAD8115B") == 0, furi_string_cmp(temp_str, "2196FAD8115B") == 0,
"string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n"); "string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n");
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n"); mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
@ -216,7 +217,7 @@ MU_TEST(mf_classic_dict_test) {
"mf_classic_dict_delete_index == true assert failed\r\n"); "mf_classic_dict_delete_index == true assert failed\r\n");
mf_classic_dict_free(instance); mf_classic_dict_free(instance);
string_clear(temp_str); furi_string_free(temp_str);
} }
MU_TEST_SUITE(nfc) { MU_TEST_SUITE(nfc) {

View File

@ -10,7 +10,6 @@
#include <furi.h> #include <furi.h>
#include "../minunit.h" #include "../minunit.h"
#include <stdint.h> #include <stdint.h>
#include <stream_buffer.h>
#include <pb.h> #include <pb.h>
#include <pb_encode.h> #include <pb_encode.h>
#include <m-list.h> #include <m-list.h>
@ -34,7 +33,7 @@ static uint32_t command_id = 0;
typedef struct { typedef struct {
RpcSession* session; RpcSession* session;
StreamBufferHandle_t output_stream; FuriStreamBuffer* output_stream;
SemaphoreHandle_t close_session_semaphore; SemaphoreHandle_t close_session_semaphore;
SemaphoreHandle_t terminate_semaphore; SemaphoreHandle_t terminate_semaphore;
TickType_t timeout; TickType_t timeout;
@ -90,7 +89,7 @@ static void test_rpc_setup(void) {
} }
furi_check(rpc_session[0].session); furi_check(rpc_session[0].session);
rpc_session[0].output_stream = xStreamBufferCreate(1000, 1); rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback); rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary(); rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary(); rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
@ -110,7 +109,7 @@ static void test_rpc_setup_second_session(void) {
} }
furi_check(rpc_session[1].session); furi_check(rpc_session[1].session);
rpc_session[1].output_stream = xStreamBufferCreate(1000, 1); rpc_session[1].output_stream = furi_stream_buffer_alloc(1000, 1);
rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback); rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback);
rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary(); rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary();
rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary(); rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary();
@ -126,7 +125,7 @@ static void test_rpc_teardown(void) {
rpc_session_close(rpc_session[0].session); rpc_session_close(rpc_session[0].session);
furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY)); furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY));
furi_record_close(RECORD_RPC); furi_record_close(RECORD_RPC);
vStreamBufferDelete(rpc_session[0].output_stream); furi_stream_buffer_free(rpc_session[0].output_stream);
vSemaphoreDelete(rpc_session[0].close_session_semaphore); vSemaphoreDelete(rpc_session[0].close_session_semaphore);
vSemaphoreDelete(rpc_session[0].terminate_semaphore); vSemaphoreDelete(rpc_session[0].terminate_semaphore);
++command_id; ++command_id;
@ -141,7 +140,7 @@ static void test_rpc_teardown_second_session(void) {
xSemaphoreTake(rpc_session[1].terminate_semaphore, 0); xSemaphoreTake(rpc_session[1].terminate_semaphore, 0);
rpc_session_close(rpc_session[1].session); rpc_session_close(rpc_session[1].session);
furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY)); furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY));
vStreamBufferDelete(rpc_session[1].output_stream); furi_stream_buffer_free(rpc_session[1].output_stream);
vSemaphoreDelete(rpc_session[1].close_session_semaphore); vSemaphoreDelete(rpc_session[1].close_session_semaphore);
vSemaphoreDelete(rpc_session[1].terminate_semaphore); vSemaphoreDelete(rpc_session[1].terminate_semaphore);
++command_id; ++command_id;
@ -268,8 +267,8 @@ static PB_CommandStatus test_rpc_storage_get_file_error(File* file) {
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) { static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) {
RpcSessionContext* callbacks_context = ctx; RpcSessionContext* callbacks_context = ctx;
size_t bytes_sent = size_t bytes_sent = furi_stream_buffer_send(
xStreamBufferSend(callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever); callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever);
(void)bytes_sent; (void)bytes_sent;
furi_check(bytes_sent == got_size); furi_check(bytes_sent == got_size);
} }
@ -534,7 +533,8 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_
TickType_t now = xTaskGetTickCount(); TickType_t now = xTaskGetTickCount();
int32_t time_left = session_context->timeout - now; int32_t time_left = session_context->timeout - now;
time_left = MAX(time_left, 0); time_left = MAX(time_left, 0);
bytes_received = xStreamBufferReceive(session_context->output_stream, buf, count, time_left); bytes_received =
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
return (count == bytes_received); return (count == bytes_received);
} }

View File

@ -75,7 +75,7 @@ typedef struct {
bool visited; bool visited;
} StorageTestPath; } StorageTestPath;
DICT_DEF2(StorageTestPathDict, string_t, STRING_OPLIST, StorageTestPath, M_POD_OPLIST) DICT_DEF2(StorageTestPathDict, FuriString*, FURI_STRING_OPLIST, StorageTestPath, M_POD_OPLIST)
static StorageTestPathDict_t* static StorageTestPathDict_t*
storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) { storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) {
@ -83,15 +83,15 @@ static StorageTestPathDict_t*
StorageTestPathDict_init(*data); StorageTestPathDict_init(*data);
for(size_t i = 0; i < paths_count; i++) { for(size_t i = 0; i < paths_count; i++) {
string_t key; FuriString* key;
string_init_set(key, paths[i].path); key = furi_string_alloc_set(paths[i].path);
StorageTestPath value = { StorageTestPath value = {
.is_dir = paths[i].is_dir, .is_dir = paths[i].is_dir,
.visited = false, .visited = false,
}; };
StorageTestPathDict_set_at(*data, key, value); StorageTestPathDict_set_at(*data, key, value);
string_clear(key); furi_string_free(key);
} }
return data; return data;
@ -102,7 +102,7 @@ static void storage_test_paths_free(StorageTestPathDict_t* data) {
free(data); free(data);
} }
static bool storage_test_paths_mark(StorageTestPathDict_t* data, string_t path, bool is_dir) { static bool storage_test_paths_mark(StorageTestPathDict_t* data, FuriString* path, bool is_dir) {
bool found = false; bool found = false;
StorageTestPath* record = StorageTestPathDict_get(*data, path); StorageTestPath* record = StorageTestPathDict_get(*data, path);
@ -148,27 +148,27 @@ static bool write_file_13DA(Storage* storage, const char* path) {
} }
static void storage_dirs_create(Storage* storage, const char* base) { static void storage_dirs_create(Storage* storage, const char* base) {
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
storage_common_mkdir(storage, base); storage_common_mkdir(storage, base);
for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) { for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) {
string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]); furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]);
storage_common_mkdir(storage, string_get_cstr(path)); storage_common_mkdir(storage, furi_string_get_cstr(path));
} }
for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) { for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) {
string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]); furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]);
write_file_13DA(storage, string_get_cstr(path)); write_file_13DA(storage, furi_string_get_cstr(path));
} }
string_clear(path); furi_string_free(path);
} }
MU_TEST_1(test_dirwalk_full, Storage* storage) { MU_TEST_1(test_dirwalk_full, Storage* storage) {
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
FileInfo fileinfo; FileInfo fileinfo;
StorageTestPathDict_t* paths = StorageTestPathDict_t* paths =
@ -178,12 +178,12 @@ MU_TEST_1(test_dirwalk_full, Storage* storage) {
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk"))); mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
string_right(path, strlen(EXT_PATH("dirwalk/"))); furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
} }
dir_walk_free(dir_walk); dir_walk_free(dir_walk);
string_clear(path); furi_string_free(path);
mu_check(storage_test_paths_check(paths) == false); mu_check(storage_test_paths_check(paths) == false);
@ -191,8 +191,8 @@ MU_TEST_1(test_dirwalk_full, Storage* storage) {
} }
MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) { MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) {
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
FileInfo fileinfo; FileInfo fileinfo;
StorageTestPathDict_t* paths = storage_test_paths_alloc( StorageTestPathDict_t* paths = storage_test_paths_alloc(
@ -203,12 +203,12 @@ MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) {
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk"))); mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
string_right(path, strlen(EXT_PATH("dirwalk/"))); furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
} }
dir_walk_free(dir_walk); dir_walk_free(dir_walk);
string_clear(path); furi_string_free(path);
mu_check(storage_test_paths_check(paths) == false); mu_check(storage_test_paths_check(paths) == false);
@ -230,8 +230,8 @@ static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* filein
} }
MU_TEST_1(test_dirwalk_filter, Storage* storage) { MU_TEST_1(test_dirwalk_filter, Storage* storage) {
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
FileInfo fileinfo; FileInfo fileinfo;
StorageTestPathDict_t* paths = storage_test_paths_alloc( StorageTestPathDict_t* paths = storage_test_paths_alloc(
@ -242,12 +242,12 @@ MU_TEST_1(test_dirwalk_filter, Storage* storage) {
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk"))); mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
string_right(path, strlen(EXT_PATH("dirwalk/"))); furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
} }
dir_walk_free(dir_walk); dir_walk_free(dir_walk);
string_clear(path); furi_string_free(path);
mu_check(storage_test_paths_check(paths) == false); mu_check(storage_test_paths_check(paths) == false);

View File

@ -211,22 +211,22 @@ static bool check_file_13DA(Storage* storage, const char* path) {
} }
static void storage_dir_create(Storage* storage, const char* base) { static void storage_dir_create(Storage* storage, const char* base) {
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
storage_common_mkdir(storage, base); storage_common_mkdir(storage, base);
for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) {
string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); furi_string_printf(path, "%s/%s", base, storage_copy_test_paths[i]);
storage_common_mkdir(storage, string_get_cstr(path)); storage_common_mkdir(storage, furi_string_get_cstr(path));
} }
for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) {
string_printf(path, "%s/%s", base, storage_copy_test_files[i]); furi_string_printf(path, "%s/%s", base, storage_copy_test_files[i]);
write_file_13DA(storage, string_get_cstr(path)); write_file_13DA(storage, furi_string_get_cstr(path));
} }
string_clear(path); furi_string_free(path);
} }
static void storage_dir_remove(Storage* storage, const char* base) { static void storage_dir_remove(Storage* storage, const char* base) {
@ -235,15 +235,15 @@ static void storage_dir_remove(Storage* storage, const char* base) {
static bool storage_dir_rename_check(Storage* storage, const char* base) { static bool storage_dir_rename_check(Storage* storage, const char* base) {
bool result = false; bool result = false;
string_t path; FuriString* path;
string_init(path); path = furi_string_alloc();
result = (storage_common_stat(storage, base, NULL) == FSE_OK); result = (storage_common_stat(storage, base, NULL) == FSE_OK);
if(result) { if(result) {
for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) {
string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); furi_string_printf(path, "%s/%s", base, storage_copy_test_paths[i]);
result = (storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK); result = (storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK);
if(!result) { if(!result) {
break; break;
} }
@ -252,15 +252,15 @@ static bool storage_dir_rename_check(Storage* storage, const char* base) {
if(result) { if(result) {
for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) {
string_printf(path, "%s/%s", base, storage_copy_test_files[i]); furi_string_printf(path, "%s/%s", base, storage_copy_test_files[i]);
result = check_file_13DA(storage, string_get_cstr(path)); result = check_file_13DA(storage, furi_string_get_cstr(path));
if(!result) { if(!result) {
break; break;
} }
} }
} }
string_clear(path); furi_string_free(path);
return result; return result;
} }

View File

@ -18,8 +18,8 @@ static const char* stream_test_right_data =
MU_TEST_1(stream_composite_subtest, Stream* stream) { MU_TEST_1(stream_composite_subtest, Stream* stream) {
const size_t data_size = 128; const size_t data_size = 128;
uint8_t data[data_size]; uint8_t data[data_size];
string_t string_lee; FuriString* string_lee;
string_init_set(string_lee, "lee"); string_lee = furi_string_alloc_set("lee");
// test that stream is empty // test that stream is empty
// "" -> "" // "" -> ""
@ -267,7 +267,7 @@ MU_TEST_1(stream_composite_subtest, Stream* stream) {
mu_assert_int_eq(9, stream_tell(stream)); mu_assert_int_eq(9, stream_tell(stream));
mu_check(stream_eof(stream)); mu_check(stream_eof(stream));
string_clear(string_lee); furi_string_free(string_lee);
} }
MU_TEST(stream_composite_test) { MU_TEST(stream_composite_test) {
@ -416,10 +416,10 @@ MU_TEST(stream_buffered_write_after_read_test) {
} }
MU_TEST(stream_buffered_large_file_test) { MU_TEST(stream_buffered_large_file_test) {
string_t input_data; FuriString* input_data;
string_t output_data; FuriString* output_data;
string_init(input_data); input_data = furi_string_alloc();
string_init(output_data); output_data = furi_string_alloc();
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
@ -429,7 +429,7 @@ MU_TEST(stream_buffered_large_file_test) {
const size_t rep_count = data_size / line_size + 1; const size_t rep_count = data_size / line_size + 1;
for(size_t i = 0; i < rep_count; ++i) { for(size_t i = 0; i < rep_count; ++i) {
string_cat_printf(input_data, "%s\n", stream_test_data); furi_string_cat_printf(input_data, "%s\n", stream_test_data);
} }
// write test data to file // write test data to file
@ -437,8 +437,8 @@ MU_TEST(stream_buffered_large_file_test) {
mu_check(buffered_file_stream_open( mu_check(buffered_file_stream_open(
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)); stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_assert_int_eq(0, stream_size(stream)); mu_assert_int_eq(0, stream_size(stream));
mu_assert_int_eq(string_size(input_data), stream_write_string(stream, input_data)); mu_assert_int_eq(furi_string_size(input_data), stream_write_string(stream, input_data));
mu_assert_int_eq(string_size(input_data), stream_size(stream)); mu_assert_int_eq(furi_string_size(input_data), stream_size(stream));
const size_t substr_start = 8; const size_t substr_start = 8;
const size_t substr_len = 11; const size_t substr_len = 11;
@ -475,23 +475,23 @@ MU_TEST(stream_buffered_large_file_test) {
// read the whole file // read the whole file
mu_check(stream_rewind(stream)); mu_check(stream_rewind(stream));
string_t tmp; FuriString* tmp;
string_init(tmp); tmp = furi_string_alloc();
while(stream_read_line(stream, tmp)) { while(stream_read_line(stream, tmp)) {
string_cat(output_data, tmp); furi_string_cat(output_data, tmp);
} }
string_clear(tmp); furi_string_free(tmp);
// check against generated data // check against generated data
mu_assert_int_eq(string_size(input_data), string_size(output_data)); mu_assert_int_eq(furi_string_size(input_data), furi_string_size(output_data));
mu_check(string_equal_p(input_data, output_data)); mu_check(furi_string_equal(input_data, output_data));
mu_check(stream_eof(stream)); mu_check(stream_eof(stream));
stream_free(stream); stream_free(stream);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
string_clear(input_data); furi_string_free(input_data);
string_clear(output_data); furi_string_free(output_data);
} }
MU_TEST_SUITE(stream_suite) { MU_TEST_SUITE(stream_suite) {

View File

@ -28,12 +28,12 @@ static void subghz_test_rx_callback(
void* context) { void* context) {
UNUSED(receiver); UNUSED(receiver);
UNUSED(context); UNUSED(context);
string_t text; FuriString* text;
string_init(text); text = furi_string_alloc();
subghz_protocol_decoder_base_get_string(decoder_base, text); subghz_protocol_decoder_base_get_string(decoder_base, text);
subghz_receiver_reset(receiver_handler); subghz_receiver_reset(receiver_handler);
FURI_LOG_T(TAG, "\r\n%s", string_get_cstr(text)); FURI_LOG_T(TAG, "\r\n%s", furi_string_get_cstr(text));
string_clear(text); furi_string_free(text);
subghz_test_decoder_count++; subghz_test_decoder_count++;
} }
@ -141,8 +141,8 @@ static bool subghz_decode_random_test(const char* path) {
static bool subghz_encoder_test(const char* path) { static bool subghz_encoder_test(const char* path) {
subghz_test_decoder_count = 0; subghz_test_decoder_count = 0;
uint32_t test_start = furi_get_tick(); uint32_t test_start = furi_get_tick();
string_t temp_str; FuriString* temp_str;
string_init(temp_str); temp_str = furi_string_alloc();
bool file_load = false; bool file_load = false;
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
@ -167,11 +167,11 @@ static bool subghz_encoder_test(const char* path) {
} while(false); } while(false);
if(file_load) { if(file_load) {
SubGhzTransmitter* transmitter = SubGhzTransmitter* transmitter =
subghz_transmitter_alloc_init(environment_handler, string_get_cstr(temp_str)); subghz_transmitter_alloc_init(environment_handler, furi_string_get_cstr(temp_str));
subghz_transmitter_deserialize(transmitter, fff_data_file); subghz_transmitter_deserialize(transmitter, fff_data_file);
SubGhzProtocolDecoderBase* decoder = subghz_receiver_search_decoder_base_by_name( SubGhzProtocolDecoderBase* decoder = subghz_receiver_search_decoder_base_by_name(
receiver_handler, string_get_cstr(temp_str)); receiver_handler, furi_string_get_cstr(temp_str));
if(decoder) { if(decoder) {
LevelDuration level_duration; LevelDuration level_duration;
@ -192,10 +192,11 @@ static bool subghz_encoder_test(const char* path) {
flipper_format_free(fff_data_file); flipper_format_free(fff_data_file);
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
if(furi_get_tick() - test_start > TEST_TIMEOUT) { if(furi_get_tick() - test_start > TEST_TIMEOUT) {
printf("\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", string_get_cstr(temp_str)); printf(
"\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", furi_string_get_cstr(temp_str));
subghz_test_decoder_count = 0; subghz_test_decoder_count = 0;
} }
string_clear(temp_str); furi_string_free(temp_str);
return subghz_test_decoder_count ? true : false; return subghz_test_decoder_count ? true : false;
} }

View File

@ -1,5 +1,3 @@
#include "m-string.h"
#include <stdio.h> #include <stdio.h>
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
@ -11,6 +9,7 @@
#define TAG "UnitTests" #define TAG "UnitTests"
int run_minunit_test_furi(); int run_minunit_test_furi();
int run_minunit_test_furi_string();
int run_minunit_test_infrared(); int run_minunit_test_infrared();
int run_minunit_test_rpc(); int run_minunit_test_rpc();
int run_minunit_test_flipper_format(); int run_minunit_test_flipper_format();
@ -33,6 +32,7 @@ typedef struct {
const UnitTest unit_tests[] = { const UnitTest unit_tests[] = {
{.name = "furi", .entry = run_minunit_test_furi}, {.name = "furi", .entry = run_minunit_test_furi},
{.name = "furi_string", .entry = run_minunit_test_furi_string},
{.name = "storage", .entry = run_minunit_test_storage}, {.name = "storage", .entry = run_minunit_test_storage},
{.name = "stream", .entry = run_minunit_test_stream}, {.name = "stream", .entry = run_minunit_test_stream},
{.name = "dirwalk", .entry = run_minunit_test_dirwalk}, {.name = "dirwalk", .entry = run_minunit_test_dirwalk},
@ -63,7 +63,7 @@ void minunit_print_fail(const char* str) {
printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str); printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str);
} }
void unit_tests_cli(Cli* cli, string_t args, void* context) { void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(cli); UNUSED(cli);
UNUSED(args); UNUSED(args);
UNUSED(context); UNUSED(context);
@ -91,8 +91,8 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
break; break;
} }
if(string_size(args)) { if(furi_string_size(args)) {
if(string_cmp_str(args, unit_tests[i].name) == 0) { if(furi_string_cmp_str(args, unit_tests[i].name) == 0) {
failed_tests += unit_tests[i].entry(); failed_tests += unit_tests[i].entry();
} else { } else {
printf("Skipping %s\r\n", unit_tests[i].name); printf("Skipping %s\r\n", unit_tests[i].name);

View File

@ -0,0 +1,5 @@
App(
appid="sample_apps",
name="Sample apps bundle",
apptype=FlipperAppType.METAPACKAGE,
)

View File

@ -0,0 +1,10 @@
App(
appid="example_images",
name="Example: Images",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_images_main",
requires=["gui"],
stack_size=1 * 1024,
fap_category="Examples",
fap_icon_assets="images",
)

View File

@ -0,0 +1,81 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <input/input.h>
/* Magic happens here -- this file is generated by fbt.
* Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
#include "example_images_icons.h"
typedef struct {
uint8_t x, y;
} ImagePosition;
static ImagePosition image_position = {.x = 0, .y = 0};
// Screen is 128x64 px
static void app_draw_callback(Canvas* canvas, void* ctx) {
UNUSED(ctx);
canvas_clear(canvas);
canvas_draw_icon(canvas, image_position.x % 128, image_position.y % 64, &I_dolphin_71x25);
}
static void app_input_callback(InputEvent* input_event, void* ctx) {
furi_assert(ctx);
FuriMessageQueue* event_queue = ctx;
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
}
int32_t example_images_main(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
// Configure view port
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, app_draw_callback, view_port);
view_port_input_callback_set(view_port, app_input_callback, event_queue);
// Register view port in GUI
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
InputEvent event;
bool running = true;
while(running) {
if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
switch(event.key) {
case InputKeyLeft:
image_position.x -= 2;
break;
case InputKeyRight:
image_position.x += 2;
break;
case InputKeyUp:
image_position.y -= 2;
break;
case InputKeyDown:
image_position.y += 2;
break;
default:
running = false;
break;
}
}
}
view_port_update(view_port);
}
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
furi_message_queue_free(event_queue);
furi_record_close(RECORD_GUI);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,5 +1,4 @@
#include "archive_i.h" #include "archive_i.h"
#include "m-string.h"
bool archive_custom_event_callback(void* context, uint32_t event) { bool archive_custom_event_callback(void* context, uint32_t event) {
furi_assert(context); furi_assert(context);
@ -18,7 +17,7 @@ ArchiveApp* archive_alloc() {
archive->gui = furi_record_open(RECORD_GUI); archive->gui = furi_record_open(RECORD_GUI);
archive->text_input = text_input_alloc(); archive->text_input = text_input_alloc();
string_init(archive->fav_move_str); archive->fav_move_str = furi_string_alloc();
archive->view_dispatcher = view_dispatcher_alloc(); archive->view_dispatcher = view_dispatcher_alloc();
archive->scene_manager = scene_manager_alloc(&archive_scene_handlers, archive); archive->scene_manager = scene_manager_alloc(&archive_scene_handlers, archive);
@ -58,7 +57,7 @@ void archive_free(ArchiveApp* archive) {
view_dispatcher_free(archive->view_dispatcher); view_dispatcher_free(archive->view_dispatcher);
scene_manager_free(archive->scene_manager); scene_manager_free(archive->scene_manager);
browser_free(archive->browser); browser_free(archive->browser);
string_clear(archive->fav_move_str); furi_string_free(archive->fav_move_str);
text_input_free(archive->text_input); text_input_free(archive->text_input);

View File

@ -28,7 +28,7 @@ struct ArchiveApp {
TextInput* text_input; TextInput* text_input;
Widget* widget; Widget* widget;
FuriPubSubSubscription* loader_stop_subscription; FuriPubSubSubscription* loader_stop_subscription;
string_t fav_move_str; FuriString* fav_move_str;
char text_store[MAX_NAME_LEN]; char text_store[MAX_NAME_LEN];
char file_extension[MAX_EXT_LEN + 1]; char file_extension[MAX_EXT_LEN + 1];
}; };

View File

@ -5,7 +5,7 @@
#include <core/common_defines.h> #include <core/common_defines.h>
#include <core/log.h> #include <core/log.h>
#include "gui/modules/file_browser_worker.h" #include "gui/modules/file_browser_worker.h"
#include "m-string.h" #include <fap_loader/fap_loader_app.h>
#include <math.h> #include <math.h>
static void static void
@ -19,9 +19,11 @@ static void
if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) { if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) {
archive_switch_tab(browser, browser->last_tab_switch_dir); archive_switch_tab(browser, browser->last_tab_switch_dir);
} else if(!string_start_with_str_p(browser->path, "/app:")) { } else if(!furi_string_start_with_str(browser->path, "/app:")) {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
files_array_reset(model->files); files_array_reset(model->files);
model->item_cnt = item_cnt; model->item_cnt = item_cnt;
model->item_idx = (file_idx > 0) ? file_idx : 0; model->item_idx = (file_idx > 0) ? file_idx : 0;
@ -31,8 +33,8 @@ static void
model->list_offset = 0; model->list_offset = 0;
model->list_loading = true; model->list_loading = true;
model->folder_loading = false; model->folder_loading = false;
return false; },
}); false);
archive_update_offset(browser); archive_update_offset(browser);
file_browser_worker_load(browser->worker, load_offset, FILE_LIST_BUF_LEN); file_browser_worker_load(browser->worker, load_offset, FILE_LIST_BUF_LEN);
@ -44,25 +46,25 @@ static void archive_list_load_cb(void* context, uint32_t list_load_offset) {
ArchiveBrowserView* browser = (ArchiveBrowserView*)context; ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
files_array_reset(model->files); files_array_reset(model->files);
model->array_offset = list_load_offset; model->array_offset = list_load_offset;
return false; },
}); false);
} }
static void archive_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last) { static void
archive_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) {
furi_assert(context); furi_assert(context);
ArchiveBrowserView* browser = (ArchiveBrowserView*)context; ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
if(!is_last) { if(!is_last) {
archive_add_file_item(browser, is_folder, string_get_cstr(item_path)); archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
} else { } else {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true);
model->list_loading = false;
return true;
});
} }
} }
@ -71,15 +73,12 @@ static void archive_long_load_cb(void* context) {
ArchiveBrowserView* browser = (ArchiveBrowserView*)context; ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { model->folder_loading = true; }, true);
model->folder_loading = true;
return true;
});
} }
static void archive_file_browser_set_path( static void archive_file_browser_set_path(
ArchiveBrowserView* browser, ArchiveBrowserView* browser,
string_t path, FuriString* path,
const char* filter_ext, const char* filter_ext,
bool skip_assets) { bool skip_assets) {
furi_assert(browser); furi_assert(browser);
@ -112,7 +111,9 @@ void archive_update_offset(ArchiveBrowserView* browser) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt; uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt;
if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) { if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) {
@ -124,33 +125,34 @@ void archive_update_offset(ArchiveBrowserView* browser) {
model->list_offset = model->list_offset =
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
} }
},
return true; true);
});
} }
void archive_update_focus(ArchiveBrowserView* browser, const char* target) { void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
furi_assert(browser); furi_assert(browser);
furi_assert(target); furi_assert(target);
archive_get_items(browser, string_get_cstr(browser->path)); archive_get_items(browser, furi_string_get_cstr(browser->path));
if(!archive_file_get_array_size(browser) && archive_is_home(browser)) { if(!archive_file_get_array_size(browser) && archive_is_home(browser)) {
archive_switch_tab(browser, TAB_RIGHT); archive_switch_tab(browser, TAB_RIGHT);
} else { } else {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
uint16_t idx = 0; uint16_t idx = 0;
while(idx < files_array_size(model->files)) { while(idx < files_array_size(model->files)) {
ArchiveFile_t* current = files_array_get(model->files, idx); ArchiveFile_t* current = files_array_get(model->files, idx);
if(!string_search(current->path, target)) { if(!furi_string_search(current->path, target)) {
model->item_idx = idx + model->array_offset; model->item_idx = idx + model->array_offset;
break; break;
} }
++idx; ++idx;
} }
return false; },
}); false);
archive_update_offset(browser); archive_update_offset(browser);
} }
@ -161,10 +163,10 @@ size_t archive_file_get_array_size(ArchiveBrowserView* browser) {
uint16_t size = 0; uint16_t size = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
size = files_array_size(model->files); ArchiveBrowserViewModel * model,
return false; { size = files_array_size(model->files); },
}); false);
return size; return size;
} }
@ -172,11 +174,13 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
model->item_cnt = count; model->item_cnt = count;
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
return false; },
}); false);
archive_update_offset(browser); archive_update_offset(browser);
} }
@ -185,7 +189,9 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
uint32_t items_cnt = 0; uint32_t items_cnt = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
files_array_remove_v( files_array_remove_v(
model->files, model->files,
model->item_idx - model->array_offset, model->item_idx - model->array_offset,
@ -193,8 +199,8 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
model->item_cnt--; model->item_cnt--;
model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0);
items_cnt = model->item_cnt; items_cnt = model->item_cnt;
return false; },
}); false);
if((items_cnt == 0) && (archive_is_home(browser))) { if((items_cnt == 0) && (archive_is_home(browser))) {
archive_switch_tab(browser, TAB_RIGHT); archive_switch_tab(browser, TAB_RIGHT);
@ -207,7 +213,9 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
ArchiveFile_t temp; ArchiveFile_t temp;
size_t array_size = files_array_size(model->files) - 1; size_t array_size = files_array_size(model->files) - 1;
uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u); uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u);
@ -225,18 +233,18 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) {
} else { } else {
files_array_swap_at(model->files, model->item_idx, swap_idx); files_array_swap_at(model->files, model->item_idx, swap_idx);
} }
return false; },
}); false);
} }
void archive_file_array_rm_all(ArchiveBrowserView* browser) { void archive_file_array_rm_all(ArchiveBrowserView* browser) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
files_array_reset(model->files); ArchiveBrowserViewModel * model,
return false; { files_array_reset(model->files); },
}); false);
} }
void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
@ -245,7 +253,9 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
int32_t offset_new = 0; int32_t offset_new = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
if(model->item_cnt > FILE_LIST_BUF_LEN) { if(model->item_cnt > FILE_LIST_BUF_LEN) {
if(dir < 0) { if(dir < 0) {
offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 3; offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 3;
@ -261,8 +271,8 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) {
offset_new = 0; offset_new = 0;
} }
} }
return false; },
}); false);
file_browser_worker_load(browser->worker, offset_new, FILE_LIST_BUF_LEN); file_browser_worker_load(browser->worker, offset_new, FILE_LIST_BUF_LEN);
} }
@ -272,12 +282,14 @@ ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) {
ArchiveFile_t* selected = NULL; ArchiveFile_t* selected = NULL;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
selected = files_array_size(model->files) ? selected = files_array_size(model->files) ?
files_array_get(model->files, model->item_idx - model->array_offset) : files_array_get(model->files, model->item_idx - model->array_offset) :
NULL; NULL;
return false; },
}); false);
return selected; return selected;
} }
@ -287,11 +299,13 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) {
ArchiveFile_t* selected = NULL; ArchiveFile_t* selected = NULL;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u); idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u);
selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL; selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL;
return false; },
}); false);
return selected; return selected;
} }
@ -300,10 +314,7 @@ ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) {
ArchiveTabEnum tab_id = 0; ArchiveTabEnum tab_id = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { tab_id = model->tab_idx; }, false);
tab_id = model->tab_idx;
return false;
});
return tab_id; return tab_id;
} }
@ -315,22 +326,19 @@ bool archive_is_home(ArchiveBrowserView* browser) {
} }
const char* default_path = archive_get_default_path(archive_get_tab(browser)); const char* default_path = archive_get_default_path(archive_get_tab(browser));
return (string_cmp_str(browser->path, default_path) == 0); return (furi_string_cmp_str(browser->path, default_path) == 0);
} }
const char* archive_get_name(ArchiveBrowserView* browser) { const char* archive_get_name(ArchiveBrowserView* browser) {
ArchiveFile_t* selected = archive_get_current_file(browser); ArchiveFile_t* selected = archive_get_current_file(browser);
return string_get_cstr(selected->path); return furi_string_get_cstr(selected->path);
} }
void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { model->tab_idx = tab; }, false);
model->tab_idx = tab;
return false;
});
} }
void archive_add_app_item(ArchiveBrowserView* browser, const char* name) { void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
@ -339,75 +347,92 @@ void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
ArchiveFile_t item; ArchiveFile_t item;
ArchiveFile_t_init(&item); ArchiveFile_t_init(&item);
string_set_str(item.path, name); furi_string_set(item.path, name);
archive_set_file_type(&item, name, false, true); archive_set_file_type(&item, name, false, true);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
files_array_push_back(model->files, item); files_array_push_back(model->files, item);
model->item_cnt = files_array_size(model->files); model->item_cnt = files_array_size(model->files);
return false; },
}); false);
ArchiveFile_t_clear(&item); ArchiveFile_t_clear(&item);
} }
static bool archive_get_fap_meta(FuriString* file_path, FuriString* fap_name, uint8_t** icon_ptr) {
Storage* storage = furi_record_open(RECORD_STORAGE);
bool success = false;
if(fap_loader_load_name_and_icon(file_path, storage, icon_ptr, fap_name)) {
success = true;
}
furi_record_close(RECORD_STORAGE);
return success;
}
void archive_add_file_item(ArchiveBrowserView* browser, bool is_folder, const char* name) { void archive_add_file_item(ArchiveBrowserView* browser, bool is_folder, const char* name) {
furi_assert(browser); furi_assert(browser);
furi_assert(name); furi_assert(name);
ArchiveFile_t item; ArchiveFile_t item;
ArchiveFile_t_init(&item); ArchiveFile_t_init(&item);
string_init_set_str(item.path, name);
archive_set_file_type(&item, string_get_cstr(browser->path), is_folder, false);
furi_string_set(item.path, name);
archive_set_file_type(&item, furi_string_get_cstr(browser->path), is_folder, false);
if(item.type == ArchiveFileTypeApplication) {
item.custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
if(!archive_get_fap_meta(item.path, item.custom_name, &item.custom_icon_data)) {
free(item.custom_icon_data);
item.custom_icon_data = NULL;
}
}
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
files_array_push_back(model->files, item); ArchiveBrowserViewModel * model,
return false; { files_array_push_back(model->files, item); },
}); false);
ArchiveFile_t_clear(&item); ArchiveFile_t_clear(&item);
} }
void archive_show_file_menu(ArchiveBrowserView* browser, bool show) { void archive_show_file_menu(ArchiveBrowserView* browser, bool show) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
if(show) { if(show) {
if(archive_is_item_in_array(model, model->item_idx)) { if(archive_is_item_in_array(model, model->item_idx)) {
model->menu = true; model->menu = true;
model->menu_idx = 0; model->menu_idx = 0;
ArchiveFile_t* selected = ArchiveFile_t* selected =
files_array_get(model->files, model->item_idx - model->array_offset); files_array_get(model->files, model->item_idx - model->array_offset);
selected->fav = archive_is_favorite("%s", string_get_cstr(selected->path)); selected->fav =
archive_is_favorite("%s", furi_string_get_cstr(selected->path));
} }
} else { } else {
model->menu = false; model->menu = false;
model->menu_idx = 0; model->menu_idx = 0;
} }
},
return true; true);
});
} }
void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) { void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { model->move_fav = active; }, true);
model->move_fav = active;
return true;
});
} }
static bool archive_is_dir_exists(string_t path) { static bool archive_is_dir_exists(FuriString* path) {
if(string_equal_str_p(path, STORAGE_ANY_PATH_PREFIX)) { if(furi_string_equal(path, STORAGE_ANY_PATH_PREFIX)) {
return true; return true;
} }
bool state = false; bool state = false;
FileInfo file_info; FileInfo file_info;
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) { if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) {
if(file_info.flags & FSF_DIRECTORY) { if(file_info.flags & FSF_DIRECTORY) {
state = true; state = true;
} }
@ -431,16 +456,16 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
browser->is_root = true; browser->is_root = true;
archive_set_tab(browser, tab); archive_set_tab(browser, tab);
string_set_str(browser->path, archive_get_default_path(tab)); furi_string_set(browser->path, archive_get_default_path(tab));
bool tab_empty = true; bool tab_empty = true;
if(tab == ArchiveTabFavorites) { if(tab == ArchiveTabFavorites) {
if(archive_favorites_count(browser) > 0) { if(archive_favorites_count(browser) > 0) {
tab_empty = false; tab_empty = false;
} }
} else if(string_start_with_str_p(browser->path, "/app:")) { } else if(furi_string_start_with_str(browser->path, "/app:")) {
char* app_name = strchr(string_get_cstr(browser->path), ':'); char* app_name = strchr(furi_string_get_cstr(browser->path), ':');
if(app_name != NULL) { if(app_name != NULL) {
if(archive_app_is_available(browser, string_get_cstr(browser->path))) { if(archive_app_is_available(browser, furi_string_get_cstr(browser->path))) {
tab_empty = false; tab_empty = false;
} }
} }
@ -458,29 +483,28 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
archive_switch_tab(browser, key); archive_switch_tab(browser, key);
} else { } else {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
model->item_idx = 0; model->item_idx = 0;
model->array_offset = 0; model->array_offset = 0;
return false; },
}); false);
archive_get_items(browser, string_get_cstr(browser->path)); archive_get_items(browser, furi_string_get_cstr(browser->path));
archive_update_offset(browser); archive_update_offset(browser);
} }
} }
void archive_enter_dir(ArchiveBrowserView* browser, string_t path) { void archive_enter_dir(ArchiveBrowserView* browser, FuriString* path) {
furi_assert(browser); furi_assert(browser);
furi_assert(path); furi_assert(path);
int32_t idx_temp = 0; int32_t idx_temp = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
idx_temp = model->item_idx;
return false;
});
string_set(browser->path, path); furi_string_set(browser->path, path);
file_browser_worker_folder_enter(browser->worker, path, idx_temp); file_browser_worker_folder_enter(browser->worker, path, idx_temp);
} }
@ -496,9 +520,6 @@ void archive_refresh_dir(ArchiveBrowserView* browser) {
int32_t idx_temp = 0; int32_t idx_temp = 0;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
idx_temp = model->item_idx;
return false;
});
file_browser_worker_folder_refresh(browser->worker, idx_temp); file_browser_worker_folder_refresh(browser->worker, idx_temp);
} }

View File

@ -16,6 +16,7 @@ static const char* tab_default_paths[] = {
[ArchiveTabInfrared] = ANY_PATH("infrared"), [ArchiveTabInfrared] = ANY_PATH("infrared"),
[ArchiveTabBadUsb] = ANY_PATH("badusb"), [ArchiveTabBadUsb] = ANY_PATH("badusb"),
[ArchiveTabU2f] = "/app:u2f", [ArchiveTabU2f] = "/app:u2f",
[ArchiveTabApplications] = ANY_PATH("apps"),
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX, [ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
}; };
@ -27,6 +28,7 @@ static const char* known_ext[] = {
[ArchiveFileTypeInfrared] = ".ir", [ArchiveFileTypeInfrared] = ".ir",
[ArchiveFileTypeBadUsb] = ".txt", [ArchiveFileTypeBadUsb] = ".txt",
[ArchiveFileTypeU2f] = "?", [ArchiveFileTypeU2f] = "?",
[ArchiveFileTypeApplication] = ".fap",
[ArchiveFileTypeUpdateManifest] = ".fuf", [ArchiveFileTypeUpdateManifest] = ".fuf",
[ArchiveFileTypeFolder] = "?", [ArchiveFileTypeFolder] = "?",
[ArchiveFileTypeUnknown] = "*", [ArchiveFileTypeUnknown] = "*",
@ -41,6 +43,7 @@ static const ArchiveFileTypeEnum known_type[] = {
[ArchiveTabInfrared] = ArchiveFileTypeInfrared, [ArchiveTabInfrared] = ArchiveFileTypeInfrared,
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb, [ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
[ArchiveTabU2f] = ArchiveFileTypeU2f, [ArchiveTabU2f] = ArchiveFileTypeU2f,
[ArchiveTabApplications] = ArchiveFileTypeApplication,
[ArchiveTabBrowser] = ArchiveFileTypeUnknown, [ArchiveTabBrowser] = ArchiveFileTypeUnknown,
}; };
@ -84,6 +87,6 @@ void archive_show_file_menu(ArchiveBrowserView* browser, bool show);
void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active); void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active);
void archive_switch_tab(ArchiveBrowserView* browser, InputKey key); void archive_switch_tab(ArchiveBrowserView* browser, InputKey key);
void archive_enter_dir(ArchiveBrowserView* browser, string_t name); void archive_enter_dir(ArchiveBrowserView* browser, FuriString* name);
void archive_leave_dir(ArchiveBrowserView* browser); void archive_leave_dir(ArchiveBrowserView* browser);
void archive_refresh_dir(ArchiveBrowserView* browser); void archive_refresh_dir(ArchiveBrowserView* browser);

View File

@ -6,8 +6,8 @@
#define ARCHIVE_FAV_FILE_BUF_LEN 32 #define ARCHIVE_FAV_FILE_BUF_LEN 32
static bool archive_favorites_read_line(File* file, string_t str_result) { static bool archive_favorites_read_line(File* file, FuriString* str_result) {
string_reset(str_result); furi_string_reset(str_result);
uint8_t buffer[ARCHIVE_FAV_FILE_BUF_LEN]; uint8_t buffer[ARCHIVE_FAV_FILE_BUF_LEN];
bool result = false; bool result = false;
@ -34,7 +34,7 @@ static bool archive_favorites_read_line(File* file, string_t str_result) {
result = true; result = true;
break; break;
} else { } else {
string_push_back(str_result, buffer[i]); furi_string_push_back(str_result, buffer[i]);
} }
} }
@ -52,8 +52,8 @@ uint16_t archive_favorites_count(void* context) {
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(fs_api); File* file = storage_file_alloc(fs_api);
string_t buffer; FuriString* buffer;
string_init(buffer); buffer = furi_string_alloc();
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
uint16_t lines = 0; uint16_t lines = 0;
@ -63,7 +63,7 @@ uint16_t archive_favorites_count(void* context) {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; // Skip empty lines continue; // Skip empty lines
} }
++lines; ++lines;
@ -72,7 +72,7 @@ uint16_t archive_favorites_count(void* context) {
storage_file_close(file); storage_file_close(file);
string_clear(buffer); furi_string_free(buffer);
storage_file_free(file); storage_file_free(file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
@ -80,8 +80,8 @@ uint16_t archive_favorites_count(void* context) {
} }
static bool archive_favourites_rescan() { static bool archive_favourites_rescan() {
string_t buffer; FuriString* buffer;
string_init(buffer); buffer = furi_string_alloc();
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(storage); File* file = storage_file_alloc(storage);
@ -91,23 +91,25 @@ static bool archive_favourites_rescan() {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; continue;
} }
if(string_search(buffer, "/app:") == 0) { if(furi_string_search(buffer, "/app:") == 0) {
if(archive_app_is_available(NULL, string_get_cstr(buffer))) { if(archive_app_is_available(NULL, furi_string_get_cstr(buffer))) {
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); archive_file_append(
ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(buffer));
} }
} else { } else {
if(storage_file_exists(storage, string_get_cstr(buffer))) { if(storage_file_exists(storage, furi_string_get_cstr(buffer))) {
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); archive_file_append(
ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(buffer));
} }
} }
} }
} }
string_clear(buffer); furi_string_free(buffer);
storage_file_close(file); storage_file_close(file);
storage_common_remove(storage, ARCHIVE_FAV_PATH); storage_common_remove(storage, ARCHIVE_FAV_PATH);
@ -127,9 +129,9 @@ bool archive_favorites_read(void* context) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(storage); File* file = storage_file_alloc(storage);
string_t buffer; FuriString* buffer;
FileInfo file_info; FileInfo file_info;
string_init(buffer); buffer = furi_string_alloc();
bool need_refresh = false; bool need_refresh = false;
uint16_t file_count = 0; uint16_t file_count = 0;
@ -143,33 +145,33 @@ bool archive_favorites_read(void* context) {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; continue;
} }
if(string_search(buffer, "/app:") == 0) { if(furi_string_search(buffer, "/app:") == 0) {
if(archive_app_is_available(browser, string_get_cstr(buffer))) { if(archive_app_is_available(browser, furi_string_get_cstr(buffer))) {
archive_add_app_item(browser, string_get_cstr(buffer)); archive_add_app_item(browser, furi_string_get_cstr(buffer));
file_count++; file_count++;
} else { } else {
need_refresh = true; need_refresh = true;
} }
} else { } else {
if(storage_file_exists(storage, string_get_cstr(buffer))) { if(storage_file_exists(storage, furi_string_get_cstr(buffer))) {
storage_common_stat(storage, string_get_cstr(buffer), &file_info); storage_common_stat(storage, furi_string_get_cstr(buffer), &file_info);
archive_add_file_item( archive_add_file_item(
browser, (file_info.flags & FSF_DIRECTORY), string_get_cstr(buffer)); browser, (file_info.flags & FSF_DIRECTORY), furi_string_get_cstr(buffer));
file_count++; file_count++;
} else { } else {
need_refresh = true; need_refresh = true;
} }
} }
string_reset(buffer); furi_string_reset(buffer);
} }
} }
storage_file_close(file); storage_file_close(file);
string_clear(buffer); furi_string_free(buffer);
storage_file_free(file); storage_file_free(file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
@ -183,14 +185,14 @@ bool archive_favorites_read(void* context) {
} }
bool archive_favorites_delete(const char* format, ...) { bool archive_favorites_delete(const char* format, ...) {
string_t buffer; FuriString* buffer;
string_t filename; FuriString* filename;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
string_init_vprintf(filename, format, args); filename = furi_string_alloc_vprintf(format, args);
va_end(args); va_end(args);
string_init(buffer); buffer = furi_string_alloc();
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(fs_api); File* file = storage_file_alloc(fs_api);
@ -201,18 +203,18 @@ bool archive_favorites_delete(const char* format, ...) {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; continue;
} }
if(string_search(buffer, filename)) { if(furi_string_search(buffer, filename)) {
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(buffer));
} }
} }
} }
string_clear(buffer); furi_string_free(buffer);
string_clear(filename); furi_string_free(filename);
storage_file_close(file); storage_file_close(file);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH); storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
@ -226,14 +228,14 @@ bool archive_favorites_delete(const char* format, ...) {
} }
bool archive_is_favorite(const char* format, ...) { bool archive_is_favorite(const char* format, ...) {
string_t buffer; FuriString* buffer;
string_t filename; FuriString* filename;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
string_init_vprintf(filename, format, args); filename = furi_string_alloc_vprintf(format, args);
va_end(args); va_end(args);
string_init(buffer); buffer = furi_string_alloc();
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(fs_api); File* file = storage_file_alloc(fs_api);
@ -245,10 +247,10 @@ bool archive_is_favorite(const char* format, ...) {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; continue;
} }
if(!string_search(buffer, filename)) { if(!furi_string_search(buffer, filename)) {
found = true; found = true;
break; break;
} }
@ -256,8 +258,8 @@ bool archive_is_favorite(const char* format, ...) {
} }
storage_file_close(file); storage_file_close(file);
string_clear(buffer); furi_string_free(buffer);
string_clear(filename); furi_string_free(filename);
storage_file_free(file); storage_file_free(file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
@ -271,13 +273,13 @@ bool archive_favorites_rename(const char* src, const char* dst) {
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(fs_api); File* file = storage_file_alloc(fs_api);
string_t path; FuriString* path;
string_t buffer; FuriString* buffer;
string_init(buffer); buffer = furi_string_alloc();
string_init(path); path = furi_string_alloc();
string_printf(path, "%s", src); furi_string_printf(path, "%s", src);
bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(result) { if(result) {
@ -285,19 +287,19 @@ bool archive_favorites_rename(const char* src, const char* dst) {
if(!archive_favorites_read_line(file, buffer)) { if(!archive_favorites_read_line(file, buffer)) {
break; break;
} }
if(!string_size(buffer)) { if(!furi_string_size(buffer)) {
continue; continue;
} }
archive_file_append( archive_file_append(
ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_TEMP_PATH,
"%s\n", "%s\n",
string_search(buffer, path) ? string_get_cstr(buffer) : dst); furi_string_search(buffer, path) ? furi_string_get_cstr(buffer) : dst);
} }
} }
string_clear(buffer); furi_string_free(buffer);
string_clear(path); furi_string_free(path);
storage_file_close(file); storage_file_close(file);
storage_common_remove(fs_api, ARCHIVE_FAV_PATH); storage_common_remove(fs_api, ARCHIVE_FAV_PATH);
@ -325,7 +327,7 @@ void archive_favorites_save(void* context) {
for(size_t i = 0; i < archive_file_get_array_size(browser); i++) { for(size_t i = 0; i < archive_file_get_array_size(browser); i++) {
ArchiveFile_t* item = archive_get_file_at(browser, i); ArchiveFile_t* item = archive_get_file_at(browser, i);
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(item->path)); archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(item->path));
} }
storage_common_remove(fs_api, ARCHIVE_FAV_PATH); storage_common_remove(fs_api, ARCHIVE_FAV_PATH);

View File

@ -7,8 +7,8 @@
uint16_t archive_favorites_count(void* context); uint16_t archive_favorites_count(void* context);
bool archive_favorites_read(void* context); bool archive_favorites_read(void* context);
bool archive_favorites_delete(const char* format, ...); bool archive_favorites_delete(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
bool archive_is_favorite(const char* format, ...); bool archive_is_favorite(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
bool archive_favorites_rename(const char* src, const char* dst); bool archive_favorites_rename(const char* src, const char* dst);
void archive_add_to_favorites(const char* file_path); void archive_add_to_favorites(const char* file_path);
void archive_favorites_save(void* context); void archive_favorites_save(void* context);

View File

@ -15,10 +15,10 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder
} else { } else {
for(size_t i = 0; i < COUNT_OF(known_ext); i++) { for(size_t i = 0; i < COUNT_OF(known_ext); i++) {
if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue;
if(string_search_str(file->path, known_ext[i], 0) != STRING_FAILURE) { if(furi_string_search(file->path, known_ext[i], 0) != FURI_STRING_FAILURE) {
if(i == ArchiveFileTypeBadUsb) { if(i == ArchiveFileTypeBadUsb) {
if(string_search_str(file->path, archive_get_default_path(ArchiveTabBadUsb)) == if(furi_string_search(
0) { file->path, archive_get_default_path(ArchiveTabBadUsb)) == 0) {
file->type = i; file->type = i;
return; // *.txt file is a BadUSB script only if it is in BadUSB folder return; // *.txt file is a BadUSB script only if it is in BadUSB folder
} }
@ -54,10 +54,10 @@ bool archive_get_items(void* context, const char* path) {
void archive_file_append(const char* path, const char* format, ...) { void archive_file_append(const char* path, const char* format, ...) {
furi_assert(path); furi_assert(path);
string_t string; FuriString* string;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
string_init_vprintf(string, format, args); string = furi_string_alloc_vprintf(format, args);
va_end(args); va_end(args);
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
@ -66,7 +66,7 @@ void archive_file_append(const char* path, const char* format, ...) {
bool res = storage_file_open(file, path, FSAM_WRITE, FSOM_OPEN_APPEND); bool res = storage_file_open(file, path, FSAM_WRITE, FSOM_OPEN_APPEND);
if(res) { if(res) {
storage_file_write(file, string_get_cstr(string), string_size(string)); storage_file_write(file, furi_string_get_cstr(string), furi_string_size(string));
} }
storage_file_close(file); storage_file_close(file);
@ -77,35 +77,35 @@ void archive_file_append(const char* path, const char* format, ...) {
void archive_delete_file(void* context, const char* format, ...) { void archive_delete_file(void* context, const char* format, ...) {
furi_assert(context); furi_assert(context);
string_t filename; FuriString* filename;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
string_init_vprintf(filename, format, args); filename = furi_string_alloc_vprintf(format, args);
va_end(args); va_end(args);
ArchiveBrowserView* browser = context; ArchiveBrowserView* browser = context;
Storage* fs_api = furi_record_open(RECORD_STORAGE); Storage* fs_api = furi_record_open(RECORD_STORAGE);
FileInfo fileinfo; FileInfo fileinfo;
storage_common_stat(fs_api, string_get_cstr(filename), &fileinfo); storage_common_stat(fs_api, furi_string_get_cstr(filename), &fileinfo);
bool res = false; bool res = false;
if(fileinfo.flags & FSF_DIRECTORY) { if(fileinfo.flags & FSF_DIRECTORY) {
res = storage_simply_remove_recursive(fs_api, string_get_cstr(filename)); res = storage_simply_remove_recursive(fs_api, furi_string_get_cstr(filename));
} else { } else {
res = (storage_common_remove(fs_api, string_get_cstr(filename)) == FSE_OK); res = (storage_common_remove(fs_api, furi_string_get_cstr(filename)) == FSE_OK);
} }
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
if(archive_is_favorite("%s", string_get_cstr(filename))) { if(archive_is_favorite("%s", furi_string_get_cstr(filename))) {
archive_favorites_delete("%s", string_get_cstr(filename)); archive_favorites_delete("%s", furi_string_get_cstr(filename));
} }
if(res) { if(res) {
archive_file_array_rm_selected(browser); archive_file_array_rm_selected(browser);
} }
string_clear(filename); furi_string_free(filename);
} }

View File

@ -1,9 +1,11 @@
#pragma once #pragma once
#include <m-array.h> #include <m-array.h>
#include <m-string.h> #include <furi.h>
#include <storage/storage.h> #include <storage/storage.h>
#define FAP_MANIFEST_MAX_ICON_SIZE 32
typedef enum { typedef enum {
ArchiveFileTypeIButton, ArchiveFileTypeIButton,
ArchiveFileTypeNFC, ArchiveFileTypeNFC,
@ -13,41 +15,65 @@ typedef enum {
ArchiveFileTypeBadUsb, ArchiveFileTypeBadUsb,
ArchiveFileTypeU2f, ArchiveFileTypeU2f,
ArchiveFileTypeUpdateManifest, ArchiveFileTypeUpdateManifest,
ArchiveFileTypeApplication,
ArchiveFileTypeFolder, ArchiveFileTypeFolder,
ArchiveFileTypeUnknown, ArchiveFileTypeUnknown,
ArchiveFileTypeLoading, ArchiveFileTypeLoading,
} ArchiveFileTypeEnum; } ArchiveFileTypeEnum;
typedef struct { typedef struct {
string_t path; FuriString* path;
ArchiveFileTypeEnum type; ArchiveFileTypeEnum type;
uint8_t* custom_icon_data;
FuriString* custom_name;
bool fav; bool fav;
bool is_app; bool is_app;
} ArchiveFile_t; } ArchiveFile_t;
static void ArchiveFile_t_init(ArchiveFile_t* obj) { static void ArchiveFile_t_init(ArchiveFile_t* obj) {
obj->path = furi_string_alloc();
obj->type = ArchiveFileTypeUnknown; obj->type = ArchiveFileTypeUnknown;
obj->is_app = false; obj->custom_icon_data = NULL;
obj->custom_name = furi_string_alloc();
obj->fav = false; obj->fav = false;
string_init(obj->path); obj->is_app = false;
} }
static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
obj->path = furi_string_alloc_set(src->path);
obj->type = src->type; obj->type = src->type;
obj->is_app = src->is_app; if(src->custom_icon_data) {
obj->custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
memcpy(obj->custom_icon_data, src->custom_icon_data, FAP_MANIFEST_MAX_ICON_SIZE);
} else {
obj->custom_icon_data = NULL;
}
obj->custom_name = furi_string_alloc_set(src->custom_name);
obj->fav = src->fav; obj->fav = src->fav;
string_init_set(obj->path, src->path); obj->is_app = src->is_app;
} }
static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
furi_string_set(obj->path, src->path);
obj->type = src->type; obj->type = src->type;
obj->is_app = src->is_app; if(src->custom_icon_data) {
obj->custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
memcpy(obj->custom_icon_data, src->custom_icon_data, FAP_MANIFEST_MAX_ICON_SIZE);
} else {
obj->custom_icon_data = NULL;
}
furi_string_set(obj->custom_name, src->custom_name);
obj->fav = src->fav; obj->fav = src->fav;
string_set(obj->path, src->path); obj->is_app = src->is_app;
} }
static void ArchiveFile_t_clear(ArchiveFile_t* obj) { static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
string_clear(obj->path); furi_string_free(obj->path);
if(obj->custom_icon_data) {
free(obj->custom_icon_data);
obj->custom_icon_data = NULL;
}
furi_string_free(obj->custom_name);
} }
ARRAY_DEF( ARRAY_DEF(
@ -60,5 +86,7 @@ ARRAY_DEF(
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app); void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
bool archive_get_items(void* context, const char* path); bool archive_get_items(void* context, const char* path);
void archive_file_append(const char* path, const char* format, ...); void archive_file_append(const char* path, const char* format, ...)
void archive_delete_file(void* context, const char* format, ...); _ATTRIBUTE((__format__(__printf__, 2, 3)));
void archive_delete_file(void* context, const char* format, ...)
_ATTRIBUTE((__format__(__printf__, 2, 3)));

View File

@ -20,6 +20,7 @@ static const char* flipper_app_name[] = {
[ArchiveFileTypeBadUsb] = "Bad USB", [ArchiveFileTypeBadUsb] = "Bad USB",
[ArchiveFileTypeU2f] = "U2F", [ArchiveFileTypeU2f] = "U2F",
[ArchiveFileTypeUpdateManifest] = "UpdaterApp", [ArchiveFileTypeUpdateManifest] = "UpdaterApp",
[ArchiveFileTypeApplication] = "Applications",
}; };
static void archive_loader_callback(const void* message, void* context) { static void archive_loader_callback(const void* message, void* context) {
@ -40,14 +41,14 @@ static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selec
LoaderStatus status; LoaderStatus status;
if(selected->is_app) { if(selected->is_app) {
char* param = strrchr(string_get_cstr(selected->path), '/'); char* param = strrchr(furi_string_get_cstr(selected->path), '/');
if(param != NULL) { if(param != NULL) {
param++; param++;
} }
status = loader_start(loader, flipper_app_name[selected->type], param); status = loader_start(loader, flipper_app_name[selected->type], param);
} else { } else {
status = loader_start( status = loader_start(
loader, flipper_app_name[selected->type], string_get_cstr(selected->path)); loader, flipper_app_name[selected->type], furi_string_get_cstr(selected->path));
} }
if(status != LoaderStatusOk) { if(status != LoaderStatusOk) {
@ -159,13 +160,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
break; break;
case ArchiveBrowserEventEnterFavMove: case ArchiveBrowserEventEnterFavMove:
string_set(archive->fav_move_str, selected->path); furi_string_set(archive->fav_move_str, selected->path);
archive_show_file_menu(browser, false); archive_show_file_menu(browser, false);
archive_favorites_move_mode(archive->browser, true); archive_favorites_move_mode(archive->browser, true);
consumed = true; consumed = true;
break; break;
case ArchiveBrowserEventExitFavMove: case ArchiveBrowserEventExitFavMove:
archive_update_focus(browser, string_get_cstr(archive->fav_move_str)); archive_update_focus(browser, furi_string_get_cstr(archive->fav_move_str));
archive_favorites_move_mode(archive->browser, false); archive_favorites_move_mode(archive->browser, false);
consumed = true; consumed = true;
break; break;

View File

@ -4,7 +4,6 @@
#include "../helpers/archive_apps.h" #include "../helpers/archive_apps.h"
#include "../helpers/archive_browser.h" #include "../helpers/archive_browser.h"
#include "toolbox/path.h" #include "toolbox/path.h"
#include "m-string.h"
#define SCENE_DELETE_CUSTOM_EVENT (0UL) #define SCENE_DELETE_CUSTOM_EVENT (0UL)
#define MAX_TEXT_INPUT_LEN 22 #define MAX_TEXT_INPUT_LEN 22
@ -26,18 +25,18 @@ void archive_scene_delete_on_enter(void* context) {
widget_add_button_element( widget_add_button_element(
app->widget, GuiButtonTypeRight, "Delete", archive_scene_delete_widget_callback, app); app->widget, GuiButtonTypeRight, "Delete", archive_scene_delete_widget_callback, app);
string_t filename; FuriString* filename;
string_init(filename); filename = furi_string_alloc();
ArchiveFile_t* current = archive_get_current_file(app->browser); ArchiveFile_t* current = archive_get_current_file(app->browser);
path_extract_filename(current->path, filename, false); path_extract_filename(current->path, filename, false);
char delete_str[64]; char delete_str[64];
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", string_get_cstr(filename)); snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", furi_string_get_cstr(filename));
widget_add_text_box_element( widget_add_text_box_element(
app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str, false); app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str, false);
string_clear(filename); furi_string_free(filename);
view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewWidget); view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewWidget);
} }

View File

@ -19,10 +19,10 @@ void archive_scene_rename_on_enter(void* context) {
TextInput* text_input = archive->text_input; TextInput* text_input = archive->text_input;
ArchiveFile_t* current = archive_get_current_file(archive->browser); ArchiveFile_t* current = archive_get_current_file(archive->browser);
string_t filename; FuriString* filename;
string_init(filename); filename = furi_string_alloc();
path_extract_filename(current->path, filename, true); path_extract_filename(current->path, filename, true);
strlcpy(archive->text_store, string_get_cstr(filename), MAX_NAME_LEN); strlcpy(archive->text_store, furi_string_get_cstr(filename), MAX_NAME_LEN);
path_extract_extension(current->path, archive->file_extension, MAX_EXT_LEN); path_extract_extension(current->path, archive->file_extension, MAX_EXT_LEN);
@ -37,10 +37,10 @@ void archive_scene_rename_on_enter(void* context) {
false); false);
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(archive->browser->path), archive->file_extension, ""); furi_string_get_cstr(archive->browser->path), archive->file_extension, "");
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
string_clear(filename); furi_string_free(filename);
view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput); view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput);
} }
@ -56,19 +56,19 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) {
const char* path_src = archive_get_name(archive->browser); const char* path_src = archive_get_name(archive->browser);
ArchiveFile_t* file = archive_get_current_file(archive->browser); ArchiveFile_t* file = archive_get_current_file(archive->browser);
string_t path_dst; FuriString* path_dst;
string_init(path_dst); path_dst = furi_string_alloc();
path_extract_dirname(path_src, path_dst); path_extract_dirname(path_src, path_dst);
string_cat_printf(path_dst, "/%s%s", archive->text_store, known_ext[file->type]); furi_string_cat_printf(path_dst, "/%s%s", archive->text_store, known_ext[file->type]);
storage_common_rename(fs_api, path_src, string_get_cstr(path_dst)); storage_common_rename(fs_api, path_src, furi_string_get_cstr(path_dst));
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
if(file->fav) { if(file->fav) {
archive_favorites_rename(path_src, string_get_cstr(path_dst)); archive_favorites_rename(path_src, furi_string_get_cstr(path_dst));
} }
string_clear(path_dst); furi_string_free(path_dst);
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser);
consumed = true; consumed = true;

View File

@ -14,6 +14,7 @@ static const char* ArchiveTabNames[] = {
[ArchiveTabInfrared] = "Infrared", [ArchiveTabInfrared] = "Infrared",
[ArchiveTabBadUsb] = "Bad USB", [ArchiveTabBadUsb] = "Bad USB",
[ArchiveTabU2f] = "U2F", [ArchiveTabU2f] = "U2F",
[ArchiveTabApplications] = "Apps",
[ArchiveTabBrowser] = "Browser", [ArchiveTabBrowser] = "Browser",
}; };
@ -29,6 +30,7 @@ static const Icon* ArchiveItemIcons[] = {
[ArchiveFileTypeFolder] = &I_dir_10px, [ArchiveFileTypeFolder] = &I_dir_10px,
[ArchiveFileTypeUnknown] = &I_unknown_10px, [ArchiveFileTypeUnknown] = &I_unknown_10px,
[ArchiveFileTypeLoading] = &I_loading_10px, [ArchiveFileTypeLoading] = &I_loading_10px,
[ArchiveFileTypeApplication] = &I_unknown_10px,
}; };
void archive_browser_set_callback( void archive_browser_set_callback(
@ -47,35 +49,35 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
elements_slightly_rounded_frame(canvas, 70, 16, 58, 48); elements_slightly_rounded_frame(canvas, 70, 16, 58, 48);
string_t menu[MENU_ITEMS]; FuriString* menu[MENU_ITEMS];
string_init_set_str(menu[0], "Run in app"); menu[0] = furi_string_alloc_set("Run in app");
string_init_set_str(menu[1], "Pin"); menu[1] = furi_string_alloc_set("Pin");
string_init_set_str(menu[2], "Rename"); menu[2] = furi_string_alloc_set("Rename");
string_init_set_str(menu[3], "Delete"); menu[3] = furi_string_alloc_set("Delete");
ArchiveFile_t* selected = files_array_get(model->files, model->item_idx - model->array_offset); ArchiveFile_t* selected = files_array_get(model->files, model->item_idx - model->array_offset);
if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) { if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) {
string_set_str(menu[1], "Unpin"); furi_string_set(menu[1], "Unpin");
} }
if(!archive_is_known_app(selected->type)) { if(!archive_is_known_app(selected->type)) {
string_set_str(menu[0], "---"); furi_string_set(menu[0], "---");
string_set_str(menu[1], "---"); furi_string_set(menu[1], "---");
string_set_str(menu[2], "---"); furi_string_set(menu[2], "---");
} else { } else {
if(model->tab_idx == ArchiveTabFavorites) { if(model->tab_idx == ArchiveTabFavorites) {
string_set_str(menu[2], "Move"); furi_string_set(menu[2], "Move");
string_set_str(menu[3], "---"); furi_string_set(menu[3], "---");
} else if(selected->is_app) { } else if(selected->is_app) {
string_set_str(menu[2], "---"); furi_string_set(menu[2], "---");
} }
} }
for(size_t i = 0; i < MENU_ITEMS; i++) { for(size_t i = 0; i < MENU_ITEMS; i++) {
canvas_draw_str(canvas, 82, 27 + i * 11, string_get_cstr(menu[i])); canvas_draw_str(canvas, 82, 27 + i * 11, furi_string_get_cstr(menu[i]));
string_clear(menu[i]); furi_string_free(menu[i]);
} }
canvas_draw_icon(canvas, 74, 20 + model->menu_idx * 11, &I_ButtonRight_4x7); canvas_draw_icon(canvas, 74, 20 + model->menu_idx * 11, &I_ButtonRight_4x7);
@ -118,20 +120,31 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
bool scrollbar = model->item_cnt > 4; bool scrollbar = model->item_cnt > 4;
for(uint32_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { for(uint32_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) {
string_t str_buf; FuriString* str_buf;
string_init(str_buf); str_buf = furi_string_alloc();
int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u);
uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0; uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0;
ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading;
uint8_t* custom_icon_data = NULL;
if(archive_is_item_in_array(model, idx)) { if(archive_is_item_in_array(model, idx)) {
ArchiveFile_t* file = files_array_get( ArchiveFile_t* file = files_array_get(
model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
file_type = file->type; file_type = file->type;
if(file_type == ArchiveFileTypeApplication) {
if(file->custom_icon_data) {
custom_icon_data = file->custom_icon_data;
furi_string_set(str_buf, file->custom_name);
} else {
file_type = ArchiveFileTypeUnknown;
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
}
} else {
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
}
} else { } else {
string_set_str(str_buf, "---"); furi_string_set(str_buf, "---");
} }
elements_string_fit_width( elements_string_fit_width(
@ -143,10 +156,17 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
} }
canvas_draw_icon(canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]); if(custom_icon_data) {
canvas_draw_str(canvas, 15 + x_offset, 24 + i * FRAME_HEIGHT, string_get_cstr(str_buf)); canvas_draw_bitmap(
canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, 11, 10, custom_icon_data);
} else {
canvas_draw_icon(
canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]);
}
canvas_draw_str(
canvas, 15 + x_offset, 24 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buf));
string_clear(str_buf); furi_string_free(str_buf);
} }
if(scrollbar) { if(scrollbar) {
@ -243,33 +263,37 @@ static bool archive_view_input(InputEvent* event, void* context) {
bool in_menu; bool in_menu;
bool move_fav_mode; bool move_fav_mode;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
in_menu = model->menu; in_menu = model->menu;
move_fav_mode = model->move_fav; move_fav_mode = model->move_fav;
return false; },
}); false);
if(in_menu) { if(in_menu) {
if(event->type == InputTypeShort) { if(event->type == InputTypeShort) {
if(event->key == InputKeyUp || event->key == InputKeyDown) { if(event->key == InputKeyUp || event->key == InputKeyDown) {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
if(event->key == InputKeyUp) { if(event->key == InputKeyUp) {
model->menu_idx = ((model->menu_idx - 1) + MENU_ITEMS) % MENU_ITEMS; model->menu_idx = ((model->menu_idx - 1) + MENU_ITEMS) % MENU_ITEMS;
} else if(event->key == InputKeyDown) { } else if(event->key == InputKeyDown) {
model->menu_idx = (model->menu_idx + 1) % MENU_ITEMS; model->menu_idx = (model->menu_idx + 1) % MENU_ITEMS;
} }
return true; },
}); true);
} }
if(event->key == InputKeyOk) { if(event->key == InputKeyOk) {
uint8_t idx; uint8_t idx;
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
idx = model->menu_idx; ArchiveBrowserViewModel * model,
return false; { idx = model->menu_idx; },
}); false);
browser->callback(file_menu_actions[idx], browser->context); browser->callback(file_menu_actions[idx], browser->context);
} else if(event->key == InputKeyBack) { } else if(event->key == InputKeyBack) {
browser->callback(ArchiveBrowserEventFileMenuClose, browser->context); browser->callback(ArchiveBrowserEventFileMenuClose, browser->context);
@ -293,7 +317,9 @@ static bool archive_view_input(InputEvent* event, void* context) {
if((event->key == InputKeyUp || event->key == InputKeyDown) && if((event->key == InputKeyUp || event->key == InputKeyDown) &&
(event->type == InputTypeShort || event->type == InputTypeRepeat)) { (event->type == InputTypeShort || event->type == InputTypeRepeat)) {
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
if(event->key == InputKeyUp) { if(event->key == InputKeyUp) {
model->item_idx = model->item_idx =
((model->item_idx - 1) + model->item_cnt) % model->item_cnt; ((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
@ -314,9 +340,8 @@ static bool archive_view_input(InputEvent* event, void* context) {
browser->callback(ArchiveBrowserEventFavMoveDown, browser->context); browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
} }
} }
},
return true; true);
});
archive_update_offset(browser); archive_update_offset(browser);
} }
@ -361,14 +386,16 @@ ArchiveBrowserView* browser_alloc() {
view_set_draw_callback(browser->view, archive_view_render); view_set_draw_callback(browser->view, archive_view_render);
view_set_input_callback(browser->view, archive_view_input); view_set_input_callback(browser->view, archive_view_input);
string_init_set_str(browser->path, archive_get_default_path(TAB_DEFAULT)); browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
ArchiveBrowserViewModel * model,
{
files_array_init(model->files); files_array_init(model->files);
model->tab_idx = TAB_DEFAULT; model->tab_idx = TAB_DEFAULT;
return true; },
}); true);
return browser; return browser;
} }
@ -381,12 +408,12 @@ void browser_free(ArchiveBrowserView* browser) {
} }
with_view_model( with_view_model(
browser->view, (ArchiveBrowserViewModel * model) { browser->view,
files_array_clear(model->files); ArchiveBrowserViewModel * model,
return false; { files_array_clear(model->files); },
}); false);
string_clear(browser->path); furi_string_free(browser->path);
view_free(browser->view); view_free(browser->view);
free(browser); free(browser);

View File

@ -26,6 +26,7 @@ typedef enum {
ArchiveTabIButton, ArchiveTabIButton,
ArchiveTabBadUsb, ArchiveTabBadUsb,
ArchiveTabU2f, ArchiveTabU2f,
ArchiveTabApplications,
ArchiveTabBrowser, ArchiveTabBrowser,
ArchiveTabTotal, ArchiveTabTotal,
} ArchiveTabEnum; } ArchiveTabEnum;
@ -77,7 +78,7 @@ struct ArchiveBrowserView {
bool worker_running; bool worker_running;
ArchiveBrowserViewCallback callback; ArchiveBrowserViewCallback callback;
void* context; void* context;
string_t path; FuriString* path;
InputKey last_tab_switch_dir; InputKey last_tab_switch_dir;
bool is_root; bool is_root;
}; };

View File

@ -1,5 +1,4 @@
#include "bad_usb_app_i.h" #include "bad_usb_app_i.h"
#include "m-string.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <storage/storage.h> #include <storage/storage.h>
@ -26,10 +25,10 @@ static void bad_usb_app_tick_event_callback(void* context) {
BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* bad_usb_app_alloc(char* arg) {
BadUsbApp* app = malloc(sizeof(BadUsbApp)); BadUsbApp* app = malloc(sizeof(BadUsbApp));
string_init(app->file_path); app->file_path = furi_string_alloc();
if(arg && strlen(arg)) { if(arg && strlen(arg)) {
string_set_str(app->file_path, arg); furi_string_set(app->file_path, arg);
} }
app->gui = furi_record_open(RECORD_GUI); app->gui = furi_record_open(RECORD_GUI);
@ -64,10 +63,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
app->error = BadUsbAppErrorCloseRpc; app->error = BadUsbAppErrorCloseRpc;
scene_manager_next_scene(app->scene_manager, BadUsbSceneError); scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
} else { } else {
if(!string_empty_p(app->file_path)) { if(!furi_string_empty(app->file_path)) {
scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); scene_manager_next_scene(app->scene_manager, BadUsbSceneWork);
} else { } else {
string_set_str(app->file_path, BAD_USB_APP_PATH_FOLDER); furi_string_set(app->file_path, BAD_USB_APP_PATH_FOLDER);
scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect);
} }
} }
@ -95,7 +94,7 @@ void bad_usb_app_free(BadUsbApp* app) {
furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_DIALOGS);
string_clear(app->file_path); furi_string_free(app->file_path);
free(app); free(app);
} }

View File

@ -31,7 +31,7 @@ struct BadUsbApp {
Widget* widget; Widget* widget;
BadUsbAppError error; BadUsbAppError error;
string_t file_path; FuriString* file_path;
BadUsb* bad_usb_view; BadUsb* bad_usb_view;
BadUsbScript* bad_usb_script; BadUsbScript* bad_usb_script;
}; };

View File

@ -26,16 +26,16 @@ typedef enum {
struct BadUsbScript { struct BadUsbScript {
FuriHalUsbHidConfig hid_cfg; FuriHalUsbHidConfig hid_cfg;
BadUsbState st; BadUsbState st;
string_t file_path; FuriString* file_path;
uint32_t defdelay; uint32_t defdelay;
FuriThread* thread; FuriThread* thread;
uint8_t file_buf[FILE_BUFFER_LEN + 1]; uint8_t file_buf[FILE_BUFFER_LEN + 1];
uint8_t buf_start; uint8_t buf_start;
uint8_t buf_len; uint8_t buf_len;
bool file_end; bool file_end;
string_t line; FuriString* line;
string_t line_prev; FuriString* line_prev;
uint32_t repeat_cnt; uint32_t repeat_cnt;
}; };
@ -109,6 +109,7 @@ static const char ducky_cmd_string[] = {"STRING "};
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "}; static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
static const char ducky_cmd_repeat[] = {"REPEAT "}; static const char ducky_cmd_repeat[] = {"REPEAT "};
static const char ducky_cmd_sysrq[] = {"SYSRQ "};
static const char ducky_cmd_altchar[] = {"ALTCHAR "}; static const char ducky_cmd_altchar[] = {"ALTCHAR "};
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "}; static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
@ -230,9 +231,10 @@ static uint16_t ducky_get_keycode(const char* param, bool accept_chars) {
return 0; return 0;
} }
static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) { static int32_t
uint32_t line_len = string_size(line); ducky_parse_line(BadUsbScript* bad_usb, FuriString* line, char* error, size_t error_len) {
const char* line_tmp = string_get_cstr(line); uint32_t line_len = furi_string_size(line);
const char* line_tmp = furi_string_get_cstr(line);
bool state = false; bool state = false;
for(uint32_t i = 0; i < line_len; i++) { for(uint32_t i = 0; i < line_len; i++) {
@ -260,6 +262,9 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
if((state) && (delay_val > 0)) { if((state) && (delay_val > 0)) {
return (int32_t)delay_val; return (int32_t)delay_val;
} }
if(error != NULL) {
snprintf(error, error_len, "Invalid number %s", line_tmp);
}
return SCRIPT_STATE_ERROR; return SCRIPT_STATE_ERROR;
} else if( } else if(
(strncmp(line_tmp, ducky_cmd_defdelay_1, strlen(ducky_cmd_defdelay_1)) == 0) || (strncmp(line_tmp, ducky_cmd_defdelay_1, strlen(ducky_cmd_defdelay_1)) == 0) ||
@ -267,17 +272,26 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
// DEFAULT_DELAY // DEFAULT_DELAY
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
state = ducky_get_number(line_tmp, &bad_usb->defdelay); state = ducky_get_number(line_tmp, &bad_usb->defdelay);
if(!state && error != NULL) {
snprintf(error, error_len, "Invalid number %s", line_tmp);
}
return (state) ? (0) : SCRIPT_STATE_ERROR; return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
// STRING // STRING
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
state = ducky_string(line_tmp); state = ducky_string(line_tmp);
if(!state && error != NULL) {
snprintf(error, error_len, "Invalid string %s", line_tmp);
}
return (state) ? (0) : SCRIPT_STATE_ERROR; return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) { } else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) {
// ALTCHAR // ALTCHAR
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
ducky_numlock_on(); ducky_numlock_on();
state = ducky_altchar(line_tmp); state = ducky_altchar(line_tmp);
if(!state && error != NULL) {
snprintf(error, error_len, "Invalid altchar %s", line_tmp);
}
return (state) ? (0) : SCRIPT_STATE_ERROR; return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if( } else if(
(strncmp(line_tmp, ducky_cmd_altstr_1, strlen(ducky_cmd_altstr_1)) == 0) || (strncmp(line_tmp, ducky_cmd_altstr_1, strlen(ducky_cmd_altstr_1)) == 0) ||
@ -286,16 +300,35 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
ducky_numlock_on(); ducky_numlock_on();
state = ducky_altstring(line_tmp); state = ducky_altstring(line_tmp);
if(!state && error != NULL) {
snprintf(error, error_len, "Invalid altstring %s", line_tmp);
}
return (state) ? (0) : SCRIPT_STATE_ERROR; return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) { } else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) {
// REPEAT // REPEAT
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt); state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt);
if(!state && error != NULL) {
snprintf(error, error_len, "Invalid number %s", line_tmp);
}
return (state) ? (0) : SCRIPT_STATE_ERROR; return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) {
// SYSRQ
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
uint16_t key = ducky_get_keycode(line_tmp, true);
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
furi_hal_hid_kb_press(key);
furi_hal_hid_kb_release_all();
return (0);
} else { } else {
// Special keys + modifiers // Special keys + modifiers
uint16_t key = ducky_get_keycode(line_tmp, false); uint16_t key = ducky_get_keycode(line_tmp, false);
if(key == HID_KEYBOARD_NONE) return SCRIPT_STATE_ERROR; if(key == HID_KEYBOARD_NONE) {
if(error != NULL) {
snprintf(error, error_len, "No keycode defined for %s", line_tmp);
}
return SCRIPT_STATE_ERROR;
}
if((key & 0xFF00) != 0) { if((key & 0xFF00) != 0) {
// It's a modifier key // It's a modifier key
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
@ -305,6 +338,9 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
furi_hal_hid_kb_release(key); furi_hal_hid_kb_release(key);
return (0); return (0);
} }
if(error != NULL) {
strncpy(error, "Unknown error", error_len);
}
return SCRIPT_STATE_ERROR; return SCRIPT_STATE_ERROR;
} }
@ -323,7 +359,7 @@ static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
} }
FURI_LOG_D( FURI_LOG_D(
WORKER_TAG, WORKER_TAG,
"set id: %04X:%04X mfr:%s product:%s", "set id: %04lX:%04lX mfr:%s product:%s",
bad_usb->hid_cfg.vid, bad_usb->hid_cfg.vid,
bad_usb->hid_cfg.pid, bad_usb->hid_cfg.pid,
bad_usb->hid_cfg.manuf, bad_usb->hid_cfg.manuf,
@ -337,7 +373,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
uint8_t ret = 0; uint8_t ret = 0;
uint32_t line_len = 0; uint32_t line_len = 0;
string_reset(bad_usb->line); furi_string_reset(bad_usb->line);
do { do {
ret = storage_file_read(script_file, bad_usb->file_buf, FILE_BUFFER_LEN); ret = storage_file_read(script_file, bad_usb->file_buf, FILE_BUFFER_LEN);
@ -347,7 +383,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
line_len = 0; line_len = 0;
} else { } else {
if(bad_usb->st.line_nb == 0) { // Save first line if(bad_usb->st.line_nb == 0) { // Save first line
string_push_back(bad_usb->line, bad_usb->file_buf[i]); furi_string_push_back(bad_usb->line, bad_usb->file_buf[i]);
} }
line_len++; line_len++;
} }
@ -360,7 +396,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
} }
} while(ret > 0); } while(ret > 0);
const char* line_tmp = string_get_cstr(bad_usb->line); const char* line_tmp = furi_string_get_cstr(bad_usb->line);
bool id_set = false; // Looking for ID command at first line bool id_set = false; // Looking for ID command at first line
if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) {
id_set = ducky_set_usb_id(bad_usb, &line_tmp[strlen(ducky_cmd_id) + 1]); id_set = ducky_set_usb_id(bad_usb, &line_tmp[strlen(ducky_cmd_id) + 1]);
@ -373,7 +409,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
} }
storage_file_seek(script_file, 0, true); storage_file_seek(script_file, 0, true);
string_reset(bad_usb->line); furi_string_reset(bad_usb->line);
return true; return true;
} }
@ -383,20 +419,21 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
if(bad_usb->repeat_cnt > 0) { if(bad_usb->repeat_cnt > 0) {
bad_usb->repeat_cnt--; bad_usb->repeat_cnt--;
delay_val = ducky_parse_line(bad_usb, bad_usb->line_prev); delay_val = ducky_parse_line(
bad_usb, bad_usb->line_prev, bad_usb->st.error, sizeof(bad_usb->st.error));
if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line
return 0; return 0;
} else if(delay_val < 0) { // Script error } else if(delay_val < 0) { // Script error
bad_usb->st.error_line = bad_usb->st.line_cur - 1; bad_usb->st.error_line = bad_usb->st.line_cur - 1;
FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", bad_usb->st.line_cur - 1); FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur - 1);
return SCRIPT_STATE_ERROR; return SCRIPT_STATE_ERROR;
} else { } else {
return (delay_val + bad_usb->defdelay); return (delay_val + bad_usb->defdelay);
} }
} }
string_set(bad_usb->line_prev, bad_usb->line); furi_string_set(bad_usb->line_prev, bad_usb->line);
string_reset(bad_usb->line); furi_string_reset(bad_usb->line);
while(1) { while(1) {
if(bad_usb->buf_len == 0) { if(bad_usb->buf_len == 0) {
@ -413,20 +450,22 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
if(bad_usb->buf_len == 0) return SCRIPT_STATE_END; if(bad_usb->buf_len == 0) return SCRIPT_STATE_END;
} }
for(uint8_t i = bad_usb->buf_start; i < (bad_usb->buf_start + bad_usb->buf_len); i++) { for(uint8_t i = bad_usb->buf_start; i < (bad_usb->buf_start + bad_usb->buf_len); i++) {
if(bad_usb->file_buf[i] == '\n' && string_size(bad_usb->line) > 0) { if(bad_usb->file_buf[i] == '\n' && furi_string_size(bad_usb->line) > 0) {
bad_usb->st.line_cur++; bad_usb->st.line_cur++;
bad_usb->buf_len = bad_usb->buf_len + bad_usb->buf_start - (i + 1); bad_usb->buf_len = bad_usb->buf_len + bad_usb->buf_start - (i + 1);
bad_usb->buf_start = i + 1; bad_usb->buf_start = i + 1;
delay_val = ducky_parse_line(bad_usb, bad_usb->line); delay_val = ducky_parse_line(
bad_usb, bad_usb->line, bad_usb->st.error, sizeof(bad_usb->st.error));
if(delay_val < 0) { if(delay_val < 0) {
bad_usb->st.error_line = bad_usb->st.line_cur; bad_usb->st.error_line = bad_usb->st.line_cur;
FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", bad_usb->st.line_cur); FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur);
return SCRIPT_STATE_ERROR; return SCRIPT_STATE_ERROR;
} else { } else {
return (delay_val + bad_usb->defdelay); return (delay_val + bad_usb->defdelay);
} }
} else { } else {
string_push_back(bad_usb->line, bad_usb->file_buf[i]); furi_string_push_back(bad_usb->line, bad_usb->file_buf[i]);
} }
} }
bad_usb->buf_len = 0; bad_usb->buf_len = 0;
@ -456,8 +495,8 @@ static int32_t bad_usb_worker(void* context) {
FURI_LOG_I(WORKER_TAG, "Init"); FURI_LOG_I(WORKER_TAG, "Init");
File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
string_init(bad_usb->line); bad_usb->line = furi_string_alloc();
string_init(bad_usb->line_prev); bad_usb->line_prev = furi_string_alloc();
furi_hal_hid_set_state_callback(bad_usb_hid_state_callback, bad_usb); furi_hal_hid_set_state_callback(bad_usb_hid_state_callback, bad_usb);
@ -465,7 +504,7 @@ static int32_t bad_usb_worker(void* context) {
if(worker_state == BadUsbStateInit) { // State: initialization if(worker_state == BadUsbStateInit) { // State: initialization
if(storage_file_open( if(storage_file_open(
script_file, script_file,
string_get_cstr(bad_usb->file_path), furi_string_get_cstr(bad_usb->file_path),
FSAM_READ, FSAM_READ,
FSOM_OPEN_EXISTING)) { FSOM_OPEN_EXISTING)) {
if((ducky_script_preload(bad_usb, script_file)) && (bad_usb->st.line_nb > 0)) { if((ducky_script_preload(bad_usb, script_file)) && (bad_usb->st.line_nb > 0)) {
@ -577,22 +616,23 @@ static int32_t bad_usb_worker(void* context) {
storage_file_close(script_file); storage_file_close(script_file);
storage_file_free(script_file); storage_file_free(script_file);
string_clear(bad_usb->line); furi_string_free(bad_usb->line);
string_clear(bad_usb->line_prev); furi_string_free(bad_usb->line_prev);
FURI_LOG_I(WORKER_TAG, "End"); FURI_LOG_I(WORKER_TAG, "End");
return 0; return 0;
} }
BadUsbScript* bad_usb_script_open(string_t file_path) { BadUsbScript* bad_usb_script_open(FuriString* file_path) {
furi_assert(file_path); furi_assert(file_path);
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
string_init(bad_usb->file_path); bad_usb->file_path = furi_string_alloc();
string_set(bad_usb->file_path, file_path); furi_string_set(bad_usb->file_path, file_path);
bad_usb->st.state = BadUsbStateInit; bad_usb->st.state = BadUsbStateInit;
bad_usb->st.error[0] = '\0';
bad_usb->thread = furi_thread_alloc(); bad_usb->thread = furi_thread_alloc();
furi_thread_set_name(bad_usb->thread, "BadUsbWorker"); furi_thread_set_name(bad_usb->thread, "BadUsbWorker");
@ -609,7 +649,7 @@ void bad_usb_script_close(BadUsbScript* bad_usb) {
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtEnd); furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtEnd);
furi_thread_join(bad_usb->thread); furi_thread_join(bad_usb->thread);
furi_thread_free(bad_usb->thread); furi_thread_free(bad_usb->thread);
string_clear(bad_usb->file_path); furi_string_free(bad_usb->file_path);
free(bad_usb); free(bad_usb);
} }

View File

@ -5,7 +5,6 @@ extern "C" {
#endif #endif
#include <furi.h> #include <furi.h>
#include <m-string.h>
typedef struct BadUsbScript BadUsbScript; typedef struct BadUsbScript BadUsbScript;
@ -26,9 +25,10 @@ typedef struct {
uint16_t line_nb; uint16_t line_nb;
uint32_t delay_remain; uint32_t delay_remain;
uint16_t error_line; uint16_t error_line;
char error[64];
} BadUsbState; } BadUsbState;
BadUsbScript* bad_usb_script_open(string_t file_path); BadUsbScript* bad_usb_script_open(FuriString* file_path);
void bad_usb_script_close(BadUsbScript* bad_usb); void bad_usb_script_close(BadUsbScript* bad_usb);

View File

@ -2,7 +2,6 @@
#include "../bad_usb_app_i.h" #include "../bad_usb_app_i.h"
#include "../views/bad_usb_view.h" #include "../views/bad_usb_view.h"
#include "furi_hal.h" #include "furi_hal.h"
#include "m-string.h"
#include "toolbox/path.h" #include "toolbox/path.h"
void bad_usb_scene_work_ok_callback(InputType type, void* context) { void bad_usb_scene_work_ok_callback(InputType type, void* context) {
@ -27,14 +26,14 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) {
void bad_usb_scene_work_on_enter(void* context) { void bad_usb_scene_work_on_enter(void* context) {
BadUsbApp* app = context; BadUsbApp* app = context;
string_t file_name; FuriString* file_name;
string_init(file_name); file_name = furi_string_alloc();
path_extract_filename(app->file_path, file_name, true); path_extract_filename(app->file_path, file_name, true);
bad_usb_set_file_name(app->bad_usb_view, string_get_cstr(file_name)); bad_usb_set_file_name(app->bad_usb_view, furi_string_get_cstr(file_name));
app->bad_usb_script = bad_usb_script_open(app->file_path); app->bad_usb_script = bad_usb_script_open(app->file_path);
string_clear(file_name); furi_string_free(file_name);
bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script));

View File

@ -19,12 +19,12 @@ typedef struct {
static void bad_usb_draw_callback(Canvas* canvas, void* _model) { static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
BadUsbModel* model = _model; BadUsbModel* model = _model;
string_t disp_str; FuriString* disp_str;
string_init_set_str(disp_str, model->file_name); disp_str = furi_string_alloc_set(model->file_name);
elements_string_fit_width(canvas, disp_str, 128 - 2); elements_string_fit_width(canvas, disp_str, 128 - 2);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 8, string_get_cstr(disp_str)); canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str));
string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 22, 20, &I_UsbTree_48x22); canvas_draw_icon(canvas, 22, 20, &I_UsbTree_48x22);
@ -49,10 +49,11 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:");
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
string_printf(disp_str, "line %u", model->state.error_line); furi_string_printf(disp_str, "line %u", model->state.error_line);
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 127, 46, AlignRight, AlignBottom, string_get_cstr(disp_str)); canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error);
} else if(model->state.state == BadUsbStateIdle) { } else if(model->state.state == BadUsbStateIdle) {
canvas_draw_icon(canvas, 4, 22, &I_Smile_18x18); canvas_draw_icon(canvas, 4, 22, &I_Smile_18x18);
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
@ -65,16 +66,17 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_icon(canvas, 4, 19, &I_EviSmile2_18x21); canvas_draw_icon(canvas, 4, 19, &I_EviSmile2_18x21);
} }
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
string_printf(disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); furi_string_printf(
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 114, 36, AlignRight, AlignBottom, string_get_cstr(disp_str)); canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14);
} else if(model->state.state == BadUsbStateDone) { } else if(model->state.state == BadUsbStateDone) {
canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21);
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
canvas_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "100"); canvas_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "100");
string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14);
} else if(model->state.state == BadUsbStateDelay) { } else if(model->state.state == BadUsbStateDelay) {
if(model->anim_frame == 0) { if(model->anim_frame == 0) {
@ -83,21 +85,22 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_icon(canvas, 4, 19, &I_EviWaiting2_18x21); canvas_draw_icon(canvas, 4, 19, &I_EviWaiting2_18x21);
} }
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
string_printf(disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); furi_string_printf(
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 114, 36, AlignRight, AlignBottom, string_get_cstr(disp_str)); canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
string_printf(disp_str, "delay %us", model->state.delay_remain); furi_string_printf(disp_str, "delay %lus", model->state.delay_remain);
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 127, 46, AlignRight, AlignBottom, string_get_cstr(disp_str)); canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
string_reset(disp_str); furi_string_reset(disp_str);
} else { } else {
canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18);
} }
string_clear(disp_str); furi_string_free(disp_str);
} }
static bool bad_usb_input_callback(InputEvent* event, void* context) { static bool bad_usb_input_callback(InputEvent* event, void* context) {
@ -143,29 +146,33 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c
furi_assert(bad_usb); furi_assert(bad_usb);
furi_assert(callback); furi_assert(callback);
with_view_model( with_view_model(
bad_usb->view, (BadUsbModel * model) { bad_usb->view,
BadUsbModel * model,
{
UNUSED(model); UNUSED(model);
bad_usb->callback = callback; bad_usb->callback = callback;
bad_usb->context = context; bad_usb->context = context;
return true; },
}); true);
} }
void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) {
furi_assert(name); furi_assert(name);
with_view_model( with_view_model(
bad_usb->view, (BadUsbModel * model) { bad_usb->view,
strlcpy(model->file_name, name, MAX_NAME_LEN); BadUsbModel * model,
return true; { strlcpy(model->file_name, name, MAX_NAME_LEN); },
}); true);
} }
void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) {
furi_assert(st); furi_assert(st);
with_view_model( with_view_model(
bad_usb->view, (BadUsbModel * model) { bad_usb->view,
BadUsbModel * model,
{
memcpy(&(model->state), st, sizeof(BadUsbState)); memcpy(&(model->state), st, sizeof(BadUsbState));
model->anim_frame ^= 1; model->anim_frame ^= 1;
return true; },
}); true);
} }

View File

@ -3,6 +3,7 @@ App(
name="Applications", name="Applications",
apptype=FlipperAppType.APP, apptype=FlipperAppType.APP,
entry_point="fap_loader_app", entry_point="fap_loader_app",
cdefines=["APP_FAP_LOADER"],
requires=[ requires=[
"gui", "gui",
"storage", "storage",

View File

@ -31,7 +31,7 @@ bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address) {
auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key); 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))) { if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) {
FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %x)!", name, gnu_sym_hash); FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %lx)!", name, gnu_sym_hash);
result = false; result = false;
} else { } else {
result = true; result = true;

View File

@ -1,34 +1,34 @@
#include <furi.h> #include <furi.h>
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/modules/loading.h>
#include <storage/storage.h> #include <storage/storage.h>
#include <gui/modules/loading.h>
#include <dialogs/dialogs.h> #include <dialogs/dialogs.h>
#include "elf_cpp/elf_hashtable.h"
#include <flipper_application/flipper_application.h> #include <flipper_application/flipper_application.h>
#include "elf_cpp/elf_hashtable.h"
#include "fap_loader_app.h"
#define TAG "fap_loader_app" #define TAG "fap_loader_app"
typedef struct { struct FapLoader {
FlipperApplication* app; FlipperApplication* app;
Storage* storage; Storage* storage;
DialogsApp* dialogs; DialogsApp* dialogs;
Gui* gui; Gui* gui;
string_t fap_path; FuriString* fap_path;
ViewDispatcher* view_dispatcher; ViewDispatcher* view_dispatcher;
Loading* loading; Loading* loading;
} FapLoader; };
static bool bool fap_loader_load_name_and_icon(
fap_loader_item_callback(string_t path, void* context, uint8_t** icon_ptr, string_t item_name) { FuriString* path,
FapLoader* loader = context; Storage* storage,
furi_assert(loader); uint8_t** icon_ptr,
FuriString* item_name) {
FlipperApplication* app = flipper_application_alloc(loader->storage, &hashtable_api_interface); FlipperApplication* app = flipper_application_alloc(storage, &hashtable_api_interface);
FlipperApplicationPreloadStatus preload_res = FlipperApplicationPreloadStatus preload_res =
flipper_application_preload_manifest(app, string_get_cstr(path)); flipper_application_preload_manifest(app, furi_string_get_cstr(path));
bool load_success = false; bool load_success = false;
@ -37,10 +37,10 @@ static bool
if(manifest->has_icon) { if(manifest->has_icon) {
memcpy(*icon_ptr, manifest->icon, FAP_MANIFEST_MAX_ICON_SIZE); memcpy(*icon_ptr, manifest->icon, FAP_MANIFEST_MAX_ICON_SIZE);
} }
string_set_str(item_name, manifest->name); furi_string_set(item_name, manifest->name);
load_success = true; load_success = true;
} else { } else {
FURI_LOG_E(TAG, "FAP Loader failed to preload %s", string_get_cstr(path)); FURI_LOG_E(TAG, "FAP Loader failed to preload %s", furi_string_get_cstr(path));
load_success = false; load_success = false;
} }
@ -48,30 +48,41 @@ static bool
return load_success; return load_success;
} }
static bool fap_loader_item_callback(
FuriString* path,
void* context,
uint8_t** icon_ptr,
FuriString* item_name) {
FapLoader* fap_loader = context;
furi_assert(fap_loader);
return fap_loader_load_name_and_icon(path, fap_loader->storage, icon_ptr, item_name);
}
static bool fap_loader_run_selected_app(FapLoader* loader) { static bool fap_loader_run_selected_app(FapLoader* loader) {
furi_assert(loader); furi_assert(loader);
string_t error_message; FuriString* error_message;
string_init_set(error_message, "unknown error"); error_message = furi_string_alloc_set("unknown error");
bool file_selected = false; bool file_selected = false;
bool show_error = true; bool show_error = true;
do { do {
file_selected = true; file_selected = true;
loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface); loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
size_t start = furi_get_tick();
FURI_LOG_I(TAG, "FAP Loader is loading %s", string_get_cstr(loader->fap_path)); FURI_LOG_I(TAG, "FAP Loader is loading %s", furi_string_get_cstr(loader->fap_path));
FlipperApplicationPreloadStatus preload_res = FlipperApplicationPreloadStatus preload_res =
flipper_application_preload(loader->app, string_get_cstr(loader->fap_path)); flipper_application_preload(loader->app, furi_string_get_cstr(loader->fap_path));
if(preload_res != FlipperApplicationPreloadStatusSuccess) { if(preload_res != FlipperApplicationPreloadStatusSuccess) {
const char* err_msg = flipper_application_preload_status_to_string(preload_res); const char* err_msg = flipper_application_preload_status_to_string(preload_res);
string_printf(error_message, "Preload failed: %s", err_msg); furi_string_printf(error_message, "Preload failed: %s", err_msg);
FURI_LOG_E( FURI_LOG_E(
TAG, TAG,
"FAP Loader failed to preload %s: %s", "FAP Loader failed to preload %s: %s",
string_get_cstr(loader->fap_path), furi_string_get_cstr(loader->fap_path),
err_msg); err_msg);
break; break;
} }
@ -80,16 +91,17 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(loader->app); FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(loader->app);
if(load_status != FlipperApplicationLoadStatusSuccess) { if(load_status != FlipperApplicationLoadStatusSuccess) {
const char* err_msg = flipper_application_load_status_to_string(load_status); const char* err_msg = flipper_application_load_status_to_string(load_status);
string_printf(error_message, "Load failed: %s", err_msg); furi_string_printf(error_message, "Load failed: %s", err_msg);
FURI_LOG_E( FURI_LOG_E(
TAG, TAG,
"FAP Loader failed to map to memory %s: %s", "FAP Loader failed to map to memory %s: %s",
string_get_cstr(loader->fap_path), furi_string_get_cstr(loader->fap_path),
err_msg); err_msg);
break; break;
} }
FURI_LOG_I(TAG, "FAP Loader is staring app"); FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start));
FURI_LOG_I(TAG, "FAP Loader is starting app");
FuriThread* thread = flipper_application_spawn(loader->app, NULL); FuriThread* thread = flipper_application_spawn(loader->app, NULL);
furi_thread_start(thread); furi_thread_start(thread);
@ -106,19 +118,19 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, NULL); dialog_message_set_buttons(message, NULL, NULL, NULL);
string_t buffer; FuriString* buffer;
string_init(buffer); buffer = furi_string_alloc();
string_printf(buffer, "%s", string_get_cstr(error_message)); furi_string_printf(buffer, "%s", furi_string_get_cstr(error_message));
string_replace_str(buffer, ":", "\n"); furi_string_replace(buffer, ":", "\n");
dialog_message_set_text( dialog_message_set_text(
message, string_get_cstr(buffer), 64, 32, AlignCenter, AlignCenter); message, furi_string_get_cstr(buffer), 64, 32, AlignCenter, AlignCenter);
dialog_message_show(loader->dialogs, message); dialog_message_show(loader->dialogs, message);
dialog_message_free(message); dialog_message_free(message);
string_clear(buffer); furi_string_free(buffer);
} }
string_clear(error_message); furi_string_free(error_message);
if(file_selected) { if(file_selected) {
flipper_application_free(loader->app); flipper_application_free(loader->app);
@ -131,7 +143,7 @@ static bool fap_loader_select_app(FapLoader* loader) {
const DialogsFileBrowserOptions browser_options = { const DialogsFileBrowserOptions browser_options = {
.extension = ".fap", .extension = ".fap",
.skip_assets = true, .skip_assets = true,
.icon = &I_badusb_10px, .icon = &I_unknown_10px,
.hide_ext = true, .hide_ext = true,
.item_loader_callback = fap_loader_item_callback, .item_loader_callback = fap_loader_item_callback,
.item_loader_context = loader, .item_loader_context = loader,
@ -141,39 +153,45 @@ static bool fap_loader_select_app(FapLoader* loader) {
loader->dialogs, loader->fap_path, loader->fap_path, &browser_options); loader->dialogs, loader->fap_path, loader->fap_path, &browser_options);
} }
int32_t fap_loader_app(void* p) { static FapLoader* fap_loader_alloc(const char* path) {
FapLoader* loader = malloc(sizeof(FapLoader)); FapLoader* loader = malloc(sizeof(FapLoader));
loader->fap_path = furi_string_alloc_set(path);
loader->storage = furi_record_open(RECORD_STORAGE); loader->storage = furi_record_open(RECORD_STORAGE);
loader->dialogs = furi_record_open(RECORD_DIALOGS); loader->dialogs = furi_record_open(RECORD_DIALOGS);
loader->gui = furi_record_open(RECORD_GUI); loader->gui = furi_record_open(RECORD_GUI);
loader->view_dispatcher = view_dispatcher_alloc(); loader->view_dispatcher = view_dispatcher_alloc();
loader->loading = loading_alloc(); loader->loading = loading_alloc();
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_add_view(loader->view_dispatcher, 0, loading_get_view(loader->loading)); view_dispatcher_add_view(loader->view_dispatcher, 0, loading_get_view(loader->loading));
return loader;
}
static void fap_loader_free(FapLoader* loader) {
view_dispatcher_remove_view(loader->view_dispatcher, 0);
loading_free(loader->loading);
view_dispatcher_free(loader->view_dispatcher);
furi_string_free(loader->fap_path);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_DIALOGS);
furi_record_close(RECORD_STORAGE);
free(loader);
}
int32_t fap_loader_app(void* p) {
FapLoader* loader;
if(p) { if(p) {
string_init_set(loader->fap_path, (const char*)p); loader = fap_loader_alloc((const char*)p);
view_dispatcher_switch_to_view(loader->view_dispatcher, 0);
fap_loader_run_selected_app(loader); fap_loader_run_selected_app(loader);
} else { } else {
string_init_set(loader->fap_path, EXT_PATH("apps")); loader = fap_loader_alloc(EXT_PATH("apps"));
while(fap_loader_select_app(loader)) { while(fap_loader_select_app(loader)) {
view_dispatcher_switch_to_view(loader->view_dispatcher, 0); view_dispatcher_switch_to_view(loader->view_dispatcher, 0);
fap_loader_run_selected_app(loader); fap_loader_run_selected_app(loader);
}; };
} }
view_dispatcher_remove_view(loader->view_dispatcher, 0); fap_loader_free(loader);
loading_free(loader->loading);
view_dispatcher_free(loader->view_dispatcher);
string_clear(loader->fap_path);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_DIALOGS);
furi_record_close(RECORD_STORAGE);
free(loader);
return 0; return 0;
} }

View File

@ -0,0 +1,27 @@
#pragma once
#include <storage/storage.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FapLoader FapLoader;
/**
* @brief Load name and icon from FAP file.
*
* @param path Path to FAP file.
* @param storage Storage instance.
* @param icon_ptr Icon pointer.
* @param item_name Application name.
* @return true if icon and name were loaded successfully.
*/
bool fap_loader_load_name_and_icon(
FuriString* path,
Storage* storage,
uint8_t** icon_ptr,
FuriString* item_name);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,7 @@
#include "../gpio_app_i.h" #include "../gpio_app_i.h"
#include "furi_hal_power.h" #include "furi_hal_power.h"
#include "furi_hal_usb.h" #include "furi_hal_usb.h"
#include <dolphin/dolphin.h>
enum GpioItem { enum GpioItem {
GpioItemUsbUart, GpioItemUsbUart,
@ -88,6 +89,7 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == GpioStartEventUsbUart) { } else if(event.event == GpioStartEventUsbUart) {
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart); scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart);
if(!furi_hal_usb_is_locked()) { if(!furi_hal_usb_is_locked()) {
DOLPHIN_DEED(DolphinDeedGpioUartBridge);
scene_manager_next_scene(app->scene_manager, GpioSceneUsbUart); scene_manager_next_scene(app->scene_manager, GpioSceneUsbUart);
} else { } else {
scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCloseRpc); scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCloseRpc);

View File

@ -1,6 +1,5 @@
#include "usb_uart_bridge.h" #include "usb_uart_bridge.h"
#include "furi_hal.h" #include "furi_hal.h"
#include <stream_buffer.h>
#include <furi_hal_usb_cdc.h> #include <furi_hal_usb_cdc.h>
#include "usb_cdc.h" #include "usb_cdc.h"
#include "cli/cli_vcp.h" #include "cli/cli_vcp.h"
@ -43,7 +42,7 @@ struct UsbUartBridge {
FuriThread* thread; FuriThread* thread;
FuriThread* tx_thread; FuriThread* tx_thread;
StreamBufferHandle_t rx_stream; FuriStreamBuffer* rx_stream;
FuriMutex* usb_mutex; FuriMutex* usb_mutex;
@ -74,12 +73,10 @@ static int32_t usb_uart_tx_thread(void* context);
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
UsbUartBridge* usb_uart = (UsbUartBridge*)context; UsbUartBridge* usb_uart = (UsbUartBridge*)context;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(ev == UartIrqEventRXNE) { if(ev == UartIrqEventRXNE) {
xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken); furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone); furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} }
} }
@ -156,7 +153,7 @@ static int32_t usb_uart_worker(void* context) {
memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig)); memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig));
usb_uart->rx_stream = xStreamBufferCreate(USB_UART_RX_BUF_SIZE, 1); usb_uart->rx_stream = furi_stream_buffer_alloc(USB_UART_RX_BUF_SIZE, 1);
usb_uart->tx_sem = furi_semaphore_alloc(1, 1); usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal); usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
@ -189,8 +186,8 @@ static int32_t usb_uart_worker(void* context) {
furi_check((events & FuriFlagError) == 0); furi_check((events & FuriFlagError) == 0);
if(events & WorkerEvtStop) break; if(events & WorkerEvtStop) break;
if(events & WorkerEvtRxDone) { if(events & WorkerEvtRxDone) {
size_t len = size_t len = furi_stream_buffer_receive(
xStreamBufferReceive(usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0); usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
if(len > 0) { if(len > 0) {
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) { if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) {
usb_uart->st.rx_cnt += len; usb_uart->st.rx_cnt += len;
@ -199,7 +196,7 @@ static int32_t usb_uart_worker(void* context) {
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len); furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len);
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk); furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
} else { } else {
xStreamBufferReset(usb_uart->rx_stream); furi_stream_buffer_reset(usb_uart->rx_stream);
} }
} }
} }
@ -270,7 +267,7 @@ static int32_t usb_uart_worker(void* context) {
furi_thread_join(usb_uart->tx_thread); furi_thread_join(usb_uart->tx_thread);
furi_thread_free(usb_uart->tx_thread); furi_thread_free(usb_uart->tx_thread);
vStreamBufferDelete(usb_uart->rx_stream); furi_stream_buffer_free(usb_uart->rx_stream);
furi_mutex_free(usb_uart->usb_mutex); furi_mutex_free(usb_uart->usb_mutex);
furi_semaphore_free(usb_uart->tx_sem); furi_semaphore_free(usb_uart->tx_sem);

View File

@ -48,23 +48,27 @@ static bool gpio_test_input_callback(InputEvent* event, void* context) {
static bool gpio_test_process_left(GpioTest* gpio_test) { static bool gpio_test_process_left(GpioTest* gpio_test) {
with_view_model( with_view_model(
gpio_test->view, (GpioTestModel * model) { gpio_test->view,
GpioTestModel * model,
{
if(model->pin_idx) { if(model->pin_idx) {
model->pin_idx--; model->pin_idx--;
} }
return true; },
}); true);
return true; return true;
} }
static bool gpio_test_process_right(GpioTest* gpio_test) { static bool gpio_test_process_right(GpioTest* gpio_test) {
with_view_model( with_view_model(
gpio_test->view, (GpioTestModel * model) { gpio_test->view,
GpioTestModel * model,
{
if(model->pin_idx < GPIO_ITEM_COUNT) { if(model->pin_idx < GPIO_ITEM_COUNT) {
model->pin_idx++; model->pin_idx++;
} }
return true; },
}); true);
return true; return true;
} }
@ -72,7 +76,9 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
bool consumed = false; bool consumed = false;
with_view_model( with_view_model(
gpio_test->view, (GpioTestModel * model) { gpio_test->view,
GpioTestModel * model,
{
if(event->type == InputTypePress) { if(event->type == InputTypePress) {
if(model->pin_idx < GPIO_ITEM_COUNT) { if(model->pin_idx < GPIO_ITEM_COUNT) {
gpio_item_set_pin(model->pin_idx, true); gpio_item_set_pin(model->pin_idx, true);
@ -89,8 +95,8 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
consumed = true; consumed = true;
} }
gpio_test->callback(event->type, gpio_test->context); gpio_test->callback(event->type, gpio_test->context);
return true; },
}); true);
return consumed; return consumed;
} }
@ -122,10 +128,12 @@ void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback,
furi_assert(gpio_test); furi_assert(gpio_test);
furi_assert(callback); furi_assert(callback);
with_view_model( with_view_model(
gpio_test->view, (GpioTestModel * model) { gpio_test->view,
GpioTestModel * model,
{
UNUSED(model); UNUSED(model);
gpio_test->callback = callback; gpio_test->callback = callback;
gpio_test->context = context; gpio_test->context = context;
return false; },
}); false);
} }

View File

@ -54,7 +54,7 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned(canvas, 116, 24, AlignRight, AlignBottom, temp_str); canvas_draw_str_aligned(canvas, 116, 24, AlignRight, AlignBottom, temp_str);
} else { } else {
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "KB."); canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "KiB.");
canvas_set_font(canvas, FontKeyboard); canvas_set_font(canvas, FontKeyboard);
snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024); snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024);
canvas_draw_str_aligned(canvas, 111, 24, AlignRight, AlignBottom, temp_str); canvas_draw_str_aligned(canvas, 111, 24, AlignRight, AlignBottom, temp_str);
@ -68,7 +68,7 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned(canvas, 116, 41, AlignRight, AlignBottom, temp_str); canvas_draw_str_aligned(canvas, 116, 41, AlignRight, AlignBottom, temp_str);
} else { } else {
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "KB."); canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "KiB.");
canvas_set_font(canvas, FontKeyboard); canvas_set_font(canvas, FontKeyboard);
snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024); snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024);
canvas_draw_str_aligned(canvas, 111, 41, AlignRight, AlignBottom, temp_str); canvas_draw_str_aligned(canvas, 111, 41, AlignRight, AlignBottom, temp_str);
@ -129,12 +129,14 @@ void gpio_usb_uart_set_callback(GpioUsbUart* usb_uart, GpioUsbUartCallback callb
furi_assert(callback); furi_assert(callback);
with_view_model( with_view_model(
usb_uart->view, (GpioUsbUartModel * model) { usb_uart->view,
GpioUsbUartModel * model,
{
UNUSED(model); UNUSED(model);
usb_uart->callback = callback; usb_uart->callback = callback;
usb_uart->context = context; usb_uart->context = context;
return false; },
}); false);
} }
void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUartState* st) { void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUartState* st) {
@ -143,7 +145,9 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa
furi_assert(st); furi_assert(st);
with_view_model( with_view_model(
instance->view, (GpioUsbUartModel * model) { instance->view,
GpioUsbUartModel * model,
{
model->baudrate = st->baudrate_cur; model->baudrate = st->baudrate_cur;
model->vcp_port = cfg->vcp_ch; model->vcp_port = cfg->vcp_ch;
model->tx_pin = (cfg->uart_ch == 0) ? (13) : (15); model->tx_pin = (cfg->uart_ch == 0) ? (13) : (15);
@ -152,6 +156,6 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa
model->rx_active = (model->rx_cnt != st->rx_cnt); model->rx_active = (model->rx_cnt != st->rx_cnt);
model->tx_cnt = st->tx_cnt; model->tx_cnt = st->tx_cnt;
model->rx_cnt = st->rx_cnt; model->rx_cnt = st->rx_cnt;
return true; },
}); true);
} }

View File

@ -2,7 +2,6 @@
#include "assets_icons.h" #include "assets_icons.h"
#include "ibutton_i.h" #include "ibutton_i.h"
#include "ibutton/scenes/ibutton_scene.h" #include "ibutton/scenes/ibutton_scene.h"
#include "m-string.h"
#include <toolbox/path.h> #include <toolbox/path.h>
#include <flipper_format/flipper_format.h> #include <flipper_format/flipper_format.h>
#include <rpc/rpc_app.h> #include <rpc/rpc_app.h>
@ -39,25 +38,25 @@ static void ibutton_make_app_folder(iButton* ibutton) {
} }
} }
bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) { bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog) {
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
bool result = false; bool result = false;
string_t data; FuriString* data;
string_init(data); data = furi_string_alloc();
do { do {
if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break; if(!flipper_format_file_open_existing(file, furi_string_get_cstr(key_path))) break;
// header // header
uint32_t version; uint32_t version;
if(!flipper_format_read_header(file, data, &version)) break; if(!flipper_format_read_header(file, data, &version)) break;
if(string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break; if(furi_string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break;
if(version != 1) break; if(version != 1) break;
// key type // key type
iButtonKeyType type; iButtonKeyType type;
if(!flipper_format_read_string(file, "Key type", data)) break; if(!flipper_format_read_string(file, "Key type", data)) break;
if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; if(!ibutton_key_get_type_by_string(furi_string_get_cstr(data), &type)) break;
// key data // key data
uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0};
@ -71,7 +70,7 @@ bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog
} while(false); } while(false);
flipper_format_free(file); flipper_format_free(file);
string_clear(data); furi_string_free(data);
if((!result) && (show_dialog)) { if((!result) && (show_dialog)) {
dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file");
@ -119,7 +118,7 @@ void ibutton_tick_event_callback(void* context) {
iButton* ibutton_alloc() { iButton* ibutton_alloc() {
iButton* ibutton = malloc(sizeof(iButton)); iButton* ibutton = malloc(sizeof(iButton));
string_init(ibutton->file_path); ibutton->file_path = furi_string_alloc();
ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton); ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton);
@ -210,7 +209,7 @@ void ibutton_free(iButton* ibutton) {
ibutton_worker_free(ibutton->key_worker); ibutton_worker_free(ibutton->key_worker);
ibutton_key_free(ibutton->key); ibutton_key_free(ibutton->key);
string_clear(ibutton->file_path); furi_string_free(ibutton->file_path);
free(ibutton); free(ibutton);
} }
@ -240,19 +239,19 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
do { do {
// Check if we has old key // Check if we has old key
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
// First remove old key // First remove old key
ibutton_delete_key(ibutton); ibutton_delete_key(ibutton);
// Remove old key name from path // Remove old key name from path
size_t filename_start = string_search_rchar(ibutton->file_path, '/'); size_t filename_start = furi_string_search_rchar(ibutton->file_path, '/');
string_left(ibutton->file_path, filename_start); furi_string_left(ibutton->file_path, filename_start);
} }
string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION); furi_string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION);
// Open file for write // Open file for write
if(!flipper_format_file_open_always(file, string_get_cstr(ibutton->file_path))) break; if(!flipper_format_file_open_always(file, furi_string_get_cstr(ibutton->file_path))) break;
// Write header // Write header
if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break; if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break;
@ -286,7 +285,7 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
bool ibutton_delete_key(iButton* ibutton) { bool ibutton_delete_key(iButton* ibutton) {
bool result = false; bool result = false;
result = storage_simply_remove(ibutton->storage, string_get_cstr(ibutton->file_path)); result = storage_simply_remove(ibutton->storage, furi_string_get_cstr(ibutton->file_path));
return result; return result;
} }
@ -326,7 +325,7 @@ int32_t ibutton_app(void* p) {
rpc_system_app_set_callback(ibutton->rpc_ctx, ibutton_rpc_command_callback, ibutton); rpc_system_app_set_callback(ibutton->rpc_ctx, ibutton_rpc_command_callback, ibutton);
rpc_system_app_send_started(ibutton->rpc_ctx); rpc_system_app_send_started(ibutton->rpc_ctx);
} else { } else {
string_set_str(ibutton->file_path, (const char*)p); furi_string_set(ibutton->file_path, (const char*)p);
if(ibutton_load_key_data(ibutton, ibutton->file_path, true)) { if(ibutton_load_key_data(ibutton, ibutton->file_path, true)) {
key_loaded = true; key_loaded = true;
// TODO: Display an error if the key from p could not be loaded // TODO: Display an error if the key from p could not be loaded

View File

@ -6,8 +6,8 @@
#include <one_wire/ibutton/ibutton_worker.h> #include <one_wire/ibutton/ibutton_worker.h>
#include <one_wire/one_wire_host.h> #include <one_wire/one_wire_host.h>
static void ibutton_cli(Cli* cli, string_t args, void* context); static void ibutton_cli(Cli* cli, FuriString* args, void* context);
static void onewire_cli(Cli* cli, string_t args, void* context); static void onewire_cli(Cli* cli, FuriString* args, void* context);
// app cli function // app cli function
void ibutton_on_system_start() { void ibutton_on_system_start() {
@ -34,16 +34,16 @@ void ibutton_cli_print_usage() {
printf("\t<key_data> are hex-formatted\r\n"); printf("\t<key_data> are hex-formatted\r\n");
}; };
bool ibutton_cli_get_key_type(string_t data, iButtonKeyType* type) { bool ibutton_cli_get_key_type(FuriString* data, iButtonKeyType* type) {
bool result = false; bool result = false;
if(string_cmp_str(data, "Dallas") == 0 || string_cmp_str(data, "dallas") == 0) { if(furi_string_cmp_str(data, "Dallas") == 0 || furi_string_cmp_str(data, "dallas") == 0) {
result = true; result = true;
*type = iButtonKeyDS1990; *type = iButtonKeyDS1990;
} else if(string_cmp_str(data, "Cyfral") == 0 || string_cmp_str(data, "cyfral") == 0) { } else if(furi_string_cmp_str(data, "Cyfral") == 0 || furi_string_cmp_str(data, "cyfral") == 0) {
result = true; result = true;
*type = iButtonKeyCyfral; *type = iButtonKeyCyfral;
} else if(string_cmp_str(data, "Metakom") == 0 || string_cmp_str(data, "metakom") == 0) { } else if(furi_string_cmp_str(data, "Metakom") == 0 || furi_string_cmp_str(data, "metakom") == 0) {
result = true; result = true;
*type = iButtonKeyMetakom; *type = iButtonKeyMetakom;
} }
@ -123,17 +123,17 @@ static void ibutton_cli_worker_write_cb(void* context, iButtonWorkerWriteResult
furi_event_flag_set(write_context->event, EVENT_FLAG_IBUTTON_COMPLETE); furi_event_flag_set(write_context->event, EVENT_FLAG_IBUTTON_COMPLETE);
} }
void ibutton_cli_write(Cli* cli, string_t args) { void ibutton_cli_write(Cli* cli, FuriString* args) {
iButtonKey* key = ibutton_key_alloc(); iButtonKey* key = ibutton_key_alloc();
iButtonWorker* worker = ibutton_worker_alloc(); iButtonWorker* worker = ibutton_worker_alloc();
iButtonKeyType type; iButtonKeyType type;
iButtonWriteContext write_context; iButtonWriteContext write_context;
uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; uint8_t key_data[IBUTTON_KEY_DATA_SIZE];
string_t data; FuriString* data;
write_context.event = furi_event_flag_alloc(); write_context.event = furi_event_flag_alloc();
string_init(data); data = furi_string_alloc();
ibutton_worker_start_thread(worker); ibutton_worker_start_thread(worker);
ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context); ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context);
@ -186,7 +186,7 @@ void ibutton_cli_write(Cli* cli, string_t args) {
ibutton_worker_stop(worker); ibutton_worker_stop(worker);
} while(false); } while(false);
string_clear(data); furi_string_free(data);
ibutton_worker_stop_thread(worker); ibutton_worker_stop_thread(worker);
ibutton_worker_free(worker); ibutton_worker_free(worker);
ibutton_key_free(key); ibutton_key_free(key);
@ -194,14 +194,14 @@ void ibutton_cli_write(Cli* cli, string_t args) {
furi_event_flag_free(write_context.event); furi_event_flag_free(write_context.event);
}; };
void ibutton_cli_emulate(Cli* cli, string_t args) { void ibutton_cli_emulate(Cli* cli, FuriString* args) {
iButtonKey* key = ibutton_key_alloc(); iButtonKey* key = ibutton_key_alloc();
iButtonWorker* worker = ibutton_worker_alloc(); iButtonWorker* worker = ibutton_worker_alloc();
iButtonKeyType type; iButtonKeyType type;
uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; uint8_t key_data[IBUTTON_KEY_DATA_SIZE];
string_t data; FuriString* data;
string_init(data); data = furi_string_alloc();
ibutton_worker_start_thread(worker); ibutton_worker_start_thread(worker);
do { do {
@ -234,34 +234,34 @@ void ibutton_cli_emulate(Cli* cli, string_t args) {
ibutton_worker_stop(worker); ibutton_worker_stop(worker);
} while(false); } while(false);
string_clear(data); furi_string_free(data);
ibutton_worker_stop_thread(worker); ibutton_worker_stop_thread(worker);
ibutton_worker_free(worker); ibutton_worker_free(worker);
ibutton_key_free(key); ibutton_key_free(key);
}; };
static void ibutton_cli(Cli* cli, string_t args, void* context) { static void ibutton_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(context); UNUSED(context);
string_t cmd; FuriString* cmd;
string_init(cmd); cmd = furi_string_alloc();
if(!args_read_string_and_trim(args, cmd)) { if(!args_read_string_and_trim(args, cmd)) {
string_clear(cmd); furi_string_free(cmd);
ibutton_cli_print_usage(); ibutton_cli_print_usage();
return; return;
} }
if(string_cmp_str(cmd, "read") == 0) { if(furi_string_cmp_str(cmd, "read") == 0) {
ibutton_cli_read(cli); ibutton_cli_read(cli);
} else if(string_cmp_str(cmd, "write") == 0) { } else if(furi_string_cmp_str(cmd, "write") == 0) {
ibutton_cli_write(cli, args); ibutton_cli_write(cli, args);
} else if(string_cmp_str(cmd, "emulate") == 0) { } else if(furi_string_cmp_str(cmd, "emulate") == 0) {
ibutton_cli_emulate(cli, args); ibutton_cli_emulate(cli, args);
} else { } else {
ibutton_cli_print_usage(); ibutton_cli_print_usage();
} }
string_clear(cmd); furi_string_free(cmd);
} }
void onewire_cli_print_usage() { void onewire_cli_print_usage() {
@ -299,20 +299,20 @@ static void onewire_cli_search(Cli* cli) {
onewire_host_free(onewire); onewire_host_free(onewire);
} }
void onewire_cli(Cli* cli, string_t args, void* context) { void onewire_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(context); UNUSED(context);
string_t cmd; FuriString* cmd;
string_init(cmd); cmd = furi_string_alloc();
if(!args_read_string_and_trim(args, cmd)) { if(!args_read_string_and_trim(args, cmd)) {
string_clear(cmd); furi_string_free(cmd);
onewire_cli_print_usage(); onewire_cli_print_usage();
return; return;
} }
if(string_cmp_str(cmd, "search") == 0) { if(furi_string_cmp_str(cmd, "search") == 0) {
onewire_cli_search(cli); onewire_cli_search(cli);
} }
string_clear(cmd); furi_string_free(cmd);
} }

View File

@ -41,7 +41,7 @@ struct iButton {
iButtonWorker* key_worker; iButtonWorker* key_worker;
iButtonKey* key; iButtonKey* key;
string_t file_path; FuriString* file_path;
char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; char text_store[IBUTTON_TEXT_STORE_SIZE + 1];
Submenu* submenu; Submenu* submenu;
@ -78,7 +78,7 @@ typedef enum {
} iButtonNotificationMessage; } iButtonNotificationMessage;
bool ibutton_file_select(iButton* ibutton); bool ibutton_file_select(iButton* ibutton);
bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog); bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog);
bool ibutton_save_key(iButton* ibutton, const char* key_name); bool ibutton_save_key(iButton* ibutton, const char* key_name);
bool ibutton_delete_key(iButton* ibutton); bool ibutton_delete_key(iButton* ibutton);
void ibutton_text_store_set(iButton* ibutton, const char* text, ...); void ibutton_text_store_set(iButton* ibutton, const char* text, ...);

View File

@ -1,5 +1,4 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include "m-string.h"
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexCyfral, SubmenuIndexCyfral,
@ -47,7 +46,7 @@ bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) {
furi_crash("Unknown key type"); furi_crash("Unknown key type");
} }
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
ibutton_key_clear_data(key); ibutton_key_clear_data(key);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue);
} }

View File

@ -17,11 +17,11 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
iButtonKey* key = ibutton->key; iButtonKey* key = ibutton->key;
const uint8_t* key_data = ibutton_key_get_data_p(key); const uint8_t* key_data = ibutton_key_get_data_p(key);
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", furi_string_get_cstr(key_name));
widget_add_text_box_element( widget_add_text_box_element(
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true); widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true);
widget_add_button_element( widget_add_button_element(
@ -68,7 +68,7 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
string_clear(key_name); furi_string_free(key_name);
} }
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {

View File

@ -20,17 +20,17 @@ void ibutton_scene_emulate_on_enter(void* context) {
const uint8_t* key_data = ibutton_key_get_data_p(key); const uint8_t* key_data = ibutton_key_get_data_p(key);
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
} }
DOLPHIN_DEED(DolphinDeedIbuttonEmulate); DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
// check that stored key has name // check that stored key has name
if(!string_empty_p(key_name)) { if(!furi_string_empty(key_name)) {
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
} else { } else {
// if not, show key data // if not, show key data
switch(ibutton_key_get_type(key)) { switch(ibutton_key_get_type(key)) {
@ -69,7 +69,7 @@ void ibutton_scene_emulate_on_enter(void* context) {
ibutton->key_worker, ibutton_scene_emulate_callback, ibutton); ibutton->key_worker, ibutton_scene_emulate_callback, ibutton);
ibutton_worker_emulate_start(ibutton->key_worker, key); ibutton_worker_emulate_start(ibutton->key_worker, key);
string_clear(key_name); furi_string_free(key_name);
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
} }

View File

@ -8,11 +8,11 @@ void ibutton_scene_info_on_enter(void* context) {
const uint8_t* key_data = ibutton_key_get_data_p(key); const uint8_t* key_data = ibutton_key_get_data_p(key);
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
widget_add_text_box_element( widget_add_text_box_element(
widget, 0, 0, 128, 23, AlignCenter, AlignCenter, ibutton->text_store, true); widget, 0, 0, 128, 23, AlignCenter, AlignCenter, ibutton->text_store, true);
@ -50,7 +50,7 @@ void ibutton_scene_info_on_enter(void* context) {
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
string_clear(key_name); furi_string_free(key_name);
} }
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) { bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {

View File

@ -18,7 +18,7 @@ void ibutton_scene_read_on_enter(void* context) {
popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton); ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton);
ibutton_worker_read_start(worker, key); ibutton_worker_read_start(worker, key);

View File

@ -29,19 +29,19 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
if(event.event == iButtonCustomEventRpcLoad) { if(event.event == iButtonCustomEventRpcLoad) {
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
bool result = false; bool result = false;
if(arg && (string_empty_p(ibutton->file_path))) { if(arg && (furi_string_empty(ibutton->file_path))) {
string_set_str(ibutton->file_path, arg); furi_string_set(ibutton->file_path, arg);
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
} }
if(!string_empty_p(key_name)) { if(!furi_string_empty(key_name)) {
ibutton_text_store_set( ibutton_text_store_set(
ibutton, "emulating\n%s", string_get_cstr(key_name)); ibutton, "emulating\n%s", furi_string_get_cstr(key_name));
} else { } else {
ibutton_text_store_set(ibutton, "emulating"); ibutton_text_store_set(ibutton, "emulating");
} }
@ -49,10 +49,10 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
string_clear(key_name); furi_string_free(key_name);
result = true; result = true;
} else { } else {
string_reset(ibutton->file_path); furi_string_reset(ibutton->file_path);
} }
} }
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result); rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);

View File

@ -1,5 +1,4 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include "m-string.h"
#include <lib/toolbox/random_name.h> #include <lib/toolbox/random_name.h>
#include <toolbox/path.h> #include <toolbox/path.h>
@ -12,17 +11,17 @@ void ibutton_scene_save_name_on_enter(void* context) {
iButton* ibutton = context; iButton* ibutton = context;
TextInput* text_input = ibutton->text_input; TextInput* text_input = ibutton->text_input;
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
} }
const bool key_name_is_empty = string_empty_p(key_name); const bool key_name_is_empty = furi_string_empty(key_name);
if(key_name_is_empty) { if(key_name_is_empty) {
set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE); set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE);
} else { } else {
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
} }
text_input_set_header_text(text_input, "Name the key"); text_input_set_header_text(text_input, "Name the key");
@ -34,19 +33,19 @@ void ibutton_scene_save_name_on_enter(void* context) {
IBUTTON_KEY_NAME_SIZE, IBUTTON_KEY_NAME_SIZE,
key_name_is_empty); key_name_is_empty);
string_t folder_path; FuriString* folder_path;
string_init(folder_path); folder_path = furi_string_alloc();
path_extract_dirname(string_get_cstr(ibutton->file_path), folder_path); path_extract_dirname(furi_string_get_cstr(ibutton->file_path), folder_path);
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(folder_path), IBUTTON_APP_EXTENSION, string_get_cstr(key_name)); furi_string_get_cstr(folder_path), IBUTTON_APP_EXTENSION, furi_string_get_cstr(key_name));
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput);
string_clear(key_name); furi_string_free(key_name);
string_clear(folder_path); furi_string_free(folder_path);
} }
bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {

View File

@ -39,7 +39,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexRead) { if(event.event == SubmenuIndexRead) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
} else if(event.event == SubmenuIndexSaved) { } else if(event.event == SubmenuIndexSaved) {
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
} else if(event.event == SubmenuIndexAdd) { } else if(event.event == SubmenuIndexAdd) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType);

View File

@ -1,5 +1,4 @@
#include "../ibutton_i.h" #include "../ibutton_i.h"
#include "m-string.h"
#include "toolbox/path.h" #include "toolbox/path.h"
typedef enum { typedef enum {
@ -20,15 +19,15 @@ void ibutton_scene_write_on_enter(void* context) {
const uint8_t* key_data = ibutton_key_get_data_p(key); const uint8_t* key_data = ibutton_key_get_data_p(key);
string_t key_name; FuriString* key_name;
string_init(key_name); key_name = furi_string_alloc();
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true); path_extract_filename(ibutton->file_path, key_name, true);
} }
// check that stored key has name // check that stored key has name
if(!string_empty_p(key_name)) { if(!furi_string_empty(key_name)) {
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
} else { } else {
// if not, show key data // if not, show key data
switch(ibutton_key_get_type(key)) { switch(ibutton_key_get_type(key)) {
@ -66,7 +65,7 @@ void ibutton_scene_write_on_enter(void* context) {
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton); ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
ibutton_worker_write_start(worker, key); ibutton_worker_write_start(worker, key);
string_clear(key_name); furi_string_free(key_name);
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
} }

View File

@ -65,51 +65,52 @@ static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context
} }
} }
static void infrared_find_vacant_remote_name(string_t name, const char* path) { static void infrared_find_vacant_remote_name(FuriString* name, const char* path) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
string_t base_path; FuriString* base_path;
string_init_set_str(base_path, path); base_path = furi_string_alloc_set(path);
if(string_end_with_str_p(base_path, INFRARED_APP_EXTENSION)) { if(furi_string_end_with(base_path, INFRARED_APP_EXTENSION)) {
size_t filename_start = string_search_rchar(base_path, '/'); size_t filename_start = furi_string_search_rchar(base_path, '/');
string_left(base_path, filename_start); furi_string_left(base_path, filename_start);
} }
string_printf(base_path, "%s/%s%s", path, string_get_cstr(name), INFRARED_APP_EXTENSION); furi_string_printf(
base_path, "%s/%s%s", path, furi_string_get_cstr(name), INFRARED_APP_EXTENSION);
FS_Error status = storage_common_stat(storage, string_get_cstr(base_path), NULL); FS_Error status = storage_common_stat(storage, furi_string_get_cstr(base_path), NULL);
if(status == FSE_OK) { if(status == FSE_OK) {
/* If the suggested name is occupied, try another one (name2, name3, etc) */ /* If the suggested name is occupied, try another one (name2, name3, etc) */
size_t dot = string_search_rchar(base_path, '.'); size_t dot = furi_string_search_rchar(base_path, '.');
string_left(base_path, dot); furi_string_left(base_path, dot);
string_t path_temp; FuriString* path_temp;
string_init(path_temp); path_temp = furi_string_alloc();
uint32_t i = 1; uint32_t i = 1;
do { do {
string_printf( furi_string_printf(
path_temp, "%s%u%s", string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION); path_temp, "%s%lu%s", furi_string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION);
status = storage_common_stat(storage, string_get_cstr(path_temp), NULL); status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL);
} while(status == FSE_OK); } while(status == FSE_OK);
string_clear(path_temp); furi_string_free(path_temp);
if(status == FSE_NOT_EXIST) { if(status == FSE_NOT_EXIST) {
string_cat_printf(name, "%u", i); furi_string_cat_printf(name, "%lu", i);
} }
} }
string_clear(base_path); furi_string_free(base_path);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static Infrared* infrared_alloc() { static Infrared* infrared_alloc() {
Infrared* infrared = malloc(sizeof(Infrared)); Infrared* infrared = malloc(sizeof(Infrared));
string_init(infrared->file_path); infrared->file_path = furi_string_alloc();
InfraredAppState* app_state = &infrared->app_state; InfraredAppState* app_state = &infrared->app_state;
app_state->is_learning_new_remote = false; app_state->is_learning_new_remote = false;
@ -232,7 +233,7 @@ static void infrared_free(Infrared* infrared) {
furi_record_close(RECORD_GUI); furi_record_close(RECORD_GUI);
infrared->gui = NULL; infrared->gui = NULL;
string_clear(infrared->file_path); furi_string_free(infrared->file_path);
free(infrared); free(infrared);
} }
@ -243,19 +244,20 @@ bool infrared_add_remote_with_button(
InfraredSignal* signal) { InfraredSignal* signal) {
InfraredRemote* remote = infrared->remote; InfraredRemote* remote = infrared->remote;
string_t new_name, new_path; FuriString *new_name, *new_path;
string_init_set_str(new_name, INFRARED_DEFAULT_REMOTE_NAME); new_name = furi_string_alloc_set(INFRARED_DEFAULT_REMOTE_NAME);
string_init_set_str(new_path, INFRARED_APP_FOLDER); new_path = furi_string_alloc_set(INFRARED_APP_FOLDER);
infrared_find_vacant_remote_name(new_name, string_get_cstr(new_path)); infrared_find_vacant_remote_name(new_name, furi_string_get_cstr(new_path));
string_cat_printf(new_path, "/%s%s", string_get_cstr(new_name), INFRARED_APP_EXTENSION); furi_string_cat_printf(
new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION);
infrared_remote_reset(remote); infrared_remote_reset(remote);
infrared_remote_set_name(remote, string_get_cstr(new_name)); infrared_remote_set_name(remote, furi_string_get_cstr(new_name));
infrared_remote_set_path(remote, string_get_cstr(new_path)); infrared_remote_set_path(remote, furi_string_get_cstr(new_path));
string_clear(new_name); furi_string_free(new_name);
string_clear(new_path); furi_string_free(new_path);
return infrared_remote_add_button(remote, button_name, signal); return infrared_remote_add_button(remote, button_name, signal);
} }
@ -267,28 +269,29 @@ bool infrared_rename_current_remote(Infrared* infrared, const char* name) {
return true; return true;
} }
string_t new_name; FuriString* new_name;
string_init_set_str(new_name, name); new_name = furi_string_alloc_set(name);
infrared_find_vacant_remote_name(new_name, remote_path); infrared_find_vacant_remote_name(new_name, remote_path);
string_t new_path; FuriString* new_path;
string_init_set(new_path, infrared_remote_get_path(remote)); new_path = furi_string_alloc_set(infrared_remote_get_path(remote));
if(string_end_with_str_p(new_path, INFRARED_APP_EXTENSION)) { if(furi_string_end_with(new_path, INFRARED_APP_EXTENSION)) {
size_t filename_start = string_search_rchar(new_path, '/'); size_t filename_start = furi_string_search_rchar(new_path, '/');
string_left(new_path, filename_start); furi_string_left(new_path, filename_start);
} }
string_cat_printf(new_path, "/%s%s", string_get_cstr(new_name), INFRARED_APP_EXTENSION); furi_string_cat_printf(
new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION);
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FS_Error status = storage_common_rename( FS_Error status = storage_common_rename(
storage, infrared_remote_get_path(remote), string_get_cstr(new_path)); storage, infrared_remote_get_path(remote), furi_string_get_cstr(new_path));
infrared_remote_set_name(remote, string_get_cstr(new_name)); infrared_remote_set_name(remote, furi_string_get_cstr(new_name));
infrared_remote_set_path(remote, string_get_cstr(new_path)); infrared_remote_set_path(remote, furi_string_get_cstr(new_path));
string_clear(new_name); furi_string_free(new_name);
string_clear(new_path); furi_string_free(new_path);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
return (status == FSE_OK || status == FSE_EXIST); return (status == FSE_OK || status == FSE_EXIST);
@ -435,7 +438,7 @@ int32_t infrared_app(void* p) {
rpc_system_app_send_started(infrared->rpc_ctx); rpc_system_app_send_started(infrared->rpc_ctx);
is_rpc_mode = true; is_rpc_mode = true;
} else { } else {
string_set_str(infrared->file_path, (const char*)p); furi_string_set(infrared->file_path, (const char*)p);
is_remote_loaded = infrared_remote_load(infrared->remote, infrared->file_path); is_remote_loaded = infrared_remote_load(infrared->remote, infrared->file_path);
if(!is_remote_loaded) { if(!is_remote_loaded) {
dialog_message_show_storage_error( dialog_message_show_storage_error(

View File

@ -2,7 +2,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <m-dict.h> #include <m-dict.h>
#include <m-string.h>
#include <flipper_format/flipper_format.h> #include <flipper_format/flipper_format.h>
#include "infrared_signal.h" #include "infrared_signal.h"
@ -14,15 +13,15 @@ typedef struct {
DICT_DEF2( DICT_DEF2(
InfraredBruteForceRecordDict, InfraredBruteForceRecordDict,
string_t, FuriString*,
STRING_OPLIST, FURI_STRING_OPLIST,
InfraredBruteForceRecord, InfraredBruteForceRecord,
M_POD_OPLIST); M_POD_OPLIST);
struct InfraredBruteForce { struct InfraredBruteForce {
FlipperFormat* ff; FlipperFormat* ff;
const char* db_filename; const char* db_filename;
string_t current_record_name; FuriString* current_record_name;
InfraredSignal* current_signal; InfraredSignal* current_signal;
InfraredBruteForceRecordDict_t records; InfraredBruteForceRecordDict_t records;
bool is_started; bool is_started;
@ -34,7 +33,7 @@ InfraredBruteForce* infrared_brute_force_alloc() {
brute_force->db_filename = NULL; brute_force->db_filename = NULL;
brute_force->current_signal = NULL; brute_force->current_signal = NULL;
brute_force->is_started = false; brute_force->is_started = false;
string_init(brute_force->current_record_name); brute_force->current_record_name = furi_string_alloc();
InfraredBruteForceRecordDict_init(brute_force->records); InfraredBruteForceRecordDict_init(brute_force->records);
return brute_force; return brute_force;
} }
@ -42,7 +41,7 @@ InfraredBruteForce* infrared_brute_force_alloc() {
void infrared_brute_force_free(InfraredBruteForce* brute_force) { void infrared_brute_force_free(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->is_started); furi_assert(!brute_force->is_started);
InfraredBruteForceRecordDict_clear(brute_force->records); InfraredBruteForceRecordDict_clear(brute_force->records);
string_clear(brute_force->current_record_name); furi_string_free(brute_force->current_record_name);
free(brute_force); free(brute_force);
} }
@ -61,8 +60,8 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
success = flipper_format_buffered_file_open_existing(ff, brute_force->db_filename); success = flipper_format_buffered_file_open_existing(ff, brute_force->db_filename);
if(success) { if(success) {
string_t signal_name; FuriString* signal_name;
string_init(signal_name); signal_name = furi_string_alloc();
while(flipper_format_read_string(ff, "name", signal_name)) { while(flipper_format_read_string(ff, "name", signal_name)) {
InfraredBruteForceRecord* record = InfraredBruteForceRecord* record =
InfraredBruteForceRecordDict_get(brute_force->records, signal_name); InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
@ -70,7 +69,7 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
++(record->count); ++(record->count);
} }
} }
string_clear(signal_name); furi_string_free(signal_name);
} }
flipper_format_free(ff); flipper_format_free(ff);
@ -94,7 +93,7 @@ bool infrared_brute_force_start(
if(record->value.index == index) { if(record->value.index == index) {
*record_count = record->value.count; *record_count = record->value.count;
if(*record_count) { if(*record_count) {
string_set(brute_force->current_record_name, record->key); furi_string_set(brute_force->current_record_name, record->key);
} }
break; break;
} }
@ -118,7 +117,7 @@ bool infrared_brute_force_is_started(InfraredBruteForce* brute_force) {
void infrared_brute_force_stop(InfraredBruteForce* brute_force) { void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
furi_assert(brute_force->is_started); furi_assert(brute_force->is_started);
string_reset(brute_force->current_record_name); furi_string_reset(brute_force->current_record_name);
infrared_signal_free(brute_force->current_signal); infrared_signal_free(brute_force->current_signal);
flipper_format_free(brute_force->ff); flipper_format_free(brute_force->ff);
brute_force->current_signal = NULL; brute_force->current_signal = NULL;
@ -142,10 +141,10 @@ void infrared_brute_force_add_record(
uint32_t index, uint32_t index,
const char* name) { const char* name) {
InfraredBruteForceRecord value = {.index = index, .count = 0}; InfraredBruteForceRecord value = {.index = index, .count = 0};
string_t key; FuriString* key;
string_init_set_str(key, name); key = furi_string_alloc_set(name);
InfraredBruteForceRecordDict_set_at(brute_force->records, key, value); InfraredBruteForceRecordDict_set_at(brute_force->records, key, value);
string_clear(key); furi_string_free(key);
} }
void infrared_brute_force_reset(InfraredBruteForce* brute_force) { void infrared_brute_force_reset(InfraredBruteForce* brute_force) {

View File

@ -1,4 +1,3 @@
#include <m-string.h>
#include <cli/cli.h> #include <cli/cli.h>
#include <infrared.h> #include <infrared.h>
#include <infrared_worker.h> #include <infrared_worker.h>
@ -10,13 +9,13 @@
#define INFRARED_CLI_BUF_SIZE 10 #define INFRARED_CLI_BUF_SIZE 10
static void infrared_cli_start_ir_rx(Cli* cli, string_t args); static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args);
static void infrared_cli_start_ir_tx(Cli* cli, string_t args); static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args);
static void infrared_cli_process_decode(Cli* cli, string_t args); static void infrared_cli_process_decode(Cli* cli, FuriString* args);
static const struct { static const struct {
const char* cmd; const char* cmd;
void (*process_function)(Cli* cli, string_t args); void (*process_function)(Cli* cli, FuriString* args);
} infrared_cli_commands[] = { } infrared_cli_commands[] = {
{.cmd = "rx", .process_function = infrared_cli_start_ir_rx}, {.cmd = "rx", .process_function = infrared_cli_start_ir_rx},
{.cmd = "tx", .process_function = infrared_cli_start_ir_tx}, {.cmd = "tx", .process_function = infrared_cli_start_ir_tx},
@ -58,7 +57,7 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv
} }
} }
static void infrared_cli_start_ir_rx(Cli* cli, string_t args) { static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
UNUSED(args); UNUSED(args);
InfraredWorker* worker = infrared_worker_alloc(); InfraredWorker* worker = infrared_worker_alloc();
@ -151,9 +150,9 @@ static bool infrared_cli_parse_raw(const char* str, InfraredSignal* signal) {
return infrared_signal_is_valid(signal); return infrared_signal_is_valid(signal);
} }
static void infrared_cli_start_ir_tx(Cli* cli, string_t args) { static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
const char* str = string_get_cstr(args); const char* str = furi_string_get_cstr(args);
InfraredSignal* signal = infrared_signal_alloc(); InfraredSignal* signal = infrared_signal_alloc();
bool success = infrared_cli_parse_message(str, signal) || infrared_cli_parse_raw(str, signal); bool success = infrared_cli_parse_message(str, signal) || infrared_cli_parse_raw(str, signal);
@ -231,8 +230,8 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o
InfraredSignal* signal = infrared_signal_alloc(); InfraredSignal* signal = infrared_signal_alloc();
InfraredDecoderHandler* decoder = infrared_alloc_decoder(); InfraredDecoderHandler* decoder = infrared_alloc_decoder();
string_t tmp; FuriString* tmp;
string_init(tmp); tmp = furi_string_alloc();
while(infrared_signal_read(signal, input_file, tmp)) { while(infrared_signal_read(signal, input_file, tmp)) {
ret = false; ret = false;
@ -242,7 +241,7 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o
} }
if(!infrared_signal_is_raw(signal)) { if(!infrared_signal_is_raw(signal)) {
if(output_file && if(output_file &&
!infrared_cli_save_signal(signal, output_file, string_get_cstr(tmp))) { !infrared_cli_save_signal(signal, output_file, furi_string_get_cstr(tmp))) {
break; break;
} else { } else {
printf("Skipping decoded signal\r\n"); printf("Skipping decoded signal\r\n");
@ -250,31 +249,33 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o
} }
} }
InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal); InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal);
printf("Raw signal: %s, %u samples\r\n", string_get_cstr(tmp), raw_signal->timings_size); printf(
if(!infrared_cli_decode_raw_signal(raw_signal, decoder, output_file, string_get_cstr(tmp))) "Raw signal: %s, %u samples\r\n", furi_string_get_cstr(tmp), raw_signal->timings_size);
if(!infrared_cli_decode_raw_signal(
raw_signal, decoder, output_file, furi_string_get_cstr(tmp)))
break; break;
ret = true; ret = true;
} }
infrared_free_decoder(decoder); infrared_free_decoder(decoder);
infrared_signal_free(signal); infrared_signal_free(signal);
string_clear(tmp); furi_string_free(tmp);
return ret; return ret;
} }
static void infrared_cli_process_decode(Cli* cli, string_t args) { static void infrared_cli_process_decode(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* input_file = flipper_format_buffered_file_alloc(storage); FlipperFormat* input_file = flipper_format_buffered_file_alloc(storage);
FlipperFormat* output_file = NULL; FlipperFormat* output_file = NULL;
uint32_t version; uint32_t version;
string_t tmp, header, input_path, output_path; FuriString *tmp, *header, *input_path, *output_path;
string_init(tmp); tmp = furi_string_alloc();
string_init(header); header = furi_string_alloc();
string_init(input_path); input_path = furi_string_alloc();
string_init(output_path); output_path = furi_string_alloc();
do { do {
if(!args_read_probably_quoted_string_and_trim(args, input_path)) { if(!args_read_probably_quoted_string_and_trim(args, input_path)) {
@ -283,26 +284,32 @@ static void infrared_cli_process_decode(Cli* cli, string_t args) {
break; break;
} }
args_read_probably_quoted_string_and_trim(args, output_path); args_read_probably_quoted_string_and_trim(args, output_path);
if(!flipper_format_buffered_file_open_existing(input_file, string_get_cstr(input_path))) { if(!flipper_format_buffered_file_open_existing(
printf("Failed to open file for reading: \"%s\"\r\n", string_get_cstr(input_path)); input_file, furi_string_get_cstr(input_path))) {
printf(
"Failed to open file for reading: \"%s\"\r\n", furi_string_get_cstr(input_path));
break; break;
} }
if(!flipper_format_read_header(input_file, header, &version) || if(!flipper_format_read_header(input_file, header, &version) ||
(!string_start_with_str_p(header, "IR")) || version != 1) { (!furi_string_start_with_str(header, "IR")) || version != 1) {
printf("Invalid or corrupted input file: \"%s\"\r\n", string_get_cstr(input_path)); printf(
"Invalid or corrupted input file: \"%s\"\r\n", furi_string_get_cstr(input_path));
break; break;
} }
if(!string_empty_p(output_path)) { if(!furi_string_empty(output_path)) {
printf("Writing output to file: \"%s\"\r\n", string_get_cstr(output_path)); printf("Writing output to file: \"%s\"\r\n", furi_string_get_cstr(output_path));
output_file = flipper_format_file_alloc(storage); output_file = flipper_format_file_alloc(storage);
} }
if(output_file && if(output_file &&
!flipper_format_file_open_always(output_file, string_get_cstr(output_path))) { !flipper_format_file_open_always(output_file, furi_string_get_cstr(output_path))) {
printf("Failed to open file for writing: \"%s\"\r\n", string_get_cstr(output_path)); printf(
"Failed to open file for writing: \"%s\"\r\n", furi_string_get_cstr(output_path));
break; break;
} }
if(output_file && !flipper_format_write_header(output_file, header, version)) { if(output_file && !flipper_format_write_header(output_file, header, version)) {
printf("Failed to write to the output file: \"%s\"\r\n", string_get_cstr(output_path)); printf(
"Failed to write to the output file: \"%s\"\r\n",
furi_string_get_cstr(output_path));
break; break;
} }
if(!infrared_cli_decode_file(input_file, output_file)) { if(!infrared_cli_decode_file(input_file, output_file)) {
@ -311,31 +318,31 @@ static void infrared_cli_process_decode(Cli* cli, string_t args) {
printf("File successfully decoded.\r\n"); printf("File successfully decoded.\r\n");
} while(false); } while(false);
string_clear(tmp); furi_string_free(tmp);
string_clear(header); furi_string_free(header);
string_clear(input_path); furi_string_free(input_path);
string_clear(output_path); furi_string_free(output_path);
flipper_format_free(input_file); flipper_format_free(input_file);
if(output_file) flipper_format_free(output_file); if(output_file) flipper_format_free(output_file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { static void infrared_cli_start_ir(Cli* cli, FuriString* args, void* context) {
UNUSED(context); UNUSED(context);
if(furi_hal_infrared_is_busy()) { if(furi_hal_infrared_is_busy()) {
printf("INFRARED is busy. Exiting."); printf("INFRARED is busy. Exiting.");
return; return;
} }
string_t command; FuriString* command;
string_init(command); command = furi_string_alloc();
args_read_string_and_trim(args, command); args_read_string_and_trim(args, command);
size_t i = 0; size_t i = 0;
for(; i < COUNT_OF(infrared_cli_commands); ++i) { for(; i < COUNT_OF(infrared_cli_commands); ++i) {
size_t cmd_len = strlen(infrared_cli_commands[i].cmd); size_t cmd_len = strlen(infrared_cli_commands[i].cmd);
if(!strncmp(string_get_cstr(command), infrared_cli_commands[i].cmd, cmd_len)) { if(!strncmp(furi_string_get_cstr(command), infrared_cli_commands[i].cmd, cmd_len)) {
break; break;
} }
} }
@ -346,7 +353,7 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) {
infrared_cli_print_usage(); infrared_cli_print_usage();
} }
string_clear(command); furi_string_free(command);
} }
void infrared_on_system_start() { void infrared_on_system_start() {
#ifdef SRV_CLI #ifdef SRV_CLI

View File

@ -96,7 +96,7 @@ struct Infrared {
Loading* loading; Loading* loading;
InfraredProgressView* progress; InfraredProgressView* progress;
string_t file_path; FuriString* file_path;
char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1];
InfraredAppState app_state; InfraredAppState app_state;

View File

@ -3,7 +3,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <m-string.h>
#include <m-array.h> #include <m-array.h>
#include <toolbox/path.h> #include <toolbox/path.h>
#include <storage/storage.h> #include <storage/storage.h>
@ -15,8 +14,8 @@ ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST);
struct InfraredRemote { struct InfraredRemote {
InfraredButtonArray_t buttons; InfraredButtonArray_t buttons;
string_t name; FuriString* name;
string_t path; FuriString* path;
}; };
static void infrared_remote_clear_buttons(InfraredRemote* remote) { static void infrared_remote_clear_buttons(InfraredRemote* remote) {
@ -31,39 +30,39 @@ static void infrared_remote_clear_buttons(InfraredRemote* remote) {
InfraredRemote* infrared_remote_alloc() { InfraredRemote* infrared_remote_alloc() {
InfraredRemote* remote = malloc(sizeof(InfraredRemote)); InfraredRemote* remote = malloc(sizeof(InfraredRemote));
InfraredButtonArray_init(remote->buttons); InfraredButtonArray_init(remote->buttons);
string_init(remote->name); remote->name = furi_string_alloc();
string_init(remote->path); remote->path = furi_string_alloc();
return remote; return remote;
} }
void infrared_remote_free(InfraredRemote* remote) { void infrared_remote_free(InfraredRemote* remote) {
infrared_remote_clear_buttons(remote); infrared_remote_clear_buttons(remote);
InfraredButtonArray_clear(remote->buttons); InfraredButtonArray_clear(remote->buttons);
string_clear(remote->path); furi_string_free(remote->path);
string_clear(remote->name); furi_string_free(remote->name);
free(remote); free(remote);
} }
void infrared_remote_reset(InfraredRemote* remote) { void infrared_remote_reset(InfraredRemote* remote) {
infrared_remote_clear_buttons(remote); infrared_remote_clear_buttons(remote);
string_reset(remote->name); furi_string_reset(remote->name);
string_reset(remote->path); furi_string_reset(remote->path);
} }
void infrared_remote_set_name(InfraredRemote* remote, const char* name) { void infrared_remote_set_name(InfraredRemote* remote, const char* name) {
string_set_str(remote->name, name); furi_string_set(remote->name, name);
} }
const char* infrared_remote_get_name(InfraredRemote* remote) { const char* infrared_remote_get_name(InfraredRemote* remote) {
return string_get_cstr(remote->name); return furi_string_get_cstr(remote->name);
} }
void infrared_remote_set_path(InfraredRemote* remote, const char* path) { void infrared_remote_set_path(InfraredRemote* remote, const char* path) {
string_set_str(remote->path, path); furi_string_set(remote->path, path);
} }
const char* infrared_remote_get_path(InfraredRemote* remote) { const char* infrared_remote_get_path(InfraredRemote* remote) {
return string_get_cstr(remote->path); return furi_string_get_cstr(remote->path);
} }
size_t infrared_remote_get_button_count(InfraredRemote* remote) { size_t infrared_remote_get_button_count(InfraredRemote* remote) {
@ -112,7 +111,7 @@ bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) {
bool infrared_remote_store(InfraredRemote* remote) { bool infrared_remote_store(InfraredRemote* remote) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_file_alloc(storage); FlipperFormat* ff = flipper_format_file_alloc(storage);
const char* path = string_get_cstr(remote->path); const char* path = furi_string_get_cstr(remote->path);
FURI_LOG_I(TAG, "store file: \'%s\'", path); FURI_LOG_I(TAG, "store file: \'%s\'", path);
@ -138,33 +137,33 @@ bool infrared_remote_store(InfraredRemote* remote) {
return success; return success;
} }
bool infrared_remote_load(InfraredRemote* remote, string_t path) { bool infrared_remote_load(InfraredRemote* remote, FuriString* path) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
FURI_LOG_I(TAG, "load file: \'%s\'", string_get_cstr(path)); FURI_LOG_I(TAG, "load file: \'%s\'", furi_string_get_cstr(path));
bool success = flipper_format_buffered_file_open_existing(ff, string_get_cstr(path)); bool success = flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path));
if(success) { if(success) {
uint32_t version; uint32_t version;
success = flipper_format_read_header(ff, buf, &version) && success = flipper_format_read_header(ff, buf, &version) &&
!string_cmp_str(buf, "IR signals file") && (version == 1); !furi_string_cmp(buf, "IR signals file") && (version == 1);
} }
if(success) { if(success) {
path_extract_filename(path, buf, true); path_extract_filename(path, buf, true);
infrared_remote_clear_buttons(remote); infrared_remote_clear_buttons(remote);
infrared_remote_set_name(remote, string_get_cstr(buf)); infrared_remote_set_name(remote, furi_string_get_cstr(buf));
infrared_remote_set_path(remote, string_get_cstr(path)); infrared_remote_set_path(remote, furi_string_get_cstr(path));
for(bool can_read = true; can_read;) { for(bool can_read = true; can_read;) {
InfraredRemoteButton* button = infrared_remote_button_alloc(); InfraredRemoteButton* button = infrared_remote_button_alloc();
can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf); can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf);
if(can_read) { if(can_read) {
infrared_remote_button_set_name(button, string_get_cstr(buf)); infrared_remote_button_set_name(button, furi_string_get_cstr(buf));
InfraredButtonArray_push_back(remote->buttons, button); InfraredButtonArray_push_back(remote->buttons, button);
} else { } else {
infrared_remote_button_free(button); infrared_remote_button_free(button);
@ -172,7 +171,7 @@ bool infrared_remote_load(InfraredRemote* remote, string_t path) {
} }
} }
string_clear(buf); furi_string_free(buf);
flipper_format_free(ff); flipper_format_free(ff);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
return success; return success;
@ -181,7 +180,7 @@ bool infrared_remote_load(InfraredRemote* remote, string_t path) {
bool infrared_remote_remove(InfraredRemote* remote) { bool infrared_remote_remove(InfraredRemote* remote) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FS_Error status = storage_common_remove(storage, string_get_cstr(remote->path)); FS_Error status = storage_common_remove(storage, furi_string_get_cstr(remote->path));
infrared_remote_reset(remote); infrared_remote_reset(remote);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);

View File

@ -25,5 +25,5 @@ bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name,
bool infrared_remote_delete_button(InfraredRemote* remote, size_t index); bool infrared_remote_delete_button(InfraredRemote* remote, size_t index);
bool infrared_remote_store(InfraredRemote* remote); bool infrared_remote_store(InfraredRemote* remote);
bool infrared_remote_load(InfraredRemote* remote, string_t path); bool infrared_remote_load(InfraredRemote* remote, FuriString* path);
bool infrared_remote_remove(InfraredRemote* remote); bool infrared_remote_remove(InfraredRemote* remote);

View File

@ -1,32 +1,31 @@
#include "infrared_remote_button.h" #include "infrared_remote_button.h"
#include <stdlib.h> #include <stdlib.h>
#include <m-string.h>
struct InfraredRemoteButton { struct InfraredRemoteButton {
string_t name; FuriString* name;
InfraredSignal* signal; InfraredSignal* signal;
}; };
InfraredRemoteButton* infrared_remote_button_alloc() { InfraredRemoteButton* infrared_remote_button_alloc() {
InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton)); InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton));
string_init(button->name); button->name = furi_string_alloc();
button->signal = infrared_signal_alloc(); button->signal = infrared_signal_alloc();
return button; return button;
} }
void infrared_remote_button_free(InfraredRemoteButton* button) { void infrared_remote_button_free(InfraredRemoteButton* button) {
string_clear(button->name); furi_string_free(button->name);
infrared_signal_free(button->signal); infrared_signal_free(button->signal);
free(button); free(button);
} }
void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name) { void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name) {
string_set_str(button->name, name); furi_string_set(button->name, name);
} }
const char* infrared_remote_button_get_name(InfraredRemoteButton* button) { const char* infrared_remote_button_get_name(InfraredRemoteButton* button) {
return string_get_cstr(button->name); return furi_string_get_cstr(button->name);
} }
void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal) { void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal) {

View File

@ -61,7 +61,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) {
if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) { if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
FURI_LOG_E( FURI_LOG_E(
TAG, TAG,
"Frequency is out of range (%lX - %lX): %lX", "Frequency is out of range (%X - %X): %lX",
INFRARED_MIN_FREQUENCY, INFRARED_MIN_FREQUENCY,
INFRARED_MAX_FREQUENCY, INFRARED_MAX_FREQUENCY,
raw->frequency); raw->frequency);
@ -74,7 +74,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) {
} else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) { } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
FURI_LOG_E( FURI_LOG_E(
TAG, TAG,
"Timings amount is out of range (0 - %lX): %lX", "Timings amount is out of range (0 - %X): %X",
MAX_TIMINGS_AMOUNT, MAX_TIMINGS_AMOUNT,
raw->timings_size); raw->timings_size);
return false; return false;
@ -100,15 +100,15 @@ static inline bool infrared_signal_save_raw(InfraredRawSignal* raw, FlipperForma
} }
static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) { static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
string_t buf; FuriString* buf;
string_init(buf); buf = furi_string_alloc();
bool success = false; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "protocol", buf)) break; if(!flipper_format_read_string(ff, "protocol", buf)) break;
InfraredMessage message; InfraredMessage message;
message.protocol = infrared_get_protocol_by_name(string_get_cstr(buf)); message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) && success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) && flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
@ -119,7 +119,7 @@ static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperF
infrared_signal_set_message(signal, &message); infrared_signal_set_message(signal, &message);
} while(0); } while(0);
string_clear(buf); furi_string_free(buf);
return success; return success;
} }
@ -147,22 +147,22 @@ static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperForma
} }
static bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) { static bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
string_t tmp; FuriString* tmp = furi_string_alloc();
string_init(tmp);
bool success = false; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "type", tmp)) break; if(!flipper_format_read_string(ff, "type", tmp)) break;
if(string_equal_p(tmp, "raw")) { if(furi_string_equal(tmp, "raw")) {
success = infrared_signal_read_raw(signal, ff); success = infrared_signal_read_raw(signal, ff);
} else if(string_equal_p(tmp, "parsed")) { } else if(furi_string_equal(tmp, "parsed")) {
success = infrared_signal_read_message(signal, ff); success = infrared_signal_read_message(signal, ff);
} else { } else {
FURI_LOG_E(TAG, "Unknown signal type"); FURI_LOG_E(TAG, "Unknown signal type");
} }
} while(false); } while(false);
string_clear(tmp); furi_string_free(tmp);
return success; return success;
} }
@ -246,34 +246,33 @@ bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char*
} }
} }
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name) { bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
string_t tmp; FuriString* tmp = furi_string_alloc();
string_init(tmp);
bool success = false; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "name", tmp)) break; if(!flipper_format_read_string(ff, "name", tmp)) break;
string_set(name, tmp); furi_string_set(name, tmp);
if(!infrared_signal_read_body(signal, ff)) break; if(!infrared_signal_read_body(signal, ff)) break;
success = true; success = true;
} while(0); } while(0);
string_clear(tmp); furi_string_free(tmp);
return success; return success;
} }
bool infrared_signal_search_and_read( bool infrared_signal_search_and_read(
InfraredSignal* signal, InfraredSignal* signal,
FlipperFormat* ff, FlipperFormat* ff,
const string_t name) { const FuriString* name) {
bool success = false; bool success = false;
string_t tmp; FuriString* tmp = furi_string_alloc();
string_init(tmp);
do { do {
bool is_name_found = false; bool is_name_found = false;
while(flipper_format_read_string(ff, "name", tmp)) { while(flipper_format_read_string(ff, "name", tmp)) {
is_name_found = string_equal_p(name, tmp); is_name_found = furi_string_equal(name, tmp);
if(is_name_found) break; if(is_name_found) break;
} }
if(!is_name_found) break; if(!is_name_found) break;
@ -281,7 +280,7 @@ bool infrared_signal_search_and_read(
success = true; success = true;
} while(false); } while(false);
string_clear(tmp); furi_string_free(tmp);
return success; return success;
} }

View File

@ -36,10 +36,10 @@ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage*
InfraredMessage* infrared_signal_get_message(InfraredSignal* signal); InfraredMessage* infrared_signal_get_message(InfraredSignal* signal);
bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name); bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name);
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name); bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name);
bool infrared_signal_search_and_read( bool infrared_signal_search_and_read(
InfraredSignal* signal, InfraredSignal* signal,
FlipperFormat* ff, FlipperFormat* ff,
const string_t name); const FuriString* name);
void infrared_signal_transmit(InfraredSignal* signal); void infrared_signal_transmit(InfraredSignal* signal);

View File

@ -70,7 +70,7 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
uint32_t record_count; uint32_t record_count;
if(infrared_brute_force_start( if(infrared_brute_force_start(
brute_force, infrared_custom_event_get_value(event.event), &record_count)) { brute_force, infrared_custom_event_get_value(event.event), &record_count)) {
DOLPHIN_DEED(DolphinDeedIrBruteForce); DOLPHIN_DEED(DolphinDeedIrSend);
infrared_scene_universal_common_show_popup(infrared, record_count); infrared_scene_universal_common_show_popup(infrared, record_count);
} else { } else {
scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases); scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases);

View File

@ -29,20 +29,20 @@ void infrared_scene_edit_rename_on_enter(void* context) {
enter_name_length = INFRARED_MAX_REMOTE_NAME_LENGTH; enter_name_length = INFRARED_MAX_REMOTE_NAME_LENGTH;
strncpy(infrared->text_store[0], infrared_remote_get_name(remote), enter_name_length); strncpy(infrared->text_store[0], infrared_remote_get_name(remote), enter_name_length);
string_t folder_path; FuriString* folder_path;
string_init(folder_path); folder_path = furi_string_alloc();
if(string_end_with_str_p(infrared->file_path, INFRARED_APP_EXTENSION)) { if(furi_string_end_with(infrared->file_path, INFRARED_APP_EXTENSION)) {
path_extract_dirname(string_get_cstr(infrared->file_path), folder_path); path_extract_dirname(furi_string_get_cstr(infrared->file_path), folder_path);
} }
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(folder_path), furi_string_get_cstr(folder_path),
INFRARED_APP_EXTENSION, INFRARED_APP_EXTENSION,
infrared_remote_get_name(remote)); infrared_remote_get_name(remote));
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
string_clear(folder_path); furi_string_free(folder_path);
} else { } else {
furi_assert(0); furi_assert(0);
} }

View File

@ -50,8 +50,10 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e
if(success) { if(success) {
scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); scene_manager_next_scene(scene_manager, InfraredSceneLearnDone);
} else { } else {
scene_manager_search_and_switch_to_previous_scene( dialog_message_show_storage_error(infrared->dialogs, "Failed to save file");
scene_manager, InfraredSceneRemoteList); const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
scene_manager_search_and_switch_to_previous_scene_one_of(
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
} }
consumed = true; consumed = true;
} }

View File

@ -42,7 +42,7 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
bool result = false; bool result = false;
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
if(arg && (state == InfraredRpcStateIdle)) { if(arg && (state == InfraredRpcStateIdle)) {
string_set_str(infrared->file_path, arg); furi_string_set(infrared->file_path, arg);
result = infrared_remote_load(infrared->remote, infrared->file_path); result = infrared_remote_load(infrared->remote, infrared->file_path);
if(result) { if(result) {
scene_manager_set_scene_state( scene_manager_set_scene_state(

View File

@ -66,7 +66,7 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(scene_manager, InfraredSceneLearn); scene_manager_next_scene(scene_manager, InfraredSceneLearn);
consumed = true; consumed = true;
} else if(submenu_index == SubmenuIndexSavedRemotes) { } else if(submenu_index == SubmenuIndexSavedRemotes) {
string_set_str(infrared->file_path, INFRARED_APP_FOLDER); furi_string_set(infrared->file_path, INFRARED_APP_FOLDER);
scene_manager_next_scene(scene_manager, InfraredSceneRemoteList); scene_manager_next_scene(scene_manager, InfraredSceneRemoteList);
consumed = true; consumed = true;
} else if(submenu_index == SubmenuIndexDebug) { } else if(submenu_index == SubmenuIndexDebug) {

View File

@ -4,7 +4,6 @@
#include "gui/canvas.h" #include "gui/canvas.h"
#include "gui/view.h" #include "gui/view.h"
#include "input/input.h" #include "input/input.h"
#include "m-string.h"
#include <gui/elements.h> #include <gui/elements.h>
#include <furi.h> #include <furi.h>
#include "infrared_progress_view.h" #include "infrared_progress_view.h"

View File

@ -36,9 +36,9 @@ static LfRfid* lfrfid_alloc() {
lfrfid->storage = furi_record_open(RECORD_STORAGE); lfrfid->storage = furi_record_open(RECORD_STORAGE);
lfrfid->dialogs = furi_record_open(RECORD_DIALOGS); lfrfid->dialogs = furi_record_open(RECORD_DIALOGS);
string_init(lfrfid->file_name); lfrfid->file_name = furi_string_alloc();
string_init(lfrfid->raw_file_name); lfrfid->raw_file_name = furi_string_alloc();
string_init_set_str(lfrfid->file_path, LFRFID_APP_FOLDER); lfrfid->file_path = furi_string_alloc_set(LFRFID_APP_FOLDER);
lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
@ -104,9 +104,9 @@ static LfRfid* lfrfid_alloc() {
static void lfrfid_free(LfRfid* lfrfid) { static void lfrfid_free(LfRfid* lfrfid) {
furi_assert(lfrfid); furi_assert(lfrfid);
string_clear(lfrfid->raw_file_name); furi_string_free(lfrfid->raw_file_name);
string_clear(lfrfid->file_name); furi_string_free(lfrfid->file_name);
string_clear(lfrfid->file_path); furi_string_free(lfrfid->file_path);
protocol_dict_free(lfrfid->dict); protocol_dict_free(lfrfid->dict);
lfrfid_worker_free(lfrfid->lfworker); lfrfid_worker_free(lfrfid->lfworker);
@ -183,7 +183,7 @@ int32_t lfrfid_app(void* p) {
app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop); app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop);
scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc); scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc);
} else { } else {
string_set_str(app->file_path, args); furi_string_set(app->file_path, args);
lfrfid_load_key_data(app, app->file_path, true); lfrfid_load_key_data(app, app->file_path, true);
view_dispatcher_attach_to_gui( view_dispatcher_attach_to_gui(
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
@ -210,13 +210,13 @@ bool lfrfid_save_key(LfRfid* app) {
lfrfid_make_app_folder(app); lfrfid_make_app_folder(app);
if(string_end_with_str_p(app->file_path, LFRFID_APP_EXTENSION)) { if(furi_string_end_with(app->file_path, LFRFID_APP_EXTENSION)) {
size_t filename_start = string_search_rchar(app->file_path, '/'); size_t filename_start = furi_string_search_rchar(app->file_path, '/');
string_left(app->file_path, filename_start); furi_string_left(app->file_path, filename_start);
} }
string_cat_printf( furi_string_cat_printf(
app->file_path, "/%s%s", string_get_cstr(app->file_name), LFRFID_APP_EXTENSION); app->file_path, "/%s%s", furi_string_get_cstr(app->file_name), LFRFID_APP_EXTENSION);
result = lfrfid_save_key_data(app, app->file_path); result = lfrfid_save_key_data(app, app->file_path);
return result; return result;
@ -242,14 +242,14 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) {
bool lfrfid_delete_key(LfRfid* app) { bool lfrfid_delete_key(LfRfid* app) {
furi_assert(app); furi_assert(app);
return storage_simply_remove(app->storage, string_get_cstr(app->file_path)); return storage_simply_remove(app->storage, furi_string_get_cstr(app->file_path));
} }
bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog) { bool lfrfid_load_key_data(LfRfid* app, FuriString* path, bool show_dialog) {
bool result = false; bool result = false;
do { do {
app->protocol_id = lfrfid_dict_file_load(app->dict, string_get_cstr(path)); app->protocol_id = lfrfid_dict_file_load(app->dict, furi_string_get_cstr(path));
if(app->protocol_id == PROTOCOL_NO) break; if(app->protocol_id == PROTOCOL_NO) break;
path_extract_filename(path, app->file_name, true); path_extract_filename(path, app->file_name, true);
@ -263,8 +263,8 @@ bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog) {
return result; return result;
} }
bool lfrfid_save_key_data(LfRfid* app, string_t path) { bool lfrfid_save_key_data(LfRfid* app, FuriString* path) {
bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, string_get_cstr(path)); bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, furi_string_get_cstr(path));
if(!result) { if(!result) {
dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file"); dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file");

View File

@ -14,7 +14,7 @@
#include <lfrfid/lfrfid_raw_file.h> #include <lfrfid/lfrfid_raw_file.h>
#include <toolbox/pulse_protocols/pulse_glue.h> #include <toolbox/pulse_protocols/pulse_glue.h>
static void lfrfid_cli(Cli* cli, string_t args, void* context); static void lfrfid_cli(Cli* cli, FuriString* args, void* context);
// app cli function // app cli function
void lfrfid_on_system_start() { void lfrfid_on_system_start() {
@ -46,27 +46,28 @@ static void lfrfid_cli_read_callback(LFRFIDWorkerReadResult result, ProtocolId p
furi_event_flag_set(context->event, 1 << result); furi_event_flag_set(context->event, 1 << result);
} }
static void lfrfid_cli_read(Cli* cli, string_t args) { static void lfrfid_cli_read(Cli* cli, FuriString* args) {
string_t type_string; FuriString* type_string;
string_init(type_string); type_string = furi_string_alloc();
LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto; LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto;
if(args_read_string_and_trim(args, type_string)) { if(args_read_string_and_trim(args, type_string)) {
if(string_cmp_str(type_string, "normal") == 0 || string_cmp_str(type_string, "ask") == 0) { if(furi_string_cmp_str(type_string, "normal") == 0 ||
furi_string_cmp_str(type_string, "ask") == 0) {
// ask // ask
type = LFRFIDWorkerReadTypeASKOnly; type = LFRFIDWorkerReadTypeASKOnly;
} else if( } else if(
string_cmp_str(type_string, "indala") == 0 || furi_string_cmp_str(type_string, "indala") == 0 ||
string_cmp_str(type_string, "psk") == 0) { furi_string_cmp_str(type_string, "psk") == 0) {
// psk // psk
type = LFRFIDWorkerReadTypePSKOnly; type = LFRFIDWorkerReadTypePSKOnly;
} else { } else {
lfrfid_cli_print_usage(); lfrfid_cli_print_usage();
string_clear(type_string); furi_string_free(type_string);
return; return;
} }
} }
string_clear(type_string); furi_string_free(type_string);
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
LFRFIDWorker* worker = lfrfid_worker_alloc(dict); LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
@ -111,13 +112,13 @@ static void lfrfid_cli_read(Cli* cli, string_t args) {
printf("\r\n"); printf("\r\n");
free(data); free(data);
string_t info; FuriString* info;
string_init(info); info = furi_string_alloc();
protocol_dict_render_data(dict, info, context.protocol); protocol_dict_render_data(dict, info, context.protocol);
if(!string_empty_p(info)) { if(!furi_string_empty(info)) {
printf("%s\r\n", string_get_cstr(info)); printf("%s\r\n", furi_string_get_cstr(info));
} }
string_clear(info); furi_string_free(info);
} }
printf("Reading stopped\r\n"); printf("Reading stopped\r\n");
@ -126,11 +127,11 @@ static void lfrfid_cli_read(Cli* cli, string_t args) {
furi_event_flag_free(context.event); furi_event_flag_free(context.event);
} }
static bool lfrfid_cli_parse_args(string_t args, ProtocolDict* dict, ProtocolId* protocol) { static bool lfrfid_cli_parse_args(FuriString* args, ProtocolDict* dict, ProtocolId* protocol) {
bool result = false; bool result = false;
string_t protocol_name, data_text; FuriString *protocol_name, *data_text;
string_init(protocol_name); protocol_name = furi_string_alloc();
string_init(data_text); data_text = furi_string_alloc();
size_t data_size = protocol_dict_get_max_data_size(dict); size_t data_size = protocol_dict_get_max_data_size(dict);
uint8_t* data = malloc(data_size); uint8_t* data = malloc(data_size);
@ -143,12 +144,12 @@ static bool lfrfid_cli_parse_args(string_t args, ProtocolDict* dict, ProtocolId*
} }
// check protocol arg // check protocol arg
*protocol = protocol_dict_get_protocol_by_name(dict, string_get_cstr(protocol_name)); *protocol = protocol_dict_get_protocol_by_name(dict, furi_string_get_cstr(protocol_name));
if(*protocol == PROTOCOL_NO) { if(*protocol == PROTOCOL_NO) {
printf( printf(
"Unknown protocol: %s\r\n" "Unknown protocol: %s\r\n"
"Available protocols:\r\n", "Available protocols:\r\n",
string_get_cstr(protocol_name)); furi_string_get_cstr(protocol_name));
for(ProtocolId i = 0; i < LFRFIDProtocolMax; i++) { for(ProtocolId i = 0; i < LFRFIDProtocolMax; i++) {
printf( printf(
@ -177,8 +178,8 @@ static bool lfrfid_cli_parse_args(string_t args, ProtocolDict* dict, ProtocolId*
} while(false); } while(false);
free(data); free(data);
string_clear(protocol_name); furi_string_free(protocol_name);
string_clear(data_text); furi_string_free(data_text);
return result; return result;
} }
@ -188,7 +189,7 @@ static void lfrfid_cli_write_callback(LFRFIDWorkerWriteResult result, void* ctx)
furi_event_flag_set(events, 1 << result); furi_event_flag_set(events, 1 << result);
} }
static void lfrfid_cli_write(Cli* cli, string_t args) { static void lfrfid_cli_write(Cli* cli, FuriString* args) {
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
ProtocolId protocol; ProtocolId protocol;
@ -235,7 +236,7 @@ static void lfrfid_cli_write(Cli* cli, string_t args) {
furi_event_flag_free(event); furi_event_flag_free(event);
} }
static void lfrfid_cli_emulate(Cli* cli, string_t args) { static void lfrfid_cli_emulate(Cli* cli, FuriString* args) {
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
ProtocolId protocol; ProtocolId protocol;
@ -261,11 +262,11 @@ static void lfrfid_cli_emulate(Cli* cli, string_t args) {
protocol_dict_free(dict); protocol_dict_free(dict);
} }
static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) { static void lfrfid_cli_raw_analyze(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
string_t filepath, info_string; FuriString *filepath, *info_string;
string_init(filepath); filepath = furi_string_alloc();
string_init(info_string); info_string = furi_string_alloc();
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage); LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
@ -278,7 +279,7 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) {
break; break;
} }
if(!lfrfid_raw_file_open_read(file, string_get_cstr(filepath))) { if(!lfrfid_raw_file_open_read(file, furi_string_get_cstr(filepath))) {
printf("Failed to open file\r\n"); printf("Failed to open file\r\n");
break; break;
} }
@ -308,10 +309,10 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) {
warn = true; warn = true;
} }
string_printf(info_string, "[%ld %ld]", pulse, duration); furi_string_printf(info_string, "[%ld %ld]", pulse, duration);
printf("%-16s", string_get_cstr(info_string)); printf("%-16s", furi_string_get_cstr(info_string));
string_printf(info_string, "[%ld %ld]", pulse, duration - pulse); furi_string_printf(info_string, "[%ld %ld]", pulse, duration - pulse);
printf("%-16s", string_get_cstr(info_string)); printf("%-16s", furi_string_get_cstr(info_string));
if(warn) { if(warn) {
printf(" <<----"); printf(" <<----");
@ -366,7 +367,7 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) {
printf("]\r\n"); printf("]\r\n");
protocol_dict_render_data(dict, info_string, total_protocol); protocol_dict_render_data(dict, info_string, total_protocol);
printf("%s\r\n", string_get_cstr(info_string)); printf("%s\r\n", furi_string_get_cstr(info_string));
free(data); free(data);
} else { } else {
@ -376,8 +377,8 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) {
protocol_dict_free(dict); protocol_dict_free(dict);
} while(false); } while(false);
string_clear(filepath); furi_string_free(filepath);
string_clear(info_string); furi_string_free(info_string);
lfrfid_raw_file_free(file); lfrfid_raw_file_free(file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
@ -388,23 +389,23 @@ static void lfrfid_cli_raw_read_callback(LFRFIDWorkerReadRawResult result, void*
furi_event_flag_set(event, 1 << result); furi_event_flag_set(event, 1 << result);
} }
static void lfrfid_cli_raw_read(Cli* cli, string_t args) { static void lfrfid_cli_raw_read(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
string_t filepath, type_string; FuriString *filepath, *type_string;
string_init(filepath); filepath = furi_string_alloc();
string_init(type_string); type_string = furi_string_alloc();
LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto; LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto;
do { do {
if(args_read_string_and_trim(args, type_string)) { if(args_read_string_and_trim(args, type_string)) {
if(string_cmp_str(type_string, "normal") == 0 || if(furi_string_cmp_str(type_string, "normal") == 0 ||
string_cmp_str(type_string, "ask") == 0) { furi_string_cmp_str(type_string, "ask") == 0) {
// ask // ask
type = LFRFIDWorkerReadTypeASKOnly; type = LFRFIDWorkerReadTypeASKOnly;
} else if( } else if(
string_cmp_str(type_string, "indala") == 0 || furi_string_cmp_str(type_string, "indala") == 0 ||
string_cmp_str(type_string, "psk") == 0) { furi_string_cmp_str(type_string, "psk") == 0) {
// psk // psk
type = LFRFIDWorkerReadTypePSKOnly; type = LFRFIDWorkerReadTypePSKOnly;
} else { } else {
@ -430,7 +431,7 @@ static void lfrfid_cli_raw_read(Cli* cli, string_t args) {
(1 << LFRFIDWorkerReadRawOverrun); (1 << LFRFIDWorkerReadRawOverrun);
lfrfid_worker_read_raw_start( lfrfid_worker_read_raw_start(
worker, string_get_cstr(filepath), type, lfrfid_cli_raw_read_callback, event); worker, furi_string_get_cstr(filepath), type, lfrfid_cli_raw_read_callback, event);
while(true) { while(true) {
uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100); uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100);
@ -465,8 +466,8 @@ static void lfrfid_cli_raw_read(Cli* cli, string_t args) {
} while(false); } while(false);
string_clear(filepath); furi_string_free(filepath);
string_clear(type_string); furi_string_free(type_string);
} }
static void lfrfid_cli_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) { static void lfrfid_cli_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) {
@ -475,11 +476,11 @@ static void lfrfid_cli_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result,
furi_event_flag_set(event, 1 << result); furi_event_flag_set(event, 1 << result);
} }
static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) { static void lfrfid_cli_raw_emulate(Cli* cli, FuriString* args) {
UNUSED(cli); UNUSED(cli);
string_t filepath; FuriString* filepath;
string_init(filepath); filepath = furi_string_alloc();
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
do { do {
@ -488,8 +489,8 @@ static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) {
break; break;
} }
if(!storage_file_exists(storage, string_get_cstr(filepath))) { if(!storage_file_exists(storage, furi_string_get_cstr(filepath))) {
printf("File not found: \"%s\"\r\n", string_get_cstr(filepath)); printf("File not found: \"%s\"\r\n", furi_string_get_cstr(filepath));
break; break;
} }
@ -505,7 +506,7 @@ static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) {
(1 << LFRFIDWorkerEmulateRawOverrun); (1 << LFRFIDWorkerEmulateRawOverrun);
lfrfid_worker_emulate_raw_start( lfrfid_worker_emulate_raw_start(
worker, string_get_cstr(filepath), lfrfid_cli_raw_emulate_callback, event); worker, furi_string_get_cstr(filepath), lfrfid_cli_raw_emulate_callback, event);
while(true) { while(true) {
uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100); uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100);
@ -541,35 +542,35 @@ static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) {
} while(false); } while(false);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
string_clear(filepath); furi_string_free(filepath);
} }
static void lfrfid_cli(Cli* cli, string_t args, void* context) { static void lfrfid_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(context); UNUSED(context);
string_t cmd; FuriString* cmd;
string_init(cmd); cmd = furi_string_alloc();
if(!args_read_string_and_trim(args, cmd)) { if(!args_read_string_and_trim(args, cmd)) {
string_clear(cmd); furi_string_free(cmd);
lfrfid_cli_print_usage(); lfrfid_cli_print_usage();
return; return;
} }
if(string_cmp_str(cmd, "read") == 0) { if(furi_string_cmp_str(cmd, "read") == 0) {
lfrfid_cli_read(cli, args); lfrfid_cli_read(cli, args);
} else if(string_cmp_str(cmd, "write") == 0) { } else if(furi_string_cmp_str(cmd, "write") == 0) {
lfrfid_cli_write(cli, args); lfrfid_cli_write(cli, args);
} else if(string_cmp_str(cmd, "emulate") == 0) { } else if(furi_string_cmp_str(cmd, "emulate") == 0) {
lfrfid_cli_emulate(cli, args); lfrfid_cli_emulate(cli, args);
} else if(string_cmp_str(cmd, "raw_read") == 0) { } else if(furi_string_cmp_str(cmd, "raw_read") == 0) {
lfrfid_cli_raw_read(cli, args); lfrfid_cli_raw_read(cli, args);
} else if(string_cmp_str(cmd, "raw_emulate") == 0) { } else if(furi_string_cmp_str(cmd, "raw_emulate") == 0) {
lfrfid_cli_raw_emulate(cli, args); lfrfid_cli_raw_emulate(cli, args);
} else if(string_cmp_str(cmd, "raw_analyze") == 0) { } else if(furi_string_cmp_str(cmd, "raw_analyze") == 0) {
lfrfid_cli_raw_analyze(cli, args); lfrfid_cli_raw_analyze(cli, args);
} else { } else {
lfrfid_cli_print_usage(); lfrfid_cli_print_usage();
} }
string_clear(cmd); furi_string_free(cmd);
} }

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "m-string.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
@ -86,9 +84,9 @@ struct LfRfid {
Widget* widget; Widget* widget;
char text_store[LFRFID_TEXT_STORE_SIZE + 1]; char text_store[LFRFID_TEXT_STORE_SIZE + 1];
string_t file_path; FuriString* file_path;
string_t file_name; FuriString* file_name;
string_t raw_file_name; FuriString* raw_file_name;
ProtocolDict* dict; ProtocolDict* dict;
ProtocolId protocol_id; ProtocolId protocol_id;
@ -128,9 +126,9 @@ bool lfrfid_load_key_from_file_select(LfRfid* app);
bool lfrfid_delete_key(LfRfid* app); bool lfrfid_delete_key(LfRfid* app);
bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog); bool lfrfid_load_key_data(LfRfid* app, FuriString* path, bool show_dialog);
bool lfrfid_save_key_data(LfRfid* app, string_t path); bool lfrfid_save_key_data(LfRfid* app, FuriString* path);
void lfrfid_make_app_folder(LfRfid* app); void lfrfid_make_app_folder(LfRfid* app);

View File

@ -4,31 +4,31 @@ void lfrfid_scene_delete_confirm_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
Widget* widget = app->widget; Widget* widget = app->widget;
string_t tmp_string; FuriString* tmp_string;
string_init(tmp_string); tmp_string = furi_string_alloc();
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app);
widget_add_button_element(widget, GuiButtonTypeRight, "Delete", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeRight, "Delete", lfrfid_widget_callback, app);
string_printf(tmp_string, "Delete %s?", string_get_cstr(app->file_name)); furi_string_printf(tmp_string, "Delete %s?", furi_string_get_cstr(app->file_name));
widget_add_string_element( widget_add_string_element(
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, string_get_cstr(tmp_string)); widget, 64, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp_string));
string_reset(tmp_string); furi_string_reset(tmp_string);
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
uint8_t* data = (uint8_t*)malloc(size); uint8_t* data = (uint8_t*)malloc(size);
protocol_dict_get_data(app->dict, app->protocol_id, data, size); protocol_dict_get_data(app->dict, app->protocol_id, data, size);
for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) { for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
if(i != 0) { if(i != 0) {
string_cat_printf(tmp_string, " "); furi_string_cat_printf(tmp_string, " ");
} }
string_cat_printf(tmp_string, "%02X", data[i]); furi_string_cat_printf(tmp_string, "%02X", data[i]);
} }
free(data); free(data);
widget_add_string_element( widget_add_string_element(
widget, 64, 19, AlignCenter, AlignTop, FontSecondary, string_get_cstr(tmp_string)); widget, 64, 19, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp_string));
widget_add_string_element( widget_add_string_element(
widget, widget,
64, 64,
@ -39,7 +39,7 @@ void lfrfid_scene_delete_confirm_on_enter(void* context) {
protocol_dict_get_name(app->dict, app->protocol_id)); protocol_dict_get_name(app->dict, app->protocol_id));
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
string_clear(tmp_string); furi_string_free(tmp_string);
} }
bool lfrfid_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { bool lfrfid_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {

View File

@ -8,8 +8,8 @@ void lfrfid_scene_emulate_on_enter(void* context) {
DOLPHIN_DEED(DolphinDeedRfidEmulate); DOLPHIN_DEED(DolphinDeedRfidEmulate);
popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop); popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop);
if(!string_empty_p(app->file_name)) { if(!furi_string_empty(app->file_name)) {
popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
} else { } else {
popup_set_text( popup_set_text(
popup, popup,

View File

@ -42,7 +42,7 @@ void lfrfid_scene_extra_actions_on_enter(void* context) {
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions)); submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
// clear key // clear key
string_reset(app->file_name); furi_string_reset(app->file_name);
app->protocol_id = PROTOCOL_NO; app->protocol_id = PROTOCOL_NO;
app->read_type = LFRFIDWorkerReadTypeAuto; app->read_type = LFRFIDWorkerReadTypeAuto;

View File

@ -4,8 +4,8 @@ void lfrfid_scene_raw_info_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
Widget* widget = app->widget; Widget* widget = app->widget;
// string_t tmp_string; // FuriString* tmp_string;
// string_init(tmp_string); // tmp_string = furi_string_alloc();
bool sd_exist = storage_sd_status(app->storage) == FSE_OK; bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
if(!sd_exist) { if(!sd_exist) {

View File

@ -4,9 +4,9 @@ void lfrfid_scene_raw_name_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
TextInput* text_input = app->text_input; TextInput* text_input = app->text_input;
const char* key_name = string_get_cstr(app->raw_file_name); const char* key_name = furi_string_get_cstr(app->raw_file_name);
bool key_name_is_empty = string_empty_p(app->file_name); bool key_name_is_empty = furi_string_empty(app->file_name);
if(key_name_is_empty) { if(key_name_is_empty) {
lfrfid_text_store_set(app, "RfidRecord"); lfrfid_text_store_set(app, "RfidRecord");
} else { } else {
@ -38,7 +38,7 @@ bool lfrfid_scene_raw_name_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == LfRfidEventNext) { if(event.event == LfRfidEventNext) {
consumed = true; consumed = true;
string_set_str(app->raw_file_name, app->text_store); furi_string_set(app->raw_file_name, app->text_store);
scene_manager_next_scene(scene_manager, LfRfidSceneRawInfo); scene_manager_next_scene(scene_manager, LfRfidSceneRawInfo);
} }
} }

View File

@ -3,7 +3,7 @@
#define RAW_READ_TIME 5000 #define RAW_READ_TIME 5000
typedef struct { typedef struct {
string_t string_file_name; FuriString* string_file_name;
FuriTimer* timer; FuriTimer* timer;
bool is_psk; bool is_psk;
bool error; bool error;
@ -31,7 +31,7 @@ void lfrfid_scene_raw_read_on_enter(void* context) {
LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState)); LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState));
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state); scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state);
string_init(state->string_file_name); state->string_file_name = furi_string_alloc();
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
@ -40,16 +40,16 @@ void lfrfid_scene_raw_read_on_enter(void* context) {
state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app); state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app);
furi_timer_start(state->timer, RAW_READ_TIME); furi_timer_start(state->timer, RAW_READ_TIME);
string_printf( furi_string_printf(
state->string_file_name, state->string_file_name,
"%s/%s%s", "%s/%s%s",
LFRFID_SD_FOLDER, LFRFID_SD_FOLDER,
string_get_cstr(app->raw_file_name), furi_string_get_cstr(app->raw_file_name),
LFRFID_APP_RAW_ASK_EXTENSION); LFRFID_APP_RAW_ASK_EXTENSION);
popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop); popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
lfrfid_worker_read_raw_start( lfrfid_worker_read_raw_start(
app->lfworker, app->lfworker,
string_get_cstr(state->string_file_name), furi_string_get_cstr(state->string_file_name),
LFRFIDWorkerReadTypeASKOnly, LFRFIDWorkerReadTypeASKOnly,
lfrfid_read_callback, lfrfid_read_callback,
app); app);
@ -88,15 +88,15 @@ bool lfrfid_scene_raw_read_on_event(void* context, SceneManagerEvent event) {
popup, "Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop); popup, "Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop);
notification_message(app->notifications, &sequence_blink_start_yellow); notification_message(app->notifications, &sequence_blink_start_yellow);
lfrfid_worker_stop(app->lfworker); lfrfid_worker_stop(app->lfworker);
string_printf( furi_string_printf(
state->string_file_name, state->string_file_name,
"%s/%s%s", "%s/%s%s",
LFRFID_SD_FOLDER, LFRFID_SD_FOLDER,
string_get_cstr(app->raw_file_name), furi_string_get_cstr(app->raw_file_name),
LFRFID_APP_RAW_PSK_EXTENSION); LFRFID_APP_RAW_PSK_EXTENSION);
lfrfid_worker_read_raw_start( lfrfid_worker_read_raw_start(
app->lfworker, app->lfworker,
string_get_cstr(state->string_file_name), furi_string_get_cstr(state->string_file_name),
LFRFIDWorkerReadTypePSKOnly, LFRFIDWorkerReadTypePSKOnly,
lfrfid_read_callback, lfrfid_read_callback,
app); app);
@ -121,6 +121,6 @@ void lfrfid_scene_raw_read_on_exit(void* context) {
lfrfid_worker_stop_thread(app->lfworker); lfrfid_worker_stop_thread(app->lfworker);
furi_timer_free(state->timer); furi_timer_free(state->timer);
string_clear(state->string_file_name); furi_string_free(state->string_file_name);
free(state); free(state);
} }

View File

@ -81,7 +81,7 @@ bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
app->protocol_id = app->protocol_id_next; app->protocol_id = app->protocol_id_next;
DOLPHIN_DEED(DolphinDeedRfidReadSuccess); DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
notification_message(app->notifications, &sequence_success); notification_message(app->notifications, &sequence_success);
string_reset(app->file_name); furi_string_reset(app->file_name);
scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess); scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess);
consumed = true; consumed = true;
} else if(event.event == LfRfidEventReadStartPSK) { } else if(event.event == LfRfidEventReadStartPSK) {

View File

@ -38,7 +38,7 @@ bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event)
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite); scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexSave) { } else if(event.event == SubmenuIndexSave) {
string_reset(app->file_name); furi_string_reset(app->file_name);
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName); scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexEmulate) { } else if(event.event == SubmenuIndexEmulate) {

View File

@ -4,51 +4,51 @@ void lfrfid_scene_read_success_on_enter(void* context) {
LfRfid* app = context; LfRfid* app = context;
Widget* widget = app->widget; Widget* widget = app->widget;
string_t tmp_string; FuriString* tmp_string;
string_init(tmp_string); tmp_string = furi_string_alloc();
widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app);
widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app);
string_printf( furi_string_printf(
tmp_string, tmp_string,
"%s[%s]", "%s[%s]",
protocol_dict_get_name(app->dict, app->protocol_id), protocol_dict_get_name(app->dict, app->protocol_id),
protocol_dict_get_manufacturer(app->dict, app->protocol_id)); protocol_dict_get_manufacturer(app->dict, app->protocol_id));
widget_add_string_element( widget_add_string_element(
widget, 0, 2, AlignLeft, AlignTop, FontPrimary, string_get_cstr(tmp_string)); widget, 0, 2, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(tmp_string));
string_reset(tmp_string); furi_string_reset(tmp_string);
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
uint8_t* data = (uint8_t*)malloc(size); uint8_t* data = (uint8_t*)malloc(size);
protocol_dict_get_data(app->dict, app->protocol_id, data, size); protocol_dict_get_data(app->dict, app->protocol_id, data, size);
for(uint8_t i = 0; i < size; i++) { for(uint8_t i = 0; i < size; i++) {
if(i >= 9) { if(i >= 9) {
string_cat_printf(tmp_string, ".."); furi_string_cat_printf(tmp_string, "..");
break; break;
} else { } else {
if(i != 0) { if(i != 0) {
string_cat_printf(tmp_string, " "); furi_string_cat_printf(tmp_string, " ");
} }
string_cat_printf(tmp_string, "%02X", data[i]); furi_string_cat_printf(tmp_string, "%02X", data[i]);
} }
} }
free(data); free(data);
string_t render_data; FuriString* render_data;
string_init(render_data); render_data = furi_string_alloc();
protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id); protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data)); furi_string_cat_printf(tmp_string, "\r\n%s", furi_string_get_cstr(render_data));
string_clear(render_data); furi_string_free(render_data);
widget_add_string_multiline_element( widget_add_string_multiline_element(
widget, 0, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string)); widget, 0, 16, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp_string));
notification_message_block(app->notifications, &sequence_set_green_255); notification_message_block(app->notifications, &sequence_set_green_255);
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
string_clear(tmp_string); furi_string_free(tmp_string);
} }
bool lfrfid_scene_read_success_on_event(void* context, SceneManagerEvent event) { bool lfrfid_scene_read_success_on_event(void* context, SceneManagerEvent event) {

View File

@ -34,13 +34,14 @@ bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) {
const char* arg = rpc_system_app_get_data(app->rpc_ctx); const char* arg = rpc_system_app_get_data(app->rpc_ctx);
bool result = false; bool result = false;
if(arg && (app->rpc_state == LfRfidRpcStateIdle)) { if(arg && (app->rpc_state == LfRfidRpcStateIdle)) {
string_set_str(app->file_path, arg); furi_string_set(app->file_path, arg);
if(lfrfid_load_key_data(app, app->file_path, false)) { if(lfrfid_load_key_data(app, app->file_path, false)) {
lfrfid_worker_start_thread(app->lfworker); lfrfid_worker_start_thread(app->lfworker);
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
app->rpc_state = LfRfidRpcStateEmulating; app->rpc_state = LfRfidRpcStateEmulating;
lfrfid_text_store_set(app, "emulating\n%s", string_get_cstr(app->file_name)); lfrfid_text_store_set(
app, "emulating\n%s", furi_string_get_cstr(app->file_name));
popup_set_text(popup, app->text_store, 89, 44, AlignCenter, AlignTop); popup_set_text(popup, app->text_store, 89, 44, AlignCenter, AlignTop);
notification_message(app->notifications, &sequence_blink_start_magenta); notification_message(app->notifications, &sequence_blink_start_magenta);

View File

@ -9,14 +9,11 @@ void lfrfid_scene_save_data_on_enter(void* context) {
bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData); bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData);
if(need_restore) { if(!need_restore) {
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
} else {
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size); protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
} }
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
byte_input_set_header_text(byte_input, "Enter the data in hex"); byte_input_set_header_text(byte_input, "Enter the data in hex");
byte_input_set_result_callback( byte_input_set_result_callback(
@ -41,6 +38,8 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
} }
} else if(event.type == SceneManagerEventTypeBack) { } else if(event.type == SceneManagerEventTypeBack) {
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0); scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
} }
return consumed; return consumed;

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