diff --git a/.github/workflows/amap_analyse.yml b/.github/workflows/amap_analyse.yml index 6be99c9d..a50c5436 100644 --- a/.github/workflows/amap_analyse.yml +++ b/.github/workflows/amap_analyse.yml @@ -62,6 +62,8 @@ jobs: - name: 'Download build artifacts' 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; chmod 600 ./deploy_key; rsync -avzP \ @@ -97,3 +99,4 @@ jobs: ${{ secrets.AMAP_MARIADB_PORT }} \ ${{ secrets.AMAP_MARIADB_DATABASE }} \ artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15b3966a..7d616295 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,14 +56,14 @@ jobs: - name: 'Bundle scripts' if: ${{ !github.event.pull_request.head.repo.fork }} 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' run: | set -e for TARGET in ${TARGETS}; do - FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ - updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} + FBT_TOOLCHAIN_PATH=/runner/_work ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ + copro_dist updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} done - name: 'Move upload files' @@ -74,17 +74,6 @@ jobs: mv dist/${TARGET}-*/* artifacts/ 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" run: | git diff --exit-code @@ -97,8 +86,7 @@ jobs: - name: 'Bundle core2 firmware' if: ${{ !github.event.pull_request.head.repo.fork }} run: | - FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist - tar czpf "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" -C assets core2_firmware + cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" - name: 'Copy .map file' run: | @@ -107,6 +95,8 @@ jobs: - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} 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; chmod 600 ./deploy_key; rsync -avzP --delete --mkpath \ @@ -137,7 +127,7 @@ jobs: **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) - [📥 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 compact: @@ -174,6 +164,6 @@ jobs: run: | set -e 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 done diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml index e4178c3c..eba4affc 100644 --- a/.github/workflows/check_submodules.yml +++ b/.github/workflows/check_submodules.yml @@ -27,6 +27,7 @@ jobs: - name: 'Check protobuf branch' run: | + git submodule update --init SUB_PATH="assets/protobuf"; SUB_BRANCH="dev"; SUB_COMMITS_MIN=40; diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index becafcab..23dc6c69 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -30,7 +30,7 @@ jobs: - name: 'Check code formatting' 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 if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index d5ff834e..c2f09211 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -26,4 +26,4 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} - 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 diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index 7bd71de4..e3d5fc13 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -57,14 +57,15 @@ jobs: - name: 'Generate compile_comands.json' 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' 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 analyze \ @.pvsoptions \ + --disableLicenseExpirationCheck \ -j$(grep -c processor /proc/cpuinfo) \ -f build/f7-firmware-DC/compile_commands.json \ -o PVS-Studio.log @@ -75,6 +76,8 @@ jobs: - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} 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; chmod 600 ./deploy_key; rsync -avrzP --mkpath \ diff --git a/SConstruct b/SConstruct index 5ad2ac3c..74fa5667 100644 --- a/SConstruct +++ b/SConstruct @@ -7,7 +7,6 @@ # construction of certain targets behind command-line options. import os -import subprocess DefaultEnvironment(tools=[]) @@ -15,17 +14,22 @@ EnsurePythonVersion(3, 8) # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) - # This environment is created only for loading options & validating file/dir existence fbt_variables = SConscript("site_scons/commandline.scons") -cmd_environment = Environment(tools=[], variables=fbt_variables) -Help(fbt_variables.GenerateHelpText(cmd_environment)) +cmd_environment = Environment( + toolpath=["#/scripts/fbt_tools"], + tools=[ + ("fbt_help", {"vars": fbt_variables}), + ], + variables=fbt_variables, +) # Building basic environment - tools, utility methods, cross-compilation # settings, gcc flags for Cortex-M4, basic builders and more coreenv = SConscript( "site_scons/environ.scons", exports={"VAR_ENV": cmd_environment}, + toolpath=["#/scripts/fbt_tools"], ) 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 distenv = coreenv.Clone( - tools=["fbt_dist", "openocd", "blackmagic", "jflash"], - OPENOCD_GDB_PIPE=[ - "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" + tools=[ + "fbt_dist", + "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, ) @@ -166,7 +142,7 @@ basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) distenv.Default(basic_dist) dist_dir = distenv.GetProjetDirName() -plugin_dist = [ +fap_dist = [ distenv.Install( f"#/dist/{dist_dir}/apps/debug_elf", firmware_env["FW_EXTAPPS"]["debug"].values(), @@ -176,9 +152,9 @@ plugin_dist = [ for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values() ), ] -Depends(plugin_dist, firmware_env["FW_EXTAPPS"]["validators"].values()) -Alias("plugin_dist", plugin_dist) -# distenv.Default(plugin_dist) +Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values()) +Alias("fap_dist", fap_dist) +# distenv.Default(fap_dist) plugin_resources_dist = list( 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 copro_dist = distenv.CoproBuilder( - distenv.Dir("assets/core2_firmware"), + "#/build/core2_firmware.tgz", [], ) +distenv.AlwaysBuild(copro_dist) distenv.Alias("copro_dist", copro_dist) firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) diff --git a/applications/debug/bt_debug_app/views/bt_test.c b/applications/debug/bt_debug_app/views/bt_test.c index 70f57c12..9588b667 100644 --- a/applications/debug/bt_debug_app/views/bt_test.c +++ b/applications/debug/bt_debug_app/views/bt_test.c @@ -3,14 +3,13 @@ #include #include #include -#include #include #include struct BtTestParam { const char* label; uint8_t current_value_index; - string_t current_value_text; + FuriString* current_value_text; uint8_t values_count; BtTestParamChangeCallback change_callback; 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, 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)) { 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) { with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { uint8_t params_on_screen = 3; if(model->position > 0) { model->position--; @@ -168,13 +170,15 @@ void bt_test_process_up(BtTest* bt_test) { model->window_position = model->position - (params_on_screen - 1); } } - return true; - }); + }, + true); } void bt_test_process_down(BtTest* bt_test) { with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { uint8_t params_on_screen = 3; if(model->position < (BtTestParamArray_size(model->params) - 1)) { model->position++; @@ -187,8 +191,8 @@ void bt_test_process_down(BtTest* bt_test) { model->position = 0; model->window_position = 0; } - return true; - }); + }, + true); } 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) { BtTestParam* param; with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { param = bt_test_get_selected_param(model); if(param->current_value_index > 0) { param->current_value_index--; @@ -225,8 +231,8 @@ void bt_test_process_left(BtTest* bt_test) { model->packets_num_tx = 0; } } - return true; - }); + }, + true); if(param->change_callback) { param->change_callback(param); } @@ -235,7 +241,9 @@ void bt_test_process_left(BtTest* bt_test) { void bt_test_process_right(BtTest* bt_test) { BtTestParam* param; with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { param = bt_test_get_selected_param(model); if(param->current_value_index < (param->values_count - 1)) { param->current_value_index++; @@ -247,8 +255,8 @@ void bt_test_process_right(BtTest* bt_test) { model->packets_num_tx = 0; } } - return true; - }); + }, + true); if(param->change_callback) { param->change_callback(param); } @@ -257,7 +265,9 @@ void bt_test_process_right(BtTest* bt_test) { void bt_test_process_ok(BtTest* bt_test) { BtTestState state; with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { if(model->state == BtTestStateStarted) { model->state = BtTestStateStopped; model->message = BT_TEST_START_MESSAGE; @@ -269,8 +279,8 @@ void bt_test_process_ok(BtTest* bt_test) { model->message = BT_TEST_STOP_MESSAGE; } state = model->state; - return true; - }); + }, + true); if(bt_test->change_state_callback) { 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) { with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { model->state = BtTestStateStopped; model->rssi = 0.0f; model->packets_num_rx = 0; model->packets_num_tx = 0; - return false; - }); + }, + false); if(bt_test->back_callback) { 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); with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { model->state = BtTestStateStopped; model->message = "Ok - Start"; BtTestParamArray_init(model->params); @@ -308,8 +322,8 @@ BtTest* bt_test_alloc() { model->rssi = 0.0f; model->packets_num_tx = 0; model->packets_num_rx = 0; - return true; - }); + }, + true); return bt_test; } @@ -318,15 +332,17 @@ void bt_test_free(BtTest* bt_test) { furi_assert(bt_test); with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { BtTestParamArray_it_t it; for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(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); - return false; - }); + }, + false); view_free(bt_test->view); free(bt_test); } @@ -347,16 +363,18 @@ BtTestParam* bt_test_param_add( furi_assert(bt_test); with_view_model( - bt_test->view, (BtTestModel * model) { + bt_test->view, + BtTestModel * model, + { param = BtTestParamArray_push_new(model->params); param->label = label; param->values_count = values_count; param->change_callback = change_callback; param->context = context; param->current_value_index = 0; - string_init(param->current_value_text); - return true; - }); + param->current_value_text = furi_string_alloc(); + }, + true); return param; } @@ -364,28 +382,19 @@ BtTestParam* bt_test_param_add( void bt_test_set_rssi(BtTest* bt_test, float rssi) { furi_assert(bt_test); with_view_model( - bt_test->view, (BtTestModel * model) { - model->rssi = rssi; - return true; - }); + bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true); } void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) { furi_assert(bt_test); with_view_model( - bt_test->view, (BtTestModel * model) { - model->packets_num_tx = packets_num; - return true; - }); + bt_test->view, BtTestModel * model, { model->packets_num_tx = packets_num; }, true); } void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) { furi_assert(bt_test); with_view_model( - bt_test->view, (BtTestModel * model) { - model->packets_num_rx = packets_num; - return true; - }); + bt_test->view, BtTestModel * model, { model->packets_num_rx = packets_num; }, true); } 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) { - 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) { diff --git a/applications/debug/display_test/display_test.c b/applications/debug/display_test/display_test.c index 947e4dc8..e7f366cb 100644 --- a/applications/debug/display_test/display_test.c +++ b/applications/debug/display_test/display_test.c @@ -113,11 +113,11 @@ static void display_config_set_regulation_ratio(VariableItem* item) { static void display_config_set_contrast(VariableItem* item) { DisplayTest* instance = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - string_t temp; - string_init(temp); - string_cat_printf(temp, "%d", index); - variable_item_set_current_value_text(item, string_get_cstr(temp)); - string_clear(temp); + FuriString* temp; + temp = furi_string_alloc(); + furi_string_cat_printf(temp, "%d", index); + variable_item_set_current_value_text(item, furi_string_get_cstr(temp)); + furi_string_free(temp); instance->config_contrast = index; display_test_reload_config(instance); } diff --git a/applications/debug/display_test/view_display_test.c b/applications/debug/display_test/view_display_test.c index f00fe009..b47c74c6 100644 --- a/applications/debug/display_test/view_display_test.c +++ b/applications/debug/display_test/view_display_test.c @@ -110,7 +110,9 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) { bool consumed = false; if(event->type == InputTypeShort || event->type == InputTypeRepeat) { with_view_model( - instance->view, (ViewDisplayTestModel * model) { + instance->view, + ViewDisplayTestModel * model, + { if(event->key == InputKeyLeft && model->test > 0) { model->test--; consumed = true; @@ -129,8 +131,8 @@ static bool view_display_test_input_callback(InputEvent* event, void* context) { model->flip_flop = !model->flip_flop; consumed = true; } - return consumed; - }); + }, + consumed); } return consumed; @@ -149,10 +151,7 @@ static void view_display_test_exit(void* context) { static void view_display_test_timer_callback(void* context) { ViewDisplayTest* instance = context; with_view_model( - instance->view, (ViewDisplayTestModel * model) { - model->counter++; - return true; - }); + instance->view, ViewDisplayTestModel * model, { model->counter++; }, true); } ViewDisplayTest* view_display_test_alloc() { diff --git a/applications/debug/file_browser_test/file_browser_app.c b/applications/debug/file_browser_test/file_browser_app.c index c7f461d4..5c7b93bc 100644 --- a/applications/debug/file_browser_test/file_browser_app.c +++ b/applications/debug/file_browser_test/file_browser_app.c @@ -1,7 +1,6 @@ #include "assets_icons.h" #include "file_browser_app_i.h" #include "gui/modules/file_browser.h" -#include "m-string.h" #include #include #include @@ -47,7 +46,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) { app->widget = widget_alloc(); - string_init(app->file_path); + app->file_path = furi_string_alloc(); app->file_browser = file_browser_alloc(app->file_path); 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_DIALOGS); - string_clear(app->file_path); + furi_string_free(app->file_path); free(app); } diff --git a/applications/debug/file_browser_test/file_browser_app_i.h b/applications/debug/file_browser_test/file_browser_app_i.h index 6e8412c9..20f4c3a0 100644 --- a/applications/debug/file_browser_test/file_browser_app_i.h +++ b/applications/debug/file_browser_test/file_browser_app_i.h @@ -22,7 +22,7 @@ struct FileBrowserApp { Widget* widget; FileBrowser* file_browser; - string_t file_path; + FuriString* file_path; }; typedef enum { diff --git a/applications/debug/file_browser_test/scenes/file_browser_scene_browser.c b/applications/debug/file_browser_test/scenes/file_browser_scene_browser.c index d9bd1ac5..0bf70e9c 100644 --- a/applications/debug/file_browser_test/scenes/file_browser_scene_browser.c +++ b/applications/debug/file_browser_test/scenes/file_browser_scene_browser.c @@ -1,8 +1,5 @@ #include "../file_browser_app_i.h" -#include -#include -#include "furi_hal.h" -#include "m-string.h" +#include #define DEFAULT_PATH "/" #define EXTENSION "*" diff --git a/applications/debug/file_browser_test/scenes/file_browser_scene_result.c b/applications/debug/file_browser_test/scenes/file_browser_scene_result.c index 53576cef..4c68d80f 100644 --- a/applications/debug/file_browser_test/scenes/file_browser_scene_result.c +++ b/applications/debug/file_browser_test/scenes/file_browser_scene_result.c @@ -1,6 +1,5 @@ #include "../file_browser_app_i.h" -#include "furi_hal.h" -#include "m-string.h" +#include void file_browser_scene_result_ok_callback(InputType type, void* context) { furi_assert(context); @@ -24,7 +23,13 @@ void file_browser_scene_result_on_enter(void* context) { FileBrowserApp* app = context; 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); } diff --git a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c index b3381f0a..9eb26944 100644 --- a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c +++ b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c @@ -19,7 +19,7 @@ bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) { bool consumed = false; 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); consumed = true; } else if(event.type == SceneManagerEventTypeTick) { diff --git a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c index 38fe3603..fd221c4e 100644 --- a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c +++ b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c @@ -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) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { if(model->pos > 0) model->pos--; - return true; - }); + }, + true); } static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { if(model->pos < 1) model->pos++; - return true; - }); + }, + true); } static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { if(model->pos == 0) { if(model->fine) { model->ARR -= 1; @@ -84,13 +90,15 @@ static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) { } model->dirty = true; - return true; - }); + }, + true); } static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { if(model->pos == 0) { if(model->fine) { model->ARR += 1; @@ -106,16 +114,13 @@ static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) { } model->dirty = true; - return true; - }); + }, + true); } static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { - model->fine = !model->fine; - return true; - }); + tune_view->view, LfRfidTuneViewModel * model, { model->fine = !model->fine; }, true); } 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)); with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { model->dirty = true; model->fine = false; model->ARR = 511; model->CCR = 255; model->pos = 0; - return true; - }); + }, + true); 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); @@ -184,24 +191,28 @@ View* lfrfid_debug_view_tune_get_view(LfRfidTuneView* tune_view) { void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) { with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { model->dirty = true; model->fine = false; model->ARR = 511; model->CCR = 255; model->pos = 0; - return true; - }); + }, + true); } bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) { bool result = false; with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { + tune_view->view, + LfRfidTuneViewModel * model, + { result = model->dirty; model->dirty = false; - return false; - }); + }, + false); 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 result = false; with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { - result = model->ARR; - return false; - }); + tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false); 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 result = false; with_view_model( - tune_view->view, (LfRfidTuneViewModel * model) { - result = model->CCR; - return false; - }); + tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false); return result; } diff --git a/applications/debug/uart_echo/uart_echo.c b/applications/debug/uart_echo/uart_echo.c index 7a0f5c39..701e5325 100644 --- a/applications/debug/uart_echo/uart_echo.c +++ b/applications/debug/uart_echo/uart_echo.c @@ -1,10 +1,8 @@ #include -#include #include #include #include #include -#include #include #include #include @@ -21,11 +19,11 @@ typedef struct { ViewDispatcher* view_dispatcher; View* view; FuriThread* worker_thread; - StreamBufferHandle_t rx_stream; + FuriStreamBuffer* rx_stream; } UartEchoApp; typedef struct { - string_t text; + FuriString* text; } ListElement; struct UartDumpModel { @@ -64,10 +62,11 @@ static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { canvas, 0, (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) { - 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, @@ -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) { furi_assert(context); - BaseType_t xHigherPriorityTaskWoken = pdFALSE; UartEchoApp* app = context; 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); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } @@ -113,7 +110,7 @@ static void uart_echo_push_to_list(UartDumpModel* model, const char data) { model->escape = true; } else if((data >= ' ' && data <= '~') || (data == '\n' || data == '\r')) { 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; } else if((data == '\n' || data == '\r')) { // 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]; } - string_reset(first->text); + furi_string_reset(first->text); model->list[model->line] = first; } } 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; @@ -158,25 +155,24 @@ static int32_t uart_echo_worker(void* context) { size_t length = 0; do { 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) { furi_hal_uart_tx(FuriHalUartIdUSART1, data, length); with_view_model( - app->view, (UartDumpModel * model) { + app->view, + UartDumpModel * model, + { for(size_t i = 0; i < length; i++) { uart_echo_push_to_list(model, data[i]); } - return false; - }); + }, + false); } } while(length > 0); notification_message(app->notification, &sequence_notification); with_view_model( - app->view, (UartDumpModel * model) { - UNUSED(model); - return true; - }); + app->view, UartDumpModel * model, { UNUSED(model); }, true); } } @@ -186,7 +182,7 @@ static int32_t uart_echo_worker(void* context) { static UartEchoApp* uart_echo_app_alloc() { UartEchoApp* app = malloc(sizeof(UartEchoApp)); - app->rx_stream = xStreamBufferCreate(2048, 1); + app->rx_stream = furi_stream_buffer_alloc(2048, 1); // 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_allocate_model(app->view, ViewModelTypeLocking, sizeof(UartDumpModel)); with_view_model( - app->view, (UartDumpModel * model) { + app->view, + UartDumpModel * model, + { for(size_t i = 0; i < LINES_ON_SCREEN; i++) { model->line = 0; model->escape = false; 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_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); with_view_model( - app->view, (UartDumpModel * model) { + app->view, + UartDumpModel * model, + { 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]); } - return true; - }); + }, + true); view_free(app->view); view_dispatcher_free(app->view_dispatcher); @@ -260,7 +260,7 @@ static void uart_echo_app_free(UartEchoApp* app) { furi_record_close(RECORD_NOTIFICATION); app->gui = NULL; - vStreamBufferDelete(app->rx_stream); + furi_stream_buffer_free(app->rx_stream); // Free rest free(app); diff --git a/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c b/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c index b22b333a..920a22a4 100644 --- a/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c +++ b/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c @@ -58,7 +58,7 @@ static const char* test_data_win = "Filetype: Flipper Format test\r\n" #define ARRAY_W_BSIZE(x) (x), (sizeof(x)) MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) { - string_t tmpstr; + FuriString* tmpstr; uint32_t version; uint32_t uint32_data[COUNT_OF(test_uint_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))); // read test - string_init(tmpstr); + tmpstr = furi_string_alloc(); 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_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_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)); - string_clear(tmpstr); + furi_string_free(tmpstr); // update data 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)]; 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_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_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_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)); - string_clear(tmpstr); + furi_string_free(tmpstr); // update data 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)]; 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_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_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_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)); - string_clear(tmpstr); + furi_string_free(tmpstr); // delete key test mu_check(flipper_format_rewind(flipper_format)); diff --git a/applications/debug/unit_tests/flipper_format/flipper_format_test.c b/applications/debug/unit_tests/flipper_format/flipper_format_test.c index 86e2df21..012e905b 100644 --- a/applications/debug/unit_tests/flipper_format/flipper_format_test.c +++ b/applications/debug/unit_tests/flipper_format/flipper_format_test.c @@ -57,6 +57,23 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n" "Hex data: DE AD BE"; #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 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; // data created by flipper itself 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) { Storage* storage = furi_record_open(RECORD_STORAGE); @@ -102,8 +121,8 @@ static bool test_read(const char* file_name) { bool result = false; FlipperFormat* file = flipper_format_file_alloc(storage); - string_t string_value; - string_init(string_value); + FuriString* string_value; + string_value = furi_string_alloc(); uint32_t uint32_value; 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_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(!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(uint32_value != COUNT_OF(test_int_data)) break; @@ -150,7 +169,7 @@ static bool test_read(const char* file_name) { } while(false); free(scratchpad); - string_clear(string_value); + furi_string_free(string_value); flipper_format_free(file); @@ -164,8 +183,8 @@ static bool test_read_updated(const char* file_name) { bool result = false; FlipperFormat* file = flipper_format_file_alloc(storage); - string_t string_value; - string_init(string_value); + FuriString* string_value; + string_value = furi_string_alloc(); uint32_t uint32_value; 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_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(!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(uint32_value != COUNT_OF(test_int_updated_data)) break; @@ -228,7 +247,7 @@ static bool test_read_updated(const char* file_name) { } while(false); free(scratchpad); - string_clear(string_value); + furi_string_free(string_value); flipper_format_free(file); @@ -401,14 +420,14 @@ static bool test_read_multikey(const char* file_name) { bool result = false; FlipperFormat* file = flipper_format_file_alloc(storage); - string_t string_value; - string_init(string_value); + FuriString* string_value; + string_value = furi_string_alloc(); uint32_t uint32_value; do { if(!flipper_format_file_open_existing(file, file_name)) 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; bool error = false; @@ -429,7 +448,7 @@ static bool test_read_multikey(const char* file_name) { result = true; } while(false); - string_clear(string_value); + furi_string_free(string_value); flipper_format_free(file); 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_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) { tests_setup(); 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_result_test); MU_RUN_TEST(flipper_format_multikey_test); + MU_RUN_TEST(flipper_format_oddities_test); tests_teardown(); } diff --git a/applications/debug/unit_tests/furi/furi_string_test.c b/applications/debug/unit_tests/furi/furi_string_test.c new file mode 100644 index 00000000..3ea95b92 --- /dev/null +++ b/applications/debug/unit_tests/furi/furi_string_test.c @@ -0,0 +1,469 @@ +#include +#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; +} \ No newline at end of file diff --git a/applications/debug/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/infrared/infrared_test.c index 32266c48..8879c8fc 100644 --- a/applications/debug/unit_tests/infrared/infrared_test.c +++ b/applications/debug/unit_tests/infrared/infrared_test.c @@ -11,7 +11,7 @@ typedef struct { InfraredDecoderHandler* decoder_handler; InfraredEncoderHandler* encoder_handler; - string_t file_path; + FuriString* file_path; FlipperFormat* ff; } InfraredTest; @@ -23,7 +23,7 @@ static void infrared_test_alloc() { test->decoder_handler = infrared_alloc_decoder(); test->encoder_handler = infrared_alloc_encoder(); test->ff = flipper_format_buffered_file_alloc(storage); - string_init(test->file_path); + test->file_path = furi_string_alloc(); } static void infrared_test_free() { @@ -31,18 +31,18 @@ static void infrared_test_free() { infrared_free_decoder(test->decoder_handler); infrared_free_encoder(test->encoder_handler); flipper_format_free(test->ff); - string_clear(test->file_path); + furi_string_free(test->file_path); furi_record_close(RECORD_STORAGE); free(test); test = NULL; } static bool infrared_test_prepare_file(const char* protocol_name) { - string_t file_type; - string_init(file_type); + FuriString* file_type; + file_type = furi_string_alloc(); bool success = false; - string_printf( + furi_string_printf( test->file_path, "%s%s%s%s", IR_TEST_FILES_DIR, @@ -52,14 +52,15 @@ static bool infrared_test_prepare_file(const char* protocol_name) { do { 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; 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; } while(false); - string_clear(file_type); + furi_string_free(file_type); return success; } @@ -68,18 +69,18 @@ static bool infrared_test_load_raw_signal( const char* signal_name, uint32_t** timings, uint32_t* timings_count) { - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); bool success = false; do { bool is_name_found = false; 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(!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(!*timings_count) break; @@ -91,18 +92,18 @@ static bool infrared_test_load_raw_signal( success = true; } while(false); - string_clear(buf); + furi_string_free(buf); return success; } static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* message) { - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); bool success = false; do { 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(!flipper_format_read_hex(ff, "address", (uint8_t*)&message->address, sizeof(uint32_t))) break; @@ -112,7 +113,7 @@ static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* messa success = true; } while(false); - string_clear(buf); + furi_string_free(buf); return success; } @@ -121,18 +122,19 @@ static bool infrared_test_load_messages( const char* signal_name, InfraredMessage** messages, uint32_t* messages_count) { - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); bool success = false; do { bool is_name_found = false; 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(!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; if(!flipper_format_read_uint32(ff, "count", messages_count, 1)) break; if(!*messages_count) break; @@ -151,7 +153,7 @@ static bool infrared_test_load_messages( success = true; } while(false); - string_clear(buf); + furi_string_free(buf); return success; } @@ -213,26 +215,26 @@ static void infrared_test_run_encoder(InfraredProtocol protocol, uint32_t test_i InfraredMessage* input_messages; uint32_t input_messages_count; - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); const char* protocol_name = infrared_get_protocol_name(protocol); 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( 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"); - string_printf(buf, "encoder_expected%d", test_index); + furi_string_printf(buf, "encoder_expected%ld", test_index); mu_assert( 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"); flipper_format_buffered_file_close(test->ff); - string_clear(buf); + furi_string_free(buf); uint32_t j = 0; 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; bool level = false; - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); timings = malloc(sizeof(uint32_t) * timings_count); const char* protocol_name = infrared_get_protocol_name(protocol); 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( 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"); 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) { 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; uint32_t messages_count; - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); mu_assert( infrared_test_prepare_file(infrared_get_protocol_name(protocol)), "Failed to prepare test file"); - string_printf(buf, "decoder_input%d", test_index); + furi_string_printf(buf, "decoder_input%ld", test_index); 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"); - string_printf(buf, "decoder_expected%d", test_index); + furi_string_printf(buf, "decoder_expected%ld", test_index); 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"); flipper_format_buffered_file_close(test->ff); - string_clear(buf); + furi_string_free(buf); InfraredMessage message_decoded_check_local; bool level = 0; diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index 580943f2..f149508b 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -53,14 +53,15 @@ static bool nfc_test_read_signal_from_file(const char* file_name) { bool success = false; FlipperFormat* file = flipper_format_file_alloc(nfc_test->storage); - string_t file_type; - string_init(file_type); + FuriString* file_type; + file_type = furi_string_alloc(); uint32_t file_version = 0; do { if(!flipper_format_file_open_existing(file, file_name)) 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; 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; @@ -76,7 +77,7 @@ static bool nfc_test_read_signal_from_file(const char* file_name) { success = true; } while(false); - string_clear(file_type); + furi_string_free(file_type); flipper_format_free(file); return success; @@ -111,7 +112,7 @@ static bool nfc_test_digital_signal_test_encode( // Check timings if(time > encode_max_time) { 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; } @@ -131,7 +132,7 @@ static bool nfc_test_digital_signal_test_encode( ref_timings_sum += ref[i]; if(timings_diff > timing_tolerance) { 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; break; } @@ -142,16 +143,16 @@ static bool nfc_test_digital_signal_test_encode( if(sum_diff > timings_sum_tolerance) { FURI_LOG_E( TAG, - "Too big difference in timings sum. Ref: %d, DUT: %d", + "Too big difference in timings sum. Ref: %ld, DUT: %ld", ref_timings_sum, dut_timings_sum); 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( 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, timings_sum_tolerance); success = true; @@ -174,8 +175,8 @@ MU_TEST(nfc_digital_signal_test) { MU_TEST(mf_classic_dict_test) { MfClassicDict* instance = NULL; uint64_t key = 0; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest); 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 == 0 assert failed\r\n"); - string_set(temp_str, "2196FAD8115B"); + furi_string_set(temp_str, "2196FAD8115B"); mu_assert( mf_classic_dict_add_key_str(instance, temp_str), "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 == true assert failed\r\n"); 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"); 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_free(instance); - string_clear(temp_str); + furi_string_free(temp_str); } MU_TEST_SUITE(nfc) { diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index 6ee2aed6..5b52df2f 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -10,7 +10,6 @@ #include #include "../minunit.h" #include -#include #include #include #include @@ -34,7 +33,7 @@ static uint32_t command_id = 0; typedef struct { RpcSession* session; - StreamBufferHandle_t output_stream; + FuriStreamBuffer* output_stream; SemaphoreHandle_t close_session_semaphore; SemaphoreHandle_t terminate_semaphore; TickType_t timeout; @@ -90,7 +89,7 @@ static void test_rpc_setup(void) { } 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[0].close_session_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); - 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[1].close_session_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); furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY)); 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].terminate_semaphore); ++command_id; @@ -141,7 +140,7 @@ static void test_rpc_teardown_second_session(void) { xSemaphoreTake(rpc_session[1].terminate_semaphore, 0); rpc_session_close(rpc_session[1].session); 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].terminate_semaphore); ++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) { RpcSessionContext* callbacks_context = ctx; - size_t bytes_sent = - xStreamBufferSend(callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever); + size_t bytes_sent = furi_stream_buffer_send( + callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever); (void)bytes_sent; 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(); int32_t time_left = session_context->timeout - now; 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); } diff --git a/applications/debug/unit_tests/storage/dirwalk_test.c b/applications/debug/unit_tests/storage/dirwalk_test.c index db3d91a9..97aaa358 100644 --- a/applications/debug/unit_tests/storage/dirwalk_test.c +++ b/applications/debug/unit_tests/storage/dirwalk_test.c @@ -75,7 +75,7 @@ typedef struct { bool visited; } 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* storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) { @@ -83,15 +83,15 @@ static StorageTestPathDict_t* StorageTestPathDict_init(*data); for(size_t i = 0; i < paths_count; i++) { - string_t key; - string_init_set(key, paths[i].path); + FuriString* key; + key = furi_string_alloc_set(paths[i].path); StorageTestPath value = { .is_dir = paths[i].is_dir, .visited = false, }; StorageTestPathDict_set_at(*data, key, value); - string_clear(key); + furi_string_free(key); } return data; @@ -102,7 +102,7 @@ static void storage_test_paths_free(StorageTestPathDict_t* 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; 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) { - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); storage_common_mkdir(storage, base); for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) { - string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]); - storage_common_mkdir(storage, string_get_cstr(path)); + furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]); + storage_common_mkdir(storage, furi_string_get_cstr(path)); } for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) { - string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]); - write_file_13DA(storage, string_get_cstr(path)); + furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]); + write_file_13DA(storage, furi_string_get_cstr(path)); } - string_clear(path); + furi_string_free(path); } MU_TEST_1(test_dirwalk_full, Storage* storage) { - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); FileInfo fileinfo; 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"))); 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))); } dir_walk_free(dir_walk); - string_clear(path); + furi_string_free(path); 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) { - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); FileInfo fileinfo; 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"))); 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))); } dir_walk_free(dir_walk); - string_clear(path); + furi_string_free(path); 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) { - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); FileInfo fileinfo; 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"))); 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))); } dir_walk_free(dir_walk); - string_clear(path); + furi_string_free(path); mu_check(storage_test_paths_check(paths) == false); diff --git a/applications/debug/unit_tests/storage/storage_test.c b/applications/debug/unit_tests/storage/storage_test.c index 099be0d5..7c1c669f 100644 --- a/applications/debug/unit_tests/storage/storage_test.c +++ b/applications/debug/unit_tests/storage/storage_test.c @@ -211,22 +211,22 @@ static bool check_file_13DA(Storage* storage, const char* path) { } static void storage_dir_create(Storage* storage, const char* base) { - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); storage_common_mkdir(storage, base); for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { - string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); - storage_common_mkdir(storage, string_get_cstr(path)); + furi_string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); + storage_common_mkdir(storage, furi_string_get_cstr(path)); } for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { - string_printf(path, "%s/%s", base, storage_copy_test_files[i]); - write_file_13DA(storage, string_get_cstr(path)); + furi_string_printf(path, "%s/%s", base, storage_copy_test_files[i]); + 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) { @@ -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) { bool result = false; - string_t path; - string_init(path); + FuriString* path; + path = furi_string_alloc(); result = (storage_common_stat(storage, base, NULL) == FSE_OK); if(result) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) { - string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); - result = (storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK); + furi_string_printf(path, "%s/%s", base, storage_copy_test_paths[i]); + result = (storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK); if(!result) { break; } @@ -252,15 +252,15 @@ static bool storage_dir_rename_check(Storage* storage, const char* base) { if(result) { for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) { - string_printf(path, "%s/%s", base, storage_copy_test_files[i]); - result = check_file_13DA(storage, string_get_cstr(path)); + furi_string_printf(path, "%s/%s", base, storage_copy_test_files[i]); + result = check_file_13DA(storage, furi_string_get_cstr(path)); if(!result) { break; } } } - string_clear(path); + furi_string_free(path); return result; } diff --git a/applications/debug/unit_tests/stream/stream_test.c b/applications/debug/unit_tests/stream/stream_test.c index b5a2d398..c04e119c 100644 --- a/applications/debug/unit_tests/stream/stream_test.c +++ b/applications/debug/unit_tests/stream/stream_test.c @@ -18,8 +18,8 @@ static const char* stream_test_right_data = MU_TEST_1(stream_composite_subtest, Stream* stream) { const size_t data_size = 128; uint8_t data[data_size]; - string_t string_lee; - string_init_set(string_lee, "lee"); + FuriString* string_lee; + string_lee = furi_string_alloc_set("lee"); // 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_check(stream_eof(stream)); - string_clear(string_lee); + furi_string_free(string_lee); } MU_TEST(stream_composite_test) { @@ -416,10 +416,10 @@ MU_TEST(stream_buffered_write_after_read_test) { } MU_TEST(stream_buffered_large_file_test) { - string_t input_data; - string_t output_data; - string_init(input_data); - string_init(output_data); + FuriString* input_data; + FuriString* output_data; + input_data = furi_string_alloc(); + output_data = furi_string_alloc(); 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; 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 @@ -437,8 +437,8 @@ MU_TEST(stream_buffered_large_file_test) { mu_check(buffered_file_stream_open( stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)); 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(string_size(input_data), stream_size(stream)); + mu_assert_int_eq(furi_string_size(input_data), stream_write_string(stream, input_data)); + mu_assert_int_eq(furi_string_size(input_data), stream_size(stream)); const size_t substr_start = 8; const size_t substr_len = 11; @@ -475,23 +475,23 @@ MU_TEST(stream_buffered_large_file_test) { // read the whole file mu_check(stream_rewind(stream)); - string_t tmp; - string_init(tmp); + FuriString* tmp; + tmp = furi_string_alloc(); 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 - mu_assert_int_eq(string_size(input_data), string_size(output_data)); - mu_check(string_equal_p(input_data, output_data)); + mu_assert_int_eq(furi_string_size(input_data), furi_string_size(output_data)); + mu_check(furi_string_equal(input_data, output_data)); mu_check(stream_eof(stream)); stream_free(stream); furi_record_close(RECORD_STORAGE); - string_clear(input_data); - string_clear(output_data); + furi_string_free(input_data); + furi_string_free(output_data); } MU_TEST_SUITE(stream_suite) { diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 36f5b94c..210d3770 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -28,12 +28,12 @@ static void subghz_test_rx_callback( void* context) { UNUSED(receiver); UNUSED(context); - string_t text; - string_init(text); + FuriString* text; + text = furi_string_alloc(); subghz_protocol_decoder_base_get_string(decoder_base, text); subghz_receiver_reset(receiver_handler); - FURI_LOG_T(TAG, "\r\n%s", string_get_cstr(text)); - string_clear(text); + FURI_LOG_T(TAG, "\r\n%s", furi_string_get_cstr(text)); + furi_string_free(text); 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) { subghz_test_decoder_count = 0; uint32_t test_start = furi_get_tick(); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); bool file_load = false; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -167,11 +167,11 @@ static bool subghz_encoder_test(const char* path) { } while(false); if(file_load) { 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); 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) { LevelDuration level_duration; @@ -192,10 +192,11 @@ static bool subghz_encoder_test(const char* path) { 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); 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; } - string_clear(temp_str); + furi_string_free(temp_str); return subghz_test_decoder_count ? true : false; } diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 81d891b2..2009d4a5 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -1,5 +1,3 @@ -#include "m-string.h" - #include #include #include @@ -11,6 +9,7 @@ #define TAG "UnitTests" int run_minunit_test_furi(); +int run_minunit_test_furi_string(); int run_minunit_test_infrared(); int run_minunit_test_rpc(); int run_minunit_test_flipper_format(); @@ -33,6 +32,7 @@ typedef struct { const UnitTest unit_tests[] = { {.name = "furi", .entry = run_minunit_test_furi}, + {.name = "furi_string", .entry = run_minunit_test_furi_string}, {.name = "storage", .entry = run_minunit_test_storage}, {.name = "stream", .entry = run_minunit_test_stream}, {.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); } -void unit_tests_cli(Cli* cli, string_t args, void* context) { +void unit_tests_cli(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); @@ -91,8 +91,8 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { break; } - if(string_size(args)) { - if(string_cmp_str(args, unit_tests[i].name) == 0) { + if(furi_string_size(args)) { + if(furi_string_cmp_str(args, unit_tests[i].name) == 0) { failed_tests += unit_tests[i].entry(); } else { printf("Skipping %s\r\n", unit_tests[i].name); diff --git a/applications/examples/application.fam b/applications/examples/application.fam new file mode 100644 index 00000000..16d240cc --- /dev/null +++ b/applications/examples/application.fam @@ -0,0 +1,5 @@ +App( + appid="sample_apps", + name="Sample apps bundle", + apptype=FlipperAppType.METAPACKAGE, +) diff --git a/applications/examples/example_images/application.fam b/applications/examples/example_images/application.fam new file mode 100644 index 00000000..9a5f8e03 --- /dev/null +++ b/applications/examples/example_images/application.fam @@ -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", +) diff --git a/applications/examples/example_images/example_images.c b/applications/examples/example_images/example_images.c new file mode 100644 index 00000000..b00818cd --- /dev/null +++ b/applications/examples/example_images/example_images.c @@ -0,0 +1,81 @@ +#include +#include + +#include +#include + +/* 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; +} diff --git a/applications/examples/example_images/images/dolphin_71x25.png b/applications/examples/example_images/images/dolphin_71x25.png new file mode 100644 index 00000000..6b3f8aa5 Binary files /dev/null and b/applications/examples/example_images/images/dolphin_71x25.png differ diff --git a/applications/main/archive/archive.c b/applications/main/archive/archive.c index bbe532c8..b8609cf2 100644 --- a/applications/main/archive/archive.c +++ b/applications/main/archive/archive.c @@ -1,5 +1,4 @@ #include "archive_i.h" -#include "m-string.h" bool archive_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -18,7 +17,7 @@ ArchiveApp* archive_alloc() { archive->gui = furi_record_open(RECORD_GUI); 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->scene_manager = scene_manager_alloc(&archive_scene_handlers, archive); @@ -58,7 +57,7 @@ void archive_free(ArchiveApp* archive) { view_dispatcher_free(archive->view_dispatcher); scene_manager_free(archive->scene_manager); browser_free(archive->browser); - string_clear(archive->fav_move_str); + furi_string_free(archive->fav_move_str); text_input_free(archive->text_input); diff --git a/applications/main/archive/archive_i.h b/applications/main/archive/archive_i.h index 865e837d..d444aef8 100644 --- a/applications/main/archive/archive_i.h +++ b/applications/main/archive/archive_i.h @@ -28,7 +28,7 @@ struct ArchiveApp { TextInput* text_input; Widget* widget; FuriPubSubSubscription* loader_stop_subscription; - string_t fav_move_str; + FuriString* fav_move_str; char text_store[MAX_NAME_LEN]; char file_extension[MAX_EXT_LEN + 1]; }; diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index 00bb6b06..9689454b 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -5,7 +5,7 @@ #include #include #include "gui/modules/file_browser_worker.h" -#include "m-string.h" +#include #include static void @@ -19,9 +19,11 @@ static void if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) { 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( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { files_array_reset(model->files); model->item_cnt = item_cnt; model->item_idx = (file_idx > 0) ? file_idx : 0; @@ -31,8 +33,8 @@ static void model->list_offset = 0; model->list_loading = true; model->folder_loading = false; - return false; - }); + }, + false); archive_update_offset(browser); 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; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { files_array_reset(model->files); 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); ArchiveBrowserView* browser = (ArchiveBrowserView*)context; 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 { with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - model->list_loading = false; - return true; - }); + browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true); } } @@ -71,15 +73,12 @@ static void archive_long_load_cb(void* context) { ArchiveBrowserView* browser = (ArchiveBrowserView*)context; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - model->folder_loading = true; - return true; - }); + browser->view, ArchiveBrowserViewModel * model, { model->folder_loading = true; }, true); } static void archive_file_browser_set_path( ArchiveBrowserView* browser, - string_t path, + FuriString* path, const char* filter_ext, bool skip_assets) { furi_assert(browser); @@ -112,7 +111,9 @@ void archive_update_offset(ArchiveBrowserView* browser) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { 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))) { @@ -124,33 +125,34 @@ void archive_update_offset(ArchiveBrowserView* browser) { model->list_offset = CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); } - - return true; - }); + }, + true); } void archive_update_focus(ArchiveBrowserView* browser, const char* target) { furi_assert(browser); 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)) { archive_switch_tab(browser, TAB_RIGHT); } else { with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { uint16_t idx = 0; while(idx < files_array_size(model->files)) { 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; break; } ++idx; } - return false; - }); + }, + false); archive_update_offset(browser); } @@ -161,10 +163,10 @@ size_t archive_file_get_array_size(ArchiveBrowserView* browser) { uint16_t size = 0; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - size = files_array_size(model->files); - return false; - }); + browser->view, + ArchiveBrowserViewModel * model, + { size = files_array_size(model->files); }, + false); return size; } @@ -172,11 +174,13 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { model->item_cnt = count; model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); - return false; - }); + }, + false); archive_update_offset(browser); } @@ -185,7 +189,9 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { uint32_t items_cnt = 0; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { files_array_remove_v( model->files, model->item_idx - model->array_offset, @@ -193,8 +199,8 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { model->item_cnt--; model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); items_cnt = model->item_cnt; - return false; - }); + }, + false); if((items_cnt == 0) && (archive_is_home(browser))) { archive_switch_tab(browser, TAB_RIGHT); @@ -207,7 +213,9 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { ArchiveFile_t temp; size_t array_size = files_array_size(model->files) - 1; 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 { files_array_swap_at(model->files, model->item_idx, swap_idx); } - return false; - }); + }, + false); } void archive_file_array_rm_all(ArchiveBrowserView* browser) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - files_array_reset(model->files); - return false; - }); + browser->view, + ArchiveBrowserViewModel * model, + { files_array_reset(model->files); }, + false); } 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; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { if(model->item_cnt > FILE_LIST_BUF_LEN) { if(dir < 0) { 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; } } - return false; - }); + }, + false); 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; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { selected = files_array_size(model->files) ? files_array_get(model->files, model->item_idx - model->array_offset) : NULL; - return false; - }); + }, + false); return selected; } @@ -287,11 +299,13 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { ArchiveFile_t* selected = NULL; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { 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; - return false; - }); + }, + false); return selected; } @@ -300,10 +314,7 @@ ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) { ArchiveTabEnum tab_id = 0; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - tab_id = model->tab_idx; - return false; - }); + browser->view, ArchiveBrowserViewModel * model, { tab_id = model->tab_idx; }, false); 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)); - 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) { 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) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - model->tab_idx = tab; - return false; - }); + browser->view, ArchiveBrowserViewModel * model, { model->tab_idx = tab; }, false); } 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_init(&item); - string_set_str(item.path, name); + furi_string_set(item.path, name); archive_set_file_type(&item, name, false, true); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { files_array_push_back(model->files, item); model->item_cnt = files_array_size(model->files); - return false; - }); + }, + false); 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) { furi_assert(browser); furi_assert(name); ArchiveFile_t 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( - browser->view, (ArchiveBrowserViewModel * model) { - files_array_push_back(model->files, item); - return false; - }); + browser->view, + ArchiveBrowserViewModel * model, + { files_array_push_back(model->files, item); }, + false); ArchiveFile_t_clear(&item); } void archive_show_file_menu(ArchiveBrowserView* browser, bool show) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { if(show) { if(archive_is_item_in_array(model, model->item_idx)) { model->menu = true; model->menu_idx = 0; ArchiveFile_t* selected = 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 { model->menu = false; model->menu_idx = 0; } - - return true; - }); + }, + true); } void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) { furi_assert(browser); with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - model->move_fav = active; - return true; - }); + browser->view, ArchiveBrowserViewModel * model, { model->move_fav = active; }, true); } -static bool archive_is_dir_exists(string_t path) { - if(string_equal_str_p(path, STORAGE_ANY_PATH_PREFIX)) { +static bool archive_is_dir_exists(FuriString* path) { + if(furi_string_equal(path, STORAGE_ANY_PATH_PREFIX)) { return true; } bool state = false; FileInfo file_info; 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) { state = true; } @@ -431,16 +456,16 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { browser->is_root = true; 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; if(tab == ArchiveTabFavorites) { if(archive_favorites_count(browser) > 0) { tab_empty = false; } - } else if(string_start_with_str_p(browser->path, "/app:")) { - char* app_name = strchr(string_get_cstr(browser->path), ':'); + } else if(furi_string_start_with_str(browser->path, "/app:")) { + char* app_name = strchr(furi_string_get_cstr(browser->path), ':'); 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; } } @@ -458,29 +483,28 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { archive_switch_tab(browser, key); } else { with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { model->item_idx = 0; model->array_offset = 0; - return false; - }); - archive_get_items(browser, string_get_cstr(browser->path)); + }, + false); + archive_get_items(browser, furi_string_get_cstr(browser->path)); 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(path); int32_t idx_temp = 0; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - idx_temp = model->item_idx; - return false; - }); + browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false); - string_set(browser->path, path); + furi_string_set(browser->path, path); 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; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - idx_temp = model->item_idx; - return false; - }); + browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false); file_browser_worker_folder_refresh(browser->worker, idx_temp); } diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index ad64a984..519a34a2 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -16,6 +16,7 @@ static const char* tab_default_paths[] = { [ArchiveTabInfrared] = ANY_PATH("infrared"), [ArchiveTabBadUsb] = ANY_PATH("badusb"), [ArchiveTabU2f] = "/app:u2f", + [ArchiveTabApplications] = ANY_PATH("apps"), [ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX, }; @@ -27,6 +28,7 @@ static const char* known_ext[] = { [ArchiveFileTypeInfrared] = ".ir", [ArchiveFileTypeBadUsb] = ".txt", [ArchiveFileTypeU2f] = "?", + [ArchiveFileTypeApplication] = ".fap", [ArchiveFileTypeUpdateManifest] = ".fuf", [ArchiveFileTypeFolder] = "?", [ArchiveFileTypeUnknown] = "*", @@ -41,6 +43,7 @@ static const ArchiveFileTypeEnum known_type[] = { [ArchiveTabInfrared] = ArchiveFileTypeInfrared, [ArchiveTabBadUsb] = ArchiveFileTypeBadUsb, [ArchiveTabU2f] = ArchiveFileTypeU2f, + [ArchiveTabApplications] = ArchiveFileTypeApplication, [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_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_refresh_dir(ArchiveBrowserView* browser); diff --git a/applications/main/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c index 4d5b555f..86a294f7 100644 --- a/applications/main/archive/helpers/archive_favorites.c +++ b/applications/main/archive/helpers/archive_favorites.c @@ -6,8 +6,8 @@ #define ARCHIVE_FAV_FILE_BUF_LEN 32 -static bool archive_favorites_read_line(File* file, string_t str_result) { - string_reset(str_result); +static bool archive_favorites_read_line(File* file, FuriString* str_result) { + furi_string_reset(str_result); uint8_t buffer[ARCHIVE_FAV_FILE_BUF_LEN]; bool result = false; @@ -34,7 +34,7 @@ static bool archive_favorites_read_line(File* file, string_t str_result) { result = true; break; } 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); File* file = storage_file_alloc(fs_api); - string_t buffer; - string_init(buffer); + FuriString* buffer; + buffer = furi_string_alloc(); bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); uint16_t lines = 0; @@ -63,7 +63,7 @@ uint16_t archive_favorites_count(void* context) { if(!archive_favorites_read_line(file, buffer)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; // Skip empty lines } ++lines; @@ -72,7 +72,7 @@ uint16_t archive_favorites_count(void* context) { storage_file_close(file); - string_clear(buffer); + furi_string_free(buffer); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -80,8 +80,8 @@ uint16_t archive_favorites_count(void* context) { } static bool archive_favourites_rescan() { - string_t buffer; - string_init(buffer); + FuriString* buffer; + buffer = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); @@ -91,23 +91,25 @@ static bool archive_favourites_rescan() { if(!archive_favorites_read_line(file, buffer)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; } - if(string_search(buffer, "/app:") == 0) { - if(archive_app_is_available(NULL, string_get_cstr(buffer))) { - archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + if(furi_string_search(buffer, "/app:") == 0) { + if(archive_app_is_available(NULL, furi_string_get_cstr(buffer))) { + archive_file_append( + ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(buffer)); } } else { - if(storage_file_exists(storage, string_get_cstr(buffer))) { - archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + if(storage_file_exists(storage, furi_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_common_remove(storage, ARCHIVE_FAV_PATH); @@ -127,9 +129,9 @@ bool archive_favorites_read(void* context) { Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); - string_t buffer; + FuriString* buffer; FileInfo file_info; - string_init(buffer); + buffer = furi_string_alloc(); bool need_refresh = false; uint16_t file_count = 0; @@ -143,33 +145,33 @@ bool archive_favorites_read(void* context) { if(!archive_favorites_read_line(file, buffer)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; } - if(string_search(buffer, "/app:") == 0) { - if(archive_app_is_available(browser, string_get_cstr(buffer))) { - archive_add_app_item(browser, string_get_cstr(buffer)); + if(furi_string_search(buffer, "/app:") == 0) { + if(archive_app_is_available(browser, furi_string_get_cstr(buffer))) { + archive_add_app_item(browser, furi_string_get_cstr(buffer)); file_count++; } else { need_refresh = true; } } else { - if(storage_file_exists(storage, string_get_cstr(buffer))) { - storage_common_stat(storage, string_get_cstr(buffer), &file_info); + if(storage_file_exists(storage, furi_string_get_cstr(buffer))) { + storage_common_stat(storage, furi_string_get_cstr(buffer), &file_info); 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++; } else { need_refresh = true; } } - string_reset(buffer); + furi_string_reset(buffer); } } storage_file_close(file); - string_clear(buffer); + furi_string_free(buffer); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -183,14 +185,14 @@ bool archive_favorites_read(void* context) { } bool archive_favorites_delete(const char* format, ...) { - string_t buffer; - string_t filename; + FuriString* buffer; + FuriString* filename; va_list args; va_start(args, format); - string_init_vprintf(filename, format, args); + filename = furi_string_alloc_vprintf(format, args); va_end(args); - string_init(buffer); + buffer = furi_string_alloc(); Storage* fs_api = furi_record_open(RECORD_STORAGE); 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)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; } - if(string_search(buffer, filename)) { - archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + if(furi_string_search(buffer, filename)) { + archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(buffer)); } } } - string_clear(buffer); - string_clear(filename); + furi_string_free(buffer); + furi_string_free(filename); storage_file_close(file); 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, ...) { - string_t buffer; - string_t filename; + FuriString* buffer; + FuriString* filename; va_list args; va_start(args, format); - string_init_vprintf(filename, format, args); + filename = furi_string_alloc_vprintf(format, args); va_end(args); - string_init(buffer); + buffer = furi_string_alloc(); Storage* fs_api = furi_record_open(RECORD_STORAGE); 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)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; } - if(!string_search(buffer, filename)) { + if(!furi_string_search(buffer, filename)) { found = true; break; } @@ -256,8 +258,8 @@ bool archive_is_favorite(const char* format, ...) { } storage_file_close(file); - string_clear(buffer); - string_clear(filename); + furi_string_free(buffer); + furi_string_free(filename); storage_file_free(file); 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); File* file = storage_file_alloc(fs_api); - string_t path; - string_t buffer; + FuriString* path; + FuriString* buffer; - string_init(buffer); - string_init(path); + buffer = furi_string_alloc(); + 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); if(result) { @@ -285,19 +287,19 @@ bool archive_favorites_rename(const char* src, const char* dst) { if(!archive_favorites_read_line(file, buffer)) { break; } - if(!string_size(buffer)) { + if(!furi_string_size(buffer)) { continue; } archive_file_append( ARCHIVE_FAV_TEMP_PATH, "%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); - string_clear(path); + furi_string_free(buffer); + furi_string_free(path); storage_file_close(file); 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++) { 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); diff --git a/applications/main/archive/helpers/archive_favorites.h b/applications/main/archive/helpers/archive_favorites.h index 29eedcdb..db894337 100644 --- a/applications/main/archive/helpers/archive_favorites.h +++ b/applications/main/archive/helpers/archive_favorites.h @@ -7,8 +7,8 @@ uint16_t archive_favorites_count(void* context); bool archive_favorites_read(void* context); -bool archive_favorites_delete(const char* format, ...); -bool archive_is_favorite(const char* format, ...); +bool archive_favorites_delete(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2))); +bool archive_is_favorite(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2))); bool archive_favorites_rename(const char* src, const char* dst); void archive_add_to_favorites(const char* file_path); void archive_favorites_save(void* context); diff --git a/applications/main/archive/helpers/archive_files.c b/applications/main/archive/helpers/archive_files.c index 9f8b4ee1..87265a45 100644 --- a/applications/main/archive/helpers/archive_files.c +++ b/applications/main/archive/helpers/archive_files.c @@ -15,10 +15,10 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder } else { for(size_t i = 0; i < COUNT_OF(known_ext); i++) { 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(string_search_str(file->path, archive_get_default_path(ArchiveTabBadUsb)) == - 0) { + if(furi_string_search( + file->path, archive_get_default_path(ArchiveTabBadUsb)) == 0) { file->type = i; 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, ...) { furi_assert(path); - string_t string; + FuriString* string; va_list args; va_start(args, format); - string_init_vprintf(string, format, args); + string = furi_string_alloc_vprintf(format, args); va_end(args); 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); 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); @@ -77,35 +77,35 @@ void archive_file_append(const char* path, const char* format, ...) { void archive_delete_file(void* context, const char* format, ...) { furi_assert(context); - string_t filename; + FuriString* filename; va_list args; va_start(args, format); - string_init_vprintf(filename, format, args); + filename = furi_string_alloc_vprintf(format, args); va_end(args); ArchiveBrowserView* browser = context; Storage* fs_api = furi_record_open(RECORD_STORAGE); 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; 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 { - 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); - if(archive_is_favorite("%s", string_get_cstr(filename))) { - archive_favorites_delete("%s", string_get_cstr(filename)); + if(archive_is_favorite("%s", furi_string_get_cstr(filename))) { + archive_favorites_delete("%s", furi_string_get_cstr(filename)); } if(res) { archive_file_array_rm_selected(browser); } - string_clear(filename); + furi_string_free(filename); } diff --git a/applications/main/archive/helpers/archive_files.h b/applications/main/archive/helpers/archive_files.h index 84b7e24a..1822befa 100644 --- a/applications/main/archive/helpers/archive_files.h +++ b/applications/main/archive/helpers/archive_files.h @@ -1,9 +1,11 @@ #pragma once #include -#include +#include #include +#define FAP_MANIFEST_MAX_ICON_SIZE 32 + typedef enum { ArchiveFileTypeIButton, ArchiveFileTypeNFC, @@ -13,41 +15,65 @@ typedef enum { ArchiveFileTypeBadUsb, ArchiveFileTypeU2f, ArchiveFileTypeUpdateManifest, + ArchiveFileTypeApplication, ArchiveFileTypeFolder, ArchiveFileTypeUnknown, ArchiveFileTypeLoading, } ArchiveFileTypeEnum; typedef struct { - string_t path; + FuriString* path; ArchiveFileTypeEnum type; + uint8_t* custom_icon_data; + FuriString* custom_name; bool fav; bool is_app; } ArchiveFile_t; static void ArchiveFile_t_init(ArchiveFile_t* obj) { + obj->path = furi_string_alloc(); obj->type = ArchiveFileTypeUnknown; - obj->is_app = false; + obj->custom_icon_data = NULL; + obj->custom_name = furi_string_alloc(); obj->fav = false; - string_init(obj->path); + obj->is_app = false; } 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->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; - 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) { + furi_string_set(obj->path, src->path); 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; - string_set(obj->path, src->path); + obj->is_app = src->is_app; } 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( @@ -60,5 +86,7 @@ ARRAY_DEF( 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); -void archive_file_append(const char* path, const char* format, ...); -void archive_delete_file(void* context, const char* format, ...); +void archive_file_append(const char* path, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); +void archive_delete_file(void* context, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index e22ac792..9dc67161 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -20,6 +20,7 @@ static const char* flipper_app_name[] = { [ArchiveFileTypeBadUsb] = "Bad USB", [ArchiveFileTypeU2f] = "U2F", [ArchiveFileTypeUpdateManifest] = "UpdaterApp", + [ArchiveFileTypeApplication] = "Applications", }; 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; if(selected->is_app) { - char* param = strrchr(string_get_cstr(selected->path), '/'); + char* param = strrchr(furi_string_get_cstr(selected->path), '/'); if(param != NULL) { param++; } status = loader_start(loader, flipper_app_name[selected->type], param); } else { 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) { @@ -159,13 +160,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { consumed = true; break; 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_favorites_move_mode(archive->browser, true); consumed = true; break; 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); consumed = true; break; diff --git a/applications/main/archive/scenes/archive_scene_delete.c b/applications/main/archive/scenes/archive_scene_delete.c index d882fd06..d3964d0f 100644 --- a/applications/main/archive/scenes/archive_scene_delete.c +++ b/applications/main/archive/scenes/archive_scene_delete.c @@ -4,7 +4,6 @@ #include "../helpers/archive_apps.h" #include "../helpers/archive_browser.h" #include "toolbox/path.h" -#include "m-string.h" #define SCENE_DELETE_CUSTOM_EVENT (0UL) #define MAX_TEXT_INPUT_LEN 22 @@ -26,18 +25,18 @@ void archive_scene_delete_on_enter(void* context) { widget_add_button_element( app->widget, GuiButtonTypeRight, "Delete", archive_scene_delete_widget_callback, app); - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); ArchiveFile_t* current = archive_get_current_file(app->browser); path_extract_filename(current->path, filename, false); 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( 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); } diff --git a/applications/main/archive/scenes/archive_scene_rename.c b/applications/main/archive/scenes/archive_scene_rename.c index 293fa89a..1451428b 100644 --- a/applications/main/archive/scenes/archive_scene_rename.c +++ b/applications/main/archive/scenes/archive_scene_rename.c @@ -19,10 +19,10 @@ void archive_scene_rename_on_enter(void* context) { TextInput* text_input = archive->text_input; ArchiveFile_t* current = archive_get_current_file(archive->browser); - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); 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); @@ -37,10 +37,10 @@ void archive_scene_rename_on_enter(void* context) { false); 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); - string_clear(filename); + furi_string_free(filename); 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); ArchiveFile_t* file = archive_get_current_file(archive->browser); - string_t path_dst; - string_init(path_dst); + FuriString* path_dst; + path_dst = furi_string_alloc(); 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); 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); consumed = true; diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index ddd6637d..a2e219b9 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -14,6 +14,7 @@ static const char* ArchiveTabNames[] = { [ArchiveTabInfrared] = "Infrared", [ArchiveTabBadUsb] = "Bad USB", [ArchiveTabU2f] = "U2F", + [ArchiveTabApplications] = "Apps", [ArchiveTabBrowser] = "Browser", }; @@ -29,6 +30,7 @@ static const Icon* ArchiveItemIcons[] = { [ArchiveFileTypeFolder] = &I_dir_10px, [ArchiveFileTypeUnknown] = &I_unknown_10px, [ArchiveFileTypeLoading] = &I_loading_10px, + [ArchiveFileTypeApplication] = &I_unknown_10px, }; void archive_browser_set_callback( @@ -47,35 +49,35 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) { canvas_set_color(canvas, ColorBlack); 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"); - string_init_set_str(menu[1], "Pin"); - string_init_set_str(menu[2], "Rename"); - string_init_set_str(menu[3], "Delete"); + menu[0] = furi_string_alloc_set("Run in app"); + menu[1] = furi_string_alloc_set("Pin"); + menu[2] = furi_string_alloc_set("Rename"); + menu[3] = furi_string_alloc_set("Delete"); ArchiveFile_t* selected = files_array_get(model->files, model->item_idx - model->array_offset); 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)) { - string_set_str(menu[0], "---"); - string_set_str(menu[1], "---"); - string_set_str(menu[2], "---"); + furi_string_set(menu[0], "---"); + furi_string_set(menu[1], "---"); + furi_string_set(menu[2], "---"); } else { if(model->tab_idx == ArchiveTabFavorites) { - string_set_str(menu[2], "Move"); - string_set_str(menu[3], "---"); + furi_string_set(menu[2], "Move"); + furi_string_set(menu[3], "---"); } else if(selected->is_app) { - string_set_str(menu[2], "---"); + furi_string_set(menu[2], "---"); } } for(size_t i = 0; i < MENU_ITEMS; i++) { - canvas_draw_str(canvas, 82, 27 + i * 11, string_get_cstr(menu[i])); - string_clear(menu[i]); + canvas_draw_str(canvas, 82, 27 + i * 11, furi_string_get_cstr(menu[i])); + furi_string_free(menu[i]); } 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; for(uint32_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { - string_t str_buf; - string_init(str_buf); + FuriString* str_buf; + str_buf = furi_string_alloc(); 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; ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; + uint8_t* custom_icon_data = NULL; if(archive_is_item_in_array(model, idx)) { ArchiveFile_t* file = files_array_get( 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; + 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 { - string_set_str(str_buf, "---"); + furi_string_set(str_buf, "---"); } elements_string_fit_width( @@ -143,10 +156,17 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { canvas_set_color(canvas, ColorBlack); } - 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, string_get_cstr(str_buf)); + if(custom_icon_data) { + 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) { @@ -243,33 +263,37 @@ static bool archive_view_input(InputEvent* event, void* context) { bool in_menu; bool move_fav_mode; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { in_menu = model->menu; move_fav_mode = model->move_fav; - return false; - }); + }, + false); if(in_menu) { if(event->type == InputTypeShort) { if(event->key == InputKeyUp || event->key == InputKeyDown) { with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { if(event->key == InputKeyUp) { model->menu_idx = ((model->menu_idx - 1) + MENU_ITEMS) % MENU_ITEMS; } else if(event->key == InputKeyDown) { model->menu_idx = (model->menu_idx + 1) % MENU_ITEMS; } - return true; - }); + }, + true); } if(event->key == InputKeyOk) { uint8_t idx; with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - idx = model->menu_idx; - return false; - }); + browser->view, + ArchiveBrowserViewModel * model, + { idx = model->menu_idx; }, + false); browser->callback(file_menu_actions[idx], browser->context); } else if(event->key == InputKeyBack) { 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) && (event->type == InputTypeShort || event->type == InputTypeRepeat)) { with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { if(event->key == InputKeyUp) { model->item_idx = ((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); } } - - return true; - }); + }, + true); archive_update_offset(browser); } @@ -361,14 +386,16 @@ ArchiveBrowserView* browser_alloc() { view_set_draw_callback(browser->view, archive_view_render); 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( - browser->view, (ArchiveBrowserViewModel * model) { + browser->view, + ArchiveBrowserViewModel * model, + { files_array_init(model->files); model->tab_idx = TAB_DEFAULT; - return true; - }); + }, + true); return browser; } @@ -381,12 +408,12 @@ void browser_free(ArchiveBrowserView* browser) { } with_view_model( - browser->view, (ArchiveBrowserViewModel * model) { - files_array_clear(model->files); - return false; - }); + browser->view, + ArchiveBrowserViewModel * model, + { files_array_clear(model->files); }, + false); - string_clear(browser->path); + furi_string_free(browser->path); view_free(browser->view); free(browser); diff --git a/applications/main/archive/views/archive_browser_view.h b/applications/main/archive/views/archive_browser_view.h index 5c649c38..308af4e4 100644 --- a/applications/main/archive/views/archive_browser_view.h +++ b/applications/main/archive/views/archive_browser_view.h @@ -26,6 +26,7 @@ typedef enum { ArchiveTabIButton, ArchiveTabBadUsb, ArchiveTabU2f, + ArchiveTabApplications, ArchiveTabBrowser, ArchiveTabTotal, } ArchiveTabEnum; @@ -77,7 +78,7 @@ struct ArchiveBrowserView { bool worker_running; ArchiveBrowserViewCallback callback; void* context; - string_t path; + FuriString* path; InputKey last_tab_switch_dir; bool is_root; }; diff --git a/applications/main/bad_usb/bad_usb_app.c b/applications/main/bad_usb/bad_usb_app.c index 09d7d346..6fd29cd7 100644 --- a/applications/main/bad_usb/bad_usb_app.c +++ b/applications/main/bad_usb/bad_usb_app.c @@ -1,5 +1,4 @@ #include "bad_usb_app_i.h" -#include "m-string.h" #include #include #include @@ -26,10 +25,10 @@ static void bad_usb_app_tick_event_callback(void* context) { BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* app = malloc(sizeof(BadUsbApp)); - string_init(app->file_path); + app->file_path = furi_string_alloc(); 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); @@ -64,10 +63,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { app->error = BadUsbAppErrorCloseRpc; scene_manager_next_scene(app->scene_manager, BadUsbSceneError); } else { - if(!string_empty_p(app->file_path)) { + if(!furi_string_empty(app->file_path)) { scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); } 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); } } @@ -95,7 +94,7 @@ void bad_usb_app_free(BadUsbApp* app) { furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_DIALOGS); - string_clear(app->file_path); + furi_string_free(app->file_path); free(app); } diff --git a/applications/main/bad_usb/bad_usb_app_i.h b/applications/main/bad_usb/bad_usb_app_i.h index 6378bddf..85fd56ff 100644 --- a/applications/main/bad_usb/bad_usb_app_i.h +++ b/applications/main/bad_usb/bad_usb_app_i.h @@ -31,7 +31,7 @@ struct BadUsbApp { Widget* widget; BadUsbAppError error; - string_t file_path; + FuriString* file_path; BadUsb* bad_usb_view; BadUsbScript* bad_usb_script; }; diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index 9d9d3e39..8ff38ef6 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -26,16 +26,16 @@ typedef enum { struct BadUsbScript { FuriHalUsbHidConfig hid_cfg; BadUsbState st; - string_t file_path; + FuriString* file_path; uint32_t defdelay; FuriThread* thread; uint8_t file_buf[FILE_BUFFER_LEN + 1]; uint8_t buf_start; uint8_t buf_len; bool file_end; - string_t line; + FuriString* line; - string_t line_prev; + FuriString* line_prev; 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_2[] = {"DEFAULTDELAY "}; 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_altstr_1[] = {"ALTSTRING "}; @@ -230,9 +231,10 @@ static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { return 0; } -static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) { - uint32_t line_len = string_size(line); - const char* line_tmp = string_get_cstr(line); +static int32_t + ducky_parse_line(BadUsbScript* bad_usb, FuriString* line, char* error, size_t error_len) { + uint32_t line_len = furi_string_size(line); + const char* line_tmp = furi_string_get_cstr(line); bool state = false; 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)) { return (int32_t)delay_val; } + if(error != NULL) { + snprintf(error, error_len, "Invalid number %s", line_tmp); + } return SCRIPT_STATE_ERROR; } else if( (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 line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; 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; } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { // STRING line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; state = ducky_string(line_tmp); + if(!state && error != NULL) { + snprintf(error, error_len, "Invalid string %s", line_tmp); + } return (state) ? (0) : SCRIPT_STATE_ERROR; } else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) { // ALTCHAR line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; ducky_numlock_on(); state = ducky_altchar(line_tmp); + if(!state && error != NULL) { + snprintf(error, error_len, "Invalid altchar %s", line_tmp); + } return (state) ? (0) : SCRIPT_STATE_ERROR; } else if( (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]; ducky_numlock_on(); state = ducky_altstring(line_tmp); + if(!state && error != NULL) { + snprintf(error, error_len, "Invalid altstring %s", line_tmp); + } return (state) ? (0) : SCRIPT_STATE_ERROR; } else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) { // REPEAT line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; 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; + } 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 { // Special keys + modifiers 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) { // It's a modifier key 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); return (0); } + if(error != NULL) { + strncpy(error, "Unknown error", error_len); + } return SCRIPT_STATE_ERROR; } @@ -323,7 +359,7 @@ static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) { } FURI_LOG_D( 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.pid, bad_usb->hid_cfg.manuf, @@ -337,7 +373,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { uint8_t ret = 0; uint32_t line_len = 0; - string_reset(bad_usb->line); + furi_string_reset(bad_usb->line); do { 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; } else { 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++; } @@ -360,7 +396,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { } } 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 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]); @@ -373,7 +409,7 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { } storage_file_seek(script_file, 0, true); - string_reset(bad_usb->line); + furi_string_reset(bad_usb->line); 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) { 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 return 0; } else if(delay_val < 0) { // Script error 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; } else { return (delay_val + bad_usb->defdelay); } } - string_set(bad_usb->line_prev, bad_usb->line); - string_reset(bad_usb->line); + furi_string_set(bad_usb->line_prev, bad_usb->line); + furi_string_reset(bad_usb->line); while(1) { 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; } 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->buf_len = bad_usb->buf_len + 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) { 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; } else { return (delay_val + bad_usb->defdelay); } } 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; @@ -456,8 +495,8 @@ static int32_t bad_usb_worker(void* context) { FURI_LOG_I(WORKER_TAG, "Init"); File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - string_init(bad_usb->line); - string_init(bad_usb->line_prev); + bad_usb->line = furi_string_alloc(); + bad_usb->line_prev = furi_string_alloc(); 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(storage_file_open( script_file, - string_get_cstr(bad_usb->file_path), + furi_string_get_cstr(bad_usb->file_path), FSAM_READ, FSOM_OPEN_EXISTING)) { 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_free(script_file); - string_clear(bad_usb->line); - string_clear(bad_usb->line_prev); + furi_string_free(bad_usb->line); + furi_string_free(bad_usb->line_prev); FURI_LOG_I(WORKER_TAG, "End"); return 0; } -BadUsbScript* bad_usb_script_open(string_t file_path) { +BadUsbScript* bad_usb_script_open(FuriString* file_path) { furi_assert(file_path); BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); - string_init(bad_usb->file_path); - string_set(bad_usb->file_path, file_path); + bad_usb->file_path = furi_string_alloc(); + furi_string_set(bad_usb->file_path, file_path); bad_usb->st.state = BadUsbStateInit; + bad_usb->st.error[0] = '\0'; bad_usb->thread = furi_thread_alloc(); 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_join(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); } diff --git a/applications/main/bad_usb/bad_usb_script.h b/applications/main/bad_usb/bad_usb_script.h index 88921de3..f24372fa 100644 --- a/applications/main/bad_usb/bad_usb_script.h +++ b/applications/main/bad_usb/bad_usb_script.h @@ -5,7 +5,6 @@ extern "C" { #endif #include -#include typedef struct BadUsbScript BadUsbScript; @@ -26,9 +25,10 @@ typedef struct { uint16_t line_nb; uint32_t delay_remain; uint16_t error_line; + char error[64]; } 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); diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_work.c b/applications/main/bad_usb/scenes/bad_usb_scene_work.c index 516cbde3..689f3b4e 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_work.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_work.c @@ -2,7 +2,6 @@ #include "../bad_usb_app_i.h" #include "../views/bad_usb_view.h" #include "furi_hal.h" -#include "m-string.h" #include "toolbox/path.h" 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) { BadUsbApp* app = context; - string_t file_name; - string_init(file_name); + FuriString* file_name; + file_name = furi_string_alloc(); 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); - 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)); diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index 0679669f..6c6a1584 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -19,12 +19,12 @@ typedef struct { static void bad_usb_draw_callback(Canvas* canvas, void* _model) { BadUsbModel* model = _model; - string_t disp_str; - string_init_set_str(disp_str, model->file_name); + FuriString* disp_str; + disp_str = furi_string_alloc_set(model->file_name); elements_string_fit_width(canvas, disp_str, 128 - 2); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 8, string_get_cstr(disp_str)); - string_reset(disp_str); + canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str)); + furi_string_reset(disp_str); 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_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); 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, 127, 46, AlignRight, AlignBottom, string_get_cstr(disp_str)); - string_reset(disp_str); + canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(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) { canvas_draw_icon(canvas, 4, 22, &I_Smile_18x18); 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_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, 114, 36, AlignRight, AlignBottom, string_get_cstr(disp_str)); - string_reset(disp_str); + canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + furi_string_reset(disp_str); canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); } else if(model->state.state == BadUsbStateDone) { canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); canvas_set_font(canvas, FontBigNumbers); 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); } else if(model->state.state == BadUsbStateDelay) { 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_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, 114, 36, AlignRight, AlignBottom, string_get_cstr(disp_str)); - string_reset(disp_str); + canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + furi_string_reset(disp_str); canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); 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, 127, 46, AlignRight, AlignBottom, string_get_cstr(disp_str)); - string_reset(disp_str); + canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + furi_string_reset(disp_str); } else { 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) { @@ -143,29 +146,33 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c furi_assert(bad_usb); furi_assert(callback); with_view_model( - bad_usb->view, (BadUsbModel * model) { + bad_usb->view, + BadUsbModel * model, + { UNUSED(model); bad_usb->callback = callback; bad_usb->context = context; - return true; - }); + }, + true); } void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { furi_assert(name); with_view_model( - bad_usb->view, (BadUsbModel * model) { - strlcpy(model->file_name, name, MAX_NAME_LEN); - return true; - }); + bad_usb->view, + BadUsbModel * model, + { strlcpy(model->file_name, name, MAX_NAME_LEN); }, + true); } void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { furi_assert(st); with_view_model( - bad_usb->view, (BadUsbModel * model) { + bad_usb->view, + BadUsbModel * model, + { memcpy(&(model->state), st, sizeof(BadUsbState)); model->anim_frame ^= 1; - return true; - }); + }, + true); } diff --git a/applications/main/fap_loader/application.fam b/applications/main/fap_loader/application.fam index bd0403e0..784ee950 100644 --- a/applications/main/fap_loader/application.fam +++ b/applications/main/fap_loader/application.fam @@ -3,6 +3,7 @@ App( name="Applications", apptype=FlipperAppType.APP, entry_point="fap_loader_app", + cdefines=["APP_FAP_LOADER"], requires=[ "gui", "storage", diff --git a/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp b/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp index 17e2ba83..f8adbf9d 100644 --- a/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp +++ b/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp @@ -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); 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; } else { result = true; diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index c0f60cec..faf8eefc 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -1,34 +1,34 @@ #include #include #include -#include #include +#include #include -#include "elf_cpp/elf_hashtable.h" #include +#include "elf_cpp/elf_hashtable.h" +#include "fap_loader_app.h" #define TAG "fap_loader_app" -typedef struct { +struct FapLoader { FlipperApplication* app; Storage* storage; DialogsApp* dialogs; Gui* gui; - string_t fap_path; - + FuriString* fap_path; ViewDispatcher* view_dispatcher; Loading* loading; -} FapLoader; +}; -static bool - fap_loader_item_callback(string_t path, void* context, uint8_t** icon_ptr, string_t item_name) { - FapLoader* loader = context; - furi_assert(loader); - - FlipperApplication* app = flipper_application_alloc(loader->storage, &hashtable_api_interface); +bool fap_loader_load_name_and_icon( + FuriString* path, + Storage* storage, + uint8_t** icon_ptr, + FuriString* item_name) { + FlipperApplication* app = flipper_application_alloc(storage, &hashtable_api_interface); 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; @@ -37,10 +37,10 @@ static bool if(manifest->has_icon) { 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; } 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; } @@ -48,30 +48,41 @@ static bool 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) { 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 show_error = true; do { file_selected = true; 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 = - 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) { 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( TAG, "FAP Loader failed to preload %s: %s", - string_get_cstr(loader->fap_path), + furi_string_get_cstr(loader->fap_path), err_msg); break; } @@ -80,16 +91,17 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(loader->app); if(load_status != FlipperApplicationLoadStatusSuccess) { 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( TAG, "FAP Loader failed to map to memory %s: %s", - string_get_cstr(loader->fap_path), + furi_string_get_cstr(loader->fap_path), err_msg); 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); 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_buttons(message, NULL, NULL, NULL); - string_t buffer; - string_init(buffer); - string_printf(buffer, "%s", string_get_cstr(error_message)); - string_replace_str(buffer, ":", "\n"); + FuriString* buffer; + buffer = furi_string_alloc(); + furi_string_printf(buffer, "%s", furi_string_get_cstr(error_message)); + furi_string_replace(buffer, ":", "\n"); 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_free(message); - string_clear(buffer); + furi_string_free(buffer); } - string_clear(error_message); + furi_string_free(error_message); if(file_selected) { flipper_application_free(loader->app); @@ -131,7 +143,7 @@ static bool fap_loader_select_app(FapLoader* loader) { const DialogsFileBrowserOptions browser_options = { .extension = ".fap", .skip_assets = true, - .icon = &I_badusb_10px, + .icon = &I_unknown_10px, .hide_ext = true, .item_loader_callback = fap_loader_item_callback, .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); } -int32_t fap_loader_app(void* p) { +static FapLoader* fap_loader_alloc(const char* path) { FapLoader* loader = malloc(sizeof(FapLoader)); + loader->fap_path = furi_string_alloc_set(path); loader->storage = furi_record_open(RECORD_STORAGE); loader->dialogs = furi_record_open(RECORD_DIALOGS); loader->gui = furi_record_open(RECORD_GUI); - loader->view_dispatcher = view_dispatcher_alloc(); loader->loading = loading_alloc(); - view_dispatcher_attach_to_gui( loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); 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) { - 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); } else { - string_init_set(loader->fap_path, EXT_PATH("apps")); - + loader = fap_loader_alloc(EXT_PATH("apps")); while(fap_loader_select_app(loader)) { view_dispatcher_switch_to_view(loader->view_dispatcher, 0); fap_loader_run_selected_app(loader); }; } - view_dispatcher_remove_view(loader->view_dispatcher, 0); - 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); + fap_loader_free(loader); return 0; -} \ No newline at end of file +} diff --git a/applications/main/fap_loader/fap_loader_app.h b/applications/main/fap_loader/fap_loader_app.h new file mode 100644 index 00000000..9ed725ef --- /dev/null +++ b/applications/main/fap_loader/fap_loader_app.h @@ -0,0 +1,27 @@ +#pragma once +#include + +#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 \ No newline at end of file diff --git a/applications/main/gpio/scenes/gpio_scene_start.c b/applications/main/gpio/scenes/gpio_scene_start.c index 41b74523..72992294 100644 --- a/applications/main/gpio/scenes/gpio_scene_start.c +++ b/applications/main/gpio/scenes/gpio_scene_start.c @@ -1,6 +1,7 @@ #include "../gpio_app_i.h" #include "furi_hal_power.h" #include "furi_hal_usb.h" +#include enum GpioItem { GpioItemUsbUart, @@ -88,6 +89,7 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) { } else if(event.event == GpioStartEventUsbUart) { scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart); if(!furi_hal_usb_is_locked()) { + DOLPHIN_DEED(DolphinDeedGpioUartBridge); scene_manager_next_scene(app->scene_manager, GpioSceneUsbUart); } else { scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCloseRpc); diff --git a/applications/main/gpio/usb_uart_bridge.c b/applications/main/gpio/usb_uart_bridge.c index 02f58ed1..6e0bce73 100644 --- a/applications/main/gpio/usb_uart_bridge.c +++ b/applications/main/gpio/usb_uart_bridge.c @@ -1,6 +1,5 @@ #include "usb_uart_bridge.h" #include "furi_hal.h" -#include #include #include "usb_cdc.h" #include "cli/cli_vcp.h" @@ -43,7 +42,7 @@ struct UsbUartBridge { FuriThread* thread; FuriThread* tx_thread; - StreamBufferHandle_t rx_stream; + FuriStreamBuffer* rx_stream; 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) { UsbUartBridge* usb_uart = (UsbUartBridge*)context; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; 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); - 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)); - 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->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal); @@ -189,8 +186,8 @@ static int32_t usb_uart_worker(void* context) { furi_check((events & FuriFlagError) == 0); if(events & WorkerEvtStop) break; if(events & WorkerEvtRxDone) { - size_t len = - xStreamBufferReceive(usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0); + size_t len = furi_stream_buffer_receive( + usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0); if(len > 0) { if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) { 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_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk); } 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_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_semaphore_free(usb_uart->tx_sem); diff --git a/applications/main/gpio/views/gpio_test.c b/applications/main/gpio/views/gpio_test.c index 89c09f86..69dc0f67 100644 --- a/applications/main/gpio/views/gpio_test.c +++ b/applications/main/gpio/views/gpio_test.c @@ -48,23 +48,27 @@ static bool gpio_test_input_callback(InputEvent* event, void* context) { static bool gpio_test_process_left(GpioTest* gpio_test) { with_view_model( - gpio_test->view, (GpioTestModel * model) { + gpio_test->view, + GpioTestModel * model, + { if(model->pin_idx) { model->pin_idx--; } - return true; - }); + }, + true); return true; } static bool gpio_test_process_right(GpioTest* gpio_test) { with_view_model( - gpio_test->view, (GpioTestModel * model) { + gpio_test->view, + GpioTestModel * model, + { if(model->pin_idx < GPIO_ITEM_COUNT) { model->pin_idx++; } - return true; - }); + }, + true); return true; } @@ -72,7 +76,9 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) { bool consumed = false; with_view_model( - gpio_test->view, (GpioTestModel * model) { + gpio_test->view, + GpioTestModel * model, + { if(event->type == InputTypePress) { if(model->pin_idx < GPIO_ITEM_COUNT) { 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; } gpio_test->callback(event->type, gpio_test->context); - return true; - }); + }, + true); return consumed; } @@ -122,10 +128,12 @@ void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback, furi_assert(gpio_test); furi_assert(callback); with_view_model( - gpio_test->view, (GpioTestModel * model) { + gpio_test->view, + GpioTestModel * model, + { UNUSED(model); gpio_test->callback = callback; gpio_test->context = context; - return false; - }); + }, + false); } diff --git a/applications/main/gpio/views/gpio_usb_uart.c b/applications/main/gpio/views/gpio_usb_uart.c index d2d371b6..c7406d29 100644 --- a/applications/main/gpio/views/gpio_usb_uart.c +++ b/applications/main/gpio/views/gpio_usb_uart.c @@ -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); } else { 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); snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024); 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); } else { 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); snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024); 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); with_view_model( - usb_uart->view, (GpioUsbUartModel * model) { + usb_uart->view, + GpioUsbUartModel * model, + { UNUSED(model); usb_uart->callback = callback; usb_uart->context = context; - return false; - }); + }, + false); } 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); with_view_model( - instance->view, (GpioUsbUartModel * model) { + instance->view, + GpioUsbUartModel * model, + { model->baudrate = st->baudrate_cur; model->vcp_port = cfg->vcp_ch; 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->tx_cnt = st->tx_cnt; model->rx_cnt = st->rx_cnt; - return true; - }); + }, + true); } diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index e9ec614e..887fb3e7 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -2,7 +2,6 @@ #include "assets_icons.h" #include "ibutton_i.h" #include "ibutton/scenes/ibutton_scene.h" -#include "m-string.h" #include #include #include @@ -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); bool result = false; - string_t data; - string_init(data); + FuriString* data; + data = furi_string_alloc(); 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 uint32_t version; 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; // key type iButtonKeyType type; 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 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); flipper_format_free(file); - string_clear(data); + furi_string_free(data); if((!result) && (show_dialog)) { 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 = malloc(sizeof(iButton)); - string_init(ibutton->file_path); + ibutton->file_path = furi_string_alloc(); 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_key_free(ibutton->key); - string_clear(ibutton->file_path); + furi_string_free(ibutton->file_path); free(ibutton); } @@ -240,19 +239,19 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { do { // 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 ibutton_delete_key(ibutton); // Remove old key name from path - size_t filename_start = string_search_rchar(ibutton->file_path, '/'); - string_left(ibutton->file_path, filename_start); + size_t filename_start = furi_string_search_rchar(ibutton->file_path, '/'); + 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 - 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 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 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; } @@ -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_send_started(ibutton->rpc_ctx); } 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)) { key_loaded = true; // TODO: Display an error if the key from p could not be loaded diff --git a/applications/main/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c index d36d3dff..fab1ccf0 100644 --- a/applications/main/ibutton/ibutton_cli.c +++ b/applications/main/ibutton/ibutton_cli.c @@ -6,8 +6,8 @@ #include #include -static void ibutton_cli(Cli* cli, string_t args, void* context); -static void onewire_cli(Cli* cli, string_t args, void* context); +static void ibutton_cli(Cli* cli, FuriString* args, void* context); +static void onewire_cli(Cli* cli, FuriString* args, void* context); // app cli function void ibutton_on_system_start() { @@ -34,16 +34,16 @@ void ibutton_cli_print_usage() { printf("\t 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; - 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; *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; *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; *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); } -void ibutton_cli_write(Cli* cli, string_t args) { +void ibutton_cli_write(Cli* cli, FuriString* args) { iButtonKey* key = ibutton_key_alloc(); iButtonWorker* worker = ibutton_worker_alloc(); iButtonKeyType type; iButtonWriteContext write_context; uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; - string_t data; + FuriString* data; write_context.event = furi_event_flag_alloc(); - string_init(data); + data = furi_string_alloc(); ibutton_worker_start_thread(worker); 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); } while(false); - string_clear(data); + furi_string_free(data); ibutton_worker_stop_thread(worker); ibutton_worker_free(worker); ibutton_key_free(key); @@ -194,14 +194,14 @@ void ibutton_cli_write(Cli* cli, string_t args) { 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(); iButtonWorker* worker = ibutton_worker_alloc(); iButtonKeyType type; 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); do { @@ -234,34 +234,34 @@ void ibutton_cli_emulate(Cli* cli, string_t args) { ibutton_worker_stop(worker); } while(false); - string_clear(data); + furi_string_free(data); ibutton_worker_stop_thread(worker); ibutton_worker_free(worker); 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); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); if(!args_read_string_and_trim(args, cmd)) { - string_clear(cmd); + furi_string_free(cmd); ibutton_cli_print_usage(); return; } - if(string_cmp_str(cmd, "read") == 0) { + if(furi_string_cmp_str(cmd, "read") == 0) { 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); - } else if(string_cmp_str(cmd, "emulate") == 0) { + } else if(furi_string_cmp_str(cmd, "emulate") == 0) { ibutton_cli_emulate(cli, args); } else { ibutton_cli_print_usage(); } - string_clear(cmd); + furi_string_free(cmd); } void onewire_cli_print_usage() { @@ -299,20 +299,20 @@ static void onewire_cli_search(Cli* cli) { 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); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); if(!args_read_string_and_trim(args, cmd)) { - string_clear(cmd); + furi_string_free(cmd); onewire_cli_print_usage(); return; } - if(string_cmp_str(cmd, "search") == 0) { + if(furi_string_cmp_str(cmd, "search") == 0) { onewire_cli_search(cli); } - string_clear(cmd); + furi_string_free(cmd); } diff --git a/applications/main/ibutton/ibutton_i.h b/applications/main/ibutton/ibutton_i.h index fd11b8c1..a9515195 100644 --- a/applications/main/ibutton/ibutton_i.h +++ b/applications/main/ibutton/ibutton_i.h @@ -41,7 +41,7 @@ struct iButton { iButtonWorker* key_worker; iButtonKey* key; - string_t file_path; + FuriString* file_path; char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; Submenu* submenu; @@ -78,7 +78,7 @@ typedef enum { } iButtonNotificationMessage; 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_delete_key(iButton* ibutton); void ibutton_text_store_set(iButton* ibutton, const char* text, ...); diff --git a/applications/main/ibutton/scenes/ibutton_scene_add_type.c b/applications/main/ibutton/scenes/ibutton_scene_add_type.c index 9a0583a5..38373999 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_add_type.c +++ b/applications/main/ibutton/scenes/ibutton_scene_add_type.c @@ -1,5 +1,4 @@ #include "../ibutton_i.h" -#include "m-string.h" enum SubmenuIndex { SubmenuIndexCyfral, @@ -47,7 +46,7 @@ bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) { 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); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c index fccefe6e..3d609e83 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c +++ b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -17,11 +17,11 @@ void ibutton_scene_delete_confirm_on_enter(void* context) { iButtonKey* key = ibutton->key; const uint8_t* key_data = ibutton_key_get_data_p(key); - string_t key_name; - string_init(key_name); + FuriString* key_name; + key_name = furi_string_alloc(); 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, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true); 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); - string_clear(key_name); + furi_string_free(key_name); } bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/ibutton/scenes/ibutton_scene_emulate.c b/applications/main/ibutton/scenes/ibutton_scene_emulate.c index e6e0ec68..b3bc38ea 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_emulate.c +++ b/applications/main/ibutton/scenes/ibutton_scene_emulate.c @@ -20,17 +20,17 @@ void ibutton_scene_emulate_on_enter(void* context) { const uint8_t* key_data = ibutton_key_get_data_p(key); - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + FuriString* key_name; + key_name = furi_string_alloc(); + if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { path_extract_filename(ibutton->file_path, key_name, true); } DOLPHIN_DEED(DolphinDeedIbuttonEmulate); // check that stored key has name - if(!string_empty_p(key_name)) { - ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); + if(!furi_string_empty(key_name)) { + ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); } else { // if not, show key data 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_worker_emulate_start(ibutton->key_worker, key); - string_clear(key_name); + furi_string_free(key_name); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_info.c b/applications/main/ibutton/scenes/ibutton_scene_info.c index 9eec2bee..15648f6f 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_info.c +++ b/applications/main/ibutton/scenes/ibutton_scene_info.c @@ -8,11 +8,11 @@ void ibutton_scene_info_on_enter(void* context) { const uint8_t* key_data = ibutton_key_get_data_p(key); - string_t key_name; - string_init(key_name); + FuriString* key_name; + key_name = furi_string_alloc(); 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, 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); - string_clear(key_name); + furi_string_free(key_name); } bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/ibutton/scenes/ibutton_scene_read.c b/applications/main/ibutton/scenes/ibutton_scene_read.c index 7af351f0..05920a0a 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_read.c +++ b/applications/main/ibutton/scenes/ibutton_scene_read.c @@ -18,7 +18,7 @@ void ibutton_scene_read_on_enter(void* context) { popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); 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_start(worker, key); diff --git a/applications/main/ibutton/scenes/ibutton_scene_rpc.c b/applications/main/ibutton/scenes/ibutton_scene_rpc.c index 0755c8ff..b25b1b8d 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/main/ibutton/scenes/ibutton_scene_rpc.c @@ -29,19 +29,19 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.event == iButtonCustomEventRpcLoad) { const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); bool result = false; - if(arg && (string_empty_p(ibutton->file_path))) { - string_set_str(ibutton->file_path, arg); + if(arg && (furi_string_empty(ibutton->file_path))) { + furi_string_set(ibutton->file_path, arg); if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + FuriString* key_name; + key_name = furi_string_alloc(); + if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { 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, "emulating\n%s", string_get_cstr(key_name)); + ibutton, "emulating\n%s", furi_string_get_cstr(key_name)); } else { 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); - string_clear(key_name); + furi_string_free(key_name); result = true; } else { - string_reset(ibutton->file_path); + furi_string_reset(ibutton->file_path); } } rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result); diff --git a/applications/main/ibutton/scenes/ibutton_scene_save_name.c b/applications/main/ibutton/scenes/ibutton_scene_save_name.c index be640387..773b93e0 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_save_name.c +++ b/applications/main/ibutton/scenes/ibutton_scene_save_name.c @@ -1,5 +1,4 @@ #include "../ibutton_i.h" -#include "m-string.h" #include #include @@ -12,17 +11,17 @@ void ibutton_scene_save_name_on_enter(void* context) { iButton* ibutton = context; TextInput* text_input = ibutton->text_input; - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + FuriString* key_name; + key_name = furi_string_alloc(); + if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { 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) { set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE); } 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"); @@ -34,19 +33,19 @@ void ibutton_scene_save_name_on_enter(void* context) { IBUTTON_KEY_NAME_SIZE, key_name_is_empty); - string_t folder_path; - string_init(folder_path); + FuriString* 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( - 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); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); - string_clear(key_name); - string_clear(folder_path); + furi_string_free(key_name); + furi_string_free(folder_path); } bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/ibutton/scenes/ibutton_scene_start.c b/applications/main/ibutton/scenes/ibutton_scene_start.c index c2844cde..dde224e1 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_start.c +++ b/applications/main/ibutton/scenes/ibutton_scene_start.c @@ -39,7 +39,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexRead) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); } 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); } else if(event.event == SubmenuIndexAdd) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType); diff --git a/applications/main/ibutton/scenes/ibutton_scene_write.c b/applications/main/ibutton/scenes/ibutton_scene_write.c index af65575c..cdea04db 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_write.c +++ b/applications/main/ibutton/scenes/ibutton_scene_write.c @@ -1,5 +1,4 @@ #include "../ibutton_i.h" -#include "m-string.h" #include "toolbox/path.h" 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); - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + FuriString* key_name; + key_name = furi_string_alloc(); + if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { path_extract_filename(ibutton->file_path, key_name, true); } // check that stored key has name - if(!string_empty_p(key_name)) { - ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); + if(!furi_string_empty(key_name)) { + ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); } else { // if not, show key data 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_start(worker, key); - string_clear(key_name); + furi_string_free(key_name); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); } diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared.c index 60809e78..f62db14c 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared.c @@ -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); - string_t base_path; - string_init_set_str(base_path, path); + FuriString* base_path; + base_path = furi_string_alloc_set(path); - if(string_end_with_str_p(base_path, INFRARED_APP_EXTENSION)) { - size_t filename_start = string_search_rchar(base_path, '/'); - string_left(base_path, filename_start); + if(furi_string_end_with(base_path, INFRARED_APP_EXTENSION)) { + size_t filename_start = furi_string_search_rchar(base_path, '/'); + 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 the suggested name is occupied, try another one (name2, name3, etc) */ - size_t dot = string_search_rchar(base_path, '.'); - string_left(base_path, dot); + size_t dot = furi_string_search_rchar(base_path, '.'); + furi_string_left(base_path, dot); - string_t path_temp; - string_init(path_temp); + FuriString* path_temp; + path_temp = furi_string_alloc(); uint32_t i = 1; do { - string_printf( - path_temp, "%s%u%s", string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION); - status = storage_common_stat(storage, string_get_cstr(path_temp), NULL); + furi_string_printf( + path_temp, "%s%lu%s", furi_string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION); + status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL); } while(status == FSE_OK); - string_clear(path_temp); + furi_string_free(path_temp); 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); } static Infrared* infrared_alloc() { Infrared* infrared = malloc(sizeof(Infrared)); - string_init(infrared->file_path); + infrared->file_path = furi_string_alloc(); InfraredAppState* app_state = &infrared->app_state; app_state->is_learning_new_remote = false; @@ -232,7 +233,7 @@ static void infrared_free(Infrared* infrared) { furi_record_close(RECORD_GUI); infrared->gui = NULL; - string_clear(infrared->file_path); + furi_string_free(infrared->file_path); free(infrared); } @@ -243,19 +244,20 @@ bool infrared_add_remote_with_button( InfraredSignal* signal) { InfraredRemote* remote = infrared->remote; - string_t new_name, new_path; - string_init_set_str(new_name, INFRARED_DEFAULT_REMOTE_NAME); - string_init_set_str(new_path, INFRARED_APP_FOLDER); + FuriString *new_name, *new_path; + new_name = furi_string_alloc_set(INFRARED_DEFAULT_REMOTE_NAME); + new_path = furi_string_alloc_set(INFRARED_APP_FOLDER); - infrared_find_vacant_remote_name(new_name, string_get_cstr(new_path)); - string_cat_printf(new_path, "/%s%s", string_get_cstr(new_name), INFRARED_APP_EXTENSION); + infrared_find_vacant_remote_name(new_name, furi_string_get_cstr(new_path)); + furi_string_cat_printf( + new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION); infrared_remote_reset(remote); - infrared_remote_set_name(remote, string_get_cstr(new_name)); - infrared_remote_set_path(remote, string_get_cstr(new_path)); + infrared_remote_set_name(remote, furi_string_get_cstr(new_name)); + infrared_remote_set_path(remote, furi_string_get_cstr(new_path)); - string_clear(new_name); - string_clear(new_path); + furi_string_free(new_name); + furi_string_free(new_path); 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; } - string_t new_name; - string_init_set_str(new_name, name); + FuriString* new_name; + new_name = furi_string_alloc_set(name); infrared_find_vacant_remote_name(new_name, remote_path); - string_t new_path; - string_init_set(new_path, infrared_remote_get_path(remote)); - if(string_end_with_str_p(new_path, INFRARED_APP_EXTENSION)) { - size_t filename_start = string_search_rchar(new_path, '/'); - string_left(new_path, filename_start); + FuriString* new_path; + new_path = furi_string_alloc_set(infrared_remote_get_path(remote)); + if(furi_string_end_with(new_path, INFRARED_APP_EXTENSION)) { + size_t filename_start = furi_string_search_rchar(new_path, '/'); + 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); FS_Error status = storage_common_rename( - storage, infrared_remote_get_path(remote), string_get_cstr(new_path)); - infrared_remote_set_name(remote, string_get_cstr(new_name)); - infrared_remote_set_path(remote, string_get_cstr(new_path)); + storage, infrared_remote_get_path(remote), furi_string_get_cstr(new_path)); + infrared_remote_set_name(remote, furi_string_get_cstr(new_name)); + infrared_remote_set_path(remote, furi_string_get_cstr(new_path)); - string_clear(new_name); - string_clear(new_path); + furi_string_free(new_name); + furi_string_free(new_path); furi_record_close(RECORD_STORAGE); 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); is_rpc_mode = true; } 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); if(!is_remote_loaded) { dialog_message_show_storage_error( diff --git a/applications/main/infrared/infrared_brute_force.c b/applications/main/infrared/infrared_brute_force.c index 0edc5f74..3f426f1d 100644 --- a/applications/main/infrared/infrared_brute_force.c +++ b/applications/main/infrared/infrared_brute_force.c @@ -2,7 +2,6 @@ #include #include -#include #include #include "infrared_signal.h" @@ -14,15 +13,15 @@ typedef struct { DICT_DEF2( InfraredBruteForceRecordDict, - string_t, - STRING_OPLIST, + FuriString*, + FURI_STRING_OPLIST, InfraredBruteForceRecord, M_POD_OPLIST); struct InfraredBruteForce { FlipperFormat* ff; const char* db_filename; - string_t current_record_name; + FuriString* current_record_name; InfraredSignal* current_signal; InfraredBruteForceRecordDict_t records; bool is_started; @@ -34,7 +33,7 @@ InfraredBruteForce* infrared_brute_force_alloc() { brute_force->db_filename = NULL; brute_force->current_signal = NULL; 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); return brute_force; } @@ -42,7 +41,7 @@ InfraredBruteForce* infrared_brute_force_alloc() { void infrared_brute_force_free(InfraredBruteForce* brute_force) { furi_assert(!brute_force->is_started); InfraredBruteForceRecordDict_clear(brute_force->records); - string_clear(brute_force->current_record_name); + furi_string_free(brute_force->current_record_name); 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); if(success) { - string_t signal_name; - string_init(signal_name); + FuriString* signal_name; + signal_name = furi_string_alloc(); while(flipper_format_read_string(ff, "name", signal_name)) { InfraredBruteForceRecord* record = InfraredBruteForceRecordDict_get(brute_force->records, signal_name); @@ -70,7 +69,7 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) { ++(record->count); } } - string_clear(signal_name); + furi_string_free(signal_name); } flipper_format_free(ff); @@ -94,7 +93,7 @@ bool infrared_brute_force_start( if(record->value.index == index) { *record_count = record->value.count; if(*record_count) { - string_set(brute_force->current_record_name, record->key); + furi_string_set(brute_force->current_record_name, record->key); } break; } @@ -118,7 +117,7 @@ bool infrared_brute_force_is_started(InfraredBruteForce* brute_force) { void infrared_brute_force_stop(InfraredBruteForce* brute_force) { 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); flipper_format_free(brute_force->ff); brute_force->current_signal = NULL; @@ -142,10 +141,10 @@ void infrared_brute_force_add_record( uint32_t index, const char* name) { InfraredBruteForceRecord value = {.index = index, .count = 0}; - string_t key; - string_init_set_str(key, name); + FuriString* key; + key = furi_string_alloc_set(name); InfraredBruteForceRecordDict_set_at(brute_force->records, key, value); - string_clear(key); + furi_string_free(key); } void infrared_brute_force_reset(InfraredBruteForce* brute_force) { diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index 693e191e..5ec57c75 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -10,13 +9,13 @@ #define INFRARED_CLI_BUF_SIZE 10 -static void infrared_cli_start_ir_rx(Cli* cli, string_t args); -static void infrared_cli_start_ir_tx(Cli* cli, string_t args); -static void infrared_cli_process_decode(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, FuriString* args); +static void infrared_cli_process_decode(Cli* cli, FuriString* args); static const struct { const char* cmd; - void (*process_function)(Cli* cli, string_t args); + void (*process_function)(Cli* cli, FuriString* args); } infrared_cli_commands[] = { {.cmd = "rx", .process_function = infrared_cli_start_ir_rx}, {.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(args); 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); } -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); - const char* str = string_get_cstr(args); + const char* str = furi_string_get_cstr(args); InfraredSignal* signal = infrared_signal_alloc(); 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(); InfraredDecoderHandler* decoder = infrared_alloc_decoder(); - string_t tmp; - string_init(tmp); + FuriString* tmp; + tmp = furi_string_alloc(); while(infrared_signal_read(signal, input_file, tmp)) { ret = false; @@ -242,7 +241,7 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o } if(!infrared_signal_is_raw(signal)) { 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; } else { 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); - printf("Raw signal: %s, %u samples\r\n", string_get_cstr(tmp), raw_signal->timings_size); - if(!infrared_cli_decode_raw_signal(raw_signal, decoder, output_file, string_get_cstr(tmp))) + printf( + "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; ret = true; } infrared_free_decoder(decoder); infrared_signal_free(signal); - string_clear(tmp); + furi_string_free(tmp); 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); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* input_file = flipper_format_buffered_file_alloc(storage); FlipperFormat* output_file = NULL; uint32_t version; - string_t tmp, header, input_path, output_path; - string_init(tmp); - string_init(header); - string_init(input_path); - string_init(output_path); + FuriString *tmp, *header, *input_path, *output_path; + tmp = furi_string_alloc(); + header = furi_string_alloc(); + input_path = furi_string_alloc(); + output_path = furi_string_alloc(); do { 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; } args_read_probably_quoted_string_and_trim(args, output_path); - if(!flipper_format_buffered_file_open_existing(input_file, string_get_cstr(input_path))) { - printf("Failed to open file for reading: \"%s\"\r\n", string_get_cstr(input_path)); + if(!flipper_format_buffered_file_open_existing( + 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; } if(!flipper_format_read_header(input_file, header, &version) || - (!string_start_with_str_p(header, "IR")) || version != 1) { - printf("Invalid or corrupted input file: \"%s\"\r\n", string_get_cstr(input_path)); + (!furi_string_start_with_str(header, "IR")) || version != 1) { + printf( + "Invalid or corrupted input file: \"%s\"\r\n", furi_string_get_cstr(input_path)); break; } - if(!string_empty_p(output_path)) { - printf("Writing output to file: \"%s\"\r\n", string_get_cstr(output_path)); + if(!furi_string_empty(output_path)) { + printf("Writing output to file: \"%s\"\r\n", furi_string_get_cstr(output_path)); output_file = flipper_format_file_alloc(storage); } if(output_file && - !flipper_format_file_open_always(output_file, string_get_cstr(output_path))) { - printf("Failed to open file for writing: \"%s\"\r\n", 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", furi_string_get_cstr(output_path)); break; } 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; } 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"); } while(false); - string_clear(tmp); - string_clear(header); - string_clear(input_path); - string_clear(output_path); + furi_string_free(tmp); + furi_string_free(header); + furi_string_free(input_path); + furi_string_free(output_path); flipper_format_free(input_file); if(output_file) flipper_format_free(output_file); 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); if(furi_hal_infrared_is_busy()) { printf("INFRARED is busy. Exiting."); return; } - string_t command; - string_init(command); + FuriString* command; + command = furi_string_alloc(); args_read_string_and_trim(args, command); size_t i = 0; for(; i < COUNT_OF(infrared_cli_commands); ++i) { 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; } } @@ -346,7 +353,7 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { infrared_cli_print_usage(); } - string_clear(command); + furi_string_free(command); } void infrared_on_system_start() { #ifdef SRV_CLI diff --git a/applications/main/infrared/infrared_i.h b/applications/main/infrared/infrared_i.h index 95215258..6d25d160 100644 --- a/applications/main/infrared/infrared_i.h +++ b/applications/main/infrared/infrared_i.h @@ -96,7 +96,7 @@ struct Infrared { Loading* loading; InfraredProgressView* progress; - string_t file_path; + FuriString* file_path; char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; InfraredAppState app_state; diff --git a/applications/main/infrared/infrared_remote.c b/applications/main/infrared/infrared_remote.c index 4417c3c7..3a528a65 100644 --- a/applications/main/infrared/infrared_remote.c +++ b/applications/main/infrared/infrared_remote.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -15,8 +14,8 @@ ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST); struct InfraredRemote { InfraredButtonArray_t buttons; - string_t name; - string_t path; + FuriString* name; + FuriString* path; }; 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* remote = malloc(sizeof(InfraredRemote)); InfraredButtonArray_init(remote->buttons); - string_init(remote->name); - string_init(remote->path); + remote->name = furi_string_alloc(); + remote->path = furi_string_alloc(); return remote; } void infrared_remote_free(InfraredRemote* remote) { infrared_remote_clear_buttons(remote); InfraredButtonArray_clear(remote->buttons); - string_clear(remote->path); - string_clear(remote->name); + furi_string_free(remote->path); + furi_string_free(remote->name); free(remote); } void infrared_remote_reset(InfraredRemote* remote) { infrared_remote_clear_buttons(remote); - string_reset(remote->name); - string_reset(remote->path); + furi_string_reset(remote->name); + furi_string_reset(remote->path); } 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) { - return string_get_cstr(remote->name); + return furi_string_get_cstr(remote->name); } 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) { - return string_get_cstr(remote->path); + return furi_string_get_cstr(remote->path); } 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) { Storage* storage = furi_record_open(RECORD_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); @@ -138,33 +137,33 @@ bool infrared_remote_store(InfraredRemote* remote) { 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); FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); - FURI_LOG_I(TAG, "load file: \'%s\'", string_get_cstr(path)); - bool success = flipper_format_buffered_file_open_existing(ff, 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, furi_string_get_cstr(path)); if(success) { uint32_t 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) { path_extract_filename(path, buf, true); infrared_remote_clear_buttons(remote); - infrared_remote_set_name(remote, string_get_cstr(buf)); - infrared_remote_set_path(remote, string_get_cstr(path)); + infrared_remote_set_name(remote, furi_string_get_cstr(buf)); + infrared_remote_set_path(remote, furi_string_get_cstr(path)); for(bool can_read = true; can_read;) { InfraredRemoteButton* button = infrared_remote_button_alloc(); can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf); 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); } else { 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); furi_record_close(RECORD_STORAGE); return success; @@ -181,7 +180,7 @@ bool infrared_remote_load(InfraredRemote* remote, string_t path) { bool infrared_remote_remove(InfraredRemote* remote) { 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); furi_record_close(RECORD_STORAGE); diff --git a/applications/main/infrared/infrared_remote.h b/applications/main/infrared/infrared_remote.h index b6f63a19..6eac193d 100644 --- a/applications/main/infrared/infrared_remote.h +++ b/applications/main/infrared/infrared_remote.h @@ -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_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); diff --git a/applications/main/infrared/infrared_remote_button.c b/applications/main/infrared/infrared_remote_button.c index 7525ce48..1f6315ec 100644 --- a/applications/main/infrared/infrared_remote_button.c +++ b/applications/main/infrared/infrared_remote_button.c @@ -1,32 +1,31 @@ #include "infrared_remote_button.h" #include -#include struct InfraredRemoteButton { - string_t name; + FuriString* name; InfraredSignal* signal; }; InfraredRemoteButton* infrared_remote_button_alloc() { InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton)); - string_init(button->name); + button->name = furi_string_alloc(); button->signal = infrared_signal_alloc(); return button; } void infrared_remote_button_free(InfraredRemoteButton* button) { - string_clear(button->name); + furi_string_free(button->name); infrared_signal_free(button->signal); free(button); } 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) { - return string_get_cstr(button->name); + return furi_string_get_cstr(button->name); } void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal) { diff --git a/applications/main/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c index f2e359c8..d399b958 100644 --- a/applications/main/infrared/infrared_signal.c +++ b/applications/main/infrared/infrared_signal.c @@ -61,7 +61,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) { if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) { FURI_LOG_E( TAG, - "Frequency is out of range (%lX - %lX): %lX", + "Frequency is out of range (%X - %X): %lX", INFRARED_MIN_FREQUENCY, INFRARED_MAX_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)) { FURI_LOG_E( TAG, - "Timings amount is out of range (0 - %lX): %lX", + "Timings amount is out of range (0 - %X): %X", MAX_TIMINGS_AMOUNT, raw->timings_size); 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) { - string_t buf; - string_init(buf); + FuriString* buf; + buf = furi_string_alloc(); bool success = false; do { if(!flipper_format_read_string(ff, "protocol", buf)) break; 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) && 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); } while(0); - string_clear(buf); + furi_string_free(buf); 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) { - string_t tmp; - string_init(tmp); + FuriString* tmp = furi_string_alloc(); + bool success = false; do { 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); - } else if(string_equal_p(tmp, "parsed")) { + } else if(furi_string_equal(tmp, "parsed")) { success = infrared_signal_read_message(signal, ff); } else { FURI_LOG_E(TAG, "Unknown signal type"); } } while(false); - string_clear(tmp); + furi_string_free(tmp); 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) { - string_t tmp; - string_init(tmp); +bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) { + FuriString* tmp = furi_string_alloc(); + bool success = false; do { 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; success = true; } while(0); - string_clear(tmp); + furi_string_free(tmp); return success; } bool infrared_signal_search_and_read( InfraredSignal* signal, FlipperFormat* ff, - const string_t name) { + const FuriString* name) { bool success = false; - string_t tmp; - string_init(tmp); + FuriString* tmp = furi_string_alloc(); do { bool is_name_found = false; 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; @@ -281,7 +280,7 @@ bool infrared_signal_search_and_read( success = true; } while(false); - string_clear(tmp); + furi_string_free(tmp); return success; } diff --git a/applications/main/infrared/infrared_signal.h b/applications/main/infrared/infrared_signal.h index ad2f5d57..29c66193 100644 --- a/applications/main/infrared/infrared_signal.h +++ b/applications/main/infrared/infrared_signal.h @@ -36,10 +36,10 @@ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* InfraredMessage* infrared_signal_get_message(InfraredSignal* signal); 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( InfraredSignal* signal, FlipperFormat* ff, - const string_t name); + const FuriString* name); void infrared_signal_transmit(InfraredSignal* signal); diff --git a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c index f823ca93..d55d8d0a 100644 --- a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c +++ b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c @@ -70,7 +70,7 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e uint32_t record_count; if(infrared_brute_force_start( 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); } else { scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases); diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename.c b/applications/main/infrared/scenes/infrared_scene_edit_rename.c index ebe7c2a9..a2199215 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_rename.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_rename.c @@ -29,20 +29,20 @@ void infrared_scene_edit_rename_on_enter(void* context) { enter_name_length = INFRARED_MAX_REMOTE_NAME_LENGTH; strncpy(infrared->text_store[0], infrared_remote_get_name(remote), enter_name_length); - string_t folder_path; - string_init(folder_path); + FuriString* folder_path; + folder_path = furi_string_alloc(); - if(string_end_with_str_p(infrared->file_path, INFRARED_APP_EXTENSION)) { - path_extract_dirname(string_get_cstr(infrared->file_path), folder_path); + if(furi_string_end_with(infrared->file_path, INFRARED_APP_EXTENSION)) { + path_extract_dirname(furi_string_get_cstr(infrared->file_path), folder_path); } ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(folder_path), + furi_string_get_cstr(folder_path), INFRARED_APP_EXTENSION, infrared_remote_get_name(remote)); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - string_clear(folder_path); + furi_string_free(folder_path); } else { furi_assert(0); } diff --git a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c index b7f4179e..b6a7eac0 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c @@ -50,8 +50,10 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e if(success) { scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); } else { - scene_manager_search_and_switch_to_previous_scene( - scene_manager, InfraredSceneRemoteList); + dialog_message_show_storage_error(infrared->dialogs, "Failed to save file"); + 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; } diff --git a/applications/main/infrared/scenes/infrared_scene_rpc.c b/applications/main/infrared/scenes/infrared_scene_rpc.c index ca7bbd8d..8044e831 100644 --- a/applications/main/infrared/scenes/infrared_scene_rpc.c +++ b/applications/main/infrared/scenes/infrared_scene_rpc.c @@ -42,7 +42,7 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { bool result = false; const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); 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); if(result) { scene_manager_set_scene_state( diff --git a/applications/main/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c index d188a6c3..c7df0f45 100644 --- a/applications/main/infrared/scenes/infrared_scene_start.c +++ b/applications/main/infrared/scenes/infrared_scene_start.c @@ -66,7 +66,7 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(scene_manager, InfraredSceneLearn); consumed = true; } 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); consumed = true; } else if(submenu_index == SubmenuIndexDebug) { diff --git a/applications/main/infrared/views/infrared_progress_view.c b/applications/main/infrared/views/infrared_progress_view.c index 5c84ce0d..3c50f89e 100644 --- a/applications/main/infrared/views/infrared_progress_view.c +++ b/applications/main/infrared/views/infrared_progress_view.c @@ -4,7 +4,6 @@ #include "gui/canvas.h" #include "gui/view.h" #include "input/input.h" -#include "m-string.h" #include #include #include "infrared_progress_view.h" diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index dbed9f3a..b0f98937 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -36,9 +36,9 @@ static LfRfid* lfrfid_alloc() { lfrfid->storage = furi_record_open(RECORD_STORAGE); lfrfid->dialogs = furi_record_open(RECORD_DIALOGS); - string_init(lfrfid->file_name); - string_init(lfrfid->raw_file_name); - string_init_set_str(lfrfid->file_path, LFRFID_APP_FOLDER); + lfrfid->file_name = furi_string_alloc(); + lfrfid->raw_file_name = furi_string_alloc(); + lfrfid->file_path = furi_string_alloc_set(LFRFID_APP_FOLDER); lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); @@ -104,9 +104,9 @@ static LfRfid* lfrfid_alloc() { static void lfrfid_free(LfRfid* lfrfid) { furi_assert(lfrfid); - string_clear(lfrfid->raw_file_name); - string_clear(lfrfid->file_name); - string_clear(lfrfid->file_path); + furi_string_free(lfrfid->raw_file_name); + furi_string_free(lfrfid->file_name); + furi_string_free(lfrfid->file_path); protocol_dict_free(lfrfid->dict); lfrfid_worker_free(lfrfid->lfworker); @@ -183,7 +183,7 @@ int32_t lfrfid_app(void* p) { app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc); } else { - string_set_str(app->file_path, args); + furi_string_set(app->file_path, args); lfrfid_load_key_data(app, app->file_path, true); view_dispatcher_attach_to_gui( app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); @@ -210,13 +210,13 @@ bool lfrfid_save_key(LfRfid* app) { lfrfid_make_app_folder(app); - if(string_end_with_str_p(app->file_path, LFRFID_APP_EXTENSION)) { - size_t filename_start = string_search_rchar(app->file_path, '/'); - string_left(app->file_path, filename_start); + if(furi_string_end_with(app->file_path, LFRFID_APP_EXTENSION)) { + size_t filename_start = furi_string_search_rchar(app->file_path, '/'); + furi_string_left(app->file_path, filename_start); } - string_cat_printf( - app->file_path, "/%s%s", string_get_cstr(app->file_name), LFRFID_APP_EXTENSION); + furi_string_cat_printf( + app->file_path, "/%s%s", furi_string_get_cstr(app->file_name), LFRFID_APP_EXTENSION); result = lfrfid_save_key_data(app, app->file_path); return result; @@ -242,14 +242,14 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) { bool lfrfid_delete_key(LfRfid* 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; 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; 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; } -bool lfrfid_save_key_data(LfRfid* app, string_t path) { - bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, string_get_cstr(path)); +bool lfrfid_save_key_data(LfRfid* app, FuriString* path) { + bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, furi_string_get_cstr(path)); if(!result) { dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file"); diff --git a/applications/main/lfrfid/lfrfid_cli.c b/applications/main/lfrfid/lfrfid_cli.c index 281a0e96..64027452 100644 --- a/applications/main/lfrfid/lfrfid_cli.c +++ b/applications/main/lfrfid/lfrfid_cli.c @@ -14,7 +14,7 @@ #include #include -static void lfrfid_cli(Cli* cli, string_t args, void* context); +static void lfrfid_cli(Cli* cli, FuriString* args, void* context); // app cli function 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); } -static void lfrfid_cli_read(Cli* cli, string_t args) { - string_t type_string; - string_init(type_string); +static void lfrfid_cli_read(Cli* cli, FuriString* args) { + FuriString* type_string; + type_string = furi_string_alloc(); LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto; 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 type = LFRFIDWorkerReadTypeASKOnly; } else if( - string_cmp_str(type_string, "indala") == 0 || - string_cmp_str(type_string, "psk") == 0) { + furi_string_cmp_str(type_string, "indala") == 0 || + furi_string_cmp_str(type_string, "psk") == 0) { // psk type = LFRFIDWorkerReadTypePSKOnly; } else { lfrfid_cli_print_usage(); - string_clear(type_string); + furi_string_free(type_string); return; } } - string_clear(type_string); + furi_string_free(type_string); ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); LFRFIDWorker* worker = lfrfid_worker_alloc(dict); @@ -111,13 +112,13 @@ static void lfrfid_cli_read(Cli* cli, string_t args) { printf("\r\n"); free(data); - string_t info; - string_init(info); + FuriString* info; + info = furi_string_alloc(); protocol_dict_render_data(dict, info, context.protocol); - if(!string_empty_p(info)) { - printf("%s\r\n", string_get_cstr(info)); + if(!furi_string_empty(info)) { + printf("%s\r\n", furi_string_get_cstr(info)); } - string_clear(info); + furi_string_free(info); } 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); } -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; - string_t protocol_name, data_text; - string_init(protocol_name); - string_init(data_text); + FuriString *protocol_name, *data_text; + protocol_name = furi_string_alloc(); + data_text = furi_string_alloc(); size_t data_size = protocol_dict_get_max_data_size(dict); 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 - *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) { printf( "Unknown protocol: %s\r\n" "Available protocols:\r\n", - string_get_cstr(protocol_name)); + furi_string_get_cstr(protocol_name)); for(ProtocolId i = 0; i < LFRFIDProtocolMax; i++) { printf( @@ -177,8 +178,8 @@ static bool lfrfid_cli_parse_args(string_t args, ProtocolDict* dict, ProtocolId* } while(false); free(data); - string_clear(protocol_name); - string_clear(data_text); + furi_string_free(protocol_name); + furi_string_free(data_text); return result; } @@ -188,7 +189,7 @@ static void lfrfid_cli_write_callback(LFRFIDWorkerWriteResult result, void* ctx) 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); ProtocolId protocol; @@ -235,7 +236,7 @@ static void lfrfid_cli_write(Cli* cli, string_t args) { 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); ProtocolId protocol; @@ -261,11 +262,11 @@ static void lfrfid_cli_emulate(Cli* cli, string_t args) { 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); - string_t filepath, info_string; - string_init(filepath); - string_init(info_string); + FuriString *filepath, *info_string; + filepath = furi_string_alloc(); + info_string = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage); @@ -278,7 +279,7 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) { 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"); break; } @@ -308,10 +309,10 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) { warn = true; } - string_printf(info_string, "[%ld %ld]", pulse, duration); - printf("%-16s", string_get_cstr(info_string)); - string_printf(info_string, "[%ld %ld]", pulse, duration - pulse); - printf("%-16s", string_get_cstr(info_string)); + furi_string_printf(info_string, "[%ld %ld]", pulse, duration); + printf("%-16s", furi_string_get_cstr(info_string)); + furi_string_printf(info_string, "[%ld %ld]", pulse, duration - pulse); + printf("%-16s", furi_string_get_cstr(info_string)); if(warn) { printf(" <<----"); @@ -366,7 +367,7 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) { printf("]\r\n"); 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); } else { @@ -376,8 +377,8 @@ static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) { protocol_dict_free(dict); } while(false); - string_clear(filepath); - string_clear(info_string); + furi_string_free(filepath); + furi_string_free(info_string); lfrfid_raw_file_free(file); 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); } -static void lfrfid_cli_raw_read(Cli* cli, string_t args) { +static void lfrfid_cli_raw_read(Cli* cli, FuriString* args) { UNUSED(cli); - string_t filepath, type_string; - string_init(filepath); - string_init(type_string); + FuriString *filepath, *type_string; + filepath = furi_string_alloc(); + type_string = furi_string_alloc(); LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto; do { 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 type = LFRFIDWorkerReadTypeASKOnly; } else if( - string_cmp_str(type_string, "indala") == 0 || - string_cmp_str(type_string, "psk") == 0) { + furi_string_cmp_str(type_string, "indala") == 0 || + furi_string_cmp_str(type_string, "psk") == 0) { // psk type = LFRFIDWorkerReadTypePSKOnly; } else { @@ -430,7 +431,7 @@ static void lfrfid_cli_raw_read(Cli* cli, string_t args) { (1 << LFRFIDWorkerReadRawOverrun); 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) { 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); - string_clear(filepath); - string_clear(type_string); + furi_string_free(filepath); + furi_string_free(type_string); } 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); } -static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) { +static void lfrfid_cli_raw_emulate(Cli* cli, FuriString* args) { UNUSED(cli); - string_t filepath; - string_init(filepath); + FuriString* filepath; + filepath = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); do { @@ -488,8 +489,8 @@ static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) { break; } - if(!storage_file_exists(storage, string_get_cstr(filepath))) { - printf("File not found: \"%s\"\r\n", string_get_cstr(filepath)); + if(!storage_file_exists(storage, furi_string_get_cstr(filepath))) { + printf("File not found: \"%s\"\r\n", furi_string_get_cstr(filepath)); break; } @@ -505,7 +506,7 @@ static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) { (1 << LFRFIDWorkerEmulateRawOverrun); 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) { 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); 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); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); if(!args_read_string_and_trim(args, cmd)) { - string_clear(cmd); + furi_string_free(cmd); lfrfid_cli_print_usage(); return; } - if(string_cmp_str(cmd, "read") == 0) { + if(furi_string_cmp_str(cmd, "read") == 0) { 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); - } else if(string_cmp_str(cmd, "emulate") == 0) { + } else if(furi_string_cmp_str(cmd, "emulate") == 0) { 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); - } 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); - } 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); } else { lfrfid_cli_print_usage(); } - string_clear(cmd); + furi_string_free(cmd); } \ No newline at end of file diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h index 77e87252..71917c0c 100644 --- a/applications/main/lfrfid/lfrfid_i.h +++ b/applications/main/lfrfid/lfrfid_i.h @@ -1,7 +1,5 @@ #pragma once -#include "m-string.h" - #include #include @@ -86,9 +84,9 @@ struct LfRfid { Widget* widget; char text_store[LFRFID_TEXT_STORE_SIZE + 1]; - string_t file_path; - string_t file_name; - string_t raw_file_name; + FuriString* file_path; + FuriString* file_name; + FuriString* raw_file_name; ProtocolDict* dict; ProtocolId protocol_id; @@ -128,9 +126,9 @@ bool lfrfid_load_key_from_file_select(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); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c b/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c index dc1c3df2..b7702e26 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c @@ -4,31 +4,31 @@ void lfrfid_scene_delete_confirm_on_enter(void* context) { LfRfid* app = context; Widget* widget = app->widget; - string_t tmp_string; - string_init(tmp_string); + FuriString* tmp_string; + tmp_string = furi_string_alloc(); widget_add_button_element(widget, GuiButtonTypeLeft, "Back", 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, 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); uint8_t* data = (uint8_t*)malloc(size); protocol_dict_get_data(app->dict, app->protocol_id, data, size); for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) { 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); 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, 64, @@ -39,7 +39,7 @@ void lfrfid_scene_delete_confirm_on_enter(void* context) { protocol_dict_get_name(app->dict, app->protocol_id)); 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) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c index 70cc2418..2725982f 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c @@ -8,8 +8,8 @@ void lfrfid_scene_emulate_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedRfidEmulate); popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop); - if(!string_empty_p(app->file_name)) { - popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); + if(!furi_string_empty(app->file_name)) { + popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); } else { popup_set_text( popup, diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c index 43e3de99..d7fd93e1 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c @@ -42,7 +42,7 @@ void lfrfid_scene_extra_actions_on_enter(void* context) { submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions)); // clear key - string_reset(app->file_name); + furi_string_reset(app->file_name); app->protocol_id = PROTOCOL_NO; app->read_type = LFRFIDWorkerReadTypeAuto; diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c index f60dd624..e5193521 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c @@ -4,8 +4,8 @@ void lfrfid_scene_raw_info_on_enter(void* context) { LfRfid* app = context; Widget* widget = app->widget; - // string_t tmp_string; - // string_init(tmp_string); + // FuriString* tmp_string; + // tmp_string = furi_string_alloc(); bool sd_exist = storage_sd_status(app->storage) == FSE_OK; if(!sd_exist) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c index 512f9ee4..3e09dbf0 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c @@ -4,9 +4,9 @@ void lfrfid_scene_raw_name_on_enter(void* context) { LfRfid* app = context; 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) { lfrfid_text_store_set(app, "RfidRecord"); } else { @@ -38,7 +38,7 @@ bool lfrfid_scene_raw_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == LfRfidEventNext) { 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); } } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c index d0c03ffa..b2c7c364 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c @@ -3,7 +3,7 @@ #define RAW_READ_TIME 5000 typedef struct { - string_t string_file_name; + FuriString* string_file_name; FuriTimer* timer; bool is_psk; bool error; @@ -31,7 +31,7 @@ void lfrfid_scene_raw_read_on_enter(void* context) { LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState)); 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); 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); furi_timer_start(state->timer, RAW_READ_TIME); - string_printf( + furi_string_printf( state->string_file_name, "%s/%s%s", LFRFID_SD_FOLDER, - string_get_cstr(app->raw_file_name), + furi_string_get_cstr(app->raw_file_name), LFRFID_APP_RAW_ASK_EXTENSION); popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop); lfrfid_worker_read_raw_start( app->lfworker, - string_get_cstr(state->string_file_name), + furi_string_get_cstr(state->string_file_name), LFRFIDWorkerReadTypeASKOnly, lfrfid_read_callback, 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); notification_message(app->notifications, &sequence_blink_start_yellow); lfrfid_worker_stop(app->lfworker); - string_printf( + furi_string_printf( state->string_file_name, "%s/%s%s", LFRFID_SD_FOLDER, - string_get_cstr(app->raw_file_name), + furi_string_get_cstr(app->raw_file_name), LFRFID_APP_RAW_PSK_EXTENSION); lfrfid_worker_read_raw_start( app->lfworker, - string_get_cstr(state->string_file_name), + furi_string_get_cstr(state->string_file_name), LFRFIDWorkerReadTypePSKOnly, lfrfid_read_callback, app); @@ -121,6 +121,6 @@ void lfrfid_scene_raw_read_on_exit(void* context) { lfrfid_worker_stop_thread(app->lfworker); furi_timer_free(state->timer); - string_clear(state->string_file_name); + furi_string_free(state->string_file_name); free(state); } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read.c b/applications/main/lfrfid/scenes/lfrfid_scene_read.c index 66168038..4bdb215d 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_read.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read.c @@ -81,7 +81,7 @@ bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) { app->protocol_id = app->protocol_id_next; DOLPHIN_DEED(DolphinDeedRfidReadSuccess); 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); consumed = true; } else if(event.event == LfRfidEventReadStartPSK) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c b/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c index 221cc008..7480304b 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c @@ -38,7 +38,7 @@ bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite); consumed = true; } else if(event.event == SubmenuIndexSave) { - string_reset(app->file_name); + furi_string_reset(app->file_name); scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName); consumed = true; } else if(event.event == SubmenuIndexEmulate) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c index 5ae6f0f1..b83ef4a3 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c @@ -4,51 +4,51 @@ void lfrfid_scene_read_success_on_enter(void* context) { LfRfid* app = context; Widget* widget = app->widget; - string_t tmp_string; - string_init(tmp_string); + FuriString* tmp_string; + tmp_string = furi_string_alloc(); widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app); widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app); - string_printf( + furi_string_printf( tmp_string, "%s[%s]", protocol_dict_get_name(app->dict, app->protocol_id), protocol_dict_get_manufacturer(app->dict, app->protocol_id)); 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); uint8_t* data = (uint8_t*)malloc(size); protocol_dict_get_data(app->dict, app->protocol_id, data, size); for(uint8_t i = 0; i < size; i++) { if(i >= 9) { - string_cat_printf(tmp_string, ".."); + furi_string_cat_printf(tmp_string, ".."); break; } else { 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); - string_t render_data; - string_init(render_data); + FuriString* render_data; + render_data = furi_string_alloc(); 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)); - string_clear(render_data); + furi_string_cat_printf(tmp_string, "\r\n%s", furi_string_get_cstr(render_data)); + furi_string_free(render_data); 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); 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) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c index a69d6453..156dd97a 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c @@ -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); bool result = false; 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)) { lfrfid_worker_start_thread(app->lfworker); lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); 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); notification_message(app->notifications, &sequence_blink_start_magenta); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c index 2ca1bb43..6c5ea2f2 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c @@ -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); - if(need_restore) { - protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size); - } else { + if(!need_restore) { 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_result_callback( @@ -41,6 +38,8 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) { } } else if(event.type == SceneManagerEventTypeBack) { 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; diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c index febf30a4..ca9a52de 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c @@ -1,21 +1,20 @@ -#include "m-string.h" #include #include "../lfrfid_i.h" void lfrfid_scene_save_name_on_enter(void* context) { LfRfid* app = context; TextInput* text_input = app->text_input; - string_t folder_path; - string_init(folder_path); + FuriString* folder_path; + folder_path = furi_string_alloc(); - 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) { - string_set_str(app->file_path, LFRFID_APP_FOLDER); + furi_string_set(app->file_path, LFRFID_APP_FOLDER); set_random_name(app->text_store, LFRFID_TEXT_STORE_SIZE); - string_set_str(folder_path, LFRFID_APP_FOLDER); + furi_string_set(folder_path, LFRFID_APP_FOLDER); } else { - lfrfid_text_store_set(app, "%s", string_get_cstr(app->file_name)); - path_extract_dirname(string_get_cstr(app->file_path), folder_path); + lfrfid_text_store_set(app, "%s", furi_string_get_cstr(app->file_name)); + path_extract_dirname(furi_string_get_cstr(app->file_path), folder_path); } text_input_set_header_text(text_input, "Name the card"); @@ -27,13 +26,15 @@ void lfrfid_scene_save_name_on_enter(void* context) { LFRFID_KEY_NAME_SIZE, key_name_is_empty); - FURI_LOG_I("", "%s %s", string_get_cstr(folder_path), app->text_store); + FURI_LOG_I("", "%s %s", furi_string_get_cstr(folder_path), app->text_store); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(folder_path), LFRFID_APP_EXTENSION, string_get_cstr(app->file_name)); + furi_string_get_cstr(folder_path), + LFRFID_APP_EXTENSION, + furi_string_get_cstr(app->file_name)); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - string_clear(folder_path); + furi_string_free(folder_path); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput); } @@ -46,11 +47,11 @@ bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == LfRfidEventNext) { consumed = true; - if(!string_empty_p(app->file_name)) { + if(!furi_string_empty(app->file_name)) { lfrfid_delete_key(app); } - string_set_str(app->file_name, app->text_store); + furi_string_set(app->file_name, app->text_store); if(lfrfid_save_key(app)) { scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c index 830ef336..e91ad04e 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c @@ -5,6 +5,9 @@ void lfrfid_scene_save_success_on_enter(void* context) { LfRfid* app = context; Popup* popup = app->popup; + // Clear state of data enter scene + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0); + DOLPHIN_DEED(DolphinDeedRfidSave); popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c index 4c111600..0ba51f06 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c @@ -1,7 +1,7 @@ #include "../lfrfid_i.h" typedef struct { - string_t menu_item_name[LFRFIDProtocolMax]; + FuriString* menu_item_name[LFRFIDProtocolMax]; uint32_t line_sel; } SaveTypeCtx; @@ -20,18 +20,17 @@ void lfrfid_scene_save_type_on_enter(void* context) { if(strcmp( protocol_dict_get_manufacturer(app->dict, i), protocol_dict_get_name(app->dict, i)) != 0) { - string_init_printf( - state->menu_item_name[i], + state->menu_item_name[i] = furi_string_alloc_printf( "%s %s", protocol_dict_get_manufacturer(app->dict, i), protocol_dict_get_name(app->dict, i)); } else { - string_init_printf( - state->menu_item_name[i], "%s", protocol_dict_get_name(app->dict, i)); + state->menu_item_name[i] = + furi_string_alloc_printf("%s", protocol_dict_get_name(app->dict, i)); } submenu_add_item( submenu, - string_get_cstr(state->menu_item_name[i]), + furi_string_get_cstr(state->menu_item_name[i]), i, lfrfid_scene_save_type_submenu_callback, app); @@ -43,7 +42,7 @@ void lfrfid_scene_save_type_on_enter(void* context) { scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, (uint32_t)state); // clear key name - string_reset(app->file_name); + furi_string_reset(app->file_name); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); } @@ -75,7 +74,7 @@ void lfrfid_scene_save_type_on_exit(void* context) { submenu_reset(app->submenu); for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) { - string_clear(state->menu_item_name[i]); + furi_string_free(state->menu_item_name[i]); } uint32_t line_sel = state->line_sel; diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c b/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c index 1496c6b4..3f1c2d40 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c @@ -4,13 +4,13 @@ void lfrfid_scene_saved_info_on_enter(void* context) { LfRfid* app = context; Widget* widget = app->widget; - string_t tmp_string; - string_init(tmp_string); + FuriString* tmp_string; + tmp_string = furi_string_alloc(); - string_printf( + furi_string_printf( tmp_string, "%s [%s]\r\n", - string_get_cstr(app->file_name), + furi_string_get_cstr(app->file_name), protocol_dict_get_name(app->dict, app->protocol_id)); size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); @@ -18,24 +18,24 @@ void lfrfid_scene_saved_info_on_enter(void* context) { protocol_dict_get_data(app->dict, app->protocol_id, data, size); for(uint8_t i = 0; i < size; i++) { 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); - string_t render_data; - string_init(render_data); + FuriString* render_data; + render_data = furi_string_alloc(); protocol_dict_render_data(app->dict, render_data, app->protocol_id); - string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data)); - string_clear(render_data); + furi_string_cat_printf(tmp_string, "\r\n%s", furi_string_get_cstr(render_data)); + furi_string_free(render_data); widget_add_string_multiline_element( - widget, 0, 1, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string)); + widget, 0, 1, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp_string)); view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); - string_clear(tmp_string); + furi_string_free(tmp_string); } bool lfrfid_scene_saved_info_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_start.c b/applications/main/lfrfid/scenes/lfrfid_scene_start.c index 9074e859..d6d87f44 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_start.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_start.c @@ -33,7 +33,7 @@ void lfrfid_scene_start_on_enter(void* context) { submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneStart)); // clear key - string_reset(app->file_name); + furi_string_reset(app->file_name); app->protocol_id = PROTOCOL_NO; app->read_type = LFRFIDWorkerReadTypeAuto; @@ -49,7 +49,7 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); consumed = true; } else if(event.event == SubmenuIndexSaved) { - string_set_str(app->file_path, LFRFID_APP_FOLDER); + furi_string_set(app->file_path, LFRFID_APP_FOLDER); scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey); consumed = true; } else if(event.event == SubmenuIndexAddManually) { diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_write.c b/applications/main/lfrfid/scenes/lfrfid_scene_write.c index 8e791d52..b7faed69 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_write.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_write.c @@ -22,8 +22,8 @@ void lfrfid_scene_write_on_enter(void* context) { Popup* popup = app->popup; popup_set_header(popup, "Writing", 89, 30, AlignCenter, AlignTop); - if(!string_empty_p(app->file_name)) { - popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); + if(!furi_string_empty(app->file_name)) { + popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); } else { popup_set_text( popup, diff --git a/applications/main/lfrfid/views/lfrfid_view_read.c b/applications/main/lfrfid/views/lfrfid_view_read.c index 66caf8df..0d4db617 100644 --- a/applications/main/lfrfid/views/lfrfid_view_read.c +++ b/applications/main/lfrfid/views/lfrfid_view_read.c @@ -56,19 +56,13 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) { void lfrfid_view_read_enter(void* context) { LfRfidReadView* read_view = context; with_view_model( - read_view->view, (LfRfidReadViewModel * model) { - icon_animation_start(model->icon); - return true; - }); + read_view->view, LfRfidReadViewModel * model, { icon_animation_start(model->icon); }, true); } void lfrfid_view_read_exit(void* context) { LfRfidReadView* read_view = context; with_view_model( - read_view->view, (LfRfidReadViewModel * model) { - icon_animation_stop(model->icon); - return false; - }); + read_view->view, LfRfidReadViewModel * model, { icon_animation_stop(model->icon); }, false); } LfRfidReadView* lfrfid_view_read_alloc() { @@ -78,11 +72,13 @@ LfRfidReadView* lfrfid_view_read_alloc() { view_allocate_model(read_view->view, ViewModelTypeLocking, sizeof(LfRfidReadViewModel)); with_view_model( - read_view->view, (LfRfidReadViewModel * model) { + read_view->view, + LfRfidReadViewModel * model, + { model->icon = icon_animation_alloc(&A_Round_loader_8x8); view_tie_icon_animation(read_view->view, model->icon); - return false; - }); + }, + false); view_set_draw_callback(read_view->view, lfrfid_view_read_draw_callback); view_set_enter_callback(read_view->view, lfrfid_view_read_enter); @@ -93,10 +89,7 @@ LfRfidReadView* lfrfid_view_read_alloc() { void lfrfid_view_read_free(LfRfidReadView* read_view) { with_view_model( - read_view->view, (LfRfidReadViewModel * model) { - icon_animation_free(model->icon); - return false; - }); + read_view->view, LfRfidReadViewModel * model, { icon_animation_free(model->icon); }, false); view_free(read_view->view); free(read_view); @@ -108,10 +101,12 @@ View* lfrfid_view_read_get_view(LfRfidReadView* read_view) { void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode) { with_view_model( - read_view->view, (LfRfidReadViewModel * model) { + read_view->view, + LfRfidReadViewModel * model, + { icon_animation_stop(model->icon); icon_animation_start(model->icon); model->read_mode = mode; - return true; - }); + }, + true); } diff --git a/applications/main/nfc/helpers/nfc_emv_parser.c b/applications/main/nfc/helpers/nfc_emv_parser.c index 0d7cb5a3..30e10240 100644 --- a/applications/main/nfc/helpers/nfc_emv_parser.c +++ b/applications/main/nfc/helpers/nfc_emv_parser.c @@ -7,12 +7,12 @@ static const uint32_t nfc_resources_file_version = 1; static bool nfc_emv_parser_search_data( Storage* storage, const char* file_name, - string_t key, - string_t data) { + FuriString* key, + FuriString* data) { bool parsed = false; FlipperFormat* file = flipper_format_file_alloc(storage); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { // Open file @@ -20,14 +20,14 @@ static bool nfc_emv_parser_search_data( // Read file header and version uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, nfc_resources_header) || + if(furi_string_cmp_str(temp_str, nfc_resources_header) || (version != nfc_resources_file_version)) break; - if(!flipper_format_read_string(file, string_get_cstr(key), data)) break; + if(!flipper_format_read_string(file, furi_string_get_cstr(key), data)) break; parsed = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return parsed; } @@ -36,47 +36,47 @@ bool nfc_emv_parser_get_aid_name( Storage* storage, uint8_t* aid, uint8_t aid_len, - string_t aid_name) { + FuriString* aid_name) { furi_assert(storage); bool parsed = false; - string_t key; - string_init(key); + FuriString* key; + key = furi_string_alloc(); for(uint8_t i = 0; i < aid_len; i++) { - string_cat_printf(key, "%02X", aid[i]); + furi_string_cat_printf(key, "%02X", aid[i]); } if(nfc_emv_parser_search_data(storage, EXT_PATH("nfc/assets/aid.nfc"), key, aid_name)) { parsed = true; } - string_clear(key); + furi_string_free(key); return parsed; } bool nfc_emv_parser_get_country_name( Storage* storage, uint16_t country_code, - string_t country_name) { + FuriString* country_name) { bool parsed = false; - string_t key; - string_init_printf(key, "%04X", country_code); + FuriString* key; + key = furi_string_alloc_printf("%04X", country_code); if(nfc_emv_parser_search_data( storage, EXT_PATH("nfc/assets/country_code.nfc"), key, country_name)) { parsed = true; } - string_clear(key); + furi_string_free(key); return parsed; } bool nfc_emv_parser_get_currency_name( Storage* storage, uint16_t currency_code, - string_t currency_name) { + FuriString* currency_name) { bool parsed = false; - string_t key; - string_init_printf(key, "%04X", currency_code); + FuriString* key; + key = furi_string_alloc_printf("%04X", currency_code); if(nfc_emv_parser_search_data( storage, EXT_PATH("nfc/assets/currency_code.nfc"), key, currency_name)) { parsed = true; } - string_clear(key); + furi_string_free(key); return parsed; } diff --git a/applications/main/nfc/helpers/nfc_emv_parser.h b/applications/main/nfc/helpers/nfc_emv_parser.h index 5948ed34..abe57f47 100644 --- a/applications/main/nfc/helpers/nfc_emv_parser.h +++ b/applications/main/nfc/helpers/nfc_emv_parser.h @@ -2,7 +2,6 @@ #include #include -#include #include /** Get EMV application name by number @@ -16,7 +15,7 @@ bool nfc_emv_parser_get_aid_name( Storage* storage, uint8_t* aid, uint8_t aid_len, - string_t aid_name); + FuriString* aid_name); /** Get country name by country code * @param storage Storage instance @@ -27,7 +26,7 @@ bool nfc_emv_parser_get_aid_name( bool nfc_emv_parser_get_country_name( Storage* storage, uint16_t country_code, - string_t country_name); + FuriString* country_name); /** Get currency name by currency code * @param storage Storage instance @@ -38,4 +37,4 @@ bool nfc_emv_parser_get_country_name( bool nfc_emv_parser_get_currency_name( Storage* storage, uint16_t currency_code, - string_t currency_name); + FuriString* currency_name); diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index f47a5bac..0b685f54 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -83,7 +83,7 @@ Nfc* nfc_alloc() { nfc->text_box = text_box_alloc(); view_dispatcher_add_view( nfc->view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box)); - string_init(nfc->text_box_store); + nfc->text_box_store = furi_string_alloc(); // Custom Widget nfc->widget = widget_alloc(); @@ -153,7 +153,7 @@ void nfc_free(Nfc* nfc) { // TextBox view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewTextBox); text_box_free(nfc->text_box); - string_clear(nfc->text_box_store); + furi_string_free(nfc->text_box_store); // Custom Widget view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget); @@ -277,6 +277,8 @@ int32_t nfc_app(void* p) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 4ac95f04..a6475ca6 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -17,7 +17,7 @@ static void nfc_cli_print_usage() { } } -static void nfc_cli_detect(Cli* cli, string_t args) { +static void nfc_cli_detect(Cli* cli, FuriString* args) { UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { @@ -46,7 +46,7 @@ static void nfc_cli_detect(Cli* cli, string_t args) { furi_hal_nfc_sleep(); } -static void nfc_cli_emulate(Cli* cli, string_t args) { +static void nfc_cli_emulate(Cli* cli, FuriString* args) { UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { @@ -76,7 +76,7 @@ static void nfc_cli_emulate(Cli* cli, string_t args) { furi_hal_nfc_sleep(); } -static void nfc_cli_field(Cli* cli, string_t args) { +static void nfc_cli_field(Cli* cli, FuriString* args) { UNUSED(args); // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { @@ -98,27 +98,27 @@ static void nfc_cli_field(Cli* cli, string_t args) { furi_hal_nfc_sleep(); } -static void nfc_cli(Cli* cli, string_t args, void* context) { +static void nfc_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { nfc_cli_print_usage(); break; } - if(string_cmp_str(cmd, "detect") == 0) { + if(furi_string_cmp_str(cmd, "detect") == 0) { nfc_cli_detect(cli, args); break; } - if(string_cmp_str(cmd, "emulate") == 0) { + if(furi_string_cmp_str(cmd, "emulate") == 0) { nfc_cli_emulate(cli, args); break; } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(string_cmp_str(cmd, "field") == 0) { + if(furi_string_cmp_str(cmd, "field") == 0) { nfc_cli_field(cli, args); break; } @@ -127,7 +127,7 @@ static void nfc_cli(Cli* cli, string_t args, void* context) { nfc_cli_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } void nfc_on_system_start() { diff --git a/applications/main/nfc/nfc_i.h b/applications/main/nfc/nfc_i.h index 15ea5348..fa5b54ed 100644 --- a/applications/main/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -62,7 +62,7 @@ struct Nfc { FuriHalNfcDevData dev_edit_data; char text_store[NFC_TEXT_STORE_SIZE + 1]; - string_t text_box_store; + FuriString* text_box_store; uint8_t byte_input_store[6]; MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing diff --git a/applications/main/nfc/scenes/nfc_scene_delete.c b/applications/main/nfc/scenes/nfc_scene_delete.c index 987927e1..cbb52bfd 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete.c +++ b/applications/main/nfc/scenes/nfc_scene_delete.c @@ -12,40 +12,40 @@ void nfc_scene_delete_on_enter(void* context) { FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; // Setup Custom Widget view - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); - string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name); + furi_string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name); widget_add_text_box_element( - nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, string_get_cstr(temp_str), false); + nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, furi_string_get_cstr(temp_str), false); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Cancel", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); - string_set_str(temp_str, "UID:"); + furi_string_set(temp_str, "UID:"); for(size_t i = 0; i < nfc_data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } widget_add_string_element( - nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); + nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); NfcProtocol protocol = nfc->dev->dev_data.protocol; if(protocol == NfcDeviceProtocolEMV) { - string_set_str(temp_str, "EMV bank card"); + furi_string_set(temp_str, "EMV bank card"); } else if(protocol == NfcDeviceProtocolMifareUl) { - string_set_str(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true)); + furi_string_set(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true)); } else if(protocol == NfcDeviceProtocolMifareClassic) { - string_set_str(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type)); + furi_string_set(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type)); } else if(protocol == NfcDeviceProtocolMifareDesfire) { - string_set_str(temp_str, "MIFARE DESFire"); + furi_string_set(temp_str, "MIFARE DESFire"); } else { - string_set_str(temp_str, "Unknown ISO tag"); + furi_string_set(temp_str, "Unknown ISO tag"); } widget_add_string_element( - nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); + nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A"); - string_clear(temp_str); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/main/nfc/scenes/nfc_scene_detect_reader.c b/applications/main/nfc/scenes/nfc_scene_detect_reader.c index 5f4582d8..f0177f9c 100644 --- a/applications/main/nfc/scenes/nfc_scene_detect_reader.c +++ b/applications/main/nfc/scenes/nfc_scene_detect_reader.c @@ -1,6 +1,15 @@ #include "../nfc_i.h" #include +#define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U) + +static const NotificationSequence sequence_detect_reader = { + &message_green_255, + &message_blue_255, + &message_do_not_reset, + NULL, +}; + bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) { UNUSED(event); furi_assert(context); @@ -17,24 +26,29 @@ void nfc_scene_detect_reader_callback(void* context) { void nfc_scene_detect_reader_on_enter(void* context) { Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcEmulate); + DOLPHIN_DEED(DolphinDeedNfcDetectReader); detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc); + detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX); + + // Store number of collected nonces in scene state + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0); + notification_message(nfc->notifications, &sequence_detect_reader); + nfc_worker_start( nfc->worker, NfcWorkerStateAnalyzeReader, &nfc->dev->dev_data, nfc_detect_reader_worker_callback, nfc); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader); - - nfc_blink_read_start(nfc); } bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; + uint32_t nonces_collected = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader); if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { @@ -42,8 +56,29 @@ bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyNoncesInfo); consumed = true; } else if(event.event == NfcWorkerEventDetectReaderMfkeyCollected) { - detect_reader_inc_nonce_cnt(nfc->detect_reader); + nonces_collected += 2; + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, nonces_collected); + detect_reader_set_nonces_collected(nfc->detect_reader, nonces_collected); + if(nonces_collected >= NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + detect_reader_set_state(nfc->detect_reader, DetectReaderStateDone); + nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_single_vibro); + notification_message(nfc->notifications, &sequence_set_green_255); + nfc_worker_stop(nfc->worker); + } consumed = true; + } else if(event.event == NfcWorkerEventDetectReaderDetected) { + if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + notification_message(nfc->notifications, &sequence_blink_start_cyan); + detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderDetected); + } + } else if(event.event == NfcWorkerEventDetectReaderLost) { + if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_detect_reader); + detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderLost); + } } } @@ -59,5 +94,7 @@ void nfc_scene_detect_reader_on_exit(void* context) { // Clear view detect_reader_reset(nfc->detect_reader); + // Stop notifications nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_reset_green); } diff --git a/applications/main/nfc/scenes/nfc_scene_device_info.c b/applications/main/nfc/scenes/nfc_scene_device_info.c index 245aea5c..9780ffe4 100644 --- a/applications/main/nfc/scenes/nfc_scene_device_info.c +++ b/applications/main/nfc/scenes/nfc_scene_device_info.c @@ -12,49 +12,52 @@ void nfc_scene_device_info_on_enter(void* context) { Nfc* nfc = context; NfcDeviceData* dev_data = &nfc->dev->dev_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); if(dev_data->protocol == NfcDeviceProtocolEMV) { EmvData* emv_data = &dev_data->emv_data; - string_printf(temp_str, "\e#%s\n", emv_data->name); + furi_string_printf(temp_str, "\e#%s\n", emv_data->name); for(uint8_t i = 0; i < emv_data->number_len; i += 2) { - string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + furi_string_cat_printf( + temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); } - string_strim(temp_str); + furi_string_trim(temp_str); // Add expiration date if(emv_data->exp_mon) { - string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); + furi_string_cat_printf( + temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } // Parse currency code if((emv_data->currency_code)) { - string_t currency_name; - string_init(currency_name); + FuriString* currency_name; + currency_name = furi_string_alloc(); if(nfc_emv_parser_get_currency_name( nfc->dev->storage, emv_data->currency_code, currency_name)) { - string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); + furi_string_cat_printf( + temp_str, "\nCur: %s ", furi_string_get_cstr(currency_name)); } - string_clear(currency_name); + furi_string_free(currency_name); } // Parse country code if((emv_data->country_code)) { - string_t country_name; - string_init(country_name); + FuriString* country_name; + country_name = furi_string_alloc(); if(nfc_emv_parser_get_country_name( nfc->dev->storage, emv_data->country_code, country_name)) { - string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); + furi_string_cat_printf(temp_str, "Reg: %s", furi_string_get_cstr(country_name)); } - string_clear(country_name); + furi_string_free(country_name); } } else if( dev_data->protocol == NfcDeviceProtocolMifareClassic || dev_data->protocol == NfcDeviceProtocolMifareUl) { - string_set(temp_str, nfc->dev->dev_data.parsed_data); + furi_string_set(temp_str, nfc->dev->dev_data.parsed_data); } - widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "More", nfc_scene_device_info_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c index f6402301..8bb20796 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -35,22 +35,22 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; widget_reset(widget); - string_t info_str; - string_init(info_str); + FuriString* info_str; + info_str = furi_string_alloc(); widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); widget_add_string_element(widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Emulating UID"); if(strcmp(nfc->dev->dev_name, "")) { - string_printf(info_str, "%s", nfc->dev->dev_name); + furi_string_printf(info_str, "%s", nfc->dev->dev_name); } else { for(uint8_t i = 0; i < data->uid_len; i++) { - string_cat_printf(info_str, "%02X ", data->uid[i]); + furi_string_cat_printf(info_str, "%02X ", data->uid[i]); } } - string_strim(info_str); + furi_string_trim(info_str); widget_add_text_box_element( - widget, 56, 43, 70, 21, AlignCenter, AlignTop, string_get_cstr(info_str), true); - string_clear(info_str); + widget, 56, 43, 70, 21, AlignCenter, AlignTop, furi_string_get_cstr(info_str), true); + furi_string_free(info_str); if(data_received) { widget_add_button_element( widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_uid_widget_callback, nfc); @@ -67,7 +67,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) { TextBox* text_box = nfc->text_box; text_box_set_font(text_box, TextBoxFontHex); text_box_set_focus(text_box, TextBoxFocusEnd); - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); // Set Widget state and view scene_manager_set_scene_state( @@ -94,17 +94,17 @@ bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { // Add data button to widget if data is received for the first time - if(!string_size(nfc->text_box_store)) { + if(!furi_string_size(nfc->text_box_store)) { nfc_scene_emulate_uid_widget_config(nfc, true); } // Update TextBox data - if(string_size(nfc->text_box_store) < NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX) { - string_cat_printf(nfc->text_box_store, "R:"); + if(furi_string_size(nfc->text_box_store) < NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX) { + furi_string_cat_printf(nfc->text_box_store, "R:"); for(uint16_t i = 0; i < reader_data->size; i++) { - string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); + furi_string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); } - string_push_back(nfc->text_box_store, '\n'); - text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store)); + furi_string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, furi_string_get_cstr(nfc->text_box_store)); } memset(reader_data, 0, sizeof(NfcReaderRequestData)); consumed = true; @@ -140,7 +140,7 @@ void nfc_scene_emulate_uid_on_exit(void* context) { // Clear view widget_reset(nfc->widget); text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); nfc_blink_stop(nfc); } diff --git a/applications/main/nfc/scenes/nfc_scene_emv_menu.c b/applications/main/nfc/scenes/nfc_scene_emv_menu.c index 1da630fc..eb1e1004 100644 --- a/applications/main/nfc/scenes/nfc_scene_emv_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_emv_menu.c @@ -1,7 +1,6 @@ #include "../nfc_i.h" enum SubmenuIndex { - SubmenuIndexSave, SubmenuIndexInfo, }; @@ -15,7 +14,6 @@ void nfc_scene_emv_menu_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; - submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_emv_menu_submenu_callback, nfc); submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_emv_menu_submenu_callback, nfc); submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMenu)); @@ -28,13 +26,7 @@ bool nfc_scene_emv_menu_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSave) { - nfc->dev->format = NfcDeviceSaveFormatBankCard; - // Clear device name - nfc_device_set_name(nfc->dev, ""); - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - consumed = true; - } else if(event.event == SubmenuIndexInfo) { + if(event.event == SubmenuIndexInfo) { scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); consumed = true; } diff --git a/applications/main/nfc/scenes/nfc_scene_emv_read_success.c b/applications/main/nfc/scenes/nfc_scene_emv_read_success.c index a40b4c1c..6a0b32fa 100644 --- a/applications/main/nfc/scenes/nfc_scene_emv_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_emv_read_success.c @@ -23,42 +23,65 @@ void nfc_scene_emv_read_success_on_enter(void* context) { widget_add_button_element( nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc); - string_t temp_str; - string_init_printf(temp_str, "\e#%s\n", emv_data->name); - for(uint8_t i = 0; i < emv_data->number_len; i += 2) { - string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + FuriString* temp_str; + if(emv_data->name[0] != '\0') { + temp_str = furi_string_alloc_printf("\e#%s\n", emv_data->name); + } else { + temp_str = furi_string_alloc_printf("\e#Unknown Bank Card\n"); + } + if(emv_data->number_len) { + for(uint8_t i = 0; i < emv_data->number_len; i += 2) { + furi_string_cat_printf( + temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + } + furi_string_trim(temp_str); + } else if(emv_data->aid_len) { + furi_string_cat_printf(temp_str, "Can't parse data from app\n"); + // Parse AID name + FuriString* aid_name; + aid_name = furi_string_alloc(); + if(nfc_emv_parser_get_aid_name( + nfc->dev->storage, emv_data->aid, emv_data->aid_len, aid_name)) { + furi_string_cat_printf(temp_str, "AID: %s", furi_string_get_cstr(aid_name)); + } else { + furi_string_cat_printf(temp_str, "AID: "); + for(uint8_t i = 0; i < emv_data->aid_len; i++) { + furi_string_cat_printf(temp_str, "%02X", emv_data->aid[i]); + } + } + furi_string_free(aid_name); } - string_strim(temp_str); // Add expiration date if(emv_data->exp_mon) { - string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); + furi_string_cat_printf( + temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } // Parse currency code if((emv_data->currency_code)) { - string_t currency_name; - string_init(currency_name); + FuriString* currency_name; + currency_name = furi_string_alloc(); if(nfc_emv_parser_get_currency_name( nfc->dev->storage, emv_data->currency_code, currency_name)) { - string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); + furi_string_cat_printf(temp_str, "\nCur: %s ", furi_string_get_cstr(currency_name)); } - string_clear(currency_name); + furi_string_free(currency_name); } // Parse country code if((emv_data->country_code)) { - string_t country_name; - string_init(country_name); + FuriString* country_name; + country_name = furi_string_alloc(); if(nfc_emv_parser_get_country_name( nfc->dev->storage, emv_data->country_code, country_name)) { - string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); + furi_string_cat_printf(temp_str, "Reg: %s", furi_string_get_cstr(country_name)); } - string_clear(country_name); + furi_string_free(country_name); } notification_message_block(nfc->notifications, &sequence_set_green_255); - widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/main/nfc/scenes/nfc_scene_generate_info.c b/applications/main/nfc/scenes/nfc_scene_generate_info.c index 7fb7eb94..66900767 100644 --- a/applications/main/nfc/scenes/nfc_scene_generate_info.c +++ b/applications/main/nfc/scenes/nfc_scene_generate_info.c @@ -16,15 +16,15 @@ void nfc_scene_generate_info_on_enter(void* context) { dialog_ex_set_right_button_text(dialog_ex, "More"); // Create info text - string_t info_str; - string_init_printf( - info_str, "%s\n%s\nUID:", nfc->generator->name, nfc_get_dev_type(data->type)); + FuriString* info_str = furi_string_alloc_printf( + "%s\n%s\nUID:", nfc->generator->name, nfc_get_dev_type(data->type)); + // Append UID for(int i = 0; i < data->uid_len; ++i) { - string_cat_printf(info_str, " %02X", data->uid[i]); + furi_string_cat_printf(info_str, " %02X", data->uid[i]); } - nfc_text_store_set(nfc, string_get_cstr(info_str)); - string_clear(info_str); + nfc_text_store_set(nfc, furi_string_get_cstr(info_str)); + furi_string_free(info_str); dialog_ex_set_text(dialog_ex, nfc->text_store, 0, 0, AlignLeft, AlignTop); dialog_ex_set_context(dialog_ex, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index b23f4b8f..81354690 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -91,6 +91,7 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); nfc_blink_read_start(nfc); + notification_message(nfc->notifications, &sequence_display_backlight_enforce_on); } bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) { @@ -167,4 +168,5 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { } dict_attack_reset(nfc->dict_attack); nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_display_backlight_enforce_auto); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c index 16a189da..0ea3f59a 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c @@ -16,8 +16,8 @@ void nfc_scene_mf_classic_keys_delete_on_enter(void* context) { uint32_t key_index = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete); // Setup Custom Widget view - string_t key_str; - string_init(key_str); + FuriString* key_str; + key_str = furi_string_alloc(); widget_add_string_element( nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?"); @@ -36,9 +36,15 @@ void nfc_scene_mf_classic_keys_delete_on_enter(void* context) { mf_classic_dict_get_key_at_index_str(dict, key_str, key_index); widget_add_string_element( - nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str)); + nfc->widget, + 64, + 32, + AlignCenter, + AlignCenter, + FontSecondary, + furi_string_get_cstr(key_str)); - string_clear(key_str); + furi_string_free(key_str); mf_classic_dict_free(dict); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c index 6670ae13..19d2f556 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c @@ -19,19 +19,19 @@ void nfc_scene_mf_classic_keys_list_popup_callback(void* context) { void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) { Submenu* submenu = nfc->submenu; uint32_t index = 0; - string_t temp_key; - string_init(temp_key); + FuriString* temp_key; + temp_key = furi_string_alloc(); submenu_set_header(submenu, "Select key to delete:"); while(mf_classic_dict_get_next_key_str(dict, temp_key)) { char* current_key = (char*)malloc(sizeof(char) * 13); - strncpy(current_key, string_get_cstr(temp_key), 12); + strncpy(current_key, furi_string_get_cstr(temp_key), 12); MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); - FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); + FURI_LOG_D("ListKeys", "Key %ld: %s", index, current_key); submenu_add_item( submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc); } - string_clear(temp_key); + furi_string_free(temp_key); } void nfc_scene_mf_classic_keys_list_on_enter(void* context) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c index 76d02e01..2cba0433 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include enum SubmenuIndex { SubmenuIndexSave, @@ -35,6 +36,8 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { + DOLPHIN_DEED(DolphinDeedNfcMfcAdd); + scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexSave); nfc->dev->format = NfcDeviceSaveFormatMifareClassic; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c index 3ca24416..0cdb8646 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c @@ -27,26 +27,26 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc); - string_t temp_str; - if(string_size(nfc->dev->dev_data.parsed_data)) { - string_init_set(temp_str, nfc->dev->dev_data.parsed_data); + FuriString* temp_str; + if(furi_string_size(nfc->dev->dev_data.parsed_data)) { + temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data); } else { - string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type)); - string_cat_printf(temp_str, "UID:"); + temp_str = furi_string_alloc_printf("\e#%s\n", nfc_mf_classic_type(mf_data->type)); + furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { - string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]); + furi_string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]); } uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); uint8_t keys_total = sectors_total * 2; uint8_t keys_found = 0; uint8_t sectors_read = 0; mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); - string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total); - string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total); + furi_string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total); + furi_string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total); } - widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); notification_message_block(nfc->notifications, &sequence_set_green_255); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c index dd842464..afc5f0de 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -84,7 +84,7 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { } else { MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); TextBox* text_box = nfc->text_box; - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); if(event.event == SubmenuIndexAppInfo) { mf_df_cat_application_info(app, nfc->text_box_store); } else { @@ -98,7 +98,7 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { } mf_df_cat_file(file, nfc->text_box_store); } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store)); scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); consumed = true; @@ -120,6 +120,6 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) { // Clear views popup_reset(nfc->popup); text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); submenu_reset(nfc->submenu); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c index 0019a084..e619d037 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c @@ -67,10 +67,10 @@ bool nfc_scene_mf_desfire_data_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { TextBox* text_box = nfc->text_box; - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); if(event.event == SubmenuIndexCardInfo) { mf_df_cat_card_info(data, nfc->text_box_store); - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); scene_manager_set_scene_state( nfc->scene_manager, @@ -102,6 +102,6 @@ void nfc_scene_mf_desfire_data_on_exit(void* context) { // Clear views text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); submenu_reset(nfc->submenu); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c index 12047c15..2ab0355c 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -20,20 +20,19 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) { Widget* widget = nfc->widget; // Prepare string for data display - string_t temp_str; - string_init_printf(temp_str, "\e#MIFARE DESfire\n"); - string_cat_printf(temp_str, "UID:"); + FuriString* temp_str = furi_string_alloc_printf("\e#MIFARE DESfire\n"); + furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < nfc_data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; - string_cat_printf(temp_str, "\n%d", bytes_total); + furi_string_cat_printf(temp_str, "\n%ld", bytes_total); if(data->version.sw_storage & 1) { - string_push_back(temp_str, '+'); + furi_string_push_back(temp_str, '+'); } - string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); + furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; @@ -43,20 +42,20 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) { n_files++; } } - string_cat_printf(temp_str, "%d Application", n_apps); + furi_string_cat_printf(temp_str, "%d Application", n_apps); if(n_apps != 1) { - string_push_back(temp_str, 's'); + furi_string_push_back(temp_str, 's'); } - string_cat_printf(temp_str, ", %d file", n_files); + furi_string_cat_printf(temp_str, ", %d file", n_files); if(n_files != 1) { - string_push_back(temp_str, 's'); + furi_string_push_back(temp_str, 's'); } notification_message_block(nfc->notifications, &sequence_set_green_255); // Add text scroll element - widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); // Add button elements widget_add_button_element( diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c index d4184a6b..8cd223ee 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c @@ -8,11 +8,11 @@ void nfc_scene_mf_ultralight_data_on_enter(void* context) { text_box_set_font(text_box, TextBoxFontHex); for(uint16_t i = 0; i < data->data_size; i += 2) { if(!(i % 8) && i) { - string_push_back(nfc->text_box_store, '\n'); + furi_string_push_back(nfc->text_box_store, '\n'); } - string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]); + furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]); } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); } @@ -28,5 +28,5 @@ void nfc_scene_mf_ultralight_data_on_exit(void* context) { // Clean view text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); + furi_string_reset(nfc->text_box_store); } \ No newline at end of file diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c index b9421545..5a690a21 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c @@ -14,15 +14,14 @@ void nfc_scene_mf_ultralight_read_auth_result_widget_callback( void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) { Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup dialog view FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(mf_ul_data); Widget* widget = nfc->widget; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); if((mf_ul_data->data_read == mf_ul_data->data_size) && (mf_ul_data->data_read > 0)) { widget_add_string_element( @@ -31,14 +30,15 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) { widget_add_string_element( widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Not all pages unlocked!"); } - string_set_str(temp_str, "UID:"); + furi_string_set(temp_str, "UID:"); for(size_t i = 0; i < nfc_data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } widget_add_string_element( - widget, 0, 17, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); + widget, 0, 17, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); if(mf_ul_data->auth_success) { - string_printf( + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + furi_string_printf( temp_str, "Password: %02X %02X %02X %02X", config_pages->auth_data.pwd.raw[0], @@ -46,19 +46,21 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) { config_pages->auth_data.pwd.raw[2], config_pages->auth_data.pwd.raw[3]); widget_add_string_element( - widget, 0, 28, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); - string_printf( + widget, 0, 28, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); + furi_string_printf( temp_str, "PACK: %02X %02X", config_pages->auth_data.pack.raw[0], config_pages->auth_data.pack.raw[1]); widget_add_string_element( - widget, 0, 39, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); + widget, 0, 39, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); + } else { + DOLPHIN_DEED(DolphinDeedNfcMfulError); } - string_printf( + furi_string_printf( temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); widget_add_string_element( - widget, 0, 50, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); + widget, 0, 50, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(temp_str)); widget_add_button_element( widget, GuiButtonTypeRight, @@ -66,7 +68,7 @@ void nfc_scene_mf_ultralight_read_auth_result_on_enter(void* context) { nfc_scene_mf_ultralight_read_auth_result_widget_callback, nfc); - string_clear(temp_str); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c index f6dc5984..77034ea8 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c @@ -33,23 +33,23 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { nfc_scene_mf_ultralight_read_success_widget_callback, nfc); - string_t temp_str; - if(string_size(nfc->dev->dev_data.parsed_data)) { - string_init_set(temp_str, nfc->dev->dev_data.parsed_data); + FuriString* temp_str; + if(furi_string_size(nfc->dev->dev_data.parsed_data)) { + temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data); } else { - string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); - string_cat_printf(temp_str, "UID:"); + temp_str = furi_string_alloc_printf("\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); + furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); } - string_cat_printf( + furi_string_cat_printf( temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); if(mf_ul_data->data_read != mf_ul_data->data_size) { - string_cat_printf(temp_str, "\nPassword-protected pages!"); + furi_string_cat_printf(temp_str, "\nPassword-protected pages!"); } } - widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); notification_message_block(nfc->notifications, &sequence_set_green_255); diff --git a/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c b/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c index b45b690d..6d9852f3 100644 --- a/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c +++ b/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c @@ -11,21 +11,21 @@ void nfc_scene_mfkey_nonces_info_callback(GuiButtonType result, InputType type, void nfc_scene_mfkey_nonces_info_on_enter(void* context) { Nfc* nfc = context; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint16_t nonces_saved = mfkey32_get_auth_sectors(temp_str); - widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, string_get_cstr(temp_str)); - string_printf(temp_str, "Nonces saved %d", nonces_saved); + widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, furi_string_get_cstr(temp_str)); + furi_string_printf(temp_str, "Nonce pairs saved: %d", nonces_saved); widget_add_string_element( - nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, string_get_cstr(temp_str)); + nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(temp_str)); widget_add_string_element( nfc->widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Authenticated sectors:"); widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Next", nfc_scene_mfkey_nonces_info_callback, nfc); + nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_nonces_info_callback, nfc); - string_clear(temp_str); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -35,7 +35,7 @@ bool nfc_scene_mfkey_nonces_info_on_event(void* context, SceneManagerEvent event bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeRight) { + if(event.event == GuiButtonTypeCenter) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyComplete); consumed = true; } diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c index 33f5e44a..8f33972e 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -22,47 +22,48 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { text_scroll_height = 64; } - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); // Set name if present if(nfc->dev->dev_name[0] != '\0') { - string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name); + furi_string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name); } // Set tag type if(protocol == NfcDeviceProtocolEMV) { - string_cat_printf(temp_str, "\e#EMV Bank Card\n"); + furi_string_cat_printf(temp_str, "\e#EMV Bank Card\n"); } else if(protocol == NfcDeviceProtocolMifareUl) { - string_cat_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); + furi_string_cat_printf( + temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); } else if(protocol == NfcDeviceProtocolMifareClassic) { - string_cat_printf( + furi_string_cat_printf( temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type)); } else if(protocol == NfcDeviceProtocolMifareDesfire) { - string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); + furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); } else { - string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); + furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); } // Set tag iso data char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; - string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); - string_cat_printf(temp_str, "UID:"); + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < nfc_data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } - string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); - string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); + furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); // Set application specific data if(protocol == NfcDeviceProtocolMifareDesfire) { MifareDesfireData* data = &dev_data->mf_df_data; uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; - string_cat_printf(temp_str, "\n%d", bytes_total); + furi_string_cat_printf(temp_str, "\n%ld", bytes_total); if(data->version.sw_storage & 1) { - string_push_back(temp_str, '+'); + furi_string_push_back(temp_str, '+'); } - string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); + furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; @@ -72,20 +73,20 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { n_files++; } } - string_cat_printf(temp_str, "%d Application", n_apps); + furi_string_cat_printf(temp_str, "%d Application", n_apps); if(n_apps != 1) { - string_push_back(temp_str, 's'); + furi_string_push_back(temp_str, 's'); } - string_cat_printf(temp_str, ", %d file", n_files); + furi_string_cat_printf(temp_str, ", %d file", n_files); if(n_files != 1) { - string_push_back(temp_str, 's'); + furi_string_push_back(temp_str, 's'); } } else if(protocol == NfcDeviceProtocolMifareUl) { MfUltralightData* data = &dev_data->mf_ul_data; - string_cat_printf( + furi_string_cat_printf( temp_str, "\nPages Read %d/%d", data->data_read / 4, data->data_size / 4); if(data->data_size > data->data_read) { - string_cat_printf(temp_str, "\nPassword-protected"); + furi_string_cat_printf(temp_str, "\nPassword-protected"); } } else if(protocol == NfcDeviceProtocolMifareClassic) { MfClassicData* data = &dev_data->mf_classic_data; @@ -94,14 +95,14 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { uint8_t keys_found = 0; uint8_t sectors_read = 0; mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); - string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total); - string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total); + furi_string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total); + furi_string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total); } // Add text scroll widget widget_add_text_scroll_element( - widget, 0, 0, 128, text_scroll_height, string_get_cstr(temp_str)); - string_clear(temp_str); + widget, 0, 0, 128, text_scroll_height, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c index c695da24..2ea7c992 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c @@ -22,22 +22,22 @@ void nfc_scene_nfca_read_success_on_enter(void* context) { FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; - string_t temp_str; - string_init_set_str(temp_str, "\e#Unknown ISO tag\n"); + FuriString* temp_str; + temp_str = furi_string_alloc_set("\e#Unknown ISO tag\n"); notification_message_block(nfc->notifications, &sequence_set_green_255); char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; - string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); - string_cat_printf(temp_str, "UID:"); + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); } - string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); - string_cat_printf(temp_str, " SAK: %02X", data->sak); + furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X", data->sak); - widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); - string_clear(temp_str); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfca_read_success_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_read_card_success.c b/applications/main/nfc/scenes/nfc_scene_read_card_success.c index 0cb38cbd..352cb4a7 100644 --- a/applications/main/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/main/nfc/scenes/nfc_scene_read_card_success.c @@ -16,26 +16,26 @@ void nfc_scene_read_card_success_widget_callback( void nfc_scene_read_card_success_on_enter(void* context) { Nfc* nfc = context; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup view FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; - string_set_str(temp_str, nfc_get_dev_type(data->type)); + furi_string_set(temp_str, nfc_get_dev_type(data->type)); widget_add_string_element( - widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(temp_str)); - string_set_str(temp_str, "UID:"); + widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, furi_string_get_cstr(temp_str)); + furi_string_set(temp_str, "UID:"); for(uint8_t i = 0; i < data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", data->uid[i]); + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); } widget_add_string_element( - widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(temp_str)); + widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(temp_str)); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc); - string_clear(temp_str); + furi_string_free(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/main/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index d5e05472..736eab7d 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "m-string.h" #include #include #include @@ -31,22 +30,22 @@ void nfc_scene_save_name_on_enter(void* context) { NFC_DEV_NAME_MAX_LEN, dev_name_empty); - string_t folder_path; - string_init(folder_path); + FuriString* folder_path; + folder_path = furi_string_alloc(); - if(string_end_with_str_p(nfc->dev->load_path, NFC_APP_EXTENSION)) { - path_extract_dirname(string_get_cstr(nfc->dev->load_path), folder_path); + if(furi_string_end_with(nfc->dev->load_path, NFC_APP_EXTENSION)) { + path_extract_dirname(furi_string_get_cstr(nfc->dev->load_path), folder_path); } else { - string_set_str(folder_path, NFC_APP_FOLDER); + furi_string_set(folder_path, NFC_APP_FOLDER); } ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name); + furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); - string_clear(folder_path); + furi_string_free(folder_path); } bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index c1043b3a..fe65b5b8 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -20,8 +20,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { Submenu* submenu = nfc->submenu; if(nfc->dev->format == NfcDeviceSaveFormatUid || - nfc->dev->format == NfcDeviceSaveFormatMifareDesfire || - nfc->dev->format == NfcDeviceSaveFormatBankCard) { + nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { submenu_add_item( submenu, "Emulate UID", diff --git a/applications/main/nfc/scenes/nfc_scene_set_type.c b/applications/main/nfc/scenes/nfc_scene_set_type.c index ec6d1144..3e08aeb3 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_type.c +++ b/applications/main/nfc/scenes/nfc_scene_set_type.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "m-string.h" #include "../helpers/nfc_generators.h" enum SubmenuIndex { @@ -19,7 +18,7 @@ void nfc_scene_set_type_on_enter(void* context) { Submenu* submenu = nfc->submenu; // Clear device name nfc_device_set_name(nfc->dev, ""); - string_set_str(nfc->dev->load_path, ""); + furi_string_set(nfc->dev->load_path, ""); submenu_add_item( submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc); submenu_add_item( diff --git a/applications/main/nfc/scenes/nfc_scene_set_uid.c b/applications/main/nfc/scenes/nfc_scene_set_uid.c index 0ff28971..9622ba21 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_set_uid.c @@ -30,7 +30,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { - DOLPHIN_DEED(DolphinDeedNfcAdd); + DOLPHIN_DEED(DolphinDeedNfcAddSave); if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) { diff --git a/applications/main/nfc/views/detect_reader.c b/applications/main/nfc/views/detect_reader.c index 177c13f7..2dbb4338 100644 --- a/applications/main/nfc/views/detect_reader.c +++ b/applications/main/nfc/views/detect_reader.c @@ -10,29 +10,50 @@ struct DetectReader { typedef struct { uint16_t nonces; + uint16_t nonces_max; + DetectReaderState state; } DetectReaderViewModel; static void detect_reader_draw_callback(Canvas* canvas, void* model) { DetectReaderViewModel* m = model; char text[32] = {}; - snprintf(text, sizeof(text), "Tap the reader several times"); - canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Tap the reader several times"); + // Draw header and icon + canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34); + if(m->state == DetectReaderStateStart) { + snprintf(text, sizeof(text), "Touch the reader"); + canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); + } else if(m->state == DetectReaderStateReaderDetected) { + snprintf(text, sizeof(text), "Move the Flipper away"); + canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15); + } else if(m->state == DetectReaderStateReaderLost) { + snprintf(text, sizeof(text), "Touch the reader again"); + canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); + } - if(m->nonces == 0) { + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, text); + + // Draw collected nonces + if(m->state == DetectReaderStateStart) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 52, 22, AlignLeft, AlignTop, "Emulating..."); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Emulating..."); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 52, 35, AlignLeft, AlignTop, "MIFARE Classic"); - canvas_draw_icon(canvas, 0, 13, &I_Tap_reader_36x38); + canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, "MIFARE MFkey32"); } else { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 54, 22, AlignLeft, AlignTop, "Collecting..."); + if(m->state == DetectReaderStateDone) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!"); + } else { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting..."); + } canvas_set_font(canvas, FontSecondary); - snprintf(text, sizeof(text), "Nonces: %d", m->nonces); - canvas_draw_str_aligned(canvas, 54, 35, AlignLeft, AlignTop, text); - elements_button_right(canvas, "Next"); - canvas_draw_icon(canvas, 6, 15, &I_ArrowC_1_36x36); + snprintf(text, sizeof(text), "Nonce pairs: %d/%d", m->nonces, m->nonces_max); + canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, text); + } + // Draw button + if(m->nonces > 0) { + elements_button_center(canvas, "Done"); } } @@ -43,13 +64,10 @@ static bool detect_reader_input_callback(InputEvent* event, void* context) { uint8_t nonces = 0; with_view_model( - detect_reader->view, (DetectReaderViewModel * model) { - nonces = model->nonces; - return false; - }); + detect_reader->view, DetectReaderViewModel * model, { nonces = model->nonces; }, false); if(event->type == InputTypeShort) { - if(event->key == InputKeyRight) { + if(event->key == InputKeyOk) { if(nonces > 0) { detect_reader->callback(detect_reader->context); consumed = true; @@ -82,10 +100,14 @@ void detect_reader_reset(DetectReader* detect_reader) { furi_assert(detect_reader); with_view_model( - detect_reader->view, (DetectReaderViewModel * model) { + detect_reader->view, + DetectReaderViewModel * model, + { model->nonces = 0; - return false; - }); + model->nonces_max = 0; + model->state = DetectReaderStateStart; + }, + false); } View* detect_reader_get_view(DetectReader* detect_reader) { @@ -105,11 +127,28 @@ void detect_reader_set_callback( detect_reader->context = context; } -void detect_reader_inc_nonce_cnt(DetectReader* detect_reader) { +void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max) { + furi_assert(detect_reader); + + with_view_model( + detect_reader->view, + DetectReaderViewModel * model, + { model->nonces_max = nonces_max; }, + false); +} + +void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) { + furi_assert(detect_reader); + + with_view_model( + detect_reader->view, + DetectReaderViewModel * model, + { model->nonces = nonces_collected; }, + false); +} + +void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) { furi_assert(detect_reader); with_view_model( - detect_reader->view, (DetectReaderViewModel * model) { - model->nonces++; - return false; - }); + detect_reader->view, DetectReaderViewModel * model, { model->state = state; }, true); } diff --git a/applications/main/nfc/views/detect_reader.h b/applications/main/nfc/views/detect_reader.h index 12cd03db..aabdd7c8 100644 --- a/applications/main/nfc/views/detect_reader.h +++ b/applications/main/nfc/views/detect_reader.h @@ -5,6 +5,13 @@ typedef struct DetectReader DetectReader; +typedef enum { + DetectReaderStateStart, + DetectReaderStateReaderDetected, + DetectReaderStateReaderLost, + DetectReaderStateDone, +} DetectReaderState; + typedef void (*DetectReaderDoneCallback)(void* context); DetectReader* detect_reader_alloc(); @@ -20,4 +27,8 @@ void detect_reader_set_callback( DetectReaderDoneCallback callback, void* context); -void detect_reader_inc_nonce_cnt(DetectReader* detect_reader); +void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max); + +void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected); + +void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state); diff --git a/applications/main/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c index b4674fd3..c5f55ae7 100644 --- a/applications/main/nfc/views/dict_attack.c +++ b/applications/main/nfc/views/dict_attack.c @@ -1,6 +1,5 @@ #include "dict_attack.h" -#include #include typedef enum { @@ -17,7 +16,7 @@ struct DictAttack { typedef struct { DictAttackState state; MfClassicType type; - string_t header; + FuriString* header; uint8_t sectors_total; uint8_t sectors_read; uint8_t sector_current; @@ -38,7 +37,8 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { } else if(m->state == DictAttackStateRead) { char draw_str[32] = {}; canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header)); + canvas_draw_str_aligned( + canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); canvas_set_font(canvas, FontSecondary); float dict_progress = m->dict_keys_total == 0 ? 0 : @@ -80,20 +80,20 @@ DictAttack* dict_attack_alloc() { view_set_input_callback(dict_attack->view, dict_attack_input_callback); view_set_context(dict_attack->view, dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - string_init(model->header); - return false; - }); + dict_attack->view, + DictAttackViewModel * model, + { model->header = furi_string_alloc(); }, + false); return dict_attack; } void dict_attack_free(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - string_clear(model->header); - return false; - }); + dict_attack->view, + DictAttackViewModel * model, + { furi_string_free(model->header); }, + false); view_free(dict_attack->view); free(dict_attack); } @@ -101,7 +101,9 @@ void dict_attack_free(DictAttack* dict_attack) { void dict_attack_reset(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { model->state = DictAttackStateRead; model->type = MfClassicType1k; model->sectors_total = 0; @@ -111,9 +113,9 @@ void dict_attack_reset(DictAttack* dict_attack) { model->keys_found = 0; model->dict_keys_total = 0; model->dict_keys_current = 0; - string_reset(model->header); - return false; - }); + furi_string_reset(model->header); + }, + false); } View* dict_attack_get_view(DictAttack* dict_attack) { @@ -133,99 +135,103 @@ void dict_attack_set_header(DictAttack* dict_attack, const char* header) { furi_assert(header); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - string_set_str(model->header, header); - return true; - }); + dict_attack->view, + DictAttackViewModel * model, + { furi_string_set(model->header, header); }, + true); } void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { model->state = DictAttackStateRead; model->sectors_total = mf_classic_get_total_sectors_num(type); model->keys_total = model->sectors_total * 2; - return true; - }); + }, + true); } void dict_attack_set_card_removed(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - model->state = DictAttackStateCardRemoved; - return true; - }); + dict_attack->view, + DictAttackViewModel * model, + { model->state = DictAttackStateCardRemoved; }, + true); } void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - model->sectors_read = sec_read; - return true; - }); + dict_attack->view, DictAttackViewModel * model, { model->sectors_read = sec_read; }, true); } void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - model->keys_found = keys_found; - return true; - }); + dict_attack->view, DictAttackViewModel * model, { model->keys_found = keys_found; }, true); } void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { model->sector_current = curr_sec; model->dict_keys_current = 0; - return true; - }); + }, + true); } void dict_attack_inc_current_sector(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { if(model->sector_current < model->sectors_total) { model->sector_current++; model->dict_keys_current = 0; } - return true; - }); + }, + true); } void dict_attack_inc_keys_found(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { if(model->keys_found < model->keys_total) { model->keys_found++; } - return true; - }); + }, + true); } void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - model->dict_keys_total = dict_keys_total; - return true; - }); + dict_attack->view, + DictAttackViewModel * model, + { model->dict_keys_total = dict_keys_total; }, + true); } void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) { furi_assert(dict_attack); with_view_model( - dict_attack->view, (DictAttackViewModel * model) { + dict_attack->view, + DictAttackViewModel * model, + { if(model->dict_keys_current + keys_tried < model->dict_keys_total) { model->dict_keys_current += keys_tried; } - return true; - }); + }, + true); } diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c index 10c5a9ea..0341990d 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -71,6 +71,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { .frequency_coarse = 0, .rssi_coarse = 0, .frequency_fine = 0, .rssi_fine = 0}; float rssi = 0; uint32_t frequency = 0; + float rssi_temp = 0; + uint32_t frequency_temp = 0; CC1101Status status; //Start CC1101 @@ -147,7 +149,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { FURI_LOG_T( TAG, - "RSSI: avg %f, max %f at %u, min %f", + "RSSI: avg %f, max %f at %lu, min %f", (double)(rssi_avg / rssi_avg_samples), (double)frequency_rssi.rssi_coarse, frequency_rssi.frequency_coarse, @@ -178,7 +180,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { rssi = furi_hal_subghz_get_rssi(); - FURI_LOG_T(TAG, "#:%u:%f", frequency, (double)rssi); + FURI_LOG_T(TAG, "#:%lu:%f", frequency, (double)rssi); if(frequency_rssi.rssi_fine < rssi) { frequency_rssi.rssi_fine = rssi; @@ -191,9 +193,12 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { // Deliver results fine if(frequency_rssi.rssi_fine > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) { FURI_LOG_D( - TAG, "=:%u:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine); + TAG, "=:%lu:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine); instance->sample_hold_counter = 20; + rssi_temp = frequency_rssi.rssi_fine; + frequency_temp = frequency_rssi.frequency_fine; + if(instance->filVal) { frequency_rssi.frequency_fine = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( @@ -202,18 +207,23 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { // Deliver callback if(instance->pair_callback) { instance->pair_callback( - instance->context, frequency_rssi.frequency_fine, frequency_rssi.rssi_fine); + instance->context, + frequency_rssi.frequency_fine, + frequency_rssi.rssi_fine, + true); } } else if( // Deliver results coarse (frequency_rssi.rssi_coarse > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) && (instance->sample_hold_counter < 10)) { FURI_LOG_D( TAG, - "~:%u:%f", + "~:%lu:%f", frequency_rssi.frequency_coarse, (double)frequency_rssi.rssi_coarse); instance->sample_hold_counter = 20; + rssi_temp = frequency_rssi.rssi_coarse; + frequency_temp = frequency_rssi.frequency_coarse; if(instance->filVal) { frequency_rssi.frequency_coarse = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( @@ -224,14 +234,22 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { instance->pair_callback( instance->context, frequency_rssi.frequency_coarse, - frequency_rssi.rssi_coarse); + frequency_rssi.rssi_coarse, + true); } } else { if(instance->sample_hold_counter > 0) { instance->sample_hold_counter--; + if(instance->sample_hold_counter == 18) { + if(instance->pair_callback) { + instance->pair_callback( + instance->context, frequency_temp, rssi_temp, false); + } + } } else { instance->filVal = 0; - if(instance->pair_callback) instance->pair_callback(instance->context, 0, 0); + if(instance->pair_callback) + instance->pair_callback(instance->context, 0, 0, false); } } } diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h index 50687c76..8bd1addc 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h @@ -5,8 +5,11 @@ typedef struct SubGhzFrequencyAnalyzerWorker SubGhzFrequencyAnalyzerWorker; -typedef void ( - *SubGhzFrequencyAnalyzerWorkerPairCallback)(void* context, uint32_t frequency, float rssi); +typedef void (*SubGhzFrequencyAnalyzerWorkerPairCallback)( + void* context, + uint32_t frequency, + float rssi, + bool signal); typedef struct { uint32_t frequency_coarse; diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 7fe1e7ce..023fb4b6 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -1,6 +1,5 @@ #pragma once -#include "m-string.h" #include #include @@ -72,7 +71,7 @@ typedef enum { } SubGhzViewId; struct SubGhzPresetDefinition { - string_t name; + FuriString* name; uint32_t frequency; uint8_t* data; size_t data_size; diff --git a/applications/main/subghz/scenes/subghz_scene_delete.c b/applications/main/subghz/scenes/subghz_scene_delete.c index 43151de2..94814b14 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete.c +++ b/applications/main/subghz/scenes/subghz_scene_delete.c @@ -11,17 +11,23 @@ void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* co void subghz_scene_delete_on_enter(void* context) { SubGhz* subghz = context; - string_t frequency_str; - string_t modulation_str; - string_t text; + FuriString* frequency_str; + FuriString* modulation_str; + FuriString* text; - string_init(frequency_str); - string_init(modulation_str); - string_init(text); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); + text = furi_string_alloc(); subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); widget_add_string_element( - subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(frequency_str)); + subghz->widget, + 78, + 0, + AlignLeft, + AlignTop, + FontSecondary, + furi_string_get_cstr(frequency_str)); widget_add_string_element( subghz->widget, @@ -30,14 +36,14 @@ void subghz_scene_delete_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - string_get_cstr(modulation_str)); + furi_string_get_cstr(modulation_str)); subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, text); widget_add_string_multiline_element( - subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text)); + subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text)); - string_clear(frequency_str); - string_clear(modulation_str); - string_clear(text); + furi_string_free(frequency_str); + furi_string_free(modulation_str); + furi_string_free(text); widget_add_button_element( subghz->widget, GuiButtonTypeRight, "Delete", subghz_scene_delete_callback, subghz); @@ -49,7 +55,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneDelete) { - string_set(subghz->file_path_tmp, subghz->file_path); + furi_string_set(subghz->file_path_tmp, subghz->file_path); if(subghz_delete_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_delete_raw.c b/applications/main/subghz/scenes/subghz_scene_delete_raw.c index a20968d5..fa4fc6f6 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_delete_raw.c @@ -15,18 +15,18 @@ void subghz_scene_delete_raw_callback(GuiButtonType result, InputType type, void void subghz_scene_delete_raw_on_enter(void* context) { SubGhz* subghz = context; - string_t frequency_str; - string_t modulation_str; + FuriString* frequency_str; + FuriString* modulation_str; - string_init(frequency_str); - string_init(modulation_str); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); char delete_str[SUBGHZ_MAX_LEN_NAME + 16]; - string_t file_name; - string_init(file_name); + FuriString* file_name; + file_name = furi_string_alloc(); path_extract_filename(subghz->file_path, file_name, true); - snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", string_get_cstr(file_name)); - string_clear(file_name); + snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", furi_string_get_cstr(file_name)); + furi_string_free(file_name); widget_add_text_box_element( subghz->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str, false); @@ -35,7 +35,13 @@ void subghz_scene_delete_raw_on_enter(void* context) { subghz->widget, 38, 25, AlignLeft, AlignTop, FontSecondary, "RAW signal"); subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); widget_add_string_element( - subghz->widget, 35, 37, AlignLeft, AlignTop, FontSecondary, string_get_cstr(frequency_str)); + subghz->widget, + 35, + 37, + AlignLeft, + AlignTop, + FontSecondary, + furi_string_get_cstr(frequency_str)); widget_add_string_element( subghz->widget, @@ -44,10 +50,10 @@ void subghz_scene_delete_raw_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - string_get_cstr(modulation_str)); + furi_string_get_cstr(modulation_str)); - string_clear(frequency_str); - string_clear(modulation_str); + furi_string_free(frequency_str); + furi_string_free(modulation_str); widget_add_button_element( subghz->widget, GuiButtonTypeRight, "Delete", subghz_scene_delete_raw_callback, subghz); @@ -61,7 +67,7 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneDeleteRAW) { - string_set(subghz->file_path_tmp, subghz->file_path); + furi_string_set(subghz->file_path_tmp, subghz->file_path); if(subghz_delete_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c index b42acd4d..9595c61b 100644 --- a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c +++ b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c @@ -21,6 +21,8 @@ bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent e if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneAnalyzerLock) { notification_message(subghz->notifications, &sequence_set_green_255); + notification_message(subghz->notifications, &sequence_single_vibro); + notification_message(subghz->notifications, &sequence_display_backlight_on); return true; } else if(event.event == SubGhzCustomEventSceneAnalyzerUnlock) { notification_message(subghz->notifications, &sequence_reset_rgb); diff --git a/applications/main/subghz/scenes/subghz_scene_more_raw.c b/applications/main/subghz/scenes/subghz_scene_more_raw.c index a5bade92..d75ab13c 100644 --- a/applications/main/subghz/scenes/subghz_scene_more_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_more_raw.c @@ -45,7 +45,7 @@ bool subghz_scene_more_raw_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteRAW); return true; } else if(event.event == SubmenuIndexEdit) { - string_reset(subghz->file_path_tmp); + furi_string_reset(subghz->file_path_tmp); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneMoreRAW, SubmenuIndexEdit); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 38b73e07..5dacefd6 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -10,8 +10,8 @@ bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { bool ret = false; //set the path to read the file - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { if(!flipper_format_rewind(subghz->txrx->fff_data)) { FURI_LOG_E(TAG, "Rewind error"); @@ -23,12 +23,12 @@ bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { break; } - string_set(subghz->file_path, temp_str); + furi_string_set(subghz->file_path, temp_str); ret = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return ret; } @@ -36,18 +36,20 @@ static void subghz_scene_read_raw_update_statusbar(void* context) { furi_assert(context); SubGhz* subghz = context; - string_t frequency_str; - string_t modulation_str; + FuriString* frequency_str; + FuriString* modulation_str; - string_init(frequency_str); - string_init(modulation_str); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); subghz_read_raw_add_data_statusbar( - subghz->subghz_read_raw, string_get_cstr(frequency_str), string_get_cstr(modulation_str)); + subghz->subghz_read_raw, + furi_string_get_cstr(frequency_str), + furi_string_get_cstr(modulation_str)); - string_clear(frequency_str); - string_clear(modulation_str); + furi_string_free(frequency_str); + furi_string_free(modulation_str); } void subghz_scene_read_raw_callback(SubGhzCustomEvent event, void* context) { @@ -65,8 +67,8 @@ void subghz_scene_read_raw_callback_end_tx(void* context) { void subghz_scene_read_raw_on_enter(void* context) { SubGhz* subghz = context; - string_t file_name; - string_init(file_name); + FuriString* file_name; + file_name = furi_string_alloc(); switch(subghz->txrx->rx_key_state) { case SubGhzRxKeyStateBack: @@ -75,13 +77,15 @@ void subghz_scene_read_raw_on_enter(void* context) { case SubGhzRxKeyStateRAWLoad: path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( - subghz->subghz_read_raw, SubGhzReadRAWStatusLoadKeyTX, string_get_cstr(file_name)); + subghz->subghz_read_raw, + SubGhzReadRAWStatusLoadKeyTX, + furi_string_get_cstr(file_name)); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; case SubGhzRxKeyStateRAWSave: path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( - subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, string_get_cstr(file_name)); + subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, furi_string_get_cstr(file_name)); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; default: @@ -89,7 +93,7 @@ void subghz_scene_read_raw_on_enter(void* context) { subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; } - string_clear(file_name); + furi_string_free(file_name); subghz_scene_read_raw_update_statusbar(subghz); //set callback view raw @@ -174,7 +178,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { case SubGhzCustomEventViewReadRAWErase: if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) { if(subghz_scene_read_raw_update_filename(subghz)) { - string_set(subghz->file_path_tmp, subghz->file_path); + furi_string_set(subghz->file_path_tmp, subghz->file_path); subghz_delete_file(subghz); } } @@ -245,12 +249,13 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz_protocol_raw_save_to_file_stop( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result); - string_t temp_str; - string_init(temp_str); - string_printf( + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_printf( temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); - subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, string_get_cstr(temp_str)); - string_clear(temp_str); + subghz_protocol_raw_gen_fff_data( + subghz->txrx->fff_data, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); if(spl_count > 0) { notification_message(subghz->notifications, &sequence_set_green_255); @@ -279,13 +284,14 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz_begin( subghz, subghz_setting_get_preset_data_by_name( - subghz->setting, string_get_cstr(subghz->txrx->preset->name))); + subghz->setting, + furi_string_get_cstr(subghz->txrx->preset->name))); subghz_rx(subghz, subghz->txrx->preset->frequency); } subghz->state_notifications = SubGhzNotificationStateRx; subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; } else { - string_set_str(subghz->error_str, "Function requires\nan SD card."); + furi_string_set(subghz->error_str, "Function requires\nan SD card."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 7c1f016d..77a92145 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -33,31 +33,31 @@ static const NotificationSequence subghs_sequence_rx_locked = { static void subghz_scene_receiver_update_statusbar(void* context) { SubGhz* subghz = context; - string_t history_stat_str; - string_init(history_stat_str); + FuriString* history_stat_str; + history_stat_str = furi_string_alloc(); if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) { - string_t frequency_str; - string_t modulation_str; + FuriString* frequency_str; + FuriString* modulation_str; - string_init(frequency_str); - string_init(modulation_str); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); subghz_view_receiver_add_data_statusbar( subghz->subghz_receiver, - string_get_cstr(frequency_str), - string_get_cstr(modulation_str), - string_get_cstr(history_stat_str)); + furi_string_get_cstr(frequency_str), + furi_string_get_cstr(modulation_str), + furi_string_get_cstr(history_stat_str)); - string_clear(frequency_str); - string_clear(modulation_str); + furi_string_free(frequency_str); + furi_string_free(modulation_str); } else { subghz_view_receiver_add_data_statusbar( - subghz->subghz_receiver, string_get_cstr(history_stat_str), "", ""); + subghz->subghz_receiver, furi_string_get_cstr(history_stat_str), "", ""); subghz->state_notifications = SubGhzNotificationStateIDLE; } - string_clear(history_stat_str); + furi_string_free(history_stat_str); } void subghz_scene_receiver_callback(SubGhzCustomEvent event, void* context) { @@ -72,11 +72,11 @@ static void subghz_scene_add_to_history_callback( void* context) { furi_assert(context); SubGhz* subghz = context; - string_t str_buff; - string_init(str_buff); + FuriString* str_buff; + str_buff = furi_string_alloc(); if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) { - string_reset(str_buff); + furi_string_reset(str_buff); subghz->state_notifications = SubGhzNotificationStateRxDone; @@ -84,22 +84,22 @@ static void subghz_scene_add_to_history_callback( subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, - string_get_cstr(str_buff), + furi_string_get_cstr(str_buff), subghz_history_get_type_protocol( subghz->txrx->history, subghz_history_get_item(subghz->txrx->history) - 1)); subghz_scene_receiver_update_statusbar(subghz); } subghz_receiver_reset(receiver); - string_clear(str_buff); + furi_string_free(str_buff); subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; } void subghz_scene_receiver_on_enter(void* context) { SubGhz* subghz = context; - string_t str_buff; - string_init(str_buff); + FuriString* str_buff; + str_buff = furi_string_alloc(); if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) { subghz_preset_init( @@ -113,15 +113,15 @@ void subghz_scene_receiver_on_enter(void* context) { //Load history to receiver subghz_view_receiver_exit(subghz->subghz_receiver); for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) { - string_reset(str_buff); + furi_string_reset(str_buff); subghz_history_get_text_item_menu(subghz->txrx->history, str_buff, i); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, - string_get_cstr(str_buff), + furi_string_get_cstr(str_buff), subghz_history_get_type_protocol(subghz->txrx->history, i)); subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; } - string_clear(str_buff); + furi_string_free(str_buff); subghz_scene_receiver_update_statusbar(subghz); subghz_view_receiver_set_callback( subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); @@ -137,7 +137,7 @@ void subghz_scene_receiver_on_enter(void* context) { subghz_begin( subghz, subghz_setting_get_preset_data_by_name( - subghz->setting, string_get_cstr(subghz->txrx->preset->name))); + subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); subghz_rx(subghz, subghz->txrx->preset->frequency); } subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 541ec0e0..5f022d6e 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -191,7 +191,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_preset, subghz); value_index = subghz_scene_receiver_config_next_preset( - string_get_cstr(subghz->txrx->preset->name), subghz); + furi_string_get_cstr(subghz->txrx->preset->name), subghz); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text( item, subghz_setting_get_preset_name(subghz->setting, value_index)); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 6f3e6fd1..2e833edd 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -32,7 +32,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { subghz_history_get_preset_def(subghz->txrx->history, subghz->txrx->idx_menu_chosen); subghz_preset_init( subghz, - string_get_cstr(preset->name), + furi_string_get_cstr(preset->name), preset->frequency, preset->data, preset->data_size); @@ -47,13 +47,13 @@ void subghz_scene_receiver_info_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedSubGhzReceiverInfo); if(subghz_scene_receiver_info_update_parser(subghz)) { - string_t frequency_str; - string_t modulation_str; - string_t text; + FuriString* frequency_str; + FuriString* modulation_str; + FuriString* text; - string_init(frequency_str); - string_init(modulation_str); - string_init(text); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); + text = furi_string_alloc(); subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); widget_add_string_element( @@ -63,7 +63,7 @@ void subghz_scene_receiver_info_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - string_get_cstr(frequency_str)); + furi_string_get_cstr(frequency_str)); widget_add_string_element( subghz->widget, @@ -72,14 +72,14 @@ void subghz_scene_receiver_info_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - string_get_cstr(modulation_str)); + furi_string_get_cstr(modulation_str)); subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, text); widget_add_string_multiline_element( - subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text)); + subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text)); - string_clear(frequency_str); - string_clear(modulation_str); - string_clear(text); + furi_string_free(frequency_str); + furi_string_free(modulation_str); + furi_string_free(text); if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == SubGhzProtocolFlag_Save) { @@ -146,7 +146,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) subghz_begin( subghz, subghz_setting_get_preset_data_by_name( - subghz->setting, string_get_cstr(subghz->txrx->preset->name))); + subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); subghz_rx(subghz, subghz->txrx->preset->frequency); } if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index 652499d0..1f06f4f9 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -61,20 +61,20 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(subghz_key_load(subghz, arg, false)) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded); - string_set_str(subghz->file_path, arg); + furi_string_set(subghz->file_path, arg); result = true; - string_t file_name; - string_init(file_name); + FuriString* file_name; + file_name = furi_string_alloc(); path_extract_filename(subghz->file_path, file_name, true); snprintf( subghz->file_name_tmp, SUBGHZ_MAX_LEN_NAME, "loaded\n%s", - string_get_cstr(file_name)); + furi_string_get_cstr(file_name)); popup_set_text(popup, subghz->file_name_tmp, 89, 44, AlignCenter, AlignTop); - string_clear(file_name); + furi_string_free(file_name); } } rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result); diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index 12ec9868..dfcb6586 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -1,5 +1,4 @@ #include "../subghz_i.h" -#include "m-string.h" #include "subghz/types.h" #include #include "../helpers/subghz_custom_event.h" @@ -14,6 +13,20 @@ void subghz_scene_save_name_text_input_callback(void* context) { view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneSaveName); } +void subghz_scene_save_name_get_timefilename(FuriString* name) { + FuriHalRtcDateTime datetime = {0}; + furi_hal_rtc_get_datetime(&datetime); + furi_string_printf( + name, + "RAW-%.4d%.2d%.2d-%.2d%.2d%.2d", + datetime.year, + datetime.month, + datetime.day, + datetime.hour, + datetime.minute, + datetime.second); +} + void subghz_scene_save_name_on_enter(void* context) { SubGhz* subghz = context; @@ -21,35 +34,34 @@ void subghz_scene_save_name_on_enter(void* context) { TextInput* text_input = subghz->text_input; bool dev_name_empty = false; - string_t file_name; - string_t dir_name; - string_init(file_name); - string_init(dir_name); + FuriString* file_name; + FuriString* dir_name; + file_name = furi_string_alloc(); + dir_name = furi_string_alloc(); if(!subghz_path_is_file(subghz->file_path)) { char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0}; set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME); - string_set_str(file_name, file_name_buf); - string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); + furi_string_set(file_name, file_name_buf); + furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); //highlighting the entire filename by default dev_name_empty = true; } else { - string_set(subghz->file_path_tmp, subghz->file_path); - path_extract_dirname(string_get_cstr(subghz->file_path), dir_name); + furi_string_set(subghz->file_path_tmp, subghz->file_path); + path_extract_dirname(furi_string_get_cstr(subghz->file_path), dir_name); path_extract_filename(subghz->file_path, file_name, true); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == SubGhzCustomEventManagerSetRAW) { dev_name_empty = true; - subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME); + subghz_scene_save_name_get_timefilename(file_name); } - path_extract_filename(subghz->file_path, file_name, true); } - string_set(subghz->file_path, dir_name); + furi_string_set(subghz->file_path, dir_name); } - strncpy(subghz->file_name_tmp, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME); + strncpy(subghz->file_name_tmp, furi_string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME); text_input_set_header_text(text_input, "Name signal"); text_input_set_result_callback( text_input, @@ -59,12 +71,12 @@ void subghz_scene_save_name_on_enter(void* context) { MAX_TEXT_INPUT_LEN, // buffer size dev_name_empty); - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, ""); + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + furi_string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - string_clear(file_name); - string_clear(dir_name); + furi_string_free(file_name); + furi_string_free(dir_name); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput); } @@ -75,14 +87,14 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(!strcmp(subghz->file_name_tmp, "") || scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { - string_set(subghz->file_path, subghz->file_path_tmp); + furi_string_set(subghz->file_path, subghz->file_path_tmp); } scene_manager_previous_scene(subghz->scene_manager); return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneSaveName) { if(strcmp(subghz->file_name_tmp, "")) { - string_cat_printf( + furi_string_cat_printf( subghz->file_path, "/%s%s", subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); if(subghz_path_is_file(subghz->file_path_tmp)) { if(!subghz_rename_file(subghz)) { @@ -92,7 +104,9 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType) != SubGhzCustomEventManagerNoSet) { subghz_save_protocol_to_file( - subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); + subghz, + subghz->txrx->fff_data, + furi_string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneSetType, @@ -102,14 +116,14 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { subghz, subghz_history_get_raw_data( subghz->txrx->history, subghz->txrx->idx_menu_chosen), - string_get_cstr(subghz->file_path)); + furi_string_get_cstr(subghz->file_path)); } } if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { subghz_protocol_raw_gen_fff_data( - subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); + subghz->txrx->fff_data, furi_string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); } else { @@ -119,7 +133,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); return true; } else { - string_set_str(subghz->error_str, "No name file"); + furi_string_set(subghz->error_str, "No name file"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); return true; } diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 1a359542..1e7a7474 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -27,7 +27,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, protocol_name); if(subghz->txrx->decoder_result == NULL) { - string_set_str(subghz->error_str, "Protocol not\nfound!"); + furi_string_set(subghz->error_str, "Protocol not\nfound!"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); return false; } @@ -261,7 +261,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } subghz_transmitter_free(subghz->txrx->transmitter); if(!generated_protocol) { - string_set_str( + furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } @@ -285,7 +285,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } subghz_transmitter_free(subghz->txrx->transmitter); if(!generated_protocol) { - string_set_str( + furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } diff --git a/applications/main/subghz/scenes/subghz_scene_show_error.c b/applications/main/subghz/scenes/subghz_scene_show_error.c index 5632a859..eadfb211 100644 --- a/applications/main/subghz/scenes/subghz_scene_show_error.c +++ b/applications/main/subghz/scenes/subghz_scene_show_error.c @@ -33,7 +33,7 @@ void subghz_scene_show_error_on_enter(void* context) { AlignCenter, AlignCenter, FontSecondary, - string_get_cstr(subghz->error_str)); + furi_string_get_cstr(subghz->error_str)); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowError) == SubGhzCustomEventManagerSet) { widget_add_button_element( @@ -89,6 +89,6 @@ void subghz_scene_show_error_on_exit(void* context) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneShowError, SubGhzCustomEventManagerNoSet); widget_reset(subghz->widget); - string_reset(subghz->error_str); + furi_string_reset(subghz->error_str); notification_message(subghz->notifications, &sequence_reset_rgb); } diff --git a/applications/main/subghz/scenes/subghz_scene_show_error_sub.c b/applications/main/subghz/scenes/subghz_scene_show_error_sub.c index 74e03432..2720b2b9 100644 --- a/applications/main/subghz/scenes/subghz_scene_show_error_sub.c +++ b/applications/main/subghz/scenes/subghz_scene_show_error_sub.c @@ -12,7 +12,7 @@ void subghz_scene_show_error_sub_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); - popup_set_header(popup, string_get_cstr(subghz->error_str), 14, 15, AlignLeft, AlignTop); + popup_set_header(popup, furi_string_get_cstr(subghz->error_str), 14, 15, AlignLeft, AlignTop); popup_set_timeout(popup, 1500); popup_set_context(popup, subghz); popup_set_callback(popup, subghz_scene_show_error_sub_popup_callback); @@ -46,7 +46,7 @@ void subghz_scene_show_error_sub_on_exit(void* context) { popup_set_context(popup, NULL); popup_set_timeout(popup, 0); popup_disable_timeout(popup); - string_reset(subghz->error_str); + furi_string_reset(subghz->error_str); notification_message(subghz->notifications, &sequence_reset_rgb); } diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index b3f8d079..5da6f430 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -13,13 +13,13 @@ bool subghz_scene_transmitter_update_data_show(void* context) { SubGhz* subghz = context; if(subghz->txrx->decoder_result) { - string_t key_str; - string_t frequency_str; - string_t modulation_str; + FuriString* key_str; + FuriString* frequency_str; + FuriString* modulation_str; - string_init(key_str); - string_init(frequency_str); - string_init(modulation_str); + key_str = furi_string_alloc(); + frequency_str = furi_string_alloc(); + modulation_str = furi_string_alloc(); uint8_t show_button = 0; subghz_protocol_decoder_base_deserialize( @@ -34,14 +34,14 @@ bool subghz_scene_transmitter_update_data_show(void* context) { subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); subghz_view_transmitter_add_data_to_show( subghz->subghz_transmitter, - string_get_cstr(key_str), - string_get_cstr(frequency_str), - string_get_cstr(modulation_str), + furi_string_get_cstr(key_str), + furi_string_get_cstr(frequency_str), + furi_string_get_cstr(modulation_str), show_button); - string_clear(frequency_str); - string_clear(modulation_str); - string_clear(key_str); + furi_string_free(frequency_str); + furi_string_free(modulation_str); + furi_string_free(key_str); return true; } @@ -94,7 +94,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneStart); return true; } else if(event.event == SubGhzCustomEventViewTransmitterError) { - string_set_str(subghz->error_str, "Protocol not\nfound!"); + furi_string_set(subghz->error_str, "Protocol not\nfound!"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); } } else if(event.type == SceneManagerEventTypeTick) { diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 61960218..71c6bc2c 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -1,6 +1,5 @@ /* Abandon hope, all ye who enter here. */ -#include "m-string.h" #include "subghz/types.h" #include "subghz_i.h" #include @@ -62,8 +61,8 @@ void subghz_blink_stop(SubGhz* instance) { SubGhz* subghz_alloc() { SubGhz* subghz = malloc(sizeof(SubGhz)); - string_init(subghz->file_path); - string_init(subghz->file_path_tmp); + subghz->file_path = furi_string_alloc(); + subghz->file_path_tmp = furi_string_alloc(); // GUI subghz->gui = furi_record_open(RECORD_GUI); @@ -171,7 +170,7 @@ SubGhz* subghz_alloc() { subghz->lock = SubGhzLockOff; subghz->txrx = malloc(sizeof(SubGhzTxRx)); subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition)); - string_init(subghz->txrx->preset->name); + subghz->txrx->preset->name = furi_string_alloc(); subghz_preset_init( subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); @@ -197,7 +196,7 @@ SubGhz* subghz_alloc() { subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->receiver); //Init Error_str - string_init(subghz->error_str); + subghz->error_str = furi_string_alloc(); return subghz; } @@ -282,20 +281,20 @@ void subghz_free(SubGhz* subghz) { subghz_worker_free(subghz->txrx->worker); flipper_format_free(subghz->txrx->fff_data); subghz_history_free(subghz->txrx->history); - string_clear(subghz->txrx->preset->name); + furi_string_free(subghz->txrx->preset->name); free(subghz->txrx->preset); free(subghz->txrx); //Error string - string_clear(subghz->error_str); + furi_string_free(subghz->error_str); // Notifications furi_record_close(RECORD_NOTIFICATION); subghz->notifications = NULL; // Path strings - string_clear(subghz->file_path); - string_clear(subghz->file_path_tmp); + furi_string_free(subghz->file_path); + furi_string_free(subghz->file_path_tmp); // The rest free(subghz); @@ -329,7 +328,7 @@ int32_t subghz_app(void* p) { view_dispatcher_attach_to_gui( subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); if(subghz_key_load(subghz, p, true)) { - string_set_str(subghz->file_path, p); + furi_string_set(subghz->file_path, (const char*)p); if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { //Load Raw TX @@ -348,13 +347,13 @@ int32_t subghz_app(void* p) { } else { view_dispatcher_attach_to_gui( subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); - string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); + furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); if(load_database) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); } else { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneShowError, SubGhzCustomEventManagerSet); - string_set_str( + furi_string_set( subghz->error_str, "No SD card or\ndatabase found.\nSome app function\nmay be reduced."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index d921979f..a1474885 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -24,15 +23,15 @@ #define SUBGHZ_REGION_FILENAME "/int/.region_data" -void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { +void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; - if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lu", &frequency); + if(furi_string_size(args)) { + int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); if(ret != 1) { printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz tx_carrier", "", string_get_cstr(args)); + cli_print_usage("subghz tx_carrier", "", furi_string_get_cstr(args)); return; } if(!furi_hal_subghz_is_frequency_valid(frequency)) { @@ -68,15 +67,15 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { furi_hal_power_suppress_charge_exit(); } -void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { +void subghz_cli_command_rx_carrier(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; - if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lu", &frequency); + if(furi_string_size(args)) { + int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); if(ret != 1) { printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz rx_carrier", "", string_get_cstr(args)); + cli_print_usage("subghz rx_carrier", "", furi_string_get_cstr(args)); return; } if(!furi_hal_subghz_is_frequency_valid(frequency)) { @@ -109,15 +108,16 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { furi_hal_subghz_sleep(); } -void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { +void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; uint32_t key = 0x0074BADE; uint32_t repeat = 10; uint32_t te = 403; - if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lx %lu %lu %lu", &key, &frequency, &te, &repeat); + if(furi_string_size(args)) { + int ret = + sscanf(furi_string_get_cstr(args), "%lx %lu %lu %lu", &key, &frequency, &te, &repeat); if(ret != 4) { printf( "sscanf returned %d, key: %lx, frequency: %lu, te:%lu, repeat: %lu\r\n", @@ -129,7 +129,7 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { cli_print_usage( "subghz tx", "<3 Byte Key: in hex> ", - string_get_cstr(args)); + furi_string_get_cstr(args)); return; } if(!furi_hal_subghz_is_frequency_valid(frequency)) { @@ -147,14 +147,12 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { te, repeat); - string_t flipper_format_string; - string_init_printf( - flipper_format_string, + FuriString* flipper_format_string = furi_string_alloc_printf( "Protocol: Princeton\n" "Bit: 24\n" "Key: 00 00 00 00 00 %02X %02X %02X\n" - "TE: %d\n" - "Repeat: %d\n", + "TE: %ld\n" + "Repeat: %ld\n", (uint8_t)((key >> 16) & 0xFF), (uint8_t)((key >> 8) & 0xFF), (uint8_t)(key & 0xFF), @@ -163,7 +161,7 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { FlipperFormat* flipper_format = flipper_format_string_alloc(); Stream* stream = flipper_format_get_raw_stream(flipper_format); stream_clean(stream); - stream_write_cstring(stream, string_get_cstr(flipper_format_string)); + stream_write_cstring(stream, furi_string_get_cstr(flipper_format_string)); SubGhzEnvironment* environment = subghz_environment_alloc(); @@ -195,23 +193,21 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { typedef struct { volatile bool overrun; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; size_t packet_count; } SubGhzCliCommandRx; static void subghz_cli_command_rx_capture_callback(bool level, uint32_t duration, void* context) { SubGhzCliCommandRx* instance = context; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; LevelDuration level_duration = level_duration_make(level, duration); if(instance->overrun) { instance->overrun = false; level_duration = level_duration_reset(); } - size_t ret = xStreamBufferSendFromISR( - instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken); + size_t ret = + furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0); if(sizeof(LevelDuration) != ret) instance->overrun = true; - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } static void subghz_cli_command_rx_callback( @@ -221,23 +217,23 @@ static void subghz_cli_command_rx_callback( SubGhzCliCommandRx* instance = context; instance->packet_count++; - string_t text; - string_init(text); + FuriString* text; + text = furi_string_alloc(); subghz_protocol_decoder_base_get_string(decoder_base, text); subghz_receiver_reset(receiver); - printf("%s", string_get_cstr(text)); - string_clear(text); + printf("%s", furi_string_get_cstr(text)); + furi_string_free(text); } -void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { +void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; - if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lu", &frequency); + if(furi_string_size(args)) { + int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); if(ret != 1) { printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz rx", "", string_get_cstr(args)); + cli_print_usage("subghz rx", "", furi_string_get_cstr(args)); return; } if(!furi_hal_subghz_is_frequency_valid(frequency)) { @@ -250,7 +246,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { // Allocate context and buffers SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); - instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); + instance->stream = + furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); furi_check(instance->stream); SubGhzEnvironment* environment = subghz_environment_alloc(); @@ -280,8 +277,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); LevelDuration level_duration; while(!cli_cmd_interrupt_received(cli)) { - int ret = - xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10); + int ret = furi_stream_buffer_receive( + instance->stream, &level_duration, sizeof(LevelDuration), 10); if(ret == sizeof(LevelDuration)) { if(level_duration_is_reset(level_duration)) { printf("."); @@ -305,36 +302,36 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { // Cleanup subghz_receiver_free(receiver); subghz_environment_free(environment); - vStreamBufferDelete(instance->stream); + furi_stream_buffer_free(instance->stream); free(instance); } -void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { +void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { UNUSED(context); - string_t file_name; - string_init(file_name); - string_set_str(file_name, ANY_PATH("subghz/test.sub")); + FuriString* file_name; + file_name = furi_string_alloc(); + furi_string_set(file_name, ANY_PATH("subghz/test.sub")); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t temp_data32; bool check_file = false; do { - if(string_size(args)) { + if(furi_string_size(args)) { if(!args_read_string_and_trim(args, file_name)) { cli_print_usage( - "subghz decode_raw", "", string_get_cstr(args)); + "subghz decode_raw", "", furi_string_get_cstr(args)); break; } } - if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) { + if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_name))) { printf( "subghz decode_raw \033[0;31mError open file\033[0m %s\r\n", - string_get_cstr(file_name)); + furi_string_get_cstr(file_name)); break; } @@ -343,7 +340,7 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { break; } - if(!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE) && + if(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE) && temp_data32 == SUBGHZ_KEY_FILE_VERSION) { } else { printf("subghz decode_raw \033[0;31mType or version mismatch\033[0m\r\n"); @@ -353,7 +350,7 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { check_file = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); @@ -385,14 +382,14 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance); SubGhzFileEncoderWorker* file_worker_encoder = subghz_file_encoder_worker_alloc(); - if(subghz_file_encoder_worker_start(file_worker_encoder, string_get_cstr(file_name))) { + if(subghz_file_encoder_worker_start(file_worker_encoder, furi_string_get_cstr(file_name))) { //the worker needs a file in order to open and read part of the file furi_delay_ms(100); } printf( "Listening at \033[0;33m%s\033[0m.\r\n\r\nPress CTRL+C to stop\r\n\r\n", - string_get_cstr(file_name)); + furi_string_get_cstr(file_name)); LevelDuration level_duration; while(!cli_cmd_interrupt_received(cli)) { @@ -419,7 +416,7 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { subghz_file_encoder_worker_free(file_worker_encoder); free(instance); } - string_clear(file_name); + furi_string_free(file_name); } static void subghz_cli_command_print_usage() { @@ -445,14 +442,14 @@ static void subghz_cli_command_print_usage() { } } -static void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { +static void subghz_cli_command_encrypt_keeloq(Cli* cli, FuriString* args) { UNUSED(cli); uint8_t iv[16]; - string_t source; - string_t destination; - string_init(source); - string_init(destination); + FuriString* source; + FuriString* destination; + source = furi_string_alloc(); + destination = furi_string_alloc(); SubGhzKeystore* keystore = subghz_keystore_alloc(); @@ -472,30 +469,30 @@ static void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { break; } - if(!subghz_keystore_load(keystore, string_get_cstr(source))) { + if(!subghz_keystore_load(keystore, furi_string_get_cstr(source))) { printf("Failed to load Keystore"); break; } - if(!subghz_keystore_save(keystore, string_get_cstr(destination), iv)) { + if(!subghz_keystore_save(keystore, furi_string_get_cstr(destination), iv)) { printf("Failed to save Keystore"); break; } } while(false); subghz_keystore_free(keystore); - string_clear(destination); - string_clear(source); + furi_string_free(destination); + furi_string_free(source); } -static void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { +static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { UNUSED(cli); uint8_t iv[16]; - string_t source; - string_t destination; - string_init(source); - string_init(destination); + FuriString* source; + FuriString* destination; + source = furi_string_alloc(); + destination = furi_string_alloc(); do { if(!args_read_string_and_trim(args, source)) { @@ -514,25 +511,25 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { } if(!subghz_keystore_raw_encrypted_save( - string_get_cstr(source), string_get_cstr(destination), iv)) { + furi_string_get_cstr(source), furi_string_get_cstr(destination), iv)) { printf("Failed to save Keystore"); break; } } while(false); - string_clear(destination); - string_clear(source); + furi_string_free(destination); + furi_string_free(source); } -static void subghz_cli_command_chat(Cli* cli, string_t args) { +static void subghz_cli_command_chat(Cli* cli, FuriString* args) { uint32_t frequency = 433920000; - if(string_size(args)) { - int ret = sscanf(string_get_cstr(args), "%lu", &frequency); + if(furi_string_size(args)) { + int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); if(ret != 1) { printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz chat", "", string_get_cstr(args)); + cli_print_usage("subghz chat", "", furi_string_get_cstr(args)); return; } if(!furi_hal_subghz_is_frequency_valid(frequency)) { @@ -568,22 +565,22 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { size_t message_max_len = 64; uint8_t message[64] = {0}; - string_t input; - string_init(input); - string_t name; - string_init(name); - string_t output; - string_init(output); - string_t sysmsg; - string_init(sysmsg); + FuriString* input; + input = furi_string_alloc(); + FuriString* name; + name = furi_string_alloc(); + FuriString* output; + output = furi_string_alloc(); + FuriString* sysmsg; + sysmsg = furi_string_alloc(); bool exit = false; SubGhzChatEvent chat_event; NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - string_printf(name, "\033[0;33m%s\033[0m: ", furi_hal_version_get_name_ptr()); - string_set(input, name); - printf("%s", string_get_cstr(input)); + furi_string_printf(name, "\033[0;33m%s\033[0m: ", furi_hal_version_get_name_ptr()); + furi_string_set(input, name); + printf("%s", furi_string_get_cstr(input)); fflush(stdout); while(!exit) { @@ -597,63 +594,63 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { break; } else if( (chat_event.c == CliSymbolAsciiBackspace) || (chat_event.c == CliSymbolAsciiDel)) { - size_t len = string_length_u(input); - if(len > string_length_u(name)) { + size_t len = furi_string_utf8_length(input); + if(len > furi_string_utf8_length(name)) { printf("%s", "\e[D\e[1P"); fflush(stdout); //delete 1 char UTF - const char* str = string_get_cstr(input); + const char* str = furi_string_get_cstr(input); size_t size = 0; - m_str1ng_utf8_state_e s = M_STRING_UTF8_STARTING; - string_unicode_t u = 0; - string_reset(sysmsg); + FuriStringUTF8State s = FuriStringUTF8StateStarting; + FuriStringUnicodeValue u = 0; + furi_string_reset(sysmsg); while(*str) { - m_str1ng_utf8_decode(*str, &s, &u); - if((s == M_STRING_UTF8_ERROR) || s == M_STRING_UTF8_STARTING) { - string_push_u(sysmsg, u); + furi_string_utf8_decode(*str, &s, &u); + if((s == FuriStringUTF8StateError) || s == FuriStringUTF8StateStarting) { + furi_string_utf8_push(sysmsg, u); if(++size >= len - 1) break; - s = M_STRING_UTF8_STARTING; + s = FuriStringUTF8StateStarting; } str++; } - string_set(input, sysmsg); + furi_string_set(input, sysmsg); } } else if(chat_event.c == CliSymbolAsciiCR) { printf("\r\n"); - string_push_back(input, '\r'); - string_push_back(input, '\n'); + furi_string_push_back(input, '\r'); + furi_string_push_back(input, '\n'); while(!subghz_chat_worker_write( subghz_chat, - (uint8_t*)string_get_cstr(input), - strlen(string_get_cstr(input)))) { + (uint8_t*)furi_string_get_cstr(input), + strlen(furi_string_get_cstr(input)))) { furi_delay_ms(10); } - string_printf(input, "%s", string_get_cstr(name)); - printf("%s", string_get_cstr(input)); + furi_string_printf(input, "%s", furi_string_get_cstr(name)); + printf("%s", furi_string_get_cstr(input)); fflush(stdout); } else if(chat_event.c == CliSymbolAsciiLF) { //cut out the symbol \n } else { putc(chat_event.c, stdout); fflush(stdout); - string_push_back(input, chat_event.c); + furi_string_push_back(input, chat_event.c); break; case SubGhzChatEventRXData: do { memset(message, 0x00, message_max_len); size_t len = subghz_chat_worker_read(subghz_chat, message, message_max_len); for(size_t i = 0; i < len; i++) { - string_push_back(output, message[i]); + furi_string_push_back(output, message[i]); if(message[i] == '\n') { printf("\r"); for(uint8_t i = 0; i < 80; i++) { printf(" "); } - printf("\r %s", string_get_cstr(output)); - printf("%s", string_get_cstr(input)); + printf("\r %s", furi_string_get_cstr(output)); + printf("%s", furi_string_get_cstr(input)); fflush(stdout); - string_reset(output); + furi_string_reset(output); } } } while(subghz_chat_worker_available(subghz_chat)); @@ -662,22 +659,22 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { notification_message(notification, &sequence_single_vibro); break; case SubGhzChatEventUserEntrance: - string_printf( + furi_string_printf( sysmsg, "\033[0;34m%s joined chat.\033[0m\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, - (uint8_t*)string_get_cstr(sysmsg), - strlen(string_get_cstr(sysmsg))); + (uint8_t*)furi_string_get_cstr(sysmsg), + strlen(furi_string_get_cstr(sysmsg))); break; case SubGhzChatEventUserExit: - string_printf( + furi_string_printf( sysmsg, "\033[0;31m%s left chat.\033[0m\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, - (uint8_t*)string_get_cstr(sysmsg), - strlen(string_get_cstr(sysmsg))); + (uint8_t*)furi_string_get_cstr(sysmsg), + strlen(furi_string_get_cstr(sysmsg))); furi_delay_ms(10); exit = true; break; @@ -693,10 +690,10 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { } } - string_clear(input); - string_clear(name); - string_clear(output); - string_clear(sysmsg); + furi_string_free(input); + furi_string_free(name); + furi_string_free(output); + furi_string_free(sysmsg); furi_hal_power_suppress_charge_exit(); furi_record_close(RECORD_NOTIFICATION); @@ -707,9 +704,9 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { printf("\r\nExit chat\r\n"); } -static void subghz_cli_command(Cli* cli, string_t args, void* context) { - string_t cmd; - string_init(cmd); +static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -717,43 +714,43 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) { break; } - if(string_cmp_str(cmd, "chat") == 0) { + if(furi_string_cmp_str(cmd, "chat") == 0) { subghz_cli_command_chat(cli, args); break; } - if(string_cmp_str(cmd, "tx") == 0) { + if(furi_string_cmp_str(cmd, "tx") == 0) { subghz_cli_command_tx(cli, args, context); break; } - if(string_cmp_str(cmd, "rx") == 0) { + if(furi_string_cmp_str(cmd, "rx") == 0) { subghz_cli_command_rx(cli, args, context); break; } - if(string_cmp_str(cmd, "decode_raw") == 0) { + if(furi_string_cmp_str(cmd, "decode_raw") == 0) { subghz_cli_command_decode_raw(cli, args, context); break; } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(string_cmp_str(cmd, "encrypt_keeloq") == 0) { + if(furi_string_cmp_str(cmd, "encrypt_keeloq") == 0) { subghz_cli_command_encrypt_keeloq(cli, args); break; } - if(string_cmp_str(cmd, "encrypt_raw") == 0) { + if(furi_string_cmp_str(cmd, "encrypt_raw") == 0) { subghz_cli_command_encrypt_raw(cli, args); break; } - if(string_cmp_str(cmd, "tx_carrier") == 0) { + if(furi_string_cmp_str(cmd, "tx_carrier") == 0) { subghz_cli_command_tx_carrier(cli, args, context); break; } - if(string_cmp_str(cmd, "rx_carrier") == 0) { + if(furi_string_cmp_str(cmd, "rx_carrier") == 0) { subghz_cli_command_rx_carrier(cli, args, context); break; } @@ -762,7 +759,7 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) { subghz_cli_command_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } static bool @@ -797,7 +794,7 @@ static bool subghz_on_system_start_istream_decode_band( FURI_LOG_I( "SubGhzOnStart", - "Add allowed band: start %dHz, stop %dHz, power_limit %ddBm, duty_cycle %d%%", + "Add allowed band: start %ldHz, stop %ldHz, power_limit %ddBm, duty_cycle %d%%", band.start, band.end, band.power_limit, diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 820a13d1..0f67b4fc 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -3,13 +3,12 @@ #include #include -#include #define SUBGHZ_HISTORY_MAX 50 #define TAG "SubGhzHistory" typedef struct { - string_t item_str; + FuriString* item_str; FlipperFormat* flipper_string; uint8_t type; SubGhzPresetDefinition* preset; @@ -27,13 +26,13 @@ struct SubGhzHistory { uint32_t last_update_timestamp; uint16_t last_index_write; uint8_t code_last_hash_data; - string_t tmp_string; + FuriString* tmp_string; SubGhzHistoryStruct* history; }; SubGhzHistory* subghz_history_alloc(void) { SubGhzHistory* instance = malloc(sizeof(SubGhzHistory)); - string_init(instance->tmp_string); + instance->tmp_string = furi_string_alloc(); instance->history = malloc(sizeof(SubGhzHistoryStruct)); SubGhzHistoryItemArray_init(instance->history->data); return instance; @@ -41,11 +40,11 @@ SubGhzHistory* subghz_history_alloc(void) { void subghz_history_free(SubGhzHistory* instance) { furi_assert(instance); - string_clear(instance->tmp_string); + furi_string_free(instance->tmp_string); for M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); + furi_string_free(item->item_str); + furi_string_free(item->preset->name); free(item->preset); flipper_format_free(item->flipper_string); item->type = 0; @@ -70,16 +69,16 @@ SubGhzPresetDefinition* subghz_history_get_preset_def(SubGhzHistory* instance, u const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); - return string_get_cstr(item->preset->name); + return furi_string_get_cstr(item->preset->name); } void subghz_history_reset(SubGhzHistory* instance) { furi_assert(instance); - string_reset(instance->tmp_string); + furi_string_reset(instance->tmp_string); for M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); + furi_string_free(item->item_str); + furi_string_free(item->preset->name); free(item->preset); flipper_format_free(item->flipper_string); item->type = 0; @@ -106,9 +105,9 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i flipper_format_rewind(item->flipper_string); if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { FURI_LOG_E(TAG, "Missing Protocol"); - string_reset(instance->tmp_string); + furi_string_reset(instance->tmp_string); } - return string_get_cstr(instance->tmp_string); + return furi_string_get_cstr(instance->tmp_string); } FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) { @@ -120,20 +119,20 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx return NULL; } } -bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { +bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) { furi_assert(instance); if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { - if(output != NULL) string_printf(output, "Memory is FULL"); + if(output != NULL) furi_string_printf(output, "Memory is FULL"); return true; } if(output != NULL) - string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); + furi_string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); return false; } -void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) { +void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) { SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); - string_set(output, item->item_str); + furi_string_set(output, item->item_str); } bool subghz_history_add_to_history( @@ -156,18 +155,18 @@ bool subghz_history_add_to_history( instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); instance->last_update_timestamp = furi_get_tick(); - string_t text; - string_init(text); + FuriString* text; + text = furi_string_alloc(); SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data); item->preset = malloc(sizeof(SubGhzPresetDefinition)); item->type = decoder_base->protocol->type; item->preset->frequency = preset->frequency; - string_init(item->preset->name); - string_set(item->preset->name, preset->name); + item->preset->name = furi_string_alloc(); + furi_string_set(item->preset->name, preset->name); item->preset->data = preset->data; item->preset->data_size = preset->data_size; - string_init(item->item_str); + item->item_str = furi_string_alloc(); item->flipper_string = flipper_format_string_alloc(); subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); @@ -180,20 +179,20 @@ bool subghz_history_add_to_history( FURI_LOG_E(TAG, "Missing Protocol"); break; } - if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) { - string_set_str(instance->tmp_string, "KL "); + if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) { + furi_string_set(instance->tmp_string, "KL "); if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) { FURI_LOG_E(TAG, "Missing Protocol"); break; } - string_cat(instance->tmp_string, text); - } else if(!strcmp(string_get_cstr(instance->tmp_string), "Star Line")) { - string_set_str(instance->tmp_string, "SL "); + furi_string_cat(instance->tmp_string, text); + } else if(!strcmp(furi_string_get_cstr(instance->tmp_string), "Star Line")) { + furi_string_set(instance->tmp_string, "SL "); if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) { FURI_LOG_E(TAG, "Missing Protocol"); break; } - string_cat(instance->tmp_string, text); + furi_string_cat(instance->tmp_string, text); } if(!flipper_format_rewind(item->flipper_string)) { FURI_LOG_E(TAG, "Rewind error"); @@ -209,22 +208,22 @@ bool subghz_history_add_to_history( data = (data << 8) | key_data[i]; } if(!(uint32_t)(data >> 32)) { - string_printf( + furi_string_printf( item->item_str, "%s %lX", - string_get_cstr(instance->tmp_string), + furi_string_get_cstr(instance->tmp_string), (uint32_t)(data & 0xFFFFFFFF)); } else { - string_printf( + furi_string_printf( item->item_str, "%s %lX%08lX", - string_get_cstr(instance->tmp_string), + furi_string_get_cstr(instance->tmp_string), (uint32_t)(data >> 32), (uint32_t)(data & 0xFFFFFFFF)); } } while(false); - string_clear(text); + furi_string_free(text); instance->last_index_write++; return true; } diff --git a/applications/main/subghz/subghz_history.h b/applications/main/subghz/subghz_history.h index adbcfc18..7bff3df5 100644 --- a/applications/main/subghz/subghz_history.h +++ b/applications/main/subghz/subghz_history.h @@ -71,18 +71,18 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i /** Get string item menu to history[idx] * * @param instance - SubGhzHistory instance - * @param output - string_t output + * @param output - FuriString* output * @param idx - record index */ -void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx); +void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx); /** Get string the remaining number of records to history * * @param instance - SubGhzHistory instance - * @param output - string_t output + * @param output - FuriString* output * @return bool - is FUUL */ -bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output); +bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output); /** Add protocol to history * diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 6ed8fd53..ac1036d0 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -26,7 +26,7 @@ void subghz_preset_init( size_t preset_data_size) { furi_assert(context); SubGhz* subghz = context; - string_set(subghz->txrx->preset->name, preset_name); + furi_string_set(subghz->txrx->preset->name, preset_name); subghz->txrx->preset->frequency = frequency; subghz->txrx->preset->data = preset_data; subghz->txrx->preset->data_size = preset_data_size; @@ -34,15 +34,15 @@ void subghz_preset_init( bool subghz_set_preset(SubGhz* subghz, const char* preset) { if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - string_set(subghz->txrx->preset->name, "AM270"); + furi_string_set(subghz->txrx->preset->name, "AM270"); } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - string_set(subghz->txrx->preset->name, "AM650"); + furi_string_set(subghz->txrx->preset->name, "AM650"); } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - string_set(subghz->txrx->preset->name, "FM238"); + furi_string_set(subghz->txrx->preset->name, "FM238"); } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - string_set(subghz->txrx->preset->name, "FM476"); + furi_string_set(subghz->txrx->preset->name, "FM476"); } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - string_set(subghz->txrx->preset->name, "CUSTOM"); + furi_string_set(subghz->txrx->preset->name, "CUSTOM"); } else { FURI_LOG_E(TAG, "Unknown preset"); return false; @@ -50,17 +50,17 @@ bool subghz_set_preset(SubGhz* subghz, const char* preset) { return true; } -void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation) { +void subghz_get_frequency_modulation(SubGhz* subghz, FuriString* frequency, FuriString* modulation) { furi_assert(subghz); if(frequency != NULL) { - string_printf( + furi_string_printf( frequency, "%03ld.%02ld", subghz->txrx->preset->frequency / 1000000 % 1000, subghz->txrx->preset->frequency / 10000 % 100); } if(modulation != NULL) { - string_printf(modulation, "%0.2s", string_get_cstr(subghz->txrx->preset->name)); + furi_string_printf(modulation, "%.2s", furi_string_get_cstr(subghz->txrx->preset->name)); } } @@ -137,8 +137,8 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { furi_assert(subghz); bool ret = false; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t repeat = 200; do { if(!flipper_format_rewind(flipper_format)) { @@ -155,21 +155,21 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { break; } - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, string_get_cstr(temp_str)); + subghz->txrx->transmitter = subghz_transmitter_alloc_init( + subghz->txrx->environment, furi_string_get_cstr(temp_str)); if(subghz->txrx->transmitter) { if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format)) { - if(strcmp(string_get_cstr(subghz->txrx->preset->name), "")) { + if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "")) { subghz_begin( subghz, subghz_setting_get_preset_data_by_name( - subghz->setting, string_get_cstr(subghz->txrx->preset->name))); + subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); } else { FURI_LOG_E( TAG, "Unknown name preset \" %s \"", - string_get_cstr(subghz->txrx->preset->name)); + furi_string_get_cstr(subghz->txrx->preset->name)); subghz_begin( subghz, subghz_setting_get_preset_data_by_name(subghz->setting, "AM650")); } @@ -193,7 +193,7 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { } } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return ret; } @@ -209,7 +209,7 @@ void subghz_tx_stop(SubGhz* subghz) { if((subghz->txrx->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) && (subghz_path_is_file(subghz->file_path))) { subghz_save_protocol_to_file( - subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); + subghz, subghz->txrx->fff_data, furi_string_get_cstr(subghz->file_path)); } subghz_idle(subghz); notification_message(subghz->notifications, &sequence_reset_red); @@ -244,8 +244,8 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); SubGhzLoadKeyState load_key_state = SubGhzLoadKeyStateParseErr; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t temp_data32; do { @@ -260,8 +260,8 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } - if(((!strcmp(string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || - (!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && temp_data32 == SUBGHZ_KEY_FILE_VERSION) { } else { FURI_LOG_E(TAG, "Type or version mismatch"); @@ -285,27 +285,29 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } - if(!subghz_set_preset(subghz, string_get_cstr(temp_str))) { + if(!subghz_set_preset(subghz, furi_string_get_cstr(temp_str))) { break; } - if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { //Todo add Custom_preset_module //delete preset if it already exists subghz_setting_delete_custom_preset( - subghz->setting, string_get_cstr(subghz->txrx->preset->name)); + subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name)); //load custom preset from file if(!subghz_setting_load_custom_preset( - subghz->setting, string_get_cstr(subghz->txrx->preset->name), fff_data_file)) { + subghz->setting, + furi_string_get_cstr(subghz->txrx->preset->name), + fff_data_file)) { FURI_LOG_E(TAG, "Missing Custom preset"); break; } } size_t preset_index = subghz_setting_get_inx_preset_by_name( - subghz->setting, string_get_cstr(subghz->txrx->preset->name)); + subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name)); subghz_preset_init( subghz, - string_get_cstr(subghz->txrx->preset->name), + furi_string_get_cstr(subghz->txrx->preset->name), subghz->txrx->preset->frequency, subghz_setting_get_preset_data(subghz->setting, preset_index), subghz_setting_get_preset_data_size(subghz->setting, preset_index)); @@ -314,7 +316,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { FURI_LOG_E(TAG, "Missing Protocol"); break; } - if(!strcmp(string_get_cstr(temp_str), "RAW")) { + if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { //if RAW subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, file_path); } else { @@ -324,7 +326,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { } subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, string_get_cstr(temp_str)); + subghz->txrx->receiver, furi_string_get_cstr(temp_str)); if(subghz->txrx->decoder_result) { if(!subghz_protocol_decoder_base_deserialize( subghz->txrx->decoder_result, subghz->txrx->fff_data)) { @@ -338,7 +340,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { load_key_state = SubGhzLoadKeyStateOK; } while(0); - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); @@ -362,42 +364,42 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { furi_assert(subghz); Storage* storage = furi_record_open(RECORD_STORAGE); - string_t temp_str; - string_t file_name; - string_t file_path; + FuriString* temp_str; + FuriString* file_name; + FuriString* file_path; - string_init(temp_str); - string_init(file_name); - string_init(file_path); + temp_str = furi_string_alloc(); + file_name = furi_string_alloc(); + file_path = furi_string_alloc(); bool res = false; if(subghz_path_is_file(subghz->file_path)) { //get the name of the next free file path_extract_filename(subghz->file_path, file_name, true); - path_extract_dirname(string_get_cstr(subghz->file_path), file_path); + path_extract_dirname(furi_string_get_cstr(subghz->file_path), file_path); storage_get_next_filename( storage, - string_get_cstr(file_path), - string_get_cstr(file_name), + furi_string_get_cstr(file_path), + furi_string_get_cstr(file_name), SUBGHZ_APP_EXTENSION, file_name, max_len); - string_printf( + furi_string_printf( temp_str, "%s/%s%s", - string_get_cstr(file_path), - string_get_cstr(file_name), + furi_string_get_cstr(file_path), + furi_string_get_cstr(file_name), SUBGHZ_APP_EXTENSION); - string_set(subghz->file_path, temp_str); + furi_string_set(subghz->file_path, temp_str); res = true; } - string_clear(temp_str); - string_clear(file_path); - string_clear(file_name); + furi_string_free(temp_str); + furi_string_free(file_path); + furi_string_free(file_name); furi_record_close(RECORD_STORAGE); return res; @@ -415,8 +417,8 @@ bool subghz_save_protocol_to_file( Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); bool saved = false; - string_t file_dir; - string_init(file_dir); + FuriString* file_dir; + file_dir = furi_string_alloc(); path_extract_dirname(dev_file_name, file_dir); do { @@ -425,7 +427,7 @@ bool subghz_save_protocol_to_file( flipper_format_delete_key(flipper_format, "Manufacture"); // Create subghz folder directory if necessary - if(!storage_simply_mkdir(storage, string_get_cstr(file_dir))) { + if(!storage_simply_mkdir(storage, furi_string_get_cstr(file_dir))) { dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); break; } @@ -439,7 +441,7 @@ bool subghz_save_protocol_to_file( saved = true; } while(0); - string_clear(file_dir); + furi_string_free(file_dir); furi_record_close(RECORD_STORAGE); return saved; } @@ -447,8 +449,8 @@ bool subghz_save_protocol_to_file( bool subghz_load_protocol_from_file(SubGhz* subghz) { furi_assert(subghz); - string_t file_path; - string_init(file_path); + FuriString* file_path; + file_path = furi_string_alloc(); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); @@ -458,10 +460,10 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { subghz->dialogs, subghz->file_path, subghz->file_path, &browser_options); if(res) { - res = subghz_key_load(subghz, string_get_cstr(subghz->file_path), true); + res = subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), true); } - string_clear(file_path); + furi_string_free(file_path); return res; } @@ -472,9 +474,11 @@ bool subghz_rename_file(SubGhz* subghz) { Storage* storage = furi_record_open(RECORD_STORAGE); - if(string_cmp(subghz->file_path_tmp, subghz->file_path)) { + if(furi_string_cmp(subghz->file_path_tmp, subghz->file_path)) { FS_Error fs_result = storage_common_rename( - storage, string_get_cstr(subghz->file_path_tmp), string_get_cstr(subghz->file_path)); + storage, + furi_string_get_cstr(subghz->file_path_tmp), + furi_string_get_cstr(subghz->file_path)); if(fs_result != FSE_OK) { dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory"); @@ -490,7 +494,7 @@ bool subghz_delete_file(SubGhz* subghz) { furi_assert(subghz); Storage* storage = furi_record_open(RECORD_STORAGE); - bool result = storage_simply_remove(storage, string_get_cstr(subghz->file_path_tmp)); + bool result = storage_simply_remove(storage, furi_string_get_cstr(subghz->file_path_tmp)); furi_record_close(RECORD_STORAGE); subghz_file_name_clear(subghz); @@ -500,12 +504,12 @@ bool subghz_delete_file(SubGhz* subghz) { void subghz_file_name_clear(SubGhz* subghz) { furi_assert(subghz); - string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); - string_reset(subghz->file_path_tmp); + furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); + furi_string_reset(subghz->file_path_tmp); } -bool subghz_path_is_file(string_t path) { - return string_end_with_str_p(path, SUBGHZ_APP_EXTENSION); +bool subghz_path_is_file(FuriString* path) { + return furi_string_end_with(path, SUBGHZ_APP_EXTENSION); } uint32_t subghz_random_serial(void) { diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 99a0f8a2..58d30717 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -75,8 +75,8 @@ struct SubGhz { TextInput* text_input; Widget* widget; DialogsApp* dialogs; - string_t file_path; - string_t file_path_tmp; + FuriString* file_path; + FuriString* file_path_tmp; char file_name_tmp[SUBGHZ_MAX_LEN_NAME]; SubGhzNotificationState state_notifications; @@ -89,7 +89,7 @@ struct SubGhz { SubGhzTestStatic* subghz_test_static; SubGhzTestCarrier* subghz_test_carrier; SubGhzTestPacket* subghz_test_packet; - string_t error_str; + FuriString* error_str; SubGhzSetting* setting; SubGhzLock lock; @@ -103,7 +103,7 @@ void subghz_preset_init( uint8_t* preset_data, size_t preset_data_size); bool subghz_set_preset(SubGhz* subghz, const char* preset); -void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation); +void subghz_get_frequency_modulation(SubGhz* subghz, FuriString* frequency, FuriString* modulation); void subghz_begin(SubGhz* subghz, uint8_t* preset_data); uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency); void subghz_rx_end(SubGhz* subghz); @@ -125,6 +125,6 @@ bool subghz_load_protocol_from_file(SubGhz* subghz); bool subghz_rename_file(SubGhz* subghz); bool subghz_delete_file(SubGhz* subghz); void subghz_file_name_clear(SubGhz* subghz); -bool subghz_path_is_file(string_t path); +bool subghz_path_is_file(FuriString* path); uint32_t subghz_random_serial(void); void subghz_hopper_update(SubGhz* subghz); diff --git a/applications/main/subghz/subghz_setting.c b/applications/main/subghz/subghz_setting.c index b7c143cd..e0322f6a 100644 --- a/applications/main/subghz/subghz_setting.c +++ b/applications/main/subghz/subghz_setting.c @@ -158,7 +158,7 @@ static const uint32_t subghz_hopper_frequency_list_region_jp[] = { }; typedef struct { - string_t custom_preset_name; + FuriString* custom_preset_name; uint8_t* custom_preset_data; size_t custom_preset_data_size; } SubGhzSettingCustomPresetItem; @@ -194,7 +194,7 @@ SubGhzSetting* subghz_setting_alloc(void) { static void subghz_setting_preset_reset(SubGhzSetting* instance) { for M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) { - string_clear(item->custom_preset_name); + furi_string_free(item->custom_preset_name); free(item->custom_preset_data); } SubGhzSettingCustomPresetItemArray_reset(instance->preset->data); @@ -206,7 +206,7 @@ void subghz_setting_free(SubGhzSetting* instance) { FrequencyList_clear(instance->hopper_frequencies); for M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) { - string_clear(item->custom_preset_name); + furi_string_free(item->custom_preset_name); free(item->custom_preset_data); } SubGhzSettingCustomPresetItemArray_clear(instance->preset->data); @@ -225,8 +225,8 @@ static void subghz_setting_load_default_preset( SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data); - string_init(item->custom_preset_name); - string_set(item->custom_preset_name, preset_name); + item->custom_preset_name = furi_string_alloc(); + furi_string_set(item->custom_preset_name, preset_name); while(preset_data[preset_data_count]) { preset_data_count += 2; @@ -314,8 +314,8 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t temp_data32; bool temp_bool; @@ -333,7 +333,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { break; } - if((!strcmp(string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) && + if((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) && temp_data32 == SUBGHZ_SETTING_FILE_VERSION) { } else { FURI_LOG_E(TAG, "Type or version mismatch"); @@ -402,15 +402,15 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { break; } while(flipper_format_read_string(fff_data_file, "Custom_preset_name", temp_str)) { - FURI_LOG_I(TAG, "Custom preset loaded %s", string_get_cstr(temp_str)); + FURI_LOG_I(TAG, "Custom preset loaded %s", furi_string_get_cstr(temp_str)); subghz_setting_load_custom_preset( - instance, string_get_cstr(temp_str), fff_data_file); + instance, furi_string_get_cstr(temp_str), fff_data_file); } } while(false); } - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); @@ -440,7 +440,7 @@ const char* subghz_setting_get_preset_name(SubGhzSetting* instance, size_t idx) furi_assert(instance); SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx); - return string_get_cstr(item->custom_preset_name); + return furi_string_get_cstr(item->custom_preset_name); } int subghz_setting_get_inx_preset_by_name(SubGhzSetting* instance, const char* preset_name) { @@ -448,7 +448,7 @@ int subghz_setting_get_inx_preset_by_name(SubGhzSetting* instance, const char* p size_t idx = 0; for M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) { - if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) { + if(strcmp(furi_string_get_cstr(item->custom_preset_name), preset_name) == 0) { return idx; } idx++; @@ -466,8 +466,8 @@ bool subghz_setting_load_custom_preset( uint32_t temp_data32; SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data); - string_init(item->custom_preset_name); - string_set(item->custom_preset_name, preset_name); + item->custom_preset_name = furi_string_alloc(); + furi_string_set(item->custom_preset_name, preset_name); do { if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32)) break; @@ -497,8 +497,8 @@ bool subghz_setting_delete_custom_preset(SubGhzSetting* instance, const char* pr SubGhzSettingCustomPresetItemArray_it_last(it, instance->preset->data); while(!SubGhzSettingCustomPresetItemArray_end_p(it)) { SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_ref(it); - if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) { - string_clear(item->custom_preset_name); + if(strcmp(furi_string_get_cstr(item->custom_preset_name), preset_name) == 0) { + furi_string_free(item->custom_preset_name); free(item->custom_preset_data); SubGhzSettingCustomPresetItemArray_remove(instance->preset->data, it); return true; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index c28c3363..cdebc632 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #define FRAME_HEIGHT 12 @@ -14,7 +13,7 @@ #define UNLOCK_CNT 3 typedef struct { - string_t item_str; + FuriString* item_str; uint8_t type; } SubGhzReceiverMenuItem; @@ -52,9 +51,9 @@ struct SubGhzViewReceiver { }; typedef struct { - string_t frequency_str; - string_t preset_str; - string_t history_stat_str; + FuriString* frequency_str; + FuriString* preset_str; + FuriString* history_stat_str; SubGhzReceiverHistory* history; uint16_t idx; uint16_t list_offset; @@ -68,17 +67,17 @@ void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLo if(lock == SubGhzLockOn) { subghz_receiver->lock = lock; with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - model->bar_show = SubGhzViewReceiverBarShowLock; - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowLock; }, + true); furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000)); } else { with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - model->bar_show = SubGhzViewReceiverBarShowDefault; - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowDefault; }, + true); } } @@ -96,7 +95,9 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv furi_assert(subghz_receiver); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { size_t history_item = model->history_item; uint16_t bounds = history_item > 3 ? 2 : history_item; @@ -108,8 +109,8 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv } else if(model->list_offset > model->idx - bounds) { model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); } - return true; - }); + }, + true); } void subghz_view_receiver_add_item_to_menu( @@ -118,10 +119,12 @@ void subghz_view_receiver_add_item_to_menu( uint8_t type) { furi_assert(subghz_receiver); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { SubGhzReceiverMenuItem* item_menu = SubGhzReceiverMenuItemArray_push_raw(model->history->data); - string_init_set_str(item_menu->item_str, name); + item_menu->item_str = furi_string_alloc_set(name); item_menu->type = type; if((model->idx == model->history_item - 1)) { model->history_item++; @@ -129,9 +132,8 @@ void subghz_view_receiver_add_item_to_menu( } else { model->history_item++; } - - return true; - }); + }, + true); subghz_view_receiver_update_offset(subghz_receiver); } @@ -142,12 +144,14 @@ void subghz_view_receiver_add_data_statusbar( const char* history_stat_str) { furi_assert(subghz_receiver); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - string_set_str(model->frequency_str, frequency_str); - string_set_str(model->preset_str, preset_str); - string_set_str(model->history_stat_str, history_stat_str); - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { + furi_string_set(model->frequency_str, frequency_str); + furi_string_set(model->preset_str, preset_str); + furi_string_set(model->history_stat_str, history_stat_str); + }, + true); } static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { @@ -173,15 +177,15 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_draw_line(canvas, 46, 51, 125, 51); bool scrollbar = model->history_item > 4; - string_t str_buff; - string_init(str_buff); + FuriString* str_buff; + str_buff = furi_string_alloc(); SubGhzReceiverMenuItem* item_menu; for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx); - string_set(str_buff, item_menu->item_str); + furi_string_set(str_buff, item_menu->item_str); elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); if(model->idx == idx) { subghz_view_receiver_draw_frame(canvas, i, scrollbar); @@ -189,13 +193,13 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_set_color(canvas, ColorBlack); } canvas_draw_icon(canvas, 1, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); - canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff)); - string_reset(str_buff); + canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff)); + furi_string_reset(str_buff); } if(scrollbar) { elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); } - string_clear(str_buff); + furi_string_free(str_buff); canvas_set_color(canvas, ColorBlack); @@ -213,9 +217,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_draw_str(canvas, 74, 62, "Locked"); break; case SubGhzViewReceiverBarShowToUnlockPress: - canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str)); + canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); canvas_set_font(canvas, FontSecondary); elements_bold_rounded_frame(canvas, 14, 8, 99, 48); elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); @@ -230,9 +234,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_draw_str(canvas, 74, 62, "Unlocked"); break; default: - canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str)); + canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); break; } } @@ -241,10 +245,10 @@ static void subghz_view_receiver_timer_callback(void* context) { furi_assert(context); SubGhzViewReceiver* subghz_receiver = context; with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - model->bar_show = SubGhzViewReceiverBarShowDefault; - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowDefault; }, + true); if(subghz_receiver->lock_count < UNLOCK_CNT) { subghz_receiver->callback( SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context); @@ -261,10 +265,10 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { if(subghz_receiver->lock == SubGhzLockOn) { with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - model->bar_show = SubGhzViewReceiverBarShowToUnlockPress; - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowToUnlockPress; }, + true); if(subghz_receiver->lock_count == 0) { furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000)); } @@ -275,10 +279,10 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { // subghz_receiver->callback( // SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - model->bar_show = SubGhzViewReceiverBarShowUnlock; - return true; - }); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowUnlock; }, + true); //subghz_receiver->lock = SubGhzLockOff; furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(650)); } @@ -292,29 +296,35 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { event->key == InputKeyUp && (event->type == InputTypeShort || event->type == InputTypeRepeat)) { with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { if(model->idx != 0) model->idx--; - return true; - }); + }, + true); } else if( event->key == InputKeyDown && (event->type == InputTypeShort || event->type == InputTypeRepeat)) { with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { if(model->idx != model->history_item - 1) model->idx++; - return true; - }); + }, + true); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { subghz_receiver->callback(SubGhzCustomEventViewReceiverConfig, subghz_receiver->context); } else if(event->key == InputKeyOk && event->type == InputTypeShort) { with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { if(model->history_item != 0) { subghz_receiver->callback( SubGhzCustomEventViewReceiverOK, subghz_receiver->context); } - return false; - }); + }, + false); } subghz_view_receiver_update_offset(subghz_receiver); @@ -330,21 +340,23 @@ void subghz_view_receiver_exit(void* context) { furi_assert(context); SubGhzViewReceiver* subghz_receiver = context; with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - string_reset(model->frequency_str); - string_reset(model->preset_str); - string_reset(model->history_stat_str); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { + furi_string_reset(model->frequency_str); + furi_string_reset(model->preset_str); + furi_string_reset(model->history_stat_str); for M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) { - string_clear(item_menu->item_str); + furi_string_free(item_menu->item_str); item_menu->type = 0; } SubGhzReceiverMenuItemArray_reset(model->history->data); model->idx = 0; model->list_offset = 0; model->history_item = 0; - return false; - }); + }, + false); furi_timer_stop(subghz_receiver->timer); } @@ -365,15 +377,17 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() { view_set_exit_callback(subghz_receiver->view, subghz_view_receiver_exit); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - string_init(model->frequency_str); - string_init(model->preset_str); - string_init(model->history_stat_str); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { + model->frequency_str = furi_string_alloc(); + model->preset_str = furi_string_alloc(); + model->history_stat_str = furi_string_alloc(); model->bar_show = SubGhzViewReceiverBarShowDefault; model->history = malloc(sizeof(SubGhzReceiverHistory)); SubGhzReceiverMenuItemArray_init(model->history->data); - return true; - }); + }, + true); subghz_receiver->timer = furi_timer_alloc(subghz_view_receiver_timer_callback, FuriTimerTypeOnce, subghz_receiver); return subghz_receiver; @@ -383,19 +397,21 @@ void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) { furi_assert(subghz_receiver); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - string_clear(model->frequency_str); - string_clear(model->preset_str); - string_clear(model->history_stat_str); + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { + furi_string_free(model->frequency_str); + furi_string_free(model->preset_str); + furi_string_free(model->history_stat_str); for M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) { - string_clear(item_menu->item_str); + furi_string_free(item_menu->item_str); item_menu->type = 0; } SubGhzReceiverMenuItemArray_clear(model->history->data); free(model->history); - return false; - }); + }, + false); furi_timer_free(subghz_receiver->timer); view_free(subghz_receiver->view); free(subghz_receiver); @@ -410,20 +426,19 @@ uint16_t subghz_view_receiver_get_idx_menu(SubGhzViewReceiver* subghz_receiver) furi_assert(subghz_receiver); uint32_t idx = 0; with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { - idx = model->idx; - return false; - }); + subghz_receiver->view, SubGhzViewReceiverModel * model, { idx = model->idx; }, false); return idx; } void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint16_t idx) { furi_assert(subghz_receiver); with_view_model( - subghz_receiver->view, (SubGhzViewReceiverModel * model) { + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->idx = idx; if(model->idx > 2) model->list_offset = idx - 2; - return true; - }); + }, + true); subghz_view_receiver_update_offset(subghz_receiver); } diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index d3f77315..c169f361 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -25,6 +25,8 @@ struct SubGhzFrequencyAnalyzer { typedef struct { uint32_t frequency; float rssi; + uint32_t history_frequency[3]; + bool signal; } SubGhzFrequencyAnalyzerModel; void subghz_frequency_analyzer_set_callback( @@ -38,8 +40,8 @@ void subghz_frequency_analyzer_set_callback( } void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, float rssi) { - uint8_t x = 48; - uint8_t y = 56; + uint8_t x = 20; + uint8_t y = 64; uint8_t column_number = 0; if(rssi) { rssi = (rssi + 90) / 3; @@ -53,6 +55,31 @@ void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, float rssi) { } } +static void subghz_frequency_analyzer_history_frequency_draw( + Canvas* canvas, + SubGhzFrequencyAnalyzerModel* model) { + char buffer[64]; + uint8_t x = 66; + uint8_t y = 43; + + canvas_set_font(canvas, FontKeyboard); + for(uint8_t i = 0; i < 3; i++) { + if(model->history_frequency[i]) { + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld", + model->history_frequency[i] / 1000000 % 1000, + model->history_frequency[i] / 1000 % 1000); + canvas_draw_str(canvas, x, y + i * 10, buffer); + } else { + canvas_draw_str(canvas, x, y + i * 10, "---.---"); + } + canvas_draw_str(canvas, x + 44, y + i * 10, "MHz"); + } + canvas_set_font(canvas, FontSecondary); +} + void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel* model) { char buffer[64]; @@ -60,9 +87,11 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 20, 8, "Frequency Analyzer"); - canvas_draw_str(canvas, 28, 60, "RSSI"); + canvas_draw_str(canvas, 0, 64, "RSSI"); subghz_frequency_analyzer_draw_rssi(canvas, model->rssi); + subghz_frequency_analyzer_history_frequency_draw(canvas, model); + //Frequency canvas_set_font(canvas, FontBigNumbers); snprintf( @@ -71,8 +100,14 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel "%03ld.%03ld", model->frequency / 1000000 % 1000, model->frequency / 1000 % 1000); - canvas_draw_str(canvas, 8, 35, buffer); - canvas_draw_icon(canvas, 96, 24, &I_MHz_25x11); + if(model->signal) { + canvas_draw_box(canvas, 4, 12, 121, 22); + canvas_set_color(canvas, ColorWhite); + } else { + } + + canvas_draw_str(canvas, 8, 30, buffer); + canvas_draw_icon(canvas, 96, 19, &I_MHz_25x11); } bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { @@ -85,12 +120,26 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { return true; } -void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, float rssi) { +void subghz_frequency_analyzer_pair_callback( + void* context, + uint32_t frequency, + float rssi, + bool signal) { SubGhzFrequencyAnalyzer* instance = context; if((rssi == 0.f) && (instance->locked)) { if(instance->callback) { instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context); } + //update history + with_view_model( + instance->view, + SubGhzFrequencyAnalyzerModel * model, + { + model->history_frequency[2] = model->history_frequency[1]; + model->history_frequency[1] = model->history_frequency[0]; + model->history_frequency[0] = model->frequency; + }, + false); } else if((rssi != 0.f) && (!instance->locked)) { if(instance->callback) { instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context); @@ -99,11 +148,14 @@ void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, instance->locked = (rssi != 0.f); with_view_model( - instance->view, (SubGhzFrequencyAnalyzerModel * model) { + instance->view, + SubGhzFrequencyAnalyzerModel * model, + { model->rssi = rssi; model->frequency = frequency; - return true; - }); + model->signal = signal; + }, + true); } void subghz_frequency_analyzer_enter(void* context) { @@ -121,11 +173,16 @@ void subghz_frequency_analyzer_enter(void* context) { subghz_frequency_analyzer_worker_start(instance->worker); with_view_model( - instance->view, (SubGhzFrequencyAnalyzerModel * model) { + instance->view, + SubGhzFrequencyAnalyzerModel * model, + { model->rssi = 0; model->frequency = 0; - return true; - }); + model->history_frequency[2] = 0; + model->history_frequency[1] = 0; + model->history_frequency[0] = 0; + }, + true); } void subghz_frequency_analyzer_exit(void* context) { @@ -139,10 +196,7 @@ void subghz_frequency_analyzer_exit(void* context) { subghz_frequency_analyzer_worker_free(instance->worker); with_view_model( - instance->view, (SubGhzFrequencyAnalyzerModel * model) { - model->rssi = 0; - return true; - }); + instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true); } SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() { @@ -159,10 +213,7 @@ SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() { view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit); with_view_model( - instance->view, (SubGhzFrequencyAnalyzerModel * model) { - model->rssi = 0; - return true; - }); + instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true); return instance; } diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index ccffaf42..2d951b11 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -18,10 +18,10 @@ struct SubGhzReadRAW { }; typedef struct { - string_t frequency_str; - string_t preset_str; - string_t sample_write; - string_t file_name; + FuriString* frequency_str; + FuriString* preset_str; + FuriString* sample_write; + FuriString* file_name; uint8_t* rssi_history; bool rssi_history_end; uint8_t ind_write; @@ -45,11 +45,13 @@ void subghz_read_raw_add_data_statusbar( const char* preset_str) { furi_assert(instance); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - string_set_str(model->frequency_str, frequency_str); - string_set_str(model->preset_str, preset_str); - return true; - }); + instance->view, + SubGhzReadRAWModel * model, + { + furi_string_set(model->frequency_str, frequency_str); + furi_string_set(model->preset_str, preset_str); + }, + true); } void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) { @@ -63,31 +65,35 @@ void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) { } with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { model->rssi_history[model->ind_write++] = u_rssi; if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) { model->rssi_history_end = true; model->ind_write = 0; } - return true; - }); + }, + true); } void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample) { furi_assert(instance); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - string_printf(model->sample_write, "%d spl.", sample); - return false; - }); + instance->view, + SubGhzReadRAWModel * model, + { furi_string_printf(model->sample_write, "%d spl.", sample); }, + false); } void subghz_read_raw_stop_send(SubGhzReadRAW* instance) { furi_assert(instance); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { switch(model->status) { case SubGhzReadRAWStatusTXRepeat: case SubGhzReadRAWStatusLoadKeyTXRepeat: @@ -105,19 +111,21 @@ void subghz_read_raw_stop_send(SubGhzReadRAW* instance) { model->status = SubGhzReadRAWStatusIDLE; break; } - return true; - }); + }, + true); } void subghz_read_raw_update_sin(SubGhzReadRAW* instance) { furi_assert(instance); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->ind_sin++ > 62) { model->ind_sin = 0; } - return true; - }); + }, + true); } static int8_t subghz_read_raw_tab_sin(uint8_t x) { @@ -216,10 +224,10 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { uint8_t graphics_mode = 1; canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 5, 7, string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 40, 7, string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 5, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 40, 7, furi_string_get_cstr(model->preset_str)); canvas_draw_str_aligned( - canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write)); + canvas, 126, 0, AlignRight, AlignTop, furi_string_get_cstr(model->sample_write)); canvas_draw_line(canvas, 0, 14, 115, 14); canvas_draw_line(canvas, 0, 48, 115, 48); @@ -243,7 +251,7 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { 30, AlignCenter, AlignCenter, - string_get_cstr(model->file_name), + furi_string_get_cstr(model->file_name), true); break; @@ -286,9 +294,11 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { //further check of events is not needed, we exit return false; } else if(event->key == InputKeyOk && event->type == InputTypePress) { + uint8_t ret = false; with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - uint8_t ret = false; + instance->view, + SubGhzReadRAWModel * model, + { switch(model->status) { case SubGhzReadRAWStatusIDLE: // Start TX @@ -314,11 +324,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { default: break; } - return ret; - }); + }, + ret); } else if(event->key == InputKeyOk && event->type == InputTypeRelease) { with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->status == SubGhzReadRAWStatusTXRepeat) { // Stop repeat TX model->status = SubGhzReadRAWStatusTX; @@ -326,11 +338,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { // Stop repeat TX model->status = SubGhzReadRAWStatusLoadKeyTX; } - return false; - }); + }, + false); } else if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { switch(model->status) { case SubGhzReadRAWStatusREC: //Stop REC @@ -357,11 +371,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { instance->callback(SubGhzCustomEventViewReadRAWBack, instance->context); break; } - return true; - }); + }, + true); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->status == SubGhzReadRAWStatusStart) { //Config instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context); @@ -372,15 +388,17 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { model->status = SubGhzReadRAWStatusStart; model->rssi_history_end = false; model->ind_write = 0; - string_set_str(model->sample_write, "0 spl."); - string_reset(model->file_name); + furi_string_set(model->sample_write, "0 spl."); + furi_string_reset(model->file_name); instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context); } - return true; - }); + }, + true); } else if(event->key == InputKeyRight && event->type == InputTypeShort) { with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->status == SubGhzReadRAWStatusIDLE) { //Save instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context); @@ -388,11 +406,13 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { //More instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context); } - return true; - }); + }, + true); } else if(event->key == InputKeyOk && event->type == InputTypeShort) { with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->status == SubGhzReadRAWStatusStart) { //Record instance->callback(SubGhzCustomEventViewReadRAWREC, instance->context); @@ -404,8 +424,8 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context); model->status = SubGhzReadRAWStatusIDLE; } - return true; - }); + }, + true); } return true; } @@ -419,45 +439,51 @@ void subghz_read_raw_set_status( switch(status) { case SubGhzReadRAWStatusStart: with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { model->status = SubGhzReadRAWStatusStart; model->rssi_history_end = false; model->ind_write = 0; - string_reset(model->file_name); - string_set_str(model->sample_write, "0 spl."); - return true; - }); + furi_string_reset(model->file_name); + furi_string_set(model->sample_write, "0 spl."); + }, + true); break; case SubGhzReadRAWStatusIDLE: with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - model->status = SubGhzReadRAWStatusIDLE; - return true; - }); + instance->view, + SubGhzReadRAWModel * model, + { model->status = SubGhzReadRAWStatusIDLE; }, + true); break; case SubGhzReadRAWStatusLoadKeyTX: with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { model->status = SubGhzReadRAWStatusLoadKeyIDLE; model->rssi_history_end = false; model->ind_write = 0; - string_set_str(model->file_name, file_name); - string_set_str(model->sample_write, "RAW"); - return true; - }); + furi_string_set(model->file_name, file_name); + furi_string_set(model->sample_write, "RAW"); + }, + true); break; case SubGhzReadRAWStatusSaveKey: with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { model->status = SubGhzReadRAWStatusLoadKeyIDLE; if(!model->ind_write) { - string_set_str(model->file_name, file_name); - string_set_str(model->sample_write, "RAW"); + furi_string_set(model->file_name, file_name); + furi_string_set(model->sample_write, "RAW"); } else { - string_reset(model->file_name); + furi_string_reset(model->file_name); } - return true; - }); + }, + true); break; default: @@ -476,15 +502,17 @@ void subghz_read_raw_exit(void* context) { SubGhzReadRAW* instance = context; with_view_model( - instance->view, (SubGhzReadRAWModel * model) { + instance->view, + SubGhzReadRAWModel * model, + { if(model->status != SubGhzReadRAWStatusIDLE && model->status != SubGhzReadRAWStatusStart && model->status != SubGhzReadRAWStatusLoadKeyIDLE) { instance->callback(SubGhzCustomEventViewReadRAWIDLE, instance->context); model->status = SubGhzReadRAWStatusStart; } - return true; - }); + }, + true); } SubGhzReadRAW* subghz_read_raw_alloc() { @@ -500,14 +528,16 @@ SubGhzReadRAW* subghz_read_raw_alloc() { view_set_exit_callback(instance->view, subghz_read_raw_exit); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - string_init(model->frequency_str); - string_init(model->preset_str); - string_init(model->sample_write); - string_init(model->file_name); + instance->view, + SubGhzReadRAWModel * model, + { + model->frequency_str = furi_string_alloc(); + model->preset_str = furi_string_alloc(); + model->sample_write = furi_string_alloc(); + model->file_name = furi_string_alloc(); model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t)); - return true; - }); + }, + true); return instance; } @@ -516,14 +546,16 @@ void subghz_read_raw_free(SubGhzReadRAW* instance) { furi_assert(instance); with_view_model( - instance->view, (SubGhzReadRAWModel * model) { - string_clear(model->frequency_str); - string_clear(model->preset_str); - string_clear(model->sample_write); - string_clear(model->file_name); + instance->view, + SubGhzReadRAWModel * model, + { + furi_string_free(model->frequency_str); + furi_string_free(model->preset_str); + furi_string_free(model->sample_write); + furi_string_free(model->file_name); free(model->rssi_history); - return true; - }); + }, + true); view_free(instance->view); free(instance); } diff --git a/applications/main/subghz/views/subghz_test_carrier.c b/applications/main/subghz/views/subghz_test_carrier.c index 6729eaad..e533a6aa 100644 --- a/applications/main/subghz/views/subghz_test_carrier.c +++ b/applications/main/subghz/views/subghz_test_carrier.c @@ -89,7 +89,9 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) { } with_view_model( - subghz_test_carrier->view, (SubGhzTestCarrierModel * model) { + subghz_test_carrier->view, + SubGhzTestCarrierModel * model, + { furi_hal_subghz_idle(); if(event->key == InputKeyLeft) { @@ -125,9 +127,8 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) { SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context); } } - - return true; - }); + }, + true); return true; } @@ -142,15 +143,17 @@ void subghz_test_carrier_enter(void* context) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); with_view_model( - subghz_test_carrier->view, (SubGhzTestCarrierModel * model) { + subghz_test_carrier->view, + SubGhzTestCarrierModel * model, + { model->frequency = subghz_frequencies_433_92_testing; // 433 model->real_frequency = furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]); model->path = FuriHalSubGhzPathIsolate; // isolate model->rssi = 0.0f; model->status = SubGhzTestCarrierModelStatusRx; - return true; - }); + }, + true); furi_hal_subghz_rx(); @@ -172,13 +175,14 @@ void subghz_test_carrier_rssi_timer_callback(void* context) { SubGhzTestCarrier* subghz_test_carrier = context; with_view_model( - subghz_test_carrier->view, (SubGhzTestCarrierModel * model) { + subghz_test_carrier->view, + SubGhzTestCarrierModel * model, + { if(model->status == SubGhzTestCarrierModelStatusRx) { model->rssi = furi_hal_subghz_get_rssi(); - return true; } - return false; - }); + }, + false); } SubGhzTestCarrier* subghz_test_carrier_alloc() { diff --git a/applications/main/subghz/views/subghz_test_packet.c b/applications/main/subghz/views/subghz_test_packet.c index c83aebec..a42898f7 100644 --- a/applications/main/subghz/views/subghz_test_packet.c +++ b/applications/main/subghz/views/subghz_test_packet.c @@ -68,7 +68,9 @@ static void subghz_test_packet_rssi_timer_callback(void* context) { SubGhzTestPacket* instance = context; with_view_model( - instance->view, (SubGhzTestPacketModel * model) { + instance->view, + SubGhzTestPacketModel * model, + { if(model->status == SubGhzTestPacketModelStatusRx) { model->rssi = furi_hal_subghz_get_rssi(); model->packets = instance->packet_rx; @@ -77,8 +79,8 @@ static void subghz_test_packet_rssi_timer_callback(void* context) { SUBGHZ_TEST_PACKET_COUNT - subghz_encoder_princeton_for_testing_get_repeat_left(instance->encoder); } - return true; - }); + }, + true); } static void subghz_test_packet_draw(Canvas* canvas, SubGhzTestPacketModel* model) { @@ -137,7 +139,9 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) { } with_view_model( - instance->view, (SubGhzTestPacketModel * model) { + instance->view, + SubGhzTestPacketModel * model, + { if(model->status == SubGhzTestPacketModelStatusRx) { furi_hal_subghz_stop_async_rx(); } else if(model->status == SubGhzTestPacketModelStatusTx) { @@ -179,9 +183,8 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) { instance->callback(SubGhzTestPacketEventOnlyRx, instance->context); } } - - return true; - }); + }, + true); return true; } @@ -194,15 +197,17 @@ void subghz_test_packet_enter(void* context) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); with_view_model( - instance->view, (SubGhzTestPacketModel * model) { + instance->view, + SubGhzTestPacketModel * model, + { model->frequency = subghz_frequencies_433_92_testing; model->real_frequency = furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]); model->path = FuriHalSubGhzPathIsolate; // isolate model->rssi = 0.0f; model->status = SubGhzTestPacketModelStatusRx; - return true; - }); + }, + true); furi_hal_subghz_start_async_rx(subghz_test_packet_rx_callback, instance); @@ -217,15 +222,17 @@ void subghz_test_packet_exit(void* context) { // Reinitialize IC to default state with_view_model( - instance->view, (SubGhzTestPacketModel * model) { + instance->view, + SubGhzTestPacketModel * model, + { if(model->status == SubGhzTestPacketModelStatusRx) { furi_hal_subghz_stop_async_rx(); } else if(model->status == SubGhzTestPacketModelStatusTx) { subghz_encoder_princeton_for_testing_stop(instance->encoder, furi_get_tick()); furi_hal_subghz_stop_async_tx(); } - return true; - }); + }, + true); furi_hal_subghz_sleep(); } diff --git a/applications/main/subghz/views/subghz_test_static.c b/applications/main/subghz/views/subghz_test_static.c index 7af54c3c..6abefda7 100644 --- a/applications/main/subghz/views/subghz_test_static.c +++ b/applications/main/subghz/views/subghz_test_static.c @@ -77,7 +77,9 @@ bool subghz_test_static_input(InputEvent* event, void* context) { } with_view_model( - instance->view, (SubGhzTestStaticModel * model) { + instance->view, + SubGhzTestStaticModel * model, + { if(event->type == InputTypeShort) { if(event->key == InputKeyLeft) { if(model->frequency > 0) model->frequency--; @@ -128,9 +130,8 @@ bool subghz_test_static_input(InputEvent* event, void* context) { } furi_record_close(RECORD_NOTIFICATION); } - - return true; - }); + }, + true); return true; } @@ -147,13 +148,14 @@ void subghz_test_static_enter(void* context) { instance->status_tx = SubGhzTestStaticStatusIDLE; with_view_model( - instance->view, (SubGhzTestStaticModel * model) { + instance->view, + SubGhzTestStaticModel * model, + { model->frequency = subghz_frequencies_433_92_testing; model->real_frequency = subghz_frequencies_testing[model->frequency]; model->button = 0; - - return true; - }); + }, + true); } void subghz_test_static_exit(void* context) { diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index dd2b6d32..833805cc 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -11,9 +11,9 @@ struct SubGhzViewTransmitter { }; typedef struct { - string_t frequency_str; - string_t preset_str; - string_t key_str; + FuriString* frequency_str; + FuriString* preset_str; + FuriString* key_str; uint8_t show_button; } SubGhzViewTransmitterModel; @@ -35,13 +35,15 @@ void subghz_view_transmitter_add_data_to_show( uint8_t show_button) { furi_assert(subghz_transmitter); with_view_model( - subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { - string_set_str(model->key_str, key_str); - string_set_str(model->frequency_str, frequency_str); - string_set_str(model->preset_str, preset_str); + subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { + furi_string_set(model->key_str, key_str); + furi_string_set(model->frequency_str, frequency_str); + furi_string_set(model->preset_str, preset_str); model->show_button = show_button; - return true; - }); + }, + true); } static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) { @@ -82,9 +84,9 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 8, string_get_cstr(model->key_str)); - canvas_draw_str(canvas, 78, 8, string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 113, 8, string_get_cstr(model->preset_str)); + elements_multiline_text(canvas, 0, 8, furi_string_get_cstr(model->key_str)); + canvas_draw_str(canvas, 78, 8, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 113, 8, furi_string_get_cstr(model->preset_str)); if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send"); } @@ -95,23 +97,27 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( - subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { - string_reset(model->frequency_str); - string_reset(model->preset_str); - string_reset(model->key_str); + subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { + furi_string_reset(model->frequency_str); + furi_string_reset(model->preset_str); + furi_string_reset(model->key_str); model->show_button = 0; - return false; - }); + }, + false); return false; } with_view_model( - subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { + subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { if(model->show_button) { can_be_sent = true; } - return true; - }); + }, + true); if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { subghz_transmitter->callback( @@ -149,12 +155,14 @@ SubGhzViewTransmitter* subghz_view_transmitter_alloc() { view_set_exit_callback(subghz_transmitter->view, subghz_view_transmitter_exit); with_view_model( - subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { - string_init(model->frequency_str); - string_init(model->preset_str); - string_init(model->key_str); - return true; - }); + subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { + model->frequency_str = furi_string_alloc(); + model->preset_str = furi_string_alloc(); + model->key_str = furi_string_alloc(); + }, + true); return subghz_transmitter; } @@ -162,12 +170,14 @@ void subghz_view_transmitter_free(SubGhzViewTransmitter* subghz_transmitter) { furi_assert(subghz_transmitter); with_view_model( - subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { - string_clear(model->frequency_str); - string_clear(model->preset_str); - string_clear(model->key_str); - return true; - }); + subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { + furi_string_free(model->frequency_str); + furi_string_free(model->preset_str); + furi_string_free(model->key_str); + }, + true); view_free(subghz_transmitter->view); free(subghz_transmitter); } diff --git a/applications/main/u2f/u2f_data.c b/applications/main/u2f/u2f_data.c index 117fbdbe..900af462 100644 --- a/applications/main/u2f/u2f_data.c +++ b/applications/main/u2f/u2f_data.c @@ -181,8 +181,8 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { // Check if unique key exists in secure eclave and generate it if missing if(!furi_hal_crypto_verify_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE)) return false; - string_t filetype; - string_init(filetype); + FuriString* filetype; + filetype = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -194,7 +194,7 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { break; } - if(strcmp(string_get_cstr(filetype), U2F_CERT_KEY_FILE_TYPE) != 0 || + if(strcmp(furi_string_get_cstr(filetype), U2F_CERT_KEY_FILE_TYPE) != 0 || version != U2F_CERT_KEY_VERSION) { FURI_LOG_E(TAG, "Type or version mismatch"); break; @@ -250,7 +250,7 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); - string_clear(filetype); + furi_string_free(filetype); if(cert_type == U2F_CERT_USER_UNENCRYPTED) { return u2f_data_cert_key_encrypt(cert_key); @@ -267,8 +267,8 @@ bool u2f_data_key_load(uint8_t* device_key) { uint8_t key[48]; uint32_t version = 0; - string_t filetype; - string_init(filetype); + FuriString* filetype; + filetype = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -279,7 +279,7 @@ bool u2f_data_key_load(uint8_t* device_key) { FURI_LOG_E(TAG, "Missing or incorrect header"); break; } - if(strcmp(string_get_cstr(filetype), U2F_DEVICE_KEY_FILE_TYPE) != 0 || + if(strcmp(furi_string_get_cstr(filetype), U2F_DEVICE_KEY_FILE_TYPE) != 0 || version != U2F_DEVICE_KEY_VERSION) { FURI_LOG_E(TAG, "Type or version mismatch"); break; @@ -308,7 +308,7 @@ bool u2f_data_key_load(uint8_t* device_key) { } flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); - string_clear(filetype); + furi_string_free(filetype); return state; } @@ -366,8 +366,8 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { uint8_t cnt_encr[48]; uint32_t version = 0; - string_t filetype; - string_init(filetype); + FuriString* filetype; + filetype = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -378,7 +378,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Missing or incorrect header"); break; } - if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) { + if(strcmp(furi_string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) { FURI_LOG_E(TAG, "Type mismatch"); break; } @@ -417,7 +417,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { } flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); - string_clear(filetype); + furi_string_free(filetype); if(old_counter && state) { // Change counter endianness and rewrite counter file diff --git a/applications/main/u2f/views/u2f_view.c b/applications/main/u2f/views/u2f_view.c index 11e2c9b0..fa3d6cc2 100644 --- a/applications/main/u2f/views/u2f_view.c +++ b/applications/main/u2f/views/u2f_view.c @@ -85,18 +85,17 @@ void u2f_view_set_ok_callback(U2fView* u2f, U2fOkCallback callback, void* contex furi_assert(u2f); furi_assert(callback); with_view_model( - u2f->view, (U2fModel * model) { + u2f->view, + U2fModel * model, + { UNUSED(model); u2f->callback = callback; u2f->context = context; - return false; - }); + }, + false); } void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) { with_view_model( - u2f->view, (U2fModel * model) { - model->display_msg = msg; - return true; - }); + u2f->view, U2fModel * model, { model->display_msg = msg; }, true); } diff --git a/applications/plugins/application.fam b/applications/plugins/application.fam index c88f6d28..6d25e45a 100644 --- a/applications/plugins/application.fam +++ b/applications/plugins/application.fam @@ -5,6 +5,5 @@ App( provides=[ "music_player", "snake_game", - "bt_hid", ], ) diff --git a/applications/plugins/bt_hid_app/application.fam b/applications/plugins/bt_hid_app/application.fam index e6a3b175..2712fded 100644 --- a/applications/plugins/bt_hid_app/application.fam +++ b/applications/plugins/bt_hid_app/application.fam @@ -1,15 +1,10 @@ App( appid="bt_hid", name="Bluetooth Remote", - apptype=FlipperAppType.PLUGIN, + apptype=FlipperAppType.EXTERNAL, entry_point="bt_hid_app", stack_size=1 * 1024, - cdefines=["APP_BLE_HID"], - requires=[ - "bt", - "gui", - ], - order=10, - fap_icon="bt_remote_10px.png", fap_category="Tools", + fap_icon="bt_remote_10px.png", + fap_icon_assets="assets", ) diff --git a/applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png b/applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png new file mode 100644 index 00000000..d4034efc Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png differ diff --git a/applications/plugins/bt_hid_app/assets/Arr_up_7x9.png b/applications/plugins/bt_hid_app/assets/Arr_up_7x9.png new file mode 100644 index 00000000..28b4236a Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Arr_up_7x9.png differ diff --git a/applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png b/applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png new file mode 100644 index 00000000..64dab9b5 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png differ diff --git a/applications/plugins/bt_hid_app/assets/Ble_disconnected_15x15.png b/applications/plugins/bt_hid_app/assets/Ble_disconnected_15x15.png new file mode 100644 index 00000000..0858bb93 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Ble_disconnected_15x15.png differ diff --git a/applications/plugins/bt_hid_app/assets/Button_18x18.png b/applications/plugins/bt_hid_app/assets/Button_18x18.png new file mode 100644 index 00000000..30a5b4fa Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Button_18x18.png differ diff --git a/applications/plugins/bt_hid_app/assets/Circles_47x47.png b/applications/plugins/bt_hid_app/assets/Circles_47x47.png new file mode 100644 index 00000000..6a16ebf7 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Circles_47x47.png differ diff --git a/applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png b/applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png new file mode 100644 index 00000000..c533d857 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png differ diff --git a/applications/plugins/bt_hid_app/assets/Like_def_11x9.png b/applications/plugins/bt_hid_app/assets/Like_def_11x9.png new file mode 100644 index 00000000..555bea3d Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Like_def_11x9.png differ diff --git a/applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png b/applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png new file mode 100644 index 00000000..f5bf276f Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png differ diff --git a/applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png b/applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png new file mode 100644 index 00000000..6b46ba3a Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png differ diff --git a/applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png b/applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png new file mode 100644 index 00000000..823926b8 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png differ diff --git a/applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png b/applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png new file mode 100644 index 00000000..446d7176 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png differ diff --git a/applications/plugins/bt_hid_app/assets/Space_65x18.png b/applications/plugins/bt_hid_app/assets/Space_65x18.png new file mode 100644 index 00000000..b60ae509 Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Space_65x18.png differ diff --git a/applications/plugins/bt_hid_app/assets/Voldwn_6x6.png b/applications/plugins/bt_hid_app/assets/Voldwn_6x6.png new file mode 100644 index 00000000..d7a82a2d Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Voldwn_6x6.png differ diff --git a/applications/plugins/bt_hid_app/assets/Volup_8x6.png b/applications/plugins/bt_hid_app/assets/Volup_8x6.png new file mode 100644 index 00000000..4b7ec66d Binary files /dev/null and b/applications/plugins/bt_hid_app/assets/Volup_8x6.png differ diff --git a/applications/plugins/bt_hid_app/bt_hid.c b/applications/plugins/bt_hid_app/bt_hid.c index b653fb37..4a77a249 100644 --- a/applications/plugins/bt_hid_app/bt_hid.c +++ b/applications/plugins/bt_hid_app/bt_hid.c @@ -1,6 +1,7 @@ #include "bt_hid.h" #include #include +#include #define TAG "BtHidApp" @@ -8,6 +9,7 @@ enum BtDebugSubmenuIndex { BtHidSubmenuIndexKeynote, BtHidSubmenuIndexKeyboard, BtHidSubmenuIndexMedia, + BtHidSubmenuIndexTikTok, BtHidSubmenuIndexMouse, }; @@ -26,6 +28,9 @@ void bt_hid_submenu_callback(void* context, uint32_t index) { } else if(index == BtHidSubmenuIndexMouse) { app->view_id = BtHidViewMouse; view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewMouse); + } else if(index == BtHidSubmenuIndexTikTok) { + app->view_id = BtHidViewTikTok; + view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok); } } @@ -64,6 +69,7 @@ void bt_hid_connection_status_changed_callback(BtStatus status, void* context) { bt_hid_keyboard_set_connected_status(bt_hid->bt_hid_keyboard, connected); bt_hid_media_set_connected_status(bt_hid->bt_hid_media, connected); bt_hid_mouse_set_connected_status(bt_hid->bt_hid_mouse, connected); + bt_hid_tiktok_set_connected_status(bt_hid->bt_hid_tiktok, connected); } BtHid* bt_hid_app_alloc() { @@ -90,6 +96,8 @@ BtHid* bt_hid_app_alloc() { submenu_add_item( app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app); submenu_add_item(app->submenu, "Media", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app); + submenu_add_item( + app->submenu, "TikTok Controller", BtHidSubmenuIndexTikTok, bt_hid_submenu_callback, app); submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app); view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit); view_dispatcher_add_view( @@ -126,6 +134,13 @@ BtHid* bt_hid_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, BtHidViewMedia, bt_hid_media_get_view(app->bt_hid_media)); + // TikTok view + app->bt_hid_tiktok = bt_hid_tiktok_alloc(); + view_set_previous_callback( + bt_hid_tiktok_get_view(app->bt_hid_tiktok), bt_hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, BtHidViewTikTok, bt_hid_tiktok_get_view(app->bt_hid_tiktok)); + // Mouse view app->bt_hid_mouse = bt_hid_mouse_alloc(); view_set_previous_callback(bt_hid_mouse_get_view(app->bt_hid_mouse), bt_hid_exit_confirm_view); @@ -158,6 +173,8 @@ void bt_hid_app_free(BtHid* app) { bt_hid_media_free(app->bt_hid_media); view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMouse); bt_hid_mouse_free(app->bt_hid_mouse); + view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok); + bt_hid_tiktok_free(app->bt_hid_tiktok); view_dispatcher_free(app->view_dispatcher); // Close records @@ -185,6 +202,8 @@ int32_t bt_hid_app(void* p) { } furi_hal_bt_start_advertising(); + DOLPHIN_DEED(DolphinDeedPluginStart); + view_dispatcher_run(app->view_dispatcher); bt_set_status_changed_callback(app->bt, NULL, NULL); diff --git a/applications/plugins/bt_hid_app/bt_hid.h b/applications/plugins/bt_hid_app/bt_hid.h index 0f4c7be9..89e8807f 100644 --- a/applications/plugins/bt_hid_app/bt_hid.h +++ b/applications/plugins/bt_hid_app/bt_hid.h @@ -13,6 +13,7 @@ #include "views/bt_hid_keyboard.h" #include "views/bt_hid_media.h" #include "views/bt_hid_mouse.h" +#include "views/bt_hid_tiktok.h" typedef struct { Bt* bt; @@ -25,6 +26,7 @@ typedef struct { BtHidKeyboard* bt_hid_keyboard; BtHidMedia* bt_hid_media; BtHidMouse* bt_hid_mouse; + BtHidTikTok* bt_hid_tiktok; uint32_t view_id; } BtHid; @@ -34,5 +36,6 @@ typedef enum { BtHidViewKeyboard, BtHidViewMedia, BtHidViewMouse, + BtHidViewTikTok, BtHidViewExitConfirm, } BtHidView; diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c index 3617dc0f..a1077b79 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c @@ -5,6 +5,8 @@ #include #include +#include "bt_hid_icons.h" + struct BtHidKeyboard { View* view; }; @@ -209,6 +211,11 @@ static void bt_hid_keyboard_draw_callback(Canvas* canvas, void* context) { canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keyboard"); + + canvas_draw_icon(canvas, 68, 3, &I_Pin_back_arrow_10x8); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned(canvas, 127, 4, AlignRight, AlignTop, "Hold to exit"); + elements_multiline_text_aligned( canvas, 4, 60, AlignLeft, AlignBottom, "Waiting for Connection..."); return; // Dont render the keyboard if we are not yet connected @@ -272,7 +279,9 @@ static void bt_hid_keyboard_get_select_key(BtHidKeyboardModel* model, BtHidKeybo static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* event) { with_view_model( - bt_hid_keyboard->view, (BtHidKeyboardModel * model) { + bt_hid_keyboard->view, + BtHidKeyboardModel * model, + { if(event->key == InputKeyOk) { if(event->type == InputTypePress) { model->ok_pressed = true; @@ -333,8 +342,8 @@ static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 1, .y = 0}); } } - return true; - }); + }, + true); } static bool bt_hid_keyboard_input_callback(InputEvent* event, void* context) { @@ -377,8 +386,5 @@ View* bt_hid_keyboard_get_view(BtHidKeyboard* bt_hid_keyboard) { void bt_hid_keyboard_set_connected_status(BtHidKeyboard* bt_hid_keyboard, bool connected) { furi_assert(bt_hid_keyboard); with_view_model( - bt_hid_keyboard->view, (BtHidKeyboardModel * model) { - model->connected = connected; - return true; - }); + bt_hid_keyboard->view, BtHidKeyboardModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keynote.c b/applications/plugins/bt_hid_app/views/bt_hid_keynote.c index ea4ee16f..0e81c5fa 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_keynote.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_keynote.c @@ -4,6 +4,8 @@ #include #include +#include "bt_hid_icons.h" + struct BtHidKeynote { View* view; }; @@ -106,7 +108,9 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* event) { with_view_model( - bt_hid_keynote->view, (BtHidKeynoteModel * model) { + bt_hid_keynote->view, + BtHidKeynoteModel * model, + { if(event->type == InputTypePress) { if(event->key == InputKeyUp) { model->up_pressed = true; @@ -153,8 +157,8 @@ static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* eve furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_AC_BACK); } } - return true; - }); + }, + true); } static bool bt_hid_keynote_input_callback(InputEvent* event, void* context) { @@ -197,8 +201,5 @@ View* bt_hid_keynote_get_view(BtHidKeynote* bt_hid_keynote) { void bt_hid_keynote_set_connected_status(BtHidKeynote* bt_hid_keynote, bool connected) { furi_assert(bt_hid_keynote); with_view_model( - bt_hid_keynote->view, (BtHidKeynoteModel * model) { - model->connected = connected; - return true; - }); + bt_hid_keynote->view, BtHidKeynoteModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/bt_hid_app/views/bt_hid_media.c b/applications/plugins/bt_hid_app/views/bt_hid_media.c index 258ea0a4..df7349a9 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_media.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_media.c @@ -4,6 +4,8 @@ #include #include +#include "bt_hid_icons.h" + struct BtHidMedia { View* view; }; @@ -107,7 +109,9 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* event) { with_view_model( - bt_hid_media->view, (BtHidMediaModel * model) { + bt_hid_media->view, + BtHidMediaModel * model, + { if(event->key == InputKeyUp) { model->up_pressed = true; furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT); @@ -124,13 +128,15 @@ static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* eve model->ok_pressed = true; furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_PLAY_PAUSE); } - return true; - }); + }, + true); } static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* event) { with_view_model( - bt_hid_media->view, (BtHidMediaModel * model) { + bt_hid_media->view, + BtHidMediaModel * model, + { if(event->key == InputKeyUp) { model->up_pressed = false; furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT); @@ -147,8 +153,8 @@ static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* e model->ok_pressed = false; furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_PLAY_PAUSE); } - return true; - }); + }, + true); } static bool bt_hid_media_input_callback(InputEvent* event, void* context) { @@ -196,8 +202,5 @@ View* bt_hid_media_get_view(BtHidMedia* bt_hid_media) { void bt_hid_media_set_connected_status(BtHidMedia* bt_hid_media, bool connected) { furi_assert(bt_hid_media); with_view_model( - bt_hid_media->view, (BtHidMediaModel * model) { - model->connected = connected; - return true; - }); + bt_hid_media->view, BtHidMediaModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/bt_hid_app/views/bt_hid_mouse.c b/applications/plugins/bt_hid_app/views/bt_hid_mouse.c index 395cb52c..bd48bab1 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_mouse.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_mouse.c @@ -4,6 +4,8 @@ #include #include +#include "bt_hid_icons.h" + struct BtHidMouse { View* view; }; @@ -103,7 +105,9 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) { static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { with_view_model( - bt_hid_mouse->view, (BtHidMouseModel * model) { + bt_hid_mouse->view, + BtHidMouseModel * model, + { if(event->key == InputKeyBack) { if(event->type == InputTypeShort) { furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT); @@ -167,8 +171,8 @@ static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { model->up_pressed = false; } } - return true; - }); + }, + true); } static bool bt_hid_mouse_input_callback(InputEvent* event, void* context) { @@ -211,8 +215,5 @@ View* bt_hid_mouse_get_view(BtHidMouse* bt_hid_mouse) { void bt_hid_mouse_set_connected_status(BtHidMouse* bt_hid_mouse, bool connected) { furi_assert(bt_hid_mouse); with_view_model( - bt_hid_mouse->view, (BtHidMouseModel * model) { - model->connected = connected; - return true; - }); + bt_hid_mouse->view, BtHidMouseModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.c b/applications/plugins/bt_hid_app/views/bt_hid_tiktok.c new file mode 100644 index 00000000..9af00157 --- /dev/null +++ b/applications/plugins/bt_hid_app/views/bt_hid_tiktok.c @@ -0,0 +1,207 @@ +#include "bt_hid_tiktok.h" +#include +#include +#include +#include + +#include "bt_hid_icons.h" + +struct BtHidTikTok { + View* view; +}; + +typedef struct { + bool left_pressed; + bool up_pressed; + bool right_pressed; + bool down_pressed; + bool ok_pressed; + bool connected; +} BtHidTikTokModel; + +static void bt_hid_tiktok_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + BtHidTikTokModel* model = context; + + // Header + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "TikTok"); + canvas_set_font(canvas, FontSecondary); + + // Keypad circles + canvas_draw_icon(canvas, 76, 8, &I_Circles_47x47); + + // Up + if(model->up_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 93, 9, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 96, 11, &I_Arr_up_7x9); + canvas_set_color(canvas, ColorBlack); + + // Down + if(model->down_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 93, 41, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 96, 44, &I_Arr_dwn_7x9); + canvas_set_color(canvas, ColorBlack); + + // Left + if(model->left_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 77, 25, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 81, 29, &I_Voldwn_6x6); + canvas_set_color(canvas, ColorBlack); + + // Right + if(model->right_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 109, 25, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 111, 29, &I_Volup_8x6); + canvas_set_color(canvas, ColorBlack); + + // Ok + if(model->ok_pressed) { + canvas_draw_icon(canvas, 91, 23, &I_Like_pressed_17x17); + } else { + canvas_draw_icon(canvas, 94, 27, &I_Like_def_11x9); + } + // Exit + canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); +} + +static void bt_hid_tiktok_process_press(BtHidTikTok* bt_hid_tiktok, InputEvent* event) { + with_view_model( + bt_hid_tiktok->view, + BtHidTikTokModel * model, + { + if(event->key == InputKeyUp) { + model->up_pressed = true; + } else if(event->key == InputKeyDown) { + model->down_pressed = true; + } else if(event->key == InputKeyLeft) { + model->left_pressed = true; + furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT); + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT); + } else if(event->key == InputKeyOk) { + model->ok_pressed = true; + } + }, + true); +} + +static void bt_hid_tiktok_process_release(BtHidTikTok* bt_hid_tiktok, InputEvent* event) { + with_view_model( + bt_hid_tiktok->view, + BtHidTikTokModel * model, + { + if(event->key == InputKeyUp) { + model->up_pressed = false; + } else if(event->key == InputKeyDown) { + model->down_pressed = false; + } else if(event->key == InputKeyLeft) { + model->left_pressed = false; + furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT); + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT); + } else if(event->key == InputKeyOk) { + model->ok_pressed = false; + } + }, + true); +} + +static bool bt_hid_tiktok_input_callback(InputEvent* event, void* context) { + furi_assert(context); + BtHidTikTok* bt_hid_tiktok = context; + bool consumed = false; + + if(event->type == InputTypePress) { + bt_hid_tiktok_process_press(bt_hid_tiktok, event); + consumed = true; + } else if(event->type == InputTypeRelease) { + bt_hid_tiktok_process_release(bt_hid_tiktok, event); + consumed = true; + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT); + consumed = true; + } else if(event->key == InputKeyUp) { + // Emulate up swipe + furi_hal_bt_hid_mouse_scroll(-6); + furi_hal_bt_hid_mouse_scroll(-12); + furi_hal_bt_hid_mouse_scroll(-19); + furi_hal_bt_hid_mouse_scroll(-12); + furi_hal_bt_hid_mouse_scroll(-6); + consumed = true; + } else if(event->key == InputKeyDown) { + // Emulate down swipe + furi_hal_bt_hid_mouse_scroll(6); + furi_hal_bt_hid_mouse_scroll(12); + furi_hal_bt_hid_mouse_scroll(19); + furi_hal_bt_hid_mouse_scroll(12); + furi_hal_bt_hid_mouse_scroll(6); + consumed = true; + } else if(event->key == InputKeyBack) { + furi_hal_bt_hid_consumer_key_release_all(); + consumed = true; + } + } + + return consumed; +} + +BtHidTikTok* bt_hid_tiktok_alloc() { + BtHidTikTok* bt_hid_tiktok = malloc(sizeof(BtHidTikTok)); + bt_hid_tiktok->view = view_alloc(); + view_set_context(bt_hid_tiktok->view, bt_hid_tiktok); + view_allocate_model(bt_hid_tiktok->view, ViewModelTypeLocking, sizeof(BtHidTikTokModel)); + view_set_draw_callback(bt_hid_tiktok->view, bt_hid_tiktok_draw_callback); + view_set_input_callback(bt_hid_tiktok->view, bt_hid_tiktok_input_callback); + + return bt_hid_tiktok; +} + +void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok) { + furi_assert(bt_hid_tiktok); + view_free(bt_hid_tiktok->view); + free(bt_hid_tiktok); +} + +View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok) { + furi_assert(bt_hid_tiktok); + return bt_hid_tiktok->view; +} + +void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected) { + furi_assert(bt_hid_tiktok); + with_view_model( + bt_hid_tiktok->view, BtHidTikTokModel * model, { model->connected = connected; }, true); +} diff --git a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h b/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h new file mode 100644 index 00000000..03c9afec --- /dev/null +++ b/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +typedef struct BtHidTikTok BtHidTikTok; + +BtHidTikTok* bt_hid_tiktok_alloc(); + +void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok); + +View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok); + +void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected); diff --git a/applications/plugins/music_player/music_player.c b/applications/plugins/music_player/music_player.c index 40e9085f..192500c2 100644 --- a/applications/plugins/music_player/music_player.c +++ b/applications/plugins/music_player/music_player.c @@ -8,8 +8,6 @@ #include #include -#include - #define TAG "MusicPlayer" #define MUSIC_PLAYER_APP_PATH_FOLDER ANY_PATH("music_player") @@ -250,12 +248,16 @@ static void music_player_worker_callback( view_port_update(music_player->view_port); } +void music_player_clear(MusicPlayer* instance) { + memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); + memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); + music_player_worker_clear(instance->worker); +} + MusicPlayer* music_player_alloc() { MusicPlayer* instance = malloc(sizeof(MusicPlayer)); instance->model = malloc(sizeof(MusicPlayerModel)); - memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); instance->model->volume = 3; instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); @@ -267,6 +269,8 @@ MusicPlayer* music_player_alloc() { instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance); + music_player_clear(instance); + instance->view_port = view_port_alloc(); view_port_draw_callback_set(instance->view_port, render_callback, instance); view_port_input_callback_set(instance->view_port, input_callback, instance); @@ -296,14 +300,14 @@ void music_player_free(MusicPlayer* instance) { int32_t music_player_app(void* p) { MusicPlayer* music_player = music_player_alloc(); - string_t file_path; - string_init(file_path); + FuriString* file_path; + file_path = furi_string_alloc(); do { if(p && strlen(p)) { - string_cat_str(file_path, p); + furi_string_set(file_path, (const char*)p); } else { - string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); + furi_string_set(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options( @@ -320,7 +324,7 @@ int32_t music_player_app(void* p) { } } - if(!music_player_worker_load(music_player->worker, string_get_cstr(file_path))) { + if(!music_player_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { FURI_LOG_E(TAG, "Unable to load file"); break; } @@ -352,9 +356,11 @@ int32_t music_player_app(void* p) { } music_player_worker_stop(music_player->worker); - } while(0); + if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg + music_player_clear(music_player); + } while(1); - string_clear(file_path); + furi_string_free(file_path); music_player_free(music_player); return 0; diff --git a/applications/plugins/music_player/music_player_cli.c b/applications/plugins/music_player/music_player_cli.c index 78200443..90060d7e 100644 --- a/applications/plugins/music_player/music_player_cli.c +++ b/applications/plugins/music_player/music_player_cli.c @@ -3,20 +3,20 @@ #include #include "music_player_worker.h" -static void music_player_cli(Cli* cli, string_t args, void* context) { +static void music_player_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); MusicPlayerWorker* music_player_worker = music_player_worker_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); do { - if(storage_common_stat(storage, string_get_cstr(args), NULL) == FSE_OK) { - if(!music_player_worker_load(music_player_worker, string_get_cstr(args))) { - printf("Failed to open file %s\r\n", string_get_cstr(args)); + if(storage_common_stat(storage, furi_string_get_cstr(args), NULL) == FSE_OK) { + if(!music_player_worker_load(music_player_worker, furi_string_get_cstr(args))) { + printf("Failed to open file %s\r\n", furi_string_get_cstr(args)); break; } } else { if(!music_player_worker_load_rtttl_from_string( - music_player_worker, string_get_cstr(args))) { + music_player_worker, furi_string_get_cstr(args))) { printf("Argument is not a file or RTTTL\r\n"); break; } diff --git a/applications/plugins/music_player/music_player_worker.c b/applications/plugins/music_player/music_player_worker.c index ca4f1d8c..3f1ac62f 100644 --- a/applications/plugins/music_player/music_player_worker.c +++ b/applications/plugins/music_player/music_player_worker.c @@ -108,6 +108,10 @@ MusicPlayerWorker* music_player_worker_alloc() { return instance; } +void music_player_worker_clear(MusicPlayerWorker* instance) { + NoteBlockArray_reset(instance->notes); +} + void music_player_worker_free(MusicPlayerWorker* instance) { furi_assert(instance); furi_thread_free(instance->thread); @@ -129,6 +133,7 @@ static bool is_space(const char c) { static size_t extract_number(const char* string, uint32_t* number) { size_t ret = 0; + *number = 0; while(is_digit(*string)) { *number *= 10; *number += (*string - '0'); @@ -140,6 +145,7 @@ static size_t extract_number(const char* string, uint32_t* number) { static size_t extract_dots(const char* string, uint32_t* number) { size_t ret = 0; + *number = 0; while(*string == '.') { *number += 1; string++; @@ -258,7 +264,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c if(!is_valid) { FURI_LOG_E( TAG, - "Invalid note: %u%c%c%u.%u", + "Invalid note: %lu%c%c%lu.%lu", duration, note_char == '\0' ? '_' : note_char, sharp_char == '\0' ? '_' : sharp_char, @@ -281,7 +287,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c if(music_player_worker_add_note(instance, semitone, duration, dots)) { FURI_LOG_D( TAG, - "Added note: %c%c%u.%u = %u %u", + "Added note: %c%c%lu.%lu = %u %lu", note_char == '\0' ? '_' : note_char, sharp_char == '\0' ? '_' : sharp_char, octave, @@ -291,7 +297,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c } else { FURI_LOG_E( TAG, - "Invalid note: %c%c%u.%u = %u %u", + "Invalid note: %c%c%lu.%lu = %u %lu", note_char == '\0' ? '_' : note_char, sharp_char == '\0' ? '_' : sharp_char, octave, @@ -326,8 +332,8 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c furi_assert(file_path); bool result = false; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -337,7 +343,8 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, MUSIC_PLAYER_FILETYPE) || (version != MUSIC_PLAYER_VERSION)) { + if(furi_string_cmp_str(temp_str, MUSIC_PLAYER_FILETYPE) || + (version != MUSIC_PLAYER_VERSION)) { FURI_LOG_E(TAG, "Incorrect file format or version"); break; } @@ -360,7 +367,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c break; } - if(!music_player_worker_parse_notes(instance, string_get_cstr(temp_str))) { + if(!music_player_worker_parse_notes(instance, furi_string_get_cstr(temp_str))) { break; } @@ -369,7 +376,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c furi_record_close(RECORD_STORAGE); flipper_format_free(file); - string_clear(temp_str); + furi_string_free(temp_str); return result; } @@ -379,8 +386,8 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const furi_assert(file_path); bool result = false; - string_t content; - string_init(content); + FuriString* content; + content = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); @@ -395,17 +402,17 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const uint8_t buffer[65] = {0}; ret = storage_file_read(file, buffer, sizeof(buffer) - 1); for(size_t i = 0; i < ret; i++) { - string_push_back(content, buffer[i]); + furi_string_push_back(content, buffer[i]); } } while(ret > 0); - string_strim(content); - if(!string_size(content)) { + furi_string_trim(content); + if(!furi_string_size(content)) { FURI_LOG_E(TAG, "Empty file"); break; } - if(!music_player_worker_load_rtttl_from_string(instance, string_get_cstr(content))) { + if(!music_player_worker_load_rtttl_from_string(instance, furi_string_get_cstr(content))) { FURI_LOG_E(TAG, "Invalid file content"); break; } @@ -415,7 +422,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const storage_file_free(file); furi_record_close(RECORD_STORAGE); - string_clear(content); + furi_string_free(content); return result; } diff --git a/applications/plugins/music_player/music_player_worker.h b/applications/plugins/music_player/music_player_worker.h index 3aa99ea3..00320b11 100644 --- a/applications/plugins/music_player/music_player_worker.h +++ b/applications/plugins/music_player/music_player_worker.h @@ -14,6 +14,8 @@ typedef struct MusicPlayerWorker MusicPlayerWorker; MusicPlayerWorker* music_player_worker_alloc(); +void music_player_worker_clear(MusicPlayerWorker* instance); + void music_player_worker_free(MusicPlayerWorker* instance); bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path); diff --git a/applications/plugins/picopass/application.fam b/applications/plugins/picopass/application.fam index 7a81e080..bbe37e06 100644 --- a/applications/plugins/picopass/application.fam +++ b/applications/plugins/picopass/application.fam @@ -10,8 +10,11 @@ App( stack_size=4 * 1024, order=30, fap_icon="../../../assets/icons/Archive/125_10px.png", - fap_libs=[ - "mbedtls", - ], fap_category="Tools", + fap_libs=["mbedtls"], + fap_private_libs=[ + Lib( + name="loclass", + ), + ], ) diff --git a/applications/plugins/picopass/loclass/optimized_cipher.c b/applications/plugins/picopass/lib/loclass/optimized_cipher.c similarity index 100% rename from applications/plugins/picopass/loclass/optimized_cipher.c rename to applications/plugins/picopass/lib/loclass/optimized_cipher.c diff --git a/applications/plugins/picopass/loclass/optimized_cipher.h b/applications/plugins/picopass/lib/loclass/optimized_cipher.h similarity index 100% rename from applications/plugins/picopass/loclass/optimized_cipher.h rename to applications/plugins/picopass/lib/loclass/optimized_cipher.h diff --git a/applications/plugins/picopass/loclass/optimized_cipherutils.c b/applications/plugins/picopass/lib/loclass/optimized_cipherutils.c similarity index 100% rename from applications/plugins/picopass/loclass/optimized_cipherutils.c rename to applications/plugins/picopass/lib/loclass/optimized_cipherutils.c diff --git a/applications/plugins/picopass/loclass/optimized_cipherutils.h b/applications/plugins/picopass/lib/loclass/optimized_cipherutils.h similarity index 100% rename from applications/plugins/picopass/loclass/optimized_cipherutils.h rename to applications/plugins/picopass/lib/loclass/optimized_cipherutils.h diff --git a/applications/plugins/picopass/loclass/optimized_elite.c b/applications/plugins/picopass/lib/loclass/optimized_elite.c similarity index 100% rename from applications/plugins/picopass/loclass/optimized_elite.c rename to applications/plugins/picopass/lib/loclass/optimized_elite.c diff --git a/applications/plugins/picopass/loclass/optimized_elite.h b/applications/plugins/picopass/lib/loclass/optimized_elite.h similarity index 100% rename from applications/plugins/picopass/loclass/optimized_elite.h rename to applications/plugins/picopass/lib/loclass/optimized_elite.h diff --git a/applications/plugins/picopass/loclass/optimized_ikeys.c b/applications/plugins/picopass/lib/loclass/optimized_ikeys.c similarity index 100% rename from applications/plugins/picopass/loclass/optimized_ikeys.c rename to applications/plugins/picopass/lib/loclass/optimized_ikeys.c diff --git a/applications/plugins/picopass/loclass/optimized_ikeys.h b/applications/plugins/picopass/lib/loclass/optimized_ikeys.h similarity index 100% rename from applications/plugins/picopass/loclass/optimized_ikeys.h rename to applications/plugins/picopass/lib/loclass/optimized_ikeys.h diff --git a/applications/plugins/picopass/picopass_device.c b/applications/plugins/picopass/picopass_device.c index e7f3e0be..b6e69cc2 100644 --- a/applications/plugins/picopass/picopass_device.c +++ b/applications/plugins/picopass/picopass_device.c @@ -18,7 +18,7 @@ PicopassDevice* picopass_device_alloc() { picopass_dev->dev_data.pacs.pin_length = 0; picopass_dev->storage = furi_record_open(RECORD_STORAGE); picopass_dev->dialogs = furi_record_open(RECORD_DIALOGS); - string_init(picopass_dev->load_path); + picopass_dev->load_path = furi_string_alloc(); return picopass_dev; } @@ -40,25 +40,25 @@ static bool picopass_device_save_file( FlipperFormat* file = flipper_format_file_alloc(dev->storage); PicopassPacs* pacs = &dev->dev_data.pacs; PicopassBlock* AA1 = dev->dev_data.AA1; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { - if(use_load_path && !string_empty_p(dev->load_path)) { + if(use_load_path && !furi_string_empty(dev->load_path)) { // Get directory name - path_extract_dirname(string_get_cstr(dev->load_path), temp_str); + path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str); // Create picopass directory if necessary - if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break; + if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(temp_str))) break; // Make path to file to save - string_cat_printf(temp_str, "/%s%s", dev_name, extension); + furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension); } else { // Create picopass directory if necessary if(!storage_simply_mkdir(dev->storage, PICOPASS_APP_FOLDER)) break; // First remove picopass device file if it was saved - string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); + furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); } // Open file - if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break; + if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; if(dev->format == PicopassDeviceSaveFormatHF) { uint32_t fc = pacs->record.FacilityCode; @@ -87,9 +87,9 @@ static bool picopass_device_save_file( AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] : PICOPASS_MAX_APP_LIMIT; for(size_t i = 0; i < app_limit; i++) { - string_printf(temp_str, "Block %d", i); + furi_string_printf(temp_str, "Block %d", i); if(!flipper_format_write_hex( - file, string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { + file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { block_saved = false; break; } @@ -117,7 +117,7 @@ static bool picopass_device_save_file( if(!saved) { dialog_message_show_storage_error(dev->dialogs, "Can not save\nfile"); } - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return saved; } @@ -132,13 +132,13 @@ bool picopass_device_save(PicopassDevice* dev, const char* dev_name) { return false; } -static bool picopass_device_load_data(PicopassDevice* dev, string_t path, bool show_dialog) { +static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, bool show_dialog) { bool parsed = false; FlipperFormat* file = flipper_format_file_alloc(dev->storage); PicopassBlock* AA1 = dev->dev_data.AA1; PicopassPacs* pacs = &dev->dev_data.pacs; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); bool deprecated_version = false; if(dev->loading_cb) { @@ -146,12 +146,13 @@ static bool picopass_device_load_data(PicopassDevice* dev, string_t path, bool s } do { - if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break; + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break; // Read and verify file header uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, picopass_file_header) || (version != picopass_file_version)) { + if(furi_string_cmp_str(temp_str, picopass_file_header) || + (version != picopass_file_version)) { deprecated_version = true; break; } @@ -159,9 +160,9 @@ static bool picopass_device_load_data(PicopassDevice* dev, string_t path, bool s // Parse header blocks bool block_read = true; for(size_t i = 0; i < 6; i++) { - string_printf(temp_str, "Block %d", i); + furi_string_printf(temp_str, "Block %d", i); if(!flipper_format_read_hex( - file, string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { + file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { block_read = false; break; } @@ -169,9 +170,9 @@ static bool picopass_device_load_data(PicopassDevice* dev, string_t path, bool s size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0]; for(size_t i = 6; i < app_limit; i++) { - string_printf(temp_str, "Block %d", i); + furi_string_printf(temp_str, "Block %d", i); if(!flipper_format_read_hex( - file, string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { + file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { block_read = false; break; } @@ -196,7 +197,7 @@ static bool picopass_device_load_data(PicopassDevice* dev, string_t path, bool s } } - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return parsed; @@ -208,7 +209,7 @@ void picopass_device_clear(PicopassDevice* dev) { picopass_device_data_clear(&dev->dev_data); memset(&dev->dev_data, 0, sizeof(dev->dev_data)); dev->format = PicopassDeviceSaveFormatHF; - string_reset(dev->load_path); + furi_string_reset(dev->load_path); } void picopass_device_free(PicopassDevice* picopass_dev) { @@ -216,7 +217,7 @@ void picopass_device_free(PicopassDevice* picopass_dev) { picopass_device_clear(picopass_dev); furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_DIALOGS); - string_clear(picopass_dev->load_path); + furi_string_free(picopass_dev->load_path); free(picopass_dev); } @@ -224,8 +225,8 @@ bool picopass_file_select(PicopassDevice* dev) { furi_assert(dev); // Input events and views are managed by file_browser - string_t picopass_app_folder; - string_init_set_str(picopass_app_folder, PICOPASS_APP_FOLDER); + FuriString* picopass_app_folder; + picopass_app_folder = furi_string_alloc_set(PICOPASS_APP_FOLDER); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px); @@ -233,17 +234,17 @@ bool picopass_file_select(PicopassDevice* dev) { bool res = dialog_file_browser_show( dev->dialogs, dev->load_path, picopass_app_folder, &browser_options); - string_clear(picopass_app_folder); + furi_string_free(picopass_app_folder); if(res) { - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); path_extract_filename(dev->load_path, filename, true); - strncpy(dev->dev_name, string_get_cstr(filename), PICOPASS_DEV_NAME_MAX_LEN); + strncpy(dev->dev_name, furi_string_get_cstr(filename), PICOPASS_DEV_NAME_MAX_LEN); res = picopass_device_load_data(dev, dev->load_path, true); if(res) { picopass_device_set_name(dev, dev->dev_name); } - string_clear(filename); + furi_string_free(filename); } return res; @@ -262,18 +263,18 @@ bool picopass_device_delete(PicopassDevice* dev, bool use_load_path) { furi_assert(dev); bool deleted = false; - string_t file_path; - string_init(file_path); + FuriString* file_path; + file_path = furi_string_alloc(); do { // Delete original file - if(use_load_path && !string_empty_p(dev->load_path)) { - string_set(file_path, dev->load_path); + if(use_load_path && !furi_string_empty(dev->load_path)) { + furi_string_set(file_path, dev->load_path); } else { - string_printf( + furi_string_printf( file_path, "%s/%s%s", PICOPASS_APP_FOLDER, dev->dev_name, PICOPASS_APP_EXTENSION); } - if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; deleted = true; } while(0); @@ -281,7 +282,7 @@ bool picopass_device_delete(PicopassDevice* dev, bool use_load_path) { dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); } - string_clear(file_path); + furi_string_free(file_path); return deleted; } diff --git a/applications/plugins/picopass/picopass_device.h b/applications/plugins/picopass/picopass_device.h index 745b64bd..ed6bb478 100644 --- a/applications/plugins/picopass/picopass_device.h +++ b/applications/plugins/picopass/picopass_device.h @@ -7,8 +7,8 @@ #include #include "rfal_picopass.h" -#include "loclass/optimized_ikeys.h" -#include "loclass/optimized_cipher.h" +#include +#include #define PICOPASS_DEV_NAME_MAX_LEN 22 #define PICOPASS_READER_DATA_MAX_SIZE 64 @@ -71,7 +71,7 @@ typedef struct { DialogsApp* dialogs; PicopassDeviceData dev_data; char dev_name[PICOPASS_DEV_NAME_MAX_LEN + 1]; - string_t load_path; + FuriString* load_path; PicopassDeviceSaveFormat format; PicopassLoadingCallback loading_cb; void* loading_cb_ctx; diff --git a/applications/plugins/picopass/picopass_i.h b/applications/plugins/picopass/picopass_i.h index dec5a865..8e011f22 100644 --- a/applications/plugins/picopass/picopass_i.h +++ b/applications/plugins/picopass/picopass_i.h @@ -51,7 +51,7 @@ struct Picopass { PicopassDevice* dev; char text_store[PICOPASS_TEXT_STORE_SIZE + 1]; - string_t text_box_store; + FuriString* text_box_store; // Common Views Submenu* submenu; diff --git a/applications/plugins/picopass/scenes/picopass_scene_device_info.c b/applications/plugins/picopass/scenes/picopass_scene_device_info.c index 38891b67..046e9c8e 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_device_info.c +++ b/applications/plugins/picopass/scenes/picopass_scene_device_info.c @@ -14,10 +14,10 @@ void picopass_scene_device_info_widget_callback( void picopass_scene_device_info_on_enter(void* context) { Picopass* picopass = context; - string_t credential_str; - string_t wiegand_str; - string_init(credential_str); - string_init(wiegand_str); + FuriString* credential_str; + FuriString* wiegand_str; + credential_str = furi_string_alloc(); + wiegand_str = furi_string_alloc(); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -26,25 +26,31 @@ void picopass_scene_device_info_on_enter(void* context) { Widget* widget = picopass->widget; size_t bytesLength = 1 + pacs->record.bitLength / 8; - string_set_str(credential_str, ""); + furi_string_set(credential_str, ""); for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { - string_cat_printf(credential_str, " %02X", pacs->credential[i]); + furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); } if(pacs->record.valid) { - string_cat_printf( + furi_string_cat_printf( wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); } else { - string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); + furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); } widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); + widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str)); widget_add_string_element( - widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(credential_str)); + widget, + 64, + 32, + AlignCenter, + AlignCenter, + FontSecondary, + furi_string_get_cstr(credential_str)); - string_clear(credential_str); - string_clear(wiegand_str); + furi_string_free(credential_str); + furi_string_free(wiegand_str); widget_add_button_element( picopass->widget, diff --git a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index 785f3a7d..37f1db4f 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -15,12 +15,12 @@ void picopass_scene_read_card_success_widget_callback( void picopass_scene_read_card_success_on_enter(void* context) { Picopass* picopass = context; - string_t credential_str; - string_t wiegand_str; - string_t sio_str; - string_init(credential_str); - string_init(wiegand_str); - string_init(sio_str); + FuriString* credential_str; + FuriString* wiegand_str; + FuriString* sio_str; + credential_str = furi_string_alloc(); + wiegand_str = furi_string_alloc(); + sio_str = furi_string_alloc(); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -32,10 +32,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { Widget* widget = picopass->widget; if(pacs->record.bitLength == 0) { - string_cat_printf(wiegand_str, "Read Failed"); + furi_string_cat_printf(wiegand_str, "Read Failed"); if(pacs->se_enabled) { - string_cat_printf(credential_str, "SE enabled"); + furi_string_cat_printf(credential_str, "SE enabled"); } widget_add_button_element( @@ -47,20 +47,20 @@ void picopass_scene_read_card_success_on_enter(void* context) { } else { size_t bytesLength = 1 + pacs->record.bitLength / 8; - string_set_str(credential_str, ""); + furi_string_set(credential_str, ""); for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { - string_cat_printf(credential_str, " %02X", pacs->credential[i]); + furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); } if(pacs->record.valid) { - string_cat_printf( + furi_string_cat_printf( wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); } else { - string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); + furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); } if(pacs->sio) { - string_cat_printf(sio_str, "+SIO"); + furi_string_cat_printf(sio_str, "+SIO"); } widget_add_button_element( @@ -79,15 +79,21 @@ void picopass_scene_read_card_success_on_enter(void* context) { } widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); + widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str)); widget_add_string_element( - widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(credential_str)); + widget, + 64, + 32, + AlignCenter, + AlignCenter, + FontSecondary, + furi_string_get_cstr(credential_str)); widget_add_string_element( - widget, 64, 42, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(sio_str)); + widget, 64, 42, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); - string_clear(credential_str); - string_clear(wiegand_str); - string_clear(sio_str); + furi_string_free(credential_str); + furi_string_free(wiegand_str); + furi_string_free(sio_str); view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); } diff --git a/applications/plugins/picopass/scenes/picopass_scene_save_name.c b/applications/plugins/picopass/scenes/picopass_scene_save_name.c index c5fa7dd1..17ad5927 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_save_name.c +++ b/applications/plugins/picopass/scenes/picopass_scene_save_name.c @@ -1,5 +1,4 @@ #include "../picopass_i.h" -#include "m-string.h" #include #include #include @@ -31,22 +30,22 @@ void picopass_scene_save_name_on_enter(void* context) { PICOPASS_DEV_NAME_MAX_LEN, dev_name_empty); - string_t folder_path; - string_init(folder_path); + FuriString* folder_path; + folder_path = furi_string_alloc(); - if(string_end_with_str_p(picopass->dev->load_path, PICOPASS_APP_EXTENSION)) { - path_extract_dirname(string_get_cstr(picopass->dev->load_path), folder_path); + if(furi_string_end_with(picopass->dev->load_path, PICOPASS_APP_EXTENSION)) { + path_extract_dirname(furi_string_get_cstr(picopass->dev->load_path), folder_path); } else { - string_set_str(folder_path, PICOPASS_APP_FOLDER); + furi_string_set(folder_path, PICOPASS_APP_FOLDER); } ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(folder_path), PICOPASS_APP_EXTENSION, picopass->dev->dev_name); + furi_string_get_cstr(folder_path), PICOPASS_APP_EXTENSION, picopass->dev->dev_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewTextInput); - string_clear(folder_path); + furi_string_free(folder_path); } bool picopass_scene_save_name_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/plugins/signal_generator/scenes/signal_gen_scene_mco.c b/applications/plugins/signal_generator/scenes/signal_gen_scene_mco.c index 632b08c7..0855cde0 100644 --- a/applications/plugins/signal_generator/scenes/signal_gen_scene_mco.c +++ b/applications/plugins/signal_generator/scenes/signal_gen_scene_mco.c @@ -1,12 +1,17 @@ #include "../signal_gen_app_i.h" typedef enum { + LineIndexPin, LineIndexSource, LineIndexDivision, } LineIndex; +static const char* const mco_pin_names[] = { + "13(Tx)", +}; + static const char* const mco_source_names[] = { - "32768", + "32768Hz", "64MHz", "~100K", "~200K", @@ -81,14 +86,22 @@ void signal_gen_scene_mco_on_enter(void* context) { VariableItem* item; + item = variable_item_list_add(var_item_list, "GPIO Pin", COUNT_OF(mco_pin_names), NULL, NULL); + variable_item_set_current_value_index(item, 0); + variable_item_set_current_value_text(item, mco_pin_names[0]); + item = variable_item_list_add( - var_item_list, "Source", COUNT_OF(mco_source_names), mco_source_list_change_callback, app); + var_item_list, + "Frequency", + COUNT_OF(mco_source_names), + mco_source_list_change_callback, + app); variable_item_set_current_value_index(item, 0); variable_item_set_current_value_text(item, mco_source_names[0]); item = variable_item_list_add( var_item_list, - "Division", + "Freq. divider", COUNT_OF(mco_divisor_names), mco_divisor_list_change_callback, app); diff --git a/applications/plugins/signal_generator/scenes/signal_gen_scene_start.c b/applications/plugins/signal_generator/scenes/signal_gen_scene_start.c index 91f6081d..3c7b9cc3 100644 --- a/applications/plugins/signal_generator/scenes/signal_gen_scene_start.c +++ b/applications/plugins/signal_generator/scenes/signal_gen_scene_start.c @@ -16,10 +16,10 @@ void signal_gen_scene_start_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_add_item( - submenu, "PWM", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app); + submenu, "PWM Generator", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app); submenu_add_item( submenu, - "Clock Output", + "Clock Generator", SubmenuIndexClockOutput, signal_gen_scene_start_submenu_callback, app); diff --git a/applications/plugins/signal_generator/views/signal_gen_pwm.c b/applications/plugins/signal_generator/views/signal_gen_pwm.c index 00b4ef26..6d1a3c1b 100644 --- a/applications/plugins/signal_generator/views/signal_gen_pwm.c +++ b/applications/plugins/signal_generator/views/signal_gen_pwm.c @@ -9,7 +9,7 @@ typedef enum { LineIndexTotalCount } LineIndex; -static const char* const pwm_ch_names[] = {"TIM1(2)", "LPTIM2(4)"}; +static const char* const pwm_ch_names[] = {"2(A7)", "4(A4)"}; struct SignalGenPwm { View* view; @@ -31,8 +31,8 @@ typedef struct { #define ITEM_H 64 / 3 #define ITEM_W 128 -#define VALUE_X 95 -#define VALUE_W 55 +#define VALUE_X 100 +#define VALUE_W 45 #define FREQ_VALUE_X 62 #define FREQ_MAX 1000000UL @@ -44,12 +44,14 @@ static void pwm_set_config(SignalGenPwm* pwm) { uint8_t duty; with_view_model( - pwm->view, (SignalGenPwmViewModel * model) { + pwm->view, + SignalGenPwmViewModel * model, + { channel = model->channel_id; freq = model->freq; duty = model->duty; - return false; - }); + }, + false); furi_assert(pwm->callback); pwm->callback(channel, freq, duty, pwm->context); @@ -126,11 +128,11 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) { for(uint8_t line = 0; line < LineIndexTotalCount; line++) { if(line == LineIndexChannel) { - line_label = "PWM Channel"; + line_label = "GPIO Pin"; } else if(line == LineIndexFrequency) { line_label = "Frequency"; } else if(line == LineIndexDuty) { - line_label = "Duty Cycle"; + line_label = "Pulse width"; } canvas_set_color(canvas, ColorBlack); @@ -162,9 +164,9 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontSecondary); if(model->edit_mode) { - uint8_t icon_x = (FREQ_VALUE_X - 1) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6; - canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_4x7); - canvas_draw_icon(canvas, icon_x, text_y + 4, &I_SmallArrowDown_4x7); + uint8_t icon_x = (FREQ_VALUE_X) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6; + canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_3x5); + canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_3x5); } } else if(line == LineIndexDuty) { snprintf(val_text, sizeof(val_text), "%d%%", model->duty); @@ -188,7 +190,9 @@ static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) { bool need_update = false; with_view_model( - pwm->view, (SignalGenPwmViewModel * model) { + pwm->view, + SignalGenPwmViewModel * model, + { if(model->edit_mode == false) { if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { if(event->key == InputKeyUp) { @@ -238,8 +242,8 @@ static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) { } } } - return true; - }); + }, + true); if(need_update) { pwm_set_config(pwm); @@ -279,22 +283,26 @@ void signal_gen_pwm_set_callback( furi_assert(callback); with_view_model( - pwm->view, (SignalGenPwmViewModel * model) { + pwm->view, + SignalGenPwmViewModel * model, + { UNUSED(model); pwm->callback = callback; pwm->context = context; - return false; - }); + }, + false); } void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty) { with_view_model( - pwm->view, (SignalGenPwmViewModel * model) { + pwm->view, + SignalGenPwmViewModel * model, + { model->channel_id = channel_id; model->freq = freq; model->duty = duty; - return true; - }); + }, + true); furi_assert(pwm->callback); pwm->callback(channel_id, freq, duty, pwm->context); diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index b7aabb17..283d017e 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include typedef struct { // +-----x @@ -59,6 +62,35 @@ typedef struct { InputEvent input; } SnakeEvent; +const NotificationSequence sequence_fail = { + &message_vibro_on, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_vibro_off, + NULL, +}; + +const NotificationSequence sequence_eat = { + &message_note_c7, + &message_delay_50, + &message_sound_off, + NULL, +}; + static void snake_game_render_callback(Canvas* const canvas, void* ctx) { const SnakeState* snake_state = acquire_mutex((ValueMutex*)ctx, 25); if(snake_state == NULL) { @@ -230,7 +262,8 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex snake_state->points[0] = next_step; } -static void snake_game_process_game_step(SnakeState* const snake_state) { +static void + snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { if(snake_state->state == GameStateGameOver) { return; } @@ -249,6 +282,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { return; } else if(snake_state->state == GameStateLastChance) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } } else { @@ -260,6 +294,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { crush = snake_game_collision_with_tail(snake_state, next_step); if(crush) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } @@ -268,6 +303,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { snake_state->len++; if(snake_state->len >= MAX_SNAKE_LEN) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } } @@ -276,6 +312,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { if(eatFruit) { snake_state->fruit = snake_game_get_new_fruit(snake_state); + notification_message(notification, &sequence_eat); } } @@ -306,6 +343,11 @@ int32_t snake_game_app(void* p) { // Open GUI and register view_port Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + + notification_message_block(notification, &sequence_display_backlight_enforce_on); + + DOLPHIN_DEED(DolphinDeedPluginGameStart); SnakeEvent event; for(bool processing = true; processing;) { @@ -341,7 +383,7 @@ int32_t snake_game_app(void* p) { } } } else if(event.type == EventTypeTick) { - snake_game_process_game_step(snake_state); + snake_game_process_game_step(snake_state, notification); } } else { // event timeout @@ -351,10 +393,14 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } + // Wait for all notifications to be played and return backlight to normal state + notification_message_block(notification, &sequence_display_backlight_enforce_auto); + furi_timer_free(timer); view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); + furi_record_close(RECORD_NOTIFICATION); view_port_free(view_port); furi_message_queue_free(event_queue); delete_mutex(&state_mutex); diff --git a/applications/services/bt/bt_cli.c b/applications/services/bt/bt_cli.c index ff5ebb44..02bf6cee 100644 --- a/applications/services/bt/bt_cli.c +++ b/applications/services/bt/bt_cli.c @@ -7,18 +7,18 @@ #include "bt_settings.h" #include "bt_service/bt.h" -static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { +static void bt_cli_command_hci_info(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); - string_t buffer; - string_init(buffer); + FuriString* buffer; + buffer = furi_string_alloc(); furi_hal_bt_dump_state(buffer); - printf("%s", string_get_cstr(buffer)); - string_clear(buffer); + printf("%s", furi_string_get_cstr(buffer)); + furi_string_free(buffer); } -static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { +static void bt_cli_command_carrier_tx(Cli* cli, FuriString* args, void* context) { UNUSED(context); int channel = 0; int power = 0; @@ -50,7 +50,7 @@ static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { } while(false); } -static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { +static void bt_cli_command_carrier_rx(Cli* cli, FuriString* args, void* context) { UNUSED(context); int channel = 0; @@ -81,7 +81,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { } while(false); } -static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { +static void bt_cli_command_packet_tx(Cli* cli, FuriString* args, void* context) { UNUSED(context); int channel = 0; int pattern = 0; @@ -129,7 +129,7 @@ static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { } while(false); } -static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { +static void bt_cli_command_packet_rx(Cli* cli, FuriString* args, void* context) { UNUSED(context); int channel = 0; int datarate = 1; @@ -178,12 +178,12 @@ static void bt_cli_print_usage() { } } -static void bt_cli(Cli* cli, string_t args, void* context) { +static void bt_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); furi_record_open(RECORD_BT); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); BtSettings bt_settings; bt_settings_load(&bt_settings); @@ -192,24 +192,24 @@ static void bt_cli(Cli* cli, string_t args, void* context) { bt_cli_print_usage(); break; } - if(string_cmp_str(cmd, "hci_info") == 0) { + if(furi_string_cmp_str(cmd, "hci_info") == 0) { bt_cli_command_hci_info(cli, args, NULL); break; } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) && furi_hal_bt_is_testing_supported()) { - if(string_cmp_str(cmd, "tx_carrier") == 0) { + if(furi_string_cmp_str(cmd, "tx_carrier") == 0) { bt_cli_command_carrier_tx(cli, args, NULL); break; } - if(string_cmp_str(cmd, "rx_carrier") == 0) { + if(furi_string_cmp_str(cmd, "rx_carrier") == 0) { bt_cli_command_carrier_rx(cli, args, NULL); break; } - if(string_cmp_str(cmd, "tx_packet") == 0) { + if(furi_string_cmp_str(cmd, "tx_packet") == 0) { bt_cli_command_packet_tx(cli, args, NULL); break; } - if(string_cmp_str(cmd, "rx_packet") == 0) { + if(furi_string_cmp_str(cmd, "rx_packet") == 0) { bt_cli_command_packet_rx(cli, args, NULL); break; } @@ -222,7 +222,7 @@ static void bt_cli(Cli* cli, string_t args, void* context) { furi_hal_bt_start_advertising(); } - string_clear(cmd); + furi_string_free(cmd); furi_record_close(RECORD_BT); } diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index bc80acc1..c003013e 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -75,14 +75,14 @@ static void bt_pin_code_hide(Bt* bt) { static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) { furi_assert(bt); notification_message(bt->notification, &sequence_display_backlight_on); - string_t pin_str; + FuriString* pin_str; dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0); - string_init_printf(pin_str, "Verify code\n%06d", pin); + pin_str = furi_string_alloc_printf("Verify code\n%06ld", pin); dialog_message_set_text( - bt->dialog_message, string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop); + bt->dialog_message, furi_string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop); dialog_message_set_buttons(bt->dialog_message, "Cancel", "OK", NULL); DialogMessageButton button = dialog_message_show(bt->dialogs, bt->dialog_message); - string_clear(pin_str); + furi_string_free(pin_str); return button == DialogMessageButtonCenter; } @@ -165,6 +165,11 @@ static uint16_t bt_serial_event_callback(SerialServiceEvent event, void* context ret = rpc_session_get_available_size(bt->rpc_session); } else if(event.event == SerialServiceEventTypeDataSent) { furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT); + } else if(event.event == SerialServiceEventTypesBleResetRequest) { + FURI_LOG_I(TAG, "BLE restart request received"); + BtMessage message = {.type = BtMessageTypeSetProfile, .data.profile = BtProfileSerial}; + furi_check( + furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); } return ret; } @@ -226,6 +231,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { rpc_session_set_context(bt->rpc_session, bt); furi_hal_bt_serial_set_event_callback( RPC_BUFFER_SIZE, bt_serial_event_callback, bt); + furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusActive); } else { FURI_LOG_W(TAG, "RPC is busy, failed to open new session"); } @@ -241,6 +247,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { } else if(event.type == GapEventTypeDisconnected) { if(bt->profile == BtProfileSerial && bt->rpc_session) { FURI_LOG_I(TAG, "Close RPC connection"); + furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusNotActive); furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED); rpc_session_close(bt->rpc_session); furi_hal_bt_serial_set_event_callback(0, NULL, NULL); @@ -277,7 +284,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void* context) { furi_assert(context); Bt* bt = context; - FURI_LOG_I(TAG, "Changed addr start: %08lX, size changed: %d", addr, size); + FURI_LOG_I(TAG, "Changed addr start: %p, size changed: %d", addr, size); BtMessage message = {.type = BtMessageTypeKeysStorageUpdated}; furi_check( furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); @@ -330,14 +337,20 @@ static void bt_change_profile(Bt* bt, BtMessage* message) { } furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); bt->profile = message->data.profile; - *message->result = true; + if(message->result) { + *message->result = true; + } } else { FURI_LOG_E(TAG, "Failed to start Bt App"); - *message->result = false; + if(message->result) { + *message->result = false; + } } } else { bt_show_warning(bt, "Radio stack doesn't support this app"); - *message->result = false; + if(message->result) { + *message->result = false; + } } furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); } diff --git a/applications/services/cli/cli.c b/applications/services/cli/cli.c index e554ac89..f29dca9c 100644 --- a/applications/services/cli/cli.c +++ b/applications/services/cli/cli.c @@ -11,8 +11,8 @@ Cli* cli_alloc() { CliCommandTree_init(cli->commands); - string_init(cli->last_line); - string_init(cli->line); + cli->last_line = furi_string_alloc(); + cli->line = furi_string_alloc(); cli->session = NULL; @@ -138,34 +138,26 @@ void cli_nl(Cli* cli) { void cli_prompt(Cli* cli) { UNUSED(cli); - printf("\r\n>: %s", string_get_cstr(cli->line)); + printf("\r\n>: %s", furi_string_get_cstr(cli->line)); fflush(stdout); } void cli_reset(Cli* cli) { // cli->last_line is cleared and cli->line's buffer moved to cli->last_line - string_move(cli->last_line, cli->line); + furi_string_move(cli->last_line, cli->line); // Reiniting cli->line - string_init(cli->line); + cli->line = furi_string_alloc(); cli->cursor_position = 0; } static void cli_handle_backspace(Cli* cli) { if(cli->cursor_position > 0) { - furi_assert(string_size(cli->line) > 0); + furi_assert(furi_string_size(cli->line) > 0); // Other side printf("\e[D\e[1P"); fflush(stdout); // Our side - string_t temp; - string_init(temp); - string_reserve(temp, string_size(cli->line) - 1); - string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position - 1); - string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); - - // cli->line is cleared and temp's buffer moved to cli->line - string_move(cli->line, temp); - // NO MEMORY LEAK, STOP REPORTING IT + furi_string_replace_at(cli->line, cli->cursor_position - 1, 1, ""); cli->cursor_position--; } else { @@ -174,11 +166,11 @@ static void cli_handle_backspace(Cli* cli) { } static void cli_normalize_line(Cli* cli) { - string_strim(cli->line); - cli->cursor_position = string_size(cli->line); + furi_string_trim(cli->line); + cli->cursor_position = furi_string_size(cli->line); } -static void cli_execute_command(Cli* cli, CliCommand* command, string_t args) { +static void cli_execute_command(Cli* cli, CliCommand* command, FuriString* args) { if(!(command->flags & CliCommandFlagInsomniaSafe)) { furi_hal_power_insomnia_enter(); } @@ -208,25 +200,25 @@ static void cli_execute_command(Cli* cli, CliCommand* command, string_t args) { static void cli_handle_enter(Cli* cli) { cli_normalize_line(cli); - if(string_size(cli->line) == 0) { + if(furi_string_size(cli->line) == 0) { cli_prompt(cli); return; } // Command and args container - string_t command; - string_init(command); - string_t args; - string_init(args); + FuriString* command; + command = furi_string_alloc(); + FuriString* args; + args = furi_string_alloc(); // Split command and args - size_t ws = string_search_char(cli->line, ' '); - if(ws == STRING_FAILURE) { - string_set(command, cli->line); + size_t ws = furi_string_search_char(cli->line, ' '); + if(ws == FURI_STRING_FAILURE) { + furi_string_set(command, cli->line); } else { - string_set_n(command, cli->line, 0, ws); - string_set_n(args, cli->line, ws, string_size(cli->line)); - string_strim(args); + furi_string_set_n(command, cli->line, 0, ws); + furi_string_set_n(args, cli->line, ws, furi_string_size(cli->line)); + furi_string_trim(args); } // Search for command @@ -244,7 +236,7 @@ static void cli_handle_enter(Cli* cli) { cli_nl(cli); printf( "`%s` command not found, use `help` or `?` to list all available commands", - string_get_cstr(command)); + furi_string_get_cstr(command)); cli_putc(cli, CliSymbolAsciiBell); } @@ -252,59 +244,59 @@ static void cli_handle_enter(Cli* cli) { cli_prompt(cli); // Cleanup command and args - string_clear(command); - string_clear(args); + furi_string_free(command); + furi_string_free(args); } static void cli_handle_autocomplete(Cli* cli) { cli_normalize_line(cli); - if(string_size(cli->line) == 0) { + if(furi_string_size(cli->line) == 0) { return; } cli_nl(cli); // Prepare common base for autocomplete - string_t common; - string_init(common); + FuriString* common; + common = furi_string_alloc(); // Iterate throw commands for M_EACH(cli_command, cli->commands, CliCommandTree_t) { // Process only if starts with line buffer - if(string_start_with_string_p(*cli_command->key_ptr, cli->line)) { + if(furi_string_start_with(*cli_command->key_ptr, cli->line)) { // Show autocomplete option - printf("%s\r\n", string_get_cstr(*cli_command->key_ptr)); + printf("%s\r\n", furi_string_get_cstr(*cli_command->key_ptr)); // Process common base for autocomplete - if(string_size(common) > 0) { + if(furi_string_size(common) > 0) { // Choose shortest string - const size_t key_size = string_size(*cli_command->key_ptr); - const size_t common_size = string_size(common); + const size_t key_size = furi_string_size(*cli_command->key_ptr); + const size_t common_size = furi_string_size(common); const size_t min_size = key_size > common_size ? common_size : key_size; size_t i = 0; while(i < min_size) { // Stop when do not match - if(string_get_char(*cli_command->key_ptr, i) != - string_get_char(common, i)) { + if(furi_string_get_char(*cli_command->key_ptr, i) != + furi_string_get_char(common, i)) { break; } i++; } // Cut right part if any - string_left(common, i); + furi_string_left(common, i); } else { // Start with something - string_set(common, *cli_command->key_ptr); + furi_string_set(common, *cli_command->key_ptr); } } } // Replace line buffer if autocomplete better - if(string_size(common) > string_size(cli->line)) { - string_set(cli->line, common); - cli->cursor_position = string_size(cli->line); + if(furi_string_size(common) > furi_string_size(cli->line)) { + furi_string_set(cli->line, common); + cli->cursor_position = furi_string_size(cli->line); } // Cleanup - string_clear(common); + furi_string_free(common); // Show prompt cli_prompt(cli); } @@ -312,16 +304,16 @@ static void cli_handle_autocomplete(Cli* cli) { static void cli_handle_escape(Cli* cli, char c) { if(c == 'A') { // Use previous command if line buffer is empty - if(string_size(cli->line) == 0 && string_cmp(cli->line, cli->last_line) != 0) { + if(furi_string_size(cli->line) == 0 && furi_string_cmp(cli->line, cli->last_line) != 0) { // Set line buffer and cursor position - string_set(cli->line, cli->last_line); - cli->cursor_position = string_size(cli->line); + furi_string_set(cli->line, cli->last_line); + cli->cursor_position = furi_string_size(cli->line); // Show new line to user - printf("%s", string_get_cstr(cli->line)); + printf("%s", furi_string_get_cstr(cli->line)); } } else if(c == 'B') { } else if(c == 'C') { - if(cli->cursor_position < string_size(cli->line)) { + if(cli->cursor_position < furi_string_size(cli->line)) { cli->cursor_position++; printf("\e[C"); } @@ -362,21 +354,13 @@ void cli_process_input(Cli* cli) { } else if(in_chr == CliSymbolAsciiCR) { cli_handle_enter(cli); } else if(in_chr >= 0x20 && in_chr < 0x7F) { - if(cli->cursor_position == string_size(cli->line)) { - string_push_back(cli->line, in_chr); + if(cli->cursor_position == furi_string_size(cli->line)) { + furi_string_push_back(cli->line, in_chr); cli_putc(cli, in_chr); } else { - // ToDo: better way? - string_t temp; - string_init(temp); - string_reserve(temp, string_size(cli->line) + 1); - string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position); - string_push_back(temp, in_chr); - string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); - - // cli->line is cleared and temp's buffer moved to cli->line - string_move(cli->line, temp); - // NO MEMORY LEAK, STOP REPORTING IT + // Insert character to line buffer + const char in_str[2] = {in_chr, 0}; + furi_string_replace_at(cli->line, cli->cursor_position, 0, in_str); // Print character in replace mode printf("\e[4h%c\e[4l", in_chr); @@ -394,14 +378,14 @@ void cli_add_command( CliCommandFlag flags, CliCallback callback, void* context) { - string_t name_str; - string_init_set_str(name_str, name); - string_strim(name_str); + FuriString* name_str; + name_str = furi_string_alloc_set(name); + furi_string_trim(name_str); size_t name_replace; do { - name_replace = string_replace_str(name_str, " ", "_"); - } while(name_replace != STRING_FAILURE); + name_replace = furi_string_replace(name_str, " ", "_"); + } while(name_replace != FURI_STRING_FAILURE); CliCommand c; c.callback = callback; @@ -412,24 +396,24 @@ void cli_add_command( CliCommandTree_set_at(cli->commands, name_str, c); furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk); - string_clear(name_str); + furi_string_free(name_str); } void cli_delete_command(Cli* cli, const char* name) { - string_t name_str; - string_init_set_str(name_str, name); - string_strim(name_str); + FuriString* name_str; + name_str = furi_string_alloc_set(name); + furi_string_trim(name_str); size_t name_replace; do { - name_replace = string_replace_str(name_str, " ", "_"); - } while(name_replace != STRING_FAILURE); + name_replace = furi_string_replace(name_str, " ", "_"); + } while(name_replace != FURI_STRING_FAILURE); furi_check(furi_mutex_acquire(cli->mutex, FuriWaitForever) == FuriStatusOk); CliCommandTree_erase(cli->commands, name_str); furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk); - string_clear(name_str); + furi_string_free(name_str); } void cli_session_open(Cli* cli, void* session) { diff --git a/applications/services/cli/cli.h b/applications/services/cli/cli.h index 549e72cc..09f54f05 100644 --- a/applications/services/cli/cli.h +++ b/applications/services/cli/cli.h @@ -4,8 +4,7 @@ */ #pragma once - -#include +#include #ifdef __cplusplus extern "C" { @@ -43,7 +42,7 @@ typedef struct Cli Cli; * @param args string with what was passed after command * @param context pointer to whatever you gave us on cli_add_command */ -typedef void (*CliCallback)(Cli* cli, string_t args, void* context); +typedef void (*CliCallback)(Cli* cli, FuriString* args, void* context); /** Add cli command Registers you command callback * diff --git a/applications/services/cli/cli_command_gpio.c b/applications/services/cli/cli_command_gpio.c index d5ec8d65..54671eda 100644 --- a/applications/services/cli/cli_command_gpio.c +++ b/applications/services/cli/cli_command_gpio.c @@ -35,11 +35,11 @@ void cli_command_gpio_print_usage() { printf("\tread \t - Read gpio value\r\n"); } -static bool pin_name_to_int(string_t pin_name, size_t* result) { +static bool pin_name_to_int(FuriString* pin_name, size_t* result) { bool found = false; bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { - if(!string_cmp(pin_name, cli_command_gpio_pins[i].name)) { + if(!furi_string_cmp(pin_name, cli_command_gpio_pins[i].name)) { if(!cli_command_gpio_pins[i].debug || (cli_command_gpio_pins[i].debug && debug)) { *result = i; found = true; @@ -63,29 +63,29 @@ static void gpio_print_pins(void) { typedef enum { OK, ERR_CMD_SYNTAX, ERR_PIN, ERR_VALUE } GpioParseError; -static GpioParseError gpio_command_parse(string_t args, size_t* pin_num, uint8_t* value) { - string_t pin_name; - string_init(pin_name); +static GpioParseError gpio_command_parse(FuriString* args, size_t* pin_num, uint8_t* value) { + FuriString* pin_name; + pin_name = furi_string_alloc(); - size_t ws = string_search_char(args, ' '); - if(ws == STRING_FAILURE) { + size_t ws = furi_string_search_char(args, ' '); + if(ws == FURI_STRING_FAILURE) { return ERR_CMD_SYNTAX; } - string_set_n(pin_name, args, 0, ws); - string_right(args, ws); - string_strim(args); + furi_string_set_n(pin_name, args, 0, ws); + furi_string_right(args, ws); + furi_string_trim(args); if(!pin_name_to_int(pin_name, pin_num)) { - string_clear(pin_name); + furi_string_free(pin_name); return ERR_PIN; } - string_clear(pin_name); + furi_string_free(pin_name); - if(!string_cmp(args, "0")) { + if(!furi_string_cmp(args, "0")) { *value = 0; - } else if(!string_cmp(args, "1")) { + } else if(!furi_string_cmp(args, "1")) { *value = 1; } else { return ERR_VALUE; @@ -94,7 +94,7 @@ static GpioParseError gpio_command_parse(string_t args, size_t* pin_num, uint8_t return OK; } -void cli_command_gpio_mode(Cli* cli, string_t args, void* context) { +void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); @@ -104,7 +104,7 @@ void cli_command_gpio_mode(Cli* cli, string_t args, void* context) { GpioParseError err = gpio_command_parse(args, &num, &value); if(ERR_CMD_SYNTAX == err) { - cli_print_usage("gpio mode", " <0|1>", string_get_cstr(args)); + cli_print_usage("gpio mode", " <0|1>", furi_string_get_cstr(args)); return; } else if(ERR_PIN == err) { gpio_print_pins(); @@ -134,7 +134,7 @@ void cli_command_gpio_mode(Cli* cli, string_t args, void* context) { } } -void cli_command_gpio_read(Cli* cli, string_t args, void* context) { +void cli_command_gpio_read(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); @@ -156,7 +156,7 @@ void cli_command_gpio_read(Cli* cli, string_t args, void* context) { printf("Pin %s <= %u", cli_command_gpio_pins[num].name, val); } -void cli_command_gpio_set(Cli* cli, string_t args, void* context) { +void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) { UNUSED(context); size_t num = 0; @@ -164,7 +164,7 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { GpioParseError err = gpio_command_parse(args, &num, &value); if(ERR_CMD_SYNTAX == err) { - cli_print_usage("gpio set", " <0|1>", string_get_cstr(args)); + cli_print_usage("gpio set", " <0|1>", furi_string_get_cstr(args)); return; } else if(ERR_PIN == err) { gpio_print_pins(); @@ -196,9 +196,9 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { printf("Pin %s => %u", cli_command_gpio_pins[num].name, !!value); } -void cli_command_gpio(Cli* cli, string_t args, void* context) { - string_t cmd; - string_init(cmd); +void cli_command_gpio(Cli* cli, FuriString* args, void* context) { + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -206,17 +206,17 @@ void cli_command_gpio(Cli* cli, string_t args, void* context) { break; } - if(string_cmp_str(cmd, "mode") == 0) { + if(furi_string_cmp_str(cmd, "mode") == 0) { cli_command_gpio_mode(cli, args, context); break; } - if(string_cmp_str(cmd, "set") == 0) { + if(furi_string_cmp_str(cmd, "set") == 0) { cli_command_gpio_set(cli, args, context); break; } - if(string_cmp_str(cmd, "read") == 0) { + if(furi_string_cmp_str(cmd, "read") == 0) { cli_command_gpio_read(cli, args, context); break; } @@ -224,5 +224,5 @@ void cli_command_gpio(Cli* cli, string_t args, void* context) { cli_command_gpio_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } diff --git a/applications/services/cli/cli_command_gpio.h b/applications/services/cli/cli_command_gpio.h index c9b908a0..7ae5aa62 100644 --- a/applications/services/cli/cli_command_gpio.h +++ b/applications/services/cli/cli_command_gpio.h @@ -2,4 +2,4 @@ #include "cli_i.h" -void cli_command_gpio(Cli* cli, string_t args, void* context); +void cli_command_gpio(Cli* cli, FuriString* args, void* context); diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index a6dd672f..239434b7 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -7,7 +7,6 @@ #include #include #include -#include // Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'` #define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d" @@ -22,13 +21,13 @@ void cli_command_device_info_callback(const char* key, const char* value, bool l * Device Info Command * This command is intended to be used by humans */ -void cli_command_device_info(Cli* cli, string_t args, void* context) { +void cli_command_device_info(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); furi_hal_info_get(cli_command_device_info_callback, context); } -void cli_command_help(Cli* cli, string_t args, void* context) { +void cli_command_help(Cli* cli, FuriString* args, void* context) { UNUSED(args); UNUSED(context); printf("Commands we have:"); @@ -49,34 +48,34 @@ void cli_command_help(Cli* cli, string_t args, void* context) { printf("\r\n"); // Left Column if(!CliCommandTree_end_p(it_left)) { - printf("%-30s", string_get_cstr(*CliCommandTree_ref(it_left)->key_ptr)); + printf("%-30s", furi_string_get_cstr(*CliCommandTree_ref(it_left)->key_ptr)); CliCommandTree_next(it_left); } // Right Column if(!CliCommandTree_end_p(it_right)) { - printf("%s", string_get_cstr(*CliCommandTree_ref(it_right)->key_ptr)); + printf("%s", furi_string_get_cstr(*CliCommandTree_ref(it_right)->key_ptr)); CliCommandTree_next(it_right); } }; - if(string_size(args) > 0) { + if(furi_string_size(args) > 0) { cli_nl(); printf("Also I have no clue what '"); - printf("%s", string_get_cstr(args)); + printf("%s", furi_string_get_cstr(args)); printf("' is."); } } -void cli_command_date(Cli* cli, string_t args, void* context) { +void cli_command_date(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); FuriHalRtcDateTime datetime = {0}; - if(string_size(args) > 0) { + if(furi_string_size(args) > 0) { uint16_t hours, minutes, seconds, month, day, year, weekday; int ret = sscanf( - string_get_cstr(args), + furi_string_get_cstr(args), "%hu-%hu-%hu %hu:%hu:%hu %hu", &year, &month, @@ -101,7 +100,7 @@ void cli_command_date(Cli* cli, string_t args, void* context) { "Invalid datetime format, use `%s`. sscanf %d %s", "%Y-%m-%d %H:%M:%S %u", ret, - string_get_cstr(args)); + furi_string_get_cstr(args)); return; } @@ -140,97 +139,128 @@ void cli_command_date(Cli* cli, string_t args, void* context) { #define CLI_COMMAND_LOG_BUFFER_SIZE 64 void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* context) { - xStreamBufferSend(context, buffer, size, 0); + furi_stream_buffer_send(context, buffer, size, 0); } -void cli_command_log(Cli* cli, string_t args, void* context) { - UNUSED(args); +void cli_command_log_level_set_from_string(FuriString* level) { + if(furi_string_cmpi_str(level, "default") == 0) { + furi_log_set_level(FuriLogLevelDefault); + } else if(furi_string_cmpi_str(level, "none") == 0) { + furi_log_set_level(FuriLogLevelNone); + } else if(furi_string_cmpi_str(level, "error") == 0) { + furi_log_set_level(FuriLogLevelError); + } else if(furi_string_cmpi_str(level, "warn") == 0) { + furi_log_set_level(FuriLogLevelWarn); + } else if(furi_string_cmpi_str(level, "info") == 0) { + furi_log_set_level(FuriLogLevelInfo); + } else if(furi_string_cmpi_str(level, "debug") == 0) { + furi_log_set_level(FuriLogLevelDebug); + } else if(furi_string_cmpi_str(level, "trace") == 0) { + furi_log_set_level(FuriLogLevelTrace); + } else { + printf("Unknown log level\r\n"); + } +} + +void cli_command_log(Cli* cli, FuriString* args, void* context) { UNUSED(context); - StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1); + FuriStreamBuffer* ring = furi_stream_buffer_alloc(CLI_COMMAND_LOG_RING_SIZE, 1); uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE]; + FuriLogLevel previous_level = furi_log_get_level(); + bool restore_log_level = false; + + if(furi_string_size(args) > 0) { + cli_command_log_level_set_from_string(args); + restore_log_level = true; + } furi_hal_console_set_tx_callback(cli_command_log_tx_callback, ring); printf("Press CTRL+C to stop...\r\n"); while(!cli_cmd_interrupt_received(cli)) { - size_t ret = xStreamBufferReceive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50); + size_t ret = furi_stream_buffer_receive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50); cli_write(cli, buffer, ret); } furi_hal_console_set_tx_callback(NULL, NULL); - vStreamBufferDelete(ring); + if(restore_log_level) { + // There will be strange behaviour if log level is set from settings while log command is running + furi_log_set_level(previous_level); + } + + furi_stream_buffer_free(ring); } -void cli_command_vibro(Cli* cli, string_t args, void* context) { +void cli_command_vibro(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); - if(!string_cmp(args, "0")) { + if(!furi_string_cmp(args, "0")) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message_block(notification, &sequence_reset_vibro); furi_record_close(RECORD_NOTIFICATION); - } else if(!string_cmp(args, "1")) { + } else if(!furi_string_cmp(args, "1")) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message_block(notification, &sequence_set_vibro_on); furi_record_close(RECORD_NOTIFICATION); } else { - cli_print_usage("vibro", "<1|0>", string_get_cstr(args)); + cli_print_usage("vibro", "<1|0>", furi_string_get_cstr(args)); } } -void cli_command_debug(Cli* cli, string_t args, void* context) { +void cli_command_debug(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); - if(!string_cmp(args, "0")) { + if(!furi_string_cmp(args, "0")) { furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); loader_update_menu(); printf("Debug disabled."); - } else if(!string_cmp(args, "1")) { + } else if(!furi_string_cmp(args, "1")) { furi_hal_rtc_set_flag(FuriHalRtcFlagDebug); loader_update_menu(); printf("Debug enabled."); } else { - cli_print_usage("debug", "<1|0>", string_get_cstr(args)); + cli_print_usage("debug", "<1|0>", furi_string_get_cstr(args)); } } -void cli_command_led(Cli* cli, string_t args, void* context) { +void cli_command_led(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); // Get first word as light name NotificationMessage notification_led_message; - string_t light_name; - string_init(light_name); - size_t ws = string_search_char(args, ' '); - if(ws == STRING_FAILURE) { - cli_print_usage("led", " <0-255>", string_get_cstr(args)); - string_clear(light_name); + FuriString* light_name; + light_name = furi_string_alloc(); + size_t ws = furi_string_search_char(args, ' '); + if(ws == FURI_STRING_FAILURE) { + cli_print_usage("led", " <0-255>", furi_string_get_cstr(args)); + furi_string_free(light_name); return; } else { - string_set_n(light_name, args, 0, ws); - string_right(args, ws); - string_strim(args); + furi_string_set_n(light_name, args, 0, ws); + furi_string_right(args, ws); + furi_string_trim(args); } // Check light name - if(!string_cmp(light_name, "r")) { + if(!furi_string_cmp(light_name, "r")) { notification_led_message.type = NotificationMessageTypeLedRed; - } else if(!string_cmp(light_name, "g")) { + } else if(!furi_string_cmp(light_name, "g")) { notification_led_message.type = NotificationMessageTypeLedGreen; - } else if(!string_cmp(light_name, "b")) { + } else if(!furi_string_cmp(light_name, "b")) { notification_led_message.type = NotificationMessageTypeLedBlue; - } else if(!string_cmp(light_name, "bl")) { + } else if(!furi_string_cmp(light_name, "bl")) { notification_led_message.type = NotificationMessageTypeLedDisplayBacklight; } else { - cli_print_usage("led", " <0-255>", string_get_cstr(args)); - string_clear(light_name); + cli_print_usage("led", " <0-255>", furi_string_get_cstr(args)); + furi_string_free(light_name); return; } - string_clear(light_name); + furi_string_free(light_name); // Read light value from the rest of the string char* end_ptr; - uint32_t value = strtoul(string_get_cstr(args), &end_ptr, 0); + uint32_t value = strtoul(furi_string_get_cstr(args), &end_ptr, 0); if(!(value < 256 && *end_ptr == '\0')) { - cli_print_usage("led", " <0-255>", string_get_cstr(args)); + cli_print_usage("led", " <0-255>", furi_string_get_cstr(args)); return; } @@ -249,7 +279,7 @@ void cli_command_led(Cli* cli, string_t args, void* context) { furi_record_close(RECORD_NOTIFICATION); } -void cli_command_ps(Cli* cli, string_t args, void* context) { +void cli_command_ps(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); @@ -272,7 +302,7 @@ void cli_command_ps(Cli* cli, string_t args, void* context) { printf("\r\nTotal: %d", thread_num); } -void cli_command_free(Cli* cli, string_t args, void* context) { +void cli_command_free(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); @@ -286,7 +316,7 @@ void cli_command_free(Cli* cli, string_t args, void* context) { printf("Maximum pool block: %d\r\n", memmgr_pool_get_max_block()); } -void cli_command_free_blocks(Cli* cli, string_t args, void* context) { +void cli_command_free_blocks(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); @@ -294,7 +324,7 @@ void cli_command_free_blocks(Cli* cli, string_t args, void* context) { memmgr_heap_printf_free_blocks(); } -void cli_command_i2c(Cli* cli, string_t args, void* context) { +void cli_command_i2c(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); diff --git a/applications/services/cli/cli_i.h b/applications/services/cli/cli_i.h index ba4582d0..858cd0c8 100644 --- a/applications/services/cli/cli_i.h +++ b/applications/services/cli/cli_i.h @@ -36,8 +36,8 @@ struct CliSession { BPTREE_DEF2( CliCommandTree, CLI_COMMANDS_TREE_RANK, - string_t, - STRING_OPLIST, + FuriString*, + FURI_STRING_OPLIST, CliCommand, M_POD_OPLIST) @@ -47,8 +47,8 @@ struct Cli { CliCommandTree_t commands; FuriMutex* mutex; FuriSemaphore* idle_sem; - string_t last_line; - string_t line; + FuriString* last_line; + FuriString* line; CliSession* session; size_t cursor_position; diff --git a/applications/services/cli/cli_vcp.c b/applications/services/cli/cli_vcp.c index f2893a48..1e27e185 100644 --- a/applications/services/cli/cli_vcp.c +++ b/applications/services/cli/cli_vcp.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "cli_i.h" #define TAG "CliVcp" @@ -29,8 +28,8 @@ typedef enum { typedef struct { FuriThread* thread; - StreamBufferHandle_t tx_stream; - StreamBufferHandle_t rx_stream; + FuriStreamBuffer* tx_stream; + FuriStreamBuffer* rx_stream; volatile bool connected; volatile bool running; @@ -62,8 +61,8 @@ static const uint8_t ascii_eot = 0x04; static void cli_vcp_init() { if(vcp == NULL) { vcp = malloc(sizeof(CliVcp)); - vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1); - vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1); + vcp->tx_stream = furi_stream_buffer_alloc(VCP_TX_BUF_SIZE, 1); + vcp->rx_stream = furi_stream_buffer_alloc(VCP_RX_BUF_SIZE, 1); } furi_assert(vcp->thread == NULL); @@ -113,7 +112,7 @@ static int32_t vcp_worker(void* context) { #endif if(vcp->connected == false) { vcp->connected = true; - xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever); + furi_stream_buffer_send(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever); } } @@ -124,8 +123,8 @@ static int32_t vcp_worker(void* context) { #endif if(vcp->connected == true) { vcp->connected = false; - xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); - xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever); + furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); + furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever); } } @@ -134,7 +133,7 @@ static int32_t vcp_worker(void* context) { #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "StreamRx"); #endif - if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) { flags |= VcpEvtRx; missed_rx--; } @@ -142,14 +141,15 @@ static int32_t vcp_worker(void* context) { // New data received if(flags & VcpEvtRx) { - if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) { int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Rx %d", len); #endif if(len > 0) { furi_check( - xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) == + furi_stream_buffer_send( + vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) == (size_t)len); } } else { @@ -173,7 +173,7 @@ static int32_t vcp_worker(void* context) { // CDC write transfer done if(flags & VcpEvtTx) { size_t len = - xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); + furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Tx %d", len); #endif @@ -202,8 +202,8 @@ static int32_t vcp_worker(void* context) { furi_hal_usb_unlock(); furi_hal_usb_set_config(vcp->usb_if_prev, NULL); } - xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); - xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever); + furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); + furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever); break; } } @@ -229,7 +229,7 @@ static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) { size_t batch_size = size; if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE; - size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout); + size_t len = furi_stream_buffer_receive(vcp->rx_stream, buffer, batch_size, timeout); #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "rx %u ", batch_size); #endif @@ -262,7 +262,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) { size_t batch_size = size; if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN; - xStreamBufferSend(vcp->tx_stream, buffer, batch_size, FuriWaitForever); + furi_stream_buffer_send(vcp->tx_stream, buffer, batch_size, FuriWaitForever); furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx); #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "tx %u", batch_size); diff --git a/applications/services/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c index 26e1fb9c..a64a3ad0 100644 --- a/applications/services/crypto/crypto_cli.c +++ b/applications/services/crypto/crypto_cli.c @@ -17,7 +17,7 @@ void crypto_cli_print_usage() { "\tstore_key \t - Store key in secure enclave. !!! NON-REVERSABLE OPERATION - READ MANUAL FIRST !!!\r\n"); }; -void crypto_cli_encrypt(Cli* cli, string_t args) { +void crypto_cli_encrypt(Cli* cli, FuriString* args) { int key_slot = 0; bool key_loaded = false; uint8_t iv[16]; @@ -41,8 +41,8 @@ void crypto_cli_encrypt(Cli* cli, string_t args) { printf("Enter plain text and press Ctrl+C to complete encryption:\r\n"); - string_t input; - string_init(input); + FuriString* input; + input = furi_string_alloc(); char c; while(cli_read(cli, (uint8_t*)&c, 1) == 1) { if(c == CliSymbolAsciiETX) { @@ -51,14 +51,14 @@ void crypto_cli_encrypt(Cli* cli, string_t args) { } else if(c >= 0x20 && c < 0x7F) { putc(c, stdout); fflush(stdout); - string_push_back(input, c); + furi_string_push_back(input, c); } else if(c == CliSymbolAsciiCR) { printf("\r\n"); - string_cat_str(input, "\r\n"); + furi_string_cat(input, "\r\n"); } } - size_t size = string_size(input); + size_t size = furi_string_size(input); if(size > 0) { // C-string null termination and block alignments size++; @@ -66,9 +66,10 @@ void crypto_cli_encrypt(Cli* cli, string_t args) { if(remain) { size = size - remain + 16; } - string_reserve(input, size); + furi_string_reserve(input, size); uint8_t* output = malloc(size); - if(!furi_hal_crypto_encrypt((const uint8_t*)string_get_cstr(input), output, size)) { + if(!furi_hal_crypto_encrypt( + (const uint8_t*)furi_string_get_cstr(input), output, size)) { printf("Failed to encrypt input"); } else { printf("Hex-encoded encrypted data:\r\n"); @@ -83,7 +84,7 @@ void crypto_cli_encrypt(Cli* cli, string_t args) { printf("No input"); } - string_clear(input); + furi_string_free(input); } while(0); if(key_loaded) { @@ -91,7 +92,7 @@ void crypto_cli_encrypt(Cli* cli, string_t args) { } } -void crypto_cli_decrypt(Cli* cli, string_t args) { +void crypto_cli_decrypt(Cli* cli, FuriString* args) { int key_slot = 0; bool key_loaded = false; uint8_t iv[16]; @@ -115,8 +116,8 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { printf("Enter Hex-encoded data and press Ctrl+C to complete decryption:\r\n"); - string_t hex_input; - string_init(hex_input); + FuriString* hex_input; + hex_input = furi_string_alloc(); char c; while(cli_read(cli, (uint8_t*)&c, 1) == 1) { if(c == CliSymbolAsciiETX) { @@ -125,14 +126,14 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { } else if(c >= 0x20 && c < 0x7F) { putc(c, stdout); fflush(stdout); - string_push_back(hex_input, c); + furi_string_push_back(hex_input, c); } else if(c == CliSymbolAsciiCR) { printf("\r\n"); } } - string_strim(hex_input); - size_t hex_size = string_size(hex_input); + furi_string_trim(hex_input); + size_t hex_size = furi_string_size(hex_input); if(hex_size > 0 && hex_size % 2 == 0) { size_t size = hex_size / 2; uint8_t* input = malloc(size); @@ -155,7 +156,7 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { printf("Invalid or empty input"); } - string_clear(hex_input); + furi_string_free(hex_input); } while(0); if(key_loaded) { @@ -163,7 +164,7 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { } } -void crypto_cli_has_key(Cli* cli, string_t args) { +void crypto_cli_has_key(Cli* cli, FuriString* args) { UNUSED(cli); int key_slot = 0; uint8_t iv[16]; @@ -185,12 +186,12 @@ void crypto_cli_has_key(Cli* cli, string_t args) { } while(0); } -void crypto_cli_store_key(Cli* cli, string_t args) { +void crypto_cli_store_key(Cli* cli, FuriString* args) { UNUSED(cli); int key_slot = 0; int key_size = 0; - string_t key_type; - string_init(key_type); + FuriString* key_type; + key_type = furi_string_alloc(); uint8_t data[32 + 12] = {}; FuriHalCryptoKey key; @@ -207,19 +208,19 @@ void crypto_cli_store_key(Cli* cli, string_t args) { break; } - if(string_cmp_str(key_type, "master") == 0) { + if(furi_string_cmp_str(key_type, "master") == 0) { if(key_slot != 0) { printf("Master keyslot must be is 0"); break; } key.type = FuriHalCryptoKeyTypeMaster; - } else if(string_cmp_str(key_type, "simple") == 0) { + } else if(furi_string_cmp_str(key_type, "simple") == 0) { if(key_slot < 1 || key_slot > 99) { printf("Simple keyslot must be in range"); break; } key.type = FuriHalCryptoKeyTypeSimple; - } else if(string_cmp_str(key_type, "encrypted") == 0) { + } else if(furi_string_cmp_str(key_type, "encrypted") == 0) { key.type = FuriHalCryptoKeyTypeEncrypted; data_size += 12; } else { @@ -275,13 +276,13 @@ void crypto_cli_store_key(Cli* cli, string_t args) { } } while(0); - string_clear(key_type); + furi_string_free(key_type); } -static void crypto_cli(Cli* cli, string_t args, void* context) { +static void crypto_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -289,22 +290,22 @@ static void crypto_cli(Cli* cli, string_t args, void* context) { break; } - if(string_cmp_str(cmd, "encrypt") == 0) { + if(furi_string_cmp_str(cmd, "encrypt") == 0) { crypto_cli_encrypt(cli, args); break; } - if(string_cmp_str(cmd, "decrypt") == 0) { + if(furi_string_cmp_str(cmd, "decrypt") == 0) { crypto_cli_decrypt(cli, args); break; } - if(string_cmp_str(cmd, "has_key") == 0) { + if(furi_string_cmp_str(cmd, "has_key") == 0) { crypto_cli_has_key(cli, args); break; } - if(string_cmp_str(cmd, "store_key") == 0) { + if(furi_string_cmp_str(cmd, "store_key") == 0) { crypto_cli_store_key(cli, args); break; } @@ -312,7 +313,7 @@ static void crypto_cli(Cli* cli, string_t args, void* context) { crypto_cli_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } void crypto_on_system_start() { diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 1e2a521e..36c5b397 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -50,7 +49,7 @@ struct AnimationManager { AnimationManagerSetNewIdleAnimationCallback new_idle_callback; AnimationManagerSetNewIdleAnimationCallback check_blocking_callback; void* context; - string_t freezed_animation_name; + FuriString* freezed_animation_name; int32_t freezed_animation_time_left; ViewStack* view_stack; }; @@ -279,7 +278,7 @@ AnimationManager* animation_manager_alloc(void) { animation_manager->view_stack = view_stack_alloc(); View* animation_view = bubble_animation_get_view(animation_manager->animation_view); view_stack_add_view(animation_manager->view_stack, animation_view); - string_init(animation_manager->freezed_animation_name); + animation_manager->freezed_animation_name = furi_string_alloc(); animation_manager->idle_animation_timer = furi_timer_alloc(animation_manager_timer_callback, FuriTimerTypeOnce, animation_manager); @@ -317,7 +316,7 @@ void animation_manager_free(AnimationManager* animation_manager) { storage_get_pubsub(storage), animation_manager->pubsub_subscription_storage); furi_record_close(RECORD_STORAGE); - string_clear(animation_manager->freezed_animation_name); + furi_string_free(animation_manager->freezed_animation_name); View* animation_view = bubble_animation_get_view(animation_manager->animation_view); view_stack_remove_view(animation_manager->view_stack, animation_view); bubble_animation_view_free(animation_manager->animation_view); @@ -433,7 +432,7 @@ bool animation_manager_is_animation_loaded(AnimationManager* animation_manager) void animation_manager_unload_and_stall_animation(AnimationManager* animation_manager) { furi_assert(animation_manager); furi_assert(animation_manager->current_animation); - furi_assert(!string_size(animation_manager->freezed_animation_name)); + furi_assert(!furi_string_size(animation_manager->freezed_animation_name)); furi_assert( (animation_manager->state == AnimationManagerStateIdle) || (animation_manager->state == AnimationManagerStateBlocked)); @@ -461,7 +460,7 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma StorageAnimationManifestInfo* meta = animation_storage_get_meta(animation_manager->current_animation); /* copy str, not move, because it can be internal animation */ - string_set_str(animation_manager->freezed_animation_name, meta->name); + furi_string_set(animation_manager->freezed_animation_name, meta->name); bubble_animation_freeze(animation_manager->animation_view); animation_storage_free_storage_animation(&animation_manager->current_animation); @@ -470,14 +469,14 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma void animation_manager_load_and_continue_animation(AnimationManager* animation_manager) { furi_assert(animation_manager); furi_assert(!animation_manager->current_animation); - furi_assert(string_size(animation_manager->freezed_animation_name)); + furi_assert(furi_string_size(animation_manager->freezed_animation_name)); furi_assert( (animation_manager->state == AnimationManagerStateFreezedIdle) || (animation_manager->state == AnimationManagerStateFreezedBlocked)); if(animation_manager->state == AnimationManagerStateFreezedBlocked) { StorageAnimation* restore_animation = animation_storage_find_animation( - string_get_cstr(animation_manager->freezed_animation_name)); + furi_string_get_cstr(animation_manager->freezed_animation_name)); /* all blocked animations must be in flipper -> we can * always find blocking animation */ furi_assert(restore_animation); @@ -489,7 +488,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m if(!blocked) { /* if no blocking - try restore last one idle */ StorageAnimation* restore_animation = animation_storage_find_animation( - string_get_cstr(animation_manager->freezed_animation_name)); + furi_string_get_cstr(animation_manager->freezed_animation_name)); if(restore_animation) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); @@ -517,7 +516,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m FURI_LOG_E( TAG, "Failed to restore \'%s\'", - string_get_cstr(animation_manager->freezed_animation_name)); + furi_string_get_cstr(animation_manager->freezed_animation_name)); } } } else { @@ -535,7 +534,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_storage_get_meta(animation_manager->current_animation)->name); bubble_animation_unfreeze(animation_manager->animation_view); - string_reset(animation_manager->freezed_animation_name); + furi_string_reset(animation_manager->freezed_animation_name); furi_assert(animation_manager->current_animation); } diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index e0c6bf41..0727fd6a 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -5,7 +5,6 @@ #include #include #include -#include #include "animation_manager.h" #include "animation_storage.h" @@ -32,8 +31,8 @@ static bool animation_storage_load_single_manifest_info( Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); flipper_format_set_strict_mode(file, true); - string_t read_string; - string_init(read_string); + FuriString* read_string; + read_string = furi_string_alloc(); do { uint32_t u32value; @@ -41,20 +40,20 @@ static bool animation_storage_load_single_manifest_info( if(!flipper_format_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break; if(!flipper_format_read_header(file, read_string, &u32value)) break; - if(string_cmp_str(read_string, "Flipper Animation Manifest")) break; + if(furi_string_cmp_str(read_string, "Flipper Animation Manifest")) break; manifest_info->name = NULL; /* skip other animation names */ flipper_format_set_strict_mode(file, false); while(flipper_format_read_string(file, "Name", read_string) && - string_cmp_str(read_string, name)) + furi_string_cmp_str(read_string, name)) ; - if(string_cmp_str(read_string, name)) break; + if(furi_string_cmp_str(read_string, name)) break; flipper_format_set_strict_mode(file, true); - manifest_info->name = malloc(string_size(read_string) + 1); - strcpy((char*)manifest_info->name, string_get_cstr(read_string)); + manifest_info->name = malloc(furi_string_size(read_string) + 1); + strcpy((char*)manifest_info->name, furi_string_get_cstr(read_string)); if(!flipper_format_read_uint32(file, "Min butthurt", &u32value, 1)) break; manifest_info->min_butthurt = u32value; @@ -72,7 +71,7 @@ static bool animation_storage_load_single_manifest_info( if(!result && manifest_info->name) { free((void*)manifest_info->name); } - string_clear(read_string); + furi_string_free(read_string); flipper_format_free(file); furi_record_close(RECORD_STORAGE); @@ -88,8 +87,8 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis FlipperFormat* file = flipper_format_file_alloc(storage); /* Forbid skipping fields */ flipper_format_set_strict_mode(file, true); - string_t read_string; - string_init(read_string); + FuriString* read_string; + read_string = furi_string_alloc(); do { uint32_t u32value; @@ -98,7 +97,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis if(FSE_OK != storage_sd_status(storage)) break; if(!flipper_format_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break; if(!flipper_format_read_header(file, read_string, &u32value)) break; - if(string_cmp_str(read_string, "Flipper Animation Manifest")) break; + if(furi_string_cmp_str(read_string, "Flipper Animation Manifest")) break; do { storage_animation = malloc(sizeof(StorageAnimation)); storage_animation->external = true; @@ -106,8 +105,9 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis storage_animation->manifest_info.name = NULL; if(!flipper_format_read_string(file, "Name", read_string)) break; - storage_animation->manifest_info.name = malloc(string_size(read_string) + 1); - strcpy((char*)storage_animation->manifest_info.name, string_get_cstr(read_string)); + storage_animation->manifest_info.name = malloc(furi_string_size(read_string) + 1); + strcpy( + (char*)storage_animation->manifest_info.name, furi_string_get_cstr(read_string)); if(!flipper_format_read_uint32(file, "Min butthurt", &u32value, 1)) break; storage_animation->manifest_info.min_butthurt = u32value; @@ -126,7 +126,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis animation_storage_free_storage_animation(&storage_animation); } while(0); - string_clear(read_string); + furi_string_free(read_string); flipper_format_free(file); // add hard-coded animations @@ -231,16 +231,16 @@ void animation_storage_free_storage_animation(StorageAnimation** storage_animati *storage_animation = NULL; } -static bool animation_storage_cast_align(string_t align_str, Align* align) { - if(!string_cmp_str(align_str, "Bottom")) { +static bool animation_storage_cast_align(FuriString* align_str, Align* align) { + if(!furi_string_cmp(align_str, "Bottom")) { *align = AlignBottom; - } else if(!string_cmp_str(align_str, "Top")) { + } else if(!furi_string_cmp(align_str, "Top")) { *align = AlignTop; - } else if(!string_cmp_str(align_str, "Left")) { + } else if(!furi_string_cmp(align_str, "Left")) { *align = AlignLeft; - } else if(!string_cmp_str(align_str, "Right")) { + } else if(!furi_string_cmp(align_str, "Right")) { *align = AlignRight; - } else if(!string_cmp_str(align_str, "Center")) { + } else if(!furi_string_cmp(align_str, "Center")) { *align = AlignCenter; } else { return false; @@ -291,33 +291,35 @@ static bool animation_storage_load_frames( bool frames_ok = false; File* file = storage_file_alloc(storage); FileInfo file_info; - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); size_t max_filesize = ROUND_UP_TO(width, 8) * height + 1; for(int i = 0; i < icon->frame_count; ++i) { frames_ok = false; - string_printf(filename, ANIMATION_DIR "/%s/frame_%d.bm", name, i); + furi_string_printf(filename, ANIMATION_DIR "/%s/frame_%d.bm", name, i); - if(storage_common_stat(storage, string_get_cstr(filename), &file_info) != FSE_OK) break; + if(storage_common_stat(storage, furi_string_get_cstr(filename), &file_info) != FSE_OK) + break; if(file_info.size > max_filesize) { FURI_LOG_E( TAG, - "Filesize %d, max: %d (width %d, height %d)", + "Filesize %lld, max: %d (width %d, height %d)", file_info.size, max_filesize, width, height); break; } - if(!storage_file_open(file, string_get_cstr(filename), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Can't open file \'%s\'", string_get_cstr(filename)); + if(!storage_file_open( + file, furi_string_get_cstr(filename), FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E(TAG, "Can't open file \'%s\'", furi_string_get_cstr(filename)); break; } FURI_CONST_ASSIGN_PTR(icon->frames[i], malloc(file_info.size)); if(storage_file_read(file, (void*)icon->frames[i], file_info.size) != file_info.size) { - FURI_LOG_E(TAG, "Read failed: \'%s\'", string_get_cstr(filename)); + FURI_LOG_E(TAG, "Read failed: \'%s\'", furi_string_get_cstr(filename)); break; } storage_file_close(file); @@ -327,8 +329,8 @@ static bool animation_storage_load_frames( if(!frames_ok) { FURI_LOG_E( TAG, - "Load \'%s\' failed, %dx%d, size: %d", - string_get_cstr(filename), + "Load \'%s\' failed, %dx%d, size: %lld", + furi_string_get_cstr(filename), width, height, file_info.size); @@ -341,15 +343,15 @@ static bool animation_storage_load_frames( } storage_file_free(file); - string_clear(filename); + furi_string_free(filename); return frames_ok; } static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFormat* ff) { uint32_t u32value; - string_t str; - string_init(str); + FuriString* str; + str = furi_string_alloc(); bool success = false; furi_assert(!animation->frame_bubble_sequences); @@ -396,12 +398,12 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo FURI_CONST_ASSIGN(bubble->bubble.y, u32value); if(!flipper_format_read_string(ff, "Text", str)) break; - if(string_size(str) > 100) break; + if(furi_string_size(str) > 100) break; - string_replace_all_str(str, "\\n", "\n"); + furi_string_replace_all(str, "\\n", "\n"); - FURI_CONST_ASSIGN_PTR(bubble->bubble.text, malloc(string_size(str) + 1)); - strcpy((char*)bubble->bubble.text, string_get_cstr(str)); + FURI_CONST_ASSIGN_PTR(bubble->bubble.text, malloc(furi_string_size(str) + 1)); + strcpy((char*)bubble->bubble.text, furi_string_get_cstr(str)); if(!flipper_format_read_string(ff, "AlignH", str)) break; if(!animation_storage_cast_align(str, (Align*)&bubble->bubble.align_h)) break; @@ -423,7 +425,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo } } - string_clear(str); + furi_string_free(str); return success; } @@ -438,8 +440,8 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) { FlipperFormat* ff = flipper_format_file_alloc(storage); /* Forbid skipping fields */ flipper_format_set_strict_mode(ff, true); - string_t str; - string_init(str); + FuriString* str; + str = furi_string_alloc(); animation->frame_bubble_sequences = NULL; bool success = false; @@ -448,10 +450,10 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) { if(FSE_OK != storage_sd_status(storage)) break; - string_printf(str, ANIMATION_DIR "/%s/" ANIMATION_META_FILE, name); - if(!flipper_format_file_open_existing(ff, string_get_cstr(str))) break; + furi_string_printf(str, ANIMATION_DIR "/%s/" ANIMATION_META_FILE, name); + if(!flipper_format_file_open_existing(ff, furi_string_get_cstr(str))) break; if(!flipper_format_read_header(ff, str, &u32value)) break; - if(string_cmp_str(str, "Flipper Animation")) break; + if(furi_string_cmp_str(str, "Flipper Animation")) break; if(!flipper_format_read_uint32(ff, "Width", &width, 1)) break; if(!flipper_format_read_uint32(ff, "Height", &height, 1)) break; @@ -492,7 +494,7 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) { success = true; } while(0); - string_clear(str); + furi_string_free(str); flipper_format_free(ff); if(u32array) { free(u32array); diff --git a/applications/services/desktop/animations/animation_storage.h b/applications/services/desktop/animations/animation_storage.h index e53c1133..16c0feab 100644 --- a/applications/services/desktop/animations/animation_storage.h +++ b/applications/services/desktop/animations/animation_storage.h @@ -2,7 +2,6 @@ #include #include #include "views/bubble_animation_view.h" -#include /** Main structure to handle animation data. * Contains all, including animation playing data (BubbleAnimation), diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 3b10fbb1..e502c35f 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (5) +#define DESKTOP_SETTINGS_VER (6) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -34,6 +34,9 @@ #define MAX_PIN_SIZE 10 #define MIN_PIN_SIZE 4 +#define MAX_APP_LENGTH 128 + +#define FAP_LOADER_APP_NAME "Applications" typedef struct { InputKey data[MAX_PIN_SIZE]; @@ -41,8 +44,13 @@ typedef struct { } PinCode; typedef struct { - uint16_t favorite_primary; - uint16_t favorite_secondary; + bool is_external; + char name_or_path[MAX_APP_LENGTH]; +} FavoriteApp; + +typedef struct { + FavoriteApp favorite_primary; + FavoriteApp favorite_secondary; PinCode pin_code; uint8_t is_locked; uint32_t auto_lock_delay_ms; diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index dc9ac04d..654de44d 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -114,29 +114,39 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { case DesktopMainEventOpenFavoritePrimary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_primary < FLIPPER_APPS_COUNT) { + if(desktop->settings.favorite_primary.is_external) { LoaderStatus status = loader_start( - desktop->loader, FLIPPER_APPS[desktop->settings.favorite_primary].name, NULL); + desktop->loader, + FAP_LOADER_APP_NAME, + desktop->settings.favorite_primary.name_or_path); if(status != LoaderStatusOk) { FURI_LOG_E(TAG, "loader_start failed: %d", status); } } else { - FURI_LOG_E(TAG, "Can't find primary favorite application"); + LoaderStatus status = loader_start( + desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } } consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_secondary < FLIPPER_APPS_COUNT) { + if(desktop->settings.favorite_secondary.is_external) { LoaderStatus status = loader_start( desktop->loader, - FLIPPER_APPS[desktop->settings.favorite_secondary].name, - NULL); + FAP_LOADER_APP_NAME, + desktop->settings.favorite_secondary.name_or_path); if(status != LoaderStatusOk) { FURI_LOG_E(TAG, "loader_start failed: %d", status); } } else { - FURI_LOG_E(TAG, "Can't find secondary favorite application"); + LoaderStatus status = loader_start( + desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } } consumed = true; break; @@ -166,7 +176,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { } case DesktopMainEventOpenGameMenu: { LoaderStatus status = loader_start( - desktop->loader, "Applications", EXT_PATH("/apps/Games/snake_game.fap")); + desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/snake_game.fap")); if(status != LoaderStatusOk) { FURI_LOG_E(TAG, "loader_start failed: %d", status); } diff --git a/applications/services/desktop/views/desktop_view_debug.c b/applications/services/desktop/views/desktop_view_debug.c index c965432f..f9c8aedc 100644 --- a/applications/services/desktop/views/desktop_view_debug.c +++ b/applications/services/desktop/views/desktop_view_debug.c @@ -124,16 +124,17 @@ bool desktop_debug_input(InputEvent* event, void* context) { DesktopViewStatsScreens current = 0; with_view_model( - debug_view->view, (DesktopDebugViewModel * model) { - + debug_view->view, + DesktopDebugViewModel * model, + { #ifdef SRV_DOLPHIN_STATE_DEBUG if((event->key == InputKeyDown) || (event->key == InputKeyUp)) { model->screen = !model->screen; } #endif current = model->screen; - return true; - }); + }, + true); size_t count = (event->type == InputTypeRepeat) ? 10 : 1; if(current == DesktopViewStatsMeta) { @@ -181,20 +182,19 @@ void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); with_view_model( - debug_view->view, (DesktopDebugViewModel * model) { + debug_view->view, + DesktopDebugViewModel * model, + { model->icounter = stats.icounter; model->butthurt = stats.butthurt; model->timestamp = stats.timestamp; - return true; - }); + }, + true); furi_record_close(RECORD_DOLPHIN); } void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view) { with_view_model( - debug_view->view, (DesktopDebugViewModel * model) { - model->screen = 0; - return true; - }); + debug_view->view, DesktopDebugViewModel * model, { model->screen = 0; }, true); } diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 294191bf..8cb8a7a1 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -24,27 +24,24 @@ void desktop_lock_menu_set_callback( void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set) { with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->pin_is_set = pin_is_set; - return true; - }); + lock_menu->view, + DesktopLockMenuViewModel * model, + { model->pin_is_set = pin_is_set; }, + true); } void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode) { with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->dummy_mode = dummy_mode; - return true; - }); + lock_menu->view, + DesktopLockMenuViewModel * model, + { model->dummy_mode = dummy_mode; }, + true); } void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { furi_assert(idx < DesktopLockMenuIndexTotalCount); with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->idx = idx; - return true; - }); + lock_menu->view, DesktopLockMenuViewModel * model, { model->idx = idx; }, true); } void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { @@ -95,10 +92,12 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { uint8_t idx = 0; bool consumed = false; bool dummy_mode = false; + bool update = false; with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - bool ret = false; + lock_menu->view, + DesktopLockMenuViewModel * model, + { if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { if(event->key == InputKeyUp) { if(model->idx == 0) { @@ -106,7 +105,7 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { } else { model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0); } - ret = true; + update = true; consumed = true; } else if(event->key == InputKeyDown) { if(model->idx == DesktopLockMenuIndexTotalCount - 1) { @@ -114,14 +113,14 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { } else { model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0); } - ret = true; + update = true; consumed = true; } } idx = model->idx; dummy_mode = model->dummy_mode; - return ret; - }); + }, + update); if(event->key == InputKeyOk) { if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) { diff --git a/applications/services/dialogs/dialogs.h b/applications/services/dialogs/dialogs.h index 2522c8b5..4e836e36 100644 --- a/applications/services/dialogs/dialogs.h +++ b/applications/services/dialogs/dialogs.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include "m-string.h" #include #ifdef __cplusplus @@ -56,8 +55,8 @@ void dialog_file_browser_set_basic_options( */ bool dialog_file_browser_show( DialogsApp* context, - string_ptr result_path, - string_ptr path, + FuriString* result_path, + FuriString* path, const DialogsFileBrowserOptions* options); /****************** MESSAGE ******************/ diff --git a/applications/services/dialogs/dialogs_api.c b/applications/services/dialogs/dialogs_api.c index fd3b2e96..6fd51782 100644 --- a/applications/services/dialogs/dialogs_api.c +++ b/applications/services/dialogs/dialogs_api.c @@ -1,14 +1,13 @@ #include "dialogs/dialogs_message.h" #include "dialogs_i.h" #include "dialogs_api_lock.h" -#include "m-string.h" /****************** File browser ******************/ bool dialog_file_browser_show( DialogsApp* context, - string_ptr result_path, - string_ptr path, + FuriString* result_path, + FuriString* path, const DialogsFileBrowserOptions* options) { FuriApiLock lock = API_LOCK_INIT_LOCKED(); furi_check(lock != NULL); diff --git a/applications/services/dialogs/dialogs_message.h b/applications/services/dialogs/dialogs_message.h index 2dc66f13..91e040ce 100644 --- a/applications/services/dialogs/dialogs_message.h +++ b/applications/services/dialogs/dialogs_message.h @@ -2,7 +2,6 @@ #include #include "dialogs_i.h" #include "dialogs_api_lock.h" -#include "m-string.h" #ifdef __cplusplus extern "C" { @@ -13,8 +12,8 @@ typedef struct { bool skip_assets; bool hide_ext; const Icon* file_icon; - string_ptr result_path; - string_ptr preselected_filename; + FuriString* result_path; + FuriString* preselected_filename; FileBrowserLoadItemCallback item_callback; void* item_callback_context; } DialogsAppMessageDataFileBrowser; diff --git a/applications/services/dolphin/helpers/dolphin_deed.c b/applications/services/dolphin/helpers/dolphin_deed.c index b112d82a..ce3e058b 100644 --- a/applications/services/dolphin/helpers/dolphin_deed.c +++ b/applications/services/dolphin/helpers/dolphin_deed.c @@ -18,13 +18,15 @@ static const DolphinDeedWeight dolphin_deed_weights[] = { {1, DolphinAppNfc}, // DolphinDeedNfcRead {3, DolphinAppNfc}, // DolphinDeedNfcReadSuccess {3, DolphinAppNfc}, // DolphinDeedNfcSave + {1, DolphinAppNfc}, // DolphinDeedNfcDetectReader {2, DolphinAppNfc}, // DolphinDeedNfcEmulate - {2, DolphinAppNfc}, // DolphinDeedNfcAdd + {2, DolphinAppNfc}, // DolphinDeedNfcMfcAdd + {1, DolphinAppNfc}, // DolphinDeedNfcMfulError + {1, DolphinAppNfc}, // DolphinDeedNfcAddSave {1, DolphinAppIr}, // DolphinDeedIrSend {3, DolphinAppIr}, // DolphinDeedIrLearnSuccess {3, DolphinAppIr}, // DolphinDeedIrSave - {2, DolphinAppIr}, // DolphinDeedIrBruteForce {1, DolphinAppIbutton}, // DolphinDeedIbuttonRead {3, DolphinAppIbutton}, // DolphinDeedIbuttonReadSuccess @@ -33,17 +35,23 @@ static const DolphinDeedWeight dolphin_deed_weights[] = { {2, DolphinAppIbutton}, // DolphinDeedIbuttonAdd {3, DolphinAppBadusb}, // DolphinDeedBadUsbPlayScript - {3, DolphinAppU2f}, // DolphinDeedU2fAuthorized + {3, DolphinAppPlugin}, // DolphinDeedU2fAuthorized + + {1, DolphinAppPlugin}, // DolphinDeedGpioUartBridge + + {1, DolphinAppPlugin}, // DolphinDeedPluginStart + {1, DolphinAppPlugin}, // DolphinDeedPluginGameStart + {10, DolphinAppPlugin}, // DolphinDeedPluginGameWin }; static uint8_t dolphin_deed_limits[] = { - 15, // DolphinAppSubGhz - 15, // DolphinAppRfid - 15, // DolphinAppNfc - 15, // DolphinAppIr - 15, // DolphinAppIbutton - 15, // DolphinAppBadusb - 15, // DolphinAppU2f + 20, // DolphinAppSubGhz + 20, // DolphinAppRfid + 20, // DolphinAppNfc + 20, // DolphinAppIr + 20, // DolphinAppIbutton + 20, // DolphinAppBadusb + 20, // DolphinAppPlugin }; _Static_assert(COUNT_OF(dolphin_deed_weights) == DolphinDeedMAX, "dolphin_deed_weights size error"); diff --git a/applications/services/dolphin/helpers/dolphin_deed.h b/applications/services/dolphin/helpers/dolphin_deed.h index 1f63db3f..abe027d7 100644 --- a/applications/services/dolphin/helpers/dolphin_deed.h +++ b/applications/services/dolphin/helpers/dolphin_deed.h @@ -13,7 +13,7 @@ typedef enum { DolphinAppIr, DolphinAppIbutton, DolphinAppBadusb, - DolphinAppU2f, + DolphinAppPlugin, DolphinAppMAX, } DolphinApp; @@ -34,13 +34,15 @@ typedef enum { DolphinDeedNfcRead, DolphinDeedNfcReadSuccess, DolphinDeedNfcSave, + DolphinDeedNfcDetectReader, DolphinDeedNfcEmulate, - DolphinDeedNfcAdd, + DolphinDeedNfcMfcAdd, + DolphinDeedNfcMfulError, + DolphinDeedNfcAddSave, DolphinDeedIrSend, DolphinDeedIrLearnSuccess, DolphinDeedIrSave, - DolphinDeedIrBruteForce, DolphinDeedIbuttonRead, DolphinDeedIbuttonReadSuccess, @@ -51,6 +53,11 @@ typedef enum { DolphinDeedBadUsbPlayScript, DolphinDeedU2fAuthorized, + DolphinDeedGpioUartBridge, + + DolphinDeedPluginStart, + DolphinDeedPluginGameStart, + DolphinDeedPluginGameWin, DolphinDeedMAX, diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index 95e2f42f..10cb85c2 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -171,7 +171,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { FURI_LOG_D( TAG, - "icounter %d, butthurt %d", + "icounter %ld, butthurt %ld", dolphin_state->data.icounter, dolphin_state->data.butthurt); } diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 58b44603..0f7cf73f 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -8,7 +8,6 @@ #include #include -#include #include #include "canvas_i.h" @@ -189,12 +188,12 @@ static size_t end = text + strlen(text); } size_t text_size = end - text; - string_t str; - string_init_set_str(str, text); - string_left(str, text_size); + FuriString* str; + str = furi_string_alloc_set(text); + furi_string_left(str, text_size); size_t result = 0; - uint16_t len_px = canvas_string_width(canvas, string_get_cstr(str)); + uint16_t len_px = canvas_string_width(canvas, furi_string_get_cstr(str)); uint8_t px_left = 0; if(horizontal == AlignCenter) { if(x > (canvas_width(canvas) / 2)) { @@ -224,7 +223,7 @@ static size_t result = text_size; } - string_clear(str); + furi_string_free(str); return result; } @@ -240,7 +239,7 @@ void elements_multiline_text_aligned( uint8_t lines_count = 0; uint8_t font_height = canvas_current_font_height(canvas); - string_t line; + FuriString* line; /* go through text line by line and count lines */ for(const char* start = text; start[0];) { @@ -261,14 +260,14 @@ void elements_multiline_text_aligned( size_t chars_fit = elements_get_max_chars_to_fit(canvas, horizontal, start, x); if((start[chars_fit] == '\n') || (start[chars_fit] == 0)) { - string_init_printf(line, "%.*s", chars_fit, start); + line = furi_string_alloc_printf("%.*s", chars_fit, start); } else if((y + font_height) > canvas_height(canvas)) { - string_init_printf(line, "%.*s...\n", chars_fit, start); + line = furi_string_alloc_printf("%.*s...\n", chars_fit, start); } else { - string_init_printf(line, "%.*s-\n", chars_fit, start); + line = furi_string_alloc_printf("%.*s-\n", chars_fit, start); } - canvas_draw_str_aligned(canvas, x, y, horizontal, vertical, string_get_cstr(line)); - string_clear(line); + canvas_draw_str_aligned(canvas, x, y, horizontal, vertical, furi_string_get_cstr(line)); + furi_string_free(line); y += font_height; if(y > canvas_height(canvas)) { break; @@ -284,22 +283,22 @@ void elements_multiline_text(Canvas* canvas, uint8_t x, uint8_t y, const char* t furi_assert(text); uint8_t font_height = canvas_current_font_height(canvas); - string_t str; - string_init(str); + FuriString* str; + str = furi_string_alloc(); const char* start = text; char* end; do { end = strchr(start, '\n'); if(end) { - string_set_strn(str, start, end - start); + furi_string_set_strn(str, start, end - start); } else { - string_set_str(str, start); + furi_string_set(str, start); } - canvas_draw_str(canvas, x, y, string_get_cstr(str)); + canvas_draw_str(canvas, x, y, furi_string_get_cstr(str)); start = end + 1; y += font_height; } while(end && y < 64); - string_clear(str); + furi_string_free(str); } void elements_multiline_text_framed(Canvas* canvas, uint8_t x, uint8_t y, const char* text) { @@ -533,18 +532,18 @@ void elements_bubble_str( canvas_draw_line(canvas, x2, y2, x3, y3); } -void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) { +void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width) { furi_assert(canvas); furi_assert(string); - uint16_t len_px = canvas_string_width(canvas, string_get_cstr(string)); + uint16_t len_px = canvas_string_width(canvas, furi_string_get_cstr(string)); if(len_px > width) { width -= canvas_string_width(canvas, "..."); do { - string_left(string, string_size(string) - 1); - len_px = canvas_string_width(canvas, string_get_cstr(string)); + furi_string_left(string, furi_string_size(string) - 1); + len_px = canvas_string_width(canvas, furi_string_get_cstr(string)); } while(len_px > width); - string_cat(string, "..."); + furi_string_cat(string, "..."); } } diff --git a/applications/services/gui/elements.h b/applications/services/gui/elements.h index 2329ca27..b2d204de 100644 --- a/applications/services/gui/elements.h +++ b/applications/services/gui/elements.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include "canvas.h" #ifdef __cplusplus @@ -190,7 +190,7 @@ void elements_bubble_str( * @param string string to trim * @param width max width */ -void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width); +void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width); /** Draw text box element * diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 6b4b9a0a..0535b32b 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -260,7 +260,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { "non-complementary input, discarding key: %s type: %s, sequence: %p", input_get_key_name(input_event->key), input_get_type_name(input_event->type), - input_event->sequence); + (void*)input_event->sequence); return; } @@ -290,7 +290,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { view_port, input_get_key_name(input_event->key), input_get_type_name(input_event->type), - input_event->sequence); + (void*)input_event->sequence); view_port_input(gui->ongoing_input_view_port, input_event); } else { FURI_LOG_D( @@ -300,7 +300,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { view_port, input_get_key_name(input_event->key), input_get_type_name(input_event->type), - input_event->sequence); + (void*)input_event->sequence); } gui_unlock(gui); diff --git a/applications/services/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c index 84fea788..37a04326 100644 --- a/applications/services/gui/modules/button_menu.c +++ b/applications/services/gui/modules/button_menu.c @@ -79,8 +79,8 @@ static void button_menu_draw_common_button( canvas_draw_rframe(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT, 5); } - string_t disp_str; - string_init_set_str(disp_str, text); + FuriString* disp_str; + disp_str = furi_string_alloc_set(text); elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6); canvas_draw_str_aligned( @@ -89,9 +89,9 @@ static void button_menu_draw_common_button( item_y + (ITEM_HEIGHT / 2), AlignCenter, AlignCenter, - string_get_cstr(disp_str)); + furi_string_get_cstr(disp_str)); - string_clear(disp_str); + furi_string_free(disp_str); } static void button_menu_view_draw_callback(Canvas* canvas, void* _model) { @@ -116,12 +116,12 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) { } if(model->header) { - string_t disp_str; - string_init_set_str(disp_str, model->header); + FuriString* disp_str; + disp_str = furi_string_alloc_set(model->header); elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6); canvas_draw_str_aligned( - canvas, 32, 10, AlignCenter, AlignCenter, string_get_cstr(disp_str)); - string_clear(disp_str); + canvas, 32, 10, AlignCenter, AlignCenter, furi_string_get_cstr(disp_str)); + furi_string_free(disp_str); } for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); @@ -148,28 +148,32 @@ static void button_menu_process_up(ButtonMenu* button_menu) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { if(model->position > 0) { model->position--; } else { model->position = ButtonMenuItemArray_size(model->items) - 1; } - return true; - }); + }, + true); } static void button_menu_process_down(ButtonMenu* button_menu) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { if(model->position < (ButtonMenuItemArray_size(model->items) - 1)) { model->position++; } else { model->position = 0; } - return true; - }); + }, + true); } static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { @@ -178,12 +182,14 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { ButtonMenuItem* item = NULL; with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { if(model->position < (ButtonMenuItemArray_size(model->items))) { item = ButtonMenuItemArray_get(model->items, model->position); } - return false; - }); + }, + false); if(item) { if(item->type == ButtonMenuItemTypeControl) { @@ -248,22 +254,21 @@ void button_menu_reset(ButtonMenu* button_menu) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { ButtonMenuItemArray_reset(model->items); model->position = 0; model->header = NULL; - return true; - }); + }, + true); } void button_menu_set_header(ButtonMenu* button_menu, const char* header) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { - model->header = header; - return true; - }); + button_menu->view, ButtonMenuModel * model, { model->header = header; }, true); } ButtonMenuItem* button_menu_add_item( @@ -278,15 +283,17 @@ ButtonMenuItem* button_menu_add_item( furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { item = ButtonMenuItemArray_push_new(model->items); item->label = label; item->index = index; item->type = type; item->callback = callback; item->callback_context = callback_context; - return true; - }); + }, + true); return item; } @@ -301,12 +308,14 @@ ButtonMenu* button_menu_alloc(void) { view_set_input_callback(button_menu->view, button_menu_view_input_callback); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { ButtonMenuItemArray_init(model->items); model->position = 0; model->header = NULL; - return true; - }); + }, + true); button_menu->freeze_input = false; return button_menu; @@ -316,10 +325,10 @@ void button_menu_free(ButtonMenu* button_menu) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { - ButtonMenuItemArray_clear(model->items); - return true; - }); + button_menu->view, + ButtonMenuModel * model, + { ButtonMenuItemArray_clear(model->items); }, + true); view_free(button_menu->view); free(button_menu); } @@ -328,7 +337,9 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) { furi_assert(button_menu); with_view_model( - button_menu->view, (ButtonMenuModel * model) { + button_menu->view, + ButtonMenuModel * model, + { uint8_t item_position = 0; ButtonMenuItemArray_it_t it; for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); @@ -338,6 +349,6 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) { break; } } - return true; - }); + }, + true); } diff --git a/applications/services/gui/modules/button_panel.c b/applications/services/gui/modules/button_panel.c index c823e4b1..47b6ed48 100644 --- a/applications/services/gui/modules/button_panel.c +++ b/applications/services/gui/modules/button_panel.c @@ -70,15 +70,17 @@ ButtonPanel* button_panel_alloc() { view_set_input_callback(button_panel->view, button_panel_view_input_callback); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { model->reserve_x = 0; model->reserve_y = 0; model->selected_item_x = 0; model->selected_item_y = 0; ButtonMatrix_init(model->button_matrix); LabelList_init(model->labels); - return true; - }); + }, + true); return button_panel; } @@ -88,7 +90,9 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re furi_check(reserve_y > 0); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { model->reserve_x = reserve_x; model->reserve_y = reserve_y; ButtonMatrix_reserve(model->button_matrix, model->reserve_y); @@ -99,8 +103,8 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re // TODO: do we need to clear allocated memory of ptr-s to ButtonItem ?? } LabelList_init(model->labels); - return true; - }); + }, + true); } void button_panel_free(ButtonPanel* button_panel) { @@ -109,11 +113,13 @@ void button_panel_free(ButtonPanel* button_panel) { button_panel_reset(button_panel); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { LabelList_clear(model->labels); ButtonMatrix_clear(model->button_matrix); - return true; - }); + }, + true); view_free(button_panel->view); free(button_panel); @@ -123,7 +129,9 @@ void button_panel_reset(ButtonPanel* button_panel) { furi_assert(button_panel); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { for(size_t x = 0; x < model->reserve_x; ++x) { for(size_t y = 0; y < model->reserve_y; ++y) { ButtonItem** button_item = button_panel_get_item(model, x, y); @@ -137,8 +145,8 @@ void button_panel_reset(ButtonPanel* button_panel) { model->selected_item_y = 0; LabelList_reset(model->labels); ButtonMatrix_reset(model->button_matrix); - return true; - }); + }, + true); } static ButtonItem** button_panel_get_item(ButtonPanelModel* model, size_t x, size_t y) { @@ -165,7 +173,9 @@ void button_panel_add_item( furi_assert(button_panel); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { ButtonItem** button_item_ptr = button_panel_get_item(model, matrix_place_x, matrix_place_y); furi_check(*button_item_ptr == NULL); @@ -178,8 +188,8 @@ void button_panel_add_item( button_item->icon.name = icon_name; button_item->icon.name_selected = icon_name_selected; button_item->index = index; - return true; - }); + }, + true); } View* button_panel_get_view(ButtonPanel* button_panel) { @@ -216,114 +226,123 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) { static void button_panel_process_down(ButtonPanel* button_panel) { with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { uint16_t new_selected_item_x = model->selected_item_x; uint16_t new_selected_item_y = model->selected_item_y; size_t i; - if(new_selected_item_y >= (model->reserve_y - 1)) return false; + if(new_selected_item_y < (model->reserve_y - 1)) { + ++new_selected_item_y; - ++new_selected_item_y; - - for(i = 0; i < model->reserve_x; ++i) { - new_selected_item_x = (model->selected_item_x + i) % model->reserve_x; - if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { - break; + for(i = 0; i < model->reserve_x; ++i) { + new_selected_item_x = (model->selected_item_x + i) % model->reserve_x; + if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { + break; + } + } + if(i != model->reserve_x) { + model->selected_item_x = new_selected_item_x; + model->selected_item_y = new_selected_item_y; } } - if(i == model->reserve_x) return false; - - model->selected_item_x = new_selected_item_x; - model->selected_item_y = new_selected_item_y; - - return true; - }); + }, + true); } static void button_panel_process_up(ButtonPanel* button_panel) { with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { size_t new_selected_item_x = model->selected_item_x; size_t new_selected_item_y = model->selected_item_y; size_t i; - if(new_selected_item_y <= 0) return false; + if(new_selected_item_y > 0) { + --new_selected_item_y; - --new_selected_item_y; - - for(i = 0; i < model->reserve_x; ++i) { - new_selected_item_x = (model->selected_item_x + i) % model->reserve_x; - if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { - break; + for(i = 0; i < model->reserve_x; ++i) { + new_selected_item_x = (model->selected_item_x + i) % model->reserve_x; + if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { + break; + } + } + if(i != model->reserve_x) { + model->selected_item_x = new_selected_item_x; + model->selected_item_y = new_selected_item_y; } } - if(i == model->reserve_x) return false; - - model->selected_item_x = new_selected_item_x; - model->selected_item_y = new_selected_item_y; - return true; - }); + }, + true); } static void button_panel_process_left(ButtonPanel* button_panel) { with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { size_t new_selected_item_x = model->selected_item_x; size_t new_selected_item_y = model->selected_item_y; size_t i; - if(new_selected_item_x <= 0) return false; + if(new_selected_item_x > 0) { + --new_selected_item_x; - --new_selected_item_x; - - for(i = 0; i < model->reserve_y; ++i) { - new_selected_item_y = (model->selected_item_y + i) % model->reserve_y; - if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { - break; + for(i = 0; i < model->reserve_y; ++i) { + new_selected_item_y = (model->selected_item_y + i) % model->reserve_y; + if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { + break; + } + } + if(i != model->reserve_y) { + model->selected_item_x = new_selected_item_x; + model->selected_item_y = new_selected_item_y; } } - if(i == model->reserve_y) return false; - - model->selected_item_x = new_selected_item_x; - model->selected_item_y = new_selected_item_y; - return true; - }); + }, + true); } static void button_panel_process_right(ButtonPanel* button_panel) { with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { uint16_t new_selected_item_x = model->selected_item_x; uint16_t new_selected_item_y = model->selected_item_y; size_t i; - if(new_selected_item_x >= (model->reserve_x - 1)) return false; + if(new_selected_item_x < (model->reserve_x - 1)) { + ++new_selected_item_x; - ++new_selected_item_x; - - for(i = 0; i < model->reserve_y; ++i) { - new_selected_item_y = (model->selected_item_y + i) % model->reserve_y; - if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { - break; + for(i = 0; i < model->reserve_y; ++i) { + new_selected_item_y = (model->selected_item_y + i) % model->reserve_y; + if(*button_panel_get_item(model, new_selected_item_x, new_selected_item_y)) { + break; + } + } + if(i != model->reserve_y) { + model->selected_item_x = new_selected_item_x; + model->selected_item_y = new_selected_item_y; } } - if(i == model->reserve_y) return false; - - model->selected_item_x = new_selected_item_x; - model->selected_item_y = new_selected_item_y; - return true; - }); + }, + true); } void button_panel_process_ok(ButtonPanel* button_panel) { ButtonItem* button_item = NULL; with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { button_item = *button_panel_get_item(model, model->selected_item_x, model->selected_item_y); - return true; - }); + }, + true); if(button_item && button_item->callback) { button_item->callback(button_item->callback_context, button_item->index); @@ -374,12 +393,14 @@ void button_panel_add_label( furi_assert(button_panel); with_view_model( - button_panel->view, (ButtonPanelModel * model) { + button_panel->view, + ButtonPanelModel * model, + { LabelElement* label = LabelList_push_raw(model->labels); label->x = x; label->y = y; label->font = font; label->str = label_str; - return true; - }); + }, + true); } diff --git a/applications/services/gui/modules/byte_input.c b/applications/services/gui/modules/byte_input.c index bb18a107..8d7e7fd4 100644 --- a/applications/services/gui/modules/byte_input.c +++ b/applications/services/gui/modules/byte_input.c @@ -618,42 +618,30 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) { switch(event->key) { case InputKeyLeft: with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_handle_left(model); - return true; - }); + byte_input->view, ByteInputModel * model, { byte_input_handle_left(model); }, true); consumed = true; break; case InputKeyRight: with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_handle_right(model); - return true; - }); + byte_input->view, + ByteInputModel * model, + { byte_input_handle_right(model); }, + true); consumed = true; break; case InputKeyUp: with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_handle_up(model); - return true; - }); + byte_input->view, ByteInputModel * model, { byte_input_handle_up(model); }, true); consumed = true; break; case InputKeyDown: with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_handle_down(model); - return true; - }); + byte_input->view, ByteInputModel * model, { byte_input_handle_down(model); }, true); consumed = true; break; case InputKeyOk: with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_handle_ok(model); - return true; - }); + byte_input->view, ByteInputModel * model, { byte_input_handle_ok(model); }, true); consumed = true; break; default: @@ -664,10 +652,10 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) { if((event->type == InputTypeLong || event->type == InputTypeRepeat) && event->key == InputKeyBack) { with_view_model( - byte_input->view, (ByteInputModel * model) { - byte_input_clear_selected_byte(model); - return true; - }); + byte_input->view, + ByteInputModel * model, + { byte_input_clear_selected_byte(model); }, + true); consumed = true; } @@ -703,14 +691,16 @@ ByteInput* byte_input_alloc() { view_set_input_callback(byte_input->view, byte_input_view_input_callback); with_view_model( - byte_input->view, (ByteInputModel * model) { + byte_input->view, + ByteInputModel * model, + { model->header = ""; model->input_callback = NULL; model->changed_callback = NULL; model->callback_context = NULL; byte_input_reset_model_input_data(model); - return true; - }); + }, + true); return byte_input; } @@ -755,15 +745,17 @@ void byte_input_set_result_callback( uint8_t* bytes, uint8_t bytes_count) { with_view_model( - byte_input->view, (ByteInputModel * model) { + byte_input->view, + ByteInputModel * model, + { byte_input_reset_model_input_data(model); model->input_callback = input_callback; model->changed_callback = changed_callback; model->callback_context = callback_context; model->bytes = bytes; model->bytes_count = bytes_count; - return true; - }); + }, + true); } /** @@ -774,8 +766,5 @@ void byte_input_set_result_callback( */ void byte_input_set_header_text(ByteInput* byte_input, const char* text) { with_view_model( - byte_input->view, (ByteInputModel * model) { - model->header = text; - return true; - }); + byte_input->view, ByteInputModel * model, { model->header = text; }, true); } diff --git a/applications/services/gui/modules/dialog_ex.c b/applications/services/gui/modules/dialog_ex.c index dee2a097..1cb46723 100644 --- a/applications/services/gui/modules/dialog_ex.c +++ b/applications/services/gui/modules/dialog_ex.c @@ -90,12 +90,14 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) { const char* right_text = NULL; with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { left_text = model->left_text; center_text = model->center_text; right_text = model->right_text; - return true; - }); + }, + true); if(dialog_ex->callback) { if(event->type == InputTypeShort) { @@ -149,7 +151,9 @@ DialogEx* dialog_ex_alloc() { view_set_draw_callback(dialog_ex->view, dialog_ex_view_draw_callback); view_set_input_callback(dialog_ex->view, dialog_ex_view_input_callback); with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { model->header.text = NULL; model->header.x = 0; model->header.y = 0; @@ -169,9 +173,8 @@ DialogEx* dialog_ex_alloc() { model->left_text = NULL; model->center_text = NULL; model->right_text = NULL; - - return true; - }); + }, + true); dialog_ex->enable_extended_events = false; return dialog_ex; } @@ -206,14 +209,16 @@ void dialog_ex_set_header( Align vertical) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { model->header.text = text; model->header.x = x; model->header.y = y; model->header.horizontal = horizontal; model->header.vertical = vertical; - return true; - }); + }, + true); } void dialog_ex_set_text( @@ -225,52 +230,47 @@ void dialog_ex_set_text( Align vertical) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { model->text.text = text; model->text.x = x; model->text.y = y; model->text.horizontal = horizontal; model->text.vertical = vertical; - return true; - }); + }, + true); } void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, const Icon* icon) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { model->icon.x = x; model->icon.y = y; model->icon.icon = icon; - return true; - }); + }, + true); } void dialog_ex_set_left_button_text(DialogEx* dialog_ex, const char* text) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { - model->left_text = text; - return true; - }); + dialog_ex->view, DialogExModel * model, { model->left_text = text; }, true); } void dialog_ex_set_center_button_text(DialogEx* dialog_ex, const char* text) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { - model->center_text = text; - return true; - }); + dialog_ex->view, DialogExModel * model, { model->center_text = text; }, true); } void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) { furi_assert(dialog_ex); with_view_model( - dialog_ex->view, (DialogExModel * model) { - model->right_text = text; - return true; - }); + dialog_ex->view, DialogExModel * model, { model->right_text = text; }, true); } void dialog_ex_reset(DialogEx* dialog_ex) { @@ -279,15 +279,17 @@ void dialog_ex_reset(DialogEx* dialog_ex) { .text = NULL, .x = 0, .y = 0, .horizontal = AlignLeft, .vertical = AlignLeft}; IconElement clean_icon_el = {.icon = NULL, .x = 0, .y = 0}; with_view_model( - dialog_ex->view, (DialogExModel * model) { + dialog_ex->view, + DialogExModel * model, + { model->header = clean_text_el; model->text = clean_text_el; model->icon = clean_icon_el; model->left_text = NULL; model->center_text = NULL; model->right_text = NULL; - return true; - }); + }, + true); dialog_ex->context = NULL; dialog_ex->callback = NULL; } diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index 1c0c8c74..60e78b01 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -5,7 +5,6 @@ #include #include #include "furi_hal_resources.h" -#include "m-string.h" #include #include #include @@ -28,23 +27,23 @@ typedef enum { } BrowserItemType; typedef struct { - string_t path; + FuriString* path; BrowserItemType type; uint8_t* custom_icon_data; - string_t display_name; + FuriString* display_name; } BrowserItem_t; static void BrowserItem_t_init(BrowserItem_t* obj) { obj->type = BrowserItemTypeLoading; - string_init(obj->path); - string_init(obj->display_name); + obj->path = furi_string_alloc(); + obj->display_name = furi_string_alloc(); obj->custom_icon_data = NULL; } static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) { obj->type = src->type; - string_init_set(obj->path, src->path); - string_init_set(obj->display_name, src->display_name); + obj->path = furi_string_alloc_set(src->path); + obj->display_name = furi_string_alloc_set(src->display_name); if(src->custom_icon_data) { obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE); @@ -55,10 +54,9 @@ static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) { obj->type = src->type; - string_set(obj->path, src->path); - string_set(obj->display_name, src->display_name); + furi_string_set(obj->path, src->path); + furi_string_set(obj->display_name, src->display_name); if(src->custom_icon_data) { - obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE); } else { obj->custom_icon_data = NULL; @@ -66,8 +64,8 @@ static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) { } static void BrowserItem_t_clear(BrowserItem_t* obj) { - string_clear(obj->path); - string_clear(obj->display_name); + furi_string_free(obj->path); + furi_string_free(obj->display_name); if(obj->custom_icon_data) { free(obj->custom_icon_data); } @@ -94,7 +92,7 @@ struct FileBrowser { FileBrowserLoadItemCallback item_callback; void* item_context; - string_ptr result_path; + FuriString* result_path; }; typedef struct { @@ -125,10 +123,11 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context); static void browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root); static void browser_list_load_cb(void* context, uint32_t list_load_offset); -static void browser_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last); +static void + browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last); static void browser_long_load_cb(void* context); -FileBrowser* file_browser_alloc(string_ptr result_path) { +FileBrowser* file_browser_alloc(FuriString* result_path) { furi_assert(result_path); FileBrowser* browser = malloc(sizeof(FileBrowser)); browser->view = view_alloc(); @@ -140,10 +139,7 @@ FileBrowser* file_browser_alloc(string_ptr result_path) { browser->result_path = result_path; with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_init(model->items); - return false; - }); + browser->view, FileBrowserModel * model, { items_array_init(model->items); }, false); return browser; } @@ -152,10 +148,7 @@ void file_browser_free(FileBrowser* browser) { furi_assert(browser); with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_clear(model->items); - return false; - }); + browser->view, FileBrowserModel * model, { items_array_clear(model->items); }, false); view_free(browser->view); free(browser); @@ -179,14 +172,16 @@ void file_browser_configure( browser->hide_ext = hide_ext; with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { model->file_icon = file_icon; model->hide_ext = hide_ext; - return false; - }); + }, + false); } -void file_browser_start(FileBrowser* browser, string_t path) { +void file_browser_start(FileBrowser* browser, FuriString* path) { furi_assert(browser); browser->worker = file_browser_worker_alloc(path, browser->ext_filter, browser->skip_assets); file_browser_worker_set_callback_context(browser->worker, browser); @@ -200,14 +195,16 @@ void file_browser_stop(FileBrowser* browser) { furi_assert(browser); file_browser_worker_free(browser->worker); with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { items_array_reset(model->items); model->item_cnt = 0; model->item_idx = 0; model->array_offset = 0; model->list_offset = 0; - return false; - }); + }, + false); } void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) { @@ -258,7 +255,9 @@ static void browser_update_offset(FileBrowser* browser) { furi_assert(browser); with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { uint16_t bounds = model->item_cnt > (LIST_ITEMS - 1) ? 2 : model->item_cnt; if((model->item_cnt > (LIST_ITEMS - 1)) && @@ -273,9 +272,8 @@ static void browser_update_offset(FileBrowser* browser) { model->list_offset = CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); } - - return false; - }); + }, + false); } static void @@ -286,7 +284,9 @@ static void int32_t load_offset = 0; with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { items_array_reset(model->items); if(is_root) { model->item_cnt = item_cnt; @@ -304,8 +304,8 @@ static void model->is_root = is_root; model->list_loading = true; model->folder_loading = false; - return true; - }); + }, + true); browser_update_offset(browser); file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX); @@ -320,7 +320,9 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) { back_item.type = BrowserItemTypeBack; with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { items_array_reset(model->items); model->array_offset = list_load_offset; if(!model->is_root) { @@ -330,13 +332,14 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) { model->array_offset += 1; } } - return false; - }); + }, + true); BrowserItem_t_clear(&back_item); } -static void browser_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last) { +static void + browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) { furi_assert(context); FileBrowser* browser = (FileBrowser*)context; @@ -344,8 +347,8 @@ static void browser_list_item_cb(void* context, string_t item_path, bool is_fold item.custom_icon_data = NULL; if(!is_last) { - string_init_set(item.path, item_path); - string_init(item.display_name); + item.path = furi_string_alloc_set(item_path); + item.display_name = furi_string_alloc(); if(is_folder) { item.type = BrowserItemTypeFolder; } else { @@ -363,7 +366,7 @@ static void browser_list_item_cb(void* context, string_t item_path, bool is_fold } } - if(string_empty_p(item.display_name)) { + if(furi_string_empty(item.display_name)) { path_extract_filename( item_path, item.display_name, @@ -371,19 +374,21 @@ static void browser_list_item_cb(void* context, string_t item_path, bool is_fold } with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { items_array_push_back(model->items, item); // TODO: calculate if element is visible - return true; - }); - string_clear(item.display_name); - string_clear(item.path); + }, + true); + furi_string_free(item.display_name); + furi_string_free(item.path); + if(item.custom_icon_data) { + free(item.custom_icon_data); + } } else { with_view_model( - browser->view, (FileBrowserModel * model) { - model->list_loading = false; - return true; - }); + browser->view, FileBrowserModel * model, { model->list_loading = false; }, true); } } @@ -392,10 +397,7 @@ static void browser_long_load_cb(void* context) { FileBrowser* browser = (FileBrowser*)context; with_view_model( - browser->view, (FileBrowserModel * model) { - model->folder_loading = true; - return true; - }); + browser->view, FileBrowserModel * model, { model->folder_loading = true; }, true); } static void browser_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { @@ -427,8 +429,8 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { uint32_t array_size = items_array_size(model->items); bool show_scrollbar = model->item_cnt > LIST_ITEMS; - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); for(uint32_t i = 0; i < MIN(model->item_cnt, LIST_ITEMS); i++) { int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); @@ -440,16 +442,16 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { BrowserItem_t* item = items_array_get( model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); item_type = item->type; - string_set(filename, item->display_name); + furi_string_set(filename, item->display_name); if(item_type == BrowserItemTypeFile) { custom_icon_data = item->custom_icon_data; } } else { - string_set_str(filename, "---"); + furi_string_set(filename, "---"); } if(item_type == BrowserItemTypeBack) { - string_set_str(filename, ". ."); + furi_string_set(filename, ". ."); } elements_string_fit_width( @@ -471,7 +473,8 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { canvas_draw_icon( canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, BrowserItemIcons[item_type]); } - canvas_draw_str(canvas, 15, Y_OFFSET + 9 + i * FRAME_HEIGHT, string_get_cstr(filename)); + canvas_draw_str( + canvas, 15, Y_OFFSET + 9 + i * FRAME_HEIGHT, furi_string_get_cstr(filename)); } if(show_scrollbar) { @@ -484,7 +487,7 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { model->item_cnt); } - string_clear(filename); + furi_string_free(filename); } static void file_browser_view_draw_callback(Canvas* canvas, void* _model) { @@ -504,17 +507,16 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { bool is_loading = false; with_view_model( - browser->view, (FileBrowserModel * model) { - is_loading = model->folder_loading; - return false; - }); + browser->view, FileBrowserModel * model, { is_loading = model->folder_loading; }, false); if(is_loading) { return false; } else if(event->key == InputKeyUp || event->key == InputKeyDown) { if(event->type == InputTypeShort || event->type == InputTypeRepeat) { with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { if(event->key == InputKeyUp) { model->item_idx = ((model->item_idx - 1) + model->item_cnt) % model->item_cnt; @@ -539,8 +541,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { browser->worker, load_offset, ITEM_LIST_LEN_MAX); } } - return true; - }); + }, + true); browser_update_offset(browser); consumed = true; } @@ -549,7 +551,9 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { BrowserItem_t* selected_item = NULL; int32_t select_index = 0; with_view_model( - browser->view, (FileBrowserModel * model) { + browser->view, + FileBrowserModel * model, + { if(browser_is_item_in_array(model, model->item_idx)) { selected_item = items_array_get(model->items, model->item_idx - model->array_offset); @@ -558,8 +562,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { select_index -= 1; } } - return false; - }); + }, + false); if(selected_item) { if(selected_item->type == BrowserItemTypeBack) { @@ -568,7 +572,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { file_browser_worker_folder_enter( browser->worker, selected_item->path, select_index); } else if(selected_item->type == BrowserItemTypeFile) { - string_set(browser->result_path, selected_item->path); + furi_string_set(browser->result_path, selected_item->path); if(browser->callback) { browser->callback(browser->context); } @@ -580,10 +584,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { if(event->type == InputTypeShort) { bool is_root = false; with_view_model( - browser->view, (FileBrowserModel * model) { - is_root = model->is_root; - return false; - }); + browser->view, FileBrowserModel * model, { is_root = model->is_root; }, false); if(!is_root) { file_browser_worker_folder_exit(browser->worker); } diff --git a/applications/services/gui/modules/file_browser.h b/applications/services/gui/modules/file_browser.h index 57a9f096..c9fdddb5 100644 --- a/applications/services/gui/modules/file_browser.h +++ b/applications/services/gui/modules/file_browser.h @@ -5,7 +5,6 @@ #pragma once -#include "m-string.h" #include #ifdef __cplusplus @@ -15,10 +14,13 @@ extern "C" { typedef struct FileBrowser FileBrowser; typedef void (*FileBrowserCallback)(void* context); -typedef bool ( - *FileBrowserLoadItemCallback)(string_t path, void* context, uint8_t** icon, string_t item_name); +typedef bool (*FileBrowserLoadItemCallback)( + FuriString* path, + void* context, + uint8_t** icon, + FuriString* item_name); -FileBrowser* file_browser_alloc(string_ptr result_path); +FileBrowser* file_browser_alloc(FuriString* result_path); void file_browser_free(FileBrowser* browser); @@ -31,7 +33,7 @@ void file_browser_configure( const Icon* file_icon, bool hide_ext); -void file_browser_start(FileBrowser* browser, string_t path); +void file_browser_start(FileBrowser* browser, FuriString* path); void file_browser_stop(FileBrowser* browser); diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index 36df6cc8..fdaf8273 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -1,7 +1,6 @@ #include "file_browser_worker.h" #include #include -#include "m-string.h" #include "storage/filesystem_api_defines.h" #include #include @@ -35,8 +34,8 @@ ARRAY_DEF(idx_last_array, int32_t) struct BrowserWorker { FuriThread* thread; - string_t filter_extension; - string_t path_next; + FuriString* filter_extension; + FuriString* path_next; int32_t item_sel_idx; uint32_t load_offset; uint32_t load_count; @@ -50,11 +49,11 @@ struct BrowserWorker { BrowserWorkerLongLoadCallback long_load_cb; }; -static bool browser_path_is_file(string_t path) { +static bool browser_path_is_file(FuriString* path) { bool state = false; FileInfo file_info; 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) == 0) { state = true; } @@ -63,50 +62,50 @@ static bool browser_path_is_file(string_t path) { return state; } -static bool browser_path_trim(string_t path) { +static bool browser_path_trim(FuriString* path) { bool is_root = false; - size_t filename_start = string_search_rchar(path, '/'); - string_left(path, filename_start); - if((string_empty_p(path)) || (filename_start == STRING_FAILURE)) { - string_set_str(path, BROWSER_ROOT); + size_t filename_start = furi_string_search_rchar(path, '/'); + furi_string_left(path, filename_start); + if((furi_string_empty(path)) || (filename_start == FURI_STRING_FAILURE)) { + furi_string_set(path, BROWSER_ROOT); is_root = true; } return is_root; } -static bool browser_filter_by_name(BrowserWorker* browser, string_t name, bool is_folder) { +static bool browser_filter_by_name(BrowserWorker* browser, FuriString* name, bool is_folder) { if(is_folder) { // Skip assets folders (if enabled) if(browser->skip_assets) { - return ((string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)); + return ((furi_string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)); } else { return true; } } else { // Filter files by extension - if((string_empty_p(browser->filter_extension)) || - (string_cmp_str(browser->filter_extension, "*") == 0)) { + if((furi_string_empty(browser->filter_extension)) || + (furi_string_cmp_str(browser->filter_extension, "*") == 0)) { return true; } - if(string_end_with_string_p(name, browser->filter_extension)) { + if(furi_string_end_with(name, browser->filter_extension)) { return true; } } return false; } -static bool browser_folder_check_and_switch(string_t path) { +static bool browser_folder_check_and_switch(FuriString* path) { FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); bool is_root = false; - if(string_search_rchar(path, '/') == 0) { + if(furi_string_search_rchar(path, '/') == 0) { is_root = true; } while(1) { // Check if folder is existing and navigate back if not - 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) { break; } @@ -122,8 +121,8 @@ static bool browser_folder_check_and_switch(string_t path) { static bool browser_folder_init( BrowserWorker* browser, - string_t path, - string_t filename, + FuriString* path, + FuriString* filename, uint32_t* item_cnt, int32_t* file_idx) { bool state = false; @@ -134,13 +133,13 @@ static bool browser_folder_init( File* directory = storage_file_alloc(storage); char name_temp[FILE_NAME_LEN_MAX]; - string_t name_str; - string_init(name_str); + FuriString* name_str; + name_str = furi_string_alloc(); *item_cnt = 0; *file_idx = -1; - if(storage_dir_open(directory, string_get_cstr(path))) { + if(storage_dir_open(directory, furi_string_get_cstr(path))) { state = true; while(1) { if(!storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX)) { @@ -148,10 +147,10 @@ static bool browser_folder_init( } if((storage_file_get_error(directory) == FSE_OK) && (name_temp[0] != '\0')) { total_files_cnt++; - string_set_str(name_str, name_temp); + furi_string_set(name_str, name_temp); if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { - if(!string_empty_p(filename)) { - if(string_cmp(name_str, filename) == 0) { + if(!furi_string_empty(filename)) { + if(furi_string_cmp(name_str, filename) == 0) { *file_idx = *item_cnt; } } @@ -167,7 +166,7 @@ static bool browser_folder_init( } } - string_clear(name_str); + furi_string_free(name_str); storage_dir_close(directory); storage_file_free(directory); @@ -178,20 +177,20 @@ static bool browser_folder_init( } static bool - browser_folder_load(BrowserWorker* browser, string_t path, uint32_t offset, uint32_t count) { + browser_folder_load(BrowserWorker* browser, FuriString* path, uint32_t offset, uint32_t count) { FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); File* directory = storage_file_alloc(storage); char name_temp[FILE_NAME_LEN_MAX]; - string_t name_str; - string_init(name_str); + FuriString* name_str; + name_str = furi_string_alloc(); uint32_t items_cnt = 0; do { - if(!storage_dir_open(directory, string_get_cstr(path))) { + if(!storage_dir_open(directory, furi_string_get_cstr(path))) { break; } @@ -201,7 +200,7 @@ static bool break; } if(storage_file_get_error(directory) == FSE_OK) { - string_set_str(name_str, name_temp); + furi_string_set(name_str, name_temp); if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { items_cnt++; } @@ -223,9 +222,9 @@ static bool break; } if(storage_file_get_error(directory) == FSE_OK) { - string_set_str(name_str, name_temp); + furi_string_set(name_str, name_temp); if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { - string_printf(name_str, "%s/%s", string_get_cstr(path), name_temp); + furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp); if(browser->list_item_cb) { browser->list_item_cb( browser->cb_ctx, name_str, (file_info.flags & FSF_DIRECTORY), false); @@ -241,7 +240,7 @@ static bool } } while(0); - string_clear(name_str); + furi_string_free(name_str); storage_dir_close(directory); storage_file_free(directory); @@ -257,12 +256,12 @@ static int32_t browser_worker(void* context) { FURI_LOG_D(TAG, "Start"); uint32_t items_cnt = 0; - string_t path; - string_init_set_str(path, BROWSER_ROOT); + FuriString* path; + path = furi_string_alloc_set(BROWSER_ROOT); browser->item_sel_idx = -1; - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange); @@ -282,7 +281,7 @@ static int32_t browser_worker(void* context) { } if(flags & WorkerEvtFolderEnter) { - string_set(path, browser->path_next); + furi_string_set(path, browser->path_next); bool is_root = browser_folder_check_and_switch(path); // Push previous selected item index to history array @@ -292,14 +291,14 @@ static int32_t browser_worker(void* context) { browser_folder_init(browser, path, filename, &items_cnt, &file_idx); FURI_LOG_D( TAG, - "Enter folder: %s items: %u idx: %d", - string_get_cstr(path), + "Enter folder: %s items: %lu idx: %ld", + furi_string_get_cstr(path), items_cnt, file_idx); if(browser->folder_cb) { browser->folder_cb(browser->cb_ctx, items_cnt, file_idx, is_root); } - string_reset(filename); + furi_string_reset(filename); } if(flags & WorkerEvtFolderExit) { @@ -313,7 +312,11 @@ static int32_t browser_worker(void* context) { idx_last_array_pop_back(&file_idx, browser->idx_last); } FURI_LOG_D( - TAG, "Exit to: %s items: %u idx: %d", string_get_cstr(path), items_cnt, file_idx); + TAG, + "Exit to: %s items: %lu idx: %ld", + furi_string_get_cstr(path), + items_cnt, + file_idx); if(browser->folder_cb) { browser->folder_cb(browser->cb_ctx, items_cnt, file_idx, is_root); } @@ -323,12 +326,12 @@ static int32_t browser_worker(void* context) { bool is_root = browser_folder_check_and_switch(path); int32_t file_idx = 0; - string_reset(filename); + furi_string_reset(filename); browser_folder_init(browser, path, filename, &items_cnt, &file_idx); FURI_LOG_D( TAG, - "Refresh folder: %s items: %u idx: %d", - string_get_cstr(path), + "Refresh folder: %s items: %lu idx: %ld", + furi_string_get_cstr(path), items_cnt, browser->item_sel_idx); if(browser->folder_cb) { @@ -337,7 +340,8 @@ static int32_t browser_worker(void* context) { } if(flags & WorkerEvtLoad) { - FURI_LOG_D(TAG, "Load offset: %u cnt: %u", browser->load_offset, browser->load_count); + FURI_LOG_D( + TAG, "Load offset: %lu cnt: %lu", browser->load_offset, browser->load_count); browser_folder_load(browser, path, browser->load_offset, browser->load_count); } @@ -346,21 +350,22 @@ static int32_t browser_worker(void* context) { } } - string_clear(filename); - string_clear(path); + furi_string_free(filename); + furi_string_free(path); FURI_LOG_D(TAG, "End"); return 0; } -BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets) { +BrowserWorker* + file_browser_worker_alloc(FuriString* path, const char* filter_ext, bool skip_assets) { BrowserWorker* browser = malloc(sizeof(BrowserWorker)); idx_last_array_init(browser->idx_last); - string_init_set_str(browser->filter_extension, filter_ext); + browser->filter_extension = furi_string_alloc_set(filter_ext); browser->skip_assets = skip_assets; - string_init_set(browser->path_next, path); + browser->path_next = furi_string_alloc_set(path); browser->thread = furi_thread_alloc(); furi_thread_set_name(browser->thread, "BrowserWorker"); @@ -379,8 +384,8 @@ void file_browser_worker_free(BrowserWorker* browser) { furi_thread_join(browser->thread); furi_thread_free(browser->thread); - string_clear(browser->filter_extension); - string_clear(browser->path_next); + furi_string_free(browser->filter_extension); + furi_string_free(browser->path_next); idx_last_array_clear(browser->idx_last); @@ -422,19 +427,19 @@ void file_browser_worker_set_long_load_callback( void file_browser_worker_set_config( BrowserWorker* browser, - string_t path, + FuriString* path, const char* filter_ext, bool skip_assets) { furi_assert(browser); - string_set(browser->path_next, path); - string_set_str(browser->filter_extension, filter_ext); + furi_string_set(browser->path_next, path); + furi_string_set(browser->filter_extension, filter_ext); browser->skip_assets = skip_assets; furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange); } -void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx) { +void file_browser_worker_folder_enter(BrowserWorker* browser, FuriString* path, int32_t item_idx) { furi_assert(browser); - string_set(browser->path_next, path); + furi_string_set(browser->path_next, path); browser->item_sel_idx = item_idx; furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter); } diff --git a/applications/services/gui/modules/file_browser_worker.h b/applications/services/gui/modules/file_browser_worker.h index 18c0b481..230bb5b4 100644 --- a/applications/services/gui/modules/file_browser_worker.h +++ b/applications/services/gui/modules/file_browser_worker.h @@ -1,6 +1,5 @@ #pragma once -#include "m-string.h" #include #include @@ -17,12 +16,13 @@ typedef void (*BrowserWorkerFolderOpenCallback)( typedef void (*BrowserWorkerListLoadCallback)(void* context, uint32_t list_load_offset); typedef void (*BrowserWorkerListItemCallback)( void* context, - string_t item_path, + FuriString* item_path, bool is_folder, bool is_last); typedef void (*BrowserWorkerLongLoadCallback)(void* context); -BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets); +BrowserWorker* + file_browser_worker_alloc(FuriString* path, const char* filter_ext, bool skip_assets); void file_browser_worker_free(BrowserWorker* browser); @@ -46,11 +46,11 @@ void file_browser_worker_set_long_load_callback( void file_browser_worker_set_config( BrowserWorker* browser, - string_t path, + FuriString* path, const char* filter_ext, bool skip_assets); -void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx); +void file_browser_worker_folder_enter(BrowserWorker* browser, FuriString* path, int32_t item_idx); void file_browser_worker_folder_exit(BrowserWorker* browser); diff --git a/applications/services/gui/modules/menu.c b/applications/services/gui/modules/menu.c index 67d46d5f..db0717f7 100644 --- a/applications/services/gui/modules/menu.c +++ b/applications/services/gui/modules/menu.c @@ -103,25 +103,29 @@ static bool menu_input_callback(InputEvent* event, void* context) { static void menu_enter(void* context) { Menu* menu = context; with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { MenuItem* item = MenuItemArray_get(model->items, model->position); if(item && item->icon) { icon_animation_start(item->icon); } - return false; - }); + }, + false); } static void menu_exit(void* context) { Menu* menu = context; with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { MenuItem* item = MenuItemArray_get(model->items, model->position); if(item && item->icon) { icon_animation_stop(item->icon); } - return false; - }); + }, + false); } Menu* menu_alloc() { @@ -135,11 +139,13 @@ Menu* menu_alloc() { view_set_exit_callback(menu->view, menu_exit); with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { MenuItemArray_init(model->items); model->position = 0; - return true; - }); + }, + true); return menu; } @@ -168,7 +174,9 @@ void menu_add_item( MenuItem* item = NULL; with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { item = MenuItemArray_push_new(model->items); item->label = label; item->icon = icon ? icon_animation_alloc(icon) : icon_animation_alloc(&A_Plugins_14); @@ -176,14 +184,16 @@ void menu_add_item( item->index = index; item->callback = callback; item->callback_context = context; - return true; - }); + }, + true); } void menu_reset(Menu* menu) { furi_assert(menu); with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { for M_EACH(item, model->items, MenuItemArray_t) { icon_animation_stop(item->icon); @@ -192,25 +202,27 @@ void menu_reset(Menu* menu) { MenuItemArray_reset(model->items); model->position = 0; - return true; - }); + }, + true); } void menu_set_selected_item(Menu* menu, uint32_t index) { with_view_model( - menu->view, (MenuModel * model) { - if(index >= MenuItemArray_size(model->items)) { - return false; + menu->view, + MenuModel * model, + { + if(index < MenuItemArray_size(model->items)) { + model->position = index; } - - model->position = index; - return true; - }); + }, + true); } static void menu_process_up(Menu* menu) { with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { MenuItem* item = MenuItemArray_get(model->items, model->position); if(item && item->icon) { icon_animation_stop(item->icon); @@ -226,13 +238,15 @@ static void menu_process_up(Menu* menu) { if(item && item->icon) { icon_animation_start(item->icon); } - return true; - }); + }, + true); } static void menu_process_down(Menu* menu) { with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { MenuItem* item = MenuItemArray_get(model->items, model->position); if(item && item->icon) { icon_animation_stop(item->icon); @@ -248,19 +262,21 @@ static void menu_process_down(Menu* menu) { if(item && item->icon) { icon_animation_start(item->icon); } - return true; - }); + }, + true); } static void menu_process_ok(Menu* menu) { MenuItem* item = NULL; with_view_model( - menu->view, (MenuModel * model) { + menu->view, + MenuModel * model, + { if(model->position < MenuItemArray_size(model->items)) { item = MenuItemArray_get(model->items, model->position); } - return true; - }); + }, + true); if(item && item->callback) { item->callback(item->callback_context, item->index); } diff --git a/applications/services/gui/modules/popup.c b/applications/services/gui/modules/popup.c index b3cb5e53..08e8d8c2 100644 --- a/applications/services/gui/modules/popup.c +++ b/applications/services/gui/modules/popup.c @@ -124,7 +124,9 @@ Popup* popup_alloc() { view_set_exit_callback(popup->view, popup_stop_timer); with_view_model( - popup->view, (PopupModel * model) { + popup->view, + PopupModel * model, + { model->header.text = NULL; model->header.x = 0; model->header.y = 0; @@ -140,8 +142,8 @@ Popup* popup_alloc() { model->icon.x = 0; model->icon.y = 0; model->icon.icon = NULL; - return true; - }); + }, + true); return popup; } @@ -176,14 +178,16 @@ void popup_set_header( Align vertical) { furi_assert(popup); with_view_model( - popup->view, (PopupModel * model) { + popup->view, + PopupModel * model, + { model->header.text = text; model->header.x = x; model->header.y = y; model->header.horizontal = horizontal; model->header.vertical = vertical; - return true; - }); + }, + true); } void popup_set_text( @@ -195,25 +199,29 @@ void popup_set_text( Align vertical) { furi_assert(popup); with_view_model( - popup->view, (PopupModel * model) { + popup->view, + PopupModel * model, + { model->text.text = text; model->text.x = x; model->text.y = y; model->text.horizontal = horizontal; model->text.vertical = vertical; - return true; - }); + }, + true); } void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, const Icon* icon) { furi_assert(popup); with_view_model( - popup->view, (PopupModel * model) { + popup->view, + PopupModel * model, + { model->icon.x = x; model->icon.y = y; model->icon.icon = icon; - return true; - }); + }, + true); } void popup_set_timeout(Popup* popup, uint32_t timeout_in_ms) { @@ -233,12 +241,14 @@ void popup_reset(Popup* popup) { furi_assert(popup); with_view_model( - popup->view, (PopupModel * model) { + popup->view, + PopupModel * model, + { memset(&model->header, 0, sizeof(model->header)); memset(&model->text, 0, sizeof(model->text)); memset(&model->icon, 0, sizeof(model->icon)); - return false; - }); + }, + false); popup->callback = NULL; popup->context = NULL; popup->timer_enabled = false; diff --git a/applications/services/gui/modules/submenu.c b/applications/services/gui/modules/submenu.c index 9fefeca0..94959877 100644 --- a/applications/services/gui/modules/submenu.c +++ b/applications/services/gui/modules/submenu.c @@ -65,17 +65,17 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) { canvas_set_color(canvas, ColorBlack); } - string_t disp_str; - string_init_set_str(disp_str, SubmenuItemArray_cref(it)->label); + FuriString* disp_str; + disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label); elements_string_fit_width(canvas, disp_str, item_width - 20); canvas_draw_str( canvas, 6, y_offset + (item_position * item_height) + item_height - 4, - string_get_cstr(disp_str)); + furi_string_get_cstr(disp_str)); - string_clear(disp_str); + furi_string_free(disp_str); } position++; @@ -128,13 +128,15 @@ Submenu* submenu_alloc() { view_set_input_callback(submenu->view, submenu_view_input_callback); with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { SubmenuItemArray_init(model->items); model->position = 0; model->window_position = 0; model->header = NULL; - return true; - }); + }, + true); return submenu; } @@ -143,10 +145,7 @@ void submenu_free(Submenu* submenu) { furi_assert(submenu); with_view_model( - submenu->view, (SubmenuModel * model) { - SubmenuItemArray_clear(model->items); - return true; - }); + submenu->view, SubmenuModel * model, { SubmenuItemArray_clear(model->items); }, true); view_free(submenu->view); free(submenu); } @@ -167,32 +166,38 @@ void submenu_add_item( furi_assert(submenu); with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { item = SubmenuItemArray_push_new(model->items); item->label = label; item->index = index; item->callback = callback; item->callback_context = callback_context; - return true; - }); + }, + true); } void submenu_reset(Submenu* submenu) { furi_assert(submenu); with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { SubmenuItemArray_reset(model->items); model->position = 0; model->window_position = 0; model->header = NULL; - return true; - }); + }, + true); } void submenu_set_selected_item(Submenu* submenu, uint32_t index) { with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { uint32_t position = 0; SubmenuItemArray_it_t it; for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it); @@ -225,14 +230,15 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) { (SubmenuItemArray_size(model->items) - items_on_screen); } } - - return true; - }); + }, + true); } void submenu_process_up(Submenu* submenu) { with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { uint8_t items_on_screen = model->header ? 3 : 4; if(model->position > 0) { model->position--; @@ -246,13 +252,15 @@ void submenu_process_up(Submenu* submenu) { model->window_position = model->position - (items_on_screen - 1); } } - return true; - }); + }, + true); } void submenu_process_down(Submenu* submenu) { with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { uint8_t items_on_screen = model->header ? 3 : 4; if(model->position < (SubmenuItemArray_size(model->items) - 1)) { model->position++; @@ -265,20 +273,22 @@ void submenu_process_down(Submenu* submenu) { model->position = 0; model->window_position = 0; } - return true; - }); + }, + true); } void submenu_process_ok(Submenu* submenu) { SubmenuItem* item = NULL; with_view_model( - submenu->view, (SubmenuModel * model) { + submenu->view, + SubmenuModel * model, + { if(model->position < (SubmenuItemArray_size(model->items))) { item = SubmenuItemArray_get(model->items, model->position); } - return true; - }); + }, + true); if(item && item->callback) { item->callback(item->callback_context, item->index); @@ -289,8 +299,5 @@ void submenu_set_header(Submenu* submenu, const char* header) { furi_assert(submenu); with_view_model( - submenu->view, (SubmenuModel * model) { - model->header = header; - return true; - }); + submenu->view, SubmenuModel * model, { model->header = header; }, true); } diff --git a/applications/services/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c index 52307ec2..99d7d04f 100644 --- a/applications/services/gui/modules/text_box.c +++ b/applications/services/gui/modules/text_box.c @@ -1,6 +1,5 @@ #include "text_box.h" #include "gui/canvas.h" -#include #include #include #include @@ -12,7 +11,7 @@ struct TextBox { typedef struct { const char* text; char* text_pos; - string_t text_formatted; + FuriString* text_formatted; int32_t scroll_pos; int32_t scroll_num; TextBoxFont font; @@ -22,20 +21,24 @@ typedef struct { static void text_box_process_down(TextBox* text_box) { with_view_model( - text_box->view, (TextBoxModel * model) { + text_box->view, + TextBoxModel * model, + { if(model->scroll_pos < model->scroll_num - 1) { model->scroll_pos++; // Search next line start while(*model->text_pos++ != '\n') ; } - return true; - }); + }, + true); } static void text_box_process_up(TextBox* text_box) { with_view_model( - text_box->view, (TextBoxModel * model) { + text_box->view, + TextBoxModel * model, + { if(model->scroll_pos > 0) { model->scroll_pos--; // Reach last symbol of previous line @@ -47,8 +50,8 @@ static void text_box_process_up(TextBox* text_box) { model->text_pos++; } } - return true; - }); + }, + true); } static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { @@ -66,17 +69,17 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { if(line_width + glyph_width > text_width) { line_num++; line_width = 0; - string_push_back(model->text_formatted, '\n'); + furi_string_push_back(model->text_formatted, '\n'); } line_width += glyph_width; } else { line_num++; line_width = 0; } - string_push_back(model->text_formatted, symb); + furi_string_push_back(model->text_formatted, symb); } line_num++; - model->text = string_get_cstr(model->text_formatted); + model->text = furi_string_get_cstr(model->text_formatted); model->text_pos = (char*)model->text; if(model->focus == TextBoxFocusEnd && line_num > 5) { // Set text position to 5th line from the end @@ -138,13 +141,15 @@ TextBox* text_box_alloc() { view_set_input_callback(text_box->view, text_box_view_input_callback); with_view_model( - text_box->view, (TextBoxModel * model) { + text_box->view, + TextBoxModel * model, + { model->text = NULL; - string_init_set_str(model->text_formatted, ""); + model->text_formatted = furi_string_alloc_set(""); model->formatted = false; model->font = TextBoxFontText; - return true; - }); + }, + true); return text_box; } @@ -153,10 +158,7 @@ void text_box_free(TextBox* text_box) { furi_assert(text_box); with_view_model( - text_box->view, (TextBoxModel * model) { - string_clear(model->text_formatted); - return true; - }); + text_box->view, TextBoxModel * model, { furi_string_free(model->text_formatted); }, true); view_free(text_box->view); free(text_box); } @@ -170,13 +172,15 @@ void text_box_reset(TextBox* text_box) { furi_assert(text_box); with_view_model( - text_box->view, (TextBoxModel * model) { + text_box->view, + TextBoxModel * model, + { model->text = NULL; - string_set_str(model->text_formatted, ""); + furi_string_set(model->text_formatted, ""); model->font = TextBoxFontText; model->focus = TextBoxFocusStart; - return true; - }); + }, + true); } void text_box_set_text(TextBox* text_box, const char* text) { @@ -184,31 +188,27 @@ void text_box_set_text(TextBox* text_box, const char* text) { furi_assert(text); with_view_model( - text_box->view, (TextBoxModel * model) { + text_box->view, + TextBoxModel * model, + { model->text = text; - string_reset(model->text_formatted); - string_reserve(model->text_formatted, strlen(text)); + furi_string_reset(model->text_formatted); + furi_string_reserve(model->text_formatted, strlen(text)); model->formatted = false; - return true; - }); + }, + true); } void text_box_set_font(TextBox* text_box, TextBoxFont font) { furi_assert(text_box); with_view_model( - text_box->view, (TextBoxModel * model) { - model->font = font; - return true; - }); + text_box->view, TextBoxModel * model, { model->font = font; }, true); } void text_box_set_focus(TextBox* text_box, TextBoxFocus focus) { furi_assert(text_box); with_view_model( - text_box->view, (TextBoxModel * model) { - model->focus = focus; - return true; - }); + text_box->view, TextBoxModel * model, { model->focus = focus; }, true); } diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index b2aba03f..79fa8772 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -27,7 +27,7 @@ typedef struct { TextInputValidatorCallback validator_callback; void* validator_callback_context; - string_t validator_text; + FuriString* validator_text; bool valadator_message_visible; } TextInputModel; @@ -257,7 +257,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, string_get_cstr(model->validator_text)); + elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); canvas_set_font(canvas, FontKeyboard); } } @@ -429,10 +429,10 @@ void text_input_timer_callback(void* context) { TextInput* text_input = context; with_view_model( - text_input->view, (TextInputModel * model) { - model->valadator_message_visible = false; - return true; - }); + text_input->view, + TextInputModel * model, + { model->valadator_message_visible = false; }, + true); } TextInput* text_input_alloc() { @@ -446,10 +446,10 @@ TextInput* text_input_alloc() { text_input->timer = furi_timer_alloc(text_input_timer_callback, FuriTimerTypeOnce, text_input); with_view_model( - text_input->view, (TextInputModel * model) { - string_init(model->validator_text); - return false; - }); + text_input->view, + TextInputModel * model, + { model->validator_text = furi_string_alloc(); }, + false); text_input_reset(text_input); @@ -459,10 +459,10 @@ TextInput* text_input_alloc() { void text_input_free(TextInput* text_input) { furi_assert(text_input); with_view_model( - text_input->view, (TextInputModel * model) { - string_clear(model->validator_text); - return false; - }); + text_input->view, + TextInputModel * model, + { furi_string_free(model->validator_text); }, + false); // Send stop command furi_timer_stop(text_input->timer); @@ -477,7 +477,9 @@ void text_input_free(TextInput* text_input) { void text_input_reset(TextInput* text_input) { furi_assert(text_input); with_view_model( - text_input->view, (TextInputModel * model) { + text_input->view, + TextInputModel * model, + { model->text_buffer_size = 0; model->header = ""; model->selected_row = 0; @@ -489,10 +491,10 @@ void text_input_reset(TextInput* text_input) { model->callback_context = NULL; model->validator_callback = NULL; model->validator_callback_context = NULL; - string_reset(model->validator_text); + furi_string_reset(model->validator_text); model->valadator_message_visible = false; - return true; - }); + }, + true); } View* text_input_get_view(TextInput* text_input) { @@ -508,7 +510,9 @@ void text_input_set_result_callback( size_t text_buffer_size, bool clear_default_text) { with_view_model( - text_input->view, (TextInputModel * model) { + text_input->view, + TextInputModel * model, + { model->callback = callback; model->callback_context = callback_context; model->text_buffer = text_buffer; @@ -519,8 +523,8 @@ void text_input_set_result_callback( model->selected_row = 2; model->selected_column = 8; } - return true; - }); + }, + true); } void text_input_set_validator( @@ -528,37 +532,36 @@ void text_input_set_validator( TextInputValidatorCallback callback, void* callback_context) { with_view_model( - text_input->view, (TextInputModel * model) { + text_input->view, + TextInputModel * model, + { model->validator_callback = callback; model->validator_callback_context = callback_context; - return true; - }); + }, + true); } TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input) { TextInputValidatorCallback validator_callback = NULL; with_view_model( - text_input->view, (TextInputModel * model) { - validator_callback = model->validator_callback; - return false; - }); + text_input->view, + TextInputModel * model, + { validator_callback = model->validator_callback; }, + false); return validator_callback; } void* text_input_get_validator_callback_context(TextInput* text_input) { void* validator_callback_context = NULL; with_view_model( - text_input->view, (TextInputModel * model) { - validator_callback_context = model->validator_callback_context; - return false; - }); + text_input->view, + TextInputModel * model, + { validator_callback_context = model->validator_callback_context; }, + false); return validator_callback_context; } void text_input_set_header_text(TextInput* text_input, const char* text) { with_view_model( - text_input->view, (TextInputModel * model) { - model->header = text; - return true; - }); + text_input->view, TextInputModel * model, { model->header = text; }, true); } diff --git a/applications/services/gui/modules/text_input.h b/applications/services/gui/modules/text_input.h index d30fcd4c..893fbd53 100644 --- a/applications/services/gui/modules/text_input.h +++ b/applications/services/gui/modules/text_input.h @@ -7,7 +7,6 @@ #include #include "validators.h" -#include #ifdef __cplusplus extern "C" { @@ -16,7 +15,7 @@ extern "C" { /** Text input anonymous structure */ typedef struct TextInput TextInput; typedef void (*TextInputCallback)(void* context); -typedef bool (*TextInputValidatorCallback)(const char* text, string_t error, void* context); +typedef bool (*TextInputValidatorCallback)(const char* text, FuriString* error, void* context); /** Allocate and initialize text input * diff --git a/applications/services/gui/modules/validators.c b/applications/services/gui/modules/validators.c index d5fb0fa2..0463b1c2 100644 --- a/applications/services/gui/modules/validators.c +++ b/applications/services/gui/modules/validators.c @@ -8,7 +8,7 @@ struct ValidatorIsFile { char* current_name; }; -bool validator_is_file_callback(const char* text, string_t error, void* context) { +bool validator_is_file_callback(const char* text, FuriString* error, void* context) { furi_assert(context); ValidatorIsFile* instance = context; @@ -19,16 +19,16 @@ bool validator_is_file_callback(const char* text, string_t error, void* context) } bool ret = true; - string_t path; - string_init_printf(path, "%s/%s%s", instance->app_path_folder, text, instance->app_extension); + FuriString* path = furi_string_alloc_printf( + "%s/%s%s", instance->app_path_folder, text, instance->app_extension); Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK) { + if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { ret = false; - string_printf(error, "This name\nexists!\nChoose\nanother one."); + furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); } else { ret = true; } - string_clear(path); + furi_string_free(path); furi_record_close(RECORD_STORAGE); return ret; diff --git a/applications/services/gui/modules/validators.h b/applications/services/gui/modules/validators.h index c4c4ef54..d9200b6d 100644 --- a/applications/services/gui/modules/validators.h +++ b/applications/services/gui/modules/validators.h @@ -1,6 +1,5 @@ #pragma once -#include #include #ifdef __cplusplus @@ -15,7 +14,7 @@ ValidatorIsFile* validator_is_file_alloc_init( void validator_is_file_free(ValidatorIsFile* instance); -bool validator_is_file_callback(const char* text, string_t error, void* context); +bool validator_is_file_callback(const char* text, FuriString* error, void* context); #ifdef __cplusplus } diff --git a/applications/services/gui/modules/variable_item_list.c b/applications/services/gui/modules/variable_item_list.c index 4e5e4664..acd46ee4 100644 --- a/applications/services/gui/modules/variable_item_list.c +++ b/applications/services/gui/modules/variable_item_list.c @@ -8,7 +8,7 @@ struct VariableItem { const char* label; uint8_t current_value_index; - string_t current_value_text; + FuriString* current_value_text; uint8_t values_count; VariableItemChangeCallback change_callback; void* context; @@ -77,7 +77,7 @@ static void variable_item_list_draw_callback(Canvas* canvas, void* _model) { item_text_y, AlignCenter, AlignBottom, - string_get_cstr(item->current_value_text)); + furi_string_get_cstr(item->current_value_text)); if(item->current_value_index < (item->values_count - 1)) { canvas_draw_str(canvas, 115, item_text_y, ">"); @@ -92,7 +92,9 @@ static void variable_item_list_draw_callback(Canvas* canvas, void* _model) { void variable_item_list_set_selected_item(VariableItemList* variable_item_list, uint8_t index) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { uint8_t position = index; if(position >= VariableItemArray_size(model->items)) { position = 0; @@ -112,9 +114,8 @@ void variable_item_list_set_selected_item(VariableItemList* variable_item_list, model->window_position = (VariableItemArray_size(model->items) - 4); } } - - return true; - }); + }, + true); } uint8_t variable_item_list_get_selected_item_index(VariableItemList* variable_item_list) { @@ -181,7 +182,9 @@ static bool variable_item_list_input_callback(InputEvent* event, void* context) void variable_item_list_process_up(VariableItemList* variable_item_list) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { uint8_t items_on_screen = 4; if(model->position > 0) { model->position--; @@ -195,13 +198,15 @@ void variable_item_list_process_up(VariableItemList* variable_item_list) { model->window_position = model->position - (items_on_screen - 1); } } - return true; - }); + }, + true); } void variable_item_list_process_down(VariableItemList* variable_item_list) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { uint8_t items_on_screen = 4; if(model->position < (VariableItemArray_size(model->items) - 1)) { model->position++; @@ -214,8 +219,8 @@ void variable_item_list_process_down(VariableItemList* variable_item_list) { model->position = 0; model->window_position = 0; } - return true; - }); + }, + true); } VariableItem* variable_item_list_get_selected_item(VariableItemListModel* model) { @@ -239,7 +244,9 @@ VariableItem* variable_item_list_get_selected_item(VariableItemListModel* model) void variable_item_list_process_left(VariableItemList* variable_item_list) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { VariableItem* item = variable_item_list_get_selected_item(model); if(item->current_value_index > 0) { item->current_value_index--; @@ -247,13 +254,15 @@ void variable_item_list_process_left(VariableItemList* variable_item_list) { item->change_callback(item); } } - return true; - }); + }, + true); } void variable_item_list_process_right(VariableItemList* variable_item_list) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { VariableItem* item = variable_item_list_get_selected_item(model); if(item->current_value_index < (item->values_count - 1)) { item->current_value_index++; @@ -261,18 +270,20 @@ void variable_item_list_process_right(VariableItemList* variable_item_list) { item->change_callback(item); } } - return true; - }); + }, + true); } void variable_item_list_process_ok(VariableItemList* variable_item_list) { with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { if(variable_item_list->callback) { variable_item_list->callback(variable_item_list->context, model->position); } - return false; - }); + }, + false); } VariableItemList* variable_item_list_alloc() { @@ -285,12 +296,14 @@ VariableItemList* variable_item_list_alloc() { view_set_input_callback(variable_item_list->view, variable_item_list_input_callback); with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { VariableItemArray_init(model->items); model->position = 0; model->window_position = 0; - return true; - }); + }, + true); return variable_item_list; } @@ -299,15 +312,17 @@ void variable_item_list_free(VariableItemList* variable_item_list) { furi_assert(variable_item_list); with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { VariableItemArray_it_t it; for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it); VariableItemArray_next(it)) { - string_clear(VariableItemArray_ref(it)->current_value_text); + furi_string_free(VariableItemArray_ref(it)->current_value_text); } VariableItemArray_clear(model->items); - return false; - }); + }, + false); view_free(variable_item_list->view); free(variable_item_list); } @@ -316,15 +331,17 @@ void variable_item_list_reset(VariableItemList* variable_item_list) { furi_assert(variable_item_list); with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { VariableItemArray_it_t it; for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it); VariableItemArray_next(it)) { - string_clear(VariableItemArray_ref(it)->current_value_text); + furi_string_free(VariableItemArray_ref(it)->current_value_text); } VariableItemArray_reset(model->items); - return false; - }); + }, + false); } View* variable_item_list_get_view(VariableItemList* variable_item_list) { @@ -343,16 +360,18 @@ VariableItem* variable_item_list_add( furi_assert(variable_item_list); with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { item = VariableItemArray_push_new(model->items); item->label = label; item->values_count = values_count; item->change_callback = change_callback; item->context = context; item->current_value_index = 0; - string_init(item->current_value_text); - return true; - }); + item->current_value_text = furi_string_alloc(); + }, + true); return item; } @@ -363,12 +382,14 @@ void variable_item_list_set_enter_callback( void* context) { furi_assert(callback); with_view_model( - variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->view, + VariableItemListModel * model, + { UNUSED(model); variable_item_list->callback = callback; variable_item_list->context = context; - return false; - }); + }, + false); } void variable_item_set_current_value_index(VariableItem* item, uint8_t current_value_index) { @@ -376,7 +397,7 @@ void variable_item_set_current_value_index(VariableItem* item, uint8_t current_v } void variable_item_set_current_value_text(VariableItem* item, const char* current_value_text) { - string_set_str(item->current_value_text, current_value_text); + furi_string_set(item->current_value_text, current_value_text); } uint8_t variable_item_get_current_value_index(VariableItem* item) { diff --git a/applications/services/gui/modules/widget.c b/applications/services/gui/modules/widget.c index 802f76e2..6153b425 100644 --- a/applications/services/gui/modules/widget.c +++ b/applications/services/gui/modules/widget.c @@ -36,7 +36,9 @@ static bool gui_widget_view_input_callback(InputEvent* event, void* context) { // Call all Widget Elements input handlers with_view_model( - widget->view, (GuiWidgetModel * model) { + widget->view, + GuiWidgetModel * model, + { ElementArray_it_t it; ElementArray_it(it, model->element); while(!ElementArray_end_p(it)) { @@ -46,8 +48,8 @@ static bool gui_widget_view_input_callback(InputEvent* event, void* context) { } ElementArray_next(it); } - return true; - }); + }, + true); return consumed; } @@ -61,10 +63,7 @@ Widget* widget_alloc() { view_set_input_callback(widget->view, gui_widget_view_input_callback); with_view_model( - widget->view, (GuiWidgetModel * model) { - ElementArray_init(model->element); - return true; - }); + widget->view, GuiWidgetModel * model, { ElementArray_init(model->element); }, true); return widget; } @@ -73,7 +72,9 @@ void widget_reset(Widget* widget) { furi_assert(widget); with_view_model( - widget->view, (GuiWidgetModel * model) { + widget->view, + GuiWidgetModel * model, + { ElementArray_it_t it; ElementArray_it(it, model->element); while(!ElementArray_end_p(it)) { @@ -83,8 +84,8 @@ void widget_reset(Widget* widget) { ElementArray_next(it); } ElementArray_reset(model->element); - return true; - }); + }, + true); } void widget_free(Widget* widget) { @@ -93,10 +94,7 @@ void widget_free(Widget* widget) { widget_reset(widget); // Free elements container with_view_model( - widget->view, (GuiWidgetModel * model) { - ElementArray_clear(model->element); - return true; - }); + widget->view, GuiWidgetModel * model, { ElementArray_clear(model->element); }, true); view_free(widget->view); free(widget); @@ -112,11 +110,13 @@ static void widget_add_element(Widget* widget, WidgetElement* element) { furi_assert(element); with_view_model( - widget->view, (GuiWidgetModel * model) { + widget->view, + GuiWidgetModel * model, + { element->parent = widget; ElementArray_push_back(model->element, element); - return true; - }); + }, + true); } void widget_add_string_multiline_element( diff --git a/applications/services/gui/modules/widget_elements/widget_element_button.c b/applications/services/gui/modules/widget_elements/widget_element_button.c index 92be2590..be33b189 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_button.c +++ b/applications/services/gui/modules/widget_elements/widget_element_button.c @@ -1,10 +1,9 @@ #include "widget_element_i.h" #include -#include typedef struct { GuiButtonType button_type; - string_t text; + FuriString* text; ButtonCallback callback; void* context; } GuiButtonModel; @@ -18,11 +17,11 @@ static void gui_button_draw(Canvas* canvas, WidgetElement* element) { canvas_set_font(canvas, FontSecondary); if(model->button_type == GuiButtonTypeLeft) { - elements_button_left(canvas, string_get_cstr(model->text)); + elements_button_left(canvas, furi_string_get_cstr(model->text)); } else if(model->button_type == GuiButtonTypeRight) { - elements_button_right(canvas, string_get_cstr(model->text)); + elements_button_right(canvas, furi_string_get_cstr(model->text)); } else if(model->button_type == GuiButtonTypeCenter) { - elements_button_center(canvas, string_get_cstr(model->text)); + elements_button_center(canvas, furi_string_get_cstr(model->text)); } } @@ -50,7 +49,7 @@ static void gui_button_free(WidgetElement* gui_button) { furi_assert(gui_button); GuiButtonModel* model = gui_button->model; - string_clear(model->text); + furi_string_free(model->text); free(gui_button->model); free(gui_button); } @@ -65,7 +64,7 @@ WidgetElement* widget_element_button_create( model->button_type = button_type; model->callback = callback; model->context = context; - string_init_set_str(model->text, text); + model->text = furi_string_alloc_set(text); // Allocate and init Element WidgetElement* gui_button = malloc(sizeof(WidgetElement)); diff --git a/applications/services/gui/modules/widget_elements/widget_element_string.c b/applications/services/gui/modules/widget_elements/widget_element_string.c index a03c2b6d..feb22ad1 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_string.c +++ b/applications/services/gui/modules/widget_elements/widget_element_string.c @@ -1,5 +1,4 @@ #include "widget_element_i.h" -#include typedef struct { uint8_t x; @@ -7,7 +6,7 @@ typedef struct { Align horizontal; Align vertical; Font font; - string_t text; + FuriString* text; } GuiStringModel; static void gui_string_draw(Canvas* canvas, WidgetElement* element) { @@ -15,7 +14,7 @@ static void gui_string_draw(Canvas* canvas, WidgetElement* element) { furi_assert(element); GuiStringModel* model = element->model; - if(string_size(model->text)) { + if(furi_string_size(model->text)) { canvas_set_font(canvas, model->font); canvas_draw_str_aligned( canvas, @@ -23,7 +22,7 @@ static void gui_string_draw(Canvas* canvas, WidgetElement* element) { model->y, model->horizontal, model->vertical, - string_get_cstr(model->text)); + furi_string_get_cstr(model->text)); } } @@ -31,7 +30,7 @@ static void gui_string_free(WidgetElement* gui_string) { furi_assert(gui_string); GuiStringModel* model = gui_string->model; - string_clear(model->text); + furi_string_free(model->text); free(gui_string->model); free(gui_string); } @@ -52,7 +51,7 @@ WidgetElement* widget_element_string_create( model->horizontal = horizontal; model->vertical = vertical; model->font = font; - string_init_set_str(model->text, text); + model->text = furi_string_alloc_set(text); // Allocate and init Element WidgetElement* gui_string = malloc(sizeof(WidgetElement)); diff --git a/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c b/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c index 01a70a0d..9ad2a1a8 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c +++ b/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c @@ -1,5 +1,4 @@ #include "widget_element_i.h" -#include #include typedef struct { @@ -8,7 +7,7 @@ typedef struct { Align horizontal; Align vertical; Font font; - string_t text; + FuriString* text; } GuiStringMultiLineModel; static void gui_string_multiline_draw(Canvas* canvas, WidgetElement* element) { @@ -16,7 +15,7 @@ static void gui_string_multiline_draw(Canvas* canvas, WidgetElement* element) { furi_assert(element); GuiStringMultiLineModel* model = element->model; - if(string_size(model->text)) { + if(furi_string_size(model->text)) { canvas_set_font(canvas, model->font); elements_multiline_text_aligned( canvas, @@ -24,7 +23,7 @@ static void gui_string_multiline_draw(Canvas* canvas, WidgetElement* element) { model->y, model->horizontal, model->vertical, - string_get_cstr(model->text)); + furi_string_get_cstr(model->text)); } } @@ -32,7 +31,7 @@ static void gui_string_multiline_free(WidgetElement* gui_string) { furi_assert(gui_string); GuiStringMultiLineModel* model = gui_string->model; - string_clear(model->text); + furi_string_free(model->text); free(gui_string->model); free(gui_string); } @@ -53,7 +52,7 @@ WidgetElement* widget_element_string_multiline_create( model->horizontal = horizontal; model->vertical = vertical; model->font = font; - string_init_set_str(model->text, text); + model->text = furi_string_alloc_set(text); // Allocate and init Element WidgetElement* gui_string = malloc(sizeof(WidgetElement)); diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_box.c b/applications/services/gui/modules/widget_elements/widget_element_text_box.c index 4750f8f8..2c694820 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_box.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_box.c @@ -1,5 +1,4 @@ #include "widget_element_i.h" -#include #include typedef struct { @@ -9,7 +8,7 @@ typedef struct { uint8_t height; Align horizontal; Align vertical; - string_t text; + FuriString* text; bool strip_to_dots; } GuiTextBoxModel; @@ -18,7 +17,7 @@ static void gui_text_box_draw(Canvas* canvas, WidgetElement* element) { furi_assert(element); GuiTextBoxModel* model = element->model; - if(string_size(model->text)) { + if(furi_string_size(model->text)) { elements_text_box( canvas, model->x, @@ -27,7 +26,7 @@ static void gui_text_box_draw(Canvas* canvas, WidgetElement* element) { model->height, model->horizontal, model->vertical, - string_get_cstr(model->text), + furi_string_get_cstr(model->text), model->strip_to_dots); } } @@ -36,7 +35,7 @@ static void gui_text_box_free(WidgetElement* gui_string) { furi_assert(gui_string); GuiTextBoxModel* model = gui_string->model; - string_clear(model->text); + furi_string_free(model->text); free(gui_string->model); free(gui_string); } @@ -60,7 +59,7 @@ WidgetElement* widget_element_text_box_create( model->height = height; model->horizontal = horizontal; model->vertical = vertical; - string_init_set_str(model->text, text); + model->text = furi_string_alloc_set(text); model->strip_to_dots = strip_to_dots; // Allocate and init Element diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c index 6682b106..a4d76638 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c @@ -1,5 +1,4 @@ #include "widget_element_i.h" -#include #include #include @@ -8,7 +7,7 @@ typedef struct { Font font; Align horizontal; - string_t text; + FuriString* text; } TextScrollLineArray; ARRAY_DEF(TextScrollLineArray, TextScrollLineArray, M_POD_OPLIST) @@ -19,19 +18,19 @@ typedef struct { uint8_t y; uint8_t width; uint8_t height; - string_t text; + FuriString* text; uint8_t scroll_pos_total; uint8_t scroll_pos_current; bool text_formatted; } WidgetElementTextScrollModel; static bool - widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, string_t text) { + widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, FuriString* text) { bool processed = false; do { - if(string_get_char(text, 0) != '\e') break; - char ctrl_symbol = string_get_char(text, 1); + if(furi_string_get_char(text, 0) != '\e') break; + char ctrl_symbol = furi_string_get_char(text, 1); if(ctrl_symbol == 'c') { line->horizontal = AlignCenter; } else if(ctrl_symbol == 'r') { @@ -39,7 +38,7 @@ static bool } else if(ctrl_symbol == '#') { line->font = FontPrimary; } - string_right(text, 2); + furi_string_right(text, 2); processed = true; } while(false); @@ -51,7 +50,7 @@ void widget_element_text_scroll_add_line(WidgetElement* element, TextScrollLineA TextScrollLineArray new_line; new_line.font = line->font; new_line.horizontal = line->horizontal; - string_init_set(new_line.text, line->text); + new_line.text = furi_string_alloc_set(line->text); TextScrollLineArray_push_back(model->line_array, new_line); } @@ -59,7 +58,7 @@ static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* WidgetElementTextScrollModel* model = element->model; TextScrollLineArray line_tmp; bool all_text_processed = false; - string_init(line_tmp.text); + line_tmp.text = furi_string_alloc(); bool reached_new_line = true; uint16_t total_height = 0; @@ -68,7 +67,7 @@ static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* // Set default line properties line_tmp.font = FontSecondary; line_tmp.horizontal = AlignLeft; - string_reset(line_tmp.text); + furi_string_reset(line_tmp.text); // Process control symbols while(widget_element_text_scroll_process_ctrl_symbols(&line_tmp, model->text)) ; @@ -84,38 +83,38 @@ static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* uint8_t line_width = 0; uint16_t char_i = 0; while(true) { - char next_char = string_get_char(model->text, char_i++); + char next_char = furi_string_get_char(model->text, char_i++); if(next_char == '\0') { - string_push_back(line_tmp.text, '\0'); + furi_string_push_back(line_tmp.text, '\0'); widget_element_text_scroll_add_line(element, &line_tmp); total_height += params->leading_default - params->height; all_text_processed = true; break; } else if(next_char == '\n') { - string_push_back(line_tmp.text, '\0'); + furi_string_push_back(line_tmp.text, '\0'); widget_element_text_scroll_add_line(element, &line_tmp); - string_right(model->text, char_i); + furi_string_right(model->text, char_i); total_height += params->leading_default - params->height; reached_new_line = true; break; } else { line_width += canvas_glyph_width(canvas, next_char); if(line_width > model->width) { - string_push_back(line_tmp.text, '\0'); + furi_string_push_back(line_tmp.text, '\0'); widget_element_text_scroll_add_line(element, &line_tmp); - string_right(model->text, char_i - 1); - string_reset(line_tmp.text); + furi_string_right(model->text, char_i - 1); + furi_string_reset(line_tmp.text); total_height += params->leading_default - params->height; reached_new_line = false; break; } else { - string_push_back(line_tmp.text, next_char); + furi_string_push_back(line_tmp.text, next_char); } } } } - string_clear(line_tmp.text); + furi_string_free(line_tmp.text); } static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* element) { @@ -150,7 +149,7 @@ static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* eleme x = model->x + model->width; } canvas_draw_str_aligned( - canvas, x, y, line->horizontal, AlignTop, string_get_cstr(line->text)); + canvas, x, y, line->horizontal, AlignTop, furi_string_get_cstr(line->text)); y += params->leading_default; } // Draw scroll bar @@ -205,10 +204,10 @@ static void widget_element_text_scroll_free(WidgetElement* text_scroll) { for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it); TextScrollLineArray_next(it)) { TextScrollLineArray* line = TextScrollLineArray_ref(it); - string_clear(line->text); + furi_string_free(line->text); } TextScrollLineArray_clear(model->line_array); - string_clear(model->text); + furi_string_free(model->text); free(text_scroll->model); furi_mutex_free(text_scroll->model_mutex); free(text_scroll); @@ -231,7 +230,7 @@ WidgetElement* widget_element_text_scroll_create( model->scroll_pos_current = 0; model->scroll_pos_total = 1; TextScrollLineArray_init(model->line_array); - string_init_set_str(model->text, text); + model->text = furi_string_alloc_set(text); WidgetElement* text_scroll = malloc(sizeof(WidgetElement)); text_scroll->parent = NULL; diff --git a/applications/services/gui/view.h b/applications/services/gui/view.h index 5b4bf360..b40f8ded 100644 --- a/applications/services/gui/view.h +++ b/applications/services/gui/view.h @@ -211,25 +211,25 @@ void view_commit_model(View* view, bool update); #endif #ifdef __cplusplus -#define with_view_model_cpp(view, type, var, function_body) \ +#define with_view_model_cpp(view, type, var, code, update) \ { \ - type* p = static_cast(view_get_model(view)); \ - bool update = [&](type * var) function_body(p); \ + type var = static_cast(view_get_model(view)); \ + {code}; \ view_commit_model(view, update); \ } #else /** With clause for view model * * @param view View instance pointer - * @param function_body a (){} lambda declaration, executed within you - * parent function context + * @param type View model type + * @param code Code block that will be executed between model lock and unlock + * @param update Bool flag, if true, view will be updated after code block. Can be variable, so code block can decide if update is needed. * - * @return true if you want to emit view update, false otherwise */ -#define with_view_model(view, function_body) \ - { \ - void* p = view_get_model(view); \ - bool update = ({ bool __fn__ function_body __fn__; })(p); \ - view_commit_model(view, update); \ +#define with_view_model(view, type, code, update) \ + { \ + type = view_get_model(view); \ + {code}; \ + view_commit_model(view, update); \ } #endif diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 307206c1..6e4ce836 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -246,7 +246,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e "non-complementary input, discarding key: %s, type: %s, sequence: %p", input_get_key_name(event->key), input_get_type_name(event->type), - event->sequence); + (void*)event->sequence); return; } @@ -286,7 +286,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e view_dispatcher->current_view, input_get_key_name(event->key), input_get_type_name(event->type), - event->sequence); + (void*)event->sequence); view_input(view_dispatcher->ongoing_input_view, event); } } diff --git a/applications/services/input/input_cli.c b/applications/services/input/input_cli.c index 037ac53e..d9a8eaeb 100644 --- a/applications/services/input/input_cli.c +++ b/applications/services/input/input_cli.c @@ -19,7 +19,7 @@ static void input_cli_dump_events_callback(const void* value, void* ctx) { furi_message_queue_put(input_queue, value, FuriWaitForever); } -static void input_cli_dump(Cli* cli, string_t args, Input* input) { +static void input_cli_dump(Cli* cli, FuriString* args, Input* input) { UNUSED(args); FuriMessageQueue* input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); FuriPubSubSubscription* input_subscription = @@ -47,11 +47,11 @@ static void input_cli_send_print_usage() { printf("\t\t \t - one of 'press', 'release', 'short', 'long'\r\n"); } -static void input_cli_send(Cli* cli, string_t args, Input* input) { +static void input_cli_send(Cli* cli, FuriString* args, Input* input) { UNUSED(cli); InputEvent event; - string_t key_str; - string_init(key_str); + FuriString* key_str; + key_str = furi_string_alloc(); bool parsed = false; do { @@ -59,29 +59,29 @@ static void input_cli_send(Cli* cli, string_t args, Input* input) { if(!args_read_string_and_trim(args, key_str)) { break; } - if(!string_cmp(key_str, "up")) { + if(!furi_string_cmp(key_str, "up")) { event.key = InputKeyUp; - } else if(!string_cmp(key_str, "down")) { + } else if(!furi_string_cmp(key_str, "down")) { event.key = InputKeyDown; - } else if(!string_cmp(key_str, "left")) { + } else if(!furi_string_cmp(key_str, "left")) { event.key = InputKeyLeft; - } else if(!string_cmp(key_str, "right")) { + } else if(!furi_string_cmp(key_str, "right")) { event.key = InputKeyRight; - } else if(!string_cmp(key_str, "ok")) { + } else if(!furi_string_cmp(key_str, "ok")) { event.key = InputKeyOk; - } else if(!string_cmp(key_str, "back")) { + } else if(!furi_string_cmp(key_str, "back")) { event.key = InputKeyBack; } else { break; } // Parse Type - if(!string_cmp(args, "press")) { + if(!furi_string_cmp(args, "press")) { event.type = InputTypePress; - } else if(!string_cmp(args, "release")) { + } else if(!furi_string_cmp(args, "release")) { event.type = InputTypeRelease; - } else if(!string_cmp(args, "short")) { + } else if(!furi_string_cmp(args, "short")) { event.type = InputTypeShort; - } else if(!string_cmp(args, "long")) { + } else if(!furi_string_cmp(args, "long")) { event.type = InputTypeLong; } else { break; @@ -94,26 +94,26 @@ static void input_cli_send(Cli* cli, string_t args, Input* input) { } else { input_cli_send_print_usage(); } - string_clear(key_str); + furi_string_free(key_str); } -void input_cli(Cli* cli, string_t args, void* context) { +void input_cli(Cli* cli, FuriString* args, void* context) { furi_assert(cli); furi_assert(context); Input* input = context; - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { input_cli_usage(); break; } - if(string_cmp_str(cmd, "dump") == 0) { + if(furi_string_cmp_str(cmd, "dump") == 0) { input_cli_dump(cli, args, input); break; } - if(string_cmp_str(cmd, "send") == 0) { + if(furi_string_cmp_str(cmd, "send") == 0) { input_cli_send(cli, args, input); break; } @@ -121,5 +121,5 @@ void input_cli(Cli* cli, string_t args, void* context) { input_cli_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } diff --git a/applications/services/input/input_i.h b/applications/services/input/input_i.h index f709e048..14d8b073 100644 --- a/applications/services/input/input_i.h +++ b/applications/services/input/input_i.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) @@ -46,4 +45,4 @@ void input_press_timer_callback(void* arg); void input_isr(void* _ctx); /** Input CLI command handler */ -void input_cli(Cli* cli, string_t args, void* context); +void input_cli(Cli* cli, FuriString* args, void* context); diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index cf7e5a10..bc456536 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -61,6 +61,7 @@ static void loader_cli_print_usage() { printf("Cmd list:\r\n"); printf("\tlist\t - List available applications\r\n"); printf("\topen \t - Open application by name\r\n"); + printf("\tinfo\t - Show loader state\r\n"); } static FlipperApplication const* loader_find_application_by_name_in_list( @@ -98,15 +99,20 @@ const FlipperApplication* loader_find_application_by_name(const char* name) { return application; } -void loader_cli_open(Cli* cli, string_t args, Loader* instance) { +static void loader_cli_open(Cli* cli, FuriString* args, Loader* instance) { UNUSED(cli); if(loader_is_locked(instance)) { - printf("Can't start, furi application is running"); + if(instance->application) { + furi_assert(instance->application->name); + printf("Can't start, %s application is running", instance->application->name); + } else { + printf("Can't start, furi application is running"); + } return; } - string_t application_name; - string_init(application_name); + FuriString* application_name; + application_name = furi_string_alloc(); do { if(!args_read_probably_quoted_string_and_trim(args, application_name)) { @@ -115,14 +121,14 @@ void loader_cli_open(Cli* cli, string_t args, Loader* instance) { } const FlipperApplication* application = - loader_find_application_by_name(string_get_cstr(application_name)); + loader_find_application_by_name(furi_string_get_cstr(application_name)); if(!application) { - printf("%s doesn't exists\r\n", string_get_cstr(application_name)); + printf("%s doesn't exists\r\n", furi_string_get_cstr(application_name)); break; } - string_strim(args); - if(!loader_start_application(application, string_get_cstr(args))) { + furi_string_trim(args); + if(!loader_start_application(application, furi_string_get_cstr(args))) { printf("Can't start, furi application is running"); return; } else { @@ -134,10 +140,10 @@ void loader_cli_open(Cli* cli, string_t args, Loader* instance) { } } while(false); - string_clear(application_name); + furi_string_free(application_name); } -void loader_cli_list(Cli* cli, string_t args, Loader* instance) { +static void loader_cli_list(Cli* cli, FuriString* args, Loader* instance) { UNUSED(cli); UNUSED(args); UNUSED(instance); @@ -159,12 +165,28 @@ void loader_cli_list(Cli* cli, string_t args, Loader* instance) { } } -static void loader_cli(Cli* cli, string_t args, void* _ctx) { +static void loader_cli_info(Cli* cli, FuriString* args, Loader* instance) { + UNUSED(cli); + UNUSED(args); + if(!loader_is_locked(instance)) { + printf("No application is running\r\n"); + } else { + printf("Running application: "); + if(instance->application) { + furi_assert(instance->application->name); + printf("%s\r\n", instance->application->name); + } else { + printf("unknown\r\n"); + } + } +} + +static void loader_cli(Cli* cli, FuriString* args, void* _ctx) { furi_assert(_ctx); Loader* instance = _ctx; - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -172,20 +194,25 @@ static void loader_cli(Cli* cli, string_t args, void* _ctx) { break; } - if(string_cmp_str(cmd, "list") == 0) { + if(furi_string_cmp_str(cmd, "list") == 0) { loader_cli_list(cli, args, instance); break; } - if(string_cmp_str(cmd, "open") == 0) { + if(furi_string_cmp_str(cmd, "open") == 0) { loader_cli_open(cli, args, instance); break; } + if(furi_string_cmp_str(cmd, "info") == 0) { + loader_cli_info(cli, args, instance); + break; + } + loader_cli_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } LoaderStatus loader_start(Loader* instance, const char* name, const char* args) { diff --git a/applications/services/power/power_cli.c b/applications/services/power/power_cli.c index 6af39631..5c28137e 100644 --- a/applications/services/power/power_cli.c +++ b/applications/services/power/power_cli.c @@ -5,7 +5,7 @@ #include #include -void power_cli_off(Cli* cli, string_t args) { +void power_cli_off(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); Power* power = furi_record_open(RECORD_POWER); @@ -14,13 +14,13 @@ void power_cli_off(Cli* cli, string_t args) { power_off(power); } -void power_cli_reboot(Cli* cli, string_t args) { +void power_cli_reboot(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); power_reboot(PowerBootModeNormal); } -void power_cli_reboot2dfu(Cli* cli, string_t args) { +void power_cli_reboot2dfu(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); power_reboot(PowerBootModeDfu); @@ -32,37 +32,37 @@ static void power_cli_info_callback(const char* key, const char* value, bool las printf("%-24s: %s\r\n", key, value); } -void power_cli_info(Cli* cli, string_t args) { +void power_cli_info(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); furi_hal_power_info_get(power_cli_info_callback, NULL); } -void power_cli_debug(Cli* cli, string_t args) { +void power_cli_debug(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); furi_hal_power_dump_state(); } -void power_cli_5v(Cli* cli, string_t args) { +void power_cli_5v(Cli* cli, FuriString* args) { UNUSED(cli); - if(!string_cmp(args, "0")) { + if(!furi_string_cmp(args, "0")) { furi_hal_power_disable_otg(); - } else if(!string_cmp(args, "1")) { + } else if(!furi_string_cmp(args, "1")) { furi_hal_power_enable_otg(); } else { - cli_print_usage("power_otg", "<1|0>", string_get_cstr(args)); + cli_print_usage("power_otg", "<1|0>", furi_string_get_cstr(args)); } } -void power_cli_3v3(Cli* cli, string_t args) { +void power_cli_3v3(Cli* cli, FuriString* args) { UNUSED(cli); - if(!string_cmp(args, "0")) { + if(!furi_string_cmp(args, "0")) { furi_hal_power_disable_external_3_3v(); - } else if(!string_cmp(args, "1")) { + } else if(!furi_string_cmp(args, "1")) { furi_hal_power_enable_external_3_3v(); } else { - cli_print_usage("power_ext", "<1|0>", string_get_cstr(args)); + cli_print_usage("power_ext", "<1|0>", furi_string_get_cstr(args)); } } @@ -82,10 +82,10 @@ static void power_cli_command_print_usage() { } } -void power_cli(Cli* cli, string_t args, void* context) { +void power_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); - string_t cmd; - string_init(cmd); + FuriString* cmd; + cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -93,38 +93,38 @@ void power_cli(Cli* cli, string_t args, void* context) { break; } - if(string_cmp_str(cmd, "off") == 0) { + if(furi_string_cmp_str(cmd, "off") == 0) { power_cli_off(cli, args); break; } - if(string_cmp_str(cmd, "reboot") == 0) { + if(furi_string_cmp_str(cmd, "reboot") == 0) { power_cli_reboot(cli, args); break; } - if(string_cmp_str(cmd, "reboot2dfu") == 0) { + if(furi_string_cmp_str(cmd, "reboot2dfu") == 0) { power_cli_reboot2dfu(cli, args); break; } - if(string_cmp_str(cmd, "info") == 0) { + if(furi_string_cmp_str(cmd, "info") == 0) { power_cli_info(cli, args); break; } - if(string_cmp_str(cmd, "debug") == 0) { + if(furi_string_cmp_str(cmd, "debug") == 0) { power_cli_debug(cli, args); break; } - if(string_cmp_str(cmd, "5v") == 0) { + if(furi_string_cmp_str(cmd, "5v") == 0) { power_cli_5v(cli, args); break; } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(string_cmp_str(cmd, "3v3") == 0) { + if(furi_string_cmp_str(cmd, "3v3") == 0) { power_cli_3v3(cli, args); break; } @@ -133,7 +133,7 @@ void power_cli(Cli* cli, string_t args, void* context) { power_cli_command_print_usage(); } while(false); - string_clear(cmd); + furi_string_free(cmd); } void power_on_system_start() { diff --git a/applications/services/power/power_service/views/power_off.c b/applications/services/power/power_service/views/power_off.c index 398ebe4a..b0046325 100644 --- a/applications/services/power/power_service/views/power_off.c +++ b/applications/services/power/power_service/views/power_off.c @@ -87,19 +87,13 @@ View* power_off_get_view(PowerOff* power_off) { void power_off_set_time_left(PowerOff* power_off, uint8_t time_left) { furi_assert(power_off); with_view_model( - power_off->view, (PowerOffModel * model) { - model->time_left_sec = time_left; - return true; - }); + power_off->view, PowerOffModel * model, { model->time_left_sec = time_left; }, true); } PowerOffResponse power_off_get_response(PowerOff* power_off) { furi_assert(power_off); PowerOffResponse response; with_view_model( - power_off->view, (PowerOffModel * model) { - response = model->response; - return false; - }); + power_off->view, PowerOffModel * model, { response = model->response; }, false); return response; } diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index abba6ea4..06c05173 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include #define TAG "RpcSrv" @@ -62,7 +60,7 @@ struct RpcSession { FuriThread* thread; RpcHandlerDict_t handlers; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; PB_Main* decoded_message; bool terminate; void** system_contexts; @@ -152,7 +150,7 @@ size_t furi_assert(encoded_bytes); furi_assert(size > 0); - size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout); + size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout); furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData); @@ -161,7 +159,7 @@ size_t size_t rpc_session_get_available_size(RpcSession* session) { furi_assert(session); - return xStreamBufferSpacesAvailable(session->stream); + return furi_stream_buffer_spaces_available(session->stream); } bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { @@ -175,9 +173,9 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { size_t bytes_received = 0; while(1) { - bytes_received += - xStreamBufferReceive(session->stream, buf + bytes_received, count - bytes_received, 0); - if(xStreamBufferIsEmpty(session->stream)) { + bytes_received += furi_stream_buffer_receive( + session->stream, buf + bytes_received, count - bytes_received, 0); + if(furi_stream_buffer_is_empty(session->stream)) { if(session->buffer_is_empty_callback) { session->buffer_is_empty_callback(session->context); } @@ -191,7 +189,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { } else { flags = furi_thread_flags_wait(RPC_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); if(flags & RpcEvtDisconnect) { - if(xStreamBufferIsEmpty(session->stream)) { + if(furi_stream_buffer_is_empty(session->stream)) { session->terminate = true; istream->bytes_left = 0; bytes_received = 0; @@ -280,7 +278,7 @@ static int32_t rpc_session_worker(void* context) { } if(message_decode_failed) { - xStreamBufferReset(session->stream); + furi_stream_buffer_reset(session->stream); if(!session->terminate) { /* Protobuf can't determine start and end of message. * Handle this by adding varint at beginning @@ -330,7 +328,7 @@ static void rpc_session_free_callback(FuriThreadState thread_state, void* contex free(session->system_contexts); free(session->decoded_message); RpcHandlerDict_clear(session->handlers); - vStreamBufferDelete(session->stream); + furi_stream_buffer_free(session->stream); furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever); if(session->terminated_callback) { @@ -349,7 +347,7 @@ RpcSession* rpc_session_open(Rpc* rpc) { RpcSession* session = malloc(sizeof(RpcSession)); session->callbacks_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - session->stream = xStreamBufferCreate(RPC_BUFFER_SIZE, 1); + session->stream = furi_stream_buffer_alloc(RPC_BUFFER_SIZE, 1); session->rpc = rpc; session->terminate = false; session->decode_error = false; diff --git a/applications/services/rpc/rpc_app.c b/applications/services/rpc/rpc_app.c index b8b34170..30105557 100644 --- a/applications/services/rpc/rpc_app.c +++ b/applications/services/rpc/rpc_app.c @@ -32,7 +32,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); - FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id); + FURI_LOG_D(TAG, "StartProcess: id %ld", request->command_id); PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START; @@ -63,7 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_record_close(RECORD_LOADER); - FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result); + FURI_LOG_D(TAG, "StartProcess: response id %ld, result %d", request->command_id, result); rpc_send_and_release_empty(session, request->command_id, result); } @@ -108,7 +108,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id); + FURI_LOG_D(TAG, "ExitRequest: id %ld", request->command_id); furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); rpc_app->last_id = request->command_id; @@ -116,7 +116,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + TAG, "ExitRequest: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -132,7 +132,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id); + FURI_LOG_D(TAG, "LoadFile: id %ld", request->command_id); furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); rpc_app->last_id = request->command_id; @@ -141,7 +141,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + TAG, "LoadFile: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -166,7 +166,7 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + TAG, "ButtonPress: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -190,7 +190,7 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context) } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + TAG, "ButtonRelease: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -243,7 +243,7 @@ void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool free(rpc_app->last_data); rpc_app->last_data = NULL; } - FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status); + FURI_LOG_D(TAG, "AppConfirm: event %d last_id %ld status %d", event, last_id, status); rpc_send_and_release_empty(session, last_id, status); break; default: diff --git a/applications/services/rpc/rpc_cli.c b/applications/services/rpc/rpc_cli.c index 8cb0f76a..82023e31 100644 --- a/applications/services/rpc/rpc_cli.c +++ b/applications/services/rpc/rpc_cli.c @@ -37,14 +37,14 @@ static void rpc_cli_session_terminated_callback(void* context) { furi_semaphore_release(cli_rpc->terminate_semaphore); } -void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) { +void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context) { UNUSED(args); furi_assert(cli); furi_assert(context); Rpc* rpc = context; uint32_t mem_before = memmgr_get_free_heap(); - FURI_LOG_D(TAG, "Free memory %d", mem_before); + FURI_LOG_D(TAG, "Free memory %ld", mem_before); furi_hal_usb_lock(); RpcSession* rpc_session = rpc_session_open(rpc); diff --git a/applications/services/rpc/rpc_debug.c b/applications/services/rpc/rpc_debug.c index 9c04bd89..8eb81dec 100644 --- a/applications/services/rpc/rpc_debug.c +++ b/applications/services/rpc/rpc_debug.c @@ -1,15 +1,14 @@ #include "rpc_i.h" -#include static size_t rpc_debug_print_file_msg( - string_t str, + FuriString* str, const char* prefix, const PB_Storage_File* msg_file, size_t msg_files_size) { size_t cnt = 0; for(size_t i = 0; i < msg_files_size; ++i, ++msg_file) { - string_cat_printf( + furi_string_cat_printf( str, "%s[%c] size: %5ld", prefix, @@ -17,11 +16,11 @@ static size_t rpc_debug_print_file_msg( msg_file->size); if(msg_file->name) { - string_cat_printf(str, " \'%s\'", msg_file->name); + furi_string_cat_printf(str, " \'%s\'", msg_file->name); } if(msg_file->data && msg_file->data->size) { - string_cat_printf( + furi_string_cat_printf( str, " (%d):\'%.*s%s\'", msg_file->data->size, @@ -30,42 +29,42 @@ static size_t rpc_debug_print_file_msg( msg_file->data->size > 30 ? "..." : ""); } - string_cat_printf(str, "\r\n"); + furi_string_cat_printf(str, "\r\n"); } return cnt; } void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size) { - string_t str; - string_init(str); - string_reserve(str, 100 + size * 5); + FuriString* str; + str = furi_string_alloc(); + furi_string_reserve(str, 100 + size * 5); - string_cat_printf(str, "\r\n%s DEC(%d): {", prefix, size); + furi_string_cat_printf(str, "\r\n%s DEC(%d): {", prefix, size); for(size_t i = 0; i < size; ++i) { - string_cat_printf(str, "%d, ", buffer[i]); + furi_string_cat_printf(str, "%d, ", buffer[i]); } - string_cat_printf(str, "}\r\n"); + furi_string_cat_printf(str, "}\r\n"); - printf("%s", string_get_cstr(str)); - string_reset(str); - string_reserve(str, 100 + size * 3); + printf("%s", furi_string_get_cstr(str)); + furi_string_reset(str); + furi_string_reserve(str, 100 + size * 3); - string_cat_printf(str, "%s HEX(%d): {", prefix, size); + furi_string_cat_printf(str, "%s HEX(%d): {", prefix, size); for(size_t i = 0; i < size; ++i) { - string_cat_printf(str, "%02X", buffer[i]); + furi_string_cat_printf(str, "%02X", buffer[i]); } - string_cat_printf(str, "}\r\n\r\n"); + furi_string_cat_printf(str, "}\r\n\r\n"); - printf("%s", string_get_cstr(str)); - string_clear(str); + printf("%s", furi_string_get_cstr(str)); + furi_string_free(str); } void rpc_debug_print_message(const PB_Main* message) { - string_t str; - string_init(str); + FuriString* str; + str = furi_string_alloc(); - string_cat_printf( + furi_string_cat_printf( str, "PB_Main: {\r\n\tresult: %d cmd_id: %ld (%s)\r\n", message->command_status, @@ -74,106 +73,106 @@ void rpc_debug_print_message(const PB_Main* message) { switch(message->which_content) { default: /* not implemented yet */ - string_cat_printf(str, "\tNOT_IMPLEMENTED (%d) {\r\n", message->which_content); + furi_string_cat_printf(str, "\tNOT_IMPLEMENTED (%d) {\r\n", message->which_content); break; case PB_Main_stop_session_tag: - string_cat_printf(str, "\tstop_session {\r\n"); + furi_string_cat_printf(str, "\tstop_session {\r\n"); break; case PB_Main_app_start_request_tag: { - string_cat_printf(str, "\tapp_start {\r\n"); + furi_string_cat_printf(str, "\tapp_start {\r\n"); const char* name = message->content.app_start_request.name; const char* args = message->content.app_start_request.args; if(name) { - string_cat_printf(str, "\t\tname: %s\r\n", name); + furi_string_cat_printf(str, "\t\tname: %s\r\n", name); } if(args) { - string_cat_printf(str, "\t\targs: %s\r\n", args); + furi_string_cat_printf(str, "\t\targs: %s\r\n", args); } break; } case PB_Main_app_lock_status_request_tag: { - string_cat_printf(str, "\tapp_lock_status_request {\r\n"); + furi_string_cat_printf(str, "\tapp_lock_status_request {\r\n"); break; } case PB_Main_app_lock_status_response_tag: { - string_cat_printf(str, "\tapp_lock_status_response {\r\n"); + furi_string_cat_printf(str, "\tapp_lock_status_response {\r\n"); bool lock_status = message->content.app_lock_status_response.locked; - string_cat_printf(str, "\t\tlocked: %s\r\n", lock_status ? "true" : "false"); + furi_string_cat_printf(str, "\t\tlocked: %s\r\n", lock_status ? "true" : "false"); break; } case PB_Main_storage_md5sum_request_tag: { - string_cat_printf(str, "\tmd5sum_request {\r\n"); + furi_string_cat_printf(str, "\tmd5sum_request {\r\n"); const char* path = message->content.storage_md5sum_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_storage_md5sum_response_tag: { - string_cat_printf(str, "\tmd5sum_response {\r\n"); + furi_string_cat_printf(str, "\tmd5sum_response {\r\n"); const char* path = message->content.storage_md5sum_response.md5sum; if(path) { - string_cat_printf(str, "\t\tmd5sum: %s\r\n", path); + furi_string_cat_printf(str, "\t\tmd5sum: %s\r\n", path); } break; } case PB_Main_system_ping_request_tag: - string_cat_printf(str, "\tping_request {\r\n"); + furi_string_cat_printf(str, "\tping_request {\r\n"); break; case PB_Main_system_ping_response_tag: - string_cat_printf(str, "\tping_response {\r\n"); + furi_string_cat_printf(str, "\tping_response {\r\n"); break; case PB_Main_system_device_info_request_tag: - string_cat_printf(str, "\tdevice_info_request {\r\n"); + furi_string_cat_printf(str, "\tdevice_info_request {\r\n"); break; case PB_Main_system_device_info_response_tag: - string_cat_printf(str, "\tdevice_info_response {\r\n"); - string_cat_printf( + furi_string_cat_printf(str, "\tdevice_info_response {\r\n"); + furi_string_cat_printf( str, "\t\t%s: %s\r\n", message->content.system_device_info_response.key, message->content.system_device_info_response.value); break; case PB_Main_storage_mkdir_request_tag: - string_cat_printf(str, "\tmkdir {\r\n"); + furi_string_cat_printf(str, "\tmkdir {\r\n"); break; case PB_Main_storage_delete_request_tag: { - string_cat_printf(str, "\tdelete {\r\n"); + furi_string_cat_printf(str, "\tdelete {\r\n"); const char* path = message->content.storage_delete_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_empty_tag: - string_cat_printf(str, "\tempty {\r\n"); + furi_string_cat_printf(str, "\tempty {\r\n"); break; case PB_Main_storage_info_request_tag: { - string_cat_printf(str, "\tinfo_request {\r\n"); + furi_string_cat_printf(str, "\tinfo_request {\r\n"); const char* path = message->content.storage_info_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_storage_info_response_tag: { - string_cat_printf(str, "\tinfo_response {\r\n"); - string_cat_printf( - str, "\t\ttotal_space: %lu\r\n", message->content.storage_info_response.total_space); - string_cat_printf( - str, "\t\tfree_space: %lu\r\n", message->content.storage_info_response.free_space); + furi_string_cat_printf(str, "\tinfo_response {\r\n"); + furi_string_cat_printf( + str, "\t\ttotal_space: %llu\r\n", message->content.storage_info_response.total_space); + furi_string_cat_printf( + str, "\t\tfree_space: %llu\r\n", message->content.storage_info_response.free_space); break; } case PB_Main_storage_stat_request_tag: { - string_cat_printf(str, "\tstat_request {\r\n"); + furi_string_cat_printf(str, "\tstat_request {\r\n"); const char* path = message->content.storage_stat_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_storage_stat_response_tag: { - string_cat_printf(str, "\tstat_response {\r\n"); + furi_string_cat_printf(str, "\tstat_response {\r\n"); if(message->content.storage_stat_response.has_file) { const PB_Storage_File* msg_file = &message->content.storage_stat_response.file; rpc_debug_print_file_msg(str, "\t\t\t", msg_file, 1); @@ -181,26 +180,26 @@ void rpc_debug_print_message(const PB_Main* message) { break; } case PB_Main_storage_list_request_tag: { - string_cat_printf(str, "\tlist_request {\r\n"); + furi_string_cat_printf(str, "\tlist_request {\r\n"); const char* path = message->content.storage_list_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_storage_read_request_tag: { - string_cat_printf(str, "\tread_request {\r\n"); + furi_string_cat_printf(str, "\tread_request {\r\n"); const char* path = message->content.storage_read_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } break; } case PB_Main_storage_write_request_tag: { - string_cat_printf(str, "\twrite_request {\r\n"); + furi_string_cat_printf(str, "\twrite_request {\r\n"); const char* path = message->content.storage_write_request.path; if(path) { - string_cat_printf(str, "\t\tpath: %s\r\n", path); + furi_string_cat_printf(str, "\t\tpath: %s\r\n", path); } if(message->content.storage_write_request.has_file) { const PB_Storage_File* msg_file = &message->content.storage_write_request.file; @@ -209,7 +208,7 @@ void rpc_debug_print_message(const PB_Main* message) { break; } case PB_Main_storage_read_response_tag: - string_cat_printf(str, "\tread_response {\r\n"); + furi_string_cat_printf(str, "\tread_response {\r\n"); if(message->content.storage_read_response.has_file) { const PB_Storage_File* msg_file = &message->content.storage_read_response.file; rpc_debug_print_file_msg(str, "\t\t\t", msg_file, 1); @@ -218,43 +217,43 @@ void rpc_debug_print_message(const PB_Main* message) { case PB_Main_storage_list_response_tag: { const PB_Storage_File* msg_file = message->content.storage_list_response.file; size_t msg_file_count = message->content.storage_list_response.file_count; - string_cat_printf(str, "\tlist_response {\r\n"); + furi_string_cat_printf(str, "\tlist_response {\r\n"); rpc_debug_print_file_msg(str, "\t\t", msg_file, msg_file_count); break; } case PB_Main_storage_rename_request_tag: { - string_cat_printf(str, "\trename_request {\r\n"); - string_cat_printf( + furi_string_cat_printf(str, "\trename_request {\r\n"); + furi_string_cat_printf( str, "\t\told_path: %s\r\n", message->content.storage_rename_request.old_path); - string_cat_printf( + furi_string_cat_printf( str, "\t\tnew_path: %s\r\n", message->content.storage_rename_request.new_path); break; } case PB_Main_gui_start_screen_stream_request_tag: - string_cat_printf(str, "\tstart_screen_stream {\r\n"); + furi_string_cat_printf(str, "\tstart_screen_stream {\r\n"); break; case PB_Main_gui_stop_screen_stream_request_tag: - string_cat_printf(str, "\tstop_screen_stream {\r\n"); + furi_string_cat_printf(str, "\tstop_screen_stream {\r\n"); break; case PB_Main_gui_screen_frame_tag: - string_cat_printf(str, "\tscreen_frame {\r\n"); + furi_string_cat_printf(str, "\tscreen_frame {\r\n"); break; case PB_Main_gui_send_input_event_request_tag: - string_cat_printf(str, "\tsend_input_event {\r\n"); - string_cat_printf( + furi_string_cat_printf(str, "\tsend_input_event {\r\n"); + furi_string_cat_printf( str, "\t\tkey: %d\r\n", message->content.gui_send_input_event_request.key); - string_cat_printf( + furi_string_cat_printf( str, "\t\type: %d\r\n", message->content.gui_send_input_event_request.type); break; case PB_Main_gui_start_virtual_display_request_tag: - string_cat_printf(str, "\tstart_virtual_display {\r\n"); + furi_string_cat_printf(str, "\tstart_virtual_display {\r\n"); break; case PB_Main_gui_stop_virtual_display_request_tag: - string_cat_printf(str, "\tstop_virtual_display {\r\n"); + furi_string_cat_printf(str, "\tstop_virtual_display {\r\n"); break; } - string_cat_printf(str, "\t}\r\n}\r\n"); - printf("%s", string_get_cstr(str)); + furi_string_cat_printf(str, "\t}\r\n}\r\n"); + printf("%s", furi_string_get_cstr(str)); - string_clear(str); + furi_string_free(str); } diff --git a/applications/services/rpc/rpc_i.h b/applications/services/rpc/rpc_i.h index 9ffd054a..af9033f0 100644 --- a/applications/services/rpc/rpc_i.h +++ b/applications/services/rpc/rpc_i.h @@ -38,6 +38,6 @@ void rpc_system_gpio_free(void* ctx); void rpc_debug_print_message(const PB_Main* message); void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size); -void rpc_cli_command_start_session(Cli* cli, string_t args, void* context); +void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context); PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error); diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index 1a7c9349..968b6904 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "filesystem_api_defines.h" #include "storage_sd_api.h" @@ -292,7 +291,7 @@ FS_Error storage_sd_status(Storage* api); /******************* Internal LFS Functions *******************/ -typedef void (*Storage_name_converter)(string_t); +typedef void (*Storage_name_converter)(FuriString*); /** Backs up internal storage to a tar archive * @param api pointer to the api @@ -350,7 +349,7 @@ void storage_get_next_filename( const char* dirname, const char* filename, const char* fileextension, - string_t nextfilename, + FuriString* nextfilename, uint8_t max_len); #ifdef __cplusplus diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index 802ebd54..880fb970 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -38,11 +38,11 @@ static void storage_cli_print_error(FS_Error error) { printf("Storage error: %s\r\n", storage_error_get_desc(error)); } -static void storage_cli_info(Cli* cli, string_t path) { +static void storage_cli_info(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - if(string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { + if(furi_string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { uint64_t total_space; uint64_t free_space; FS_Error error = @@ -52,12 +52,12 @@ static void storage_cli_info(Cli* cli, string_t path) { storage_cli_print_error(error); } else { printf( - "Label: %s\r\nType: LittleFS\r\n%luKB total\r\n%luKB free\r\n", + "Label: %s\r\nType: LittleFS\r\n%luKiB total\r\n%luKiB free\r\n", furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown", (uint32_t)(total_space / 1024), (uint32_t)(free_space / 1024)); } - } else if(string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { + } else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { SDInfo sd_info; FS_Error error = storage_sd_info(api, &sd_info); @@ -65,7 +65,7 @@ static void storage_cli_info(Cli* cli, string_t path) { storage_cli_print_error(error); } else { printf( - "Label: %s\r\nType: %s\r\n%luKB total\r\n%luKB free\r\n", + "Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n", sd_info.label, sd_api_get_fs_type_text(sd_info.fs_type), sd_info.kb_total, @@ -78,10 +78,10 @@ static void storage_cli_info(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); }; -static void storage_cli_format(Cli* cli, string_t path) { - if(string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { +static void storage_cli_format(Cli* cli, FuriString* path) { + if(furi_string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { storage_cli_print_error(FSE_NOT_IMPLEMENTED); - } else if(string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { + } else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { printf("Formatting SD card, All data will be lost! Are you sure (y/n)?\r\n"); char answer = cli_getc(cli); if(answer == 'y' || answer == 'Y') { @@ -104,9 +104,9 @@ static void storage_cli_format(Cli* cli, string_t path) { } }; -static void storage_cli_list(Cli* cli, string_t path) { +static void storage_cli_list(Cli* cli, FuriString* path) { UNUSED(cli); - if(string_cmp_str(path, "/") == 0) { + if(furi_string_cmp_str(path, "/") == 0) { printf("\t[D] int\r\n"); printf("\t[D] ext\r\n"); printf("\t[D] any\r\n"); @@ -114,7 +114,7 @@ static void storage_cli_list(Cli* cli, string_t path) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); - if(storage_dir_open(file, string_get_cstr(path))) { + if(storage_dir_open(file, furi_string_get_cstr(path))) { FileInfo fileinfo; char name[MAX_NAME_LENGTH]; bool read_done = false; @@ -141,28 +141,31 @@ static void storage_cli_list(Cli* cli, string_t path) { } } -static void storage_cli_tree(Cli* cli, string_t path) { - if(string_cmp_str(path, "/") == 0) { - string_set(path, STORAGE_INT_PATH_PREFIX); +static void storage_cli_tree(Cli* cli, FuriString* path) { + if(furi_string_cmp_str(path, "/") == 0) { + furi_string_set(path, STORAGE_INT_PATH_PREFIX); storage_cli_tree(cli, path); - string_set(path, STORAGE_EXT_PATH_PREFIX); + furi_string_set(path, STORAGE_EXT_PATH_PREFIX); storage_cli_tree(cli, path); } else { Storage* api = furi_record_open(RECORD_STORAGE); DirWalk* dir_walk = dir_walk_alloc(api); - string_t name; - string_init(name); + FuriString* name; + name = furi_string_alloc(); - if(dir_walk_open(dir_walk, string_get_cstr(path))) { + if(dir_walk_open(dir_walk, furi_string_get_cstr(path))) { FileInfo fileinfo; bool read_done = false; while(dir_walk_read(dir_walk, name, &fileinfo) == DirWalkOK) { read_done = true; if(fileinfo.flags & FSF_DIRECTORY) { - printf("\t[D] %s\r\n", string_get_cstr(name)); + printf("\t[D] %s\r\n", furi_string_get_cstr(name)); } else { - printf("\t[F] %s %lub\r\n", string_get_cstr(name), (uint32_t)(fileinfo.size)); + printf( + "\t[F] %s %lub\r\n", + furi_string_get_cstr(name), + (uint32_t)(fileinfo.size)); } } @@ -173,18 +176,18 @@ static void storage_cli_tree(Cli* cli, string_t path) { storage_cli_print_error(dir_walk_get_error(dir_walk)); } - string_clear(name); + furi_string_free(name); dir_walk_free(dir_walk); furi_record_close(RECORD_STORAGE); } } -static void storage_cli_read(Cli* cli, string_t path) { +static void storage_cli_read(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); - if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { const uint16_t buffer_size = 128; uint16_t read_size = 0; uint8_t* data = malloc(buffer_size); @@ -210,14 +213,14 @@ static void storage_cli_read(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_write(Cli* cli, string_t path) { +static void storage_cli_write(Cli* cli, FuriString* path) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); const uint16_t buffer_size = 512; uint8_t* buffer = malloc(buffer_size); - if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { + if(storage_file_open(file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { printf("Just write your text data. New line by Ctrl+Enter, exit by Ctrl+C.\r\n"); uint32_t read_index = 0; @@ -264,16 +267,16 @@ static void storage_cli_write(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) { +static void storage_cli_read_chunks(Cli* cli, FuriString* path, FuriString* args) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); uint32_t buffer_size; - int parsed_count = sscanf(string_get_cstr(args), "%lu", &buffer_size); + int parsed_count = sscanf(furi_string_get_cstr(args), "%lu", &buffer_size); if(parsed_count == EOF || parsed_count != 1) { storage_cli_print_usage(); - } else if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + } else if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { uint64_t file_size = storage_file_size(file); printf("Size: %lu\r\n", (uint32_t)file_size); @@ -304,17 +307,17 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) { +static void storage_cli_write_chunk(Cli* cli, FuriString* path, FuriString* args) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); uint32_t buffer_size; - int parsed_count = sscanf(string_get_cstr(args), "%lu", &buffer_size); + int parsed_count = sscanf(furi_string_get_cstr(args), "%lu", &buffer_size); if(parsed_count == EOF || parsed_count != 1) { storage_cli_print_usage(); } else { - if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { + if(storage_file_open(file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { printf("Ready\r\n"); if(buffer_size) { @@ -342,32 +345,32 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_stat(Cli* cli, string_t path) { +static void storage_cli_stat(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - if(string_cmp_str(path, "/") == 0) { + if(furi_string_cmp_str(path, "/") == 0) { printf("Storage\r\n"); } else if( - string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0 || - string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0 || - string_cmp_str(path, STORAGE_ANY_PATH_PREFIX) == 0) { + furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0 || + furi_string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0 || + furi_string_cmp_str(path, STORAGE_ANY_PATH_PREFIX) == 0) { uint64_t total_space; uint64_t free_space; FS_Error error = - storage_common_fs_info(api, string_get_cstr(path), &total_space, &free_space); + storage_common_fs_info(api, furi_string_get_cstr(path), &total_space, &free_space); if(error != FSE_OK) { storage_cli_print_error(error); } else { printf( - "Storage, %luKB total, %luKB free\r\n", + "Storage, %luKiB total, %luKiB free\r\n", (uint32_t)(total_space / 1024), (uint32_t)(free_space / 1024)); } } else { FileInfo fileinfo; - FS_Error error = storage_common_stat(api, string_get_cstr(path), &fileinfo); + FS_Error error = storage_common_stat(api, furi_string_get_cstr(path), &fileinfo); if(error == FSE_OK) { if(fileinfo.flags & FSF_DIRECTORY) { @@ -383,31 +386,31 @@ static void storage_cli_stat(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_copy(Cli* cli, string_t old_path, string_t args) { +static void storage_cli_copy(Cli* cli, FuriString* old_path, FuriString* args) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - string_t new_path; - string_init(new_path); + FuriString* new_path; + new_path = furi_string_alloc(); if(!args_read_probably_quoted_string_and_trim(args, new_path)) { storage_cli_print_usage(); } else { - FS_Error error = - storage_common_copy(api, string_get_cstr(old_path), string_get_cstr(new_path)); + FS_Error error = storage_common_copy( + api, furi_string_get_cstr(old_path), furi_string_get_cstr(new_path)); if(error != FSE_OK) { storage_cli_print_error(error); } } - string_clear(new_path); + furi_string_free(new_path); furi_record_close(RECORD_STORAGE); } -static void storage_cli_remove(Cli* cli, string_t path) { +static void storage_cli_remove(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - FS_Error error = storage_common_remove(api, string_get_cstr(path)); + FS_Error error = storage_common_remove(api, furi_string_get_cstr(path)); if(error != FSE_OK) { storage_cli_print_error(error); @@ -416,31 +419,31 @@ static void storage_cli_remove(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_rename(Cli* cli, string_t old_path, string_t args) { +static void storage_cli_rename(Cli* cli, FuriString* old_path, FuriString* args) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - string_t new_path; - string_init(new_path); + FuriString* new_path; + new_path = furi_string_alloc(); if(!args_read_probably_quoted_string_and_trim(args, new_path)) { storage_cli_print_usage(); } else { - FS_Error error = - storage_common_rename(api, string_get_cstr(old_path), string_get_cstr(new_path)); + FS_Error error = storage_common_rename( + api, furi_string_get_cstr(old_path), furi_string_get_cstr(new_path)); if(error != FSE_OK) { storage_cli_print_error(error); } } - string_clear(new_path); + furi_string_free(new_path); furi_record_close(RECORD_STORAGE); } -static void storage_cli_mkdir(Cli* cli, string_t path) { +static void storage_cli_mkdir(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); - FS_Error error = storage_common_mkdir(api, string_get_cstr(path)); + FS_Error error = storage_common_mkdir(api, furi_string_get_cstr(path)); if(error != FSE_OK) { storage_cli_print_error(error); @@ -449,12 +452,12 @@ static void storage_cli_mkdir(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -static void storage_cli_md5(Cli* cli, string_t path) { +static void storage_cli_md5(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); - if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { const uint16_t buffer_size = 512; const uint8_t hash_size = 16; uint8_t* data = malloc(buffer_size); @@ -487,12 +490,12 @@ static void storage_cli_md5(Cli* cli, string_t path) { furi_record_close(RECORD_STORAGE); } -void storage_cli(Cli* cli, string_t args, void* context) { +void storage_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); - string_t cmd; - string_t path; - string_init(cmd); - string_init(path); + FuriString* cmd; + FuriString* path; + cmd = furi_string_alloc(); + path = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { @@ -505,72 +508,72 @@ void storage_cli(Cli* cli, string_t args, void* context) { break; } - if(string_cmp_str(cmd, "info") == 0) { + if(furi_string_cmp_str(cmd, "info") == 0) { storage_cli_info(cli, path); break; } - if(string_cmp_str(cmd, "format") == 0) { + if(furi_string_cmp_str(cmd, "format") == 0) { storage_cli_format(cli, path); break; } - if(string_cmp_str(cmd, "list") == 0) { + if(furi_string_cmp_str(cmd, "list") == 0) { storage_cli_list(cli, path); break; } - if(string_cmp_str(cmd, "tree") == 0) { + if(furi_string_cmp_str(cmd, "tree") == 0) { storage_cli_tree(cli, path); break; } - if(string_cmp_str(cmd, "read") == 0) { + if(furi_string_cmp_str(cmd, "read") == 0) { storage_cli_read(cli, path); break; } - if(string_cmp_str(cmd, "read_chunks") == 0) { + if(furi_string_cmp_str(cmd, "read_chunks") == 0) { storage_cli_read_chunks(cli, path, args); break; } - if(string_cmp_str(cmd, "write") == 0) { + if(furi_string_cmp_str(cmd, "write") == 0) { storage_cli_write(cli, path); break; } - if(string_cmp_str(cmd, "write_chunk") == 0) { + if(furi_string_cmp_str(cmd, "write_chunk") == 0) { storage_cli_write_chunk(cli, path, args); break; } - if(string_cmp_str(cmd, "copy") == 0) { + if(furi_string_cmp_str(cmd, "copy") == 0) { storage_cli_copy(cli, path, args); break; } - if(string_cmp_str(cmd, "remove") == 0) { + if(furi_string_cmp_str(cmd, "remove") == 0) { storage_cli_remove(cli, path); break; } - if(string_cmp_str(cmd, "rename") == 0) { + if(furi_string_cmp_str(cmd, "rename") == 0) { storage_cli_rename(cli, path, args); break; } - if(string_cmp_str(cmd, "mkdir") == 0) { + if(furi_string_cmp_str(cmd, "mkdir") == 0) { storage_cli_mkdir(cli, path); break; } - if(string_cmp_str(cmd, "md5") == 0) { + if(furi_string_cmp_str(cmd, "md5") == 0) { storage_cli_md5(cli, path); break; } - if(string_cmp_str(cmd, "stat") == 0) { + if(furi_string_cmp_str(cmd, "stat") == 0) { storage_cli_stat(cli, path); break; } @@ -578,11 +581,11 @@ void storage_cli(Cli* cli, string_t args, void* context) { storage_cli_print_usage(); } while(false); - string_clear(path); - string_clear(cmd); + furi_string_free(path); + furi_string_free(cmd); } -static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) { +static void storage_cli_factory_reset(Cli* cli, FuriString* args, void* context) { UNUSED(args); UNUSED(context); printf("All data will be lost! Are you sure (y/n)?\r\n"); diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 80cafb28..c0c730fb 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -1,6 +1,5 @@ #include #include -#include #include "storage.h" #include "storage_i.h" #include "storage_message.h" @@ -120,7 +119,11 @@ bool storage_file_open( furi_event_flag_free(event); FURI_LOG_T( - TAG, "File %p - %p open (%s)", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE, path); + TAG, + "File %p - %p open (%s)", + (void*)((uint32_t)file - SRAM_BASE), + (void*)(file->file_id - SRAM_BASE), + path); return result; } @@ -133,7 +136,11 @@ bool storage_file_close(File* file) { S_API_MESSAGE(StorageCommandFileClose); S_API_EPILOGUE; - FURI_LOG_T(TAG, "File %p - %p closed", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE); + FURI_LOG_T( + TAG, + "File %p - %p closed", + (void*)((uint32_t)file - SRAM_BASE), + (void*)(file->file_id - SRAM_BASE)); file->type = FileTypeClosed; return S_RETURN_BOOL; @@ -292,7 +299,11 @@ bool storage_dir_open(File* file, const char* path) { furi_event_flag_free(event); FURI_LOG_T( - TAG, "Dir %p - %p open (%s)", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE, path); + TAG, + "Dir %p - %p open (%s)", + (void*)((uint32_t)file - SRAM_BASE), + (void*)(file->file_id - SRAM_BASE), + path); return result; } @@ -304,7 +315,11 @@ bool storage_dir_close(File* file) { S_API_MESSAGE(StorageCommandDirClose); S_API_EPILOGUE; - FURI_LOG_T(TAG, "Dir %p - %p closed", (uint32_t)file - SRAM_BASE, file->file_id - SRAM_BASE); + FURI_LOG_T( + TAG, + "Dir %p - %p closed", + (void*)((uint32_t)file - SRAM_BASE), + (void*)(file->file_id - SRAM_BASE)); file->type = FileTypeClosed; @@ -374,13 +389,13 @@ static FS_Error storage_copy_recursive(Storage* storage, const char* old_path, const char* new_path) { FS_Error error = storage_common_mkdir(storage, new_path); DirWalk* dir_walk = dir_walk_alloc(storage); - string_t path; - string_t tmp_new_path; - string_t tmp_old_path; + FuriString* path; + FuriString* tmp_new_path; + FuriString* tmp_old_path; FileInfo fileinfo; - string_init(path); - string_init(tmp_new_path); - string_init(tmp_old_path); + path = furi_string_alloc(); + tmp_new_path = furi_string_alloc(); + tmp_old_path = furi_string_alloc(); do { if(error != FSE_OK) break; @@ -399,15 +414,17 @@ static FS_Error } else if(res == DirWalkLast) { break; } else { - string_set(tmp_old_path, path); - string_right(path, strlen(old_path)); - string_printf(tmp_new_path, "%s%s", new_path, string_get_cstr(path)); + furi_string_set(tmp_old_path, path); + furi_string_right(path, strlen(old_path)); + furi_string_printf(tmp_new_path, "%s%s", new_path, furi_string_get_cstr(path)); if(fileinfo.flags & FSF_DIRECTORY) { - error = storage_common_mkdir(storage, string_get_cstr(tmp_new_path)); + error = storage_common_mkdir(storage, furi_string_get_cstr(tmp_new_path)); } else { error = storage_common_copy( - storage, string_get_cstr(tmp_old_path), string_get_cstr(tmp_new_path)); + storage, + furi_string_get_cstr(tmp_old_path), + furi_string_get_cstr(tmp_new_path)); } if(error != FSE_OK) break; @@ -416,9 +433,9 @@ static FS_Error } while(false); - string_clear(tmp_new_path); - string_clear(tmp_old_path); - string_clear(path); + furi_string_free(tmp_new_path); + furi_string_free(tmp_old_path); + furi_string_free(path); dir_walk_free(dir_walk); return error; } @@ -459,11 +476,11 @@ static FS_Error storage_merge_recursive(Storage* storage, const char* old_path, const char* new_path) { FS_Error error = storage_common_mkdir(storage, new_path); DirWalk* dir_walk = dir_walk_alloc(storage); - string_t path, file_basename, tmp_new_path; + FuriString *path, *file_basename, *tmp_new_path; FileInfo fileinfo; - string_init(path); - string_init(file_basename); - string_init(tmp_new_path); + path = furi_string_alloc(); + file_basename = furi_string_alloc(); + tmp_new_path = furi_string_alloc(); do { if((error != FSE_OK) && (error != FSE_EXIST)) break; @@ -483,14 +500,15 @@ static FS_Error } else if(res == DirWalkLast) { break; } else { - path_extract_basename(string_get_cstr(path), file_basename); - path_concat(new_path, string_get_cstr(file_basename), tmp_new_path); + path_extract_basename(furi_string_get_cstr(path), file_basename); + path_concat(new_path, furi_string_get_cstr(file_basename), tmp_new_path); if(fileinfo.flags & FSF_DIRECTORY) { - if(storage_common_stat(storage, string_get_cstr(tmp_new_path), &fileinfo) == - FSE_OK) { + if(storage_common_stat( + storage, furi_string_get_cstr(tmp_new_path), &fileinfo) == FSE_OK) { if(fileinfo.flags & FSF_DIRECTORY) { - error = storage_common_mkdir(storage, string_get_cstr(tmp_new_path)); + error = + storage_common_mkdir(storage, furi_string_get_cstr(tmp_new_path)); if(error != FSE_OK) { break; } @@ -498,7 +516,7 @@ static FS_Error } } error = storage_common_merge( - storage, string_get_cstr(path), string_get_cstr(tmp_new_path)); + storage, furi_string_get_cstr(path), furi_string_get_cstr(tmp_new_path)); if(error != FSE_OK) { break; @@ -508,9 +526,9 @@ static FS_Error } while(false); - string_clear(tmp_new_path); - string_clear(file_basename); - string_clear(path); + furi_string_free(tmp_new_path); + furi_string_free(file_basename); + furi_string_free(path); dir_walk_free(dir_walk); return error; } @@ -518,8 +536,8 @@ static FS_Error FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path) { FS_Error error; const char* new_path_tmp; - string_t new_path_next; - string_init(new_path_next); + FuriString* new_path_next; + new_path_next = furi_string_alloc(); FileInfo fileinfo; error = storage_common_stat(storage, old_path, &fileinfo); @@ -530,13 +548,13 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char } else { error = storage_common_stat(storage, new_path, &fileinfo); if(error == FSE_OK) { - string_set_str(new_path_next, new_path); - string_t dir_path; - string_t filename; + furi_string_set(new_path_next, new_path); + FuriString* dir_path; + FuriString* filename; char extension[MAX_EXT_LEN]; - string_init(dir_path); - string_init(filename); + dir_path = furi_string_alloc(); + filename = furi_string_alloc(); path_extract_filename(new_path_next, filename, true); path_extract_dirname(new_path, dir_path); @@ -544,17 +562,18 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char storage_get_next_filename( storage, - string_get_cstr(dir_path), - string_get_cstr(filename), + furi_string_get_cstr(dir_path), + furi_string_get_cstr(filename), extension, new_path_next, 255); - string_cat_printf(dir_path, "/%s%s", string_get_cstr(new_path_next), extension); - string_set(new_path_next, dir_path); + furi_string_cat_printf( + dir_path, "/%s%s", furi_string_get_cstr(new_path_next), extension); + furi_string_set(new_path_next, dir_path); - string_clear(dir_path); - string_clear(filename); - new_path_tmp = string_get_cstr(new_path_next); + furi_string_free(dir_path); + furi_string_free(filename); + new_path_tmp = furi_string_get_cstr(new_path_next); } else { new_path_tmp = new_path; } @@ -577,7 +596,7 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char } } - string_clear(new_path_next); + furi_string_free(new_path_next); return error; } @@ -672,7 +691,7 @@ File* storage_file_alloc(Storage* storage) { file->type = FileTypeClosed; file->storage = storage; - FURI_LOG_T(TAG, "File/Dir %p alloc", (uint32_t)file - SRAM_BASE); + FURI_LOG_T(TAG, "File/Dir %p alloc", (void*)((uint32_t)file - SRAM_BASE)); return file; } @@ -694,7 +713,7 @@ void storage_file_free(File* file) { } } - FURI_LOG_T(TAG, "File/Dir %p free", (uint32_t)file - SRAM_BASE); + FURI_LOG_T(TAG, "File/Dir %p free", (void*)((uint32_t)file - SRAM_BASE)); free(file); } @@ -707,8 +726,8 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { furi_assert(path); FileInfo fileinfo; bool result = false; - string_t fullname; - string_t cur_dir; + FuriString* fullname; + FuriString* cur_dir; if(storage_simply_remove(storage, path)) { return true; @@ -716,26 +735,26 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { char* name = malloc(MAX_NAME_LENGTH + 1); File* dir = storage_file_alloc(storage); - string_init_set_str(cur_dir, path); + cur_dir = furi_string_alloc_set(path); bool go_deeper = false; while(1) { - if(!storage_dir_open(dir, string_get_cstr(cur_dir))) { + if(!storage_dir_open(dir, furi_string_get_cstr(cur_dir))) { storage_dir_close(dir); break; } while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { if(fileinfo.flags & FSF_DIRECTORY) { - string_cat_printf(cur_dir, "/%s", name); + furi_string_cat_printf(cur_dir, "/%s", name); go_deeper = true; break; } - string_init_printf(fullname, "%s/%s", string_get_cstr(cur_dir), name); - FS_Error error = storage_common_remove(storage, string_get_cstr(fullname)); + fullname = furi_string_alloc_printf("%s/%s", furi_string_get_cstr(cur_dir), name); + FS_Error error = storage_common_remove(storage, furi_string_get_cstr(fullname)); furi_check(error == FSE_OK); - string_clear(fullname); + furi_string_free(fullname); } storage_dir_close(dir); @@ -744,13 +763,13 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { continue; } - FS_Error error = storage_common_remove(storage, string_get_cstr(cur_dir)); + FS_Error error = storage_common_remove(storage, furi_string_get_cstr(cur_dir)); furi_check(error == FSE_OK); - if(string_cmp(cur_dir, path)) { - size_t last_char = string_search_rchar(cur_dir, '/'); - furi_assert(last_char != STRING_FAILURE); - string_left(cur_dir, last_char); + if(furi_string_cmp(cur_dir, path)) { + size_t last_char = furi_string_search_rchar(cur_dir, '/'); + furi_assert(last_char != FURI_STRING_FAILURE); + furi_string_left(cur_dir, last_char); } else { result = true; break; @@ -758,7 +777,7 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { } storage_file_free(dir); - string_clear(cur_dir); + furi_string_free(cur_dir); free(name); return result; } @@ -780,22 +799,22 @@ void storage_get_next_filename( const char* dirname, const char* filename, const char* fileextension, - string_t nextfilename, + FuriString* nextfilename, uint8_t max_len) { - string_t temp_str; + FuriString* temp_str; uint16_t num = 0; - string_init_printf(temp_str, "%s/%s%s", dirname, filename, fileextension); + temp_str = furi_string_alloc_printf("%s/%s%s", dirname, filename, fileextension); - while(storage_common_stat(storage, string_get_cstr(temp_str), NULL) == FSE_OK) { + while(storage_common_stat(storage, furi_string_get_cstr(temp_str), NULL) == FSE_OK) { num++; - string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension); + furi_string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension); } if(num && (max_len > strlen(filename))) { - string_printf(nextfilename, "%s%d", filename, num); + furi_string_printf(nextfilename, "%s%d", filename, num); } else { - string_printf(nextfilename, "%s", filename); + furi_string_printf(nextfilename, "%s", filename); } - string_clear(temp_str); + furi_string_free(temp_str); } diff --git a/applications/services/storage/storage_glue.c b/applications/services/storage/storage_glue.c index d9d599c5..c5682f67 100644 --- a/applications/services/storage/storage_glue.c +++ b/applications/services/storage/storage_glue.c @@ -7,25 +7,25 @@ void storage_file_init(StorageFile* obj) { obj->file = NULL; obj->type = ST_ERROR; obj->file_data = NULL; - string_init(obj->path); + obj->path = furi_string_alloc(); } void storage_file_init_set(StorageFile* obj, const StorageFile* src) { obj->file = src->file; obj->type = src->type; obj->file_data = src->file_data; - string_init_set(obj->path, src->path); + obj->path = furi_string_alloc_set(src->path); } void storage_file_set(StorageFile* obj, const StorageFile* src) { obj->file = src->file; obj->type = src->type; obj->file_data = src->file_data; - string_set(obj->path, src->path); + furi_string_set(obj->path, src->path); } void storage_file_clear(StorageFile* obj) { - string_clear(obj->path); + furi_string_free(obj->path); } /****************** storage data ******************/ @@ -101,7 +101,7 @@ bool storage_has_file(const File* file, StorageData* storage_data) { return result; } -bool storage_path_already_open(string_t path, StorageFileList_t array) { +bool storage_path_already_open(FuriString* path, StorageFileList_t array) { bool open = false; StorageFileList_it_t it; @@ -109,7 +109,7 @@ bool storage_path_already_open(string_t path, StorageFileList_t array) { for(StorageFileList_it(it, array); !StorageFileList_end_p(it); StorageFileList_next(it)) { const StorageFile* storage_file = StorageFileList_cref(it); - if(string_cmp(storage_file->path, path) == 0) { + if(furi_string_cmp(storage_file->path, path) == 0) { open = true; break; } @@ -158,14 +158,18 @@ void* storage_get_storage_file_data(const File* file, StorageData* storage) { return founded_file->file_data; } -void storage_push_storage_file(File* file, string_t path, StorageType type, StorageData* storage) { +void storage_push_storage_file( + File* file, + FuriString* path, + StorageType type, + StorageData* storage) { StorageFile* storage_file = StorageFileList_push_new(storage->files); furi_check(storage_file != NULL); file->file_id = (uint32_t)storage_file; storage_file->file = file; storage_file->type = type; - string_set(storage_file->path, path); + furi_string_set(storage_file->path, path); } bool storage_pop_storage_file(File* file, StorageData* storage) { diff --git a/applications/services/storage/storage_glue.h b/applications/services/storage/storage_glue.h index 7cf2e072..53fa0de1 100644 --- a/applications/services/storage/storage_glue.h +++ b/applications/services/storage/storage_glue.h @@ -2,7 +2,6 @@ #include #include "filesystem_api_internal.h" -#include #include #ifdef __cplusplus @@ -21,7 +20,7 @@ typedef struct { File* file; StorageType type; void* file_data; - string_t path; + FuriString* path; } StorageFile; typedef enum { @@ -62,12 +61,16 @@ struct StorageData { }; bool storage_has_file(const File* file, StorageData* storage_data); -bool storage_path_already_open(string_t path, StorageFileList_t files); +bool storage_path_already_open(FuriString* path, StorageFileList_t files); void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage); void* storage_get_storage_file_data(const File* file, StorageData* storage); -void storage_push_storage_file(File* file, string_t path, StorageType type, StorageData* storage); +void storage_push_storage_file( + File* file, + FuriString* path, + StorageType type, + StorageData* storage); bool storage_pop_storage_file(File* file, StorageData* storage); #ifdef __cplusplus diff --git a/applications/services/storage/storage_internal_api.c b/applications/services/storage/storage_internal_api.c index 620eae36..6d620b9c 100644 --- a/applications/services/storage/storage_internal_api.c +++ b/applications/services/storage/storage_internal_api.c @@ -1,5 +1,4 @@ #include -#include #include "storage.h" #include diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index 46ca4e16..8643e974 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -1,7 +1,6 @@ #include "storage_processing.h" #include #include -#include #define FS_CALL(_storage, _fn) \ storage_data_lock(_storage); \ @@ -68,21 +67,22 @@ static StorageType storage_get_type_by_path(Storage* app, const char* path) { return type; } -static void storage_path_change_to_real_storage(string_t path, StorageType real_storage) { - if(memcmp(string_get_cstr(path), STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == +static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) { + if(memcmp( + furi_string_get_cstr(path), STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) { switch(real_storage) { case ST_EXT: - string_set_char(path, 0, STORAGE_EXT_PATH_PREFIX[0]); - string_set_char(path, 1, STORAGE_EXT_PATH_PREFIX[1]); - string_set_char(path, 2, STORAGE_EXT_PATH_PREFIX[2]); - string_set_char(path, 3, STORAGE_EXT_PATH_PREFIX[3]); + furi_string_set_char(path, 0, STORAGE_EXT_PATH_PREFIX[0]); + furi_string_set_char(path, 1, STORAGE_EXT_PATH_PREFIX[1]); + furi_string_set_char(path, 2, STORAGE_EXT_PATH_PREFIX[2]); + furi_string_set_char(path, 3, STORAGE_EXT_PATH_PREFIX[3]); break; case ST_INT: - string_set_char(path, 0, STORAGE_INT_PATH_PREFIX[0]); - string_set_char(path, 1, STORAGE_INT_PATH_PREFIX[1]); - string_set_char(path, 2, STORAGE_INT_PATH_PREFIX[2]); - string_set_char(path, 3, STORAGE_INT_PATH_PREFIX[3]); + furi_string_set_char(path, 0, STORAGE_INT_PATH_PREFIX[0]); + furi_string_set_char(path, 1, STORAGE_INT_PATH_PREFIX[1]); + furi_string_set_char(path, 2, STORAGE_INT_PATH_PREFIX[2]); + furi_string_set_char(path, 3, STORAGE_INT_PATH_PREFIX[3]); break; default: break; @@ -107,8 +107,8 @@ bool storage_process_file_open( file->error_id = FSE_INVALID_NAME; } else { storage = storage_get_storage_by_type(app, type); - string_t real_path; - string_init_set(real_path, path); + FuriString* real_path; + real_path = furi_string_alloc_set(path); storage_path_change_to_real_storage(real_path, type); if(storage_path_already_open(real_path, storage->files)) { @@ -118,7 +118,7 @@ bool storage_process_file_open( FS_CALL(storage, file.open(storage, file, remove_vfs(path), access_mode, open_mode)); } - string_clear(real_path); + furi_string_free(real_path); } return ret; @@ -266,8 +266,8 @@ bool storage_process_dir_open(Storage* app, File* file, const char* path) { file->error_id = FSE_INVALID_NAME; } else { storage = storage_get_storage_by_type(app, type); - string_t real_path; - string_init_set(real_path, path); + FuriString* real_path; + real_path = furi_string_alloc_set(path); storage_path_change_to_real_storage(real_path, type); if(storage_path_already_open(real_path, storage->files)) { @@ -276,7 +276,7 @@ bool storage_process_dir_open(Storage* app, File* file, const char* path) { storage_push_storage_file(file, real_path, type, storage); FS_CALL(storage, dir.open(storage, file, remove_vfs(path))); } - string_clear(real_path); + furi_string_free(real_path); } return ret; @@ -350,8 +350,8 @@ static FS_Error storage_process_common_remove(Storage* app, const char* path) { FS_Error ret = FSE_OK; StorageType type = storage_get_type_by_path(app, path); - string_t real_path; - string_init_set(real_path, path); + FuriString* real_path; + real_path = furi_string_alloc_set(path); storage_path_change_to_real_storage(real_path, type); do { @@ -369,7 +369,7 @@ static FS_Error storage_process_common_remove(Storage* app, const char* path) { FS_CALL(storage, common.remove(storage, remove_vfs(path))); } while(false); - string_clear(real_path); + furi_string_free(real_path); return ret; } diff --git a/applications/services/storage/storage_test_app.c b/applications/services/storage/storage_test_app.c index 8bfa9826..852953e9 100644 --- a/applications/services/storage/storage_test_app.c +++ b/applications/services/storage/storage_test_app.c @@ -224,13 +224,12 @@ static void do_dir_test(Storage* api, const char* path) { } static void do_test_start(Storage* api, const char* path) { - string_t str_path; - string_init_printf(str_path, "%s/test-folder", path); + FuriString* str_path = furi_string_alloc_printf("%s/test-folder", path); FURI_LOG_I(TAG, "--------- START \"%s\" ---------", path); // mkdir - FS_Error result = storage_common_mkdir(api, string_get_cstr(str_path)); + FS_Error result = storage_common_mkdir(api, furi_string_get_cstr(str_path)); if(result == FSE_OK) { FURI_LOG_I(TAG, "mkdir ok"); @@ -240,7 +239,7 @@ static void do_test_start(Storage* api, const char* path) { // stat FileInfo fileinfo; - result = storage_common_stat(api, string_get_cstr(str_path), &fileinfo); + result = storage_common_stat(api, furi_string_get_cstr(str_path), &fileinfo); if(result == FSE_OK) { if(fileinfo.flags & FSF_DIRECTORY) { @@ -252,16 +251,14 @@ static void do_test_start(Storage* api, const char* path) { FURI_LOG_E(TAG, "stat #1, %s", storage_error_get_desc(result)); } - string_clear(str_path); + furi_string_free(str_path); } static void do_test_end(Storage* api, const char* path) { uint64_t total_space; uint64_t free_space; - string_t str_path_1; - string_t str_path_2; - string_init_printf(str_path_1, "%s/test-folder", path); - string_init_printf(str_path_2, "%s/test-folder2", path); + FuriString* str_path_1 = furi_string_alloc_printf("%s/test-folder", path); + FuriString* str_path_2 = furi_string_alloc_printf("%s/test-folder2", path); FURI_LOG_I(TAG, "--------- END \"%s\" ---------", path); @@ -277,7 +274,8 @@ static void do_test_end(Storage* api, const char* path) { } // rename #1 - result = storage_common_rename(api, string_get_cstr(str_path_1), string_get_cstr(str_path_2)); + result = storage_common_rename( + api, furi_string_get_cstr(str_path_1), furi_string_get_cstr(str_path_2)); if(result == FSE_OK) { FURI_LOG_I(TAG, "rename #1 ok"); } else { @@ -285,7 +283,7 @@ static void do_test_end(Storage* api, const char* path) { } // remove #1 - result = storage_common_remove(api, string_get_cstr(str_path_2)); + result = storage_common_remove(api, furi_string_get_cstr(str_path_2)); if(result == FSE_OK) { FURI_LOG_I(TAG, "remove #1 ok"); } else { @@ -293,10 +291,11 @@ static void do_test_end(Storage* api, const char* path) { } // rename #2 - string_printf(str_path_1, "%s/test.txt", path); - string_printf(str_path_2, "%s/test2.txt", path); + furi_string_printf(str_path_1, "%s/test.txt", path); + furi_string_printf(str_path_2, "%s/test2.txt", path); - result = storage_common_rename(api, string_get_cstr(str_path_1), string_get_cstr(str_path_2)); + result = storage_common_rename( + api, furi_string_get_cstr(str_path_1), furi_string_get_cstr(str_path_2)); if(result == FSE_OK) { FURI_LOG_I(TAG, "rename #2 ok"); } else { @@ -304,15 +303,15 @@ static void do_test_end(Storage* api, const char* path) { } // remove #2 - result = storage_common_remove(api, string_get_cstr(str_path_2)); + result = storage_common_remove(api, furi_string_get_cstr(str_path_2)); if(result == FSE_OK) { FURI_LOG_I(TAG, "remove #2 ok"); } else { FURI_LOG_E(TAG, "remove #2, %s", storage_error_get_desc(result)); } - string_clear(str_path_1); - string_clear(str_path_2); + furi_string_free(str_path_1); + furi_string_free(str_path_2); } int32_t storage_test_app(void* p) { diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c index 75839735..4fa5d130 100644 --- a/applications/services/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -77,12 +77,12 @@ static int storage_int_device_read( FURI_LOG_T( TAG, - "Device read: block %d, off %d, buffer: %p, size %d, translated address: %p", + "Device read: block %ld, off %ld, buffer: %p, size %ld, translated address: %p", block, off, buffer, size, - address); + (void*)address); memcpy(buffer, (void*)address, size); @@ -100,12 +100,12 @@ static int storage_int_device_prog( FURI_LOG_T( TAG, - "Device prog: block %d, off %d, buffer: %p, size %d, translated address: %p", + "Device prog: block %ld, off %ld, buffer: %p, size %ld, translated address: %p", block, off, buffer, size, - address); + (void*)address); int ret = 0; while(size > 0) { @@ -122,7 +122,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc LFSData* lfs_data = c->context; size_t page = lfs_data->start_page + block; - FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page); + FURI_LOG_D(TAG, "Device erase: page %ld, translated page: %x", block, page); furi_hal_flash_erase(page); return 0; @@ -338,11 +338,12 @@ static bool storage_int_file_open( storage_set_storage_file_data(file, handle, storage); if(!enough_free_space) { - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); path_extract_basename(path, filename); - bool is_dot_file = (!string_empty_p(filename) && (string_get_char(filename, 0) == '.')); - string_clear(filename); + bool is_dot_file = + (!furi_string_empty(filename) && (furi_string_get_char(filename, 0) == '.')); + furi_string_free(filename); /* Restrict write & creation access to all non-dot files */ if(!is_dot_file && (flags & (LFS_O_CREAT | LFS_O_WRONLY))) { @@ -739,8 +740,8 @@ void storage_int_init(StorageData* storage) { LFSData* lfs_data = storage_int_lfs_data_alloc(); FURI_LOG_I( TAG, - "Config: start %p, read %d, write %d, page size: %d, page count: %d, cycles: %d", - lfs_data->start_address, + "Config: start %p, read %ld, write %ld, page size: %ld, page count: %ld, cycles: %ld", + (void*)lfs_data->start_address, lfs_data->config.read_size, lfs_data->config.prog_size, lfs_data->config.block_size, diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 6b4489f0..a42969b2 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -78,11 +77,11 @@ static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* mess static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - string_t buffer; - string_init(buffer); + FuriString* buffer; + buffer = furi_string_alloc(); const char* my_name = furi_hal_version_get_name_ptr(); - string_cat_printf( + furi_string_cat_printf( buffer, "%d.F%dB%dC%d %s:%s %s\n", furi_hal_version_get_hw_version(), @@ -93,26 +92,26 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* furi_hal_region_get_name(), my_name ? my_name : "Unknown"); - string_cat_printf(buffer, "Serial Number:\n"); + furi_string_cat_printf(buffer, "Serial Number:\n"); const uint8_t* uid = furi_hal_version_uid(); for(size_t i = 0; i < furi_hal_version_uid_size(); i++) { - string_cat_printf(buffer, "%02X", uid[i]); + furi_string_cat_printf(buffer, "%02X", uid[i]); } dialog_message_set_header(message, "HW Version Info:", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); + dialog_message_set_text(message, furi_string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); result = dialog_message_show(dialogs, message); dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop); dialog_message_set_header(message, NULL, 0, 0, AlignLeft, AlignTop); - string_clear(buffer); + furi_string_free(buffer); return result; } static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - string_t buffer; - string_init(buffer); + FuriString* buffer; + buffer = furi_string_alloc(); const Version* ver = furi_hal_version_get_firmware_version(); const BleGlueC2Info* c2_ver = NULL; #ifdef SRV_BT @@ -120,9 +119,9 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* #endif if(!ver) { - string_cat_printf(buffer, "No info\n"); + furi_string_cat_printf(buffer, "No info\n"); } else { - string_cat_printf( + furi_string_cat_printf( buffer, "%s [%s]\n%s%s [%s] %s\n[%d] %s", version_get_version(ver), @@ -136,11 +135,11 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* } dialog_message_set_header(message, "FW Version Info:", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); + dialog_message_set_text(message, furi_string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); result = dialog_message_show(dialogs, message); dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop); dialog_message_set_header(message, NULL, 0, 0, AlignLeft, AlignTop); - string_clear(buffer); + furi_string_free(buffer); return result; } diff --git a/applications/settings/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c index a2ed8b72..afb5d59e 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -22,6 +22,7 @@ DesktopSettingsApp* desktop_settings_app_alloc() { DesktopSettingsApp* app = malloc(sizeof(DesktopSettingsApp)); app->gui = furi_record_open(RECORD_GUI); + app->dialogs = furi_record_open(RECORD_DIALOGS); app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&desktop_settings_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); @@ -83,6 +84,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); // Records + furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_GUI); free(app); } diff --git a/applications/settings/desktop_settings/desktop_settings_app.h b/applications/settings/desktop_settings/desktop_settings_app.h index 25c5b3ad..fc56c325 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.h +++ b/applications/settings/desktop_settings/desktop_settings_app.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,7 @@ typedef struct { DesktopSettings settings; Gui* gui; + DialogsApp* dialogs; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; VariableItemList* variable_item_list; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index d8c579b3..bdd9589e 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -1,6 +1,35 @@ #include "../desktop_settings_app.h" #include "applications.h" #include "desktop_settings_scene.h" +#include +#include +#include + +static bool favorite_fap_selector_item_callback( + FuriString* file_path, + void* context, + uint8_t** icon_ptr, + FuriString* item_name) { + UNUSED(context); +#ifdef APP_FAP_LOADER + Storage* storage = furi_record_open(RECORD_STORAGE); + bool success = fap_loader_load_name_and_icon(file_path, storage, icon_ptr, item_name); + furi_record_close(RECORD_STORAGE); +#else + UNUSED(file_path); + UNUSED(icon_ptr); + UNUSED(item_name); + bool success = false; +#endif + return success; +} + +static bool favorite_fap_selector_file_exists(char* file_path) { + Storage* storage = furi_record_open(RECORD_STORAGE); + bool exists = storage_file_exists(storage, file_path); + furi_record_close(RECORD_STORAGE); + return exists; +} static void desktop_settings_scene_favorite_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -12,6 +41,10 @@ void desktop_settings_scene_favorite_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_reset(submenu); + uint32_t primary_favorite = + scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); + uint32_t pre_select_item = 0; + for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { submenu_add_item( submenu, @@ -19,38 +52,96 @@ void desktop_settings_scene_favorite_on_enter(void* context) { i, desktop_settings_scene_favorite_submenu_callback, app); - } - uint32_t primary_favorite = - scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); + if(primary_favorite) { // Select favorite item in submenu + if((app->settings.favorite_primary.is_external && + !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || + (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_primary.name_or_path))) { + pre_select_item = i; + } + } else { + if((app->settings.favorite_secondary.is_external && + !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || + (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_secondary.name_or_path))) { + pre_select_item = i; + } + } + } submenu_set_header( - app->submenu, primary_favorite ? "Primary favorite app:" : "Secondary favorite app:"); + submenu, primary_favorite ? "Primary favorite app:" : "Secondary favorite app:"); + submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch. - if(primary_favorite) { - submenu_set_selected_item(app->submenu, app->settings.favorite_primary); - } else { - submenu_set_selected_item(app->submenu, app->settings.favorite_secondary); - } view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu); } bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent event) { DesktopSettingsApp* app = context; bool consumed = false; + FuriString* temp_path = furi_string_alloc_set_str(EXT_PATH("apps")); uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); if(event.type == SceneManagerEventTypeCustom) { - if(primary_favorite) { - app->settings.favorite_primary = event.event; + if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME)) { + if(primary_favorite) { + app->settings.favorite_primary.is_external = false; + strncpy( + app->settings.favorite_primary.name_or_path, + FLIPPER_APPS[event.event].name, + MAX_APP_LENGTH); + } else { + app->settings.favorite_secondary.is_external = false; + strncpy( + app->settings.favorite_secondary.name_or_path, + FLIPPER_APPS[event.event].name, + MAX_APP_LENGTH); + } } else { - app->settings.favorite_secondary = event.event; + const DialogsFileBrowserOptions browser_options = { + .extension = ".fap", + .icon = &I_unknown_10px, + .skip_assets = true, + .hide_ext = true, + .item_loader_callback = favorite_fap_selector_item_callback, + .item_loader_context = app, + }; + + if(primary_favorite) { // Select favorite fap in file browser + if(favorite_fap_selector_file_exists( + app->settings.favorite_primary.name_or_path)) { + furi_string_set_str(temp_path, app->settings.favorite_primary.name_or_path); + } + } else { + if(favorite_fap_selector_file_exists( + app->settings.favorite_secondary.name_or_path)) { + furi_string_set_str(temp_path, app->settings.favorite_secondary.name_or_path); + } + } + + submenu_reset(app->submenu); + if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { + if(primary_favorite) { + app->settings.favorite_primary.is_external = true; + strncpy( + app->settings.favorite_primary.name_or_path, + furi_string_get_cstr(temp_path), + MAX_APP_LENGTH); + } else { + app->settings.favorite_secondary.is_external = true; + strncpy( + app->settings.favorite_secondary.name_or_path, + furi_string_get_cstr(temp_path), + MAX_APP_LENGTH); + } + } } scene_manager_previous_scene(app->scene_manager); consumed = true; } + + furi_string_free(temp_path); return consumed; } diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index aa3a1e96..1a8bc71e 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -119,8 +119,8 @@ void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) { furi_assert(battery_info); furi_assert(data); with_view_model( - battery_info->view, (BatteryInfoModel * model) { - memcpy(model, data, sizeof(BatteryInfoModel)); - return true; - }); + battery_info->view, + BatteryInfoModel * model, + { memcpy(model, data, sizeof(BatteryInfoModel)); }, + true); } diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c b/applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c index ddeea4eb..71a3df78 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c @@ -92,19 +92,19 @@ static void storage_settings_scene_benchmark(StorageSettings* app) { app->fs_api, bench_size[i], bench_data, &bench_w_speed[i])) break; - if(i > 0) string_cat_printf(app->text_string, "\n"); - string_cat_printf(app->text_string, "%ub : W %luK ", bench_size[i], bench_w_speed[i]); + if(i > 0) furi_string_cat_printf(app->text_string, "\n"); + furi_string_cat_printf(app->text_string, "%ub : W %luK ", bench_size[i], bench_w_speed[i]); dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); dialog_ex_set_text( - dialog_ex, string_get_cstr(app->text_string), 0, 32, AlignLeft, AlignCenter); + dialog_ex, furi_string_get_cstr(app->text_string), 0, 32, AlignLeft, AlignCenter); if(!storage_settings_scene_bench_read( app->fs_api, bench_size[i], bench_data, &bench_r_speed[i])) break; - string_cat_printf(app->text_string, "R %luK", bench_r_speed[i]); + furi_string_cat_printf(app->text_string, "R %luK", bench_r_speed[i]); dialog_ex_set_text( - dialog_ex, string_get_cstr(app->text_string), 0, 32, AlignLeft, AlignCenter); + dialog_ex, furi_string_get_cstr(app->text_string), 0, 32, AlignLeft, AlignCenter); } free(bench_data); @@ -159,5 +159,5 @@ void storage_settings_scene_benchmark_on_exit(void* context) { dialog_ex_reset(dialog_ex); - string_reset(app->text_string); + furi_string_reset(app->text_string); } diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c index a6947968..64d2b96b 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c @@ -49,13 +49,13 @@ bool storage_settings_scene_factory_reset_on_event(void* context, SceneManagerEv case DialogExResultRight: counter++; if(counter < STORAGE_SETTINGS_SCENE_FACTORY_RESET_CONFIRM_COUNT) { - string_printf( + furi_string_printf( app->text_string, "%ld presses left", STORAGE_SETTINGS_SCENE_FACTORY_RESET_CONFIRM_COUNT - counter); dialog_ex_set_text( app->dialog_ex, - string_get_cstr(app->text_string), + furi_string_get_cstr(app->text_string), 64, 32, AlignCenter, @@ -83,5 +83,5 @@ void storage_settings_scene_factory_reset_on_exit(void* context) { dialog_ex_reset(dialog_ex); - string_reset(app->text_string); + furi_string_reset(app->text_string); } diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c index 76c7fd0e..f205efc0 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c @@ -25,14 +25,14 @@ void storage_settings_scene_internal_info_on_enter(void* context) { dialog_ex_set_text( dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter); } else { - string_printf( + furi_string_printf( app->text_string, - "Label: %s\nType: LittleFS\n%lu KB total\n%lu KB free", + "Label: %s\nType: LittleFS\n%lu KiB total\n%lu KiB free", furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown", (uint32_t)(total_space / 1024), (uint32_t)(free_space / 1024)); dialog_ex_set_text( - dialog_ex, string_get_cstr(app->text_string), 4, 4, AlignLeft, AlignTop); + dialog_ex, furi_string_get_cstr(app->text_string), 4, 4, AlignLeft, AlignTop); } view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx); @@ -58,5 +58,5 @@ void storage_settings_scene_internal_info_on_exit(void* context) { dialog_ex_reset(dialog_ex); - string_reset(app->text_string); + furi_string_reset(app->text_string); } diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c index cfb4f310..ede610d0 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c @@ -24,15 +24,15 @@ void storage_settings_scene_sd_info_on_enter(void* context) { dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop); dialog_ex_set_center_button_text(dialog_ex, "Ok"); } else { - string_printf( + furi_string_printf( app->text_string, - "Label: %s\nType: %s\n%lu KB total\n%lu KB free", + "Label: %s\nType: %s\n%lu KiB total\n%lu KiB free", sd_info.label, sd_api_get_fs_type_text(sd_info.fs_type), sd_info.kb_total, sd_info.kb_free); dialog_ex_set_text( - dialog_ex, string_get_cstr(app->text_string), 4, 4, AlignLeft, AlignTop); + dialog_ex, furi_string_get_cstr(app->text_string), 4, 4, AlignLeft, AlignTop); } view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx); @@ -70,5 +70,5 @@ void storage_settings_scene_sd_info_on_exit(void* context) { dialog_ex_reset(dialog_ex); - string_reset(app->text_string); + furi_string_reset(app->text_string); } diff --git a/applications/settings/storage_settings/storage_settings.c b/applications/settings/storage_settings/storage_settings.c index f580e636..77a8f0f2 100644 --- a/applications/settings/storage_settings/storage_settings.c +++ b/applications/settings/storage_settings/storage_settings.c @@ -21,7 +21,7 @@ static StorageSettings* storage_settings_alloc() { app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&storage_settings_scene_handlers, app); - string_init(app->text_string); + app->text_string = furi_string_alloc(); view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); @@ -60,7 +60,7 @@ static void storage_settings_free(StorageSettings* app) { furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_NOTIFICATION); - string_clear(app->text_string); + furi_string_free(app->text_string); free(app); } diff --git a/applications/settings/storage_settings/storage_settings.h b/applications/settings/storage_settings/storage_settings.h index f2d071c4..4cf185e0 100644 --- a/applications/settings/storage_settings/storage_settings.h +++ b/applications/settings/storage_settings/storage_settings.h @@ -34,7 +34,7 @@ typedef struct { DialogEx* dialog_ex; // text - string_t text_string; + FuriString* text_string; } StorageSettings; typedef enum { diff --git a/applications/system/storage_move_to_sd/storage_move_to_sd.c b/applications/system/storage_move_to_sd/storage_move_to_sd.c index e5b195d5..2027bd23 100644 --- a/applications/system/storage_move_to_sd/storage_move_to_sd.c +++ b/applications/system/storage_move_to_sd/storage_move_to_sd.c @@ -2,7 +2,6 @@ #include #include #include "loader/loader.h" -#include "m-string.h" #include #include #include @@ -28,25 +27,26 @@ bool storage_move_to_sd_perform(void) { dir_walk_set_recursive(dir_walk, false); dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL); - string_t path_src, path_dst; + FuriString *path_src, *path_dst; - string_init(path_dst); - string_init(path_src); + path_dst = furi_string_alloc(); + path_src = furi_string_alloc(); if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) { while(dir_walk_read(dir_walk, path_src, NULL) == DirWalkOK) { - string_set(path_dst, path_src); - string_replace_at( + furi_string_set(path_dst, path_src); + furi_string_replace_at( path_dst, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX); - storage_common_merge(storage, string_get_cstr(path_src), string_get_cstr(path_dst)); - storage_simply_remove_recursive(storage, string_get_cstr(path_src)); + storage_common_merge( + storage, furi_string_get_cstr(path_src), furi_string_get_cstr(path_dst)); + storage_simply_remove_recursive(storage, furi_string_get_cstr(path_src)); } } dir_walk_free(dir_walk); - string_clear(path_dst); - string_clear(path_src); + furi_string_free(path_dst); + furi_string_free(path_src); furi_record_close(RECORD_STORAGE); @@ -62,8 +62,8 @@ static bool storage_move_to_sd_check(void) { dir_walk_set_recursive(dir_walk, false); dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL); - string_t name; - string_init(name); + FuriString* name; + name = furi_string_alloc(); if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) { // if at least 1 entry is present, we should migrate @@ -71,7 +71,7 @@ static bool storage_move_to_sd_check(void) { } dir_walk_free(dir_walk); - string_clear(name); + furi_string_free(name); furi_record_close(RECORD_STORAGE); diff --git a/applications/system/updater/cli/updater_cli.c b/applications/system/updater/cli/updater_cli.c index ec209bd1..c3cdbb5f 100644 --- a/applications/system/updater/cli/updater_cli.c +++ b/applications/system/updater/cli/updater_cli.c @@ -1,7 +1,6 @@ #include #include -#include #include #include #include @@ -12,16 +11,16 @@ #include #include -typedef void (*cmd_handler)(string_t args); +typedef void (*cmd_handler)(FuriString* args); typedef struct { const char* command; const cmd_handler handler; } CliSubcommand; -static void updater_cli_install(string_t manifest_path) { - printf("Verifying update package at '%s'\r\n", string_get_cstr(manifest_path)); +static void updater_cli_install(FuriString* manifest_path) { + printf("Verifying update package at '%s'\r\n", furi_string_get_cstr(manifest_path)); - UpdatePrepareResult result = update_operation_prepare(string_get_cstr(manifest_path)); + UpdatePrepareResult result = update_operation_prepare(furi_string_get_cstr(manifest_path)); if(result != UpdatePrepareResultOK) { printf( "Error: %s. Stopping update.\r\n", @@ -33,23 +32,23 @@ static void updater_cli_install(string_t manifest_path) { furi_hal_power_reset(); } -static void updater_cli_backup(string_t args) { - printf("Backup /int to '%s'\r\n", string_get_cstr(args)); +static void updater_cli_backup(FuriString* args) { + printf("Backup /int to '%s'\r\n", furi_string_get_cstr(args)); Storage* storage = furi_record_open(RECORD_STORAGE); - bool success = lfs_backup_create(storage, string_get_cstr(args)); + bool success = lfs_backup_create(storage, furi_string_get_cstr(args)); furi_record_close(RECORD_STORAGE); printf("Result: %s\r\n", success ? "OK" : "FAIL"); } -static void updater_cli_restore(string_t args) { - printf("Restore /int from '%s'\r\n", string_get_cstr(args)); +static void updater_cli_restore(FuriString* args) { + printf("Restore /int from '%s'\r\n", furi_string_get_cstr(args)); Storage* storage = furi_record_open(RECORD_STORAGE); - bool success = lfs_backup_unpack(storage, string_get_cstr(args)); + bool success = lfs_backup_unpack(storage, furi_string_get_cstr(args)); furi_record_close(RECORD_STORAGE); printf("Result: %s\r\n", success ? "OK" : "FAIL"); } -static void updater_cli_help(string_t args) { +static void updater_cli_help(FuriString* args) { UNUSED(args); printf("Commands:\r\n" "\tinstall /ext/path/to/update.fuf - verify & apply update package\r\n" @@ -64,25 +63,25 @@ static const CliSubcommand update_cli_subcommands[] = { {.command = "help", .handler = updater_cli_help}, }; -static void updater_cli_ep(Cli* cli, string_t args, void* context) { +static void updater_cli_ep(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); - string_t subcommand; - string_init(subcommand); - if(!args_read_string_and_trim(args, subcommand) || string_empty_p(args)) { + FuriString* subcommand; + subcommand = furi_string_alloc(); + if(!args_read_string_and_trim(args, subcommand) || furi_string_empty(args)) { updater_cli_help(args); - string_clear(subcommand); + furi_string_free(subcommand); return; } for(size_t idx = 0; idx < COUNT_OF(update_cli_subcommands); ++idx) { const CliSubcommand* subcmd_def = &update_cli_subcommands[idx]; - if(string_cmp_str(subcommand, subcmd_def->command) == 0) { - string_clear(subcommand); + if(furi_string_cmp_str(subcommand, subcmd_def->command) == 0) { + furi_string_free(subcommand); subcmd_def->handler(args); return; } } - string_clear(subcommand); + furi_string_free(subcommand); updater_cli_help(args); } diff --git a/applications/system/updater/scenes/updater_scene_loadcfg.c b/applications/system/updater/scenes/updater_scene_loadcfg.c index c7f48c78..14f7b203 100644 --- a/applications/system/updater/scenes/updater_scene_loadcfg.c +++ b/applications/system/updater/scenes/updater_scene_loadcfg.c @@ -25,7 +25,7 @@ void updater_scene_loadcfg_on_enter(void* context) { malloc(sizeof(UpdaterManifestProcessingState)); pending_upd->manifest = update_manifest_alloc(); - if(update_manifest_init(pending_upd->manifest, string_get_cstr(updater->startup_arg))) { + if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) { widget_add_string_element( updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update"); @@ -37,7 +37,7 @@ void updater_scene_loadcfg_on_enter(void* context) { 32, AlignCenter, AlignCenter, - string_get_cstr(pending_upd->manifest->version), + furi_string_get_cstr(pending_upd->manifest->version), true); widget_add_button_element( @@ -72,7 +72,7 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case UpdaterCustomEventStartUpdate: updater->preparation_result = - update_operation_prepare(string_get_cstr(updater->startup_arg)); + update_operation_prepare(furi_string_get_cstr(updater->startup_arg)); if(updater->preparation_result == UpdatePrepareResultOK) { furi_hal_power_reset(); } else { @@ -99,7 +99,7 @@ void updater_scene_loadcfg_on_exit(void* context) { if(updater->pending_update) { update_manifest_free(updater->pending_update->manifest); - string_clear(updater->pending_update->message); + furi_string_free(updater->pending_update->message); } widget_reset(updater->widget); diff --git a/applications/system/updater/updater.c b/applications/system/updater/updater.c index e9bedc72..e749f3ce 100644 --- a/applications/system/updater/updater.c +++ b/applications/system/updater/updater.c @@ -35,10 +35,10 @@ static void Updater* updater_alloc(const char* arg) { Updater* updater = malloc(sizeof(Updater)); if(arg && strlen(arg)) { - string_init_set_str(updater->startup_arg, arg); - string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); + updater->startup_arg = furi_string_alloc_set(arg); + furi_string_replace(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); } else { - string_init(updater->startup_arg); + updater->startup_arg = furi_string_alloc(); } updater->storage = furi_record_open(RECORD_STORAGE); @@ -94,7 +94,7 @@ Updater* updater_alloc(const char* arg) { void updater_free(Updater* updater) { furi_assert(updater); - string_clear(updater->startup_arg); + furi_string_free(updater->startup_arg); if(updater->update_task) { update_task_set_progress_cb(updater->update_task, NULL, NULL); update_task_free(updater->update_task); diff --git a/applications/system/updater/updater_i.h b/applications/system/updater/updater_i.h index 8a021a08..ae249f38 100644 --- a/applications/system/updater/updater_i.h +++ b/applications/system/updater/updater_i.h @@ -35,7 +35,7 @@ typedef enum { typedef struct UpdaterManifestProcessingState { UpdateManifest* manifest; - string_t message; + FuriString* message; bool ready_to_be_applied; } UpdaterManifestProcessingState; @@ -54,7 +54,7 @@ typedef struct { UpdateTask* update_task; Widget* widget; - string_t startup_arg; + FuriString* startup_arg; int32_t idle_ticks; } Updater; diff --git a/applications/system/updater/util/update_task.c b/applications/system/updater/util/update_task.c index b0477319..de172dd4 100644 --- a/applications/system/updater/util/update_task.c +++ b/applications/system/updater/util/update_task.c @@ -69,19 +69,19 @@ static const UpdateTaskStageGroupMap update_task_stage_progress[] = { static UpdateTaskStageGroup update_task_get_task_groups(UpdateTask* update_task) { UpdateTaskStageGroup ret = UpdateTaskStageGroupPreUpdate | UpdateTaskStageGroupPostUpdate; UpdateManifest* manifest = update_task->manifest; - if(!string_empty_p(manifest->radio_image)) { + if(!furi_string_empty(manifest->radio_image)) { ret |= UpdateTaskStageGroupRadio; } if(update_manifest_has_obdata(manifest)) { ret |= UpdateTaskStageGroupOptionBytes; } - if(!string_empty_p(manifest->firmware_dfu_image)) { + if(!furi_string_empty(manifest->firmware_dfu_image)) { ret |= UpdateTaskStageGroupFirmware; } - if(!string_empty_p(manifest->resource_bundle)) { + if(!furi_string_empty(manifest->resource_bundle)) { ret |= UpdateTaskStageGroupResources; } - if(!string_empty_p(manifest->splash_file)) { + if(!furi_string_empty(manifest->splash_file)) { ret |= UpdateTaskStageGroupSplashscreen; } return ret; @@ -109,14 +109,14 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui } /* Build error message with code "[stage_idx-stage_percent]" */ if(stage >= UpdateTaskStageError) { - string_printf( + furi_string_printf( update_task->state.status, "%s #[%d-%d]", update_task_stage_descr[stage], update_task->state.stage, update_task->state.stage_progress); } else { - string_set_str(update_task->state.status, update_task_stage_descr[stage]); + furi_string_set(update_task->state.status, update_task_stage_descr[stage]); } /* Store stage update */ update_task->state.stage = stage; @@ -149,7 +149,7 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui if(update_task->status_change_cb) { (update_task->status_change_cb)( - string_get_cstr(update_task->state.status), + furi_string_get_cstr(update_task->state.status), adapted_progress, update_stage_is_error(update_task->state.stage), update_task->status_change_cb_state); @@ -165,26 +165,26 @@ static void update_task_close_file(UpdateTask* update_task) { storage_file_close(update_task->file); } -static bool update_task_check_file_exists(UpdateTask* update_task, string_t filename) { +static bool update_task_check_file_exists(UpdateTask* update_task, FuriString* filename) { furi_assert(update_task); - string_t tmp_path; - string_init_set(tmp_path, update_task->update_path); - path_append(tmp_path, string_get_cstr(filename)); - bool exists = storage_file_exists(update_task->storage, string_get_cstr(tmp_path)); - string_clear(tmp_path); + FuriString* tmp_path; + tmp_path = furi_string_alloc_set(update_task->update_path); + path_append(tmp_path, furi_string_get_cstr(filename)); + bool exists = storage_file_exists(update_task->storage, furi_string_get_cstr(tmp_path)); + furi_string_free(tmp_path); return exists; } -bool update_task_open_file(UpdateTask* update_task, string_t filename) { +bool update_task_open_file(UpdateTask* update_task, FuriString* filename) { furi_assert(update_task); update_task_close_file(update_task); - string_t tmp_path; - string_init_set(tmp_path, update_task->update_path); - path_append(tmp_path, string_get_cstr(filename)); + FuriString* tmp_path; + tmp_path = furi_string_alloc_set(update_task->update_path); + path_append(tmp_path, furi_string_get_cstr(filename)); bool open_success = storage_file_open( - update_task->file, string_get_cstr(tmp_path), FSAM_READ, FSOM_OPEN_EXISTING); - string_clear(tmp_path); + update_task->file, furi_string_get_cstr(tmp_path), FSAM_READ, FSOM_OPEN_EXISTING); + furi_string_free(tmp_path); return open_success; } @@ -207,14 +207,14 @@ UpdateTask* update_task_alloc() { update_task->state.stage = UpdateTaskStageProgress; update_task->state.stage_progress = 0; update_task->state.overall_progress = 0; - string_init(update_task->state.status); + update_task->state.status = furi_string_alloc(); update_task->manifest = update_manifest_alloc(); update_task->storage = furi_record_open(RECORD_STORAGE); update_task->file = storage_file_alloc(update_task->storage); update_task->status_change_cb = NULL; update_task->boot_mode = furi_hal_rtc_get_boot_mode(); - string_init(update_task->update_path); + update_task->update_path = furi_string_alloc(); FuriThread* thread = update_task->thread = furi_thread_alloc(); @@ -246,7 +246,7 @@ void update_task_free(UpdateTask* update_task) { update_manifest_free(update_task->manifest); furi_record_close(RECORD_STORAGE); - string_clear(update_task->update_path); + furi_string_free(update_task->update_path); free(update_task); } @@ -261,8 +261,8 @@ bool update_task_parse_manifest(UpdateTask* update_task) { update_task_set_progress(update_task, UpdateTaskStageReadManifest, 0); bool result = false; - string_t manifest_path; - string_init(manifest_path); + FuriString* manifest_path; + manifest_path = furi_string_alloc(); do { update_task_set_progress(update_task, UpdateTaskStageProgress, 13); @@ -276,11 +276,11 @@ bool update_task_parse_manifest(UpdateTask* update_task) { break; } - path_extract_dirname(string_get_cstr(manifest_path), update_task->update_path); + path_extract_dirname(furi_string_get_cstr(manifest_path), update_task->update_path); update_task_set_progress(update_task, UpdateTaskStageProgress, 30); UpdateManifest* manifest = update_task->manifest; - if(!update_manifest_init(manifest, string_get_cstr(manifest_path))) { + if(!update_manifest_init(manifest, furi_string_get_cstr(manifest_path))) { break; } @@ -320,7 +320,7 @@ bool update_task_parse_manifest(UpdateTask* update_task) { result = true; } while(false); - string_clear(manifest_path); + furi_string_free(manifest_path); return result; } diff --git a/applications/system/updater/util/update_task.h b/applications/system/updater/util/update_task.h index ad8c5085..b3ac3f2f 100644 --- a/applications/system/updater/util/update_task.h +++ b/applications/system/updater/util/update_task.h @@ -8,7 +8,6 @@ extern "C" { #include #include -#include #define UPDATE_DELAY_OPERATION_OK 10 #define UPDATE_DELAY_OPERATION_ERROR INT_MAX @@ -59,7 +58,7 @@ typedef enum { typedef struct { UpdateTaskStage stage; uint8_t overall_progress, stage_progress; - string_t status; + FuriString* status; UpdateTaskStageGroup groups; uint32_t total_progress_points; uint32_t completed_stages_points; diff --git a/applications/system/updater/util/update_task_i.h b/applications/system/updater/util/update_task_i.h index 95c63f64..0dbeca5f 100644 --- a/applications/system/updater/util/update_task_i.h +++ b/applications/system/updater/util/update_task_i.h @@ -8,7 +8,7 @@ typedef struct UpdateTask { UpdateTaskState state; - string_t update_path; + FuriString* update_path; UpdateManifest* manifest; FuriThread* thread; Storage* storage; @@ -20,7 +20,7 @@ typedef struct UpdateTask { void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, uint8_t progress); bool update_task_parse_manifest(UpdateTask* update_task); -bool update_task_open_file(UpdateTask* update_task, string_t filename); +bool update_task_open_file(UpdateTask* update_task, FuriString* filename); int32_t update_task_worker_flash_writer(void* context); int32_t update_task_worker_backup_restore(void* context); diff --git a/applications/system/updater/util/update_task_worker_backup.c b/applications/system/updater/util/update_task_worker_backup.c index 046be372..ce62da2a 100644 --- a/applications/system/updater/util/update_task_worker_backup.c +++ b/applications/system/updater/util/update_task_worker_backup.c @@ -22,19 +22,22 @@ static bool update_task_pre_update(UpdateTask* update_task) { bool success = false; - string_t backup_file_path; - string_init(backup_file_path); + FuriString* backup_file_path; + backup_file_path = furi_string_alloc(); path_concat( - string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, backup_file_path); + furi_string_get_cstr(update_task->update_path), + LFS_BACKUP_DEFAULT_FILENAME, + backup_file_path); update_task_set_progress(update_task, UpdateTaskStageLfsBackup, 0); /* to avoid bootloops */ furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); - if((success = lfs_backup_create(update_task->storage, string_get_cstr(backup_file_path)))) { + if((success = + lfs_backup_create(update_task->storage, furi_string_get_cstr(backup_file_path)))) { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeUpdate); } - string_clear(backup_file_path); + furi_string_free(backup_file_path); return success; } @@ -79,12 +82,12 @@ static void /* For this stage, first 30% of progress = cleanup */ (n_processed_files++ * 30) / (n_approx_file_entries + 1)); - string_t file_path; - string_init(file_path); - path_concat(STORAGE_EXT_PATH_PREFIX, string_get_cstr(entry_ptr->name), file_path); - FURI_LOG_D(TAG, "Removing %s", string_get_cstr(file_path)); - storage_simply_remove(update_task->storage, string_get_cstr(file_path)); - string_clear(file_path); + FuriString* file_path = furi_string_alloc(); + path_concat( + STORAGE_EXT_PATH_PREFIX, furi_string_get_cstr(entry_ptr->name), file_path); + FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path)); + storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path)); + furi_string_free(file_path); } } } while(false); @@ -94,17 +97,19 @@ static void static bool update_task_post_update(UpdateTask* update_task) { bool success = false; - string_t file_path; - string_init(file_path); + FuriString* file_path; + file_path = furi_string_alloc(); TarArchive* archive = tar_archive_alloc(update_task->storage); do { path_concat( - string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, file_path); + furi_string_get_cstr(update_task->update_path), + LFS_BACKUP_DEFAULT_FILENAME, + file_path); update_task_set_progress(update_task, UpdateTaskStageLfsRestore, 0); - CHECK_RESULT(lfs_backup_unpack(update_task->storage, string_get_cstr(file_path))); + CHECK_RESULT(lfs_backup_unpack(update_task->storage, furi_string_get_cstr(file_path))); if(update_task->state.groups & UpdateTaskStageGroupResources) { TarUnpackProgress progress = { @@ -115,13 +120,13 @@ static bool update_task_post_update(UpdateTask* update_task) { update_task_set_progress(update_task, UpdateTaskStageResourcesUpdate, 0); path_concat( - string_get_cstr(update_task->update_path), - string_get_cstr(update_task->manifest->resource_bundle), + furi_string_get_cstr(update_task->update_path), + furi_string_get_cstr(update_task->manifest->resource_bundle), file_path); tar_archive_set_file_callback(archive, update_task_resource_unpack_cb, &progress); CHECK_RESULT( - tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ)); + tar_archive_open(archive, furi_string_get_cstr(file_path), TAR_OPEN_MODE_READ)); progress.total_files = tar_archive_get_entries_count(archive); if(progress.total_files > 0) { @@ -133,23 +138,23 @@ static bool update_task_post_update(UpdateTask* update_task) { if(update_task->state.groups & UpdateTaskStageGroupSplashscreen) { update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 0); - string_t tmp_path; - string_init_set(tmp_path, update_task->update_path); - path_append(tmp_path, string_get_cstr(update_task->manifest->splash_file)); + FuriString* tmp_path; + tmp_path = furi_string_alloc_set(update_task->update_path); + path_append(tmp_path, furi_string_get_cstr(update_task->manifest->splash_file)); if(storage_common_copy( update_task->storage, - string_get_cstr(tmp_path), + furi_string_get_cstr(tmp_path), INT_PATH(SLIDESHOW_FILE_NAME)) != FSE_OK) { // actually, not critical } - string_clear(tmp_path); + furi_string_free(tmp_path); update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 100); } success = true; } while(false); tar_archive_free(archive); - string_clear(file_path); + furi_string_free(file_path); return success; } diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index b235d001..7358a633 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -271,7 +271,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { match = false; FURI_LOG_E( TAG, - "OB MISMATCH: #%d: real %08X != %08X (exp.), full %08X", + "OB MISMATCH: #%d: real %08lX != %08lX (exp.), full %08lX", idx, device_ob_value_masked, ref_value, @@ -289,7 +289,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { (manifest->ob_reference.obs[idx].values.base & manifest->ob_write_mask.obs[idx].values.base); - FURI_LOG_W(TAG, "Fixing up OB byte #%d to %08X", idx, patched_value); + FURI_LOG_W(TAG, "Fixing up OB byte #%d to %08lX", idx, patched_value); ob_dirty = true; bool is_fixed = furi_hal_flash_ob_set_word(idx, patched_value) && @@ -301,7 +301,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { * reference value */ FURI_LOG_W( TAG, - "OB #%d is FUBAR (fixed&masked %08X, not %08X)", + "OB #%d is FUBAR (fixed&masked %08lX, not %08lX)", idx, patched_value, ref_value); @@ -310,7 +310,7 @@ bool update_task_validate_optionbytes(UpdateTask* update_task) { } else { FURI_LOG_D( TAG, - "OB MATCH: #%d: real %08X == %08X (exp.)", + "OB MATCH: #%d: real %08lX == %08lX (exp.)", idx, device_ob_value_masked, ref_value); diff --git a/applications/system/updater/views/updater_main.c b/applications/system/updater/views/updater_main.c index 72541b9a..5ed3c70a 100644 --- a/applications/system/updater/views/updater_main.c +++ b/applications/system/updater/views/updater_main.c @@ -18,7 +18,7 @@ struct UpdaterMainView { static const uint8_t PROGRESS_RENDER_STEP = 1; /* percent, to limit rendering rate */ typedef struct { - string_t status; + FuriString* status; uint8_t progress, rendered_progress; bool failed; } UpdaterProgressModel; @@ -28,22 +28,25 @@ void updater_main_model_set_state( const char* message, uint8_t progress, bool failed) { + bool update = false; with_view_model( - main_view->view, (UpdaterProgressModel * model) { + main_view->view, + UpdaterProgressModel * model, + { model->failed = failed; model->progress = progress; - if(string_cmp_str(model->status, message)) { - string_set(model->status, message); + if(furi_string_cmp_str(model->status, message)) { + furi_string_set(model->status, message); model->rendered_progress = progress; - return true; - } - if((model->rendered_progress > progress) || - ((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) { + update = true; + } else if( + (model->rendered_progress > progress) || + ((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) { model->rendered_progress = progress; - return true; + update = true; } - return false; - }); + }, + update); } View* updater_main_get_view(UpdaterMainView* main_view) { @@ -80,7 +83,7 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) { canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!"); canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned( - canvas, 42, 32, AlignLeft, AlignTop, string_get_cstr(model->status)); + canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status)); canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23); canvas_draw_str_aligned( @@ -91,7 +94,7 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) { canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING"); canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned( - canvas, 64, 51, AlignCenter, AlignTop, string_get_cstr(model->status)); + canvas, 64, 51, AlignCenter, AlignTop, furi_string_get_cstr(model->status)); canvas_draw_icon(canvas, 4, 5, &I_Updating_32x40); elements_progress_bar(canvas, 42, 29, 80, (float)model->progress / 100); } @@ -104,10 +107,10 @@ UpdaterMainView* updater_main_alloc() { view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(UpdaterProgressModel)); with_view_model( - main_view->view, (UpdaterProgressModel * model) { - string_init_set(model->status, "Waiting for SD card"); - return true; - }); + main_view->view, + UpdaterProgressModel * model, + { model->status = furi_string_alloc_set("Waiting for SD card"); }, + true); view_set_context(main_view->view, main_view); view_set_input_callback(main_view->view, updater_main_input); @@ -119,10 +122,7 @@ UpdaterMainView* updater_main_alloc() { void updater_main_free(UpdaterMainView* main_view) { furi_assert(main_view); with_view_model( - main_view->view, (UpdaterProgressModel * model) { - string_clear(model->status); - return false; - }); + main_view->view, UpdaterProgressModel * model, { furi_string_free(model->status); }, false); view_free(main_view->view); free(main_view); } diff --git a/assets/SConscript b/assets/SConscript index a0b3b13a..e1bf546c 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -9,28 +9,13 @@ assetsenv = env.Clone( ) assetsenv.ApplyLibFlags() -if not assetsenv["VERBOSE"]: - assetsenv.SetDefault( - ICONSCOMSTR="\tICONS\t${TARGET}", - PROTOCOMSTR="\tPROTO\t${SOURCE}", - DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}", - RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}", - PBVERCOMSTR="\tPBVER\t${TARGET}", - ) - -# Gathering icons sources -icons_src = assetsenv.GlobRecursive("*.png", "icons") -icons_src += assetsenv.GlobRecursive("frame_rate", "icons") - -icons = assetsenv.IconBuilder( - assetsenv.Dir("compiled"), ICON_SRC_DIR=assetsenv.Dir("#/assets/icons") +icons = assetsenv.CompileIcons( + assetsenv.Dir("compiled"), assetsenv.Dir("#/assets/icons") ) -assetsenv.Depends(icons, icons_src) assetsenv.Alias("icons", icons) # Protobuf .proto -> .c + .h - proto_src = assetsenv.Glob("protobuf/*.proto", source=True) proto_options = assetsenv.Glob("protobuf/*.options", source=True) proto = assetsenv.ProtoBuilder(assetsenv.Dir("compiled"), proto_src) diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_0.png b/assets/dolphin/external/L1_Painting_128x64/frame_0.png new file mode 100644 index 00000000..b2f9bc77 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_1.png b/assets/dolphin/external/L1_Painting_128x64/frame_1.png new file mode 100644 index 00000000..02ac533c Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_10.png b/assets/dolphin/external/L1_Painting_128x64/frame_10.png new file mode 100644 index 00000000..ae3148c3 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_11.png b/assets/dolphin/external/L1_Painting_128x64/frame_11.png new file mode 100644 index 00000000..89d003d0 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_2.png b/assets/dolphin/external/L1_Painting_128x64/frame_2.png new file mode 100644 index 00000000..8bfe6b33 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_3.png b/assets/dolphin/external/L1_Painting_128x64/frame_3.png new file mode 100644 index 00000000..1c6fc214 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_4.png b/assets/dolphin/external/L1_Painting_128x64/frame_4.png new file mode 100644 index 00000000..d39cddea Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_5.png b/assets/dolphin/external/L1_Painting_128x64/frame_5.png new file mode 100644 index 00000000..4f21a268 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_6.png b/assets/dolphin/external/L1_Painting_128x64/frame_6.png new file mode 100644 index 00000000..3f492eab Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_7.png b/assets/dolphin/external/L1_Painting_128x64/frame_7.png new file mode 100644 index 00000000..336cffcb Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_8.png b/assets/dolphin/external/L1_Painting_128x64/frame_8.png new file mode 100644 index 00000000..a44a7315 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_9.png b/assets/dolphin/external/L1_Painting_128x64/frame_9.png new file mode 100644 index 00000000..7cd42529 Binary files /dev/null and b/assets/dolphin/external/L1_Painting_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/meta.txt b/assets/dolphin/external/L1_Painting_128x64/meta.txt new file mode 100644 index 00000000..6964b479 --- /dev/null +++ b/assets/dolphin/external/L1_Painting_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 9 +Active frames: 13 +Frames order: 0 1 2 3 4 5 2 3 4 10 6 7 8 7 8 7 8 7 8 9 10 11 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 1 + +Slot: 0 +X: 57 +Y: 24 +Text: No mistakes, +AlignH: Left +AlignV: Center +StartFrame: 11 +EndFrame: 14 + +Slot: 0 +X: 57 +Y: 21 +Text: only happy\n accidents +AlignH: Left +AlignV: Center +StartFrame: 15 +EndFrame: 18 \ No newline at end of file diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 19706067..6bf6957c 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -85,6 +85,13 @@ Min level: 1 Max level: 3 Weight: 3 +Name: L1_Painting_128x64 +Min butthurt: 0 +Max butthurt: 7 +Min level: 1 +Max level: 3 +Weight: 6 + Name: L3_Hijack_radio_128x64 Min butthurt: 0 Max butthurt: 8 diff --git a/assets/icons/Interface/SmallArrowDown_3x5.png b/assets/icons/Interface/SmallArrowDown_3x5.png new file mode 100644 index 00000000..1912e5d2 Binary files /dev/null and b/assets/icons/Interface/SmallArrowDown_3x5.png differ diff --git a/assets/icons/Interface/SmallArrowUp_3x5.png b/assets/icons/Interface/SmallArrowUp_3x5.png new file mode 100644 index 00000000..9c624207 Binary files /dev/null and b/assets/icons/Interface/SmallArrowUp_3x5.png differ diff --git a/assets/icons/NFC/Modern_reader_18x34.png b/assets/icons/NFC/Modern_reader_18x34.png new file mode 100644 index 00000000..b19c0f30 Binary files /dev/null and b/assets/icons/NFC/Modern_reader_18x34.png differ diff --git a/assets/icons/NFC/Move_flipper_26x39.png b/assets/icons/NFC/Move_flipper_26x39.png new file mode 100644 index 00000000..ff4af9ff Binary files /dev/null and b/assets/icons/NFC/Move_flipper_26x39.png differ diff --git a/assets/icons/NFC/Release_arrow_18x15.png b/assets/icons/NFC/Release_arrow_18x15.png new file mode 100644 index 00000000..187a9034 Binary files /dev/null and b/assets/icons/NFC/Release_arrow_18x15.png differ diff --git a/assets/resources/badusb/demo_windows.txt b/assets/resources/badusb/demo_windows.txt index df435351..f304f5e8 100644 --- a/assets/resources/badusb/demo_windows.txt +++ b/assets/resources/badusb/demo_windows.txt @@ -78,7 +78,7 @@ ENTER STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script format ENTER -STRING More information about script synax can be found here: +STRING More information about script syntax can be found here: ENTER STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript ENTER diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_0.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_0.bm new file mode 100644 index 00000000..2694219e Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_0.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_1.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_1.bm new file mode 100644 index 00000000..3c9623d4 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_1.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_10.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_10.bm new file mode 100644 index 00000000..64a750e9 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_10.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_11.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_11.bm new file mode 100644 index 00000000..af1503fe Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_11.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_2.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_2.bm new file mode 100644 index 00000000..13916806 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_2.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_3.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_3.bm new file mode 100644 index 00000000..751fbc3e Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_3.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_4.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_4.bm new file mode 100644 index 00000000..c1135b46 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_4.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_5.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_5.bm new file mode 100644 index 00000000..a4681af9 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_5.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_6.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_6.bm new file mode 100644 index 00000000..36f2d084 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_6.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_7.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_7.bm new file mode 100644 index 00000000..9759e787 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_7.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_8.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_8.bm new file mode 100644 index 00000000..244adf31 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_8.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/frame_9.bm b/assets/resources/dolphin/L1_Painting_128x64/frame_9.bm new file mode 100644 index 00000000..99ed5071 Binary files /dev/null and b/assets/resources/dolphin/L1_Painting_128x64/frame_9.bm differ diff --git a/assets/resources/dolphin/L1_Painting_128x64/meta.txt b/assets/resources/dolphin/L1_Painting_128x64/meta.txt new file mode 100644 index 00000000..e5f5fc0a --- /dev/null +++ b/assets/resources/dolphin/L1_Painting_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 9 +Active frames: 13 +Frames order: 0 1 2 3 4 5 2 3 4 10 6 7 8 7 8 7 8 7 8 9 10 11 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 1 + +Slot: 0 +X: 57 +Y: 24 +Text: No mistakes, +AlignH: Left +AlignV: Center +StartFrame: 11 +EndFrame: 14 + +Slot: 0 +X: 57 +Y: 21 +Text: only happy\n accidents +AlignH: Left +AlignV: Center +StartFrame: 15 +EndFrame: 18 diff --git a/assets/resources/dolphin/manifest.txt b/assets/resources/dolphin/manifest.txt index 19706067..6bf6957c 100644 --- a/assets/resources/dolphin/manifest.txt +++ b/assets/resources/dolphin/manifest.txt @@ -85,6 +85,13 @@ Min level: 1 Max level: 3 Weight: 3 +Name: L1_Painting_128x64 +Min butthurt: 0 +Max butthurt: 7 +Min level: 1 +Max level: 3 +Weight: 6 + Name: L3_Hijack_radio_128x64 Min butthurt: 0 Max butthurt: 8 diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index 7866febc..97c38459 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -74,3 +74,41 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 8972 4491 592 1651 592 1655 598 532 599 535 597 542 600 541 601 544 598 1656 597 526 595 1652 591 1658 595 539 593 545 597 545 597 546 596 537 594 529 592 535 596 1653 600 534 597 541 601 539 592 552 600 533 598 525 596 530 591 538 593 539 592 1665 598 1662 591 1673 601 533 598 526 595 533 598 532 600 534 597 540 591 548 594 550 592 542 600 523 598 528 593 536 595 537 594 543 599 542 600 543 599 517 594 7937 593 531 601 526 595 535 597 537 594 542 600 541 601 543 599 1654 599 523 598 528 593 536 596 538 594 542 600 541 590 552 600 532 599 524 597 528 593 536 595 537 595 541 601 539 593 551 591 542 600 522 599 527 594 536 595 537 594 543 599 540 591 552 600 532 600 523 598 527 594 535 596 537 595 542 600 540 591 552 600 532 600 523 598 528 593 536 595 538 593 543 599 541 601 543 599 535 596 527 594 532 600 531 601 534 597 540 592 549 593 552 600 534 597 525 596 529 592 1655 598 534 597 1656 597 1661 592 1671 592 1644 599 7934 596 529 592 535 597 535 597 538 593 544 598 543 599 545 597 538 593 1650 593 535 596 534 597 536 595 540 591 547 595 547 595 536 595 526 595 529 592 536 595 535 596 539 593 546 596 547 595 538 593 528 593 531 601 529 592 541 601 536 596 545 597 548 594 540 592 532 600 526 595 535 596 1656 597 541 601 540 592 553 599 534 597 526 595 532 599 531 600 533 598 539 593 548 594 552 600 535 596 1647 596 531 590 538 593 1656 597 538 594 545 597 545 597 518 593 +# +# Model: Daichi DA25AVQS1-W +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9131 4318 815 389 817 1523 784 391 815 1523 784 1494 813 422 784 391 816 421 785 1524 784 392 814 422 783 1525 782 424 782 422 784 422 784 422 784 396 809 423 783 422 782 423 783 423 783 1496 812 1525 782 424 783 423 783 422 783 423 783 394 811 1526 782 424 782 1524 782 423 783 423 782 1525 782 423 675 19938 810 425 781 424 674 502 811 423 675 531 675 531 675 531 676 530 675 531 675 531 675 502 704 530 675 530 676 530 676 502 704 530 676 530 676 530 675 530 675 530 676 530 675 530 676 530 676 529 677 529 677 529 677 530 677 529 677 1631 676 529 677 1630 678 1631 677 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9076 4455 677 1629 678 528 677 528 677 1630 677 529 677 530 676 530 676 531 675 531 675 531 675 531 675 531 674 531 675 532 674 531 674 532 674 531 675 532 674 531 674 531 674 532 674 1633 674 1633 674 532 674 532 674 532 674 532 674 532 674 1634 673 533 673 1634 673 533 674 532 674 1633 674 533 673 19965 674 531 674 532 675 531 675 531 675 531 675 531 675 531 675 531 675 532 674 531 675 531 676 531 674 531 675 531 675 531 674 531 675 531 675 532 674 532 674 531 675 532 674 532 674 531 675 531 675 532 674 532 674 532 674 532 674 1633 674 1633 674 532 674 532 674 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9076 4453 679 1628 703 503 703 503 702 1607 700 506 699 507 699 507 699 507 699 1609 698 1610 698 1609 699 507 699 508 698 508 698 508 698 508 698 508 698 507 699 508 698 508 698 508 697 1609 698 1610 698 508 698 508 698 508 698 508 698 509 697 1610 697 508 698 1610 698 508 698 508 698 1610 697 509 697 19941 699 507 699 507 699 507 699 508 698 508 698 508 698 508 698 508 697 508 698 508 698 507 699 508 698 508 698 508 698 508 698 508 698 508 698 508 697 509 697 509 697 508 698 508 698 508 698 508 698 509 697 508 697 509 697 509 696 509 697 1635 673 533 673 1611 696 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 148 110377 9082 4422 707 499 706 500 704 1603 703 1606 701 505 700 507 699 506 700 507 699 506 700 1607 700 1608 700 1609 699 506 699 507 699 506 699 507 699 507 699 506 700 507 699 507 699 507 699 1608 699 1607 699 507 699 507 699 507 699 507 699 507 699 1609 699 507 699 1608 699 507 699 507 699 1609 699 507 699 19940 700 506 700 506 699 507 699 507 699 506 700 506 700 507 699 507 699 507 700 507 699 506 699 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 698 507 700 507 699 507 699 507 699 507 699 507 699 508 698 508 698 507 699 507 699 508 698 1610 699 508 698 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9081 4423 707 499 706 500 704 1604 702 1606 701 505 701 506 700 506 700 506 700 1608 700 1607 700 1609 699 506 700 506 700 506 700 506 700 506 700 507 699 506 700 506 700 507 699 507 699 1608 700 1608 699 507 699 507 699 507 699 507 699 507 699 1608 699 507 698 1609 698 507 699 507 699 1609 699 507 699 19938 699 506 700 506 700 507 699 506 699 506 700 506 699 506 700 507 699 507 699 507 700 506 699 507 699 507 699 507 699 507 699 507 698 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 700 507 699 507 698 507 699 507 699 1609 699 507 698 1609 699 1609 699 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9106 4398 731 499 706 500 705 502 702 504 701 505 701 505 701 1606 701 505 701 1607 701 505 701 506 700 1607 700 506 700 506 700 505 700 505 701 506 700 506 700 506 699 506 700 506 700 1607 700 506 700 506 700 506 700 505 701 506 700 506 700 1608 699 506 700 1608 699 506 700 506 700 1608 700 506 700 19941 701 1606 700 505 701 505 701 506 700 505 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 701 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 699 506 700 506 700 1608 700 1607 700 506 700 506 700 + diff --git a/documentation/AppManifests.md b/documentation/AppManifests.md index 0a4f5e9b..c7c73110 100644 --- a/documentation/AppManifests.md +++ b/documentation/AppManifests.md @@ -30,7 +30,7 @@ Only 2 parameters are mandatory: ***appid*** and ***apptype***, others are optio | METAPACKAGE | Does not define any code to be run, used for declaring dependencies and application bundles | * **name**: Name that is displayed in menus. -* **entry_point**: C function to be used as application's entry point. +* **entry_point**: C function to be used as application's entry point. Note that C++ function names are mangled, so you need to wrap them in `extern "C"` in order to use them as entry points. * **flags**: Internal flags for system apps. Do not use. * **cdefines**: C preprocessor definitions to declare globally for other apps when current application is included in active build configuration. * **requires**: List of application IDs to also include in build configuration, when current application is referenced in list of applications to build. @@ -41,16 +41,71 @@ Only 2 parameters are mandatory: ***appid*** and ***apptype***, others are optio * **order**: Order of an application within its group when sorting entries in it. The lower the order is, the closer to the start of the list the item is placed. *Used for ordering startup hooks and menu entries.* * **sdk_headers**: List of C header files from this app's code to include in API definitions for external applications. + +#### Parameters for external applications + The following parameters are used only for [FAPs](./AppsOnSDCard.md): -* **sources**: list of strings, file name masks, used for gathering sources within app folder. Default value of `["*.c*"]` includes C and CPP source files. -* **fap_version**: tuple, 2 numbers in form of (x,y): application version to be embedded within .fap file. Default value is (0,1), meanig version "0.1". +* **sources**: list of strings, file name masks, used for gathering sources within app folder. Default value of `["*.c*"]` includes C and C++ source files. Application cannot use `"lib"` folder for their own source code, as it is reserved for **fap_private_libs**. +* **fap_version**: tuple, 2 numbers in form of (x,y): application version to be embedded within .fap file. Default value is (0,1), meaning version "0.1". * **fap_icon**: name of a .png file, 1-bit color depth, 10x10px, to be embedded within .fap file. * **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption. * **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system. * **fap_description**: string, may be empty. Short application description. * **fap_author**: string, may be empty. Application's author. * **fap_weburl**: string, may be empty. Application's homepage. +* **fap_icon_assets**: string. If present, defines a folder name to be used for gathering image assets for this application. These images will be preprocessed and built alongside the application. See [FAP assets](./AppsOnSDCard.md#fap-assets) for details. +* **fap_extbuild**: provides support for parts of application sources to be built by external tools. Contains a list of `ExtFile(path="file name", command="shell command")` definitions. **`fbt`** will run the specified command for each file in the list. +Note that commands are executed at the firmware root folder's root, and all intermediate files must be placed in a application's temporary build folder. For that, you can use pattern expansion by **`fbt`**: `${FAP_WORK_DIR}` will be replaced with the path to the application's temporary build folder, and `${FAP_SRC_DIR}` will be replaced with the path to the application's source folder. You can also use other variables defined internally by **`fbt`**. + +Example for building an app from Rust sources: + +```python + sources=["target/thumbv7em-none-eabihf/release/libhello_rust.a"], + fap_extbuild=( + ExtFile( + path="${FAP_WORK_DIR}/target/thumbv7em-none-eabihf/release/libhello_rust.a", + command="cargo build --release --verbose --target thumbv7em-none-eabihf --target-dir ${FAP_WORK_DIR}/target --manifest-path ${FAP_SRC_DIR}/Cargo.toml", + ), + ), +``` + +* **fap_private_libs**: list of additional libraries that are distributed as sources alongside the application. These libraries will be built as a part of the application build process. +Library sources must be placed in a subfolder of "`lib`" folder within the application's source folder. +Each library is defined as a call to `Lib()` function, accepting the following parameters: + + - **name**: name of library's folder. Required. + - **fap_include_paths**: list of library's relative paths to add to parent fap's include path list. Default value is `["."]` meaning library's source root. + - **sources**: list of filename masks to be used for gathering include files for this library. Default value is `["*.c*"]`. + - **cflags**: list of additional compiler flags to be used for building this library. Default value is `[]`. + - **cdefines**: list of additional preprocessor definitions to be used for building this library. Default value is `[]`. + - **cincludes**: list of additional include paths to be used for building this library. Can be used for providing external search paths for this library's code - for configuration headers. Default value is `[]`. + +Example for building an app with a private library: + +```python + fap_private_libs=[ + Lib( + name="mbedtls", + fap_include_paths=["include"], + sources=[ + "library/des.c", + "library/sha1.c", + "library/platform_util.c", + ], + cdefines=["MBEDTLS_ERROR_C"], + ), + Lib( + name="loclass", + cflags=["-Wno-error"], + ), + ], +``` + +For that snippet, **`fbt`** will build 2 libraries: one from sources in `lib/mbedtls` folder, and another from sources in `lib/loclass` folder. For `mbedtls` library, **`fbt`** will add `lib/mbedtls/include` to the list of include paths for the application and compile only the files specified in `sources` list. Additionally, **`fbt`** will enable `MBEDTLS_ERROR_C` preprocessor definition for `mbedtls` sources. +For `loclass` library, **`fbt`** will add `lib/loclass` to the list of include paths for the application and build all sources in that folder. Also **`fbt`** will disable treating compiler warnings as errors for `loclass` library specifically - that can be useful when compiling large 3rd-party codebases. + +Both libraries will be linked into the application. ## .fam file contents diff --git a/documentation/AppsOnSDCard.md b/documentation/AppsOnSDCard.md index 52582153..4acb3ec3 100644 --- a/documentation/AppsOnSDCard.md +++ b/documentation/AppsOnSDCard.md @@ -2,7 +2,7 @@ [fbt](./fbt.md) has support for building applications as FAP files. FAP are essentially .elf executables with extra metadata and resources bundled in. -FAPs are built with `firmware_extapps` (or `plugin_dist`) **`fbt`** targets. +FAPs are built with `faps` target. They can also be deployed to `dist` folder with `fap_dist` target. FAPs do not depend on being run on a specific firmware version. Compatibility is determined by the FAP's metadata, which includes the required [API version](#api-versioning). @@ -13,9 +13,20 @@ FAPs are created and developed the same way as internal applications that are pa To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. - * To build your application, run `./fbt firmware_{APPID}`, where APPID is your application's ID in its manifest. + * To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest. * To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu). - * To build all FAPs, run `./fbt plugin_dist`. + * To build all FAPs, run `./fbt faps` or `./fbt fap_dist`. + + +## FAP assets + +FAPs can include static and animated images as private assets. They will be automatically compiled alongside application sources and can be referenced the same way as assets from the main firmware. + +To use that feature, put your images in a subfolder inside your application's folder, then reference that folder in your application's manifest in `fap_icon_assets` field. See [Application Manifests](./AppManifests.md#application-definition) for more details. + +To use these assets in your application, put `#include "{APPID}_icons.h"` in your application's source code, where `{APPID}` is the `appid` value field from your application's manifest. Then you can use all icons from your application's assets the same way as if they were a part of `assets_icons.h` of the main firmware. + +Images and animated icons must follow the same [naming convention](../assets/ReadMe.md#asset-naming-rules) as those from the main firmware. ## Debugging FAPs @@ -53,13 +64,13 @@ App loader allocates memory for the application and copies it to RAM, processing Not all parts of firmware are available for external applications. A subset of available functions and variables is defined in "api_symbols.csv" file, which is a part of firmware target definition in `firmware/targets/` directory. -**`fbt`** uses semantic versioning for API versioning. Major version is incremented when there are breaking changes in the API, minor version is incremented when there are new features added. +**`fbt`** uses semantic versioning for API. Major version is incremented when there are breaking changes in the API, minor version is incremented when new features are added. Breaking changes include: - removal of a function or a global variable; - changing the signature of a function. -API versioning is mostly automated by **`fbt`**. When rebuilding the firmware, **`fbt`** checks if there are any changes in the API exposed by headers gathered from `SDK_HEADERS`. If there are, it stops the build, adjusts the API version and asks the user to go through the changes in .csv file. New entries are marked with "`?`" mark, and the user is supposed to change the mark to "`+`" for the entry to be exposed for FAPs, "`-`" for it to be unavailable. +API versioning is mostly automated by **`fbt`**. When rebuilding the firmware, **`fbt`** checks if there are any changes in the API exposed by headers gathered from `SDK_HEADERS`. If so, it stops the build, adjusts the API version and asks the user to go through the changes in .csv file. New entries are marked with "`?`" mark, and the user is supposed to change the mark to "`+`" for the entry to be exposed for FAPs, "`-`" for it to be unavailable. **`fbt`** will not allow building a firmware until all "`?`" entries are changed to "`+`" or "`-`". diff --git a/documentation/fbt.md b/documentation/fbt.md index 090ff78f..3fac7ce7 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -43,7 +43,7 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. ### High-level (what you most likely need) - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified -- `plugin_dist` - build external plugins & publish to `dist` folder +- `fap_dist` - build external plugins & publish to `dist` folder - `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper - `flash` - flash attached device with OpenOCD over ST-Link @@ -56,13 +56,15 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration - `lint`, `format` - run clang-format on C source code to check and reformat it according to `.clang-format` specs - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on Python source code, build system files & application manifests +- `cli` - start Flipper CLI session over USB ### Firmware targets -- `firmware_extapps` - build all plug-ins as separate .elf files - - `firmware_snake_game`, etc - build single plug-in as .elf by its name - - Check out `--extra-ext-apps` for force adding extra apps to external build - - `firmware_snake_game_list`, etc - generate source + assembler listing for app's .elf +- `faps` - build all external & plugin apps as [.faps](./AppsOnSDCard.md#fap-flipper-application-package). +- **`fbt`** also defines per-app targets. For example, for an app with `appid=snake_game` target names are: + - `fap_snake_game`, etc - build single app as .fap by its application ID. + - Check out [`--extra-ext-apps`](#command-line-parameters) for force adding extra apps to external build + - `fap_snake_game_list`, etc - generate source + assembler listing for app's .fap - `flash`, `firmware_flash` - flash current version to attached device with OpenOCD over ST-Link - `jflash` - flash current version to attached device with JFlash using J-Link probe. JFlash executable must be on your $PATH - `flash_blackmagic` - flash current version to attached device with Blackmagic probe @@ -83,9 +85,9 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. ## Command-line parameters - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values -- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, **`fbt`** now has specific handling for updater-related targets_ - `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target +- `--proxy-env=VAR1,VAR2` - additional environment variables to expose to subprocesses spawned by `fbt`. By default, `fbt` sanitizes execution environment and doesn't forward all inherited environment variables. You can find list of variables that are always forwarded in `environ.scons` file. ## Configuration diff --git a/firmware.scons b/firmware.scons index 0970541e..d28309d0 100644 --- a/firmware.scons +++ b/firmware.scons @@ -1,8 +1,9 @@ Import("ENV", "fw_build_meta") +from SCons.Errors import UserError import itertools -from fbt.util import ( +from fbt_extra.util import ( should_gen_cdb_and_link_dir, link_elf_dir_as_latest, ) @@ -140,6 +141,10 @@ else: if extra_int_apps := GetOption("extra_int_apps"): fwenv.Append(APPS=extra_int_apps.split(",")) + +if fwenv["FAP_EXAMPLES"]: + fwenv.Append(APPDIRS=[("applications/examples", False)]) + fwenv.LoadApplicationManifests() fwenv.PrepareApplicationsBuild() @@ -164,13 +169,25 @@ apps_c = fwenv.ApplicationsC( # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed for app_dir, _ in env["APPDIRS"]: app_dir_node = env.Dir("#").Dir(app_dir) - fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", app_dir_node)) + fwenv.Depends(apps_c, app_dir_node.glob("*/application.fam")) + +# Sanity check - certain external apps are using features that are not available in base firmware +if advanced_faps := list( + filter( + lambda app: app.fap_extbuild or app.fap_private_libs or app.fap_icon_assets, + fwenv["APPBUILD"].get_builtin_apps(), + ) +): + raise UserError( + "An Application that is using fap-specific features cannot be built into base firmware." + f" Offending app(s): {', '.join(app.appid for app in advanced_faps)}" + ) sources = [apps_c] # Gather sources only from app folders in current configuration sources.extend( itertools.chain.from_iterable( - fwenv.GlobRecursive(source_type, appdir.relpath) + fwenv.GlobRecursive(source_type, appdir.relpath, exclude="lib") for appdir, source_type in fwenv["APPBUILD"].get_builtin_app_folders() ) ) @@ -259,18 +276,18 @@ fw_artifacts = fwenv["FW_ARTIFACTS"] = [ fwenv["FW_VERSION_JSON"], ] + +fwcdb = fwenv.CompilationDatabase() +# without filtering, both updater & firmware commands would be generated in same file +fwenv.Replace(COMPILATIONDB_PATH_FILTER=fwenv.subst("*${FW_FLAVOR}*")) +AlwaysBuild(fwcdb) +Precious(fwcdb) +NoClean(fwcdb) +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) + # If current configuration was explicitly requested, generate compilation database # and link its directory as build/latest if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): - fwcdb = fwenv.CompilationDatabase() - # without filtering, both updater & firmware commands would be generated - fwenv.Replace(COMPILATIONDB_PATH_FILTER=fwenv.subst("*${FW_FLAVOR}*")) - AlwaysBuild(fwcdb) - Precious(fwcdb) - NoClean(fwcdb) - Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) - AlwaysBuild(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) - Alias(fwcdb, "") fw_artifacts.append(fwcdb) # Adding as a phony target, so folder link is updated even if elf didn't change @@ -303,10 +320,13 @@ if fwenv["IS_BASE_FIRMWARE"]: "-D__inline__=inline", ], ) - Depends(sdk_source, (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"])) + # Depends(sdk_source, (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"])) + Depends(sdk_source, fwenv.ProcessSdkDepends("sdk_origin.d")) - sdk_tree = fwenv.SDKTree("sdk/sdk.opts", "sdk_origin") - AlwaysBuild(sdk_tree) + fwenv["SDK_DIR"] = fwenv.Dir("sdk") + sdk_tree = fwenv.SDKTree(fwenv["SDK_DIR"], "sdk_origin") + fw_artifacts.append(sdk_tree) + # AlwaysBuild(sdk_tree) Alias("sdk_tree", sdk_tree) sdk_apicheck = fwenv.SDKSymUpdater(fwenv.subst("$SDK_DEFINITION"), "sdk_origin") @@ -316,7 +336,7 @@ if fwenv["IS_BASE_FIRMWARE"]: Alias("sdk_check", sdk_apicheck) sdk_apisyms = fwenv.SDKSymGenerator( - "assets/compiled/symbols.h", fwenv.subst("$SDK_DEFINITION") + "assets/compiled/symbols.h", fwenv["SDK_DEFINITION"] ) Alias("api_syms", sdk_apisyms) diff --git a/firmware/targets/f7/Src/update.c b/firmware/targets/f7/Src/update.c index 36204829..722a7b61 100644 --- a/firmware/targets/f7/Src/update.c +++ b/firmware/targets/f7/Src/update.c @@ -54,20 +54,21 @@ static bool flipper_update_init() { return flipper_update_mount_sd(); } -static bool flipper_update_load_stage(const string_t work_dir, UpdateManifest* manifest) { +static bool flipper_update_load_stage(const FuriString* work_dir, UpdateManifest* manifest) { FIL file; FILINFO stat; - string_t loader_img_path; - string_init_set(loader_img_path, work_dir); - path_append(loader_img_path, string_get_cstr(manifest->staged_loader_file)); + FuriString* loader_img_path; + loader_img_path = furi_string_alloc_set(work_dir); + path_append(loader_img_path, furi_string_get_cstr(manifest->staged_loader_file)); - if((f_stat(string_get_cstr(loader_img_path), &stat) != FR_OK) || - (f_open(&file, string_get_cstr(loader_img_path), FA_OPEN_EXISTING | FA_READ) != FR_OK)) { - string_clear(loader_img_path); + if((f_stat(furi_string_get_cstr(loader_img_path), &stat) != FR_OK) || + (f_open(&file, furi_string_get_cstr(loader_img_path), FA_OPEN_EXISTING | FA_READ) != + FR_OK)) { + furi_string_free(loader_img_path); return false; } - string_clear(loader_img_path); + furi_string_free(loader_img_path); void* img = malloc(stat.fsize); uint32_t bytes_read = 0; @@ -110,13 +111,13 @@ static bool flipper_update_load_stage(const string_t work_dir, UpdateManifest* m return false; } -static bool flipper_update_get_manifest_path(string_t out_path) { +static bool flipper_update_get_manifest_path(FuriString* out_path) { FIL file; FILINFO stat; uint16_t size_read = 0; char manifest_name_buf[UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN] = {0}; - string_reset(out_path); + furi_string_reset(out_path); CHECK_FRESULT(f_stat(UPDATE_POINTER_FILE_PATH, &stat)); CHECK_FRESULT(f_open(&file, UPDATE_POINTER_FILE_PATH, FA_OPEN_EXISTING | FA_READ)); do { @@ -128,19 +129,19 @@ static bool flipper_update_get_manifest_path(string_t out_path) { if((size_read == 0) || (size_read == UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) { break; } - string_set_str(out_path, manifest_name_buf); - string_right(out_path, strlen(STORAGE_EXT_PATH_PREFIX)); + furi_string_set(out_path, manifest_name_buf); + furi_string_right(out_path, strlen(STORAGE_EXT_PATH_PREFIX)); } while(0); f_close(&file); - return !string_empty_p(out_path); + return !furi_string_empty(out_path); } -static UpdateManifest* flipper_update_process_manifest(const string_t manifest_path) { +static UpdateManifest* flipper_update_process_manifest(const FuriString* manifest_path) { FIL file; FILINFO stat; - CHECK_FRESULT(f_stat(string_get_cstr(manifest_path), &stat)); - CHECK_FRESULT(f_open(&file, string_get_cstr(manifest_path), FA_OPEN_EXISTING | FA_READ)); + CHECK_FRESULT(f_stat(furi_string_get_cstr(manifest_path), &stat)); + CHECK_FRESULT(f_open(&file, furi_string_get_cstr(manifest_path), FA_OPEN_EXISTING | FA_READ)); uint8_t* manifest_data = malloc(stat.fsize); uint32_t bytes_read = 0; @@ -177,9 +178,9 @@ void flipper_boot_update_exec() { return; } - string_t work_dir, manifest_path; - string_init(work_dir); - string_init(manifest_path); + FuriString* work_dir = furi_string_alloc(); + FuriString* manifest_path = furi_string_alloc(); + do { if(!flipper_update_get_manifest_path(manifest_path)) { break; @@ -190,12 +191,12 @@ void flipper_boot_update_exec() { break; } - path_extract_dirname(string_get_cstr(manifest_path), work_dir); + path_extract_dirname(furi_string_get_cstr(manifest_path), work_dir); if(!flipper_update_load_stage(work_dir, manifest)) { update_manifest_free(manifest); } } while(false); - string_clear(manifest_path); - string_clear(work_dir); + furi_string_free(manifest_path); + furi_string_free(work_dir); free(pfs); } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 2cbdae77..c9e2371f 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.13,, +Version,+,2.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -440,12 +440,12 @@ Function,-,arc4random,__uint32_t, Function,-,arc4random_buf,void,"void*, size_t" Function,-,arc4random_uniform,__uint32_t,__uint32_t Function,+,args_char_to_hex,_Bool,"char, char, uint8_t*" -Function,+,args_get_first_word_length,size_t,string_t -Function,+,args_length,size_t,string_t -Function,+,args_read_hex_bytes,_Bool,"string_t, uint8_t*, size_t" -Function,+,args_read_int_and_trim,_Bool,"string_t, int*" -Function,+,args_read_probably_quoted_string_and_trim,_Bool,"string_t, string_t" -Function,+,args_read_string_and_trim,_Bool,"string_t, string_t" +Function,+,args_get_first_word_length,size_t,FuriString* +Function,+,args_length,size_t,FuriString* +Function,+,args_read_hex_bytes,_Bool,"FuriString*, uint8_t*, size_t" +Function,+,args_read_int_and_trim,_Bool,"FuriString*, int*" +Function,+,args_read_probably_quoted_string_and_trim,_Bool,"FuriString*, FuriString*" +Function,+,args_read_string_and_trim,_Bool,"FuriString*, FuriString*" Function,-,asin,double,double Function,-,asinf,float,float Function,-,asinh,double,double @@ -642,7 +642,7 @@ Function,+,dialog_ex_set_result_callback,void,"DialogEx*, DialogExResultCallback Function,+,dialog_ex_set_right_button_text,void,"DialogEx*, const char*" Function,+,dialog_ex_set_text,void,"DialogEx*, const char*, uint8_t, uint8_t, Align, Align" Function,+,dialog_file_browser_set_basic_options,void,"DialogsFileBrowserOptions*, const char*, const Icon*" -Function,+,dialog_file_browser_show,_Bool,"DialogsApp*, string_ptr, string_ptr, const DialogsFileBrowserOptions*" +Function,+,dialog_file_browser_show,_Bool,"DialogsApp*, FuriString*, FuriString*, const DialogsFileBrowserOptions*" Function,+,dialog_message_alloc,DialogMessage*, Function,+,dialog_message_free,void,DialogMessage* Function,+,dialog_message_set_buttons,void,"DialogMessage*, const char*, const char*, const char*" @@ -665,7 +665,7 @@ Function,+,dir_walk_close,void,DirWalk* Function,+,dir_walk_free,void,DirWalk* Function,+,dir_walk_get_error,FS_Error,DirWalk* Function,+,dir_walk_open,_Bool,"DirWalk*, const char*" -Function,+,dir_walk_read,DirWalkResult,"DirWalk*, string_t, FileInfo*" +Function,+,dir_walk_read,DirWalkResult,"DirWalk*, FuriString*, FileInfo*" Function,+,dir_walk_set_filter_cb,void,"DirWalk*, DirWalkFilterCb, void*" Function,+,dir_walk_set_recursive,void,"DirWalk*, _Bool" Function,-,div,div_t,"int, int" @@ -698,7 +698,7 @@ Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t" Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t" Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_slightly_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" -Function,+,elements_string_fit_width,void,"Canvas*, string_t, uint8_t" +Function,+,elements_string_fit_width,void,"Canvas*, FuriString*, uint8_t" Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool" Function,+,empty_screen_alloc,EmptyScreen*, Function,+,empty_screen_free,void,EmptyScreen* @@ -746,22 +746,22 @@ Function,-,fgetc_unlocked,int,FILE* Function,-,fgetpos,int,"FILE*, fpos_t*" Function,-,fgets,char*,"char*, int, FILE*" Function,-,fgets_unlocked,char*,"char*, int, FILE*" -Function,+,file_browser_alloc,FileBrowser*,string_ptr +Function,+,file_browser_alloc,FileBrowser*,FuriString* Function,+,file_browser_configure,void,"FileBrowser*, const char*, _Bool, const Icon*, _Bool" Function,+,file_browser_free,void,FileBrowser* Function,+,file_browser_get_view,View*,FileBrowser* Function,+,file_browser_set_callback,void,"FileBrowser*, FileBrowserCallback, void*" Function,+,file_browser_set_item_callback,void,"FileBrowser*, FileBrowserLoadItemCallback, void*" -Function,+,file_browser_start,void,"FileBrowser*, string_t" +Function,+,file_browser_start,void,"FileBrowser*, FuriString*" Function,+,file_browser_stop,void,FileBrowser* -Function,+,file_browser_worker_alloc,BrowserWorker*,"string_t, const char*, _Bool" -Function,+,file_browser_worker_folder_enter,void,"BrowserWorker*, string_t, int32_t" +Function,+,file_browser_worker_alloc,BrowserWorker*,"FuriString*, const char*, _Bool" +Function,+,file_browser_worker_folder_enter,void,"BrowserWorker*, FuriString*, int32_t" Function,+,file_browser_worker_folder_exit,void,BrowserWorker* Function,+,file_browser_worker_folder_refresh,void,"BrowserWorker*, int32_t" Function,+,file_browser_worker_free,void,BrowserWorker* Function,+,file_browser_worker_load,void,"BrowserWorker*, uint32_t, uint32_t" Function,+,file_browser_worker_set_callback_context,void,"BrowserWorker*, void*" -Function,+,file_browser_worker_set_config,void,"BrowserWorker*, string_t, const char*, _Bool" +Function,+,file_browser_worker_set_config,void,"BrowserWorker*, FuriString*, const char*, _Bool" Function,+,file_browser_worker_set_folder_callback,void,"BrowserWorker*, BrowserWorkerFolderOpenCallback" Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback" Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback" @@ -806,17 +806,17 @@ Function,+,flipper_format_insert_or_update_bool,_Bool,"FlipperFormat*, const cha Function,+,flipper_format_insert_or_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" Function,+,flipper_format_insert_or_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" Function,+,flipper_format_insert_or_update_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" -Function,+,flipper_format_insert_or_update_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_insert_or_update_string,_Bool,"FlipperFormat*, const char*, FuriString*" Function,+,flipper_format_insert_or_update_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" Function,+,flipper_format_insert_or_update_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" Function,+,flipper_format_key_exist,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_read_bool,_Bool,"FlipperFormat*, const char*, _Bool*, const uint16_t" Function,+,flipper_format_read_float,_Bool,"FlipperFormat*, const char*, float*, const uint16_t" -Function,+,flipper_format_read_header,_Bool,"FlipperFormat*, string_t, uint32_t*" +Function,+,flipper_format_read_header,_Bool,"FlipperFormat*, FuriString*, uint32_t*" Function,+,flipper_format_read_hex,_Bool,"FlipperFormat*, const char*, uint8_t*, const uint16_t" Function,+,flipper_format_read_hex_uint64,_Bool,"FlipperFormat*, const char*, uint64_t*, const uint16_t" Function,+,flipper_format_read_int32,_Bool,"FlipperFormat*, const char*, int32_t*, const uint16_t" -Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, FuriString*" Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t" Function,+,flipper_format_rewind,_Bool,FlipperFormat* Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat* @@ -826,19 +826,19 @@ Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" Function,+,flipper_format_update_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" -Function,+,flipper_format_update_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_update_string,_Bool,"FlipperFormat*, const char*, FuriString*" Function,+,flipper_format_update_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" Function,+,flipper_format_update_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" -Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, string_t" +Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, FuriString*" Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" -Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, string_t, const uint32_t" +Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, FuriString*, const uint32_t" Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t" Function,+,flipper_format_write_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" Function,+,flipper_format_write_hex_uint64,_Bool,"FlipperFormat*, const char*, const uint64_t*, const uint16_t" Function,+,flipper_format_write_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" -Function,+,flipper_format_write_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_write_string,_Bool,"FlipperFormat*, const char*, FuriString*" Function,+,flipper_format_write_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" Function,+,flipper_format_write_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" Function,-,flockfile,void,FILE* @@ -899,7 +899,7 @@ Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, ui Function,+,furi_get_tick,uint32_t, Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*" Function,+,furi_hal_bt_clear_white_list,_Bool, -Function,+,furi_hal_bt_dump_state,void,string_t +Function,+,furi_hal_bt_dump_state,void,FuriString* Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*" Function,+,furi_hal_bt_get_radio_stack,FuriHalBtStack, @@ -1342,6 +1342,70 @@ Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t" Function,+,furi_semaphore_free,void,FuriSemaphore* Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore* Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore* +Function,+,furi_stream_buffer_alloc,FuriStreamBuffer*,"size_t, size_t" +Function,+,furi_stream_buffer_bytes_available,size_t,FuriStreamBuffer* +Function,+,furi_stream_buffer_free,void,FuriStreamBuffer* +Function,+,furi_stream_buffer_is_empty,_Bool,FuriStreamBuffer* +Function,+,furi_stream_buffer_is_full,_Bool,FuriStreamBuffer* +Function,+,furi_stream_buffer_receive,size_t,"FuriStreamBuffer*, void*, size_t, uint32_t" +Function,+,furi_stream_buffer_reset,FuriStatus,FuriStreamBuffer* +Function,+,furi_stream_buffer_send,size_t,"FuriStreamBuffer*, const void*, size_t, uint32_t" +Function,+,furi_stream_buffer_spaces_available,size_t,FuriStreamBuffer* +Function,+,furi_stream_set_trigger_level,_Bool,"FuriStreamBuffer*, size_t" +Function,+,furi_string_alloc,FuriString*, +Function,+,furi_string_alloc_move,FuriString*,FuriString* +Function,+,furi_string_alloc_printf,FuriString*,"const char[], ..." +Function,+,furi_string_alloc_set,FuriString*,const FuriString* +Function,+,furi_string_alloc_set_str,FuriString*,const char[] +Function,+,furi_string_alloc_vprintf,FuriString*,"const char[], va_list" +Function,+,furi_string_cat,void,"FuriString*, const FuriString*" +Function,+,furi_string_cat_printf,int,"FuriString*, const char[], ..." +Function,+,furi_string_cat_str,void,"FuriString*, const char[]" +Function,+,furi_string_cat_vprintf,int,"FuriString*, const char[], va_list" +Function,+,furi_string_cmp,int,"const FuriString*, const FuriString*" +Function,+,furi_string_cmp_str,int,"const FuriString*, const char[]" +Function,+,furi_string_cmpi,int,"const FuriString*, const FuriString*" +Function,+,furi_string_cmpi_str,int,"const FuriString*, const char[]" +Function,+,furi_string_empty,_Bool,const FuriString* +Function,+,furi_string_end_with,_Bool,"const FuriString*, const FuriString*" +Function,+,furi_string_end_with_str,_Bool,"const FuriString*, const char[]" +Function,+,furi_string_equal,_Bool,"const FuriString*, const FuriString*" +Function,+,furi_string_equal_str,_Bool,"const FuriString*, const char[]" +Function,+,furi_string_free,void,FuriString* +Function,+,furi_string_get_char,char,"const FuriString*, size_t" +Function,+,furi_string_get_cstr,const char*,const FuriString* +Function,+,furi_string_hash,size_t,const FuriString* +Function,+,furi_string_left,void,"FuriString*, size_t" +Function,+,furi_string_mid,void,"FuriString*, size_t, size_t" +Function,+,furi_string_move,void,"FuriString*, FuriString*" +Function,+,furi_string_printf,int,"FuriString*, const char[], ..." +Function,+,furi_string_push_back,void,"FuriString*, char" +Function,+,furi_string_replace,size_t,"FuriString*, FuriString*, FuriString*, size_t" +Function,+,furi_string_replace_all,void,"FuriString*, const FuriString*, const FuriString*" +Function,+,furi_string_replace_all_str,void,"FuriString*, const char[], const char[]" +Function,+,furi_string_replace_at,void,"FuriString*, size_t, size_t, const char[]" +Function,+,furi_string_replace_str,size_t,"FuriString*, const char[], const char[], size_t" +Function,+,furi_string_reserve,void,"FuriString*, size_t" +Function,+,furi_string_reset,void,FuriString* +Function,+,furi_string_right,void,"FuriString*, size_t" +Function,+,furi_string_search,size_t,"const FuriString*, const FuriString*, size_t" +Function,+,furi_string_search_char,size_t,"const FuriString*, char, size_t" +Function,+,furi_string_search_rchar,size_t,"const FuriString*, char, size_t" +Function,+,furi_string_search_str,size_t,"const FuriString*, const char[], size_t" +Function,+,furi_string_set,void,"FuriString*, FuriString*" +Function,+,furi_string_set_char,void,"FuriString*, size_t, const char" +Function,+,furi_string_set_n,void,"FuriString*, const FuriString*, size_t, size_t" +Function,+,furi_string_set_str,void,"FuriString*, const char[]" +Function,+,furi_string_set_strn,void,"FuriString*, const char[], size_t" +Function,+,furi_string_size,size_t,const FuriString* +Function,+,furi_string_start_with,_Bool,"const FuriString*, const FuriString*" +Function,+,furi_string_start_with_str,_Bool,"const FuriString*, const char[]" +Function,+,furi_string_swap,void,"FuriString*, FuriString*" +Function,+,furi_string_trim,void,"FuriString*, const char[]" +Function,+,furi_string_utf8_decode,void,"char, FuriStringUTF8State*, FuriStringUnicodeValue*" +Function,+,furi_string_utf8_length,size_t,FuriString* +Function,+,furi_string_utf8_push,void,"FuriString*, FuriStringUnicodeValue" +Function,+,furi_string_vprintf,int,"FuriString*, const char[], va_list" Function,+,furi_thread_alloc,FuriThread*, Function,+,furi_thread_catch,void, Function,-,furi_thread_disable_heap_trace,void,FuriThread* @@ -1684,14 +1748,14 @@ Function,+,onewire_slave_set_result_callback,void,"OneWireSlave*, OneWireSlaveRe Function,+,onewire_slave_start,void,OneWireSlave* Function,+,onewire_slave_stop,void,OneWireSlave* Function,-,open_memstream,FILE*,"char**, size_t*" -Function,+,path_append,void,"string_t, const char*" -Function,+,path_concat,void,"const char*, const char*, string_t" +Function,+,path_append,void,"FuriString*, const char*" +Function,+,path_concat,void,"const char*, const char*, FuriString*" Function,+,path_contains_only_ascii,_Bool,const char* -Function,+,path_extract_basename,void,"const char*, string_t" -Function,+,path_extract_dirname,void,"const char*, string_t" -Function,+,path_extract_extension,void,"string_t, char*, size_t" -Function,+,path_extract_filename,void,"string_t, string_t, _Bool" -Function,+,path_extract_filename_no_ext,void,"const char*, string_t" +Function,+,path_extract_basename,void,"const char*, FuriString*" +Function,+,path_extract_dirname,void,"const char*, FuriString*" +Function,+,path_extract_extension,void,"FuriString*, char*, size_t" +Function,+,path_extract_filename,void,"FuriString*, FuriString*, _Bool" +Function,+,path_extract_filename_no_ext,void,"const char*, FuriString*" Function,-,pcTaskGetName,char*,TaskHandle_t Function,-,pcTimerGetName,const char*,TimerHandle_t Function,-,pclose,int,FILE* @@ -1745,8 +1809,8 @@ Function,+,protocol_dict_get_name,const char*,"ProtocolDict*, size_t" Function,+,protocol_dict_get_protocol_by_name,ProtocolId,"ProtocolDict*, const char*" Function,+,protocol_dict_get_validate_count,uint32_t,"ProtocolDict*, size_t" Function,+,protocol_dict_get_write_data,_Bool,"ProtocolDict*, size_t, void*" -Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, string_t, size_t" -Function,+,protocol_dict_render_data,void,"ProtocolDict*, string_t, size_t" +Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, FuriString*, size_t" +Function,+,protocol_dict_render_data,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" Function,-,pselect,int,"int, fd_set*, fd_set*, fd_set*, const timespec*, const sigset_t*" Function,-,putc,int,"int, FILE*" @@ -2073,7 +2137,7 @@ Function,-,storage_file_sync,_Bool,File* Function,+,storage_file_tell,uint64_t,File* Function,+,storage_file_truncate,_Bool,File* Function,+,storage_file_write,uint16_t,"File*, const void*, uint16_t" -Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, string_t, uint8_t" +Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" Function,+,storage_get_pubsub,FuriPubSub*,Storage* Function,+,storage_int_backup,FS_Error,"Storage*, const char*" Function,+,storage_int_restore,FS_Error,"Storage*, const char*, Storage_name_converter" @@ -2106,7 +2170,7 @@ Function,+,stream_delete_and_insert,_Bool,"Stream*, size_t, StreamWriteCB, const Function,+,stream_delete_and_insert_char,_Bool,"Stream*, size_t, char" Function,+,stream_delete_and_insert_cstring,_Bool,"Stream*, size_t, const char*" Function,+,stream_delete_and_insert_format,_Bool,"Stream*, size_t, const char*, ..." -Function,+,stream_delete_and_insert_string,_Bool,"Stream*, size_t, string_t" +Function,+,stream_delete_and_insert_string,_Bool,"Stream*, size_t, FuriString*" Function,+,stream_delete_and_insert_vaformat,_Bool,"Stream*, size_t, const char*, va_list" Function,+,stream_dump_data,void,Stream* Function,+,stream_eof,_Bool,Stream* @@ -2115,11 +2179,11 @@ Function,+,stream_insert,_Bool,"Stream*, const uint8_t*, size_t" Function,+,stream_insert_char,_Bool,"Stream*, char" Function,+,stream_insert_cstring,_Bool,"Stream*, const char*" Function,+,stream_insert_format,_Bool,"Stream*, const char*, ..." -Function,+,stream_insert_string,_Bool,"Stream*, string_t" +Function,+,stream_insert_string,_Bool,"Stream*, FuriString*" Function,+,stream_insert_vaformat,_Bool,"Stream*, const char*, va_list" Function,+,stream_load_from_file,size_t,"Stream*, Storage*, const char*" Function,+,stream_read,size_t,"Stream*, uint8_t*, size_t" -Function,+,stream_read_line,_Bool,"Stream*, string_t" +Function,+,stream_read_line,_Bool,"Stream*, FuriString*" Function,+,stream_rewind,_Bool,Stream* Function,+,stream_save_to_file,size_t,"Stream*, Storage*, const char*, FS_OpenMode" Function,+,stream_seek,_Bool,"Stream*, int32_t, StreamOffset" @@ -2130,7 +2194,7 @@ Function,+,stream_write,size_t,"Stream*, const uint8_t*, size_t" Function,+,stream_write_char,size_t,"Stream*, char" Function,+,stream_write_cstring,size_t,"Stream*, const char*" Function,+,stream_write_format,size_t,"Stream*, const char*, ..." -Function,+,stream_write_string,size_t,"Stream*, string_t" +Function,+,stream_write_string,size_t,"Stream*, FuriString*" Function,+,stream_write_vaformat,size_t,"Stream*, const char*, va_list" Function,-,strerror,char*,int Function,-,strerror_l,char*,"int, locale_t" @@ -2191,14 +2255,14 @@ Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, si Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,-,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* -Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, string_t" +Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" Function,+,subghz_protocol_decoder_raw_free,void,void* -Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, string_t" +Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, FuriString*" Function,+,subghz_protocol_decoder_raw_reset,void,void* Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" @@ -2389,7 +2453,7 @@ Function,-,vTimerSetReloadMode,void,"TimerHandle_t, const UBaseType_t" Function,-,vTimerSetTimerID,void,"TimerHandle_t, void*" Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" -Function,+,validator_is_file_callback,_Bool,"const char*, string_t, void*" +Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* @@ -2639,6 +2703,8 @@ Variable,+,I_Lock_7x8,const Icon, Variable,+,I_Lock_8x8,const Icon, Variable,+,I_MHz_25x11,const Icon, Variable,+,I_Medium_chip_22x21,const Icon, +Variable,+,I_Modern_reader_18x34,const Icon, +Variable,+,I_Move_flipper_26x39,const Icon, Variable,+,I_Mute_25x27,const Icon, Variable,+,I_Mute_hvr_25x27,const Icon, Variable,+,I_NFC_manual_60x50,const Icon, @@ -2666,13 +2732,16 @@ Variable,+,I_RFIDDolphinReceive_97x61,const Icon, Variable,+,I_RFIDDolphinSend_97x61,const Icon, Variable,+,I_RFIDDolphinSuccess_108x57,const Icon, Variable,+,I_Reader_detect_43x40,const Icon, +Variable,+,I_Release_arrow_18x15,const Icon, Variable,+,I_Restoring_38x32,const Icon, Variable,+,I_Right_mouse_icon_9x9,const Icon, Variable,+,I_SDQuestion_35x43,const Icon, Variable,+,I_SDcardFail_11x8,const Icon, Variable,+,I_SDcardMounted_11x8,const Icon, Variable,+,I_Scanning_123x52,const Icon, +Variable,+,I_SmallArrowDown_3x5,const Icon, Variable,+,I_SmallArrowDown_4x7,const Icon, +Variable,+,I_SmallArrowUp_3x5,const Icon, Variable,+,I_SmallArrowUp_4x7,const Icon, Variable,+,I_Smile_18x18,const Icon, Variable,+,I_Space_65x18,const Icon, diff --git a/firmware/targets/f7/application-ext.ld b/firmware/targets/f7/application_ext.ld similarity index 100% rename from firmware/targets/f7/application-ext.ld rename to firmware/targets/f7/application_ext.ld diff --git a/firmware/targets/f7/ble_glue/dev_info_service.c b/firmware/targets/f7/ble_glue/dev_info_service.c index ecfa08b1..8bdb2eea 100755 --- a/firmware/targets/f7/ble_glue/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/dev_info_service.c @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -16,7 +15,7 @@ typedef struct { uint16_t firmware_rev_char_handle; uint16_t software_rev_char_handle; uint16_t rpc_version_char_handle; - string_t version_string; + FuriString* version_string; char hardware_revision[4]; } DevInfoSvc; @@ -31,8 +30,7 @@ static const uint8_t dev_info_rpc_version_uuid[] = void dev_info_svc_start() { dev_info_svc = malloc(sizeof(DevInfoSvc)); - string_init_printf( - dev_info_svc->version_string, + dev_info_svc->version_string = furi_string_alloc_printf( "%s %s %s %s", version_get_githash(NULL), version_get_gitbranch(NULL), @@ -104,7 +102,7 @@ void dev_info_svc_start() { dev_info_svc->service_handle, UUID_TYPE_16, (Char_UUID_t*)&uuid, - string_size(dev_info_svc->version_string), + furi_string_size(dev_info_svc->version_string), CHAR_PROP_READ, ATTR_PERMISSION_AUTHEN_READ, GATT_DONT_NOTIFY_EVENTS, @@ -161,8 +159,8 @@ void dev_info_svc_start() { dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle, 0, - string_size(dev_info_svc->version_string), - (uint8_t*)string_get_cstr(dev_info_svc->version_string)); + furi_string_size(dev_info_svc->version_string), + (uint8_t*)furi_string_get_cstr(dev_info_svc->version_string)); if(status) { FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); } @@ -180,7 +178,7 @@ void dev_info_svc_start() { void dev_info_svc_stop() { tBleStatus status; if(dev_info_svc) { - string_clear(dev_info_svc->version_string); + furi_string_free(dev_info_svc->version_string); // Delete service characteristics status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c index 62db30fe..aa8cd2c9 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -184,7 +184,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { FURI_LOG_I(TAG, "Pass key request event. Pin: ******"); } else { - FURI_LOG_I(TAG, "Pass key request event. Pin: %06d", pin); + FURI_LOG_I(TAG, "Pass key request event. Pin: %06ld", pin); } GapEvent event = {.type = GapEventTypePinCodeShow, .data.pin_code = pin}; gap->on_event_cb(event, gap->context); @@ -227,7 +227,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: { uint32_t pin = ((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value; - FURI_LOG_I(TAG, "Verify numeric comparison: %06d", pin); + FURI_LOG_I(TAG, "Verify numeric comparison: %06ld", pin); GapEvent event = {.type = GapEventTypePinCodeVerify, .data.pin_code = pin}; bool result = gap->on_event_cb(event, gap->context); aci_gap_numeric_comparison_value_confirm_yesno(gap->service.connection_handle, result); diff --git a/firmware/targets/f7/ble_glue/serial_service.c b/firmware/targets/f7/ble_glue/serial_service.c index eb58ae0e..c6421dc2 100644 --- a/firmware/targets/f7/ble_glue/serial_service.c +++ b/firmware/targets/f7/ble_glue/serial_service.c @@ -11,6 +11,7 @@ typedef struct { uint16_t rx_char_handle; uint16_t tx_char_handle; uint16_t flow_ctrl_char_handle; + uint16_t rpc_status_char_handle; FuriMutex* buff_size_mtx; uint32_t buff_size; uint16_t bytes_ready_to_receive; @@ -28,6 +29,8 @@ static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static const uint8_t flow_ctrl_uuid[] = {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t rpc_status_uuid[] = + {0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; @@ -63,13 +66,24 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { .size = attribute_modified->Attr_Data_Length, }}; uint32_t buff_free_size = serial_svc->callback(event, serial_svc->context); - FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size); + FURI_LOG_D(TAG, "Available buff size: %ld", buff_free_size); furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } ret = SVCCTL_EvtAckFlowEnable; + } else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) { + SerialServiceRpcStatus* rpc_status = + (SerialServiceRpcStatus*)attribute_modified->Attr_Data; + if(*rpc_status == SerialServiceRpcStatusNotActive) { + if(serial_svc->callback) { + SerialServiceEvent event = { + .event = SerialServiceEventTypesBleResetRequest, + }; + serial_svc->callback(event, serial_svc->context); + } + } } } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - FURI_LOG_T(TAG, "Ack received", blecore_evt->ecode); + FURI_LOG_T(TAG, "Ack received"); if(serial_svc->callback) { SerialServiceEvent event = { .event = SerialServiceEventTypeDataSent, @@ -82,6 +96,18 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { return ret; } +static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) { + tBleStatus ble_status = aci_gatt_update_char_value( + serial_svc->svc_handle, + serial_svc->rpc_status_char_handle, + 0, + sizeof(SerialServiceRpcStatus), + (uint8_t*)&status); + if(ble_status) { + FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status); + } +} + void serial_svc_start() { tBleStatus status; serial_svc = malloc(sizeof(SerialSvc)); @@ -90,7 +116,7 @@ void serial_svc_start() { // Add service status = aci_gatt_add_service( - UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle); + UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); if(status) { FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } @@ -141,6 +167,22 @@ void serial_svc_start() { if(status) { FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); } + // Add RPC status characteristic + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)rpc_status_uuid, + sizeof(SerialServiceRpcStatus), + CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status); + } + serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive); // Allocate buffer size mutex serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); } @@ -198,6 +240,10 @@ void serial_svc_stop() { if(status) { FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status); + } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); if(status) { @@ -242,3 +288,8 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) { return true; } + +void serial_svc_set_rpc_status(SerialServiceRpcStatus status) { + furi_assert(serial_svc); + serial_svc_update_rpc_char(status); +} diff --git a/firmware/targets/f7/ble_glue/serial_service.h b/firmware/targets/f7/ble_glue/serial_service.h index a1e5bc1c..7d38066f 100644 --- a/firmware/targets/f7/ble_glue/serial_service.h +++ b/firmware/targets/f7/ble_glue/serial_service.h @@ -10,9 +10,15 @@ extern "C" { #endif +typedef enum { + SerialServiceRpcStatusNotActive = 0UL, + SerialServiceRpcStatusActive = 1UL, +} SerialServiceRpcStatus; + typedef enum { SerialServiceEventTypeDataReceived, SerialServiceEventTypeDataSent, + SerialServiceEventTypesBleResetRequest, } SerialServiceEventType; typedef struct { @@ -34,6 +40,8 @@ void serial_svc_set_callbacks( SerialServiceEventCallback callback, void* context); +void serial_svc_set_rpc_status(SerialServiceRpcStatus status); + void serial_svc_notify_buffer_is_empty(); void serial_svc_stop(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 1a2b436d..fc1c25c7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -340,7 +340,7 @@ bool furi_hal_bt_clear_white_list() { return status != BLE_STATUS_SUCCESS; } -void furi_hal_bt_dump_state(string_t buffer) { +void furi_hal_bt_dump_state(FuriString* buffer) { if(furi_hal_bt_is_alive()) { uint8_t HCI_Version; uint16_t HCI_Revision; @@ -351,7 +351,7 @@ void furi_hal_bt_dump_state(string_t buffer) { tBleStatus ret = hci_read_local_version_information( &HCI_Version, &HCI_Revision, &LMP_PAL_Version, &Manufacturer_Name, &LMP_PAL_Subversion); - string_cat_printf( + furi_string_cat_printf( buffer, "Ret: %d, HCI_Version: %d, HCI_Revision: %d, LMP_PAL_Version: %d, Manufacturer_Name: %d, LMP_PAL_Subversion: %d", ret, @@ -361,7 +361,7 @@ void furi_hal_bt_dump_state(string_t buffer) { Manufacturer_Name, LMP_PAL_Subversion); } else { - string_cat_printf(buffer, "BLE not ready"); + furi_string_cat_printf(buffer, "BLE not ready"); } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c index 9bdad5bf..aa09dde5 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c @@ -31,6 +31,16 @@ void furi_hal_bt_serial_notify_buffer_is_empty() { serial_svc_notify_buffer_is_empty(); } +void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status) { + SerialServiceRpcStatus st; + if(status == FuriHalBtSerialRpcStatusActive) { + st = SerialServiceRpcStatusActive; + } else { + st = SerialServiceRpcStatusNotActive; + } + serial_svc_set_rpc_status(st); +} + bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) { if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) { return false; diff --git a/firmware/targets/f7/furi_hal/furi_hal_console.c b/firmware/targets/f7/furi_hal/furi_hal_console.c index e5db927b..2bdc5725 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_console.c +++ b/firmware/targets/f7/furi_hal/furi_hal_console.c @@ -4,7 +4,6 @@ #include #include #include -#include #include @@ -88,13 +87,13 @@ void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size } void furi_hal_console_printf(const char format[], ...) { - string_t string; + FuriString* string; va_list args; va_start(args, format); - string_init_vprintf(string, format, args); + string = furi_string_alloc_vprintf(format, args); va_end(args); - furi_hal_console_tx((const uint8_t*)string_get_cstr(string), string_size(string)); - string_clear(string); + furi_hal_console_tx((const uint8_t*)furi_string_get_cstr(string), furi_string_size(string)); + furi_string_free(string); } void furi_hal_console_puts(const char* data) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_console.h b/firmware/targets/f7/furi_hal/furi_hal_console.h index 104515ce..ce31a66b 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_console.h +++ b/firmware/targets/f7/furi_hal/furi_hal_console.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -27,7 +28,7 @@ void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size * @param format * @param ... */ -void furi_hal_console_printf(const char format[], ...); +void furi_hal_console_printf(const char format[], ...) _ATTRIBUTE((__format__(__printf__, 1, 2))); void furi_hal_console_puts(const char* data); diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index f99cf8c3..e49cd5f2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -83,7 +83,7 @@ void furi_hal_flash_init() { // WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR); /* Actually, reset all error flags on start */ if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) { - FURI_LOG_E(TAG, "FLASH->SR 0x%08X", FLASH->SR); + FURI_LOG_E(TAG, "FLASH->SR 0x%08lX", FLASH->SR); WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS); } } @@ -514,10 +514,10 @@ bool furi_hal_flash_ob_set_word(size_t word_idx, const uint32_t value) { FURI_LOG_W( TAG, - "Setting OB reg %d for word %d (addr 0x%08X) to 0x%08X", + "Setting OB reg %d for word %d (addr 0x%08lX) to 0x%08lX", reg_def->ob_reg, word_idx, - reg_def->ob_register_address, + (uint32_t)reg_def->ob_register_address, value); /* 1. Clear OPTLOCK option lock bit with the clearing sequence */ diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/firmware/targets/f7/furi_hal/furi_hal_info.c index 25ea42bb..15ce41a2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_info.c +++ b/firmware/targets/f7/furi_hal/furi_hal_info.c @@ -5,12 +5,12 @@ #include #include -#include +#include #include void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { - string_t value; - string_init(value); + FuriString* value; + value = furi_string_alloc(); // Device Info version out("device_info_major", "2", false, context); @@ -20,36 +20,36 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { out("hardware_model", furi_hal_version_get_model_name(), false, context); // Unique ID - string_reset(value); + furi_string_reset(value); const uint8_t* uid = furi_hal_version_uid(); for(size_t i = 0; i < furi_hal_version_uid_size(); i++) { - string_cat_printf(value, "%02X", uid[i]); + furi_string_cat_printf(value, "%02X", uid[i]); } - out("hardware_uid", string_get_cstr(value), false, context); + out("hardware_uid", furi_string_get_cstr(value), false, context); // OTP Revision - string_printf(value, "%d", furi_hal_version_get_otp_version()); - out("hardware_otp_ver", string_get_cstr(value), false, context); - string_printf(value, "%lu", furi_hal_version_get_hw_timestamp()); - out("hardware_timestamp", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_otp_version()); + out("hardware_otp_ver", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%lu", furi_hal_version_get_hw_timestamp()); + out("hardware_timestamp", furi_string_get_cstr(value), false, context); // Board Revision - string_printf(value, "%d", furi_hal_version_get_hw_version()); - out("hardware_ver", string_get_cstr(value), false, context); - string_printf(value, "%d", furi_hal_version_get_hw_target()); - out("hardware_target", string_get_cstr(value), false, context); - string_printf(value, "%d", furi_hal_version_get_hw_body()); - out("hardware_body", string_get_cstr(value), false, context); - string_printf(value, "%d", furi_hal_version_get_hw_connect()); - out("hardware_connect", string_get_cstr(value), false, context); - string_printf(value, "%d", furi_hal_version_get_hw_display()); - out("hardware_display", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_version()); + out("hardware_ver", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_target()); + out("hardware_target", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_body()); + out("hardware_body", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_connect()); + out("hardware_connect", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_display()); + out("hardware_display", furi_string_get_cstr(value), false, context); // Board Personification - string_printf(value, "%d", furi_hal_version_get_hw_color()); - out("hardware_color", string_get_cstr(value), false, context); - string_printf(value, "%d", furi_hal_version_get_hw_region()); - out("hardware_region", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_color()); + out("hardware_color", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", furi_hal_version_get_hw_region()); + out("hardware_region", furi_string_get_cstr(value), false, context); out("hardware_region_provisioned", furi_hal_region_get_name(), false, context); const char* name = furi_hal_version_get_name_ptr(); if(name) { @@ -68,8 +68,8 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { out("firmware_branch_num", version_get_gitbranchnum(firmware_version), false, context); out("firmware_version", version_get_version(firmware_version), false, context); out("firmware_build_date", version_get_builddate(firmware_version), false, context); - string_printf(value, "%d", version_get_target(firmware_version)); - out("firmware_target", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", version_get_target(firmware_version)); + out("firmware_target", furi_string_get_cstr(value), false, context); } if(furi_hal_bt_is_alive()) { @@ -78,64 +78,64 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { out("radio_mode", ble_c2_info->mode == BleGlueC2ModeFUS ? "FUS" : "Stack", false, context); // FUS Info - string_printf(value, "%d", ble_c2_info->FusVersionMajor); - out("radio_fus_major", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->FusVersionMinor); - out("radio_fus_minor", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->FusVersionSub); - out("radio_fus_sub", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->FusMemorySizeSram2B); - out("radio_fus_sram2b", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->FusMemorySizeSram2A); - out("radio_fus_sram2a", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->FusMemorySizeFlash * 4); - out("radio_fus_flash", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->FusVersionMajor); + out("radio_fus_major", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->FusVersionMinor); + out("radio_fus_minor", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->FusVersionSub); + out("radio_fus_sub", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->FusMemorySizeSram2B); + out("radio_fus_sram2b", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->FusMemorySizeSram2A); + out("radio_fus_sram2a", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->FusMemorySizeFlash * 4); + out("radio_fus_flash", furi_string_get_cstr(value), false, context); // Stack Info - string_printf(value, "%d", ble_c2_info->StackType); - out("radio_stack_type", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->VersionMajor); - out("radio_stack_major", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->VersionMinor); - out("radio_stack_minor", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->VersionSub); - out("radio_stack_sub", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->VersionBranch); - out("radio_stack_branch", string_get_cstr(value), false, context); - string_printf(value, "%d", ble_c2_info->VersionReleaseType); - out("radio_stack_release", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->MemorySizeSram2B); - out("radio_stack_sram2b", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->MemorySizeSram2A); - out("radio_stack_sram2a", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->MemorySizeSram1); - out("radio_stack_sram1", string_get_cstr(value), false, context); - string_printf(value, "%dK", ble_c2_info->MemorySizeFlash * 4); - out("radio_stack_flash", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->StackType); + out("radio_stack_type", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->VersionMajor); + out("radio_stack_major", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->VersionMinor); + out("radio_stack_minor", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->VersionSub); + out("radio_stack_sub", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->VersionBranch); + out("radio_stack_branch", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%d", ble_c2_info->VersionReleaseType); + out("radio_stack_release", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->MemorySizeSram2B); + out("radio_stack_sram2b", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->MemorySizeSram2A); + out("radio_stack_sram2a", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->MemorySizeSram1); + out("radio_stack_sram1", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%dK", ble_c2_info->MemorySizeFlash * 4); + out("radio_stack_flash", furi_string_get_cstr(value), false, context); // Mac address - string_reset(value); + furi_string_reset(value); const uint8_t* ble_mac = furi_hal_version_get_ble_mac(); for(size_t i = 0; i < 6; i++) { - string_cat_printf(value, "%02X", ble_mac[i]); + furi_string_cat_printf(value, "%02X", ble_mac[i]); } - out("radio_ble_mac", string_get_cstr(value), false, context); + out("radio_ble_mac", furi_string_get_cstr(value), false, context); // Signature verification uint8_t enclave_keys = 0; uint8_t enclave_valid_keys = 0; bool enclave_valid = furi_hal_crypto_verify_enclave(&enclave_keys, &enclave_valid_keys); - string_printf(value, "%d", enclave_valid_keys); - out("enclave_valid_keys", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", enclave_valid_keys); + out("enclave_valid_keys", furi_string_get_cstr(value), false, context); out("enclave_valid", enclave_valid ? "true" : "false", false, context); } else { out("radio_alive", "false", false, context); } - string_printf(value, "%u", PROTOBUF_MAJOR_VERSION); - out("protobuf_version_major", string_get_cstr(value), false, context); - string_printf(value, "%u", PROTOBUF_MINOR_VERSION); - out("protobuf_version_minor", string_get_cstr(value), true, context); + furi_string_printf(value, "%u", PROTOBUF_MAJOR_VERSION); + out("protobuf_version_major", furi_string_get_cstr(value), false, context); + furi_string_printf(value, "%u", PROTOBUF_MINOR_VERSION); + out("protobuf_version_minor", furi_string_get_cstr(value), true, context); - string_clear(value); + furi_string_free(value); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_memory.c b/firmware/targets/f7/furi_hal/furi_hal_memory.c index 43dc56f1..9cf2c312 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_memory.c +++ b/firmware/targets/f7/furi_hal/furi_hal_memory.c @@ -55,9 +55,9 @@ void furi_hal_memory_init() { memory->region[SRAM_B].size = sram2b_unprotected_size; FURI_LOG_I( - TAG, "SRAM2A: 0x%p, %d", memory->region[SRAM_A].start, memory->region[SRAM_A].size); + TAG, "SRAM2A: 0x%p, %ld", memory->region[SRAM_A].start, memory->region[SRAM_A].size); FURI_LOG_I( - TAG, "SRAM2B: 0x%p, %d", memory->region[SRAM_B].start, memory->region[SRAM_B].size); + TAG, "SRAM2B: 0x%p, %ld", memory->region[SRAM_B].start, memory->region[SRAM_B].size); if((memory->region[SRAM_A].size > 0) || (memory->region[SRAM_B].size > 0)) { if((memory->region[SRAM_A].size > 0)) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index de67bbc3..069ac4ea 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -743,7 +742,8 @@ void furi_hal_nfc_sleep() { rfalLowPowerModeStart(); } -FuriHalNfcReturn furi_hal_nfc_ll_set_mode(FuriHalNfcMode mode, FuriHalNfcBitrate txBR, FuriHalNfcBitrate rxBR) { +FuriHalNfcReturn + furi_hal_nfc_ll_set_mode(FuriHalNfcMode mode, FuriHalNfcBitrate txBR, FuriHalNfcBitrate rxBR) { return rfalSetMode((rfalMode)mode, (rfalBitRate)txBR, (rfalBitRate)rxBR); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 524fae0b..86505c57 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -529,8 +529,8 @@ void furi_hal_power_suppress_charge_exit() { void furi_hal_power_info_get(FuriHalPowerInfoCallback out, void* context) { furi_assert(out); - string_t value; - string_init(value); + FuriString* value; + value = furi_string_alloc(); // Power Info version out("power_info_major", "1", false, context); @@ -538,45 +538,45 @@ void furi_hal_power_info_get(FuriHalPowerInfoCallback out, void* context) { uint8_t charge = furi_hal_power_get_pct(); - string_printf(value, "%u", charge); - out("charge_level", string_get_cstr(value), false, context); + furi_string_printf(value, "%u", charge); + out("charge_level", furi_string_get_cstr(value), false, context); if(furi_hal_power_is_charging()) { if(charge < 100) { - string_printf(value, "charging"); + furi_string_printf(value, "charging"); } else { - string_printf(value, "charged"); + furi_string_printf(value, "charged"); } } else { - string_printf(value, "discharging"); + furi_string_printf(value, "discharging"); } - out("charge_state", string_get_cstr(value), false, context); + out("charge_state", furi_string_get_cstr(value), false, context); uint16_t voltage = (uint16_t)(furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge) * 1000.f); - string_printf(value, "%u", voltage); - out("battery_voltage", string_get_cstr(value), false, context); + furi_string_printf(value, "%u", voltage); + out("battery_voltage", furi_string_get_cstr(value), false, context); int16_t current = (int16_t)(furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge) * 1000.f); - string_printf(value, "%d", current); - out("battery_current", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", current); + out("battery_current", furi_string_get_cstr(value), false, context); int16_t temperature = (int16_t)furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); - string_printf(value, "%d", temperature); - out("gauge_temp", string_get_cstr(value), false, context); + furi_string_printf(value, "%d", temperature); + out("gauge_temp", furi_string_get_cstr(value), false, context); - string_printf(value, "%u", furi_hal_power_get_bat_health_pct()); - out("battery_health", string_get_cstr(value), false, context); + furi_string_printf(value, "%u", furi_hal_power_get_bat_health_pct()); + out("battery_health", furi_string_get_cstr(value), false, context); - string_printf(value, "%u", furi_hal_power_get_battery_remaining_capacity()); - out("capacity_remain", string_get_cstr(value), false, context); + furi_string_printf(value, "%lu", furi_hal_power_get_battery_remaining_capacity()); + out("capacity_remain", furi_string_get_cstr(value), false, context); - string_printf(value, "%u", furi_hal_power_get_battery_full_capacity()); - out("capacity_full", string_get_cstr(value), false, context); + furi_string_printf(value, "%lu", furi_hal_power_get_battery_full_capacity()); + out("capacity_full", furi_string_get_cstr(value), false, context); - string_printf(value, "%u", furi_hal_power_get_battery_design_capacity()); - out("capacity_design", string_get_cstr(value), true, context); + furi_string_printf(value, "%lu", furi_hal_power_get_battery_design_capacity()); + out("capacity_design", furi_string_get_cstr(value), true, context); - string_clear(value); + furi_string_free(value); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index b73d074f..5eeb4e9a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -173,7 +173,7 @@ void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { i += 2; } for(uint8_t y = i; y < i + 10; y++) { - FURI_LOG_D(TAG, "PA[%lu]: %02X", y, preset_data[y]); + FURI_LOG_D(TAG, "PA[%u]: %02X", y, preset_data[y]); } } } diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index 3f1169d1..800fc3fe 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -5,7 +5,7 @@ #pragma once -#include +#include #include #include #include @@ -122,9 +122,9 @@ void furi_hal_bt_stop_advertising(); /** Get BT/BLE system component state * - * @param[in] buffer string_t buffer to write to + * @param[in] buffer FuriString* buffer to write to */ -void furi_hal_bt_dump_state(string_t buffer); +void furi_hal_bt_dump_state(FuriString* buffer); /** Get BT/BLE system component state * diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h index e1b7af22..1b6e79ab 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h @@ -8,6 +8,11 @@ extern "C" { #define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX +typedef enum { + FuriHalBtSerialRpcStatusNotActive, + FuriHalBtSerialRpcStatusActive, +} FuriHalBtSerialRpcStatus; + /** Serial service callback type */ typedef SerialServiceEventCallback FuriHalBtSerialCallback; @@ -30,6 +35,12 @@ void furi_hal_bt_serial_set_event_callback( FuriHalBtSerialCallback callback, void* context); +/** Set BLE RPC status + * + * @param status FuriHalBtSerialRpcStatus instance + */ +void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status); + /** Notify that application buffer is empty */ void furi_hal_bt_serial_notify_buffer_is_empty(); diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index f8eaa5c3..e94877af 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -7,7 +7,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/furi/core/check.c b/furi/core/check.c index 3d0cd7a0..613b52f4 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -9,6 +9,7 @@ #include #include #include +#include extern size_t xPortGetTotalHeapSize(void); extern size_t xPortGetFreeHeapSize(void); diff --git a/furi/core/kernel.h b/furi/core/kernel.h index 28afffd4..f30f109b 100644 --- a/furi/core/kernel.h +++ b/furi/core/kernel.h @@ -1,5 +1,5 @@ /** - * @file kenrel.h + * @file kernel.h * Furi Kernel primitives */ #pragma once diff --git a/furi/core/log.c b/furi/core/log.c index 8a36a930..bb163c95 100644 --- a/furi/core/log.c +++ b/furi/core/log.c @@ -25,8 +25,8 @@ void furi_log_init() { void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) { if(level <= furi_log.log_level && furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) { - string_t string; - string_init(string); + FuriString* string; + string = furi_string_alloc(); const char* color = FURI_LOG_CLR_RESET; const char* log_letter = " "; @@ -56,23 +56,23 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form } // Timestamp - string_printf( + furi_string_printf( string, "%lu %s[%s][%s] " FURI_LOG_CLR_RESET, furi_log.timetamp(), color, log_letter, tag); - furi_log.puts(string_get_cstr(string)); - string_reset(string); + furi_log.puts(furi_string_get_cstr(string)); + furi_string_reset(string); va_list args; va_start(args, format); - string_vprintf(string, format, args); + furi_string_vprintf(string, format, args); va_end(args); - furi_log.puts(string_get_cstr(string)); - string_clear(string); + furi_log.puts(furi_string_get_cstr(string)); + furi_string_free(string); furi_log.puts("\r\n"); diff --git a/furi/core/log.h b/furi/core/log.h index 30026fc4..cb8b3d9c 100644 --- a/furi/core/log.h +++ b/furi/core/log.h @@ -51,7 +51,8 @@ void furi_log_init(); * @param format * @param ... */ -void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...); +void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 3, 4))); /** Set log level * diff --git a/furi/core/record.c b/furi/core/record.c index 63dfdbe4..773585e7 100644 --- a/furi/core/record.c +++ b/furi/core/record.c @@ -4,7 +4,6 @@ #include "mutex.h" #include "event_flag.h" -#include #include #include diff --git a/furi/core/stream_buffer.c b/furi/core/stream_buffer.c new file mode 100644 index 00000000..b9d0629f --- /dev/null +++ b/furi/core/stream_buffer.c @@ -0,0 +1,77 @@ +#include "base.h" +#include "stream_buffer.h" +#include "common_defines.h" +#include +#include + +FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level) { + return xStreamBufferCreate(size, trigger_level); +}; + +void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer) { + vStreamBufferDelete(stream_buffer); +}; + +bool furi_stream_set_trigger_level(FuriStreamBuffer* stream_buffer, size_t trigger_level) { + return xStreamBufferSetTriggerLevel(stream_buffer, trigger_level) == pdTRUE; +}; + +size_t furi_stream_buffer_send( + FuriStreamBuffer* stream_buffer, + const void* data, + size_t length, + uint32_t timeout) { + size_t ret; + + if(FURI_IS_IRQ_MODE() != 0U) { + BaseType_t yield; + ret = xStreamBufferSendFromISR(stream_buffer, data, length, &yield); + portYIELD_FROM_ISR(yield); + } else { + ret = xStreamBufferSend(stream_buffer, data, length, timeout); + } + + return ret; +}; + +size_t furi_stream_buffer_receive( + FuriStreamBuffer* stream_buffer, + void* data, + size_t length, + uint32_t timeout) { + size_t ret; + + if(FURI_IS_IRQ_MODE() != 0U) { + BaseType_t yield; + ret = xStreamBufferReceiveFromISR(stream_buffer, data, length, &yield); + portYIELD_FROM_ISR(yield); + } else { + ret = xStreamBufferReceive(stream_buffer, data, length, timeout); + } + + return ret; +} + +size_t furi_stream_buffer_bytes_available(FuriStreamBuffer* stream_buffer) { + return xStreamBufferBytesAvailable(stream_buffer); +}; + +size_t furi_stream_buffer_spaces_available(FuriStreamBuffer* stream_buffer) { + return xStreamBufferSpacesAvailable(stream_buffer); +}; + +bool furi_stream_buffer_is_full(FuriStreamBuffer* stream_buffer) { + return xStreamBufferIsFull(stream_buffer) == pdTRUE; +}; + +bool furi_stream_buffer_is_empty(FuriStreamBuffer* stream_buffer) { + return (xStreamBufferIsEmpty(stream_buffer) == pdTRUE); +}; + +FuriStatus furi_stream_buffer_reset(FuriStreamBuffer* stream_buffer) { + if(xStreamBufferReset(stream_buffer) == pdPASS) { + return FuriStatusOk; + } else { + return FuriStatusError; + } +} \ No newline at end of file diff --git a/furi/core/stream_buffer.h b/furi/core/stream_buffer.h new file mode 100644 index 00000000..d07f7e60 --- /dev/null +++ b/furi/core/stream_buffer.h @@ -0,0 +1,152 @@ +/** + * @file stream_buffer.h + * Furi stream buffer primitive. + * + * Stream buffers are used to send a continuous stream of data from one task or + * interrupt to another. Their implementation is light weight, making them + * particularly suited for interrupt to task and core to core communication + * scenarios. + * + * ***NOTE***: Stream buffer implementation assumes there is only one task or + * interrupt that will write to the buffer (the writer), and only one task or + * interrupt that will read from the buffer (the reader). + */ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void FuriStreamBuffer; + +/** + * @brief Allocate stream buffer instance. + * Stream buffer implementation assumes there is only one task or + * interrupt that will write to the buffer (the writer), and only one task or + * interrupt that will read from the buffer (the reader). + * + * @param size The total number of bytes the stream buffer will be able to hold at any one time. + * @param trigger_level The number of bytes that must be in the stream buffer + * before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state. + * @return The stream buffer instance. + */ +FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level); + +/** + * @brief Free stream buffer instance + * + * @param stream_buffer The stream buffer instance. + */ +void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer); + +/** + * @brief Set trigger level for stream buffer. + * A stream buffer's trigger level is the number of bytes that must be in the + * stream buffer before a task that is blocked on the stream buffer to + * wait for data is moved out of the blocked state. + * + * @param stream_buffer The stream buffer instance + * @param trigger_level The new trigger level for the stream buffer. + * @return true if trigger level can be be updated (new trigger level was less than or equal to the stream buffer's length). + * @return false if trigger level can't be be updated (new trigger level was greater than the stream buffer's length). + */ +bool furi_stream_set_trigger_level(FuriStreamBuffer* stream_buffer, size_t trigger_level); + +/** + * @brief Sends bytes to a stream buffer. The bytes are copied into the stream buffer. + * Wakes up task waiting for data to become available if called from ISR. + * + * @param stream_buffer The stream buffer instance. + * @param data A pointer to the data that is to be copied into the stream buffer. + * @param length The maximum number of bytes to copy from data into the stream buffer. + * @param timeout The maximum amount of time the task should remain in the + * Blocked state to wait for space to become available if the stream buffer is full. + * Will return immediately if timeout is zero. + * Setting timeout to FuriWaitForever will cause the task to wait indefinitely. + * Ignored if called from ISR. + * @return The number of bytes actually written to the stream buffer. + */ +size_t furi_stream_buffer_send( + FuriStreamBuffer* stream_buffer, + const void* data, + size_t length, + uint32_t timeout); + +/** + * @brief Receives bytes from a stream buffer. + * Wakes up task waiting for space to become available if called from ISR. + * + * @param stream_buffer The stream buffer instance. + * @param data A pointer to the buffer into which the received bytes will be + * copied. + * @param length The length of the buffer pointed to by the data parameter. + * @param timeout The maximum amount of time the task should remain in the + * Blocked state to wait for data to become available if the stream buffer is empty. + * Will return immediately if timeout is zero. + * Setting timeout to FuriWaitForever will cause the task to wait indefinitely. + * Ignored if called from ISR. + * @return The number of bytes read from the stream buffer, if any. + */ +size_t furi_stream_buffer_receive( + FuriStreamBuffer* stream_buffer, + void* data, + size_t length, + uint32_t timeout); + +/** + * @brief Queries a stream buffer to see how much data it contains, which is equal to + * the number of bytes that can be read from the stream buffer before the stream + * buffer would be empty. + * + * @param stream_buffer The stream buffer instance. + * @return The number of bytes that can be read from the stream buffer before + * the stream buffer would be empty. + */ +size_t furi_stream_buffer_bytes_available(FuriStreamBuffer* stream_buffer); + +/** + * @brief Queries a stream buffer to see how much free space it contains, which is + * equal to the amount of data that can be sent to the stream buffer before it + * is full. + * + * @param stream_buffer The stream buffer instance. + * @return The number of bytes that can be written to the stream buffer before + * the stream buffer would be full. + */ +size_t furi_stream_buffer_spaces_available(FuriStreamBuffer* stream_buffer); + +/** + * @brief Queries a stream buffer to see if it is full. + * + * @param stream_buffer stream buffer instance. + * @return true if the stream buffer is full. + * @return false if the stream buffer is not full. + */ +bool furi_stream_buffer_is_full(FuriStreamBuffer* stream_buffer); + +/** + * @brief Queries a stream buffer to see if it is empty. + * + * @param stream_buffer The stream buffer instance. + * @return true if the stream buffer is empty. + * @return false if the stream buffer is not empty. + */ +bool furi_stream_buffer_is_empty(FuriStreamBuffer* stream_buffer); + +/** + * @brief Resets a stream buffer to its initial, empty, state. Any data that was + * in the stream buffer is discarded. A stream buffer can only be reset if there + * are no tasks blocked waiting to either send to or receive from the stream buffer. + * + * @param stream_buffer The stream buffer instance. + * @return FuriStatusOk if the stream buffer is reset. + * @return FuriStatusError if there was a task blocked waiting to send to or read + * from the stream buffer then the stream buffer is not reset. + */ +FuriStatus furi_stream_buffer_reset(FuriStreamBuffer* stream_buffer); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/furi/core/string.c b/furi/core/string.c new file mode 100644 index 00000000..099f70c1 --- /dev/null +++ b/furi/core/string.c @@ -0,0 +1,302 @@ +#include "string.h" +#include + +struct FuriString { + string_t string; +}; + +#undef furi_string_alloc_set +#undef furi_string_set +#undef furi_string_cmp +#undef furi_string_cmpi +#undef furi_string_search +#undef furi_string_search_str +#undef furi_string_equal +#undef furi_string_replace +#undef furi_string_replace_str +#undef furi_string_replace_all +#undef furi_string_start_with +#undef furi_string_end_with +#undef furi_string_search_char +#undef furi_string_search_rchar +#undef furi_string_trim +#undef furi_string_cat + +FuriString* furi_string_alloc() { + FuriString* string = malloc(sizeof(FuriString)); + string_init(string->string); + return string; +} + +FuriString* furi_string_alloc_set(const FuriString* s) { + FuriString* string = malloc(sizeof(FuriString)); + string_init_set(string->string, s->string); + return string; +} + +FuriString* furi_string_alloc_set_str(const char cstr[]) { + FuriString* string = malloc(sizeof(FuriString)); + string_init_set(string->string, cstr); + return string; +} + +FuriString* furi_string_alloc_printf(const char format[], ...) { + va_list args; + va_start(args, format); + FuriString* string = furi_string_alloc_vprintf(format, args); + va_end(args); + return string; +} + +FuriString* furi_string_alloc_vprintf(const char format[], va_list args) { + FuriString* string = malloc(sizeof(FuriString)); + string_init_vprintf(string->string, format, args); + return string; +} + +FuriString* furi_string_alloc_move(FuriString* s) { + FuriString* string = malloc(sizeof(FuriString)); + string_init_move(string->string, s->string); + free(s); + return string; +} + +void furi_string_free(FuriString* s) { + string_clear(s->string); + free(s); +} + +void furi_string_reserve(FuriString* s, size_t alloc) { + string_reserve(s->string, alloc); +} + +void furi_string_reset(FuriString* s) { + string_reset(s->string); +} + +void furi_string_swap(FuriString* v1, FuriString* v2) { + string_swap(v1->string, v2->string); +} + +void furi_string_move(FuriString* v1, FuriString* v2) { + string_clear(v1->string); + string_init_move(v1->string, v2->string); + free(v2); +} + +size_t furi_string_hash(const FuriString* v) { + return string_hash(v->string); +} + +char furi_string_get_char(const FuriString* v, size_t index) { + return string_get_char(v->string, index); +} + +const char* furi_string_get_cstr(const FuriString* s) { + return string_get_cstr(s->string); +} + +void furi_string_set(FuriString* s, FuriString* source) { + string_set(s->string, source->string); +} + +void furi_string_set_str(FuriString* s, const char cstr[]) { + string_set(s->string, cstr); +} + +void furi_string_set_strn(FuriString* s, const char str[], size_t n) { + string_set_strn(s->string, str, n); +} + +void furi_string_set_char(FuriString* s, size_t index, const char c) { + string_set_char(s->string, index, c); +} + +int furi_string_cmp(const FuriString* s1, const FuriString* s2) { + return string_cmp(s1->string, s2->string); +} + +int furi_string_cmp_str(const FuriString* s1, const char str[]) { + return string_cmp(s1->string, str); +} + +int furi_string_cmpi(const FuriString* v1, const FuriString* v2) { + return string_cmpi(v1->string, v2->string); +} + +int furi_string_cmpi_str(const FuriString* v1, const char p2[]) { + return string_cmpi_str(v1->string, p2); +} + +size_t furi_string_search(const FuriString* v, const FuriString* needle, size_t start) { + return string_search(v->string, needle->string, start); +} + +size_t furi_string_search_str(const FuriString* v, const char needle[], size_t start) { + return string_search(v->string, needle, start); +} + +bool furi_string_equal(const FuriString* v1, const FuriString* v2) { + return string_equal_p(v1->string, v2->string); +} + +bool furi_string_equal_str(const FuriString* v1, const char v2[]) { + return string_equal_p(v1->string, v2); +} + +void furi_string_push_back(FuriString* v, char c) { + string_push_back(v->string, c); +} + +size_t furi_string_size(const FuriString* s) { + return string_size(s->string); +} + +int furi_string_printf(FuriString* v, const char format[], ...) { + va_list args; + va_start(args, format); + int result = furi_string_vprintf(v, format, args); + va_end(args); + return result; +} + +int furi_string_vprintf(FuriString* v, const char format[], va_list args) { + return string_vprintf(v->string, format, args); +} + +int furi_string_cat_printf(FuriString* v, const char format[], ...) { + va_list args; + va_start(args, format); + int result = furi_string_cat_vprintf(v, format, args); + va_end(args); + return result; +} + +int furi_string_cat_vprintf(FuriString* v, const char format[], va_list args) { + FuriString* string = furi_string_alloc(); + int ret = furi_string_vprintf(string, format, args); + furi_string_cat(v, string); + furi_string_free(string); + return ret; +} + +bool furi_string_empty(const FuriString* v) { + return string_empty_p(v->string); +} + +void furi_string_replace_at(FuriString* v, size_t pos, size_t len, const char str2[]) { + string_replace_at(v->string, pos, len, str2); +} + +size_t + furi_string_replace(FuriString* string, FuriString* needle, FuriString* replace, size_t start) { + return string_replace(string->string, needle->string, replace->string, start); +} + +size_t furi_string_replace_str(FuriString* v, const char str1[], const char str2[], size_t start) { + return string_replace_str(v->string, str1, str2, start); +} + +void furi_string_replace_all_str(FuriString* v, const char str1[], const char str2[]) { + string_replace_all_str(v->string, str1, str2); +} + +void furi_string_replace_all(FuriString* v, const FuriString* str1, const FuriString* str2) { + string_replace_all(v->string, str1->string, str2->string); +} + +bool furi_string_start_with(const FuriString* v, const FuriString* v2) { + return string_start_with_string_p(v->string, v2->string); +} + +bool furi_string_start_with_str(const FuriString* v, const char str[]) { + return string_start_with_str_p(v->string, str); +} + +bool furi_string_end_with(const FuriString* v, const FuriString* v2) { + return string_end_with_string_p(v->string, v2->string); +} + +bool furi_string_end_with_str(const FuriString* v, const char str[]) { + return string_end_with_str_p(v->string, str); +} + +size_t furi_string_search_char(const FuriString* v, char c, size_t start) { + return string_search_char(v->string, c, start); +} + +size_t furi_string_search_rchar(const FuriString* v, char c, size_t start) { + return string_search_rchar(v->string, c, start); +} + +void furi_string_left(FuriString* v, size_t index) { + string_left(v->string, index); +} + +void furi_string_right(FuriString* v, size_t index) { + string_right(v->string, index); +} + +void furi_string_mid(FuriString* v, size_t index, size_t size) { + string_mid(v->string, index, size); +} + +void furi_string_trim(FuriString* v, const char charac[]) { + string_strim(v->string, charac); +} + +void furi_string_cat(FuriString* v, const FuriString* v2) { + string_cat(v->string, v2->string); +} + +void furi_string_cat_str(FuriString* v, const char str[]) { + string_cat(v->string, str); +} + +void furi_string_set_n(FuriString* v, const FuriString* ref, size_t offset, size_t length) { + string_set_n(v->string, ref->string, offset, length); +} + +size_t furi_string_utf8_length(FuriString* str) { + return string_length_u(str->string); +} + +void furi_string_utf8_push(FuriString* str, FuriStringUnicodeValue u) { + string_push_u(str->string, u); +} + +static m_str1ng_utf8_state_e furi_state_to_state(FuriStringUTF8State state) { + switch(state) { + case FuriStringUTF8StateStarting: + return M_STRING_UTF8_STARTING; + case FuriStringUTF8StateDecoding1: + return M_STRING_UTF8_DECODING_1; + case FuriStringUTF8StateDecoding2: + return M_STRING_UTF8_DECODING_2; + case FuriStringUTF8StateDecoding3: + return M_STRING_UTF8_DOCODING_3; + default: + return M_STRING_UTF8_ERROR; + } +} + +static FuriStringUTF8State state_to_furi_state(m_str1ng_utf8_state_e state) { + switch(state) { + case M_STRING_UTF8_STARTING: + return FuriStringUTF8StateStarting; + case M_STRING_UTF8_DECODING_1: + return FuriStringUTF8StateDecoding1; + case M_STRING_UTF8_DECODING_2: + return FuriStringUTF8StateDecoding2; + case M_STRING_UTF8_DOCODING_3: + return FuriStringUTF8StateDecoding3; + default: + return FuriStringUTF8StateError; + } +} + +void furi_string_utf8_decode(char c, FuriStringUTF8State* state, FuriStringUnicodeValue* unicode) { + m_str1ng_utf8_state_e m_state = furi_state_to_state(*state); + m_str1ng_utf8_decode(c, &m_state, unicode); + *state = state_to_furi_state(m_state); +} \ No newline at end of file diff --git a/furi/core/string.h b/furi/core/string.h new file mode 100644 index 00000000..01b26cce --- /dev/null +++ b/furi/core/string.h @@ -0,0 +1,741 @@ +/** + * @file string.h + * Furi string primitive + */ +#pragma once + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Furi string failure constant. + */ +#define FURI_STRING_FAILURE ((size_t)-1) + +/** + * @brief Furi string primitive. + */ +typedef struct FuriString FuriString; + +//--------------------------------------------------------------------------- +// Constructors +//--------------------------------------------------------------------------- + +/** + * @brief Allocate new FuriString. + * @return FuriString* + */ +FuriString* furi_string_alloc(); + +/** + * @brief Allocate new FuriString and set it to string. + * Allocate & Set the string a to the string. + * @param source + * @return FuriString* + */ +FuriString* furi_string_alloc_set(const FuriString* source); + +/** + * @brief Allocate new FuriString and set it to C string. + * Allocate & Set the string a to the C string. + * @param cstr_source + * @return FuriString* + */ +FuriString* furi_string_alloc_set_str(const char cstr_source[]); + +/** + * @brief Allocate new FuriString and printf to it. + * Initialize and set a string to the given formatted value. + * @param format + * @param ... + * @return FuriString* + */ +FuriString* furi_string_alloc_printf(const char format[], ...) + _ATTRIBUTE((__format__(__printf__, 1, 2))); + +/** + * @brief Allocate new FuriString and printf to it. + * Initialize and set a string to the given formatted value. + * @param format + * @param args + * @return FuriString* + */ +FuriString* furi_string_alloc_vprintf(const char format[], va_list args); + +/** + * @brief Allocate new FuriString and move source string content to it. + * Allocate the string, set it to the other one, and destroy the other one. + * @param source + * @return FuriString* + */ +FuriString* furi_string_alloc_move(FuriString* source); + +//--------------------------------------------------------------------------- +// Destructors +//--------------------------------------------------------------------------- + +/** + * @brief Free FuriString. + * @param string + */ +void furi_string_free(FuriString* string); + +//--------------------------------------------------------------------------- +// String memory management +//--------------------------------------------------------------------------- + +/** + * @brief Reserve memory for string. + * Modify the string capacity to be able to handle at least 'alloc' characters (including final null char). + * @param string + * @param size + */ +void furi_string_reserve(FuriString* string, size_t size); + +/** + * @brief Reset string. + * Make the string empty. + * @param s + */ +void furi_string_reset(FuriString* string); + +/** + * @brief Swap two strings. + * Swap the two strings string_1 and string_2. + * @param string_1 + * @param string_2 + */ +void furi_string_swap(FuriString* string_1, FuriString* string_2); + +/** + * @brief Move string_2 content to string_1. + * Set the string to the other one, and destroy the other one. + * @param string_1 + * @param string_2 + */ +void furi_string_move(FuriString* string_1, FuriString* string_2); + +/** + * @brief Compute a hash for the string. + * @param string + * @return size_t + */ +size_t furi_string_hash(const FuriString* string); + +/** + * @brief Get string size (usually length, but not for UTF-8) + * @param string + * @return size_t + */ +size_t furi_string_size(const FuriString* string); + +/** + * @brief Check that string is empty or not + * @param string + * @return bool + */ +bool furi_string_empty(const FuriString* string); + +//--------------------------------------------------------------------------- +// Getters +//--------------------------------------------------------------------------- + +/** + * @brief Get the character at the given index. + * Return the selected character of the string. + * @param string + * @param index + * @return char + */ +char furi_string_get_char(const FuriString* string, size_t index); + +/** + * @brief Return the string view a classic C string. + * @param string + * @return const char* + */ +const char* furi_string_get_cstr(const FuriString* string); + +//--------------------------------------------------------------------------- +// Setters +//--------------------------------------------------------------------------- + +/** + * @brief Set the string to the other string. + * Set the string to the source string. + * @param string + * @param source + */ +void furi_string_set(FuriString* string, FuriString* source); + +/** + * @brief Set the string to the other C string. + * Set the string to the source C string. + * @param string + * @param source + */ +void furi_string_set_str(FuriString* string, const char source[]); + +/** + * @brief Set the string to the n first characters of the C string. + * @param string + * @param source + * @param length + */ +void furi_string_set_strn(FuriString* string, const char source[], size_t length); + +/** + * @brief Set the character at the given index. + * @param string + * @param index + * @param c + */ +void furi_string_set_char(FuriString* string, size_t index, const char c); + +/** + * @brief Set the string to the n first characters of other one. + * @param string + * @param source + * @param offset + * @param length + */ +void furi_string_set_n(FuriString* string, const FuriString* source, size_t offset, size_t length); + +/** + * @brief Format in the string the given printf format + * @param string + * @param format + * @param ... + * @return int + */ +int furi_string_printf(FuriString* string, const char format[], ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); + +/** + * @brief Format in the string the given printf format + * @param string + * @param format + * @param args + * @return int + */ +int furi_string_vprintf(FuriString* string, const char format[], va_list args); + +//--------------------------------------------------------------------------- +// Appending +//--------------------------------------------------------------------------- + +/** + * @brief Append a character to the string. + * @param string + * @param c + */ +void furi_string_push_back(FuriString* string, char c); + +/** + * @brief Append a string to the string. + * Concatenate the string with the other string. + * @param string_1 + * @param string_2 + */ +void furi_string_cat(FuriString* string_1, const FuriString* string_2); + +/** + * @brief Append a C string to the string. + * Concatenate the string with the C string. + * @param string_1 + * @param cstring_2 + */ +void furi_string_cat_str(FuriString* string_1, const char cstring_2[]); + +/** + * @brief Append to the string the formatted string of the given printf format. + * @param string + * @param format + * @param ... + * @return int + */ +int furi_string_cat_printf(FuriString* string, const char format[], ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); + +/** + * @brief Append to the string the formatted string of the given printf format. + * @param string + * @param format + * @param args + * @return int + */ +int furi_string_cat_vprintf(FuriString* string, const char format[], va_list args); + +//--------------------------------------------------------------------------- +// Comparators +//--------------------------------------------------------------------------- + +/** + * @brief Compare two strings and return the sort order. + * @param string_1 + * @param string_2 + * @return int + */ +int furi_string_cmp(const FuriString* string_1, const FuriString* string_2); + +/** + * @brief Compare string with C string and return the sort order. + * @param string_1 + * @param cstring_2 + * @return int + */ +int furi_string_cmp_str(const FuriString* string_1, const char cstring_2[]); + +/** + * @brief Compare two strings (case insensitive according to the current locale) and return the sort order. + * Note: doesn't work with UTF-8 strings. + * @param string_1 + * @param string_2 + * @return int + */ +int furi_string_cmpi(const FuriString* string_1, const FuriString* string_2); + +/** + * @brief Compare string with C string (case insensitive according to the current locale) and return the sort order. + * Note: doesn't work with UTF-8 strings. + * @param string_1 + * @param cstring_2 + * @return int + */ +int furi_string_cmpi_str(const FuriString* string_1, const char cstring_2[]); + +//--------------------------------------------------------------------------- +// Search +//--------------------------------------------------------------------------- + +/** + * @brief Search the first occurrence of the needle in the string from the position start. + * Return STRING_FAILURE if not found. + * By default, start is zero. + * @param string + * @param needle + * @param start + * @return size_t + */ +size_t furi_string_search(const FuriString* string, const FuriString* needle, size_t start); + +/** + * @brief Search the first occurrence of the needle in the string from the position start. + * Return STRING_FAILURE if not found. + * @param string + * @param needle + * @param start + * @return size_t + */ +size_t furi_string_search_str(const FuriString* string, const char needle[], size_t start); + +/** + * @brief Search for the position of the character c from the position start (include) in the string. + * Return STRING_FAILURE if not found. + * By default, start is zero. + * @param string + * @param c + * @param start + * @return size_t + */ +size_t furi_string_search_char(const FuriString* string, char c, size_t start); + +/** + * @brief Reverse search for the position of the character c from the position start (include) in the string. + * Return STRING_FAILURE if not found. + * By default, start is zero. + * @param string + * @param c + * @param start + * @return size_t + */ +size_t furi_string_search_rchar(const FuriString* string, char c, size_t start); + +//--------------------------------------------------------------------------- +// Equality +//--------------------------------------------------------------------------- + +/** + * @brief Test if two strings are equal. + * @param string_1 + * @param string_2 + * @return bool + */ +bool furi_string_equal(const FuriString* string_1, const FuriString* string_2); + +/** + * @brief Test if the string is equal to the C string. + * @param string_1 + * @param cstring_2 + * @return bool + */ +bool furi_string_equal_str(const FuriString* string_1, const char cstring_2[]); + +//--------------------------------------------------------------------------- +// Replace +//--------------------------------------------------------------------------- + +/** + * @brief Replace in the string the sub-string at position 'pos' for 'len' bytes into the C string 'replace'. + * @param string + * @param pos + * @param len + * @param replace + */ +void furi_string_replace_at(FuriString* string, size_t pos, size_t len, const char replace[]); + +/** + * @brief Replace a string 'needle' to string 'replace' in a string from 'start' position. + * By default, start is zero. + * Return STRING_FAILURE if 'needle' not found or replace position. + * @param string + * @param needle + * @param replace + * @param start + * @return size_t + */ +size_t + furi_string_replace(FuriString* string, FuriString* needle, FuriString* replace, size_t start); + +/** + * @brief Replace a C string 'needle' to C string 'replace' in a string from 'start' position. + * By default, start is zero. + * Return STRING_FAILURE if 'needle' not found or replace position. + * @param string + * @param needle + * @param replace + * @param start + * @return size_t + */ +size_t furi_string_replace_str( + FuriString* string, + const char needle[], + const char replace[], + size_t start); + +/** + * @brief Replace all occurrences of 'needle' string into 'replace' string. + * @param string + * @param needle + * @param replace + */ +void furi_string_replace_all( + FuriString* string, + const FuriString* needle, + const FuriString* replace); + +/** + * @brief Replace all occurrences of 'needle' C string into 'replace' C string. + * @param string + * @param needle + * @param replace + */ +void furi_string_replace_all_str(FuriString* string, const char needle[], const char replace[]); + +//--------------------------------------------------------------------------- +// Start / End tests +//--------------------------------------------------------------------------- + +/** + * @brief Test if the string starts with the given string. + * @param string + * @param start + * @return bool + */ +bool furi_string_start_with(const FuriString* string, const FuriString* start); + +/** + * @brief Test if the string starts with the given C string. + * @param string + * @param start + * @return bool + */ +bool furi_string_start_with_str(const FuriString* string, const char start[]); + +/** + * @brief Test if the string ends with the given string. + * @param string + * @param end + * @return bool + */ +bool furi_string_end_with(const FuriString* string, const FuriString* end); + +/** + * @brief Test if the string ends with the given C string. + * @param string + * @param end + * @return bool + */ +bool furi_string_end_with_str(const FuriString* string, const char end[]); + +//--------------------------------------------------------------------------- +// Trim +//--------------------------------------------------------------------------- + +/** + * @brief Trim the string left to the first 'index' bytes. + * @param string + * @param index + */ +void furi_string_left(FuriString* string, size_t index); + +/** + * @brief Trim the string right from the 'index' position to the last position. + * @param string + * @param index + */ +void furi_string_right(FuriString* string, size_t index); + +/** + * @brief Trim the string from position index to size bytes. + * See also furi_string_set_n. + * @param string + * @param index + * @param size + */ +void furi_string_mid(FuriString* string, size_t index, size_t size); + +/** + * @brief Trim a string from the given set of characters (default is " \n\r\t"). + * @param string + * @param chars + */ +void furi_string_trim(FuriString* string, const char chars[]); + +//--------------------------------------------------------------------------- +// UTF8 +//--------------------------------------------------------------------------- + +/** + * @brief An unicode value. + */ +typedef unsigned int FuriStringUnicodeValue; + +/** + * @brief Compute the length in UTF8 characters in the string. + * @param string + * @return size_t + */ +size_t furi_string_utf8_length(FuriString* string); + +/** + * @brief Push unicode into string, encoding it in UTF8. + * @param string + * @param unicode + */ +void furi_string_utf8_push(FuriString* string, FuriStringUnicodeValue unicode); + +/** + * @brief State of the UTF8 decoding machine state. + */ +typedef enum { + FuriStringUTF8StateStarting, + FuriStringUTF8StateDecoding1, + FuriStringUTF8StateDecoding2, + FuriStringUTF8StateDecoding3, + FuriStringUTF8StateError +} FuriStringUTF8State; + +/** + * @brief Main generic UTF8 decoder. + * It takes a character, and the previous state and the previous value of the unicode value. + * It updates the state and the decoded unicode value. + * A decoded unicode encoded value is valid only when the state is FuriStringUTF8StateStarting. + * @param c + * @param state + * @param unicode + */ +void furi_string_utf8_decode(char c, FuriStringUTF8State* state, FuriStringUnicodeValue* unicode); + +//--------------------------------------------------------------------------- +// Lasciate ogne speranza, voi ch’entrate +//--------------------------------------------------------------------------- + +/** + * + * Select either the string function or the str function depending on + * the b operand to the function. + * func1 is the string function / func2 is the str function. + */ + +/** + * @brief Select for 1 argument + */ +#define FURI_STRING_SELECT1(func1, func2, a) \ + _Generic((a), char* : func2, const char* : func2, FuriString* : func1, const FuriString* : func1)(a) + +/** + * @brief Select for 2 arguments + */ +#define FURI_STRING_SELECT2(func1, func2, a, b) \ + _Generic((b), char* : func2, const char* : func2, FuriString* : func1, const FuriString* : func1)(a, b) + +/** + * @brief Select for 3 arguments + */ +#define FURI_STRING_SELECT3(func1, func2, a, b, c) \ + _Generic((b), char* : func2, const char* : func2, FuriString* : func1, const FuriString* : func1)(a, b, c) + +/** + * @brief Select for 4 arguments + */ +#define FURI_STRING_SELECT4(func1, func2, a, b, c, d) \ + _Generic((b), char* : func2, const char* : func2, FuriString* : func1, const FuriString* : func1)(a, b, c, d) + +/** + * @brief Allocate new FuriString and set it content to string (or C string). + * ([c]string) + */ +#define furi_string_alloc_set(a) \ + FURI_STRING_SELECT1(furi_string_alloc_set, furi_string_alloc_set_str, a) + +/** + * @brief Set the string content to string (or C string). + * (string, [c]string) + */ +#define furi_string_set(a, b) FURI_STRING_SELECT2(furi_string_set, furi_string_set_str, a, b) + +/** + * @brief Compare string with string (or C string) and return the sort order. + * Note: doesn't work with UTF-8 strings. + * (string, [c]string) + */ +#define furi_string_cmp(a, b) FURI_STRING_SELECT2(furi_string_cmp, furi_string_cmp_str, a, b) + +/** + * @brief Compare string with string (or C string) (case insensitive according to the current locale) and return the sort order. + * Note: doesn't work with UTF-8 strings. + * (string, [c]string) + */ +#define furi_string_cmpi(a, b) FURI_STRING_SELECT2(furi_string_cmpi, furi_string_cmpi_str, a, b) + +/** + * @brief Test if the string is equal to the string (or C string). + * (string, [c]string) + */ +#define furi_string_equal(a, b) FURI_STRING_SELECT2(furi_string_equal, furi_string_equal_str, a, b) + +/** + * @brief Replace all occurrences of string into string (or C string to another C string) in a string. + * (string, [c]string, [c]string) + */ +#define furi_string_replace_all(a, b, c) \ + FURI_STRING_SELECT3(furi_string_replace_all, furi_string_replace_all_str, a, b, c) + +/** + * @brief Search for a string (or C string) in a string + * (string, [c]string[, start=0]) + */ +#define furi_string_search(v, ...) \ + M_APPLY( \ + FURI_STRING_SELECT3, \ + furi_string_search, \ + furi_string_search_str, \ + v, \ + M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief Search for a C string in a string + * (string, cstring[, start=0]) + */ +#define furi_string_search_str(v, ...) \ + M_APPLY(furi_string_search_str, v, M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief Test if the string starts with the given string (or C string). + * (string, [c]string) + */ +#define furi_string_start_with(a, b) \ + FURI_STRING_SELECT2(furi_string_start_with, furi_string_start_with_str, a, b) + +/** + * @brief Test if the string ends with the given string (or C string). + * (string, [c]string) + */ +#define furi_string_end_with(a, b) \ + FURI_STRING_SELECT2(furi_string_end_with, furi_string_end_with_str, a, b) + +/** + * @brief Append a string (or C string) to the string. + * (string, [c]string) + */ +#define furi_string_cat(a, b) FURI_STRING_SELECT2(furi_string_cat, furi_string_cat_str, a, b) + +/** + * @brief Trim a string from the given set of characters (default is " \n\r\t"). + * (string[, set=" \n\r\t"]) + */ +#define furi_string_trim(...) M_APPLY(furi_string_trim, M_IF_DEFAULT1(" \n\r\t", __VA_ARGS__)) + +/** + * @brief Search for a character in a string. + * (string, character[, start=0]) + */ +#define furi_string_search_char(v, ...) \ + M_APPLY(furi_string_search_char, v, M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief Reverse Search for a character in a string. + * (string, character[, start=0]) + */ +#define furi_string_search_rchar(v, ...) \ + M_APPLY(furi_string_search_rchar, v, M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief Replace a string to another string (or C string to another C string) in a string. + * (string, [c]string, [c]string[, start=0]) + */ +#define furi_string_replace(a, b, ...) \ + M_APPLY( \ + FURI_STRING_SELECT4, \ + furi_string_replace, \ + furi_string_replace_str, \ + a, \ + b, \ + M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief Replace a C string to another C string in a string. + * (string, cstring, cstring[, start=0]) + */ +#define furi_string_replace_str(a, b, ...) \ + M_APPLY(furi_string_replace_str, a, b, M_IF_DEFAULT1(0, __VA_ARGS__)) + +/** + * @brief INIT OPLIST for FuriString. + */ +#define F_STR_INIT(a) ((a) = furi_string_alloc()) + +/** + * @brief INIT SET OPLIST for FuriString. + */ +#define F_STR_INIT_SET(a, b) ((a) = furi_string_alloc_set(b)) + +/** + * @brief OPLIST for FuriString. + */ +#define FURI_STRING_OPLIST \ + (INIT(F_STR_INIT), \ + INIT_SET(F_STR_INIT_SET), \ + SET(furi_string_set), \ + INIT_MOVE(furi_string_alloc_move), \ + MOVE(furi_string_move), \ + SWAP(furi_string_swap), \ + RESET(furi_string_reset), \ + EMPTY_P(furi_string_empty), \ + CLEAR(furi_string_free), \ + HASH(furi_string_hash), \ + EQUAL(furi_string_equal), \ + CMP(furi_string_cmp), \ + TYPE(FuriString*)) + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/furi/core/thread.c b/furi/core/thread.c index d06fa8b3..508146f6 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -5,10 +5,10 @@ #include "check.h" #include "common_defines.h" #include "mutex.h" +#include "string.h" #include #include "log.h" -#include #include #include @@ -18,7 +18,7 @@ typedef struct FuriThreadStdout FuriThreadStdout; struct FuriThreadStdout { FuriThreadStdoutWriteCallback write_callback; - string_t buffer; + FuriString* buffer; }; struct FuriThread { @@ -103,13 +103,14 @@ static void furi_thread_body(void* context) { furi_assert(pvTaskGetThreadLocalStoragePointer(NULL, 0) != NULL); vTaskSetThreadLocalStoragePointer(NULL, 0, NULL); + thread->task_handle = NULL; vTaskDelete(NULL); furi_thread_catch(); } FuriThread* furi_thread_alloc() { FuriThread* thread = malloc(sizeof(FuriThread)); - string_init(thread->output.buffer); + thread->output.buffer = furi_string_alloc(); thread->is_service = false; return thread; } @@ -119,7 +120,7 @@ void furi_thread_free(FuriThread* thread) { furi_assert(thread->state == FuriThreadStateStopped); if(thread->name) free((void*)thread->name); - string_clear(thread->output.buffer); + furi_string_free(thread->output.buffer); free(thread); } @@ -211,13 +212,8 @@ bool furi_thread_join(FuriThread* thread) { furi_check(furi_thread_get_current() != thread); - // Check if thread was started - if(thread->task_handle == NULL) { - return false; - } - // Wait for thread to stop - while(eTaskGetState(thread->task_handle) != eDeleted) { + while(thread->task_handle) { furi_delay_ms(10); } @@ -485,11 +481,11 @@ static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, s } static int32_t __furi_thread_stdout_flush(FuriThread* thread) { - string_ptr buffer = thread->output.buffer; - size_t size = string_size(buffer); + FuriString* buffer = thread->output.buffer; + size_t size = furi_string_size(buffer); if(size > 0) { - __furi_thread_stdout_write(thread, string_get_cstr(buffer), size); - string_reset(buffer); + __furi_thread_stdout_write(thread, furi_string_get_cstr(buffer), size); + furi_string_reset(buffer); } return 0; } @@ -516,7 +512,7 @@ size_t furi_thread_stdout_write(const char* data, size_t size) { } else { // string_cat doesn't work here because we need to write the exact size data for(size_t i = 0; i < size; i++) { - string_push_back(thread->output.buffer, data[i]); + furi_string_push_back(thread->output.buffer, data[i]); if(data[i] == '\n') { __furi_thread_stdout_flush(thread); } diff --git a/furi/furi.h b/furi/furi.h index 68914b50..3ce83422 100644 --- a/furi/furi.h +++ b/furi/furi.h @@ -2,21 +2,23 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "core/check.h" +#include "core/common_defines.h" +#include "core/event_flag.h" +#include "core/kernel.h" +#include "core/log.h" +#include "core/memmgr.h" +#include "core/memmgr_heap.h" +#include "core/message_queue.h" +#include "core/mutex.h" +#include "core/pubsub.h" +#include "core/record.h" +#include "core/semaphore.h" +#include "core/thread.h" +#include "core/timer.h" +#include "core/valuemutex.h" +#include "core/string.h" +#include "core/stream_buffer.h" #include diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index e2616549..3fe57162 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -57,11 +57,26 @@ static ELFSection* elf_file_get_section(ELFFile* elf, const char* name) { return ELFSectionDict_get(elf->sections, name); } -static void elf_file_put_section(ELFFile* elf, const char* name, ELFSection* section) { - ELFSectionDict_set_at(elf->sections, strdup(name), *section); +static ELFSection* elf_file_get_or_put_section(ELFFile* elf, const char* name) { + ELFSection* section_p = elf_file_get_section(elf, name); + if(!section_p) { + ELFSectionDict_set_at( + elf->sections, + strdup(name), + (ELFSection){ + .data = NULL, + .sec_idx = 0, + .size = 0, + .rel_count = 0, + .rel_offset = 0, + }); + section_p = elf_file_get_section(elf, name); + } + + return section_p; } -static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, string_t name) { +static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, FuriString* name) { bool result = false; off_t old = storage_file_tell(elf->fd); @@ -74,7 +89,7 @@ static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, string_t nam while(true) { uint16_t read = storage_file_read(elf->fd, buffer, ELF_NAME_BUFFER_LEN); - string_cat_str(name, buffer); + furi_string_cat(name, buffer); if(strlen(buffer) < ELF_NAME_BUFFER_LEN) { result = true; break; @@ -89,11 +104,11 @@ static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, string_t nam return result; } -static bool elf_read_section_name(ELFFile* elf, off_t offset, string_t name) { +static bool elf_read_section_name(ELFFile* elf, off_t offset, FuriString* name) { return elf_read_string_from_offset(elf, elf->section_table_strings + offset, name); } -static bool elf_read_symbol_name(ELFFile* elf, off_t offset, string_t name) { +static bool elf_read_symbol_name(ELFFile* elf, off_t offset, FuriString* name) { return elf_read_string_from_offset(elf, elf->symbol_table_strings + offset, name); } @@ -103,8 +118,11 @@ static bool elf_read_section_header(ELFFile* elf, size_t section_idx, Elf32_Shdr storage_file_read(elf->fd, section_header, sizeof(Elf32_Shdr)) == sizeof(Elf32_Shdr); } -static bool - elf_read_section(ELFFile* elf, size_t section_idx, Elf32_Shdr* section_header, string_t name) { +static bool elf_read_section( + ELFFile* elf, + size_t section_idx, + Elf32_Shdr* section_header, + FuriString* name) { if(!elf_read_section_header(elf, section_idx, section_header)) { return false; } @@ -116,7 +134,7 @@ static bool return true; } -static bool elf_read_symbol(ELFFile* elf, int n, Elf32_Sym* sym, string_t name) { +static bool elf_read_symbol(ELFFile* elf, int n, Elf32_Sym* sym, FuriString* name) { bool success = false; off_t old = storage_file_tell(elf->fd); off_t pos = elf->symbol_table + n * sizeof(Elf32_Sym); @@ -276,19 +294,17 @@ static void elf_relocate_mov(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { int32_t addend = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; /* imm16 */ uint32_t addr = (symAddr + addend); - if (type == R_ARM_THM_MOVT_ABS) { + if(type == R_ARM_THM_MOVT_ABS) { addr >>= 16; /* upper 16 bits */ } else { addr &= 0x0000FFFF; /* lower 16 bits */ } /* Re-encode */ - ((uint16_t*)relAddr)[0] = (upper_insn & 0xFBF0) - | (((addr >> 11) & 1) << 10) /* i */ - | ((addr >> 12) & 0x000F); /* imm4 */ - ((uint16_t*)relAddr)[1] = (lower_insn & 0x8F00) - | (((addr >> 8) & 0x7) << 12) /* imm3 */ - | (addr & 0x00FF); /* imm8 */ + ((uint16_t*)relAddr)[0] = (upper_insn & 0xFBF0) | (((addr >> 11) & 1) << 10) /* i */ + | ((addr >> 12) & 0x000F); /* imm4 */ + ((uint16_t*)relAddr)[1] = (lower_insn & 0x8F00) | (((addr >> 8) & 0x7) << 12) /* imm3 */ + | (addr & 0x00FF); /* imm8 */ } static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { @@ -307,7 +323,10 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3 case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: elf_relocate_mov(relAddr, type, symAddr); - FURI_LOG_D(TAG, " R_ARM_THM_MOVW_ABS_NC/MOVT_ABS relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); + FURI_LOG_D( + TAG, + " R_ARM_THM_MOVW_ABS_NC/MOVT_ABS relocated is 0x%08X", + (unsigned int)*((uint32_t*)relAddr)); break; default: FURI_LOG_E(TAG, " Undefined relocation %d", type); @@ -316,17 +335,17 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3 return true; } -static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { +static bool elf_relocate(ELFFile* elf, ELFSection* s) { if(s->data) { Elf32_Rel rel; - size_t relEntries = h->sh_size / sizeof(rel); + size_t relEntries = s->rel_count; size_t relCount; - (void)storage_file_seek(elf->fd, h->sh_offset, true); + (void)storage_file_seek(elf->fd, s->rel_offset, true); FURI_LOG_D(TAG, " Offset Info Type Name"); int relocate_result = true; - string_t symbol_name; - string_init(symbol_name); + FuriString* symbol_name; + symbol_name = furi_string_alloc(); for(relCount = 0; relCount < relEntries; relCount++) { if(relCount % RESOLVER_THREAD_YIELD_STEP == 0) { @@ -336,7 +355,7 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { if(storage_file_read(elf->fd, &rel, sizeof(Elf32_Rel)) != sizeof(Elf32_Rel)) { FURI_LOG_E(TAG, " reloc read fail"); - string_clear(symbol_name); + furi_string_free(symbol_name); return false; } @@ -348,10 +367,10 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { if(!address_cache_get(elf->relocation_cache, symEntry, &symAddr)) { Elf32_Sym sym; - string_reset(symbol_name); + furi_string_reset(symbol_name); if(!elf_read_symbol(elf, symEntry, &sym, symbol_name)) { FURI_LOG_E(TAG, " symbol read fail"); - string_clear(symbol_name); + furi_string_free(symbol_name); return false; } @@ -361,9 +380,9 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { (unsigned int)rel.r_offset, (unsigned int)rel.r_info, elf_reloc_type_to_str(relType), - string_get_cstr(symbol_name)); + furi_string_get_cstr(symbol_name)); - symAddr = elf_address_of(elf, &sym, string_get_cstr(symbol_name)); + symAddr = elf_address_of(elf, &sym, furi_string_get_cstr(symbol_name)); address_cache_put(elf->relocation_cache, symEntry, symAddr); } @@ -377,11 +396,11 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { relocate_result = false; } } else { - FURI_LOG_E(TAG, " No symbol address of %s", string_get_cstr(symbol_name)); + FURI_LOG_E(TAG, " No symbol address of %s", furi_string_get_cstr(symbol_name)); relocate_result = false; } } - string_clear(symbol_name); + furi_string_free(symbol_name); return relocate_result; } else { @@ -391,14 +410,6 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { return false; } -/**************************************************************************************************/ -/********************************************* MISC ***********************************************/ -/**************************************************************************************************/ - -static bool cstr_prefix(const char* prefix, const char* string) { - return strncmp(prefix, string, strlen(prefix)) == 0; -} - /**************************************************************************************************/ /************************************ Internal FAP interfaces *************************************/ /**************************************************************************************************/ @@ -441,81 +452,137 @@ static bool elf_load_debug_link(ELFFile* elf, Elf32_Shdr* section_header) { section_header->sh_size; } +static bool str_prefix(const char* str, const char* prefix) { + return strncmp(prefix, str, strlen(prefix)) == 0; +} + +static bool elf_load_section_data(ELFFile* elf, ELFSection* section, Elf32_Shdr* section_header) { + if(section_header->sh_size == 0) { + FURI_LOG_D(TAG, "No data for section"); + return true; + } + + section->data = aligned_malloc(section_header->sh_size, section_header->sh_addralign); + section->size = section_header->sh_size; + + if(section_header->sh_type == SHT_NOBITS) { + // BSS section, no data to load + return true; + } + + if((!storage_file_seek(elf->fd, section_header->sh_offset, true)) || + (storage_file_read(elf->fd, section->data, section_header->sh_size) != + section_header->sh_size)) { + FURI_LOG_E(TAG, " seek/read fail"); + return false; + } + + FURI_LOG_D(TAG, "0x%X", section->data); + return true; +} + static SectionType elf_preload_section( ELFFile* elf, size_t section_idx, Elf32_Shdr* section_header, - string_t name_string, + FuriString* name_string, FlipperApplicationManifest* manifest) { - const char* name = string_get_cstr(name_string); + const char* name = furi_string_get_cstr(name_string); - const struct { - const char* prefix; - SectionType type; - } lookup_sections[] = { - {".text", SectionTypeData}, - {".rodata", SectionTypeData}, - {".data", SectionTypeData}, - {".bss", SectionTypeData}, - {".preinit_array", SectionTypeData}, - {".init_array", SectionTypeData}, - {".fini_array", SectionTypeData}, - {".rel.text", SectionTypeRelData}, - {".rel.rodata", SectionTypeRelData}, - {".rel.data", SectionTypeRelData}, - {".rel.preinit_array", SectionTypeRelData}, - {".rel.init_array", SectionTypeRelData}, - {".rel.fini_array", SectionTypeRelData}, - }; +#ifdef ELF_DEBUG_LOG + // log section name, type and flags + FuriString* flags_string = furi_string_alloc(); + if(section_header->sh_flags & SHF_WRITE) furi_string_cat(flags_string, "W"); + if(section_header->sh_flags & SHF_ALLOC) furi_string_cat(flags_string, "A"); + if(section_header->sh_flags & SHF_EXECINSTR) furi_string_cat(flags_string, "X"); + if(section_header->sh_flags & SHF_MERGE) furi_string_cat(flags_string, "M"); + if(section_header->sh_flags & SHF_STRINGS) furi_string_cat(flags_string, "S"); + if(section_header->sh_flags & SHF_INFO_LINK) furi_string_cat(flags_string, "I"); + if(section_header->sh_flags & SHF_LINK_ORDER) furi_string_cat(flags_string, "L"); + if(section_header->sh_flags & SHF_OS_NONCONFORMING) furi_string_cat(flags_string, "O"); + if(section_header->sh_flags & SHF_GROUP) furi_string_cat(flags_string, "G"); + if(section_header->sh_flags & SHF_TLS) furi_string_cat(flags_string, "T"); + if(section_header->sh_flags & SHF_COMPRESSED) furi_string_cat(flags_string, "T"); + if(section_header->sh_flags & SHF_MASKOS) furi_string_cat(flags_string, "o"); + if(section_header->sh_flags & SHF_MASKPROC) furi_string_cat(flags_string, "p"); + if(section_header->sh_flags & SHF_ORDERED) furi_string_cat(flags_string, "R"); + if(section_header->sh_flags & SHF_EXCLUDE) furi_string_cat(flags_string, "E"); - for(size_t i = 0; i < COUNT_OF(lookup_sections); i++) { - if(cstr_prefix(lookup_sections[i].prefix, name)) { - FURI_LOG_D(TAG, "Found section %s", lookup_sections[i].prefix); + FURI_LOG_I( + TAG, + "Section %s: type: %ld, flags: %s", + name, + section_header->sh_type, + furi_string_get_cstr(flags_string)); + furi_string_free(flags_string); +#endif - if(lookup_sections[i].type == SectionTypeRelData) { - name = name + strlen(".rel"); - } + // ignore .ARM and .rel.ARM sections + // TODO: how to do it not by name? + // .ARM: type 0x70000001, flags SHF_ALLOC | SHF_LINK_ORDER + // .rel.ARM: type 0x9, flags SHT_REL + if(str_prefix(name, ".ARM.") || str_prefix(name, ".rel.ARM.")) { + FURI_LOG_D(TAG, "Ignoring ARM section"); + return SectionTypeUnused; + } - ELFSection* section_p = elf_file_get_section(elf, name); - if(!section_p) { - ELFSection section = { - .data = NULL, - .sec_idx = 0, - .rel_sec_idx = 0, - .size = 0, - }; + // Load allocable section + if(section_header->sh_flags & SHF_ALLOC) { + ELFSection* section_p = elf_file_get_or_put_section(elf, name); + section_p->sec_idx = section_idx; - elf_file_put_section(elf, name, §ion); - section_p = elf_file_get_section(elf, name); - } + if(section_header->sh_type == SHT_PREINIT_ARRAY) { + elf->preinit_array = section_p; + } else if(section_header->sh_type == SHT_INIT_ARRAY) { + elf->init_array = section_p; + } else if(section_header->sh_type == SHT_FINI_ARRAY) { + elf->fini_array = section_p; + } - if(lookup_sections[i].type == SectionTypeRelData) { - section_p->rel_sec_idx = section_idx; - } else { - section_p->sec_idx = section_idx; - } - - return lookup_sections[i].type; + if(!elf_load_section_data(elf, section_p, section_header)) { + FURI_LOG_E(TAG, "Error loading section '%s'", name); + return SectionTypeERROR; + } else { + return SectionTypeData; } } + // Load link info section + if(section_header->sh_flags & SHF_INFO_LINK) { + name = name + strlen(".rel"); + ELFSection* section_p = elf_file_get_or_put_section(elf, name); + section_p->rel_count = section_header->sh_size / sizeof(Elf32_Rel); + section_p->rel_offset = section_header->sh_offset; + return SectionTypeRelData; + } + + // Load symbol table if(strcmp(name, ".symtab") == 0) { FURI_LOG_D(TAG, "Found .symtab section"); elf->symbol_table = section_header->sh_offset; elf->symbol_count = section_header->sh_size / sizeof(Elf32_Sym); return SectionTypeSymTab; - } else if(strcmp(name, ".strtab") == 0) { + } + + // Load string table + if(strcmp(name, ".strtab") == 0) { FURI_LOG_D(TAG, "Found .strtab section"); elf->symbol_table_strings = section_header->sh_offset; return SectionTypeStrTab; - } else if(strcmp(name, ".fapmeta") == 0) { + } + + // Load manifest section + if(strcmp(name, ".fapmeta") == 0) { FURI_LOG_D(TAG, "Found .fapmeta section"); if(elf_load_metadata(elf, section_header, manifest)) { return SectionTypeManifest; } else { return SectionTypeERROR; } - } else if(strcmp(name, ".gnu_debuglink") == 0) { + } + + // Load debug link section + if(strcmp(name, ".gnu_debuglink") == 0) { FURI_LOG_D(TAG, "Found .gnu_debuglink section"); if(elf_load_debug_link(elf, section_header)) { return SectionTypeDebugLink; @@ -527,61 +594,17 @@ static SectionType elf_preload_section( return SectionTypeUnused; } -static bool elf_load_section_data(ELFFile* elf, ELFSection* section) { - Elf32_Shdr section_header; - if(section->sec_idx == 0) { - FURI_LOG_D(TAG, "Section is not present"); - return true; - } - - if(!elf_read_section_header(elf, section->sec_idx, §ion_header)) { - return false; - } - - if(section_header.sh_size == 0) { - FURI_LOG_D(TAG, "No data for section"); - return true; - } - - section->data = aligned_malloc(section_header.sh_size, section_header.sh_addralign); - section->size = section_header.sh_size; - - if(section_header.sh_type == SHT_NOBITS) { - /* section is empty (.bss?) */ - /* no need to memset - allocator already did that */ - return true; - } - - if((!storage_file_seek(elf->fd, section_header.sh_offset, true)) || - (storage_file_read(elf->fd, section->data, section_header.sh_size) != - section_header.sh_size)) { - FURI_LOG_E(TAG, " seek/read fail"); - return false; - } - - FURI_LOG_D(TAG, "0x%X", section->data); - return true; -} - static bool elf_relocate_section(ELFFile* elf, ELFSection* section) { - Elf32_Shdr section_header; - if(section->rel_sec_idx) { + if(section->rel_count) { FURI_LOG_D(TAG, "Relocating section"); - if(elf_read_section_header(elf, section->rel_sec_idx, §ion_header)) - return elf_relocate(elf, §ion_header, section); - else { - FURI_LOG_E(TAG, "Error reading section header"); - return false; - } + return elf_relocate(elf, section); } else { FURI_LOG_D(TAG, "No relocation index"); /* Not an error */ } return true; } -static void elf_file_call_section_list(ELFFile* elf, const char* name, bool reverse_order) { - ELFSection* section = elf_file_get_section(elf, name); - +static void elf_file_call_section_list(ELFSection* section, bool reverse_order) { if(section && section->size) { const uint32_t* start = section->data; const uint32_t* end = section->data + section->size; @@ -670,19 +693,19 @@ bool elf_file_open(ELFFile* elf, const char* path) { bool elf_file_load_manifest(ELFFile* elf, FlipperApplicationManifest* manifest) { bool result = false; - string_t name; - string_init(name); + FuriString* name; + name = furi_string_alloc(); FURI_LOG_D(TAG, "Looking for manifest section"); for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { Elf32_Shdr section_header; - string_reset(name); + furi_string_reset(name); if(!elf_read_section(elf, section_idx, §ion_header, name)) { break; } - if(string_cmp(name, ".fapmeta") == 0) { + if(furi_string_cmp(name, ".fapmeta") == 0) { if(elf_load_metadata(elf, §ion_header, manifest)) { FURI_LOG_D(TAG, "Load manifest done"); result = true; @@ -693,26 +716,27 @@ bool elf_file_load_manifest(ELFFile* elf, FlipperApplicationManifest* manifest) } } - string_clear(name); + furi_string_free(name); return result; } bool elf_file_load_section_table(ELFFile* elf, FlipperApplicationManifest* manifest) { SectionType loaded_sections = SectionTypeERROR; - string_t name; - string_init(name); + FuriString* name; + name = furi_string_alloc(); FURI_LOG_D(TAG, "Scan ELF indexs..."); for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { Elf32_Shdr section_header; - string_reset(name); + furi_string_reset(name); if(!elf_read_section(elf, section_idx, §ion_header, name)) { loaded_sections = SectionTypeERROR; break; } - FURI_LOG_D(TAG, "Preloading data for section #%d %s", section_idx, string_get_cstr(name)); + FURI_LOG_D( + TAG, "Preloading data for section #%d %s", section_idx, furi_string_get_cstr(name)); SectionType section_type = elf_preload_section(elf, section_idx, §ion_header, name, manifest); loaded_sections |= section_type; @@ -723,8 +747,7 @@ bool elf_file_load_section_table(ELFFile* elf, FlipperApplicationManifest* manif } } - string_clear(name); - FURI_LOG_D(TAG, "Load symbols done"); + furi_string_free(name); return IS_FLAGS_SET(loaded_sections, SectionTypeValid); } @@ -734,16 +757,6 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { ELFSectionDict_it_t it; AddressCache_init(elf->relocation_cache); - size_t start = furi_get_tick(); - - for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); ELFSectionDict_next(it)) { - ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); - FURI_LOG_D(TAG, "Loading section '%s'", itref->key); - if(!elf_load_section_data(elf, &itref->value)) { - FURI_LOG_E(TAG, "Error loading section '%s'", itref->key); - status = ELFFileLoadStatusUnspecifiedError; - } - } if(status == ELFFileLoadStatusSuccess) { for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); @@ -772,14 +785,13 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { FURI_LOG_D(TAG, "Relocation cache size: %u", AddressCache_size(elf->relocation_cache)); FURI_LOG_D(TAG, "Trampoline cache size: %u", AddressCache_size(elf->trampoline_cache)); AddressCache_clear(elf->relocation_cache); - FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); return status; } void elf_file_pre_run(ELFFile* elf) { - elf_file_call_section_list(elf, ".preinit_array", false); - elf_file_call_section_list(elf, ".init_array", false); + elf_file_call_section_list(elf->preinit_array, false); + elf_file_call_section_list(elf->init_array, false); } int32_t elf_file_run(ELFFile* elf, void* args) { @@ -789,7 +801,7 @@ int32_t elf_file_run(ELFFile* elf, void* args) { } void elf_file_post_run(ELFFile* elf) { - elf_file_call_section_list(elf, ".fini_array", true); + elf_file_call_section_list(elf->fini_array, true); } const ElfApiInterface* elf_file_get_api_interface(ELFFile* elf_file) { diff --git a/lib/flipper_application/elf/elf_file_i.h b/lib/flipper_application/elf/elf_file_i.h index 1df075f0..9b38540b 100644 --- a/lib/flipper_application/elf/elf_file_i.h +++ b/lib/flipper_application/elf/elf_file_i.h @@ -16,8 +16,10 @@ typedef int32_t(entry_t)(void*); typedef struct { void* data; uint16_t sec_idx; - uint16_t rel_sec_idx; Elf32_Word size; + + size_t rel_count; + Elf32_Off rel_offset; } ELFSection; DICT_DEF2(ELFSectionDict, const char*, M_CSTR_OPLIST, ELFSection, M_POD_OPLIST) @@ -39,6 +41,10 @@ struct ELFFile { File* fd; const ElfApiInterface* api_interface; ELFDebugLinkInfo debug_link_info; + + ELFSection* preinit_array; + ELFSection* init_array; + ELFSection* fini_array; }; #ifdef __cplusplus diff --git a/lib/flipper_format/flipper_format.c b/lib/flipper_format/flipper_format.c index 62005127..292dab5f 100644 --- a/lib/flipper_format/flipper_format.c +++ b/lib/flipper_format/flipper_format.c @@ -137,7 +137,7 @@ bool flipper_format_key_exist(FlipperFormat* flipper_format, const char* key) { bool flipper_format_read_header( FlipperFormat* flipper_format, - string_t filetype, + FuriString* filetype, uint32_t* version) { furi_assert(flipper_format); return flipper_format_read_string(flipper_format, flipper_format_filetype_key, filetype) && @@ -146,10 +146,11 @@ bool flipper_format_read_header( bool flipper_format_write_header( FlipperFormat* flipper_format, - string_t filetype, + FuriString* filetype, const uint32_t version) { furi_assert(flipper_format); - return flipper_format_write_header_cstr(flipper_format, string_get_cstr(filetype), version); + return flipper_format_write_header_cstr( + flipper_format, furi_string_get_cstr(filetype), version); } bool flipper_format_write_header_cstr( @@ -171,18 +172,18 @@ bool flipper_format_get_value_count( flipper_format->stream, key, count, flipper_format->strict_mode); } -bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, string_t data) { +bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, FuriString* data) { furi_assert(flipper_format); return flipper_format_stream_read_value_line( flipper_format->stream, key, FlipperStreamValueStr, data, 1, flipper_format->strict_mode); } -bool flipper_format_write_string(FlipperFormat* flipper_format, const char* key, string_t data) { +bool flipper_format_write_string(FlipperFormat* flipper_format, const char* key, FuriString* data) { furi_assert(flipper_format); FlipperStreamWriteData write_data = { .key = key, .type = FlipperStreamValueStr, - .data = string_get_cstr(data), + .data = furi_string_get_cstr(data), .data_size = 1, }; bool result = flipper_format_stream_write_value_line(flipper_format->stream, &write_data); @@ -386,9 +387,9 @@ bool flipper_format_write_hex( return result; } -bool flipper_format_write_comment(FlipperFormat* flipper_format, string_t data) { +bool flipper_format_write_comment(FlipperFormat* flipper_format, FuriString* data) { furi_assert(flipper_format); - return flipper_format_write_comment_cstr(flipper_format, string_get_cstr(data)); + return flipper_format_write_comment_cstr(flipper_format, furi_string_get_cstr(data)); } bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char* data) { @@ -409,12 +410,12 @@ bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) { return result; } -bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key, string_t data) { +bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key, FuriString* data) { furi_assert(flipper_format); FlipperStreamWriteData write_data = { .key = key, .type = FlipperStreamValueStr, - .data = string_get_cstr(data), + .data = furi_string_get_cstr(data), .data_size = 1, }; bool result = flipper_format_stream_delete_key_and_write( @@ -522,7 +523,7 @@ bool flipper_format_update_hex( bool flipper_format_insert_or_update_string( FlipperFormat* flipper_format, const char* key, - string_t data) { + FuriString* data) { bool result = false; if(!flipper_format_key_exist(flipper_format, key)) { diff --git a/lib/flipper_format/flipper_format.h b/lib/flipper_format/flipper_format.h index 9e82bb31..743918e3 100644 --- a/lib/flipper_format/flipper_format.h +++ b/lib/flipper_format/flipper_format.h @@ -70,13 +70,13 @@ * * do { * uint32_t version = 1; - * string_t file_type; - * string_t string_value; + * FuriString* file_type; + * FuriString* string_value; * uint32_t uint32_value = 1; * uint16_t array_size = 4; * uint8_t* array[array_size] = {0}; - * string_init(file_type); - * string_init(string_value); + * file_type = furi_string_alloc(); + * string_value = furi_string_alloc(); * * if(!flipper_format_file_open_existing(file, EXT_PATH("flipper_format_test"))) break; * if(!flipper_format_read_header(file, file_type, &version)) break; @@ -94,7 +94,6 @@ #pragma once #include -#include #include #ifdef __cplusplus @@ -227,7 +226,7 @@ bool flipper_format_key_exist(FlipperFormat* flipper_format, const char* key); */ bool flipper_format_read_header( FlipperFormat* flipper_format, - string_t filetype, + FuriString* filetype, uint32_t* version); /** @@ -239,7 +238,7 @@ bool flipper_format_read_header( */ bool flipper_format_write_header( FlipperFormat* flipper_format, - string_t filetype, + FuriString* filetype, const uint32_t version); /** @@ -273,7 +272,7 @@ bool flipper_format_get_value_count( * @param data Value * @return True on success */ -bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, string_t data); +bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, FuriString* data); /** * Write key and string @@ -282,7 +281,7 @@ bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, * @param data Value * @return True on success */ -bool flipper_format_write_string(FlipperFormat* flipper_format, const char* key, string_t data); +bool flipper_format_write_string(FlipperFormat* flipper_format, const char* key, FuriString* data); /** * Write key and string. Plain C string version. @@ -470,7 +469,7 @@ bool flipper_format_write_hex( * @param data Comment text * @return True on success */ -bool flipper_format_write_comment(FlipperFormat* flipper_format, string_t data); +bool flipper_format_write_comment(FlipperFormat* flipper_format, FuriString* data); /** * Write comment. Plain C string version. @@ -495,7 +494,7 @@ bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key); * @param data Value * @return True on success */ -bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key, string_t data); +bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key, FuriString* data); /** * Updates the value of the first matching key to a string value. Plain C version. Sets the RW pointer to a position at the end of inserted data. @@ -585,7 +584,7 @@ bool flipper_format_update_hex( bool flipper_format_insert_or_update_string( FlipperFormat* flipper_format, const char* key, - string_t data); + FuriString* data); /** * Updates the value of the first matching key to a string value, or adds the key and value if the key did not exist. diff --git a/lib/flipper_format/flipper_format_stream.c b/lib/flipper_format/flipper_format_stream.c index e4b7b300..41934a3b 100644 --- a/lib/flipper_format/flipper_format_stream.c +++ b/lib/flipper_format/flipper_format_stream.c @@ -4,6 +4,10 @@ #include "flipper_format_stream.h" #include "flipper_format_stream_i.h" +static inline bool flipper_format_stream_is_space(char c) { + return c == ' ' || c == '\t' || c == flipper_format_eolr; +} + static bool flipper_format_stream_write(Stream* stream, const void* data, size_t data_size) { size_t bytes_written = stream_write(stream, data, data_size); return bytes_written == data_size; @@ -26,8 +30,8 @@ bool flipper_format_stream_write_eol(Stream* stream) { return flipper_format_stream_write(stream, &flipper_format_eoln, 1); } -static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) { - string_reset(key); +static bool flipper_format_stream_read_valid_key(Stream* stream, FuriString* key) { + furi_string_reset(key); const size_t buffer_size = 32; uint8_t buffer[buffer_size]; @@ -44,7 +48,7 @@ static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) { uint8_t data = buffer[i]; if(data == flipper_format_eoln) { // EOL found, clean data, start accumulating data and set the new_line flag - string_reset(key); + furi_string_reset(key); accumulate = true; new_line = true; } else if(data == flipper_format_eolr) { @@ -60,7 +64,7 @@ static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) { // this can only be if we have previously found some kind of key, so // clear the data, set the flag that we no longer want to accumulate data // and reset the new_line flag - string_reset(key); + furi_string_reset(key); accumulate = false; new_line = false; } else { @@ -82,7 +86,7 @@ static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) { new_line = false; if(accumulate) { // and accumulate data if we want - string_push_back(key, data); + furi_string_push_back(key, data); } } } @@ -95,13 +99,13 @@ static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) { bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode) { bool found = false; - string_t read_key; + FuriString* read_key; - string_init(read_key); + read_key = furi_string_alloc(); while(!stream_eof(stream)) { if(flipper_format_stream_read_valid_key(stream, read_key)) { - if(string_cmp_str(read_key, key) == 0) { + if(furi_string_cmp_str(read_key, key) == 0) { if(!stream_seek(stream, 2, StreamOffsetFromCurrent)) break; found = true; @@ -112,61 +116,70 @@ bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool str } } } - string_clear(read_key); + furi_string_free(read_key); return found; } -static bool flipper_format_stream_read_value(Stream* stream, string_t value, bool* last) { - string_reset(value); +static bool flipper_format_stream_read_value(Stream* stream, FuriString* value, bool* last) { + enum { LeadingSpace, ReadValue, TrailingSpace } state = LeadingSpace; const size_t buffer_size = 32; uint8_t buffer[buffer_size]; bool result = false; bool error = false; + furi_string_reset(value); + while(true) { size_t was_read = stream_read(stream, buffer, buffer_size); if(was_read == 0) { - // check EOF - if(stream_eof(stream) && string_size(value) > 0) { + if(state != LeadingSpace && stream_eof(stream)) { result = true; *last = true; - break; + } else { + error = true; } } for(uint16_t i = 0; i < was_read; i++) { - uint8_t data = buffer[i]; - if(data == flipper_format_eoln) { - if(string_size(value) > 0) { - if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) { - error = true; - break; - } + const uint8_t data = buffer[i]; - result = true; - *last = true; + if(state == LeadingSpace) { + if(flipper_format_stream_is_space(data)) { + continue; + } else if(data == flipper_format_eoln) { + stream_seek(stream, i - was_read, StreamOffsetFromCurrent); + error = true; break; } else { - error = true; + state = ReadValue; + furi_string_push_back(value, data); } - } else if(data == ' ') { - if(string_size(value) > 0) { + } else if(state == ReadValue) { + if(flipper_format_stream_is_space(data)) { + state = TrailingSpace; + } else if(data == flipper_format_eoln) { if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) { error = true; - break; + } else { + result = true; + *last = true; } - - result = true; - *last = false; break; + } else { + furi_string_push_back(value, data); } - - } else if(data == flipper_format_eolr) { - // Ignore - } else { - string_push_back(value, data); + } else if(state == TrailingSpace) { + if(flipper_format_stream_is_space(data)) { + continue; + } else if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) { + error = true; + } else { + *last = (data == flipper_format_eoln); + result = true; + } + break; } } @@ -176,8 +189,8 @@ static bool flipper_format_stream_read_value(Stream* stream, string_t value, boo return result; } -static bool flipper_format_stream_read_line(Stream* stream, string_t str_result) { - string_reset(str_result); +static bool flipper_format_stream_read_line(Stream* stream, FuriString* str_result) { + furi_string_reset(str_result); const size_t buffer_size = 32; uint8_t buffer[buffer_size]; @@ -201,7 +214,7 @@ static bool flipper_format_stream_read_line(Stream* stream, string_t str_result) } else if(data == flipper_format_eolr) { // Ignore } else { - string_push_back(str_result, data); + furi_string_push_back(str_result, data); } } @@ -210,7 +223,7 @@ static bool flipper_format_stream_read_line(Stream* stream, string_t str_result) } } while(true); - return string_size(str_result) != 0; + return furi_string_size(str_result) != 0; } static bool flipper_format_stream_seek_to_next_line(Stream* stream) { @@ -254,8 +267,8 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa if(write_data->type == FlipperStreamValueIgnore) { result = true; } else { - string_t value; - string_init(value); + FuriString* value; + value = furi_string_alloc(); do { if(!flipper_format_stream_write_key(stream, write_data->key)) break; @@ -267,45 +280,45 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa switch(write_data->type) { case FlipperStreamValueStr: { const char* data = write_data->data; - string_printf(value, "%s", data); + furi_string_printf(value, "%s", data); }; break; case FlipperStreamValueHex: { const uint8_t* data = write_data->data; - string_printf(value, "%02X", data[i]); + furi_string_printf(value, "%02X", data[i]); }; break; #ifndef FLIPPER_STREAM_LITE case FlipperStreamValueFloat: { const float* data = write_data->data; - string_printf(value, "%f", (double)data[i]); + furi_string_printf(value, "%f", (double)data[i]); }; break; #endif case FlipperStreamValueInt32: { const int32_t* data = write_data->data; - string_printf(value, "%" PRIi32, data[i]); + furi_string_printf(value, "%" PRIi32, data[i]); }; break; case FlipperStreamValueUint32: { const uint32_t* data = write_data->data; - string_printf(value, "%" PRId32, data[i]); + furi_string_printf(value, "%" PRId32, data[i]); }; break; case FlipperStreamValueHexUint64: { const uint64_t* data = write_data->data; - string_printf( + furi_string_printf( value, "%08lX%08lX", (uint32_t)(data[i] >> 32), (uint32_t)data[i]); }; break; case FlipperStreamValueBool: { const bool* data = write_data->data; - string_printf(value, data[i] ? "true" : "false"); + furi_string_printf(value, data[i] ? "true" : "false"); }; break; default: furi_crash("Unknown FF type"); } if((size_t)(i + 1) < write_data->data_size) { - string_cat(value, " "); + furi_string_cat(value, " "); } if(!flipper_format_stream_write( - stream, string_get_cstr(value), string_size(value))) { + stream, furi_string_get_cstr(value), furi_string_size(value))) { cycle_error = true; break; } @@ -316,7 +329,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa result = true; } while(false); - string_clear(value); + furi_string_free(value); } return result; @@ -335,15 +348,15 @@ bool flipper_format_stream_read_value_line( if(!flipper_format_stream_seek_to_key(stream, key, strict_mode)) break; if(type == FlipperStreamValueStr) { - string_ptr data = (string_ptr)_data; + FuriString* data = (FuriString*)_data; if(flipper_format_stream_read_line(stream, data)) { result = true; break; } } else { result = true; - string_t value; - string_init(value); + FuriString* value; + value = furi_string_alloc(); for(size_t i = 0; i < data_size; i++) { bool last = false; @@ -354,11 +367,11 @@ bool flipper_format_stream_read_value_line( switch(type) { case FlipperStreamValueHex: { uint8_t* data = _data; - if(string_size(value) >= 2) { + if(furi_string_size(value) >= 2) { // sscanf "%02X" does not work here if(hex_char_to_uint8( - string_get_char(value, 0), - string_get_char(value, 1), + furi_string_get_char(value, 0), + furi_string_get_char(value, 1), &data[i])) { scan_values = 1; } @@ -368,9 +381,9 @@ bool flipper_format_stream_read_value_line( case FlipperStreamValueFloat: { float* data = _data; // newlib-nano does not have sscanf for floats - // scan_values = sscanf(string_get_cstr(value), "%f", &data[i]); + // scan_values = sscanf(furi_string_get_cstr(value), "%f", &data[i]); char* end_char; - data[i] = strtof(string_get_cstr(value), &end_char); + data[i] = strtof(furi_string_get_cstr(value), &end_char); if(*end_char == 0) { // most likely ok scan_values = 1; @@ -379,23 +392,23 @@ bool flipper_format_stream_read_value_line( #endif case FlipperStreamValueInt32: { int32_t* data = _data; - scan_values = sscanf(string_get_cstr(value), "%" PRIi32, &data[i]); + scan_values = sscanf(furi_string_get_cstr(value), "%" PRIi32, &data[i]); }; break; case FlipperStreamValueUint32: { uint32_t* data = _data; - scan_values = sscanf(string_get_cstr(value), "%" PRId32, &data[i]); + scan_values = sscanf(furi_string_get_cstr(value), "%" PRId32, &data[i]); }; break; case FlipperStreamValueHexUint64: { uint64_t* data = _data; - if(string_size(value) >= 16) { - if(hex_chars_to_uint64(string_get_cstr(value), &data[i])) { + if(furi_string_size(value) >= 16) { + if(hex_chars_to_uint64(furi_string_get_cstr(value), &data[i])) { scan_values = 1; } } }; break; case FlipperStreamValueBool: { bool* data = _data; - data[i] = !string_cmpi_str(value, "true"); + data[i] = !furi_string_cmpi(value, "true"); scan_values = 1; }; break; default: @@ -416,7 +429,7 @@ bool flipper_format_stream_read_value_line( } } - string_clear(value); + furi_string_free(value); } } while(false); @@ -431,8 +444,8 @@ bool flipper_format_stream_get_value_count( bool result = false; bool last = false; - string_t value; - string_init(value); + FuriString* value; + value = furi_string_alloc(); uint32_t position = stream_tell(stream); do { @@ -456,7 +469,7 @@ bool flipper_format_stream_get_value_count( result = false; } - string_clear(value); + furi_string_free(value); return result; } diff --git a/lib/flipper_format/flipper_format_stream.h b/lib/flipper_format/flipper_format_stream.h index 75eaef20..88b096b2 100644 --- a/lib/flipper_format/flipper_format_stream.h +++ b/lib/flipper_format/flipper_format_stream.h @@ -2,7 +2,6 @@ #include #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 2b4e3cdb..86b19114 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -9,7 +9,6 @@ #include #include -#include #define INFRARED_WORKER_RX_TIMEOUT INFRARED_RAW_RX_TIMING_DELAY_US @@ -50,7 +49,7 @@ struct InfraredWorkerSignal { struct InfraredWorker { FuriThread* thread; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; InfraredWorkerSignal signal; InfraredWorkerState state; @@ -100,15 +99,13 @@ static void infrared_worker_rx_timeout_callback(void* context) { static void infrared_worker_rx_callback(void* context, bool level, uint32_t duration) { InfraredWorker* instance = context; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; furi_assert(duration != 0); LevelDuration level_duration = level_duration_make(level, duration); - size_t ret = xStreamBufferSendFromISR( - instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken); + size_t ret = + furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0); uint32_t events = (ret == sizeof(LevelDuration)) ? INFRARED_WORKER_RX_RECEIVED : INFRARED_WORKER_OVERRUN; - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); uint32_t flags_set = furi_thread_flags_set(furi_thread_get_id(instance->thread), events); furi_check(flags_set & events); @@ -179,7 +176,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { if(instance->signal.timings_cnt == 0) notification_message(instance->notification, &sequence_display_backlight_on); while(sizeof(LevelDuration) == - xStreamBufferReceive( + furi_stream_buffer_receive( instance->stream, &level_duration, sizeof(LevelDuration), 0)) { if(!instance->rx.overrun) { bool level = level_duration_get_level(level_duration); @@ -232,7 +229,7 @@ InfraredWorker* infrared_worker_alloc() { size_t buffer_size = MAX(sizeof(InfraredWorkerTiming) * (MAX_TIMINGS_AMOUNT + 1), sizeof(LevelDuration) * MAX_TIMINGS_AMOUNT); - instance->stream = xStreamBufferCreate(buffer_size, sizeof(InfraredWorkerTiming)); + instance->stream = furi_stream_buffer_alloc(buffer_size, sizeof(InfraredWorkerTiming)); instance->infrared_decoder = infrared_alloc_decoder(); instance->infrared_encoder = infrared_alloc_encoder(); instance->blink_enable = false; @@ -249,7 +246,7 @@ void infrared_worker_free(InfraredWorker* instance) { furi_record_close(RECORD_NOTIFICATION); infrared_free_decoder(instance->infrared_decoder); infrared_free_encoder(instance->infrared_encoder); - vStreamBufferDelete(instance->stream); + furi_stream_buffer_free(instance->stream); furi_thread_free(instance->thread); free(instance); @@ -259,7 +256,7 @@ void infrared_worker_rx_start(InfraredWorker* instance) { furi_assert(instance); furi_assert(instance->state == InfraredWorkerStateIdle); - xStreamBufferSetTriggerLevel(instance->stream, sizeof(LevelDuration)); + furi_stream_set_trigger_level(instance->stream, sizeof(LevelDuration)); furi_thread_set_callback(instance->thread, infrared_worker_rx_thread); furi_thread_start(instance->thread); @@ -285,9 +282,9 @@ void infrared_worker_rx_stop(InfraredWorker* instance) { furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT); furi_thread_join(instance->thread); - BaseType_t xReturn = xStreamBufferReset(instance->stream); - furi_assert(xReturn == pdPASS); - (void)xReturn; + FuriStatus status = furi_stream_buffer_reset(instance->stream); + furi_assert(status == FuriStatusOk); + (void)status; instance->state = InfraredWorkerStateIdle; } @@ -325,7 +322,7 @@ void infrared_worker_tx_start(InfraredWorker* instance) { furi_assert(instance->tx.get_signal_callback); // size have to be greater than api hal infrared async tx buffer size - xStreamBufferSetTriggerLevel(instance->stream, sizeof(InfraredWorkerTiming)); + furi_stream_set_trigger_level(instance->stream, sizeof(InfraredWorkerTiming)); furi_thread_set_callback(instance->thread, infrared_worker_tx_thread); @@ -358,7 +355,7 @@ static FuriHalInfraredTxGetDataState FuriHalInfraredTxGetDataState state; if(sizeof(InfraredWorkerTiming) == - xStreamBufferReceiveFromISR(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0)) { + furi_stream_buffer_receive(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0)) { *level = timing.level; *duration = timing.duration; state = timing.state; @@ -420,7 +417,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { InfraredWorkerTiming timing; InfraredStatus status = InfraredStatusError; - while(!xStreamBufferIsFull(instance->stream) && !instance->tx.need_reinitialization && + while(!furi_stream_buffer_is_full(instance->stream) && !instance->tx.need_reinitialization && new_data_available) { if(instance->signal.decoded) { status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level); @@ -454,7 +451,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { furi_assert(0); } uint32_t written_size = - xStreamBufferSend(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0); + furi_stream_buffer_send(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0); furi_assert(sizeof(InfraredWorkerTiming) == written_size); (void)written_size; } @@ -564,10 +561,9 @@ void infrared_worker_tx_stop(InfraredWorker* instance) { furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL); instance->signal.timings_cnt = 0; - BaseType_t xReturn = pdFAIL; - xReturn = xStreamBufferReset(instance->stream); - furi_assert(xReturn == pdPASS); - (void)xReturn; + FuriStatus status = furi_stream_buffer_reset(instance->stream); + furi_assert(status == FuriStatusOk); + (void)status; instance->state = InfraredWorkerStateIdle; } diff --git a/lib/lfrfid/lfrfid_dict_file.c b/lib/lfrfid/lfrfid_dict_file.c index bb6af39a..7ae84f8b 100644 --- a/lib/lfrfid/lfrfid_dict_file.c +++ b/lib/lfrfid/lfrfid_dict_file.c @@ -143,8 +143,8 @@ ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) { FlipperFormat* file = flipper_format_file_alloc(storage); ProtocolId result = PROTOCOL_NO; uint8_t* data = malloc(protocol_dict_get_max_data_size(dict)); - string_t str_result; - string_init(str_result); + FuriString* str_result; + str_result = furi_string_alloc(); do { if(!flipper_format_file_open_existing(file, filename)) break; @@ -152,16 +152,16 @@ ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) { // header uint32_t version; if(!flipper_format_read_header(file, str_result, &version)) break; - if(string_cmp_str(str_result, LFRFID_DICT_FILETYPE) != 0) break; + if(furi_string_cmp_str(str_result, LFRFID_DICT_FILETYPE) != 0) break; if(version != 1) break; // type if(!flipper_format_read_string(file, "Key type", str_result)) break; ProtocolId protocol; - protocol = protocol_dict_get_protocol_by_name(dict, string_get_cstr(str_result)); + protocol = protocol_dict_get_protocol_by_name(dict, furi_string_get_cstr(str_result)); if(protocol == PROTOCOL_NO) { - protocol = lfrfid_dict_protocol_fallback(dict, string_get_cstr(str_result), file); + protocol = lfrfid_dict_protocol_fallback(dict, furi_string_get_cstr(str_result), file); if(protocol == PROTOCOL_NO) break; } else { // data @@ -174,7 +174,7 @@ ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) { } while(false); free(data); - string_clear(str_result); + furi_string_free(str_result); flipper_format_free(file); furi_record_close(RECORD_STORAGE); diff --git a/lib/lfrfid/lfrfid_raw_worker.c b/lib/lfrfid/lfrfid_raw_worker.c index 4050a8ca..1547d20f 100644 --- a/lib/lfrfid/lfrfid_raw_worker.c +++ b/lib/lfrfid/lfrfid_raw_worker.c @@ -2,7 +2,6 @@ #include #include #include -#include #include "lfrfid_raw_worker.h" #include "lfrfid_raw_file.h" #include "tools/varint_pair.h" @@ -16,7 +15,7 @@ // emulate mode typedef struct { size_t overrun_count; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; } RfidEmulateCtx; typedef struct { @@ -40,7 +39,7 @@ typedef struct { // main worker struct LFRFIDRawWorker { - string_t file_path; + FuriString* file_path; FuriThread* thread; FuriEventFlag* events; @@ -69,14 +68,14 @@ LFRFIDRawWorker* lfrfid_raw_worker_alloc() { worker->events = furi_event_flag_alloc(NULL); - string_init(worker->file_path); + worker->file_path = furi_string_alloc(); return worker; } void lfrfid_raw_worker_free(LFRFIDRawWorker* worker) { furi_thread_free(worker->thread); furi_event_flag_free(worker->events); - string_clear(worker->file_path); + furi_string_free(worker->file_path); free(worker); } @@ -89,7 +88,7 @@ void lfrfid_raw_worker_start_read( void* context) { furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped); - string_set(worker->file_path, file_path); + furi_string_set(worker->file_path, file_path); worker->frequency = freq; worker->duty_cycle = duty_cycle; @@ -107,7 +106,7 @@ void lfrfid_raw_worker_start_emulate( LFRFIDWorkerEmulateRawCallback callback, void* context) { furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped); - string_set(worker->file_path, file_path); + furi_string_set(worker->file_path, file_path); worker->emulate_callback = callback; worker->context = context; furi_thread_set_callback(worker->thread, lfrfid_raw_emulate_worker_thread); @@ -126,20 +125,13 @@ void lfrfid_raw_worker_stop(LFRFIDRawWorker* worker) { static void lfrfid_raw_worker_capture(bool level, uint32_t duration, void* context) { LFRFIDRawWorkerReadData* ctx = context; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - bool need_to_send = varint_pair_pack(ctx->pair, level, duration); if(need_to_send) { buffer_stream_send_from_isr( - ctx->stream, - varint_pair_get_data(ctx->pair), - varint_pair_get_size(ctx->pair), - &xHigherPriorityTaskWoken); + ctx->stream, varint_pair_get_data(ctx->pair), varint_pair_get_size(ctx->pair)); varint_pair_reset(ctx->pair); } - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } static int32_t lfrfid_raw_read_worker_thread(void* thread_context) { @@ -147,7 +139,7 @@ static int32_t lfrfid_raw_read_worker_thread(void* thread_context) { Storage* storage = furi_record_open(RECORD_STORAGE); LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage); - const char* filename = string_get_cstr(worker->file_path); + const char* filename = furi_string_get_cstr(worker->file_path); bool file_valid = lfrfid_raw_file_open_write(file, filename); LFRFIDRawWorkerReadData* data = malloc(sizeof(LFRFIDRawWorkerReadData)); @@ -236,7 +228,7 @@ static void rfid_emulate_dma_isr(bool half, void* context) { RfidEmulateCtx* ctx = context; uint32_t flag = half ? HalfTransfer : TransferComplete; - size_t len = xStreamBufferSendFromISR(ctx->stream, &flag, sizeof(uint32_t), pdFALSE); + size_t len = furi_stream_buffer_send(ctx->stream, &flag, sizeof(uint32_t), 0); if(len != sizeof(uint32_t)) { ctx->overrun_count++; } @@ -251,12 +243,12 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) { Storage* storage = furi_record_open(RECORD_STORAGE); data->ctx.overrun_count = 0; - data->ctx.stream = xStreamBufferCreate(sizeof(uint32_t), sizeof(uint32_t)); + data->ctx.stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t)); LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage); do { - file_valid = lfrfid_raw_file_open_read(file, string_get_cstr(worker->file_path)); + file_valid = lfrfid_raw_file_open_read(file, furi_string_get_cstr(worker->file_path)); if(!file_valid) break; file_valid = lfrfid_raw_file_read_header(file, &worker->frequency, &worker->duty_cycle); if(!file_valid) break; @@ -287,7 +279,8 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) { uint32_t flag = 0; while(true) { - size_t size = xStreamBufferReceive(data->ctx.stream, &flag, sizeof(uint32_t), 100); + size_t size = + furi_stream_buffer_receive(data->ctx.stream, &flag, sizeof(uint32_t), 100); if(size == sizeof(uint32_t)) { size_t start = 0; @@ -345,10 +338,10 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) { } if(data->ctx.overrun_count) { - FURI_LOG_E(TAG_EMULATE, "overruns: %lu", data->ctx.overrun_count); + FURI_LOG_E(TAG_EMULATE, "overruns: %u", data->ctx.overrun_count); } - vStreamBufferDelete(data->ctx.stream); + furi_stream_buffer_free(data->ctx.stream); lfrfid_raw_file_free(file); furi_record_close(RECORD_STORAGE); free(data); diff --git a/lib/lfrfid/lfrfid_worker_modes.c b/lib/lfrfid/lfrfid_worker_modes.c index 16936cca..1fbae04c 100644 --- a/lib/lfrfid/lfrfid_worker_modes.c +++ b/lib/lfrfid/lfrfid_worker_modes.c @@ -2,7 +2,6 @@ #include #include "lfrfid_worker_i.h" #include "tools/t5577.h" -#include #include #include #include "tools/varint_pair.h" @@ -81,17 +80,12 @@ static void lfrfid_worker_read_capture(bool level, uint32_t duration, void* cont furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, level); #endif - BaseType_t xHigherPriorityTaskWoken = pdFALSE; bool need_to_send = varint_pair_pack(ctx->pair, level, duration); if(need_to_send) { buffer_stream_send_from_isr( - ctx->stream, - varint_pair_get_data(ctx->pair), - varint_pair_get_size(ctx->pair), - &xHigherPriorityTaskWoken); + ctx->stream, varint_pair_get_data(ctx->pair), varint_pair_get_size(ctx->pair)); varint_pair_reset(ctx->pair); } - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } typedef enum { @@ -270,14 +264,14 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal( } if(furi_log_get_level() >= FuriLogLevelDebug) { - string_t string_info; - string_init(string_info); + FuriString* string_info; + string_info = furi_string_alloc(); for(uint8_t i = 0; i < protocol_data_size; i++) { if(i != 0) { - string_cat_printf(string_info, " "); + furi_string_cat_printf(string_info, " "); } - string_cat_printf(string_info, "%02X", protocol_data[i]); + furi_string_cat_printf(string_info, "%02X", protocol_data[i]); } FURI_LOG_D( @@ -285,8 +279,8 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal( "%s, %d, [%s]", protocol_dict_get_name(worker->protocols, protocol), last_read_count, - string_get_cstr(string_info)); - string_clear(string_info); + furi_string_get_cstr(string_info)); + furi_string_free(string_info); } protocol_dict_decoders_start(worker->protocols); @@ -407,14 +401,14 @@ typedef enum { } LFRFIDWorkerEmulateDMAEvent; static void lfrfid_worker_emulate_dma_isr(bool half, void* context) { - StreamBufferHandle_t stream = context; + FuriStreamBuffer* stream = context; uint32_t flag = half ? HalfTransfer : TransferComplete; - xStreamBufferSendFromISR(stream, &flag, sizeof(uint32_t), pdFALSE); + furi_stream_buffer_send(stream, &flag, sizeof(uint32_t), 0); } static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) { LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer)); - StreamBufferHandle_t stream = xStreamBufferCreate(sizeof(uint32_t), sizeof(uint32_t)); + FuriStreamBuffer* stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t)); LFRFIDProtocol protocol = worker->protocol; PulseGlue* pulse_glue = pulse_glue_alloc(); @@ -449,7 +443,7 @@ static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) { while(true) { uint32_t flag = 0; - size_t size = xStreamBufferReceive(stream, &flag, sizeof(uint32_t), 100); + size_t size = furi_stream_buffer_receive(stream, &flag, sizeof(uint32_t), 100); #ifdef LFRFID_WORKER_READ_DEBUG_GPIO furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, true); @@ -497,7 +491,7 @@ static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) { #endif free(buffer); - vStreamBufferDelete(stream); + furi_stream_buffer_free(stream); pulse_glue_free(pulse_glue); } diff --git a/lib/lfrfid/protocols/protocol_awid.c b/lib/lfrfid/protocols/protocol_awid.c index 7131d30d..38c7793b 100644 --- a/lib/lfrfid/protocols/protocol_awid.c +++ b/lib/lfrfid/protocols/protocol_awid.c @@ -81,7 +81,7 @@ static bool protocol_awid_can_be_decoded(uint8_t* data) { // Avoid detection for invalid formats uint8_t len = bit_lib_get_bits(data, 8, 8); - if(len != 26 && len != 50 && len != 37 && len != 34) break; + if(len != 26 && len != 50 && len != 37 && len != 34 && len != 36) break; result = true; } while(false); @@ -147,7 +147,7 @@ LevelDuration protocol_awid_encoder_yield(ProtocolAwid* protocol) { return level_duration_make(level, duration); }; -void protocol_awid_render_data(ProtocolAwid* protocol, string_t result) { +void protocol_awid_render_data(ProtocolAwid* protocol, FuriString* result) { // Index map // 0 10 20 30 40 50 60 // | | | | | | | @@ -164,7 +164,7 @@ void protocol_awid_render_data(ProtocolAwid* protocol, string_t result) { uint8_t* decoded_data = protocol->data; uint8_t format_length = decoded_data[0]; - string_cat_printf(result, "Format: %d\r\n", format_length); + furi_string_cat_printf(result, "Format: %d\r\n", format_length); if(format_length == 26) { uint8_t facility; bit_lib_copy_bits(&facility, 0, 8, decoded_data, 9); @@ -172,22 +172,22 @@ void protocol_awid_render_data(ProtocolAwid* protocol, string_t result) { uint16_t card_id; bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 17); bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 25); - string_cat_printf(result, "Facility: %d\r\n", facility); - string_cat_printf(result, "Card: %d", card_id); + furi_string_cat_printf(result, "Facility: %d\r\n", facility); + furi_string_cat_printf(result, "Card: %d", card_id); } else { // print 66 bits as hex - string_cat_printf(result, "Data: "); + furi_string_cat_printf(result, "Data: "); for(size_t i = 0; i < AWID_DECODED_DATA_SIZE; i++) { - string_cat_printf(result, "%02X", decoded_data[i]); + furi_string_cat_printf(result, "%02X", decoded_data[i]); } } }; -void protocol_awid_render_brief_data(ProtocolAwid* protocol, string_t result) { +void protocol_awid_render_brief_data(ProtocolAwid* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t format_length = decoded_data[0]; - string_cat_printf(result, "Format: %d\r\n", format_length); + furi_string_cat_printf(result, "Format: %d\r\n", format_length); if(format_length == 26) { uint8_t facility; bit_lib_copy_bits(&facility, 0, 8, decoded_data, 9); @@ -195,9 +195,9 @@ void protocol_awid_render_brief_data(ProtocolAwid* protocol, string_t result) { uint16_t card_id; bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 17); bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 25); - string_cat_printf(result, "ID: %03u,%05u", facility, card_id); + furi_string_cat_printf(result, "ID: %03u,%05u", facility, card_id); } else { - string_cat_printf(result, "Data: unknown"); + furi_string_cat_printf(result, "Data: unknown"); } }; @@ -205,8 +205,15 @@ bool protocol_awid_write_data(ProtocolAwid* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Fix incorrect length byte + if(protocol->data[0] != 26 && protocol->data[0] != 50 && protocol->data[0] != 37 && + protocol->data[0] != 34 && protocol->data[0] != 36 ) { + protocol->data[0] = 26; + } + // Correct protocol data by redecoding protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); + bit_lib_remove_bit_every_nth((uint8_t*)protocol->encoded_data, 8, 88, 4); protocol_awid_decode(protocol->encoded_data, protocol->data); protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); @@ -225,7 +232,7 @@ bool protocol_awid_write_data(ProtocolAwid* protocol, void* data) { const ProtocolBase protocol_awid = { .name = "AWID", - .manufacturer = "AWIG", + .manufacturer = "AWID", .data_size = AWID_DECODED_DATA_SIZE, .features = LFRFIDFeatureASK, .validate_count = 3, diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c index 6959f753..4b720dff 100644 --- a/lib/lfrfid/protocols/protocol_em4100.c +++ b/lib/lfrfid/protocols/protocol_em4100.c @@ -251,10 +251,10 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) { // Correct protocol data by redecoding protocol_em4100_encoder_start(protocol); em4100_decode( - (uint8_t*)&protocol->encoded_data, - sizeof(EM4100DecodedData), - protocol->data, - EM4100_DECODED_DATA_SIZE); + (uint8_t*)&protocol->encoded_data, + sizeof(EM4100DecodedData), + protocol->data, + EM4100_DECODED_DATA_SIZE); protocol_em4100_encoder_start(protocol); @@ -270,9 +270,10 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) { return result; }; -void protocol_em4100_render_data(ProtocolEM4100* protocol, string_t result) { +void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) { uint8_t* data = protocol->data; - string_printf(result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4]))); + furi_string_printf( + result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4]))); }; const ProtocolBase protocol_em4100 = { diff --git a/lib/lfrfid/protocols/protocol_fdx_a.c b/lib/lfrfid/protocols/protocol_fdx_a.c index 554b9071..87daa0eb 100644 --- a/lib/lfrfid/protocols/protocol_fdx_a.c +++ b/lib/lfrfid/protocols/protocol_fdx_a.c @@ -79,6 +79,14 @@ static bool protocol_fdx_a_decode(const uint8_t* from, uint8_t* to) { return true; } +static void protocol_fdx_a_fix_parity(ProtocolFDXA* protocol) { + for(size_t i = 0; i < FDXA_DECODED_DATA_SIZE; i++) { + if(bit_lib_test_parity_32(protocol->data[i], BitLibParityOdd)) { + protocol->data[i] ^= (1 << 7); + } + } +} + static bool protocol_fdx_a_can_be_decoded(const uint8_t* data) { // check preamble if(data[0] != FDXA_PREAMBLE_0 || data[1] != FDXA_PREAMBLE_1 || data[12] != FDXA_PREAMBLE_0 || @@ -179,6 +187,7 @@ bool protocol_fdx_a_write_data(ProtocolFDXA* protocol, void* data) { bool result = false; // Correct protocol data by redecoding + protocol_fdx_a_fix_parity(protocol); protocol_fdx_a_encoder_start(protocol); protocol_fdx_a_decode(protocol->encoded_data, protocol->data); @@ -196,7 +205,7 @@ bool protocol_fdx_a_write_data(ProtocolFDXA* protocol, void* data) { return result; }; -void protocol_fdx_a_render_data(ProtocolFDXA* protocol, string_t result) { +void protocol_fdx_a_render_data(ProtocolFDXA* protocol, FuriString* result) { uint8_t data[FDXA_DECODED_DATA_SIZE]; memcpy(data, protocol->data, FDXA_DECODED_DATA_SIZE); @@ -206,7 +215,7 @@ void protocol_fdx_a_render_data(ProtocolFDXA* protocol, string_t result) { data[i] &= 0x7F; } - string_printf( + furi_string_printf( result, "ID: %02X%02X%02X%02X%02X\r\n" "Parity: %s", diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index f42b4ed9..855356f2 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -273,7 +273,7 @@ static bool protocol_fdx_b_get_temp(const uint8_t* data, float* temp) { } } -void protocol_fdx_b_render_data(ProtocolFDXB* protocol, string_t result) { +void protocol_fdx_b_render_data(ProtocolFDXB* protocol, FuriString* result) { // 38 bits of national code uint64_t national_code = protocol_fdx_b_get_national_code(protocol->data); @@ -287,19 +287,19 @@ void protocol_fdx_b_render_data(ProtocolFDXB* protocol, string_t result) { uint8_t replacement_number = bit_lib_get_bits(protocol->data, 60, 3); bool animal_flag = bit_lib_get_bit(protocol->data, 63); - string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code); - string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No"); + furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code); + furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No"); float temperature; if(protocol_fdx_b_get_temp(protocol->data, &temperature)) { float temperature_c = (temperature - 32) / 1.8; - string_cat_printf( + furi_string_cat_printf( result, "T: %.2fF, %.2fC\r\n", (double)temperature, (double)temperature_c); } else { - string_cat_printf(result, "T: ---\r\n"); + furi_string_cat_printf(result, "T: ---\r\n"); } - string_cat_printf( + furi_string_cat_printf( result, "Bits: %X-%X-%X-%X-%X", block_status, @@ -309,7 +309,7 @@ void protocol_fdx_b_render_data(ProtocolFDXB* protocol, string_t result) { replacement_number); }; -void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, string_t result) { +void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, FuriString* result) { // 38 bits of national code uint64_t national_code = protocol_fdx_b_get_national_code(protocol->data); @@ -318,15 +318,15 @@ void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, string_t result) { bool animal_flag = bit_lib_get_bit(protocol->data, 63); - string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code); - string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No"); + furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code); + furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No"); float temperature; if(protocol_fdx_b_get_temp(protocol->data, &temperature)) { float temperature_c = (temperature - 32) / 1.8; - string_cat_printf(result, "T: %.2fC", (double)temperature_c); + furi_string_cat_printf(result, "T: %.2fC", (double)temperature_c); } else { - string_cat_printf(result, "T: ---"); + furi_string_cat_printf(result, "T: ---"); } }; diff --git a/lib/lfrfid/protocols/protocol_gallagher.c b/lib/lfrfid/protocols/protocol_gallagher.c index 5d824530..4720d3a4 100644 --- a/lib/lfrfid/protocols/protocol_gallagher.c +++ b/lib/lfrfid/protocols/protocol_gallagher.c @@ -268,15 +268,15 @@ bool protocol_gallagher_write_data(ProtocolGallagher* protocol, void* data) { return result; }; -void protocol_gallagher_render_data(ProtocolGallagher* protocol, string_t result) { +void protocol_gallagher_render_data(ProtocolGallagher* protocol, FuriString* result) { UNUSED(protocol); uint8_t rc = bit_lib_get_bits(protocol->data, 0, 4); uint8_t il = bit_lib_get_bits(protocol->data, 4, 4); uint32_t fc = bit_lib_get_bits_32(protocol->data, 8, 24); uint32_t card_id = bit_lib_get_bits_32(protocol->data, 32, 32); - string_cat_printf(result, "Region: %u, Issue Level: %u\r\n", rc, il); - string_cat_printf(result, "FC: %u, C: %lu\r\n", fc, card_id); + furi_string_cat_printf(result, "Region: %u, Issue Level: %u\r\n", rc, il); + furi_string_cat_printf(result, "FC: %lu, C: %lu\r\n", fc, card_id); }; const ProtocolBase protocol_gallagher = { diff --git a/lib/lfrfid/protocols/protocol_h10301.c b/lib/lfrfid/protocols/protocol_h10301.c index 6c50c667..2d7a3e66 100644 --- a/lib/lfrfid/protocols/protocol_h10301.c +++ b/lib/lfrfid/protocols/protocol_h10301.c @@ -340,7 +340,7 @@ bool protocol_h10301_write_data(ProtocolH10301* protocol, void* data) { // Correct protocol data by redecoding protocol_h10301_encoder_start(protocol); protocol_h10301_decode(protocol->encoded_data, protocol->data); - + protocol_h10301_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { @@ -355,9 +355,9 @@ bool protocol_h10301_write_data(ProtocolH10301* protocol, void* data) { return result; }; -void protocol_h10301_render_data(ProtocolH10301* protocol, string_t result) { +void protocol_h10301_render_data(ProtocolH10301* protocol, FuriString* result) { uint8_t* data = protocol->data; - string_printf( + furi_string_printf( result, "FC: %u\r\n" "Card: %u", diff --git a/lib/lfrfid/protocols/protocol_hid_ex_generic.c b/lib/lfrfid/protocols/protocol_hid_ex_generic.c index 17b75528..240128cb 100644 --- a/lib/lfrfid/protocols/protocol_hid_ex_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_ex_generic.c @@ -192,10 +192,10 @@ bool protocol_hid_ex_generic_write_data(ProtocolHIDEx* protocol, void* data) { return result; }; -void protocol_hid_ex_generic_render_data(ProtocolHIDEx* protocol, string_t result) { +void protocol_hid_ex_generic_render_data(ProtocolHIDEx* protocol, FuriString* result) { // TODO: parser and render functions UNUSED(protocol); - string_printf(result, "Generic HID Extended\r\nData: Unknown"); + furi_string_printf(result, "Generic HID Extended\r\nData: Unknown"); }; const ProtocolBase protocol_hid_ex_generic = { diff --git a/lib/lfrfid/protocols/protocol_hid_generic.c b/lib/lfrfid/protocols/protocol_hid_generic.c index da5f5b7c..e0702140 100644 --- a/lib/lfrfid/protocols/protocol_hid_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_generic.c @@ -221,25 +221,29 @@ bool protocol_hid_generic_write_data(ProtocolHID* protocol, void* data) { return result; }; -static void protocol_hid_generic_string_cat_protocol_bits(ProtocolHID* protocol, uint8_t protocol_size, string_t result) { +static void protocol_hid_generic_string_cat_protocol_bits( + ProtocolHID* protocol, + uint8_t protocol_size, + FuriString* result) { // round up to the nearest nibble const uint8_t hex_character_count = (protocol_size + 3) / 4; const uint8_t protocol_bit_index = HID_DECODED_BIT_SIZE - protocol_size; for(size_t i = 0; i < hex_character_count; i++) { - uint8_t nibble = - i == 0 ? bit_lib_get_bits( - protocol->data, protocol_bit_index, protocol_size % 4 == 0 ? 4 : protocol_size % 4) : - bit_lib_get_bits(protocol->data, protocol_bit_index + i * 4, 4); - string_cat_printf(result, "%X", nibble & 0xF); + uint8_t nibble = i == 0 ? bit_lib_get_bits( + protocol->data, + protocol_bit_index, + protocol_size % 4 == 0 ? 4 : protocol_size % 4) : + bit_lib_get_bits(protocol->data, protocol_bit_index + i * 4, 4); + furi_string_cat_printf(result, "%X", nibble & 0xF); } } -void protocol_hid_generic_render_data(ProtocolHID* protocol, string_t result) { +void protocol_hid_generic_render_data(ProtocolHID* protocol, FuriString* result) { const uint8_t protocol_size = protocol_hid_generic_decode_protocol_size(protocol); if(protocol_size == HID_PROTOCOL_SIZE_UNKNOWN) { - string_printf( + furi_string_printf( result, "Generic HID Proximity\r\n" "Data: %02X%02X%02X%02X%02X%X", @@ -250,7 +254,7 @@ void protocol_hid_generic_render_data(ProtocolHID* protocol, string_t result) { protocol->data[4], protocol->data[5] >> 4); } else { - string_printf( + furi_string_printf( result, "%hhu-bit HID Proximity\r\n" "Data: ", diff --git a/lib/lfrfid/protocols/protocol_indala26.c b/lib/lfrfid/protocols/protocol_indala26.c index 136ececf..cafc5848 100644 --- a/lib/lfrfid/protocols/protocol_indala26.c +++ b/lib/lfrfid/protocols/protocol_indala26.c @@ -236,7 +236,10 @@ static uint16_t get_cn(const uint8_t* data) { return cn; } -void protocol_indala26_render_data_internal(ProtocolIndala* protocol, string_t result, bool brief) { +void protocol_indala26_render_data_internal( + ProtocolIndala* protocol, + FuriString* result, + bool brief) { bool wiegand_correct = true; bool checksum_correct = true; @@ -284,7 +287,7 @@ void protocol_indala26_render_data_internal(ProtocolIndala* protocol, string_t r if(odd_parity_sum % 2 != odd_parity) wiegand_correct = false; if(brief) { - string_printf( + furi_string_printf( result, "FC: %u\r\nCard: %u, Parity:%s%s", fc, @@ -292,7 +295,7 @@ void protocol_indala26_render_data_internal(ProtocolIndala* protocol, string_t r (checksum_correct ? "+" : "-"), (wiegand_correct ? "+" : "-")); } else { - string_printf( + furi_string_printf( result, "FC: %u\r\n" "Card: %u\r\n" @@ -304,10 +307,10 @@ void protocol_indala26_render_data_internal(ProtocolIndala* protocol, string_t r (wiegand_correct ? "+" : "-")); } } -void protocol_indala26_render_data(ProtocolIndala* protocol, string_t result) { +void protocol_indala26_render_data(ProtocolIndala* protocol, FuriString* result) { protocol_indala26_render_data_internal(protocol, result, false); } -void protocol_indala26_render_brief_data(ProtocolIndala* protocol, string_t result) { +void protocol_indala26_render_brief_data(ProtocolIndala* protocol, FuriString* result) { protocol_indala26_render_data_internal(protocol, result, true); } diff --git a/lib/lfrfid/protocols/protocol_io_prox_xsf.c b/lib/lfrfid/protocols/protocol_io_prox_xsf.c index f53eac68..71314856 100644 --- a/lib/lfrfid/protocols/protocol_io_prox_xsf.c +++ b/lib/lfrfid/protocols/protocol_io_prox_xsf.c @@ -232,9 +232,9 @@ LevelDuration protocol_io_prox_xsf_encoder_yield(ProtocolIOProxXSF* protocol) { return level_duration_make(level, duration); }; -void protocol_io_prox_xsf_render_data(ProtocolIOProxXSF* protocol, string_t result) { +void protocol_io_prox_xsf_render_data(ProtocolIOProxXSF* protocol, FuriString* result) { uint8_t* data = protocol->data; - string_printf( + furi_string_printf( result, "FC: %u\r\n" "VС: %u\r\n" @@ -244,9 +244,9 @@ void protocol_io_prox_xsf_render_data(ProtocolIOProxXSF* protocol, string_t resu (uint16_t)((data[2] << 8) | (data[3]))); } -void protocol_io_prox_xsf_render_brief_data(ProtocolIOProxXSF* protocol, string_t result) { +void protocol_io_prox_xsf_render_brief_data(ProtocolIOProxXSF* protocol, FuriString* result) { uint8_t* data = protocol->data; - string_printf( + furi_string_printf( result, "FC: %u, VС: %u\r\n" "Card: %u", diff --git a/lib/lfrfid/protocols/protocol_jablotron.c b/lib/lfrfid/protocols/protocol_jablotron.c index 89a59a2d..d2c7ea79 100644 --- a/lib/lfrfid/protocols/protocol_jablotron.c +++ b/lib/lfrfid/protocols/protocol_jablotron.c @@ -160,9 +160,9 @@ LevelDuration protocol_jablotron_encoder_yield(ProtocolJablotron* protocol) { return level_duration_make(protocol->last_level, duration); }; -void protocol_jablotron_render_data(ProtocolJablotron* protocol, string_t result) { +void protocol_jablotron_render_data(ProtocolJablotron* protocol, FuriString* result) { uint64_t id = protocol_jablotron_card_id(protocol->data); - string_printf(result, "ID: %llX\r\n", id); + furi_string_printf(result, "ID: %llX\r\n", id); }; bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) { diff --git a/lib/lfrfid/protocols/protocol_keri.c b/lib/lfrfid/protocols/protocol_keri.c index 7e662554..f0a12863 100644 --- a/lib/lfrfid/protocols/protocol_keri.c +++ b/lib/lfrfid/protocols/protocol_keri.c @@ -170,6 +170,7 @@ bool protocol_keri_encoder_start(ProtocolKeri* protocol) { memset(protocol->encoded_data, 0, KERI_ENCODED_DATA_SIZE); *(uint32_t*)&protocol->encoded_data[0] = 0b00000000000000000000000011100000; bit_lib_copy_bits(protocol->encoded_data, 32, 32, protocol->data, 0); + bit_lib_set_bits(protocol->encoded_data, 32, 1, 1); protocol->encoder.last_bit = bit_lib_get_bit(protocol->encoded_data, KERI_ENCODED_BIT_SIZE - 1); @@ -211,19 +212,21 @@ LevelDuration protocol_keri_encoder_yield(ProtocolKeri* protocol) { return level_duration; }; -void protocol_keri_render_data(ProtocolKeri* protocol, string_t result) { +void protocol_keri_render_data(ProtocolKeri* protocol, FuriString* result) { uint32_t data = bit_lib_get_bits_32(protocol->data, 0, 32); uint32_t internal_id = data & 0x7FFFFFFF; uint32_t fc = 0; uint32_t cn = 0; protocol_keri_descramble(&fc, &cn, &data); - string_printf(result, "Internal ID: %u\r\nFC: %u, Card: %u\r\n", internal_id, fc, cn); + furi_string_printf(result, "Internal ID: %lu\r\nFC: %lu, Card: %lu\r\n", internal_id, fc, cn); } bool protocol_keri_write_data(ProtocolKeri* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Start bit should be always set + protocol->data[0] |= (1 << 7); protocol_keri_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_pac_stanley.c b/lib/lfrfid/protocols/protocol_pac_stanley.c index b5e1ebdd..59aaf1e6 100644 --- a/lib/lfrfid/protocols/protocol_pac_stanley.c +++ b/lib/lfrfid/protocols/protocol_pac_stanley.c @@ -57,31 +57,31 @@ static void protocol_pac_stanley_decode(ProtocolPACStanley* protocol) { } static bool protocol_pac_stanley_can_be_decoded(ProtocolPACStanley* protocol) { - // Check preamble - if(bit_lib_get_bits(protocol->encoded_data, 0, 8) != 0b11111111) return false; - if(bit_lib_get_bit(protocol->encoded_data, 8) != 0) return false; - if(bit_lib_get_bit(protocol->encoded_data, 9) != 0) return false; - if(bit_lib_get_bit(protocol->encoded_data, 10) != 1) return false; - if(bit_lib_get_bits(protocol->encoded_data, 11, 8) != 0b00000010) return false; + // Check preamble + if(bit_lib_get_bits(protocol->encoded_data, 0, 8) != 0b11111111) return false; + if(bit_lib_get_bit(protocol->encoded_data, 8) != 0) return false; + if(bit_lib_get_bit(protocol->encoded_data, 9) != 0) return false; + if(bit_lib_get_bit(protocol->encoded_data, 10) != 1) return false; + if(bit_lib_get_bits(protocol->encoded_data, 11, 8) != 0b00000010) return false; - // Check next preamble - if(bit_lib_get_bits(protocol->encoded_data, 128, 8) != 0b11111111) return false; + // Check next preamble + if(bit_lib_get_bits(protocol->encoded_data, 128, 8) != 0b11111111) return false; - // Checksum - uint8_t checksum = 0; - uint8_t stripped_byte; - for(size_t idx = 0; idx < 9; idx++) { - uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits( - protocol->encoded_data, - PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx), - 8)); - stripped_byte = byte & 0x7F; // discard the parity bit - if(bit_lib_test_parity_32(stripped_byte, BitLibParityOdd) != (byte & 0x80) >> 7) { - return false; - } - if(idx < 8) checksum ^= stripped_byte; + // Checksum + uint8_t checksum = 0; + uint8_t stripped_byte; + for(size_t idx = 0; idx < 9; idx++) { + uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits( + protocol->encoded_data, + PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx), + 8)); + stripped_byte = byte & 0x7F; // discard the parity bit + if(bit_lib_test_parity_32(stripped_byte, BitLibParityOdd) != (byte & 0x80) >> 7) { + return false; } - if(stripped_byte != checksum) return false; + if(idx < 8) checksum ^= stripped_byte; + } + if(stripped_byte != checksum) return false; return true; } @@ -201,9 +201,9 @@ bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) { return result; } -void protocol_pac_stanley_render_data(ProtocolPACStanley* protocol, string_t result) { +void protocol_pac_stanley_render_data(ProtocolPACStanley* protocol, FuriString* result) { uint8_t* data = protocol->data; - string_printf(result, "CIN: %02X%02X%02X%02X", data[0], data[1], data[2], data[3]); + furi_string_printf(result, "CIN: %02X%02X%02X%02X", data[0], data[1], data[2], data[3]); } const ProtocolBase protocol_pac_stanley = { diff --git a/lib/lfrfid/protocols/protocol_paradox.c b/lib/lfrfid/protocols/protocol_paradox.c index b0b3e71d..7e029f1d 100644 --- a/lib/lfrfid/protocols/protocol_paradox.c +++ b/lib/lfrfid/protocols/protocol_paradox.c @@ -136,26 +136,26 @@ LevelDuration protocol_paradox_encoder_yield(ProtocolParadox* protocol) { return level_duration_make(level, duration); }; -void protocol_paradox_render_data(ProtocolParadox* protocol, string_t result) { +void protocol_paradox_render_data(ProtocolParadox* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); - string_cat_printf(result, "Facility: %u\r\n", fc); - string_cat_printf(result, "Card: %lu\r\n", card_id); - string_cat_printf(result, "Data: "); + furi_string_cat_printf(result, "Facility: %u\r\n", fc); + furi_string_cat_printf(result, "Card: %u\r\n", card_id); + furi_string_cat_printf(result, "Data: "); for(size_t i = 0; i < PARADOX_DECODED_DATA_SIZE; i++) { - string_cat_printf(result, "%02X", decoded_data[i]); + furi_string_cat_printf(result, "%02X", decoded_data[i]); } }; -void protocol_paradox_render_brief_data(ProtocolParadox* protocol, string_t result) { +void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); - string_cat_printf(result, "FC: %03u, Card: %05u", fc, card_id); + furi_string_cat_printf(result, "FC: %03u, Card: %05u", fc, card_id); }; bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) { diff --git a/lib/lfrfid/protocols/protocol_pyramid.c b/lib/lfrfid/protocols/protocol_pyramid.c index 1bba9871..974bb6da 100644 --- a/lib/lfrfid/protocols/protocol_pyramid.c +++ b/lib/lfrfid/protocols/protocol_pyramid.c @@ -221,6 +221,7 @@ bool protocol_pyramid_write_data(ProtocolPyramid* protocol, void* data) { // Correct protocol data by redecoding protocol_pyramid_encode(protocol); + bit_lib_remove_bit_every_nth(protocol->encoded_data, 8, 15 * 8, 8); protocol_pyramid_decode(protocol); protocol_pyramid_encoder_start(protocol); @@ -238,11 +239,11 @@ bool protocol_pyramid_write_data(ProtocolPyramid* protocol, void* data) { return result; }; -void protocol_pyramid_render_data(ProtocolPyramid* protocol, string_t result) { +void protocol_pyramid_render_data(ProtocolPyramid* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t format_length = decoded_data[0]; - string_cat_printf(result, "Format: 26\r\n", format_length); + furi_string_cat_printf(result, "Format: %d\r\n", format_length); if(format_length == 26) { uint8_t facility; bit_lib_copy_bits(&facility, 0, 8, decoded_data, 8); @@ -250,9 +251,9 @@ void protocol_pyramid_render_data(ProtocolPyramid* protocol, string_t result) { uint16_t card_id; bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 16); bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 24); - string_cat_printf(result, "FC: %03u, Card: %05u", facility, card_id); + furi_string_cat_printf(result, "FC: %03u, Card: %05u", facility, card_id); } else { - string_cat_printf(result, "Data: unknown"); + furi_string_cat_printf(result, "Data: unknown"); } }; diff --git a/lib/lfrfid/protocols/protocol_viking.c b/lib/lfrfid/protocols/protocol_viking.c index f252cc2c..8083f6d9 100644 --- a/lib/lfrfid/protocols/protocol_viking.c +++ b/lib/lfrfid/protocols/protocol_viking.c @@ -175,9 +175,9 @@ bool protocol_viking_write_data(ProtocolViking* protocol, void* data) { return result; }; -void protocol_viking_render_data(ProtocolViking* protocol, string_t result) { +void protocol_viking_render_data(ProtocolViking* protocol, FuriString* result) { uint32_t id = bit_lib_get_bits_32(protocol->data, 0, 32); - string_printf(result, "ID: %08lX\r\n", id); + furi_string_printf(result, "ID: %08lX\r\n", id); }; const ProtocolBase protocol_viking = { diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 5bb67145..a842ed92 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -66,19 +66,28 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { } // Read total amount of keys - string_t next_line; - string_init(next_line); + FuriString* next_line; + next_line = furi_string_alloc(); while(true) { - if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(!stream_read_line(dict->stream, next_line)) { + FURI_LOG_T(TAG, "No keys left in dict"); + break; + } + furi_string_trim(next_line); + FURI_LOG_T( + TAG, + "Read line: %s, len: %d", + furi_string_get_cstr(next_line), + furi_string_size(next_line)); + if(furi_string_get_char(next_line, 0) == '#') continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN - 1) continue; dict->total_keys++; } - string_clear(next_line); + furi_string_free(next_line); stream_rewind(dict->stream); dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %d keys", dict->total_keys); + FURI_LOG_I(TAG, "Loaded dictionary with %ld keys", dict->total_keys); } while(false); if(!dict_loaded) { @@ -99,20 +108,20 @@ void mf_classic_dict_free(MfClassicDict* dict) { free(dict); } -static void mf_classic_dict_int_to_str(uint8_t* key_int, string_t key_str) { - string_reset(key_str); +static void mf_classic_dict_int_to_str(uint8_t* key_int, FuriString* key_str) { + furi_string_reset(key_str); for(size_t i = 0; i < 6; i++) { - string_cat_printf(key_str, "%02X", key_int[i]); + furi_string_cat_printf(key_str, "%02X", key_int[i]); } } -static void mf_classic_dict_str_to_int(string_t key_str, uint64_t* key_int) { +static void mf_classic_dict_str_to_int(FuriString* key_str, uint64_t* key_int) { uint8_t key_byte_tmp; *key_int = 0ULL; for(uint8_t i = 0; i < 12; i += 2) { args_char_to_hex( - string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp); + furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp); *key_int |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2); } } @@ -130,17 +139,17 @@ bool mf_classic_dict_rewind(MfClassicDict* dict) { return stream_rewind(dict->stream); } -bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key) { +bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key) { furi_assert(dict); furi_assert(dict->stream); bool key_read = false; - string_reset(key); + furi_string_reset(key); while(!key_read) { if(!stream_read_line(dict->stream, key)) break; - if(string_get_char(key, 0) == '#') continue; - if(string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue; - string_left(key, 12); + if(furi_string_get_char(key, 0) == '#') continue; + if(furi_string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue; + furi_string_left(key, 12); key_read = true; } @@ -151,53 +160,53 @@ bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) { furi_assert(dict); furi_assert(dict->stream); - string_t temp_key; - string_init(temp_key); + FuriString* temp_key; + temp_key = furi_string_alloc(); bool key_read = mf_classic_dict_get_next_key_str(dict, temp_key); if(key_read) { mf_classic_dict_str_to_int(temp_key, key); } - string_clear(temp_key); + furi_string_free(temp_key); return key_read; } -bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key) { +bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key) { furi_assert(dict); furi_assert(dict->stream); - string_t next_line; - string_init(next_line); + FuriString* next_line; + next_line = furi_string_alloc(); bool key_found = false; stream_rewind(dict->stream); while(!key_found) { if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - string_left(next_line, 12); - if(!string_equal_p(key, next_line)) continue; + if(furi_string_get_char(next_line, 0) == '#') continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + furi_string_left(next_line, 12); + if(!furi_string_equal(key, next_line)) continue; key_found = true; } - string_clear(next_line); + furi_string_free(next_line); return key_found; } bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) { - string_t temp_key; + FuriString* temp_key; - string_init(temp_key); + temp_key = furi_string_alloc(); mf_classic_dict_int_to_str(key, temp_key); bool key_found = mf_classic_dict_is_key_present_str(dict, temp_key); - string_clear(temp_key); + furi_string_free(temp_key); return key_found; } -bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key) { +bool mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key) { furi_assert(dict); furi_assert(dict->stream); - string_cat_printf(key, "\n"); + furi_string_cat_printf(key, "\n"); bool key_added = false; do { @@ -207,7 +216,7 @@ bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key) { key_added = true; } while(false); - string_left(key, 12); + furi_string_left(key, 12); return key_added; } @@ -215,35 +224,35 @@ bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) { furi_assert(dict); furi_assert(dict->stream); - string_t temp_key; - string_init(temp_key); + FuriString* temp_key; + temp_key = furi_string_alloc(); mf_classic_dict_int_to_str(key, temp_key); bool key_added = mf_classic_dict_add_key_str(dict, temp_key); - string_clear(temp_key); + furi_string_free(temp_key); return key_added; } -bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target) { +bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, FuriString* key, uint32_t target) { furi_assert(dict); furi_assert(dict->stream); - string_t next_line; + FuriString* next_line; uint32_t index = 0; - string_init(next_line); - string_reset(key); + next_line = furi_string_alloc(); + furi_string_reset(key); bool key_found = false; while(!key_found) { if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(furi_string_get_char(next_line, 0) == '#') continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; if(index++ != target) continue; - string_set_n(key, next_line, 0, 12); + furi_string_set_n(key, next_line, 0, 12); key_found = true; } - string_clear(next_line); + furi_string_free(next_line); return key_found; } @@ -251,37 +260,37 @@ bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32 furi_assert(dict); furi_assert(dict->stream); - string_t temp_key; - string_init(temp_key); + FuriString* temp_key; + temp_key = furi_string_alloc(); bool key_found = mf_classic_dict_get_key_at_index_str(dict, temp_key, target); if(key_found) { mf_classic_dict_str_to_int(temp_key, key); } - string_clear(temp_key); + furi_string_free(temp_key); return key_found; } -bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target) { +bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32_t* target) { furi_assert(dict); furi_assert(dict->stream); - string_t next_line; - string_init(next_line); + FuriString* next_line; + next_line = furi_string_alloc(); bool key_found = false; uint32_t index = 0; stream_rewind(dict->stream); while(!key_found) { if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - string_left(next_line, 12); - if(!string_equal_p(key, next_line)) continue; + if(furi_string_get_char(next_line, 0) == '#') continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + furi_string_left(next_line, 12); + if(!furi_string_equal(key, next_line)) continue; key_found = true; *target = index; } - string_clear(next_line); + furi_string_free(next_line); return key_found; } @@ -289,12 +298,12 @@ bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* tar furi_assert(dict); furi_assert(dict->stream); - string_t temp_key; - string_init(temp_key); + FuriString* temp_key; + temp_key = furi_string_alloc(); mf_classic_dict_int_to_str(key, temp_key); bool key_found = mf_classic_dict_find_index_str(dict, temp_key, target); - string_clear(temp_key); + furi_string_free(temp_key); return key_found; } @@ -302,15 +311,15 @@ bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) { furi_assert(dict); furi_assert(dict->stream); - string_t next_line; - string_init(next_line); + FuriString* next_line; + next_line = furi_string_alloc(); uint32_t index = 0; bool key_removed = false; while(!key_removed) { if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(furi_string_get_char(next_line, 0) == '#') continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; if(index++ != target) continue; stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent); if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break; @@ -318,6 +327,6 @@ bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) { key_removed = true; } - string_clear(next_line); + furi_string_free(next_line); return key_removed; } diff --git a/lib/nfc/helpers/mf_classic_dict.h b/lib/nfc/helpers/mf_classic_dict.h index 9241a37b..5b0ee312 100644 --- a/lib/nfc/helpers/mf_classic_dict.h +++ b/lib/nfc/helpers/mf_classic_dict.h @@ -48,11 +48,11 @@ bool mf_classic_dict_rewind(MfClassicDict* dict); bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key); -bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key); +bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key); bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key); -bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key); +bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key); /** Get key at target offset as uint64_t * @@ -72,7 +72,7 @@ bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32 * * @return true on success */ -bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target); +bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, FuriString* key, uint32_t target); bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key); @@ -83,11 +83,11 @@ bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key); * * @return true on success */ -bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key); +bool mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key); bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target); -bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target); +bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32_t* target); /** Delete key at target offset * diff --git a/lib/nfc/helpers/mfkey32.c b/lib/nfc/helpers/mfkey32.c index 64b06e25..47e7e9f6 100644 --- a/lib/nfc/helpers/mfkey32.c +++ b/lib/nfc/helpers/mfkey32.c @@ -91,10 +91,8 @@ void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, } static bool mfkey32_write_params(Mfkey32* instance, Mfkey32Params* params) { - string_t str; - string_init_printf( - str, - "Sector %d key %c cuid %08x nt0 %08x nr0 %08x ar0 %08x nt1 %08x nr1 %08x ar1 %08x\n", + FuriString* str = furi_string_alloc_printf( + "Sec %d key %c cuid %08lx nt0 %08lx nr0 %08lx ar0 %08lx nt1 %08lx nr1 %08lx ar1 %08lx\n", params->sector, params->key == MfClassicKeyA ? 'A' : 'B', params->cuid, @@ -105,7 +103,7 @@ static bool mfkey32_write_params(Mfkey32* instance, Mfkey32Params* params) { params->nr1, params->ar1); bool write_success = stream_write_string(instance->file_stream, str); - string_clear(str); + furi_string_free(str); return write_success; } @@ -199,14 +197,14 @@ void mfkey32_process_data( } } -uint16_t mfkey32_get_auth_sectors(string_t data_str) { +uint16_t mfkey32_get_auth_sectors(FuriString* data_str) { furi_assert(data_str); uint16_t nonces_num = 0; Storage* storage = furi_record_open(RECORD_STORAGE); Stream* file_stream = buffered_file_stream_alloc(storage); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { if(!buffered_file_stream_open( @@ -214,17 +212,17 @@ uint16_t mfkey32_get_auth_sectors(string_t data_str) { break; while(true) { if(!stream_read_line(file_stream, temp_str)) break; - size_t uid_pos = string_search_str(temp_str, "cuid"); - string_left(temp_str, uid_pos); - string_push_back(temp_str, '\n'); - string_cat(data_str, temp_str); + size_t uid_pos = furi_string_search(temp_str, "cuid"); + furi_string_left(temp_str, uid_pos); + furi_string_push_back(temp_str, '\n'); + furi_string_cat(data_str, temp_str); nonces_num++; } } while(false); buffered_file_stream_close(file_stream); stream_free(file_stream); - string_clear(temp_str); + furi_string_free(temp_str); return nonces_num; } diff --git a/lib/nfc/helpers/mfkey32.h b/lib/nfc/helpers/mfkey32.h index c4f13cc2..e1f472e5 100644 --- a/lib/nfc/helpers/mfkey32.h +++ b/lib/nfc/helpers/mfkey32.h @@ -1,7 +1,6 @@ #pragma once #include -#include typedef struct Mfkey32 Mfkey32; @@ -24,4 +23,4 @@ void mfkey32_process_data( void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context); -uint16_t mfkey32_get_auth_sectors(string_t string); +uint16_t mfkey32_get_auth_sectors(FuriString* string); diff --git a/lib/nfc/helpers/nfc_debug_log.c b/lib/nfc/helpers/nfc_debug_log.c index 1cbc5224..0bfbc2c6 100644 --- a/lib/nfc/helpers/nfc_debug_log.c +++ b/lib/nfc/helpers/nfc_debug_log.c @@ -1,6 +1,5 @@ #include "nfc_debug_log.h" -#include #include #include @@ -10,7 +9,7 @@ struct NfcDebugLog { Stream* file_stream; - string_t data_str; + FuriString* data_str; }; NfcDebugLog* nfc_debug_log_alloc() { @@ -30,7 +29,7 @@ NfcDebugLog* nfc_debug_log_alloc() { free(instance); instance = NULL; } else { - string_init(instance->data_str); + instance->data_str = furi_string_alloc(); } furi_record_close(RECORD_STORAGE); @@ -44,7 +43,7 @@ void nfc_debug_log_free(NfcDebugLog* instance) { buffered_file_stream_close(instance->file_stream); stream_free(instance->file_stream); - string_clear(instance->data_str); + furi_string_free(instance->data_str); free(instance); } @@ -61,12 +60,12 @@ void nfc_debug_log_process_data( furi_assert(data); UNUSED(crc_dropped); - string_printf(instance->data_str, "%lu %c:", furi_get_tick(), reader_to_tag ? 'R' : 'T'); + furi_string_printf(instance->data_str, "%lu %c:", furi_get_tick(), reader_to_tag ? 'R' : 'T'); uint16_t data_len = len; for(size_t i = 0; i < data_len; i++) { - string_cat_printf(instance->data_str, " %02x", data[i]); + furi_string_cat_printf(instance->data_str, " %02x", data[i]); } - string_push_back(instance->data_str, '\n'); + furi_string_push_back(instance->data_str, '\n'); stream_write_string(instance->file_stream, instance->data_str); } diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c index 680b8cef..0ba657a2 100644 --- a/lib/nfc/helpers/reader_analyzer.c +++ b/lib/nfc/helpers/reader_analyzer.c @@ -1,5 +1,4 @@ #include "reader_analyzer.h" -#include #include #include #include @@ -26,7 +25,7 @@ struct ReaderAnalyzer { FuriHalNfcDevData nfc_data; bool alive; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; FuriThread* thread; ReaderAnalyzerParseDataCallback callback; @@ -86,8 +85,8 @@ int32_t reader_analyzer_thread(void* context) { ReaderAnalyzer* reader_analyzer = context; uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {}; - while(reader_analyzer->alive || !xStreamBufferIsEmpty(reader_analyzer->stream)) { - size_t ret = xStreamBufferReceive( + while(reader_analyzer->alive || !furi_stream_buffer_is_empty(reader_analyzer->stream)) { + size_t ret = furi_stream_buffer_receive( reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50); if(ret) { reader_analyzer_parse(reader_analyzer, buffer, ret); @@ -103,7 +102,7 @@ ReaderAnalyzer* reader_analyzer_alloc() { instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic]; instance->alive = false; instance->stream = - xStreamBufferCreate(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader)); + furi_stream_buffer_alloc(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader)); instance->thread = furi_thread_alloc(); furi_thread_set_name(instance->thread, "ReaderAnalyzerWorker"); @@ -129,7 +128,7 @@ static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) { void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) { furi_assert(instance); - xStreamBufferReset(instance->stream); + furi_stream_buffer_reset(instance->stream); if(mode & ReaderAnalyzerModeDebugLog) { instance->debug_log = nfc_debug_log_alloc(); } @@ -171,7 +170,7 @@ void reader_analyzer_free(ReaderAnalyzer* instance) { reader_analyzer_stop(instance); furi_thread_free(instance->thread); - vStreamBufferDelete(instance->stream); + furi_stream_buffer_free(instance->stream); free(instance); } @@ -215,12 +214,12 @@ static void reader_analyzer_write( ReaderAnalyzerHeader header = { .reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len}; size_t data_sent = 0; - data_sent = xStreamBufferSend( + data_sent = furi_stream_buffer_send( instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever); if(data_sent != sizeof(ReaderAnalyzerHeader)) { FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader)); } - data_sent = xStreamBufferSend(instance->stream, data, len, FuriWaitForever); + data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever); if(data_sent != len) { FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len); } diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index dd78e2da..06d57a0c 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1,6 +1,5 @@ #include "nfc_device.h" #include "assets_icons.h" -#include "m-string.h" #include "nfc_types.h" #include @@ -25,8 +24,8 @@ NfcDevice* nfc_device_alloc() { NfcDevice* nfc_dev = malloc(sizeof(NfcDevice)); nfc_dev->storage = furi_record_open(RECORD_STORAGE); nfc_dev->dialogs = furi_record_open(RECORD_DIALOGS); - string_init(nfc_dev->load_path); - string_init(nfc_dev->dev_data.parsed_data); + nfc_dev->load_path = furi_string_alloc(); + nfc_dev->dev_data.parsed_data = furi_string_alloc(); return nfc_dev; } @@ -35,53 +34,53 @@ void nfc_device_free(NfcDevice* nfc_dev) { nfc_device_clear(nfc_dev); furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_DIALOGS); - string_clear(nfc_dev->load_path); - string_clear(nfc_dev->dev_data.parsed_data); + furi_string_free(nfc_dev->load_path); + furi_string_free(nfc_dev->dev_data.parsed_data); free(nfc_dev); } -static void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) { +static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_string) { if(dev->format == NfcDeviceSaveFormatUid) { - string_set_str(format_string, "UID"); + furi_string_set(format_string, "UID"); } else if(dev->format == NfcDeviceSaveFormatBankCard) { - string_set_str(format_string, "Bank card"); + furi_string_set(format_string, "Bank card"); } else if(dev->format == NfcDeviceSaveFormatMifareUl) { - string_set_str(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true)); + furi_string_set(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true)); } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { - string_set_str(format_string, "Mifare Classic"); + furi_string_set(format_string, "Mifare Classic"); } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { - string_set_str(format_string, "Mifare DESFire"); + furi_string_set(format_string, "Mifare DESFire"); } else { - string_set_str(format_string, "Unknown"); + furi_string_set(format_string, "Unknown"); } } -static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { - if(string_start_with_str_p(format_string, "UID")) { +static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_string) { + if(furi_string_start_with_str(format_string, "UID")) { dev->format = NfcDeviceSaveFormatUid; dev->dev_data.protocol = NfcDeviceProtocolUnknown; return true; } - if(string_start_with_str_p(format_string, "Bank card")) { + if(furi_string_start_with_str(format_string, "Bank card")) { dev->format = NfcDeviceSaveFormatBankCard; dev->dev_data.protocol = NfcDeviceProtocolEMV; return true; } // Check Mifare Ultralight types for(MfUltralightType type = MfUltralightTypeUnknown; type < MfUltralightTypeNum; type++) { - if(string_equal_str_p(format_string, nfc_mf_ul_type(type, true))) { + if(furi_string_equal(format_string, nfc_mf_ul_type(type, true))) { dev->format = NfcDeviceSaveFormatMifareUl; dev->dev_data.protocol = NfcDeviceProtocolMifareUl; dev->dev_data.mf_ul_data.type = type; return true; } } - if(string_start_with_str_p(format_string, "Mifare Classic")) { + if(furi_string_start_with_str(format_string, "Mifare Classic")) { dev->format = NfcDeviceSaveFormatMifareClassic; dev->dev_data.protocol = NfcDeviceProtocolMifareClassic; return true; } - if(string_start_with_str_p(format_string, "Mifare DESFire")) { + if(furi_string_start_with_str(format_string, "Mifare DESFire")) { dev->format = NfcDeviceSaveFormatMifareDesfire; dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; return true; @@ -92,8 +91,8 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_strin static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; MfUltralightData* data = &dev->dev_data.mf_ul_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); // Save Mifare Ultralight specific data do { @@ -109,14 +108,15 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) // Write conters and tearing flags data bool counters_saved = true; for(uint8_t i = 0; i < 3; i++) { - string_printf(temp_str, "Counter %d", i); + furi_string_printf(temp_str, "Counter %d", i); if(!flipper_format_write_uint32( - file, string_get_cstr(temp_str), &data->counter[i], 1)) { + file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { counters_saved = false; break; } - string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { + furi_string_printf(temp_str, "Tearing %d", i); + if(!flipper_format_write_hex( + file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { counters_saved = false; break; } @@ -129,8 +129,8 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) if(!flipper_format_write_uint32(file, "Pages read", &pages_read, 1)) break; bool pages_saved = true; for(uint16_t i = 0; i < data->data_size; i += 4) { - string_printf(temp_str, "Page %d", i / 4); - if(!flipper_format_write_hex(file, string_get_cstr(temp_str), &data->data[i], 4)) { + furi_string_printf(temp_str, "Page %d", i / 4); + if(!flipper_format_write_hex(file, furi_string_get_cstr(temp_str), &data->data[i], 4)) { pages_saved = false; break; } @@ -145,15 +145,15 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) saved = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return saved; } bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { bool parsed = false; MfUltralightData* data = &dev->dev_data.mf_ul_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t data_format_version = 0; do { @@ -172,13 +172,15 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { // Read counters and tearing flags bool counters_parsed = true; for(uint8_t i = 0; i < 3; i++) { - string_printf(temp_str, "Counter %d", i); - if(!flipper_format_read_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) { + furi_string_printf(temp_str, "Counter %d", i); + if(!flipper_format_read_uint32( + file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { counters_parsed = false; break; } - string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_read_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { + furi_string_printf(temp_str, "Tearing %d", i); + if(!flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { counters_parsed = false; break; } @@ -198,8 +200,9 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { if(data->data_size > MF_UL_MAX_DUMP_SIZE || data->data_read > MF_UL_MAX_DUMP_SIZE) break; bool pages_parsed = true; for(uint16_t i = 0; i < pages_total; i++) { - string_printf(temp_str, "Page %d", i); - if(!flipper_format_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) { + furi_string_printf(temp_str, "Page %d", i); + if(!flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), &data->data[i * 4], 4)) { pages_parsed = false; break; } @@ -214,7 +217,7 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { parsed = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return parsed; } @@ -223,38 +226,40 @@ static bool nfc_device_save_mifare_df_key_settings( MifareDesfireKeySettings* ks, const char* prefix) { bool saved = false; - string_t key; - string_init(key); + FuriString* key; + key = furi_string_alloc(); do { - string_printf(key, "%s Change Key ID", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break; - string_printf(key, "%s Config Changeable", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->config_changeable, 1)) + furi_string_printf(key, "%s Change Key ID", prefix); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &ks->change_key_id, 1)) break; - string_printf(key, "%s Free Create Delete", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_create_delete, 1)) + furi_string_printf(key, "%s Config Changeable", prefix); + if(!flipper_format_write_bool(file, furi_string_get_cstr(key), &ks->config_changeable, 1)) break; - string_printf(key, "%s Free Directory List", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_directory_list, 1)) + furi_string_printf(key, "%s Free Create Delete", prefix); + if(!flipper_format_write_bool(file, furi_string_get_cstr(key), &ks->free_create_delete, 1)) break; - string_printf(key, "%s Key Changeable", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1)) + furi_string_printf(key, "%s Free Directory List", prefix); + if(!flipper_format_write_bool(file, furi_string_get_cstr(key), &ks->free_directory_list, 1)) + break; + furi_string_printf(key, "%s Key Changeable", prefix); + if(!flipper_format_write_bool( + file, furi_string_get_cstr(key), &ks->master_key_changeable, 1)) break; if(ks->flags) { - string_printf(key, "%s Flags", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->flags, 1)) break; + furi_string_printf(key, "%s Flags", prefix); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &ks->flags, 1)) break; } - string_printf(key, "%s Max Keys", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break; + furi_string_printf(key, "%s Max Keys", prefix); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &ks->max_keys, 1)) break; for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) { - string_printf(key, "%s Key %d Version", prefix, kv->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &kv->version, 1)) break; + furi_string_printf(key, "%s Key %d Version", prefix, kv->id); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &kv->version, 1)) break; } saved = true; } while(false); - string_clear(key); + furi_string_free(key); return saved; } @@ -263,36 +268,38 @@ bool nfc_device_load_mifare_df_key_settings( MifareDesfireKeySettings* ks, const char* prefix) { bool parsed = false; - string_t key; - string_init(key); + FuriString* key; + key = furi_string_alloc(); do { - string_printf(key, "%s Change Key ID", prefix); - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break; - string_printf(key, "%s Config Changeable", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->config_changeable, 1)) break; - string_printf(key, "%s Free Create Delete", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_create_delete, 1)) + furi_string_printf(key, "%s Change Key ID", prefix); + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), &ks->change_key_id, 1)) break; + furi_string_printf(key, "%s Config Changeable", prefix); + if(!flipper_format_read_bool(file, furi_string_get_cstr(key), &ks->config_changeable, 1)) break; - string_printf(key, "%s Free Directory List", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_directory_list, 1)) + furi_string_printf(key, "%s Free Create Delete", prefix); + if(!flipper_format_read_bool(file, furi_string_get_cstr(key), &ks->free_create_delete, 1)) break; - string_printf(key, "%s Key Changeable", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1)) + furi_string_printf(key, "%s Free Directory List", prefix); + if(!flipper_format_read_bool(file, furi_string_get_cstr(key), &ks->free_directory_list, 1)) break; - string_printf(key, "%s Flags", prefix); - if(flipper_format_key_exist(file, string_get_cstr(key))) { - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->flags, 1)) break; + furi_string_printf(key, "%s Key Changeable", prefix); + if(!flipper_format_read_bool( + file, furi_string_get_cstr(key), &ks->master_key_changeable, 1)) + break; + furi_string_printf(key, "%s Flags", prefix); + if(flipper_format_key_exist(file, furi_string_get_cstr(key))) { + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), &ks->flags, 1)) break; } - string_printf(key, "%s Max Keys", prefix); - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break; + furi_string_printf(key, "%s Max Keys", prefix); + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), &ks->max_keys, 1)) break; ks->flags |= ks->max_keys >> 4; ks->max_keys &= 0xF; MifareDesfireKeyVersion** kv_head = &ks->key_version_head; for(int key_id = 0; key_id < ks->max_keys; key_id++) { - string_printf(key, "%s Key %d Version", prefix, key_id); + furi_string_printf(key, "%s Key %d Version", prefix, key_id); uint8_t version; - if(flipper_format_read_hex(file, string_get_cstr(key), &version, 1)) { + if(flipper_format_read_hex(file, furi_string_get_cstr(key), &version, 1)) { MifareDesfireKeyVersion* kv = malloc(sizeof(MifareDesfireKeyVersion)); memset(kv, 0, sizeof(MifareDesfireKeyVersion)); kv->id = key_id; @@ -304,21 +311,22 @@ bool nfc_device_load_mifare_df_key_settings( parsed = true; } while(false); - string_clear(key); + furi_string_free(key); return parsed; } static bool nfc_device_save_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) { bool saved = false; - string_t prefix, key; - string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - string_init(key); + FuriString *prefix, *key; + prefix = + furi_string_alloc_printf("Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); + key = furi_string_alloc(); uint8_t* tmp = NULL; do { if(app->key_settings) { if(!nfc_device_save_mifare_df_key_settings( - file, app->key_settings, string_get_cstr(prefix))) + file, app->key_settings, furi_string_get_cstr(prefix))) break; } if(!app->file_head) break; @@ -331,68 +339,75 @@ static bool nfc_device_save_mifare_df_app(FlipperFormat* file, MifareDesfireAppl for(MifareDesfireFile* f = app->file_head; f; f = f->next) { tmp[i++] = f->id; } - string_printf(key, "%s File IDs", string_get_cstr(prefix)); - if(!flipper_format_write_hex(file, string_get_cstr(key), tmp, n_files)) break; + furi_string_printf(key, "%s File IDs", furi_string_get_cstr(prefix)); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), tmp, n_files)) break; bool saved_files = true; for(MifareDesfireFile* f = app->file_head; f; f = f->next) { saved_files = false; - string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &f->type, 1)) break; - string_printf( - key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &f->comm, 1)) break; - string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Type", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &f->type, 1)) break; + furi_string_printf( + key, "%s File %d Communication Settings", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), &f->comm, 1)) break; + furi_string_printf( + key, "%s File %d Access Rights", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_hex( - file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) + file, furi_string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) break; uint16_t size = 0; if(f->type == MifareDesfireFileTypeStandard || f->type == MifareDesfireFileTypeBackup) { size = f->settings.data.size; - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Size", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.data.size, 1)) + file, furi_string_get_cstr(key), &f->settings.data.size, 1)) break; } else if(f->type == MifareDesfireFileTypeValue) { - string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Hi Limit", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.hi_limit, 1)) + file, furi_string_get_cstr(key), &f->settings.value.hi_limit, 1)) break; - string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Lo Limit", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.lo_limit, 1)) + file, furi_string_get_cstr(key), &f->settings.value.lo_limit, 1)) break; - string_printf( - key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Limited Credit Value", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) + file, furi_string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) break; - string_printf( - key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Limited Credit Enabled", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_bool( - file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1)) + file, + furi_string_get_cstr(key), + &f->settings.value.limited_credit_enabled, + 1)) break; size = 4; } else if( f->type == MifareDesfireFileTypeLinearRecord || f->type == MifareDesfireFileTypeCyclicRecord) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Size", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.size, 1)) + file, furi_string_get_cstr(key), &f->settings.record.size, 1)) break; - string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Max", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.max, 1)) + file, furi_string_get_cstr(key), &f->settings.record.max, 1)) break; - string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Cur", furi_string_get_cstr(prefix), f->id); if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.cur, 1)) + file, furi_string_get_cstr(key), &f->settings.record.cur, 1)) break; size = f->settings.record.size * f->settings.record.cur; } if(f->contents) { - string_printf(key, "%s File %d", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), f->contents, size)) break; + furi_string_printf(key, "%s File %d", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_write_hex(file, furi_string_get_cstr(key), f->contents, size)) + break; } saved_files = true; } @@ -403,16 +418,17 @@ static bool nfc_device_save_mifare_df_app(FlipperFormat* file, MifareDesfireAppl } while(false); free(tmp); - string_clear(prefix); - string_clear(key); + furi_string_free(prefix); + furi_string_free(key); return saved; } bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) { bool parsed = false; - string_t prefix, key; - string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - string_init(key); + FuriString *prefix, *key; + prefix = + furi_string_alloc_printf("Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); + key = furi_string_alloc(); uint8_t* tmp = NULL; MifareDesfireFile* f = NULL; @@ -420,16 +436,16 @@ bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication app->key_settings = malloc(sizeof(MifareDesfireKeySettings)); memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings)); if(!nfc_device_load_mifare_df_key_settings( - file, app->key_settings, string_get_cstr(prefix))) { + file, app->key_settings, furi_string_get_cstr(prefix))) { free(app->key_settings); app->key_settings = NULL; break; } - string_printf(key, "%s File IDs", string_get_cstr(prefix)); + furi_string_printf(key, "%s File IDs", furi_string_get_cstr(prefix)); uint32_t n_files; - if(!flipper_format_get_value_count(file, string_get_cstr(key), &n_files)) break; + if(!flipper_format_get_value_count(file, furi_string_get_cstr(key), &n_files)) break; tmp = malloc(n_files); - if(!flipper_format_read_hex(file, string_get_cstr(key), tmp, n_files)) break; + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), tmp, n_files)) break; MifareDesfireFile** file_head = &app->file_head; bool parsed_files = true; for(uint32_t i = 0; i < n_files; i++) { @@ -437,61 +453,69 @@ bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication f = malloc(sizeof(MifareDesfireFile)); memset(f, 0, sizeof(MifareDesfireFile)); f->id = tmp[i]; - string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), &f->type, 1)) break; - string_printf( - key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), &f->comm, 1)) break; - string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) + furi_string_printf(key, "%s File %d Type", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), &f->type, 1)) break; + furi_string_printf( + key, "%s File %d Communication Settings", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), &f->comm, 1)) break; + furi_string_printf( + key, "%s File %d Access Rights", furi_string_get_cstr(prefix), f->id); + if(!flipper_format_read_hex( + file, furi_string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) break; if(f->type == MifareDesfireFileTypeStandard || f->type == MifareDesfireFileTypeBackup) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Size", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.data.size, 1)) + file, furi_string_get_cstr(key), &f->settings.data.size, 1)) break; } else if(f->type == MifareDesfireFileTypeValue) { - string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Hi Limit", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.hi_limit, 1)) + file, furi_string_get_cstr(key), &f->settings.value.hi_limit, 1)) break; - string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Lo Limit", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.lo_limit, 1)) + file, furi_string_get_cstr(key), &f->settings.value.lo_limit, 1)) break; - string_printf( - key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Limited Credit Value", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) + file, furi_string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) break; - string_printf( - key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id); + furi_string_printf( + key, "%s File %d Limited Credit Enabled", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_bool( - file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1)) + file, + furi_string_get_cstr(key), + &f->settings.value.limited_credit_enabled, + 1)) break; } else if( f->type == MifareDesfireFileTypeLinearRecord || f->type == MifareDesfireFileTypeCyclicRecord) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Size", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.size, 1)) + file, furi_string_get_cstr(key), &f->settings.record.size, 1)) break; - string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Max", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.max, 1)) + file, furi_string_get_cstr(key), &f->settings.record.max, 1)) break; - string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id); + furi_string_printf(key, "%s File %d Cur", furi_string_get_cstr(prefix), f->id); if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.cur, 1)) + file, furi_string_get_cstr(key), &f->settings.record.cur, 1)) break; } - string_printf(key, "%s File %d", string_get_cstr(prefix), f->id); - if(flipper_format_key_exist(file, string_get_cstr(key))) { + furi_string_printf(key, "%s File %d", furi_string_get_cstr(prefix), f->id); + if(flipper_format_key_exist(file, furi_string_get_cstr(key))) { uint32_t size; - if(!flipper_format_get_value_count(file, string_get_cstr(key), &size)) break; + if(!flipper_format_get_value_count(file, furi_string_get_cstr(key), &size)) break; f->contents = malloc(size); - if(!flipper_format_read_hex(file, string_get_cstr(key), f->contents, size)) break; + if(!flipper_format_read_hex(file, furi_string_get_cstr(key), f->contents, size)) + break; } *file_head = f; file_head = &f->next; @@ -509,8 +533,8 @@ bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication free(f); } free(tmp); - string_clear(prefix); - string_clear(key); + furi_string_free(prefix); + furi_string_free(key); return parsed; } @@ -612,42 +636,14 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { return parsed; } -static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - EmvData* data = &dev->dev_data.emv_data; - uint32_t data_temp = 0; - - do { - // Write Bank card specific data - if(!flipper_format_write_comment_cstr(file, "Bank card specific data")) break; - if(!flipper_format_write_hex(file, "AID", data->aid, data->aid_len)) break; - if(!flipper_format_write_string_cstr(file, "Name", data->name)) break; - if(!flipper_format_write_hex(file, "Number", data->number, data->number_len)) break; - if(data->exp_mon) { - uint8_t exp_data[2] = {data->exp_mon, data->exp_year}; - if(!flipper_format_write_hex(file, "Exp data", exp_data, sizeof(exp_data))) break; - } - if(data->country_code) { - data_temp = data->country_code; - if(!flipper_format_write_uint32(file, "Country code", &data_temp, 1)) break; - } - if(data->currency_code) { - data_temp = data->currency_code; - if(!flipper_format_write_uint32(file, "Currency code", &data_temp, 1)) break; - } - saved = true; - } while(false); - - return saved; -} - +// Leave for backward compatibility bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) { bool parsed = false; EmvData* data = &dev->dev_data.emv_data; memset(data, 0, sizeof(EmvData)); uint32_t data_cnt = 0; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { // Load essential data @@ -655,7 +651,7 @@ bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) { data->aid_len = data_cnt; if(!flipper_format_read_hex(file, "AID", data->aid, data->aid_len)) break; if(!flipper_format_read_string(file, "Name", temp_str)) break; - strlcpy(data->name, string_get_cstr(temp_str), sizeof(data->name)); + strlcpy(data->name, furi_string_get_cstr(temp_str), sizeof(data->name)); if(!flipper_format_get_value_count(file, "Number", &data_cnt)) break; data->number_len = data_cnt; if(!flipper_format_read_hex(file, "Number", data->number, data->number_len)) break; @@ -674,15 +670,15 @@ bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) { } } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return parsed; } static void nfc_device_write_mifare_classic_block( - string_t block_str, + FuriString* block_str, MfClassicData* data, uint8_t block_num) { - string_reset(block_str); + furi_string_reset(block_str); bool is_sec_trailer = mf_classic_is_sector_trailer(block_num); if(is_sec_trailer) { uint8_t sector_num = mf_classic_get_sector_by_block(block_num); @@ -690,45 +686,45 @@ static void nfc_device_write_mifare_classic_block( // Write key A for(size_t i = 0; i < sizeof(sec_tr->key_a); i++) { if(mf_classic_is_key_found(data, sector_num, MfClassicKeyA)) { - string_cat_printf(block_str, "%02X ", sec_tr->key_a[i]); + furi_string_cat_printf(block_str, "%02X ", sec_tr->key_a[i]); } else { - string_cat_printf(block_str, "?? "); + furi_string_cat_printf(block_str, "?? "); } } // Write Access bytes for(size_t i = 0; i < MF_CLASSIC_ACCESS_BYTES_SIZE; i++) { if(mf_classic_is_block_read(data, block_num)) { - string_cat_printf(block_str, "%02X ", sec_tr->access_bits[i]); + furi_string_cat_printf(block_str, "%02X ", sec_tr->access_bits[i]); } else { - string_cat_printf(block_str, "?? "); + furi_string_cat_printf(block_str, "?? "); } } // Write key B for(size_t i = 0; i < sizeof(sec_tr->key_b); i++) { if(mf_classic_is_key_found(data, sector_num, MfClassicKeyB)) { - string_cat_printf(block_str, "%02X ", sec_tr->key_b[i]); + furi_string_cat_printf(block_str, "%02X ", sec_tr->key_b[i]); } else { - string_cat_printf(block_str, "?? "); + furi_string_cat_printf(block_str, "?? "); } } } else { // Write data block for(size_t i = 0; i < MF_CLASSIC_BLOCK_SIZE; i++) { if(mf_classic_is_block_read(data, block_num)) { - string_cat_printf(block_str, "%02X ", data->block[block_num].value[i]); + furi_string_cat_printf(block_str, "%02X ", data->block[block_num].value[i]); } else { - string_cat_printf(block_str, "?? "); + furi_string_cat_printf(block_str, "?? "); } } } - string_strim(block_str); + furi_string_trim(block_str); } static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; MfClassicData* data = &dev->dev_data.mf_classic_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint16_t blocks = 0; // Save Mifare Classic specific data @@ -749,39 +745,39 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* file, "Mifare Classic blocks, \'??\' means unknown data")) break; bool block_saved = true; - string_t block_str; - string_init(block_str); + FuriString* block_str; + block_str = furi_string_alloc(); for(size_t i = 0; i < blocks; i++) { - string_printf(temp_str, "Block %d", i); + furi_string_printf(temp_str, "Block %d", i); nfc_device_write_mifare_classic_block(block_str, data, i); - if(!flipper_format_write_string(file, string_get_cstr(temp_str), block_str)) { + if(!flipper_format_write_string(file, furi_string_get_cstr(temp_str), block_str)) { block_saved = false; break; } } - string_clear(block_str); + furi_string_free(block_str); if(!block_saved) break; saved = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return saved; } static void nfc_device_load_mifare_classic_block( - string_t block_str, + FuriString* block_str, MfClassicData* data, uint8_t block_num) { - string_strim(block_str); + furi_string_trim(block_str); MfClassicBlock block_tmp = {}; bool is_sector_trailer = mf_classic_is_sector_trailer(block_num); uint8_t sector_num = mf_classic_get_sector_by_block(block_num); uint16_t block_unknown_bytes_mask = 0; - string_strim(block_str); + furi_string_trim(block_str); for(size_t i = 0; i < MF_CLASSIC_BLOCK_SIZE; i++) { - char hi = string_get_char(block_str, 3 * i); - char low = string_get_char(block_str, 3 * i + 1); + char hi = furi_string_get_char(block_str, 3 * i); + char low = furi_string_get_char(block_str, 3 * i + 1); uint8_t byte = 0; if(hex_char_to_uint8(hi, low, &byte)) { block_tmp.value[i] = byte; @@ -824,19 +820,19 @@ static void nfc_device_load_mifare_classic_block( static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) { bool parsed = false; MfClassicData* data = &dev->dev_data.mf_classic_data; - string_t temp_str; + FuriString* temp_str; uint32_t data_format_version = 0; - string_init(temp_str); + temp_str = furi_string_alloc(); uint16_t data_blocks = 0; memset(data, 0, sizeof(MfClassicData)); do { // Read Mifare Classic type if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!string_cmp_str(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; data_blocks = 64; - } else if(!string_cmp_str(temp_str, "4K")) { + } else if(!furi_string_cmp(temp_str, "4K")) { data->type = MfClassicType4k; data_blocks = 256; } else { @@ -857,17 +853,17 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* // Read Mifare Classic blocks bool block_read = true; - string_t block_str; - string_init(block_str); + FuriString* block_str; + block_str = furi_string_alloc(); for(size_t i = 0; i < data_blocks; i++) { - string_printf(temp_str, "Block %d", i); - if(!flipper_format_read_string(file, string_get_cstr(temp_str), block_str)) { + furi_string_printf(temp_str, "Block %d", i); + if(!flipper_format_read_string(file, furi_string_get_cstr(temp_str), block_str)) { block_read = false; break; } nfc_device_load_mifare_classic_block(block_str, data, i); } - string_clear(block_str); + furi_string_free(block_str); if(!block_read) break; // Set keys and blocks as unknown for backward compatibility @@ -880,32 +876,32 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* parsed = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return parsed; } -static void nfc_device_get_key_cache_file_path(NfcDevice* dev, string_t file_path) { +static void nfc_device_get_key_cache_file_path(NfcDevice* dev, FuriString* file_path) { uint8_t* uid = dev->dev_data.nfc_data.uid; uint8_t uid_len = dev->dev_data.nfc_data.uid_len; - string_set_str(file_path, NFC_DEVICE_KEYS_FOLDER "/"); + furi_string_set(file_path, NFC_DEVICE_KEYS_FOLDER "/"); for(size_t i = 0; i < uid_len; i++) { - string_cat_printf(file_path, "%02X", uid[i]); + furi_string_cat_printf(file_path, "%02X", uid[i]); } - string_cat_printf(file_path, NFC_DEVICE_KEYS_EXTENSION); + furi_string_cat_printf(file_path, NFC_DEVICE_KEYS_EXTENSION); } static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { FlipperFormat* file = flipper_format_file_alloc(dev->storage); MfClassicData* data = &dev->dev_data.mf_classic_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); nfc_device_get_key_cache_file_path(dev, temp_str); bool save_success = false; do { if(!storage_simply_mkdir(dev->storage, NFC_DEVICE_KEYS_FOLDER)) break; - if(!storage_simply_remove(dev->storage, string_get_cstr(temp_str))) break; - if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break; + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(temp_str))) break; + if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version)) break; if(data->type == MfClassicType1k) { @@ -920,29 +916,29 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { for(size_t i = 0; (i < sector_num) && (key_save_success); i++) { MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, i); if(FURI_BIT(data->key_a_mask, i)) { - string_printf(temp_str, "Key A sector %d", i); - key_save_success = - flipper_format_write_hex(file, string_get_cstr(temp_str), sec_tr->key_a, 6); + furi_string_printf(temp_str, "Key A sector %d", i); + key_save_success = flipper_format_write_hex( + file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6); } if(!key_save_success) break; if(FURI_BIT(data->key_a_mask, i)) { - string_printf(temp_str, "Key B sector %d", i); - key_save_success = - flipper_format_write_hex(file, string_get_cstr(temp_str), sec_tr->key_b, 6); + furi_string_printf(temp_str, "Key B sector %d", i); + key_save_success = flipper_format_write_hex( + file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6); } } save_success = key_save_success; } while(false); flipper_format_free(file); - string_clear(temp_str); + furi_string_free(temp_str); return save_success; } bool nfc_device_load_key_cache(NfcDevice* dev) { furi_assert(dev); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); MfClassicData* data = &dev->dev_data.mf_classic_data; nfc_device_get_key_cache_file_path(dev, temp_str); @@ -950,16 +946,17 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { bool load_success = false; do { - if(storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) != FSE_OK) break; - if(!flipper_format_file_open_existing(file, string_get_cstr(temp_str))) break; + if(storage_common_stat(dev->storage, furi_string_get_cstr(temp_str), NULL) != FSE_OK) + break; + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break; uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, nfc_keys_file_header)) break; + if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; if(version != nfc_keys_file_version) break; if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!string_cmp_str(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; - } else if(!string_cmp_str(temp_str, "4K")) { + } else if(!furi_string_cmp(temp_str, "4K")) { data->type = MfClassicType4k; } else { break; @@ -971,21 +968,21 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { for(size_t i = 0; (i < sectors) && (key_read_success); i++) { MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, i); if(FURI_BIT(data->key_a_mask, i)) { - string_printf(temp_str, "Key A sector %d", i); - key_read_success = - flipper_format_read_hex(file, string_get_cstr(temp_str), sec_tr->key_a, 6); + furi_string_printf(temp_str, "Key A sector %d", i); + key_read_success = flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6); } if(!key_read_success) break; if(FURI_BIT(data->key_b_mask, i)) { - string_printf(temp_str, "Key B sector %d", i); - key_read_success = - flipper_format_read_hex(file, string_get_cstr(temp_str), sec_tr->key_b, 6); + furi_string_printf(temp_str, "Key B sector %d", i); + key_read_success = flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6); } } load_success = key_read_success; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return load_success; @@ -997,16 +994,16 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) { strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN); } -static void nfc_device_get_path_without_ext(string_t orig_path, string_t shadow_path) { +static void nfc_device_get_path_without_ext(FuriString* orig_path, FuriString* shadow_path) { // TODO: this won't work if there is ".nfc" anywhere in the path other than // at the end - size_t ext_start = string_search_str(orig_path, NFC_APP_EXTENSION); - string_set_n(shadow_path, orig_path, 0, ext_start); + size_t ext_start = furi_string_search(orig_path, NFC_APP_EXTENSION); + furi_string_set_n(shadow_path, orig_path, 0, ext_start); } -static void nfc_device_get_shadow_path(string_t orig_path, string_t shadow_path) { +static void nfc_device_get_shadow_path(FuriString* orig_path, FuriString* shadow_path) { nfc_device_get_path_without_ext(orig_path, shadow_path); - string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION); + furi_string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION); } static bool nfc_device_save_file( @@ -1020,30 +1017,30 @@ static bool nfc_device_save_file( bool saved = false; FlipperFormat* file = flipper_format_file_alloc(dev->storage); FuriHalNfcDevData* data = &dev->dev_data.nfc_data; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { - if(use_load_path && !string_empty_p(dev->load_path)) { + if(use_load_path && !furi_string_empty(dev->load_path)) { // Get directory name - path_extract_dirname(string_get_cstr(dev->load_path), temp_str); + path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str); // Create nfc directory if necessary - if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break; + if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(temp_str))) break; // Make path to file to save - string_cat_printf(temp_str, "/%s%s", dev_name, extension); + furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension); } else { // Create nfc directory if necessary if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break; // First remove nfc device file if it was saved - string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); + furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); } // Open file - if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break; + if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; // Write header if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; // Write nfc device type if(!flipper_format_write_comment_cstr( - file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card")) + file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic")) break; nfc_device_prepare_format_string(dev, temp_str); if(!flipper_format_write_string(file, "Device type", temp_str)) break; @@ -1058,8 +1055,6 @@ static bool nfc_device_save_file( if(!nfc_device_save_mifare_ul_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { if(!nfc_device_save_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatBankCard) { - if(!nfc_device_save_bank_card_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { // Save data if(!nfc_device_save_mifare_classic_data(file, dev)) break; @@ -1072,7 +1067,7 @@ static bool nfc_device_save_file( if(!saved) { dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file"); } - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return saved; } @@ -1086,13 +1081,13 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) { return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true); } -static bool nfc_device_load_data(NfcDevice* dev, string_t path, bool show_dialog) { +static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dialog) { bool parsed = false; FlipperFormat* file = flipper_format_file_alloc(dev->storage); FuriHalNfcDevData* data = &dev->dev_data.nfc_data; uint32_t data_cnt = 0; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); bool deprecated_version = false; if(dev->loading_cb) { @@ -1103,17 +1098,17 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path, bool show_dialog // Check existance of shadow file nfc_device_get_shadow_path(path, temp_str); dev->shadow_file_exist = - storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK; + storage_common_stat(dev->storage, furi_string_get_cstr(temp_str), NULL) == FSE_OK; // Open shadow file if it exists. If not - open original if(dev->shadow_file_exist) { - if(!flipper_format_file_open_existing(file, string_get_cstr(temp_str))) break; + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break; } else { - if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break; + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break; } // Read and verify file header uint32_t version = 0; if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) { + if(furi_string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) { deprecated_version = true; break; } @@ -1152,7 +1147,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path, bool show_dialog } } - string_clear(temp_str); + furi_string_free(temp_str); flipper_format_free(file); return parsed; } @@ -1162,15 +1157,15 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog) { furi_assert(file_path); // Load device data - string_set_str(dev->load_path, file_path); + furi_string_set(dev->load_path, file_path); bool dev_load = nfc_device_load_data(dev, dev->load_path, show_dialog); if(dev_load) { // Set device name - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); path_extract_filename_no_ext(file_path, filename); - nfc_device_set_name(dev, string_get_cstr(filename)); - string_clear(filename); + nfc_device_set_name(dev, furi_string_get_cstr(filename)); + furi_string_free(filename); } return dev_load; @@ -1180,8 +1175,8 @@ bool nfc_file_select(NfcDevice* dev) { furi_assert(dev); // Input events and views are managed by file_browser - string_t nfc_app_folder; - string_init_set_str(nfc_app_folder, NFC_APP_FOLDER); + FuriString* nfc_app_folder; + nfc_app_folder = furi_string_alloc_set(NFC_APP_FOLDER); const DialogsFileBrowserOptions browser_options = { .extension = NFC_APP_EXTENSION, @@ -1195,17 +1190,17 @@ bool nfc_file_select(NfcDevice* dev) { bool res = dialog_file_browser_show(dev->dialogs, dev->load_path, nfc_app_folder, &browser_options); - string_clear(nfc_app_folder); + furi_string_free(nfc_app_folder); if(res) { - string_t filename; - string_init(filename); + FuriString* filename; + filename = furi_string_alloc(); path_extract_filename(dev->load_path, filename, true); - strncpy(dev->dev_name, string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN); + strncpy(dev->dev_name, furi_string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN); res = nfc_device_load_data(dev, dev->load_path, true); if(res) { nfc_device_set_name(dev, dev->dev_name); } - string_clear(filename); + furi_string_free(filename); } return res; @@ -1223,7 +1218,7 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) { } memset(&dev_data->nfc_data, 0, sizeof(FuriHalNfcDevData)); dev_data->protocol = NfcDeviceProtocolUnknown; - string_reset(dev_data->parsed_data); + furi_string_reset(dev_data->parsed_data); } void nfc_device_clear(NfcDevice* dev) { @@ -1232,33 +1227,34 @@ void nfc_device_clear(NfcDevice* dev) { nfc_device_set_name(dev, ""); nfc_device_data_clear(&dev->dev_data); dev->format = NfcDeviceSaveFormatUid; - string_reset(dev->load_path); + furi_string_reset(dev->load_path); } bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { furi_assert(dev); bool deleted = false; - string_t file_path; - string_init(file_path); + FuriString* file_path; + file_path = furi_string_alloc(); do { // Delete original file - if(use_load_path && !string_empty_p(dev->load_path)) { - string_set(file_path, dev->load_path); + if(use_load_path && !furi_string_empty(dev->load_path)) { + furi_string_set(file_path, dev->load_path); } else { - string_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + furi_string_printf( + file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); } - if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; // Delete shadow file if it exists if(dev->shadow_file_exist) { - if(use_load_path && !string_empty_p(dev->load_path)) { + if(use_load_path && !furi_string_empty(dev->load_path)) { nfc_device_get_shadow_path(dev->load_path, file_path); } else { - string_printf( + furi_string_printf( file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); } - if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; } deleted = true; } while(0); @@ -1267,7 +1263,7 @@ bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); } - string_clear(file_path); + furi_string_free(file_path); return deleted; } @@ -1276,29 +1272,29 @@ bool nfc_device_restore(NfcDevice* dev, bool use_load_path) { furi_assert(dev->shadow_file_exist); bool restored = false; - string_t path; + FuriString* path; - string_init(path); + path = furi_string_alloc(); do { - if(use_load_path && !string_empty_p(dev->load_path)) { + if(use_load_path && !furi_string_empty(dev->load_path)) { nfc_device_get_shadow_path(dev->load_path, path); } else { - string_printf( + furi_string_printf( path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); } - if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break; + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(path))) break; dev->shadow_file_exist = false; - if(use_load_path && !string_empty_p(dev->load_path)) { - string_set(path, dev->load_path); + if(use_load_path && !furi_string_empty(dev->load_path)) { + furi_string_set(path, dev->load_path); } else { - string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + furi_string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); } if(!nfc_device_load_data(dev, path, true)) break; restored = true; } while(0); - string_clear(path); + furi_string_free(path); return restored; } diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index f9a0b24b..6cac72c6 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -60,7 +60,7 @@ typedef struct { MfClassicData mf_classic_data; MifareDesfireData mf_df_data; }; - string_t parsed_data; + FuriString* parsed_data; } NfcDeviceData; typedef struct { @@ -68,7 +68,7 @@ typedef struct { DialogsApp* dialogs; NfcDeviceData dev_data; char dev_name[NFC_DEV_NAME_MAX_LEN + 1]; - string_t load_path; + FuriString* load_path; NfcDeviceSaveFormat format; bool shadow_file_exist; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 2feae443..ebe20390 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -191,7 +191,7 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FuriHalNfcTxRxCont uint8_t sectors_total = mf_classic_get_total_sectors_num(nfc_worker->dev_data->mf_classic_data.type); FURI_LOG_I(TAG, "Read %d sectors out of %d total", sectors_read, sectors_total); - read_success = (sectors_read == sectors_total); + read_success = mf_classic_is_card_read(&nfc_worker->dev_data->mf_classic_data); } } while(false); @@ -233,31 +233,51 @@ static bool nfc_worker_read_bank_card(NfcWorker* nfc_worker, FuriHalNfcTxRxConte reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); } - do { - // Read card + // Bank cards require strong field to start application. If we find AID, try at least several + // times to start EMV application + uint8_t start_application_attempts = 0; + while(start_application_attempts < 3) { + if(nfc_worker->state != NfcWorkerStateRead) break; + start_application_attempts++; if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break; - if(!emv_read_bank_card(tx_rx, &emv_app)) break; - // Copy data - // TODO Set EmvData to reader or like in mifare ultralight! - result->number_len = emv_app.card_number_len; - memcpy(result->number, emv_app.card_number, result->number_len); + if(emv_read_bank_card(tx_rx, &emv_app)) { + FURI_LOG_D(TAG, "Bank card number read from %d attempt", start_application_attempts); + break; + } else if(emv_app.aid_len && !emv_app.app_started) { + FURI_LOG_D( + TAG, + "AID found but failed to start EMV app from %d attempt", + start_application_attempts); + furi_hal_nfc_sleep(); + continue; + } else { + FURI_LOG_D(TAG, "Failed to find AID"); + break; + } + } + // Copy data + if(emv_app.aid_len) { result->aid_len = emv_app.aid_len; memcpy(result->aid, emv_app.aid, result->aid_len); - if(emv_app.name_found) { - memcpy(result->name, emv_app.name, sizeof(emv_app.name)); - } - if(emv_app.exp_month) { - result->exp_mon = emv_app.exp_month; - result->exp_year = emv_app.exp_year; - } - if(emv_app.country_code) { - result->country_code = emv_app.country_code; - } - if(emv_app.currency_code) { - result->currency_code = emv_app.currency_code; - } read_success = true; - } while(false); + } + if(emv_app.card_number_len) { + result->number_len = emv_app.card_number_len; + memcpy(result->number, emv_app.card_number, result->number_len); + } + if(emv_app.name_found) { + memcpy(result->name, emv_app.name, sizeof(emv_app.name)); + } + if(emv_app.exp_month) { + result->exp_mon = emv_app.exp_month; + result->exp_year = emv_app.exp_year; + } + if(emv_app.country_code) { + result->country_code = emv_app.country_code; + } + if(emv_app.currency_code) { + result->currency_code = emv_app.currency_code; + } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { reader_analyzer_stop(nfc_worker->reader_analyzer); @@ -453,6 +473,73 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { } } +static void nfc_worker_mf_classic_key_attack( + NfcWorker* nfc_worker, + uint64_t key, + FuriHalNfcTxRxContext* tx_rx, + uint16_t start_sector) { + furi_assert(nfc_worker); + + bool card_found_notified = true; + bool card_removed_notified = false; + + MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; + uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); + + furi_assert(start_sector < total_sectors); + + // Check every sector's A and B keys with the given key + for(size_t i = start_sector; i < total_sectors; i++) { + furi_hal_nfc_sleep(); + if(furi_hal_nfc_activate_nfca(200, NULL)) { + furi_hal_nfc_sleep(); + if(!card_found_notified) { + nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); + card_found_notified = true; + card_removed_notified = false; + } + uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i); + if(mf_classic_is_sector_read(data, i)) continue; + if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) { + FURI_LOG_D( + TAG, + "Trying A key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) { + mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + } + } + if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { + FURI_LOG_D( + TAG, + "Trying B key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) { + mf_classic_set_key_found(data, i, MfClassicKeyB, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + } + } + + if(mf_classic_is_sector_read(data, i)) continue; + mf_classic_read_sector(tx_rx, data, i); + } else { + if(!card_removed_notified) { + nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); + card_removed_notified = true; + card_found_notified = false; + } + } + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; + } +} + void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -462,6 +549,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { &nfc_worker->dev_data->mf_classic_dict_attack_data; uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); uint64_t key = 0; + uint64_t prev_key = 0; FuriHalNfcTxRxContext tx_rx = {}; bool card_found_notified = true; bool card_removed_notified = false; @@ -474,7 +562,8 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { return; } - FURI_LOG_D(TAG, "Start Dictionary attack, Key Count %d", mf_classic_dict_get_total_keys(dict)); + FURI_LOG_D( + TAG, "Start Dictionary attack, Key Count %ld", mf_classic_dict_get_total_keys(dict)); for(size_t i = 0; i < total_sectors; i++) { FURI_LOG_I(TAG, "Sector %d", i); nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context); @@ -484,6 +573,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); uint16_t key_index = 0; while(mf_classic_dict_get_next_key(dict, &key)) { + FURI_LOG_T(TAG, "Key %d", key_index); if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); } @@ -494,6 +584,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); card_found_notified = true; card_removed_notified = false; + nfc_worker_mf_classic_key_attack(nfc_worker, prev_key, &tx_rx, i); } FURI_LOG_D( TAG, @@ -505,15 +596,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) { mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } furi_hal_nfc_sleep(); } if(!is_key_b_found) { is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) { + FURI_LOG_D(TAG, "Key found"); mf_classic_set_key_found(data, i, MfClassicKeyB, key); nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } } if(is_key_a_found && is_key_b_found) break; @@ -526,6 +621,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { } if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; } + memcpy(&prev_key, &key, sizeof(key)); } if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; mf_classic_read_sector(&tx_rx, data, i); @@ -647,7 +743,8 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* furi_assert(context); NfcWorker* nfc_worker = context; - if(event == ReaderAnalyzerEventMfkeyCollected) { + if((nfc_worker->state == NfcWorkerStateAnalyzeReader) && + (event == ReaderAnalyzerEventMfkeyCollected)) { if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventDetectReaderMfkeyCollected, nfc_worker->context); } @@ -655,6 +752,9 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* } void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); + FuriHalNfcTxRxContext tx_rx = {}; ReaderAnalyzer* reader_analyzer = nfc_worker->reader_analyzer; @@ -673,17 +773,32 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { rfal_platform_spi_acquire(); FURI_LOG_D(TAG, "Start reader analyzer"); + + uint8_t reader_no_data_received_cnt = 0; + bool reader_no_data_notified = true; + while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { furi_hal_nfc_stop_cmd(); furi_delay_ms(5); furi_hal_nfc_listen_start(nfc_data); if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { + if(reader_no_data_notified) { + nfc_worker->callback(NfcWorkerEventDetectReaderDetected, nfc_worker->context); + } + reader_no_data_received_cnt = 0; + reader_no_data_notified = false; NfcProtocol protocol = reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); if(protocol == NfcDeviceProtocolMifareClassic) { mf_classic_emulator(&emulator, &tx_rx); } } else { + reader_no_data_received_cnt++; + if(!reader_no_data_notified && (reader_no_data_received_cnt > 5)) { + nfc_worker->callback(NfcWorkerEventDetectReaderLost, nfc_worker->context); + reader_no_data_received_cnt = 0; + reader_no_data_notified = true; + } FURI_LOG_D(TAG, "No data from reader"); continue; } diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index b7bf4da9..84615f5d 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -56,6 +56,8 @@ typedef enum { NfcWorkerEventFoundKeyB, // Detect Reader events + NfcWorkerEventDetectReaderDetected, + NfcWorkerEventDetectReaderLost, NfcWorkerEventDetectReaderMfkeyCollected, // Mifare Ultralight events diff --git a/lib/nfc/parsers/all_in_one.c b/lib/nfc/parsers/all_in_one.c index b49a32f7..05cfe576 100644 --- a/lib/nfc/parsers/all_in_one.c +++ b/lib/nfc/parsers/all_in_one.c @@ -107,7 +107,7 @@ bool all_in_one_parser_parse(NfcDeviceData* dev_data) { dev_data->mf_ul_data.data[4 * 4 + 5] << 4 | (dev_data->mf_ul_data.data[4 * 4 + 6] >> 4); // Format string for rides count - string_printf( - dev_data->parsed_data, "\e#All-In-One\nNumber: %u\nRides left: %u", serial, ride_count); + furi_string_printf( + dev_data->parsed_data, "\e#All-In-One\nNumber: %lu\nRides left: %u", serial, ride_count); return true; } \ No newline at end of file diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index d34b5794..4af59ade 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -4,8 +4,6 @@ #include "../nfc_worker.h" #include "../nfc_device.h" -#include - typedef enum { NfcSupportedCardTypePlantain, NfcSupportedCardTypeTroika, diff --git a/lib/nfc/parsers/plantain_4k_parser.c b/lib/nfc/parsers/plantain_4k_parser.c index 77387707..348b5a64 100644 --- a/lib/nfc/parsers/plantain_4k_parser.c +++ b/lib/nfc/parsers/plantain_4k_parser.c @@ -1,5 +1,4 @@ #include "nfc_supported_card.h" -#include "plantain_parser.h" // For luhn and string_push_uint64 #include #include @@ -118,36 +117,25 @@ bool plantain_4k_parser_parse(NfcDeviceData* dev_data) { card_number = (card_number << 8) | card_number_arr[i]; } // Convert card number to string - string_t card_number_str; - string_init(card_number_str); + FuriString* card_number_str; + card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string - string_t card_number_suffix; - string_init(card_number_suffix); + FuriString* card_number_suffix; + card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // string_t luhn_checksum_str; - // string_init(luhn_checksum_str); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - - string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); - string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + furi_string_cat_printf(card_number_suffix, "-"); + furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings - string_clear(card_number_suffix); - // string_clear(luhn_checksum_str); + furi_string_free(card_number_suffix); - string_printf( + furi_string_printf( dev_data->parsed_data, - "\e#Plantain\nN:%s\nBalance:%d\n", - string_get_cstr(card_number_str), + "\e#Plantain\nN:%s\nBalance:%ld\n", + furi_string_get_cstr(card_number_str), balance); - string_clear(card_number_str); + furi_string_free(card_number_str); return true; } diff --git a/lib/nfc/parsers/plantain_parser.c b/lib/nfc/parsers/plantain_parser.c index ff81b8e9..5328b5c4 100644 --- a/lib/nfc/parsers/plantain_parser.c +++ b/lib/nfc/parsers/plantain_parser.c @@ -55,28 +55,6 @@ bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; } -void string_push_uint64(uint64_t input, string_t output) { - const uint8_t base = 10; - - do { - char c = input % base; - input /= base; - - if(c < 10) - c += '0'; - else - c += 'A' - 10; - string_push_back(output, c); - } while(input); - - // reverse string - for(uint8_t i = 0; i < string_size(output) / 2; i++) { - char c = string_get_char(output, i); - string_set_char(output, i, string_get_char(output, string_size(output) - i - 1)); - string_set_char(output, string_size(output) - i - 1, c); - } -} - uint8_t plantain_calculate_luhn(uint64_t number) { // No. UNUSED(number); @@ -112,36 +90,25 @@ bool plantain_parser_parse(NfcDeviceData* dev_data) { card_number = (card_number << 8) | card_number_arr[i]; } // Convert card number to string - string_t card_number_str; - string_init(card_number_str); + FuriString* card_number_str; + card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string - string_t card_number_suffix; - string_init(card_number_suffix); + FuriString* card_number_suffix; + card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // string_t luhn_checksum_str; - // string_init(luhn_checksum_str); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - - string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); - string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + furi_string_cat_printf(card_number_suffix, "-"); + furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings - string_clear(card_number_suffix); - // string_clear(luhn_checksum_str); + furi_string_free(card_number_suffix); - string_printf( + furi_string_printf( dev_data->parsed_data, - "\e#Plantain\nN:%s\nBalance:%d\n", - string_get_cstr(card_number_str), + "\e#Plantain\nN:%s\nBalance:%ld\n", + furi_string_get_cstr(card_number_str), balance); - string_clear(card_number_str); + furi_string_free(card_number_str); return true; } diff --git a/lib/nfc/parsers/plantain_parser.h b/lib/nfc/parsers/plantain_parser.h index d37f0dd4..1af8c506 100644 --- a/lib/nfc/parsers/plantain_parser.h +++ b/lib/nfc/parsers/plantain_parser.h @@ -8,6 +8,4 @@ bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); bool plantain_parser_parse(NfcDeviceData* dev_data); -void string_push_uint64(uint64_t input, string_t output); - uint8_t plantain_calculate_luhn(uint64_t number); diff --git a/lib/nfc/parsers/troika_4k_parser.c b/lib/nfc/parsers/troika_4k_parser.c index 8c32381f..d87b4eba 100644 --- a/lib/nfc/parsers/troika_4k_parser.c +++ b/lib/nfc/parsers/troika_4k_parser.c @@ -98,7 +98,8 @@ bool troika_4k_parser_parse(NfcDeviceData* dev_data) { } number >>= 4; - string_printf(dev_data->parsed_data, "\e#Troika\nNum: %ld\nBalance: %d rur.", number, balance); + furi_string_printf( + dev_data->parsed_data, "\e#Troika\nNum: %ld\nBalance: %d rur.", number, balance); return true; } diff --git a/lib/nfc/parsers/troika_parser.c b/lib/nfc/parsers/troika_parser.c index f396b168..9c16296f 100644 --- a/lib/nfc/parsers/troika_parser.c +++ b/lib/nfc/parsers/troika_parser.c @@ -78,7 +78,7 @@ bool troika_parser_parse(NfcDeviceData* dev_data) { } number >>= 4; - string_printf( + furi_string_printf( dev_data->parsed_data, "\e#Troika\nNum: %ld\nBalance: %d rur.", number, balance); troika_parsed = true; } while(false); diff --git a/lib/nfc/parsers/two_cities.c b/lib/nfc/parsers/two_cities.c index d052dff1..2c6184a7 100644 --- a/lib/nfc/parsers/two_cities.c +++ b/lib/nfc/parsers/two_cities.c @@ -118,29 +118,18 @@ bool two_cities_parser_parse(NfcDeviceData* dev_data) { card_number = (card_number << 8) | card_number_arr[i]; } // Convert card number to string - string_t card_number_str; - string_init(card_number_str); + FuriString* card_number_str; + card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string - string_t card_number_suffix; - string_init(card_number_suffix); + FuriString* card_number_suffix; + card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = two_cities_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // string_t luhn_checksum_str; - // string_init(luhn_checksum_str); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - - string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); - string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + furi_string_cat_printf(card_number_suffix, "-"); + furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings - string_clear(card_number_suffix); - // string_clear(luhn_checksum_str); + furi_string_free(card_number_suffix); // ===== // --PLANTAIN-- @@ -158,14 +147,14 @@ bool two_cities_parser_parse(NfcDeviceData* dev_data) { } troika_number >>= 4; - string_printf( + furi_string_printf( dev_data->parsed_data, - "\e#Troika+Plantain\nPN: %s\nPB: %d rur.\nTN: %d\nTB: %d rur.\n", - string_get_cstr(card_number_str), + "\e#Troika+Plantain\nPN: %s\nPB: %ld rur.\nTN: %ld\nTB: %d rur.\n", + furi_string_get_cstr(card_number_str), balance, troika_number, troika_balance); - string_clear(card_number_str); + furi_string_free(card_number_str); return true; } diff --git a/lib/nfc/protocols/emv.c b/lib/nfc/protocols/emv.c index 935c9f63..e00d09e7 100644 --- a/lib/nfc/protocols/emv.c +++ b/lib/nfc/protocols/emv.c @@ -182,7 +182,7 @@ static bool emv_decode_response(uint8_t* buff, uint16_t len, EmvApplication* app return success; } -bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { +static bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { bool app_aid_found = false; const uint8_t emv_select_ppse_cmd[] = { 0x00, 0xA4, // SELECT ppse @@ -212,8 +212,8 @@ bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { return app_aid_found; } -bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { - bool select_app_success = false; +static bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { + app->app_started = false; const uint8_t emv_select_header[] = { 0x00, 0xA4, // SELECT application @@ -236,7 +236,7 @@ bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { if(furi_hal_nfc_tx_rx(tx_rx, 300)) { emv_trace(tx_rx, "Start application answer:"); if(emv_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8, app)) { - select_app_success = true; + app->app_started = true; } else { FURI_LOG_E(TAG, "Failed to read PAN or PDOL"); } @@ -244,7 +244,7 @@ bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { FURI_LOG_E(TAG, "Failed to start application"); } - return select_app_success; + return app->app_started; } static uint16_t emv_prepare_pdol(APDU* dest, APDU* src) { @@ -367,14 +367,6 @@ static bool emv_read_files(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { return card_num_read; } -bool emv_search_application(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app) { - furi_assert(tx_rx); - furi_assert(emv_app); - memset(emv_app, 0, sizeof(EmvApplication)); - - return emv_select_ppse(tx_rx, emv_app); -} - bool emv_read_bank_card(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app) { furi_assert(tx_rx); furi_assert(emv_app); diff --git a/lib/nfc/protocols/emv.h b/lib/nfc/protocols/emv.h index b5a0c574..0ccf7c3e 100644 --- a/lib/nfc/protocols/emv.h +++ b/lib/nfc/protocols/emv.h @@ -45,6 +45,7 @@ typedef struct { uint8_t priority; uint8_t aid[16]; uint8_t aid_len; + bool app_started; char name[32]; bool name_found; uint8_t card_number[10]; @@ -68,15 +69,6 @@ typedef struct { */ bool emv_read_bank_card(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app); -/** Search for EMV Application - * - * @param tx_rx FuriHalNfcTxRxContext instance - * @param emv_app EmvApplication instance - * - * @return true on success - */ -bool emv_search_application(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app); - /** Emulate bank card * @note Answer to application selection and PDOL * diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 3b534393..e879ff4e 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -155,6 +155,16 @@ void mf_classic_set_key_found( } } +void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type) { + furi_assert(data); + + if(key_type == MfClassicKeyA) { + FURI_BIT_CLEAR(data->key_a_mask, sector_num); + } else if(key_type == MfClassicKeyB) { + FURI_BIT_CLEAR(data->key_b_mask, sector_num); + } +} + bool mf_classic_is_sector_read(MfClassicData* data, uint8_t sector_num) { furi_assert(data); @@ -203,6 +213,18 @@ void mf_classic_get_read_sectors_and_keys( } } +bool mf_classic_is_card_read(MfClassicData* data) { + furi_assert(data); + + uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t sectors_read = 0; + uint8_t keys_found = 0; + mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); + bool card_read = (sectors_read == sectors_total) && (keys_found == sectors_total * 2); + + return card_read; +} + static bool mf_classic_is_allowed_access_sector_trailer( MfClassicEmulator* emulator, uint8_t block_num, @@ -612,7 +634,15 @@ static bool mf_classic_read_sector_with_reader( } // Auth to first block in sector - if(!mf_classic_auth(tx_rx, first_block, key, key_type, crypto)) break; + if(!mf_classic_auth(tx_rx, first_block, key, key_type, crypto)) { + // Set key to MF_CLASSIC_NO_KEY to prevent further attempts + if(key_type == MfClassicKeyA) { + sector_reader->key_a = MF_CLASSIC_NO_KEY; + } else { + sector_reader->key_b = MF_CLASSIC_NO_KEY; + } + break; + } sector->total_blocks = mf_classic_get_blocks_num_in_sector(sector_reader->sector_num); // Read blocks @@ -711,6 +741,13 @@ uint8_t mf_classic_update_card(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data mf_classic_set_block_read(data, first_block + j, &temp_sector.block[j]); } sectors_read++; + } else { + // Invalid key, set it to not found + if(key_a != MF_CLASSIC_NO_KEY) { + mf_classic_set_key_not_found(data, i, MfClassicKeyA); + } else { + mf_classic_set_key_not_found(data, i, MfClassicKeyB); + } } } } @@ -847,7 +884,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ FURI_LOG_D( TAG, - "%08x key%c block %d nt/nr/ar: %08x %08x %08x", + "%08lx key%c block %d nt/nr/ar: %08lx %08lx %08lx", emulator->cuid, access_key == MfClassicKeyA ? 'A' : 'B', sector_trailer_block, @@ -858,7 +895,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ crypto1_word(&emulator->crypto, nr, 1); uint32_t cardRr = ar ^ crypto1_word(&emulator->crypto, 0, 0); if(cardRr != prng_successor(nonce, 64)) { - FURI_LOG_T(TAG, "Wrong AUTH! %08X != %08X", cardRr, prng_successor(nonce, 64)); + FURI_LOG_T(TAG, "Wrong AUTH! %08lX != %08lX", cardRr, prng_successor(nonce, 64)); // Don't send NACK, as the tag doesn't send it command_processed = true; break; diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index b9921fb1..ead846e4 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -98,12 +98,16 @@ void mf_classic_set_key_found( MfClassicKey key_type, uint64_t key); +void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type); + bool mf_classic_is_block_read(MfClassicData* data, uint8_t block_num); void mf_classic_set_block_read(MfClassicData* data, uint8_t block_num, MfClassicBlock* block_data); bool mf_classic_is_sector_read(MfClassicData* data, uint8_t sector_num); +bool mf_classic_is_card_read(MfClassicData* data); + void mf_classic_get_read_sectors_and_keys( MfClassicData* data, uint8_t* sectors_read, diff --git a/lib/nfc/protocols/mifare_desfire.c b/lib/nfc/protocols/mifare_desfire.c index f969cdde..b2247bf2 100644 --- a/lib/nfc/protocols/mifare_desfire.c +++ b/lib/nfc/protocols/mifare_desfire.c @@ -42,14 +42,14 @@ void mf_df_clear(MifareDesfireData* data) { data->app_head = NULL; } -void mf_df_cat_data(MifareDesfireData* data, string_t out) { +void mf_df_cat_data(MifareDesfireData* data, FuriString* out) { mf_df_cat_card_info(data, out); for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { mf_df_cat_application(app, out); } } -void mf_df_cat_card_info(MifareDesfireData* data, string_t out) { +void mf_df_cat_card_info(MifareDesfireData* data, FuriString* out) { mf_df_cat_version(&data->version, out); if(data->free_memory) { mf_df_cat_free_mem(data->free_memory, out); @@ -59,8 +59,8 @@ void mf_df_cat_card_info(MifareDesfireData* data, string_t out) { } } -void mf_df_cat_version(MifareDesfireVersion* version, string_t out) { - string_cat_printf( +void mf_df_cat_version(MifareDesfireVersion* version, FuriString* out) { + furi_string_cat_printf( out, "%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", version->uid[0], @@ -70,7 +70,7 @@ void mf_df_cat_version(MifareDesfireVersion* version, string_t out) { version->uid[4], version->uid[5], version->uid[6]); - string_cat_printf( + furi_string_cat_printf( out, "hw %02x type %02x sub %02x\n" " maj %02x min %02x\n" @@ -82,7 +82,7 @@ void mf_df_cat_version(MifareDesfireVersion* version, string_t out) { version->hw_minor, version->hw_storage, version->hw_proto); - string_cat_printf( + furi_string_cat_printf( out, "sw %02x type %02x sub %02x\n" " maj %02x min %02x\n" @@ -94,7 +94,7 @@ void mf_df_cat_version(MifareDesfireVersion* version, string_t out) { version->sw_minor, version->sw_storage, version->sw_proto); - string_cat_printf( + furi_string_cat_printf( out, "batch %02x:%02x:%02x:%02x:%02x\n" "week %d year %d\n", @@ -107,40 +107,40 @@ void mf_df_cat_version(MifareDesfireVersion* version, string_t out) { version->prod_year); } -void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, string_t out) { - string_cat_printf(out, "freeMem %d\n", free_mem->bytes); +void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, FuriString* out) { + furi_string_cat_printf(out, "freeMem %ld\n", free_mem->bytes); } -void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, string_t out) { - string_cat_printf(out, "changeKeyID %d\n", ks->change_key_id); - string_cat_printf(out, "configChangeable %d\n", ks->config_changeable); - string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete); - string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list); - string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable); +void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, FuriString* out) { + furi_string_cat_printf(out, "changeKeyID %d\n", ks->change_key_id); + furi_string_cat_printf(out, "configChangeable %d\n", ks->config_changeable); + furi_string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete); + furi_string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list); + furi_string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable); if(ks->flags) { - string_cat_printf(out, "flags %d\n", ks->flags); + furi_string_cat_printf(out, "flags %d\n", ks->flags); } - string_cat_printf(out, "maxKeys %d\n", ks->max_keys); + furi_string_cat_printf(out, "maxKeys %d\n", ks->max_keys); for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) { - string_cat_printf(out, "key %d version %d\n", kv->id, kv->version); + furi_string_cat_printf(out, "key %d version %d\n", kv->id, kv->version); } } -void mf_df_cat_application_info(MifareDesfireApplication* app, string_t out) { - string_cat_printf(out, "Application %02x%02x%02x\n", app->id[0], app->id[1], app->id[2]); +void mf_df_cat_application_info(MifareDesfireApplication* app, FuriString* out) { + furi_string_cat_printf(out, "Application %02x%02x%02x\n", app->id[0], app->id[1], app->id[2]); if(app->key_settings) { mf_df_cat_key_settings(app->key_settings, out); } } -void mf_df_cat_application(MifareDesfireApplication* app, string_t out) { +void mf_df_cat_application(MifareDesfireApplication* app, FuriString* out) { mf_df_cat_application_info(app, out); for(MifareDesfireFile* file = app->file_head; file; file = file->next) { mf_df_cat_file(file, out); } } -void mf_df_cat_file(MifareDesfireFile* file, string_t out) { +void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) { char* type = "unknown"; switch(file->type) { case MifareDesfireFileTypeStandard: @@ -171,9 +171,9 @@ void mf_df_cat_file(MifareDesfireFile* file, string_t out) { comm = "enciphered"; break; } - string_cat_printf(out, "File %d\n", file->id); - string_cat_printf(out, "%s %s\n", type, comm); - string_cat_printf( + furi_string_cat_printf(out, "File %d\n", file->id); + furi_string_cat_printf(out, "%s %s\n", type, comm); + furi_string_cat_printf( out, "r %d w %d rw %d c %d\n", file->access_rights >> 12 & 0xF, @@ -186,15 +186,15 @@ void mf_df_cat_file(MifareDesfireFile* file, string_t out) { case MifareDesfireFileTypeStandard: case MifareDesfireFileTypeBackup: size = file->settings.data.size; - string_cat_printf(out, "size %d\n", size); + furi_string_cat_printf(out, "size %d\n", size); break; case MifareDesfireFileTypeValue: size = 4; - string_cat_printf( - out, "lo %d hi %d\n", file->settings.value.lo_limit, file->settings.value.hi_limit); - string_cat_printf( + furi_string_cat_printf( + out, "lo %ld hi %ld\n", file->settings.value.lo_limit, file->settings.value.hi_limit); + furi_string_cat_printf( out, - "limit %d enabled %d\n", + "limit %ld enabled %d\n", file->settings.value.limited_credit_value, file->settings.value.limited_credit_enabled); break; @@ -202,33 +202,33 @@ void mf_df_cat_file(MifareDesfireFile* file, string_t out) { case MifareDesfireFileTypeCyclicRecord: size = file->settings.record.size; num = file->settings.record.cur; - string_cat_printf(out, "size %d\n", size); - string_cat_printf(out, "num %d max %d\n", num, file->settings.record.max); + furi_string_cat_printf(out, "size %d\n", size); + furi_string_cat_printf(out, "num %d max %ld\n", num, file->settings.record.max); break; } uint8_t* data = file->contents; if(data) { for(int rec = 0; rec < num; rec++) { - string_cat_printf(out, "record %d\n", rec); + furi_string_cat_printf(out, "record %d\n", rec); for(int ch = 0; ch < size; ch += 4) { - string_cat_printf(out, "%03x|", ch); + furi_string_cat_printf(out, "%03x|", ch); for(int i = 0; i < 4; i++) { if(ch + i < size) { - string_cat_printf(out, "%02x ", data[rec * size + ch + i]); + furi_string_cat_printf(out, "%02x ", data[rec * size + ch + i]); } else { - string_cat_printf(out, " "); + furi_string_cat_printf(out, " "); } } for(int i = 0; i < 4 && ch + i < size; i++) { if(isprint(data[rec * size + ch + i])) { - string_cat_printf(out, "%c", data[rec * size + ch + i]); + furi_string_cat_printf(out, "%c", data[rec * size + ch + i]); } else { - string_cat_printf(out, "."); + furi_string_cat_printf(out, "."); } } - string_cat_printf(out, "\n"); + furi_string_cat_printf(out, "\n"); } - string_cat_printf(out, " \n"); + furi_string_cat_printf(out, " \n"); } } } diff --git a/lib/nfc/protocols/mifare_desfire.h b/lib/nfc/protocols/mifare_desfire.h index e59743a2..963a18f5 100644 --- a/lib/nfc/protocols/mifare_desfire.h +++ b/lib/nfc/protocols/mifare_desfire.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -120,14 +119,14 @@ typedef struct { void mf_df_clear(MifareDesfireData* data); -void mf_df_cat_data(MifareDesfireData* data, string_t out); -void mf_df_cat_card_info(MifareDesfireData* data, string_t out); -void mf_df_cat_version(MifareDesfireVersion* version, string_t out); -void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, string_t out); -void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, string_t out); -void mf_df_cat_application_info(MifareDesfireApplication* app, string_t out); -void mf_df_cat_application(MifareDesfireApplication* app, string_t out); -void mf_df_cat_file(MifareDesfireFile* file, string_t out); +void mf_df_cat_data(MifareDesfireData* data, FuriString* out); +void mf_df_cat_card_info(MifareDesfireData* data, FuriString* out); +void mf_df_cat_version(MifareDesfireVersion* version, FuriString* out); +void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, FuriString* out); +void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, FuriString* out); +void mf_df_cat_application_info(MifareDesfireApplication* app, FuriString* out); +void mf_df_cat_application(MifareDesfireApplication* app, FuriString* out); +void mf_df_cat_file(MifareDesfireFile* file, FuriString* out); bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index b3d80deb..a8d1f554 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -4,7 +4,6 @@ #include "nfc_util.h" #include #include "furi_hal_nfc.h" -#include #define TAG "MfUltralight" @@ -194,7 +193,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint *pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0]; } - FURI_LOG_I(TAG, "Auth success. Password: %08X. PACK: %04X", key, *pack); + FURI_LOG_I(TAG, "Auth success. Password: %08lX. PACK: %04X", key, *pack); authenticated = true; } while(false); @@ -1005,7 +1004,7 @@ static bool mf_ul_check_lock(MfUltralightEmulator* emulator, int16_t write_page) return (dynamic_lock_bytes & (1 << shift)) == 0; } -static void mf_ul_make_ascii_mirror(MfUltralightEmulator* emulator, string_t str) { +static void mf_ul_make_ascii_mirror(MfUltralightEmulator* emulator, FuriString* str) { // Locals to improve readability uint8_t mirror_page = emulator->config->mirror_page; uint8_t mirror_byte = emulator->config->mirror.mirror_byte; @@ -1020,14 +1019,14 @@ static void mf_ul_make_ascii_mirror(MfUltralightEmulator* emulator, string_t str if(mirror_conf == MfUltralightMirrorUid) return; // NTAG21x has the peculiar behavior when UID+counter selected, if UID does not fit but // counter will fit, it will actually mirror the counter - string_cat_str(str, " "); + furi_string_cat(str, " "); } else { for(int i = 0; i < 3; ++i) { - string_cat_printf(str, "%02X", emulator->data.data[i]); + furi_string_cat_printf(str, "%02X", emulator->data.data[i]); } // Skip BCC0 for(int i = 4; i < 8; ++i) { - string_cat_printf(str, "%02X", emulator->data.data[i]); + furi_string_cat_printf(str, "%02X", emulator->data.data[i]); } uid_printed = true; } @@ -1049,9 +1048,9 @@ static void mf_ul_make_ascii_mirror(MfUltralightEmulator* emulator, string_t str if(mirror_page == last_user_page_index - 1 && mirror_byte > 2) return; if(mirror_conf == MfUltralightMirrorUidCounter) - string_cat_str(str, uid_printed ? "x" : " "); + furi_string_cat(str, uid_printed ? "x" : " "); - string_cat_printf(str, "%06X", emulator->data.counter[2]); + furi_string_cat_printf(str, "%06lX", emulator->data.counter[2]); } } } @@ -1267,14 +1266,14 @@ bool mf_ul_prepare_emulation_response( bool reset_idle = false; #ifdef FURI_DEBUG - string_t debug_buf; - string_init(debug_buf); + FuriString* debug_buf; + debug_buf = furi_string_alloc(); for(int i = 0; i < (buff_rx_len + 7) / 8; ++i) { - string_cat_printf(debug_buf, "%02x ", buff_rx[i]); + furi_string_cat_printf(debug_buf, "%02x ", buff_rx[i]); } - string_strim(debug_buf); - FURI_LOG_T(TAG, "Emu RX (%d): %s", buff_rx_len, string_get_cstr(debug_buf)); - string_reset(debug_buf); + furi_string_trim(debug_buf); + FURI_LOG_T(TAG, "Emu RX (%d): %s", buff_rx_len, furi_string_get_cstr(debug_buf)); + furi_string_reset(debug_buf); #endif // Check composite commands @@ -1328,7 +1327,7 @@ bool mf_ul_prepare_emulation_response( uint8_t src_page = start_page; uint8_t last_page_plus_one = start_page + 4; uint8_t pwd_page = emulator->page_num - 2; - string_t ascii_mirror; + FuriString* ascii_mirror = NULL; size_t ascii_mirror_len = 0; const char* ascii_mirror_cptr = NULL; uint8_t ascii_mirror_curr_page = 0; @@ -1353,10 +1352,10 @@ bool mf_ul_prepare_emulation_response( if(last_page_plus_one > ascii_mirror_curr_page && start_page + 3 >= ascii_mirror_curr_page && start_page <= ascii_mirror_curr_page + 6) { - string_init(ascii_mirror); + ascii_mirror = furi_string_alloc(); mf_ul_make_ascii_mirror(emulator, ascii_mirror); - ascii_mirror_len = string_length_u(ascii_mirror); - ascii_mirror_cptr = string_get_cstr(ascii_mirror); + ascii_mirror_len = furi_string_utf8_length(ascii_mirror); + ascii_mirror_cptr = furi_string_get_cstr(ascii_mirror); // Move pointer to where it should be to start copying if(ascii_mirror_len > 0 && ascii_mirror_curr_page < start_page && @@ -1414,8 +1413,8 @@ bool mf_ul_prepare_emulation_response( ++src_page; if(src_page >= last_page_plus_one) src_page = 0; } - if(ascii_mirror_cptr != NULL) { - string_clear(ascii_mirror); + if(ascii_mirror != NULL) { + furi_string_free(ascii_mirror); } *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; @@ -1512,12 +1511,13 @@ bool mf_ul_prepare_emulation_response( // Copy ASCII mirror // Less stringent check here, because expecting FAST_READ to // only be issued once rather than repeatedly - string_t ascii_mirror; - string_init(ascii_mirror); + FuriString* ascii_mirror; + ascii_mirror = furi_string_alloc(); mf_ul_make_ascii_mirror(emulator, ascii_mirror); - size_t ascii_mirror_len = string_length_u(ascii_mirror); + size_t ascii_mirror_len = + furi_string_utf8_length(ascii_mirror); const char* ascii_mirror_cptr = - string_get_cstr(ascii_mirror); + furi_string_get_cstr(ascii_mirror); int16_t mirror_start_offset = (emulator->config->mirror_page - start_page) * 4 + emulator->config->mirror.mirror_byte; @@ -1547,7 +1547,7 @@ bool mf_ul_prepare_emulation_response( ++ascii_mirror_cptr; } } - string_clear(ascii_mirror); + furi_string_free(ascii_mirror); } if(emulator->supported_features & MfUltralightSupportAuth) { @@ -1851,11 +1851,11 @@ bool mf_ul_prepare_emulation_response( } else if(*buff_tx_len > 0) { int count = (*buff_tx_len + 7) / 8; for(int i = 0; i < count; ++i) { - string_cat_printf(debug_buf, "%02x ", buff_tx[i]); + furi_string_cat_printf(debug_buf, "%02x ", buff_tx[i]); } - string_strim(debug_buf); - FURI_LOG_T(TAG, "Emu TX (%d): %s", *buff_tx_len, string_get_cstr(debug_buf)); - string_clear(debug_buf); + furi_string_trim(debug_buf); + FURI_LOG_T(TAG, "Emu TX (%d): %s", *buff_tx_len, furi_string_get_cstr(debug_buf)); + furi_string_free(debug_buf); } else { FURI_LOG_T(TAG, "Emu TX: HALT"); } diff --git a/lib/one_wire/ibutton/ibutton_worker_modes.c b/lib/one_wire/ibutton/ibutton_worker_modes.c index d585e27f..691aea9e 100644 --- a/lib/one_wire/ibutton/ibutton_worker_modes.c +++ b/lib/one_wire/ibutton/ibutton_worker_modes.c @@ -2,7 +2,6 @@ #include #include "ibutton_worker_i.h" #include "ibutton_key_command.h" -#include void ibutton_worker_mode_idle_start(iButtonWorker* worker); void ibutton_worker_mode_idle_tick(iButtonWorker* worker); @@ -65,7 +64,7 @@ void ibutton_worker_mode_idle_stop(iButtonWorker* worker) { typedef struct { uint32_t last_dwt_value; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; } iButtonReadContext; void ibutton_worker_comparator_callback(bool level, void* context) { @@ -75,7 +74,7 @@ void ibutton_worker_comparator_callback(bool level, void* context) { LevelDuration data = level_duration_make(level, current_dwt_value - read_context->last_dwt_value); - xStreamBufferSend(read_context->stream, &data, sizeof(LevelDuration), 0); + furi_stream_buffer_send(read_context->stream, &data, sizeof(LevelDuration), 0); read_context->last_dwt_value = current_dwt_value; } @@ -91,7 +90,7 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) { iButtonReadContext read_context = { .last_dwt_value = DWT->CYCCNT, - .stream = xStreamBufferCreate(sizeof(LevelDuration) * 512, 1), + .stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 512, 1), }; furi_hal_rfid_comp_set_callback(ibutton_worker_comparator_callback, &read_context); @@ -100,7 +99,8 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) { uint32_t tick_start = furi_get_tick(); while(true) { LevelDuration level; - size_t ret = xStreamBufferReceive(read_context.stream, &level, sizeof(LevelDuration), 100); + size_t ret = + furi_stream_buffer_receive(read_context.stream, &level, sizeof(LevelDuration), 100); if((furi_get_tick() - tick_start) > 100) { break; @@ -141,7 +141,7 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) { furi_hal_rfid_comp_set_callback(NULL, NULL); furi_hal_rfid_pins_reset(); - vStreamBufferDelete(read_context.stream); + furi_stream_buffer_free(read_context.stream); return result; } diff --git a/lib/print/printf_tiny.h b/lib/print/printf_tiny.h index 8f292819..58f6a673 100644 --- a/lib/print/printf_tiny.h +++ b/lib/print/printf_tiny.h @@ -34,6 +34,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ void _putchar(char character); * \param format A string that specifies the format of the output * \return The number of characters that are written into the array, not counting the terminating null character */ -int printf_(const char* format, ...); +int printf_(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2))); /** * Tiny sprintf implementation @@ -63,7 +64,7 @@ int printf_(const char* format, ...); * \param format A string that specifies the format of the output * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character */ -int sprintf_(char* buffer, const char* format, ...); +int sprintf_(char* buffer, const char* format, ...) _ATTRIBUTE((__format__(__printf__, 2, 3))); /** * Tiny snprintf/vsnprintf implementation @@ -75,7 +76,8 @@ int sprintf_(char* buffer, const char* format, ...); * null character. A value equal or larger than count indicates truncation. Only when the returned value * is non-negative and less than count, the string has been completely written. */ -int snprintf_(char* buffer, size_t count, const char* format, ...); +int snprintf_(char* buffer, size_t count, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 3, 4))); int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); /** @@ -94,7 +96,8 @@ int vprintf_(const char* format, va_list va); * \param format A string that specifies the format of the output * \return The number of characters that are sent to the output function, not counting the terminating null character */ -int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 3, 4))); #ifdef __cplusplus } diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 353ff18b..7496aea3 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -4,7 +4,7 @@ #define TAG "SubGhzBlockGeneric" -void subghz_block_generic_get_preset_name(const char* preset_name, string_t preset_str) { +void subghz_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str) { const char* preset_name_temp; if(!strcmp(preset_name, "AM270")) { preset_name_temp = "FuriHalSubGhzPresetOok270Async"; @@ -17,7 +17,7 @@ void subghz_block_generic_get_preset_name(const char* preset_name, string_t pres } else { preset_name_temp = "FuriHalSubGhzPresetCustom"; } - string_set(preset_str, preset_name_temp); + furi_string_set(preset_str, preset_name_temp); } bool subghz_block_generic_serialize( @@ -26,8 +26,8 @@ bool subghz_block_generic_serialize( SubGhzPresetDefinition* preset) { furi_assert(instance); bool res = false; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { stream_clean(flipper_format_get_raw_stream(flipper_format)); if(!flipper_format_write_header_cstr( @@ -41,12 +41,13 @@ bool subghz_block_generic_serialize( break; } - subghz_block_generic_get_preset_name(string_get_cstr(preset->name), temp_str); - if(!flipper_format_write_string_cstr(flipper_format, "Preset", string_get_cstr(temp_str))) { + subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); + if(!flipper_format_write_string_cstr( + flipper_format, "Preset", furi_string_get_cstr(temp_str))) { FURI_LOG_E(TAG, "Unable to add Preset"); break; } - if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { if(!flipper_format_write_string_cstr( flipper_format, "Custom_preset_module", "CC1101")) { FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); @@ -79,15 +80,15 @@ bool subghz_block_generic_serialize( } res = true; } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return res; } bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format) { furi_assert(instance); bool res = false; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); uint32_t temp_data = 0; do { @@ -113,7 +114,7 @@ bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperForma res = true; } while(0); - string_clear(temp_str); + furi_string_free(temp_str); return res; } diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index 56a7fc2d..300807da 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -25,7 +25,7 @@ struct SubGhzBlockGeneric { * @param preset_name name preset * @param preset_str Output name preset */ -void subghz_block_generic_get_preset_name(const char* preset_name, string_t preset_str); +void subghz_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str); /** * Serialize data SubGhzBlockGeneric. diff --git a/lib/subghz/protocols/base.c b/lib/subghz/protocols/base.c index 06542f5e..4ee7a3f8 100644 --- a/lib/subghz/protocols/base.c +++ b/lib/subghz/protocols/base.c @@ -11,7 +11,7 @@ void subghz_protocol_decoder_base_set_decoder_callback( bool subghz_protocol_decoder_base_get_string( SubGhzProtocolDecoderBase* decoder_base, - string_t output) { + FuriString* output) { bool status = false; if(decoder_base->protocol && decoder_base->protocol->decoder && diff --git a/lib/subghz/protocols/base.h b/lib/subghz/protocols/base.h index fdd13567..47b4e482 100644 --- a/lib/subghz/protocols/base.h +++ b/lib/subghz/protocols/base.h @@ -11,8 +11,9 @@ typedef struct SubGhzProtocolDecoderBase SubGhzProtocolDecoderBase; typedef void ( *SubGhzProtocolDecoderBaseRxCallback)(SubGhzProtocolDecoderBase* instance, void* context); -typedef void ( - *SubGhzProtocolDecoderBaseSerialize)(SubGhzProtocolDecoderBase* decoder_base, string_t output); +typedef void (*SubGhzProtocolDecoderBaseSerialize)( + SubGhzProtocolDecoderBase* decoder_base, + FuriString* output); struct SubGhzProtocolDecoderBase { // Decoder general section @@ -41,7 +42,7 @@ void subghz_protocol_decoder_base_set_decoder_callback( */ bool subghz_protocol_decoder_base_get_string( SubGhzProtocolDecoderBase* decoder_base, - string_t output); + FuriString* output); /** * Serialize data SubGhzProtocolDecoderBase. diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index c8070257..605a922c 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -323,11 +323,11 @@ bool subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flip return ret; } -void subghz_protocol_decoder_bett_get_string(void* context, string_t output) { +void subghz_protocol_decoder_bett_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderBETT* instance = context; uint32_t data = (uint32_t)(instance->generic.data & 0x3FFFF); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%05lX\r\n" diff --git a/lib/subghz/protocols/bett.h b/lib/subghz/protocols/bett.h index 48f32b3e..04bf46b5 100644 --- a/lib/subghz/protocols/bett.h +++ b/lib/subghz/protocols/bett.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flip * @param context Pointer to a SubGhzProtocolDecoderBETT instance * @param output Resulting text */ -void subghz_protocol_decoder_bett_get_string(void* context, string_t output); +void subghz_protocol_decoder_bett_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 53d3d078..7c037bd1 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -322,7 +322,7 @@ bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flip return ret; } -void subghz_protocol_decoder_came_get_string(void* context, string_t output) { +void subghz_protocol_decoder_came_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderCame* instance = context; @@ -333,7 +333,7 @@ void subghz_protocol_decoder_came_get_string(void* context, string_t output) { uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%08lX\r\n" diff --git a/lib/subghz/protocols/came.h b/lib/subghz/protocols/came.h index c2648c05..d1ac7628 100644 --- a/lib/subghz/protocols/came.h +++ b/lib/subghz/protocols/came.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flip * @param context Pointer to a SubGhzProtocolDecoderCame instance * @param output Resulting text */ -void subghz_protocol_decoder_came_get_string(void* context, string_t output); +void subghz_protocol_decoder_came_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 0c3cdd8a..8c2a542c 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -325,7 +325,7 @@ bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat return ret; } -void subghz_protocol_decoder_came_atomo_get_string(void* context, string_t output) { +void subghz_protocol_decoder_came_atomo_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderCameAtomo* instance = context; subghz_protocol_came_atomo_remote_controller( @@ -333,12 +333,12 @@ void subghz_protocol_decoder_came_atomo_get_string(void* context, string_t outpu uint32_t code_found_hi = instance->generic.data >> 32; uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%08lX Btn:0x%01X\r\n" - "Cnt:0x%03X\r\n", + "Cnt:0x%03lX\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/came_atomo.h b/lib/subghz/protocols/came_atomo.h index 70a79eca..aa1cffd0 100644 --- a/lib/subghz/protocols/came_atomo.h +++ b/lib/subghz/protocols/came_atomo.h @@ -69,4 +69,4 @@ bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderCameAtomo instance * @param output Resulting text */ -void subghz_protocol_decoder_came_atomo_get_string(void* context, string_t output); +void subghz_protocol_decoder_came_atomo_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index b5b409c5..3d5029ec 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -446,18 +446,18 @@ bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output) { +void subghz_protocol_decoder_came_twee_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderCameTwee* instance = context; subghz_protocol_came_twee_remote_controller(&instance->generic); uint32_t code_found_hi = instance->generic.data >> 32; uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" - "Btn:%lX\r\n" + "Btn:%X\r\n" "DIP:" DIP_PATTERN "\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/came_twee.h b/lib/subghz/protocols/came_twee.h index 42e6ddaf..aa1f0e0d 100644 --- a/lib/subghz/protocols/came_twee.h +++ b/lib/subghz/protocols/came_twee.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderCameTwee instance * @param output Resulting text */ -void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output); +void subghz_protocol_decoder_came_twee_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 66d230d1..d2d19af2 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -451,7 +451,7 @@ bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat return ret; } -void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t output) { +void subghz_protocol_decoder_chamb_code_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderChamb_Code* instance = context; @@ -462,7 +462,7 @@ void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t outpu uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%03lX\r\n" @@ -474,19 +474,19 @@ void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t outpu switch(instance->generic.data_count_bit) { case 7: - string_cat_printf( + furi_string_cat_printf( output, "DIP:" CHAMBERLAIN_7_CODE_DIP_PATTERN "\r\n", CHAMBERLAIN_7_CODE_DATA_TO_DIP(code_found_lo)); break; case 8: - string_cat_printf( + furi_string_cat_printf( output, "DIP:" CHAMBERLAIN_8_CODE_DIP_PATTERN "\r\n", CHAMBERLAIN_8_CODE_DATA_TO_DIP(code_found_lo)); break; case 9: - string_cat_printf( + furi_string_cat_printf( output, "DIP:" CHAMBERLAIN_9_CODE_DIP_PATTERN "\r\n", CHAMBERLAIN_9_CODE_DATA_TO_DIP(code_found_lo)); diff --git a/lib/subghz/protocols/chamberlain_code.h b/lib/subghz/protocols/chamberlain_code.h index 1ac2f9f9..923a3151 100644 --- a/lib/subghz/protocols/chamberlain_code.h +++ b/lib/subghz/protocols/chamberlain_code.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance * @param output Resulting text */ -void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t output); +void subghz_protocol_decoder_chamb_code_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/clemsa.c b/lib/subghz/protocols/clemsa.c index 33734693..dbee0ac9 100644 --- a/lib/subghz/protocols/clemsa.c +++ b/lib/subghz/protocols/clemsa.c @@ -343,12 +343,12 @@ bool subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* fl return ret; } -void subghz_protocol_decoder_clemsa_get_string(void* context, string_t output) { +void subghz_protocol_decoder_clemsa_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderClemsa* instance = context; subghz_protocol_clemsa_check_remote_controller(&instance->generic); //uint32_t data = (uint32_t)(instance->generic.data & 0xFFFFFF); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%05lX Btn %X\r\n" diff --git a/lib/subghz/protocols/clemsa.h b/lib/subghz/protocols/clemsa.h index a8398312..8287af23 100644 --- a/lib/subghz/protocols/clemsa.h +++ b/lib/subghz/protocols/clemsa.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* fl * @param context Pointer to a SubGhzProtocolDecoderClemsa instance * @param output Resulting text */ -void subghz_protocol_decoder_clemsa_get_string(void* context, string_t output); +void subghz_protocol_decoder_clemsa_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index 9122c193..5c340214 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -337,15 +337,15 @@ bool subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_doitrand_get_string(void* context, string_t output) { +void subghz_protocol_decoder_doitrand_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderDoitrand* instance = context; subghz_protocol_doitrand_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%02lX%08lX\r\n" - "Btn:%lX\r\n" + "Btn:%X\r\n" "DIP:" DIP_PATTERN "\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/doitrand.h b/lib/subghz/protocols/doitrand.h index f94d7389..c96946a1 100644 --- a/lib/subghz/protocols/doitrand.h +++ b/lib/subghz/protocols/doitrand.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderDoitrand instance * @param output Resulting text */ -void subghz_protocol_decoder_doitrand_get_string(void* context, string_t output); +void subghz_protocol_decoder_doitrand_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 8b90f471..b5443590 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -207,7 +207,7 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_faac_slh_get_string(void* context, string_t output) { +void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; subghz_protocol_faac_slh_check_remote_controller(&instance->generic); @@ -216,13 +216,13 @@ void subghz_protocol_decoder_faac_slh_get_string(void* context, string_t output) uint32_t code_fix = code_found_reverse & 0xFFFFFFFF; uint32_t code_hop = (code_found_reverse >> 32) & 0xFFFFFFFF; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%lX%08lX\r\n" "Fix:%08lX \r\n" "Hop:%08lX \r\n" - "Sn:%07lX Btn:%lX\r\n", + "Sn:%07lX Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data >> 32), diff --git a/lib/subghz/protocols/faac_slh.h b/lib/subghz/protocols/faac_slh.h index fe7a7926..9b18f5ea 100644 --- a/lib/subghz/protocols/faac_slh.h +++ b/lib/subghz/protocols/faac_slh.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderFaacSLH instance * @param output Resulting text */ -void subghz_protocol_decoder_faac_slh_get_string(void* context, string_t output); +void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index 56c224ae..5cf3a871 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -317,15 +317,15 @@ bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* f return ret; } -void subghz_protocol_decoder_gate_tx_get_string(void* context, string_t output) { +void subghz_protocol_decoder_gate_tx_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderGateTx* instance = context; subghz_protocol_gate_tx_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%06lX\r\n" - "Sn:%05lX Btn:%lX\r\n", + "Sn:%05lX Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data & 0xFFFFFF), diff --git a/lib/subghz/protocols/gate_tx.h b/lib/subghz/protocols/gate_tx.h index 17157681..36eeb9a9 100644 --- a/lib/subghz/protocols/gate_tx.h +++ b/lib/subghz/protocols/gate_tx.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* f * @param context Pointer to a SubGhzProtocolDecoderGateTx instance * @param output Resulting text */ -void subghz_protocol_decoder_gate_tx_get_string(void* context, string_t output); +void subghz_protocol_decoder_gate_tx_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 5cd16063..230f4cfe 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -350,12 +350,12 @@ bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* fl return ret; } -void subghz_protocol_decoder_holtek_get_string(void* context, string_t output) { +void subghz_protocol_decoder_holtek_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderHoltek* instance = context; subghz_protocol_holtek_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" @@ -368,8 +368,8 @@ void subghz_protocol_decoder_holtek_get_string(void* context, string_t output) { instance->generic.btn >> 4); if((instance->generic.btn & 0xF) == 0xE) { - string_cat_printf(output, "ON\r\n"); + furi_string_cat_printf(output, "ON\r\n"); } else if(((instance->generic.btn & 0xF) == 0xB)) { - string_cat_printf(output, "OFF\r\n"); + furi_string_cat_printf(output, "OFF\r\n"); } } diff --git a/lib/subghz/protocols/holtek.h b/lib/subghz/protocols/holtek.h index df7dd644..1dac783b 100644 --- a/lib/subghz/protocols/holtek.h +++ b/lib/subghz/protocols/holtek.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* fl * @param context Pointer to a SubGhzProtocolDecoderHoltek instance * @param output Resulting text */ -void subghz_protocol_decoder_holtek_get_string(void* context, string_t output); +void subghz_protocol_decoder_holtek_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index 451a13f5..3cd62698 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -374,18 +374,18 @@ bool subghz_protocol_decoder_honeywell_wdb_deserialize( return ret; } -void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, string_t output) { +void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderHoneywell_WDB* instance = context; subghz_protocol_honeywell_wdb_check_remote_controller(instance); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%05lX\r\n" "DT:%s Al:%s\r\n" - "SK:%01lX R:%01lX LBat:%01lX\r\n", + "SK:%01X R:%01X LBat:%01X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)((instance->generic.data >> 32) & 0xFFFFFFFF), diff --git a/lib/subghz/protocols/honeywell_wdb.h b/lib/subghz/protocols/honeywell_wdb.h index 012b3699..c61aa822 100644 --- a/lib/subghz/protocols/honeywell_wdb.h +++ b/lib/subghz/protocols/honeywell_wdb.h @@ -108,4 +108,4 @@ bool subghz_protocol_decoder_honeywell_wdb_deserialize( * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance * @param output Resulting text */ -void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, string_t output); +void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index d78bc927..d8438604 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -338,12 +338,12 @@ bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* f return ret; } -void subghz_protocol_decoder_hormann_get_string(void* context, string_t output) { +void subghz_protocol_decoder_hormann_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderHormann* instance = context; subghz_protocol_hormann_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s\r\n" "%dbit\r\n" diff --git a/lib/subghz/protocols/hormann.h b/lib/subghz/protocols/hormann.h index 45d6eb22..743ad0b3 100644 --- a/lib/subghz/protocols/hormann.h +++ b/lib/subghz/protocols/hormann.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* f * @param context Pointer to a SubGhzProtocolDecoderHormann instance * @param output Resulting text */ -void subghz_protocol_decoder_hormann_get_string(void* context, string_t output); +void subghz_protocol_decoder_hormann_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index 91446844..6cc60bde 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -205,7 +205,7 @@ bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipp return ret; } -void subghz_protocol_decoder_ido_get_string(void* context, string_t output) { +void subghz_protocol_decoder_ido_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderIDo* instance = context; @@ -215,13 +215,13 @@ void subghz_protocol_decoder_ido_get_string(void* context, string_t output) { uint32_t code_fix = code_found_reverse & 0xFFFFFF; uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFFF; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" "Fix:%06lX \r\n" "Hop:%06lX \r\n" - "Sn:%05lX Btn:%lX\r\n", + "Sn:%05lX Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data >> 32), diff --git a/lib/subghz/protocols/ido.h b/lib/subghz/protocols/ido.h index 4fe4e740..67d2b4d8 100644 --- a/lib/subghz/protocols/ido.h +++ b/lib/subghz/protocols/ido.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipp * @param context Pointer to a SubGhzProtocolDecoderIDo instance * @param output Resulting text */ -void subghz_protocol_decoder_ido_get_string(void* context, string_t output); +void subghz_protocol_decoder_ido_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/intertechno_v3.c b/lib/subghz/protocols/intertechno_v3.c index ffe52e87..14e137ca 100644 --- a/lib/subghz/protocols/intertechno_v3.c +++ b/lib/subghz/protocols/intertechno_v3.c @@ -434,13 +434,13 @@ bool subghz_protocol_decoder_intertechno_v3_deserialize( return ret; } -void subghz_protocol_decoder_intertechno_v3_get_string(void* context, string_t output) { +void subghz_protocol_decoder_intertechno_v3_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderIntertechno_V3* instance = context; subghz_protocol_intertechno_v3_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%.11s %db\r\n" "Key:0x%08llX\r\n" @@ -453,17 +453,17 @@ void subghz_protocol_decoder_intertechno_v3_get_string(void* context, string_t o if(instance->generic.data_count_bit == subghz_protocol_intertechno_v3_const.min_count_bit_for_found) { if(instance->generic.cnt >> 5) { - string_cat_printf( + furi_string_cat_printf( output, "Ch: All Btn:%s\r\n", (instance->generic.btn ? "On" : "Off")); } else { - string_cat_printf( + furi_string_cat_printf( output, "Ch:" CH_PATTERN " Btn:%s\r\n", CNT_TO_CH(instance->generic.cnt), (instance->generic.btn ? "On" : "Off")); } } else if(instance->generic.data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) { - string_cat_printf( + furi_string_cat_printf( output, "Ch:" CH_PATTERN " Dimm:%d%%\r\n", CNT_TO_CH(instance->generic.cnt), diff --git a/lib/subghz/protocols/intertechno_v3.h b/lib/subghz/protocols/intertechno_v3.h index 65d6f61d..078d0397 100644 --- a/lib/subghz/protocols/intertechno_v3.h +++ b/lib/subghz/protocols/intertechno_v3.h @@ -108,4 +108,4 @@ bool subghz_protocol_decoder_intertechno_v3_deserialize( * @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance * @param output Resulting text */ -void subghz_protocol_decoder_intertechno_v3_get_string(void* context, string_t output); +void subghz_protocol_decoder_intertechno_v3_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index cfb92fe8..039d97a6 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -2,7 +2,6 @@ #include "keeloq_common.h" #include "../subghz_keystore.h" -#include #include #include "../blocks/const.h" @@ -131,7 +130,7 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc for M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) { - res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name); + res = strcmp(furi_string_get_cstr(manufacture_code->name), instance->manufacture_name); if(res == 0) { switch(manufacture_code->type) { case KEELOQ_LEARNING_SIMPLE: @@ -489,7 +488,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( // Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -499,7 +498,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -508,7 +507,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( fix, seed, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -517,7 +516,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -526,7 +525,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -534,7 +533,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( // Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -548,7 +547,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -558,7 +557,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -566,7 +565,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -575,7 +574,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( fix, seed, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -583,7 +582,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man = subghz_protocol_keeloq_common_secure_learning(fix, seed, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -592,7 +591,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } @@ -600,7 +599,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man = subghz_protocol_keeloq_common_magic_xor_type1_learning(fix, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -683,7 +682,7 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl return res; } -void subghz_protocol_decoder_keeloq_get_string(void* context, string_t output) { +void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; subghz_protocol_keeloq_check_remote_controller( @@ -697,12 +696,12 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, string_t output) { uint32_t code_found_reverse_hi = code_found_reverse >> 32; uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%08lX%08lX\r\n" - "Fix:0x%08lX Cnt:%04X\r\n" - "Hop:0x%08lX Btn:%01lX\r\n" + "Fix:0x%08lX Cnt:%04lX\r\n" + "Hop:0x%08lX Btn:%01X\r\n" "MF:%s\r\n" "Sn:0x%07lX \r\n", instance->generic.protocol_name, diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index e1485e5e..c0575bd9 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -124,4 +124,4 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl * @param context Pointer to a SubGhzProtocolDecoderKeeloq instance * @param output Resulting text */ -void subghz_protocol_decoder_keeloq_get_string(void* context, string_t output); +void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/keeloq_common.c b/lib/subghz/protocols/keeloq_common.c index 4c0c1d4e..6c9bc461 100644 --- a/lib/subghz/protocols/keeloq_common.c +++ b/lib/subghz/protocols/keeloq_common.c @@ -2,7 +2,6 @@ #include -#include #include #define bit(x, n) (((x) >> (n)) & 1) diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index 6fc10617..d4683866 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -256,7 +256,7 @@ bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipp return ret; } -void subghz_protocol_decoder_kia_get_string(void* context, string_t output) { +void subghz_protocol_decoder_kia_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderKIA* instance = context; @@ -264,11 +264,11 @@ void subghz_protocol_decoder_kia_get_string(void* context, string_t output) { uint32_t code_found_hi = instance->generic.data >> 32; uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%08lX%08lX\r\n" - "Sn:%07lX Btn:%lX Cnt:%04X\r\n", + "Sn:%07lX Btn:%X Cnt:%04lX\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, code_found_hi, diff --git a/lib/subghz/protocols/kia.h b/lib/subghz/protocols/kia.h index 743ab7cb..cf186921 100644 --- a/lib/subghz/protocols/kia.h +++ b/lib/subghz/protocols/kia.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipp * @param context Pointer to a SubGhzProtocolDecoderKIA instance * @param output Resulting text */ -void subghz_protocol_decoder_kia_get_string(void* context, string_t output); +void subghz_protocol_decoder_kia_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index 8f7aed79..582c4aaf 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -327,7 +327,7 @@ bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* fl return ret; } -void subghz_protocol_decoder_linear_get_string(void* context, string_t output) { +void subghz_protocol_decoder_linear_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderLinear* instance = context; @@ -338,7 +338,7 @@ void subghz_protocol_decoder_linear_get_string(void* context, string_t output) { uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%08lX\r\n" diff --git a/lib/subghz/protocols/linear.h b/lib/subghz/protocols/linear.h index 035b130c..6111ad85 100644 --- a/lib/subghz/protocols/linear.h +++ b/lib/subghz/protocols/linear.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* fl * @param context Pointer to a SubGhzProtocolDecoderLinear instance * @param output Resulting text */ -void subghz_protocol_decoder_linear_get_string(void* context, string_t output); +void subghz_protocol_decoder_linear_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/magellen.c b/lib/subghz/protocols/magellen.c index 6dcc83e5..160ec4a2 100644 --- a/lib/subghz/protocols/magellen.c +++ b/lib/subghz/protocols/magellen.c @@ -375,8 +375,8 @@ static void subghz_protocol_magellen_check_remote_controller(SubGhzBlockGeneric* instance->btn = (data_rev >> 16) & 0xFF; } -static void subghz_protocol_magellen_get_event_serialize(uint8_t event, string_t output) { - string_cat_printf( +static void subghz_protocol_magellen_get_event_serialize(uint8_t event, FuriString* output) { + furi_string_cat_printf( output, "%s%s%s%s%s%s%s%s", ((event >> 4) & 0x1 ? (event & 0x1 ? " Open" : " Close") : @@ -424,15 +424,15 @@ bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_magellen_get_string(void* context, string_t output) { +void subghz_protocol_decoder_magellen_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderMagellen* instance = context; subghz_protocol_magellen_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%08lX\r\n" - "Sn:%03d%03d, Event:0x%02X\r\n" + "Sn:%03ld%03ld, Event:0x%02X\r\n" "Stat:", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/magellen.h b/lib/subghz/protocols/magellen.h index 224f7901..226919c8 100644 --- a/lib/subghz/protocols/magellen.h +++ b/lib/subghz/protocols/magellen.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderMagellen instance * @param output Resulting text */ -void subghz_protocol_decoder_magellen_get_string(void* context, string_t output); +void subghz_protocol_decoder_magellen_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/marantec.c b/lib/subghz/protocols/marantec.c index bdce6593..a72238a4 100644 --- a/lib/subghz/protocols/marantec.c +++ b/lib/subghz/protocols/marantec.c @@ -373,17 +373,17 @@ bool subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_marantec_get_string(void* context, string_t output) { +void subghz_protocol_decoder_marantec_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderMarantec* instance = context; subghz_protocol_marantec_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%07lX \r\n" - "Btn:%lX\r\n", + "Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data >> 32), diff --git a/lib/subghz/protocols/marantec.h b/lib/subghz/protocols/marantec.h index 2da3c88a..5fc042e7 100644 --- a/lib/subghz/protocols/marantec.h +++ b/lib/subghz/protocols/marantec.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderMarantec instance * @param output Resulting text */ -void subghz_protocol_decoder_marantec_get_string(void* context, string_t output); +void subghz_protocol_decoder_marantec_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 1501580d..baa8188d 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -408,17 +408,17 @@ bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_megacode_get_string(void* context, string_t output) { +void subghz_protocol_decoder_megacode_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderMegaCode* instance = context; subghz_protocol_megacode_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%06lX\r\n" - "Sn:0x%04lX - %d\r\n" - "Facility:%X Btn:%X\r\n", + "Sn:0x%04lX - %ld\r\n" + "Facility:%lX Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)instance->generic.data, diff --git a/lib/subghz/protocols/megacode.h b/lib/subghz/protocols/megacode.h index c8010665..0fafddb6 100644 --- a/lib/subghz/protocols/megacode.h +++ b/lib/subghz/protocols/megacode.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance * @param output Resulting text */ -void subghz_protocol_decoder_megacode_get_string(void* context, string_t output); +void subghz_protocol_decoder_megacode_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index b5a7e8c0..d6925d48 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -370,7 +370,7 @@ bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat return ret; } -void subghz_protocol_decoder_nero_radio_get_string(void* context, string_t output) { +void subghz_protocol_decoder_nero_radio_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderNeroRadio* instance = context; @@ -383,7 +383,7 @@ void subghz_protocol_decoder_nero_radio_get_string(void* context, string_t outpu uint32_t code_found_reverse_hi = code_found_reverse >> 32; uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" diff --git a/lib/subghz/protocols/nero_radio.h b/lib/subghz/protocols/nero_radio.h index f04dc2b3..ef270342 100644 --- a/lib/subghz/protocols/nero_radio.h +++ b/lib/subghz/protocols/nero_radio.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderNeroRadio instance * @param output Resulting text */ -void subghz_protocol_decoder_nero_radio_get_string(void* context, string_t output); +void subghz_protocol_decoder_nero_radio_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 66ee569c..8080bf9e 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -355,7 +355,7 @@ bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperForma return ret; } -void subghz_protocol_decoder_nero_sketch_get_string(void* context, string_t output) { +void subghz_protocol_decoder_nero_sketch_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderNeroSketch* instance = context; @@ -368,7 +368,7 @@ void subghz_protocol_decoder_nero_sketch_get_string(void* context, string_t outp uint32_t code_found_reverse_hi = code_found_reverse >> 32; uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" diff --git a/lib/subghz/protocols/nero_sketch.h b/lib/subghz/protocols/nero_sketch.h index ab592b48..4536e704 100644 --- a/lib/subghz/protocols/nero_sketch.h +++ b/lib/subghz/protocols/nero_sketch.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperForma * @param context Pointer to a SubGhzProtocolDecoderNeroSketch instance * @param output Resulting text */ -void subghz_protocol_decoder_nero_sketch_get_string(void* context, string_t output); +void subghz_protocol_decoder_nero_sketch_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index f07e9efc..06538db1 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -309,7 +309,7 @@ bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* return ret; } -void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output) { +void subghz_protocol_decoder_nice_flo_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderNiceFlo* instance = context; @@ -318,7 +318,7 @@ void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output) instance->generic.data, instance->generic.data_count_bit); uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%08lX\r\n" diff --git a/lib/subghz/protocols/nice_flo.h b/lib/subghz/protocols/nice_flo.h index 0873e81b..dd374006 100644 --- a/lib/subghz/protocols/nice_flo.h +++ b/lib/subghz/protocols/nice_flo.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance * @param output Resulting text */ -void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output); +void subghz_protocol_decoder_nice_flo_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 1d370e85..d567ddf2 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -354,7 +354,7 @@ bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperForma return ret; } -void subghz_protocol_decoder_nice_flor_s_get_string(void* context, string_t output) { +void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; @@ -363,12 +363,12 @@ void subghz_protocol_decoder_nice_flor_s_get_string(void* context, string_t outp uint32_t code_found_hi = instance->generic.data >> 32; uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:%05lX\r\n" - "Cnt:%04X Btn:%02lX\r\n", + "Cnt:%04lX Btn:%02X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, code_found_hi, diff --git a/lib/subghz/protocols/nice_flor_s.h b/lib/subghz/protocols/nice_flor_s.h index 7d98876f..286d03d4 100644 --- a/lib/subghz/protocols/nice_flor_s.h +++ b/lib/subghz/protocols/nice_flor_s.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperForma * @param context Pointer to a SubGhzProtocolDecoderNiceFlorS instance * @param output Resulting text */ -void subghz_protocol_decoder_nice_flor_s_get_string(void* context, string_t output); +void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/oregon2.c b/lib/subghz/protocols/oregon2.c index 84bb38be..561df819 100644 --- a/lib/subghz/protocols/oregon2.c +++ b/lib/subghz/protocols/oregon2.c @@ -5,7 +5,6 @@ #include "../blocks/math.h" #include #include -#include #define TAG "SubGhzProtocolOregon2" @@ -247,21 +246,21 @@ bool subghz_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* f // append string of the variable data static void - oregon2_var_data_append_string(uint16_t sensor_id, uint32_t var_data, string_t output) { + oregon2_var_data_append_string(uint16_t sensor_id, uint32_t var_data, FuriString* output) { uint32_t val; if(sensor_id == 0xEC40) { val = ((var_data >> 4) & 0xF) * 10 + ((var_data >> 8) & 0xF); - string_cat_printf( + furi_string_cat_printf( output, - "Temp: %s%d.%d C\r\n", + "Temp: %s%ld.%ld C\r\n", (var_data & 0xF) ? "-" : "+", val, (uint32_t)(var_data >> 12) & 0xF); } } -static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, string_t output) { +static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, FuriString* output) { uint8_t sum = fix_data & 0xF; uint8_t ref_sum = var_data & 0xFF; var_data >>= 8; @@ -275,19 +274,19 @@ static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, strin // swap calculated sum nibbles sum = (((sum >> 4) & 0xF) | (sum << 4)) & 0xFF; if(sum == ref_sum) - string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum); + furi_string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum); else - string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum); + furi_string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum); } -void subghz_protocol_decoder_oregon2_get_string(void* context, string_t output) { +void subghz_protocol_decoder_oregon2_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderOregon2* instance = context; uint16_t sensor_id = OREGON2_SENSOR_ID(instance->generic.data); - string_cat_printf( + furi_string_cat_printf( output, "%s\r\n" - "ID: 0x%04lX, ch: %d%s, rc: 0x%02lX\r\n", + "ID: 0x%04lX, ch: %ld%s, rc: 0x%02lX\r\n", instance->generic.protocol_name, (uint32_t)sensor_id, (uint32_t)(instance->generic.data >> 12) & 0xF, diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index d680b2e6..019c3ec2 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -320,16 +320,16 @@ bool subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat return ret; } -void subghz_protocol_decoder_phoenix_v2_get_string(void* context, string_t output) { +void subghz_protocol_decoder_phoenix_v2_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderPhoenix_V2* instance = context; subghz_protocol_phoenix_v2_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%02lX%08lX\r\n" "Sn:0x%07lX \r\n" - "Btn:%lX\r\n", + "Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data >> 32) & 0xFFFFFFFF, diff --git a/lib/subghz/protocols/phoenix_v2.h b/lib/subghz/protocols/phoenix_v2.h index 38cadc1a..b2f18279 100644 --- a/lib/subghz/protocols/phoenix_v2.h +++ b/lib/subghz/protocols/phoenix_v2.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderPhoenix_V2 instance * @param output Resulting text */ -void subghz_protocol_decoder_phoenix_v2_get_string(void* context, string_t output); +void subghz_protocol_decoder_phoenix_v2_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index bd009d88..3ec35c74 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -373,12 +373,12 @@ bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperForma return ret; } -void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output) { +void subghz_protocol_decoder_power_smart_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderPowerSmart* instance = context; subghz_protocol_power_smart_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" diff --git a/lib/subghz/protocols/power_smart.h b/lib/subghz/protocols/power_smart.h index f6e9571b..21e5dcf4 100644 --- a/lib/subghz/protocols/power_smart.h +++ b/lib/subghz/protocols/power_smart.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperForma * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance * @param output Resulting text */ -void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output); +void subghz_protocol_decoder_power_smart_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index a5b8134d..370f33fb 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -351,20 +351,20 @@ bool subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* return res; } -void subghz_protocol_decoder_princeton_get_string(void* context, string_t output) { +void subghz_protocol_decoder_princeton_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; subghz_protocol_princeton_check_remote_controller(&instance->generic); uint32_t data_rev = subghz_protocol_blocks_reverse_key( instance->generic.data, instance->generic.data_count_bit); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%08lX\r\n" "Yek:0x%08lX\r\n" "Sn:0x%05lX Btn:%01X\r\n" - "Te:%dus\r\n", + "Te:%ldus\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data & 0xFFFFFF), diff --git a/lib/subghz/protocols/princeton.h b/lib/subghz/protocols/princeton.h index 9c296c4a..4e482f74 100644 --- a/lib/subghz/protocols/princeton.h +++ b/lib/subghz/protocols/princeton.h @@ -104,4 +104,4 @@ bool subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderPrinceton instance * @param output Resulting text */ -void subghz_protocol_decoder_princeton_get_string(void* context, string_t output); +void subghz_protocol_decoder_princeton_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/princeton_for_testing.c b/lib/subghz/protocols/princeton_for_testing.c index 43078d2e..0987e0ad 100644 --- a/lib/subghz/protocols/princeton_for_testing.c +++ b/lib/subghz/protocols/princeton_for_testing.c @@ -94,7 +94,7 @@ void subghz_encoder_princeton_for_testing_print_log(void* context) { ((float)instance->time_high / (instance->time_high + instance->time_low)) * 100; FURI_LOG_I( TAG "Encoder", - "Radio tx_time=%dus ON=%dus, OFF=%dus, DutyCycle=%d,%d%%", + "Radio tx_time=%ldus ON=%ldus, OFF=%ldus, DutyCycle=%ld,%ld%%", instance->time_high + instance->time_low, instance->time_high, instance->time_low, diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 0419a39a..fd234502 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -29,7 +29,7 @@ struct SubGhzProtocolDecoderRAW { Storage* storage; FlipperFormat* flipper_file; uint32_t file_is_open; - string_t file_name; + FuriString* file_name; size_t sample_write; bool last_level; }; @@ -38,7 +38,7 @@ struct SubGhzProtocolEncoderRAW { SubGhzProtocolEncoderBase base; bool is_running; - string_t file_name; + FuriString* file_name; SubGhzFileEncoderWorker* file_worker_encoder; }; @@ -90,8 +90,8 @@ bool subghz_protocol_raw_save_to_file_init( instance->storage = furi_record_open(RECORD_STORAGE); instance->flipper_file = flipper_format_file_alloc(instance->storage); - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); bool init = false; do { @@ -104,17 +104,18 @@ bool subghz_protocol_raw_save_to_file_init( break; } - string_set(instance->file_name, dev_name); + furi_string_set(instance->file_name, dev_name); // First remove subghz device file if it was saved - string_printf(temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); + furi_string_printf(temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); - if(!storage_simply_remove(instance->storage, string_get_cstr(temp_str))) { + if(!storage_simply_remove(instance->storage, furi_string_get_cstr(temp_str))) { break; } // Open file - if(!flipper_format_file_open_always(instance->flipper_file, string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Unable to open file for write: %s", temp_str); + if(!flipper_format_file_open_always( + instance->flipper_file, furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Unable to open file for write: %s", furi_string_get_cstr(temp_str)); break; } @@ -130,13 +131,13 @@ bool subghz_protocol_raw_save_to_file_init( break; } - subghz_block_generic_get_preset_name(string_get_cstr(preset->name), temp_str); + subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); if(!flipper_format_write_string_cstr( - instance->flipper_file, "Preset", string_get_cstr(temp_str))) { + instance->flipper_file, "Preset", furi_string_get_cstr(temp_str))) { FURI_LOG_E(TAG, "Unable to add Preset"); break; } - if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { if(!flipper_format_write_string_cstr( instance->flipper_file, "Custom_preset_module", "CC1101")) { FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); @@ -160,7 +161,7 @@ bool subghz_protocol_raw_save_to_file_init( init = true; } while(0); - string_clear(temp_str); + furi_string_free(temp_str); return init; } @@ -210,7 +211,7 @@ void* subghz_protocol_decoder_raw_alloc(SubGhzEnvironment* environment) { instance->ind_write = 0; instance->last_level = false; instance->file_is_open = RAWFileIsOpenClose; - string_init(instance->file_name); + instance->file_name = furi_string_alloc(); return instance; } @@ -218,7 +219,7 @@ void* subghz_protocol_decoder_raw_alloc(SubGhzEnvironment* environment) { void subghz_protocol_decoder_raw_free(void* context) { furi_assert(context); SubGhzProtocolDecoderRAW* instance = context; - string_clear(instance->file_name); + furi_string_free(instance->file_name); free(instance); } @@ -255,12 +256,12 @@ bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipp return true; } -void subghz_protocol_decoder_raw_get_string(void* context, string_t output) { +void subghz_protocol_decoder_raw_get_string(void* context, FuriString* output) { furi_assert(context); //SubGhzProtocolDecoderRAW* instance = context; UNUSED(context); //ToDo no use - string_cat_printf(output, "RAW Date"); + furi_string_cat_printf(output, "RAW Date"); } void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { @@ -268,7 +269,7 @@ void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { SubGhzProtocolEncoderRAW* instance = malloc(sizeof(SubGhzProtocolEncoderRAW)); instance->base.protocol = &subghz_protocol_raw; - string_init(instance->file_name); + instance->file_name = furi_string_alloc(); instance->is_running = false; return instance; } @@ -286,7 +287,7 @@ void subghz_protocol_encoder_raw_free(void* context) { furi_assert(context); SubGhzProtocolEncoderRAW* instance = context; subghz_protocol_encoder_raw_stop(instance); - string_clear(instance->file_name); + furi_string_free(instance->file_name); free(instance); } @@ -305,7 +306,7 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in instance->file_worker_encoder = subghz_file_encoder_worker_alloc(); if(subghz_file_encoder_worker_start( - instance->file_worker_encoder, string_get_cstr(instance->file_name))) { + instance->file_worker_encoder, furi_string_get_cstr(instance->file_name))) { //the worker needs a file in order to open and read part of the file furi_delay_ms(100); instance->is_running = true; @@ -334,8 +335,8 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp furi_assert(context); SubGhzProtocolEncoderRAW* instance = context; bool res = false; - string_t temp_str; - string_init(temp_str); + FuriString* temp_str; + temp_str = furi_string_alloc(); do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); @@ -346,11 +347,11 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp FURI_LOG_E(TAG, "Missing File_name"); break; } - string_set(instance->file_name, temp_str); + furi_string_set(instance->file_name, temp_str); res = subghz_protocol_encoder_raw_worker_init(instance); } while(false); - string_clear(temp_str); + furi_string_free(temp_str); return res; } diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index b52a7d84..be03dea2 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -82,7 +82,7 @@ bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipp * @param context Pointer to a SubGhzProtocolDecoderRAW instance * @param output Resulting text */ -void subghz_protocol_decoder_raw_get_string(void* context, string_t output); +void subghz_protocol_decoder_raw_get_string(void* context, FuriString* output); /** * Allocate SubGhzProtocolEncoderRAW. diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index 1c044e9d..837dcf05 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -263,18 +263,18 @@ bool subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat return subghz_block_generic_deserialize(&instance->generic, flipper_format); } -void subghz_protocol_decoder_scher_khan_get_string(void* context, string_t output) { +void subghz_protocol_decoder_scher_khan_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderScherKhan* instance = context; subghz_protocol_scher_khan_check_remote_controller( &instance->generic, &instance->protocol_name); - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:0x%lX%08lX\r\n" - "Sn:%07lX Btn:%lX Cnt:%04X\r\n" + "Sn:%07lX Btn:%X Cnt:%04lX\r\n" "Pt: %s\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/scher_khan.h b/lib/subghz/protocols/scher_khan.h index 391ccc41..f0fe595b 100644 --- a/lib/subghz/protocols/scher_khan.h +++ b/lib/subghz/protocols/scher_khan.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderScherKhan instance * @param output Resulting text */ -void subghz_protocol_decoder_scher_khan_get_string(void* context, string_t output); +void subghz_protocol_decoder_scher_khan_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 77a0c62a..cfe6bdee 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -555,7 +555,7 @@ bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) { return true; } -void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output) { +void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v1* instance = context; @@ -567,7 +567,7 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t outpu uint8_t id1 = (fixed / 9) % 3; uint16_t pin = 0; - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" @@ -587,9 +587,9 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t outpu pin = (fixed / 59049) % 19683; if(pin <= 9999) { - string_cat_printf(output, " pin:%d", pin); + furi_string_cat_printf(output, " pin:%d", pin); } else if(10000 <= pin && pin <= 11029) { - string_cat_printf(output, " pin:enter"); + furi_string_cat_printf(output, " pin:enter"); } int pin_suffix = 0; @@ -597,16 +597,16 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t outpu pin_suffix = (fixed / 1162261467) % 3; if(pin_suffix == 1) { - string_cat_printf(output, " #\r\n"); + furi_string_cat_printf(output, " #\r\n"); } else if(pin_suffix == 2) { - string_cat_printf(output, " *\r\n"); + furi_string_cat_printf(output, " *\r\n"); } else { - string_cat_printf(output, "\r\n"); + furi_string_cat_printf(output, "\r\n"); } - string_cat_printf( + furi_string_cat_printf( output, "Sn:0x%08lX\r\n" - "Cnt:0x%03X\r\n" + "Cnt:0x%03lX\r\n" "Sw_id:0x%X\r\n", instance->generic.serial, instance->generic.cnt, @@ -615,17 +615,17 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t outpu //id = fixed / 27; instance->generic.serial = fixed / 27; if(instance->generic.btn == 1) { - string_cat_printf(output, " Btn:left\r\n"); + furi_string_cat_printf(output, " Btn:left\r\n"); } else if(instance->generic.btn == 0) { - string_cat_printf(output, " Btn:middle\r\n"); + furi_string_cat_printf(output, " Btn:middle\r\n"); } else if(instance->generic.btn == 2) { - string_cat_printf(output, " Btn:right\r\n"); + furi_string_cat_printf(output, " Btn:right\r\n"); } - string_cat_printf( + furi_string_cat_printf( output, "Sn:0x%08lX\r\n" - "Cnt:0x%03X\r\n" + "Cnt:0x%03lX\r\n" "Sw_id:0x%X\r\n", instance->generic.serial, instance->generic.cnt, diff --git a/lib/subghz/protocols/secplus_v1.h b/lib/subghz/protocols/secplus_v1.h index 8ae1c0cb..ba1762f5 100644 --- a/lib/subghz/protocols/secplus_v1.h +++ b/lib/subghz/protocols/secplus_v1.h @@ -110,4 +110,4 @@ bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance * @param output Resulting text */ -void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output); +void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index c242d0b4..73bb7802 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -810,18 +810,18 @@ bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat return res; } -void subghz_protocol_decoder_secplus_v2_get_string(void* context, string_t output) { +void subghz_protocol_decoder_secplus_v2_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v2* instance = context; subghz_protocol_secplus_v2_remote_controller(&instance->generic, instance->secplus_packet_1); - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Pk1:0x%lX%08lX\r\n" "Pk2:0x%lX%08lX\r\n" "Sn:0x%08lX Btn:0x%01X\r\n" - "Cnt:0x%03X\r\n", + "Cnt:0x%03lX\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h index 9e9ae2a7..007609fc 100644 --- a/lib/subghz/protocols/secplus_v2.h +++ b/lib/subghz/protocols/secplus_v2.h @@ -122,4 +122,4 @@ bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance * @param output Resulting text */ -void subghz_protocol_decoder_secplus_v2_get_string(void* context, string_t output); +void subghz_protocol_decoder_secplus_v2_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index 7a3b2186..cf627ef3 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -426,18 +426,18 @@ bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperForm return res; } -void subghz_protocol_decoder_somfy_keytis_get_string(void* context, string_t output) { +void subghz_protocol_decoder_somfy_keytis_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderSomfyKeytis* instance = context; subghz_protocol_somfy_keytis_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "%lX%08lX%06lX\r\n" "Sn:0x%06lX \r\n" - "Cnt:0x%04X\r\n" + "Cnt:0x%04lX\r\n" "Btn:%s\r\n", instance->generic.protocol_name, diff --git a/lib/subghz/protocols/somfy_keytis.h b/lib/subghz/protocols/somfy_keytis.h index 29f96cd6..af1df91d 100644 --- a/lib/subghz/protocols/somfy_keytis.h +++ b/lib/subghz/protocols/somfy_keytis.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperForm * @param context Pointer to a SubGhzProtocolDecoderSomfyKeytis instance * @param output Resulting text */ -void subghz_protocol_decoder_somfy_keytis_get_string(void* context, string_t output); +void subghz_protocol_decoder_somfy_keytis_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index b9aac577..6e375bb3 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -363,18 +363,18 @@ bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperForma return ret; } -void subghz_protocol_decoder_somfy_telis_get_string(void* context, string_t output) { +void subghz_protocol_decoder_somfy_telis_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderSomfyTelis* instance = context; subghz_protocol_somfy_telis_check_remote_controller(&instance->generic); - string_cat_printf( + furi_string_cat_printf( output, "%s %db\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%06lX \r\n" - "Cnt:0x%04X\r\n" + "Cnt:0x%04lX\r\n" "Btn:%s\r\n", instance->generic.protocol_name, diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index ff5b45e2..b6e58e34 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperForma * @param context Pointer to a SubGhzProtocolDecoderSomfyTelis instance * @param output Resulting text */ -void subghz_protocol_decoder_somfy_telis_get_string(void* context, string_t output); +void subghz_protocol_decoder_somfy_telis_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index 757b5662..4b89bd2b 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -2,7 +2,6 @@ #include "keeloq_common.h" #include "../subghz_keystore.h" -#include #include #include "../blocks/const.h" @@ -229,7 +228,7 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( //Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -240,7 +239,7 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -248,7 +247,7 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( // Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } // Check for mirrored man @@ -260,7 +259,7 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( } decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } //########################### @@ -270,13 +269,13 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { - *manufacture_name = string_get_cstr(manufacture_code->name); + *manufacture_name = furi_string_get_cstr(manufacture_code->name); return 1; } break; @@ -355,7 +354,7 @@ bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* return res; } -void subghz_protocol_decoder_star_line_get_string(void* context, string_t output) { +void subghz_protocol_decoder_star_line_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderStarLine* instance = context; @@ -370,12 +369,12 @@ void subghz_protocol_decoder_star_line_get_string(void* context, string_t output uint32_t code_found_reverse_hi = code_found_reverse >> 32; uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; - string_cat_printf( + furi_string_cat_printf( output, "%s %dbit\r\n" "Key:%08lX%08lX\r\n" - "Fix:0x%08lX Cnt:%04X\r\n" - "Hop:0x%08lX Btn:%02lX\r\n" + "Fix:0x%08lX Cnt:%04lX\r\n" + "Hop:0x%08lX Btn:%02X\r\n" "MF:%s\r\n" "Sn:0x%07lX \r\n", instance->generic.protocol_name, diff --git a/lib/subghz/protocols/star_line.h b/lib/subghz/protocols/star_line.h index e240954b..74c99410 100644 --- a/lib/subghz/protocols/star_line.h +++ b/lib/subghz/protocols/star_line.h @@ -70,4 +70,4 @@ bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* * @param context Pointer to a SubGhzProtocolDecoderStarLine instance * @param output Resulting text */ -void subghz_protocol_decoder_star_line_get_string(void* context, string_t output); +void subghz_protocol_decoder_star_line_get_string(void* context, FuriString* output); diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index 8f65ea00..29834b41 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -1,5 +1,4 @@ #include "subghz_file_encoder_worker.h" -#include #include #include @@ -11,7 +10,7 @@ struct SubGhzFileEncoderWorker { FuriThread* thread; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; Storage* storage; FlipperFormat* flipper_format; @@ -19,8 +18,8 @@ struct SubGhzFileEncoderWorker { volatile bool worker_running; volatile bool worker_stoping; bool level; - string_t str_data; - string_t file_path; + FuriString* str_data; + FuriString* file_path; SubGhzFileEncoderWorkerCallbackEnd callback_end; void* context_end; @@ -48,7 +47,7 @@ void subghz_file_encoder_worker_add_level_duration( if(res) { instance->level = !instance->level; - xStreamBufferSend(instance->stream, &duration, sizeof(int32_t), 100); + furi_stream_buffer_send(instance->stream, &duration, sizeof(int32_t), 100); } else { FURI_LOG_E(TAG, "Invalid level in the stream"); } @@ -83,10 +82,7 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { furi_assert(context); SubGhzFileEncoderWorker* instance = context; int32_t duration; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - int ret = xStreamBufferReceiveFromISR( - instance->stream, &duration, sizeof(int32_t), &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + int ret = furi_stream_buffer_receive(instance->stream, &duration, sizeof(int32_t), 0); if(ret == sizeof(int32_t)) { LevelDuration level_duration = {.level = LEVEL_DURATION_RESET}; if(duration < 0) { @@ -117,9 +113,11 @@ static int32_t subghz_file_encoder_worker_thread(void* context) { Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); do { if(!flipper_format_file_open_existing( - instance->flipper_format, string_get_cstr(instance->file_path))) { + instance->flipper_format, furi_string_get_cstr(instance->file_path))) { FURI_LOG_E( - TAG, "Unable to open file for read: %s", string_get_cstr(instance->file_path)); + TAG, + "Unable to open file for read: %s", + furi_string_get_cstr(instance->file_path)); break; } if(!flipper_format_read_string(instance->flipper_format, "Protocol", instance->str_data)) { @@ -135,12 +133,12 @@ static int32_t subghz_file_encoder_worker_thread(void* context) { } while(0); while(res && instance->worker_running) { - size_t stream_free_byte = xStreamBufferSpacesAvailable(instance->stream); + size_t stream_free_byte = furi_stream_buffer_spaces_available(instance->stream); if((stream_free_byte / sizeof(int32_t)) >= SUBGHZ_FILE_ENCODER_LOAD) { if(stream_read_line(stream, instance->str_data)) { - string_strim(instance->str_data); + furi_string_trim(instance->str_data); if(!subghz_file_encoder_worker_data_parse( - instance, string_get_cstr(instance->str_data))) { + instance, furi_string_get_cstr(instance->str_data))) { //to stop DMA correctly subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); subghz_file_encoder_worker_add_level_duration(instance, LEVEL_DURATION_RESET); @@ -181,13 +179,13 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() { furi_thread_set_stack_size(instance->thread, 2048); furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_file_encoder_worker_thread); - instance->stream = xStreamBufferCreate(sizeof(int32_t) * 2048, sizeof(int32_t)); + instance->stream = furi_stream_buffer_alloc(sizeof(int32_t) * 2048, sizeof(int32_t)); instance->storage = furi_record_open(RECORD_STORAGE); instance->flipper_format = flipper_format_file_alloc(instance->storage); - string_init(instance->str_data); - string_init(instance->file_path); + instance->str_data = furi_string_alloc(); + instance->file_path = furi_string_alloc(); instance->level = false; instance->worker_stoping = true; @@ -197,11 +195,11 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() { void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) { furi_assert(instance); - vStreamBufferDelete(instance->stream); + furi_stream_buffer_free(instance->stream); furi_thread_free(instance->thread); - string_clear(instance->str_data); - string_clear(instance->file_path); + furi_string_free(instance->str_data); + furi_string_free(instance->file_path); flipper_format_free(instance->flipper_format); furi_record_close(RECORD_STORAGE); @@ -213,8 +211,8 @@ bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const c furi_assert(instance); furi_assert(!instance->worker_running); - xStreamBufferReset(instance->stream); - string_set(instance->file_path, file_path); + furi_stream_buffer_reset(instance->stream); + furi_string_set(instance->file_path, file_path); instance->worker_running = true; furi_thread_start(instance->thread); diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index 4d2eb0e5..1b4b3b71 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -43,7 +43,7 @@ void subghz_keystore_free(SubGhzKeystore* instance) { for M_EACH(manufacture_code, instance->data, SubGhzKeyArray_t) { - string_clear(manufacture_code->name); + furi_string_free(manufacture_code->name); manufacture_code->key = 0; } SubGhzKeyArray_clear(instance->data); @@ -57,7 +57,7 @@ static void subghz_keystore_add_key( uint64_t key, uint16_t type) { SubGhzKey* manufacture_code = SubGhzKeyArray_push_raw(instance->data); - string_init_set_str(manufacture_code->name, name); + manufacture_code->name = furi_string_alloc_set(name); manufacture_code->key = key; manufacture_code->type = type; } @@ -191,8 +191,8 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { uint32_t version; SubGhzKeystoreEncryption encryption; - string_t filetype; - string_init(filetype); + FuriString* filetype; + filetype = furi_string_alloc(); FURI_LOG_I(TAG, "Loading keystore %s", file_name); @@ -213,7 +213,7 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { break; } - if(strcmp(string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_TYPE) != 0 || + if(strcmp(furi_string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { FURI_LOG_E(TAG, "Type or version mismatch"); break; @@ -238,7 +238,7 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { furi_record_close(RECORD_STORAGE); - string_clear(filetype); + furi_string_free(filetype); return result; } @@ -294,7 +294,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 (uint32_t)(key->key >> 32), (uint32_t)key->key, key->type, - string_get_cstr(key->name)); + furi_string_get_cstr(key->name)); // Verify length and align furi_assert(len > 0); if(len % 16 != 0) { @@ -349,8 +349,8 @@ bool subghz_keystore_raw_encrypted_save( uint8_t* iv) { bool encrypted = false; uint32_t version; - string_t filetype; - string_init(filetype); + FuriString* filetype; + filetype = furi_string_alloc(); SubGhzKeystoreEncryption encryption; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -373,7 +373,7 @@ bool subghz_keystore_raw_encrypted_save( break; } - if(strcmp(string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || + if(strcmp(furi_string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { FURI_LOG_E(TAG, "Type or version mismatch"); break; @@ -392,7 +392,9 @@ bool subghz_keystore_raw_encrypted_save( break; } if(!flipper_format_write_header_cstr( - output_flipper_format, string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_VERSION)) { + output_flipper_format, + furi_string_get_cstr(filetype), + SUBGHZ_KEYSTORE_FILE_VERSION)) { FURI_LOG_E(TAG, "Unable to add header"); break; } @@ -488,8 +490,8 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* uint32_t version; SubGhzKeystoreEncryption encryption; - string_t str_temp; - string_init(str_temp); + FuriString* str_temp; + str_temp = furi_string_alloc(); Storage* storage = furi_record_open(RECORD_STORAGE); char* decrypted_line = malloc(SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); @@ -509,7 +511,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* break; } - if(strcmp(string_get_cstr(str_temp), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || + if(strcmp(furi_string_get_cstr(str_temp), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { FURI_LOG_E(TAG, "Type or version mismatch"); break; @@ -605,7 +607,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* free(decrypted_line); - string_clear(str_temp); + furi_string_free(str_temp); return result; } diff --git a/lib/subghz/subghz_keystore.h b/lib/subghz/subghz_keystore.h index 2b7880f0..06ae8ada 100644 --- a/lib/subghz/subghz_keystore.h +++ b/lib/subghz/subghz_keystore.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -9,7 +9,7 @@ extern "C" { #endif typedef struct { - string_t name; + FuriString* name; uint64_t key; uint16_t type; } SubGhzKey; diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 78a18693..37c0bfc5 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -1,6 +1,5 @@ #include "subghz_tx_rx_worker.h" -#include #include #define TAG "SubGhzTxRxWorker" @@ -13,8 +12,8 @@ struct SubGhzTxRxWorker { FuriThread* thread; - StreamBufferHandle_t stream_tx; - StreamBufferHandle_t stream_rx; + FuriStreamBuffer* stream_tx; + FuriStreamBuffer* stream_rx; volatile bool worker_running; volatile bool worker_stoping; @@ -30,9 +29,9 @@ struct SubGhzTxRxWorker { bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { furi_assert(instance); bool ret = false; - size_t stream_tx_free_byte = xStreamBufferSpacesAvailable(instance->stream_tx); + size_t stream_tx_free_byte = furi_stream_buffer_spaces_available(instance->stream_tx); if(size && (stream_tx_free_byte >= size)) { - if(xStreamBufferSend( + if(furi_stream_buffer_send( instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) == size) { ret = true; @@ -43,12 +42,12 @@ bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) { furi_assert(instance); - return xStreamBufferBytesAvailable(instance->stream_rx); + return furi_stream_buffer_bytes_available(instance->stream_rx); } size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { furi_assert(instance); - return xStreamBufferReceive(instance->stream_rx, data, size, 0); + return furi_stream_buffer_receive(instance->stream_rx, data, size, 0); } void subghz_tx_rx_worker_set_callback_have_read( @@ -148,11 +147,11 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { while(instance->worker_running) { //transmit - size_tx = xStreamBufferBytesAvailable(instance->stream_tx); + size_tx = furi_stream_buffer_bytes_available(instance->stream_tx); if(size_tx > 0 && !timeout_tx) { timeout_tx = 10; //20ms if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) { - xStreamBufferReceive( + furi_stream_buffer_receive( instance->stream_tx, &data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE, @@ -160,20 +159,20 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE); } else { //todo checking that he managed to write all the data to the TX buffer - xStreamBufferReceive( + furi_stream_buffer_receive( instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); subghz_tx_rx_worker_tx(instance, data, size_tx); } } else { //recive if(subghz_tx_rx_worker_rx(instance, data, size_rx)) { - if(xStreamBufferSpacesAvailable(instance->stream_rx) >= size_rx[0]) { + if(furi_stream_buffer_spaces_available(instance->stream_rx) >= size_rx[0]) { if(instance->callback_have_read && - xStreamBufferBytesAvailable(instance->stream_rx) == 0) { + furi_stream_buffer_bytes_available(instance->stream_rx) == 0) { callback_rx = true; } //todo checking that he managed to write all the data to the RX buffer - xStreamBufferSend( + furi_stream_buffer_send( instance->stream_rx, &data, size_rx[0], @@ -208,9 +207,9 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread); instance->stream_tx = - xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); + furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); instance->stream_rx = - xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); + furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); instance->status = SubGhzTxRxWorkerStatusIDLE; instance->worker_stoping = true; @@ -221,8 +220,8 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { furi_assert(instance); furi_assert(!instance->worker_running); - vStreamBufferDelete(instance->stream_tx); - vStreamBufferDelete(instance->stream_rx); + furi_stream_buffer_free(instance->stream_tx); + furi_stream_buffer_free(instance->stream_rx); furi_thread_free(instance->thread); free(instance); @@ -232,8 +231,8 @@ bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { furi_assert(instance); furi_assert(!instance->worker_running); bool res = false; - xStreamBufferReset(instance->stream_tx); - xStreamBufferReset(instance->stream_rx); + furi_stream_buffer_reset(instance->stream_tx); + furi_stream_buffer_reset(instance->stream_rx); instance->worker_running = true; diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 58db8ea5..61146c16 100644 --- a/lib/subghz/subghz_worker.c +++ b/lib/subghz/subghz_worker.c @@ -1,13 +1,12 @@ #include "subghz_worker.h" -#include #include #define TAG "SubGhzWorker" struct SubGhzWorker { FuriThread* thread; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; volatile bool running; volatile bool overrun; @@ -30,16 +29,14 @@ struct SubGhzWorker { void subghz_worker_rx_callback(bool level, uint32_t duration, void* context) { SubGhzWorker* instance = context; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; LevelDuration level_duration = level_duration_make(level, duration); if(instance->overrun) { instance->overrun = false; level_duration = level_duration_reset(); } - size_t ret = xStreamBufferSendFromISR( - instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken); + size_t ret = + furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0); if(sizeof(LevelDuration) != ret) instance->overrun = true; - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /** Worker callback thread @@ -52,8 +49,8 @@ static int32_t subghz_worker_thread_callback(void* context) { LevelDuration level_duration; while(instance->running) { - int ret = - xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10); + int ret = furi_stream_buffer_receive( + instance->stream, &level_duration, sizeof(LevelDuration), 10); if(ret == sizeof(LevelDuration)) { if(level_duration_is_reset(level_duration)) { FURI_LOG_E(TAG, "Overrun buffer"); @@ -97,7 +94,8 @@ SubGhzWorker* subghz_worker_alloc() { furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_worker_thread_callback); - instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 4096, sizeof(LevelDuration)); + instance->stream = + furi_stream_buffer_alloc(sizeof(LevelDuration) * 4096, sizeof(LevelDuration)); //setting filter instance->filter_running = true; @@ -109,7 +107,7 @@ SubGhzWorker* subghz_worker_alloc() { void subghz_worker_free(SubGhzWorker* instance) { furi_assert(instance); - vStreamBufferDelete(instance->stream); + furi_stream_buffer_free(instance->stream); furi_thread_free(instance->thread); free(instance); diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 32b70b65..dd9cefb8 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -41,7 +41,7 @@ typedef bool (*SubGhzDeserialize)(void* context, FlipperFormat* flipper_format); typedef void (*SubGhzDecoderFeed)(void* decoder, bool level, uint32_t duration); typedef void (*SubGhzDecoderReset)(void* decoder); typedef uint8_t (*SubGhzGetHashData)(void* decoder); -typedef void (*SubGhzGetString)(void* decoder, string_t output); +typedef void (*SubGhzGetString)(void* decoder, FuriString* output); // Encoder specific typedef void (*SubGhzEncoderStop)(void* encoder); diff --git a/lib/toolbox/args.c b/lib/toolbox/args.c index 287ca7ef..aa790ad6 100644 --- a/lib/toolbox/args.c +++ b/lib/toolbox/args.c @@ -1,60 +1,60 @@ #include "args.h" #include "hex.h" -size_t args_get_first_word_length(string_t args) { - size_t ws = string_search_char(args, ' '); - if(ws == STRING_FAILURE) { - ws = string_size(args); +size_t args_get_first_word_length(FuriString* args) { + size_t ws = furi_string_search_char(args, ' '); + if(ws == FURI_STRING_FAILURE) { + ws = furi_string_size(args); } return ws; } -size_t args_length(string_t args) { - return string_size(args); +size_t args_length(FuriString* args) { + return furi_string_size(args); } -bool args_read_int_and_trim(string_t args, int* value) { +bool args_read_int_and_trim(FuriString* args, int* value) { size_t cmd_length = args_get_first_word_length(args); if(cmd_length == 0) { return false; } - if(sscanf(string_get_cstr(args), "%d", value) == 1) { - string_right(args, cmd_length); - string_strim(args); + if(sscanf(furi_string_get_cstr(args), "%d", value) == 1) { + furi_string_right(args, cmd_length); + furi_string_trim(args); return true; } return false; } -bool args_read_string_and_trim(string_t args, string_t word) { +bool args_read_string_and_trim(FuriString* args, FuriString* word) { size_t cmd_length = args_get_first_word_length(args); if(cmd_length == 0) { return false; } - string_set_n(word, args, 0, cmd_length); - string_right(args, cmd_length); - string_strim(args); + furi_string_set_n(word, args, 0, cmd_length); + furi_string_right(args, cmd_length); + furi_string_trim(args); return true; } -bool args_read_probably_quoted_string_and_trim(string_t args, string_t word) { - if(string_size(args) > 1 && string_get_char(args, 0) == '\"') { - size_t second_quote_pos = string_search_char(args, '\"', 1); +bool args_read_probably_quoted_string_and_trim(FuriString* args, FuriString* word) { + if(furi_string_size(args) > 1 && furi_string_get_char(args, 0) == '\"') { + size_t second_quote_pos = furi_string_search_char(args, '\"', 1); if(second_quote_pos == 0) { return false; } - string_set_n(word, args, 1, second_quote_pos - 1); - string_right(args, second_quote_pos + 1); - string_strim(args); + furi_string_set_n(word, args, 1, second_quote_pos - 1); + furi_string_right(args, second_quote_pos + 1); + furi_string_trim(args); return true; } else { return args_read_string_and_trim(args, word); @@ -76,9 +76,9 @@ bool args_char_to_hex(char hi_nibble, char low_nibble, uint8_t* byte) { return result; } -bool args_read_hex_bytes(string_t args, uint8_t* bytes, size_t bytes_count) { +bool args_read_hex_bytes(FuriString* args, uint8_t* bytes, size_t bytes_count) { bool result = true; - const char* str_pointer = string_get_cstr(args); + const char* str_pointer = furi_string_get_cstr(args); if(args_get_first_word_length(args) == (bytes_count * 2)) { for(size_t i = 0; i < bytes_count; i++) { diff --git a/lib/toolbox/args.h b/lib/toolbox/args.h index dc72bdaf..556fd4a7 100644 --- a/lib/toolbox/args.h +++ b/lib/toolbox/args.h @@ -2,7 +2,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C" { @@ -15,7 +15,7 @@ extern "C" { * @return true - success * @return false - arguments string does not contain int */ -bool args_read_int_and_trim(string_t args, int* value); +bool args_read_int_and_trim(FuriString* args, int* value); /** * @brief Extract first argument from arguments string and trim arguments string @@ -25,7 +25,7 @@ bool args_read_int_and_trim(string_t args, int* value); * @return true - success * @return false - arguments string does not contain anything */ -bool args_read_string_and_trim(string_t args, string_t word); +bool args_read_string_and_trim(FuriString* args, FuriString* word); /** * @brief Extract the first quoted argument from the argument string and trim the argument string. If the argument is not quoted, calls args_read_string_and_trim. @@ -35,7 +35,7 @@ bool args_read_string_and_trim(string_t args, string_t word); * @return true - success * @return false - arguments string does not contain anything */ -bool args_read_probably_quoted_string_and_trim(string_t args, string_t word); +bool args_read_probably_quoted_string_and_trim(FuriString* args, FuriString* word); /** * @brief Convert hex ASCII values to byte array @@ -46,7 +46,7 @@ bool args_read_probably_quoted_string_and_trim(string_t args, string_t word); * @return true - success * @return false - arguments string does not contain enough values, or contain non-hex ASCII values */ -bool args_read_hex_bytes(string_t args, uint8_t* bytes, size_t bytes_count); +bool args_read_hex_bytes(FuriString* args, uint8_t* bytes, size_t bytes_count); /************************************ HELPERS ***************************************/ @@ -56,7 +56,7 @@ bool args_read_hex_bytes(string_t args, uint8_t* bytes, size_t bytes_count); * @param args arguments string * @return size_t length of first word */ -size_t args_get_first_word_length(string_t args); +size_t args_get_first_word_length(FuriString* args); /** * @brief Get length of arguments string @@ -64,7 +64,7 @@ size_t args_get_first_word_length(string_t args); * @param args arguments string * @return size_t length of arguments string */ -size_t args_length(string_t args); +size_t args_length(FuriString* args); /** * @brief Convert ASCII hex values to byte diff --git a/lib/toolbox/buffer_stream.c b/lib/toolbox/buffer_stream.c index 66d21096..37b2514e 100644 --- a/lib/toolbox/buffer_stream.c +++ b/lib/toolbox/buffer_stream.c @@ -1,5 +1,4 @@ #include "buffer_stream.h" -#include struct Buffer { volatile bool occupied; @@ -10,7 +9,7 @@ struct Buffer { struct BufferStream { size_t stream_overrun_count; - StreamBufferHandle_t stream; + FuriStreamBuffer* stream; size_t index; Buffer* buffers; @@ -54,7 +53,7 @@ BufferStream* buffer_stream_alloc(size_t buffer_size, size_t buffers_count) { buffer_stream->buffers[i].data = malloc(buffer_size); buffer_stream->buffers[i].max_data_size = buffer_size; } - buffer_stream->stream = xStreamBufferCreate( + buffer_stream->stream = furi_stream_buffer_alloc( sizeof(BufferStream*) * buffer_stream->max_buffers_count, sizeof(BufferStream*)); buffer_stream->stream_overrun_count = 0; buffer_stream->index = 0; @@ -66,7 +65,7 @@ void buffer_stream_free(BufferStream* buffer_stream) { for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) { free(buffer_stream->buffers[i].data); } - vStreamBufferDelete(buffer_stream->stream); + furi_stream_buffer_free(buffer_stream->stream); free(buffer_stream->buffers); free(buffer_stream); } @@ -83,11 +82,7 @@ static inline int8_t buffer_stream_get_free_buffer(BufferStream* buffer_stream) return id; } -bool buffer_stream_send_from_isr( - BufferStream* buffer_stream, - const uint8_t* data, - size_t size, - BaseType_t* const task_woken) { +bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* data, size_t size) { Buffer* buffer = &buffer_stream->buffers[buffer_stream->index]; bool result = true; @@ -96,7 +91,7 @@ bool buffer_stream_send_from_isr( // if buffer is full - send it buffer->occupied = true; // we always have space for buffer in stream - xStreamBufferSendFromISR(buffer_stream->stream, &buffer, sizeof(Buffer*), task_woken); + furi_stream_buffer_send(buffer_stream->stream, &buffer, sizeof(Buffer*), 0); // get new buffer from the pool int8_t index = buffer_stream_get_free_buffer(buffer_stream); @@ -119,7 +114,8 @@ bool buffer_stream_send_from_isr( Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout) { Buffer* buffer; - size_t size = xStreamBufferReceive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout); + size_t size = + furi_stream_buffer_receive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout); if(size == sizeof(Buffer*)) { return buffer; @@ -134,9 +130,8 @@ size_t buffer_stream_get_overrun_count(BufferStream* buffer_stream) { void buffer_stream_reset(BufferStream* buffer_stream) { FURI_CRITICAL_ENTER(); - BaseType_t xReturn = xStreamBufferReset(buffer_stream->stream); - furi_assert(xReturn == pdPASS); - UNUSED(xReturn); + furi_stream_buffer_reset(buffer_stream->stream); + buffer_stream->stream_overrun_count = 0; for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) { buffer_reset(&buffer_stream->buffers[i]); diff --git a/lib/toolbox/buffer_stream.h b/lib/toolbox/buffer_stream.h index d4c3cddf..9db54775 100644 --- a/lib/toolbox/buffer_stream.h +++ b/lib/toolbox/buffer_stream.h @@ -59,14 +59,9 @@ void buffer_stream_free(BufferStream* buffer_stream); * @param buffer_stream * @param data * @param size - * @param task_woken * @return bool */ -bool buffer_stream_send_from_isr( - BufferStream* buffer_stream, - const uint8_t* data, - size_t size, - BaseType_t* const task_woken); +bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* data, size_t size); /** * @brief Receive buffer from stream diff --git a/lib/toolbox/dir_walk.c b/lib/toolbox/dir_walk.c index 348bd544..b5e2cb52 100644 --- a/lib/toolbox/dir_walk.c +++ b/lib/toolbox/dir_walk.c @@ -5,7 +5,7 @@ LIST_DEF(DirIndexList, uint32_t); struct DirWalk { File* file; - string_t path; + FuriString* path; DirIndexList_t index_list; uint32_t current_index; bool recursive; @@ -15,7 +15,7 @@ struct DirWalk { DirWalk* dir_walk_alloc(Storage* storage) { DirWalk* dir_walk = malloc(sizeof(DirWalk)); - string_init(dir_walk->path); + dir_walk->path = furi_string_alloc(); dir_walk->file = storage_file_alloc(storage); DirIndexList_init(dir_walk->index_list); dir_walk->recursive = true; @@ -25,7 +25,7 @@ DirWalk* dir_walk_alloc(Storage* storage) { void dir_walk_free(DirWalk* dir_walk) { storage_file_free(dir_walk->file); - string_clear(dir_walk->path); + furi_string_free(dir_walk->path); DirIndexList_clear(dir_walk->index_list); free(dir_walk); } @@ -40,7 +40,7 @@ void dir_walk_set_filter_cb(DirWalk* dir_walk, DirWalkFilterCb cb, void* context } bool dir_walk_open(DirWalk* dir_walk, const char* path) { - string_set(dir_walk->path, path); + furi_string_set(dir_walk->path, path); dir_walk->current_index = 0; return storage_dir_open(dir_walk->file, path); } @@ -53,7 +53,8 @@ static bool dir_walk_filter(DirWalk* dir_walk, const char* name, FileInfo* filei } } -static DirWalkResult dir_walk_iter(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo) { +static DirWalkResult + dir_walk_iter(DirWalk* dir_walk, FuriString* return_path, FileInfo* fileinfo) { DirWalkResult result = DirWalkError; char* name = malloc(256); // FIXME: remove magic number FileInfo info; @@ -68,7 +69,8 @@ static DirWalkResult dir_walk_iter(DirWalk* dir_walk, string_t return_path, File if(dir_walk_filter(dir_walk, name, &info)) { if(return_path != NULL) { - string_printf(return_path, "%s/%s", string_get_cstr(dir_walk->path), name); + furi_string_printf( + return_path, "%s/%s", furi_string_get_cstr(dir_walk->path), name); } if(fileinfo != NULL) { @@ -84,8 +86,8 @@ static DirWalkResult dir_walk_iter(DirWalk* dir_walk, string_t return_path, File dir_walk->current_index = 0; storage_dir_close(dir_walk->file); - string_cat_printf(dir_walk->path, "/%s", name); - storage_dir_open(dir_walk->file, string_get_cstr(dir_walk->path)); + furi_string_cat_printf(dir_walk->path, "/%s", name); + storage_dir_open(dir_walk->file, furi_string_get_cstr(dir_walk->path)); } } else if(storage_file_get_error(dir_walk->file) == FSE_NOT_EXIST) { if(DirIndexList_size(dir_walk->index_list) == 0) { @@ -100,12 +102,12 @@ static DirWalkResult dir_walk_iter(DirWalk* dir_walk, string_t return_path, File storage_dir_close(dir_walk->file); - size_t last_char = string_search_rchar(dir_walk->path, '/'); - if(last_char != STRING_FAILURE) { - string_left(dir_walk->path, last_char); + size_t last_char = furi_string_search_rchar(dir_walk->path, '/'); + if(last_char != FURI_STRING_FAILURE) { + furi_string_left(dir_walk->path, last_char); } - storage_dir_open(dir_walk->file, string_get_cstr(dir_walk->path)); + storage_dir_open(dir_walk->file, furi_string_get_cstr(dir_walk->path)); // rewind while(true) { @@ -137,7 +139,7 @@ FS_Error dir_walk_get_error(DirWalk* dir_walk) { return storage_file_get_error(dir_walk->file); } -DirWalkResult dir_walk_read(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo) { +DirWalkResult dir_walk_read(DirWalk* dir_walk, FuriString* return_path, FileInfo* fileinfo) { return dir_walk_iter(dir_walk, return_path, fileinfo); } @@ -147,6 +149,6 @@ void dir_walk_close(DirWalk* dir_walk) { } DirIndexList_reset(dir_walk->index_list); - string_reset(dir_walk->path); + furi_string_reset(dir_walk->path); dir_walk->current_index = 0; } diff --git a/lib/toolbox/dir_walk.h b/lib/toolbox/dir_walk.h index fc651042..535237fc 100644 --- a/lib/toolbox/dir_walk.h +++ b/lib/toolbox/dir_walk.h @@ -66,7 +66,7 @@ FS_Error dir_walk_get_error(DirWalk* dir_walk); * @param fileinfo * @return DirWalkResult */ -DirWalkResult dir_walk_read(DirWalk* dir_walk, string_t return_path, FileInfo* fileinfo); +DirWalkResult dir_walk_read(DirWalk* dir_walk, FuriString* return_path, FileInfo* fileinfo); /** * Close directory diff --git a/lib/toolbox/m_cstr_dup.h b/lib/toolbox/m_cstr_dup.h index 2bc35c87..0555f72c 100644 --- a/lib/toolbox/m_cstr_dup.h +++ b/lib/toolbox/m_cstr_dup.h @@ -13,5 +13,4 @@ HASH(m_core_cstr_hash), \ EQUAL(M_CSTR_EQUAL), \ CMP(strcmp), \ - TYPE(const char*), \ - OUT_STR(M_CSTR_OUT_STR)) + TYPE(const char*)) diff --git a/lib/toolbox/path.c b/lib/toolbox/path.c index 1262362e..53e9fc09 100644 --- a/lib/toolbox/path.c +++ b/lib/toolbox/path.c @@ -1,86 +1,85 @@ #include "path.h" -#include "m-string.h" #include -void path_extract_filename_no_ext(const char* path, string_t filename) { - string_set(filename, path); +void path_extract_filename_no_ext(const char* path, FuriString* filename) { + furi_string_set(filename, path); - size_t start_position = string_search_rchar(filename, '/'); - size_t end_position = string_search_rchar(filename, '.'); + size_t start_position = furi_string_search_rchar(filename, '/'); + size_t end_position = furi_string_search_rchar(filename, '.'); - if(start_position == STRING_FAILURE) { + if(start_position == FURI_STRING_FAILURE) { start_position = 0; } else { start_position += 1; } - if(end_position == STRING_FAILURE) { - end_position = string_size(filename); + if(end_position == FURI_STRING_FAILURE) { + end_position = furi_string_size(filename); } - string_mid(filename, start_position, end_position - start_position); + furi_string_mid(filename, start_position, end_position - start_position); } -void path_extract_filename(string_t path, string_t name, bool trim_ext) { - size_t filename_start = string_search_rchar(path, '/'); +void path_extract_filename(FuriString* path, FuriString* name, bool trim_ext) { + size_t filename_start = furi_string_search_rchar(path, '/'); if(filename_start > 0) { filename_start++; - string_set_n(name, path, filename_start, string_size(path) - filename_start); + furi_string_set_n(name, path, filename_start, furi_string_size(path) - filename_start); } if(trim_ext) { - size_t dot = string_search_rchar(name, '.'); + size_t dot = furi_string_search_rchar(name, '.'); if(dot > 0) { - string_left(name, dot); + furi_string_left(name, dot); } } } -void path_extract_extension(string_t path, char* ext, size_t ext_len_max) { - size_t dot = string_search_rchar(path, '.'); - size_t filename_start = string_search_rchar(path, '/'); +void path_extract_extension(FuriString* path, char* ext, size_t ext_len_max) { + size_t dot = furi_string_search_rchar(path, '.'); + size_t filename_start = furi_string_search_rchar(path, '/'); if((dot > 0) && (filename_start < dot)) { - strlcpy(ext, &(string_get_cstr(path))[dot], ext_len_max); + strlcpy(ext, &(furi_string_get_cstr(path))[dot], ext_len_max); } } -static inline void path_cleanup(string_t path) { - string_strim(path); - while(string_end_with_str_p(path, "/")) { - string_left(path, string_size(path) - 1); +static inline void path_cleanup(FuriString* path) { + furi_string_trim(path); + while(furi_string_end_with(path, "/")) { + furi_string_left(path, furi_string_size(path) - 1); } } -void path_extract_basename(const char* path, string_t basename) { - string_set(basename, path); +void path_extract_basename(const char* path, FuriString* basename) { + furi_string_set(basename, path); path_cleanup(basename); - size_t pos = string_search_rchar(basename, '/'); - if(pos != STRING_FAILURE) { - string_right(basename, pos + 1); + size_t pos = furi_string_search_rchar(basename, '/'); + if(pos != FURI_STRING_FAILURE) { + furi_string_right(basename, pos + 1); } } -void path_extract_dirname(const char* path, string_t dirname) { - string_set(dirname, path); +void path_extract_dirname(const char* path, FuriString* dirname) { + furi_string_set(dirname, path); path_cleanup(dirname); - size_t pos = string_search_rchar(dirname, '/'); - if(pos != STRING_FAILURE) { - string_left(dirname, pos); + size_t pos = furi_string_search_rchar(dirname, '/'); + if(pos != FURI_STRING_FAILURE) { + furi_string_left(dirname, pos); } } -void path_append(string_t path, const char* suffix) { +void path_append(FuriString* path, const char* suffix) { path_cleanup(path); - string_t suffix_str; - string_init_set(suffix_str, suffix); - string_strim(suffix_str); - string_strim(suffix_str, "/"); - string_cat_printf(path, "/%s", string_get_cstr(suffix_str)); - string_clear(suffix_str); + FuriString* suffix_str; + suffix_str = furi_string_alloc_set(suffix); + furi_string_trim(suffix_str); + furi_string_trim(suffix_str, "/"); + furi_string_cat_printf(path, "/%s", furi_string_get_cstr(suffix_str)); + furi_string_free(suffix_str); } -void path_concat(const char* path, const char* suffix, string_t out_path) { - string_set(out_path, path); +void path_concat(const char* path, const char* suffix, FuriString* out_path) { + furi_string_set(out_path, path); path_append(out_path, suffix); } diff --git a/lib/toolbox/path.h b/lib/toolbox/path.h index d46b210f..e6145b71 100644 --- a/lib/toolbox/path.h +++ b/lib/toolbox/path.h @@ -1,6 +1,5 @@ #pragma once - -#include +#include #ifdef __cplusplus extern "C" { @@ -12,7 +11,7 @@ extern "C" { * @param path path string * @param filename output filename string. Must be initialized before. */ -void path_extract_filename_no_ext(const char* path, string_t filename); +void path_extract_filename_no_ext(const char* path, FuriString* filename); /** * @brief Extract filename string from path. @@ -21,7 +20,7 @@ void path_extract_filename_no_ext(const char* path, string_t filename); * @param filename output filename string. Must be initialized before. * @param trim_ext true - get filename without extension */ -void path_extract_filename(string_t path, string_t filename, bool trim_ext); +void path_extract_filename(FuriString* path, FuriString* filename, bool trim_ext); /** * @brief Extract file extension from path. @@ -30,7 +29,7 @@ void path_extract_filename(string_t path, string_t filename, bool trim_ext); * @param ext output extension string * @param ext_len_max maximum extension string length */ -void path_extract_extension(string_t path, char* ext, size_t ext_len_max); +void path_extract_extension(FuriString* path, char* ext, size_t ext_len_max); /** * @brief Extract last path component @@ -38,7 +37,7 @@ void path_extract_extension(string_t path, char* ext, size_t ext_len_max); * @param path path string * @param filename output string. Must be initialized before. */ -void path_extract_basename(const char* path, string_t basename); +void path_extract_basename(const char* path, FuriString* basename); /** * @brief Extract path, except for last component @@ -46,7 +45,7 @@ void path_extract_basename(const char* path, string_t basename); * @param path path string * @param filename output string. Must be initialized before. */ -void path_extract_dirname(const char* path, string_t dirname); +void path_extract_dirname(const char* path, FuriString* dirname); /** * @brief Appends new component to path, adding path delimiter @@ -54,7 +53,7 @@ void path_extract_dirname(const char* path, string_t dirname); * @param path path string * @param suffix path part to apply */ -void path_append(string_t path, const char* suffix); +void path_append(FuriString* path, const char* suffix); /** * @brief Appends new component to path, adding path delimiter @@ -63,7 +62,7 @@ void path_append(string_t path, const char* suffix); * @param suffix second path part * @param out_path output string to combine parts into. Must be initialized */ -void path_concat(const char* path, const char* suffix, string_t out_path); +void path_concat(const char* path, const char* suffix, FuriString* out_path); /** * @brief Check that path contains only ascii characters diff --git a/lib/toolbox/protocols/protocol.h b/lib/toolbox/protocols/protocol.h index 56bb1b74..5a8015b1 100644 --- a/lib/toolbox/protocols/protocol.h +++ b/lib/toolbox/protocols/protocol.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include typedef void* (*ProtocolAlloc)(void); typedef void (*ProtocolFree)(void* protocol); @@ -15,7 +15,7 @@ typedef bool (*ProtocolDecoderFeed)(void* protocol, bool level, uint32_t duratio typedef bool (*ProtocolEncoderStart)(void* protocol); typedef LevelDuration (*ProtocolEncoderYield)(void* protocol); -typedef void (*ProtocolRenderData)(void* protocol, string_t result); +typedef void (*ProtocolRenderData)(void* protocol, FuriString* result); typedef bool (*ProtocolWriteData)(void* protocol, void* data); typedef struct { diff --git a/lib/toolbox/protocols/protocol_dict.c b/lib/toolbox/protocols/protocol_dict.c index 2a022cc4..136dc137 100644 --- a/lib/toolbox/protocols/protocol_dict.c +++ b/lib/toolbox/protocols/protocol_dict.c @@ -185,7 +185,7 @@ LevelDuration protocol_dict_encoder_yield(ProtocolDict* dict, size_t protocol_in } } -void protocol_dict_render_data(ProtocolDict* dict, string_t result, size_t protocol_index) { +void protocol_dict_render_data(ProtocolDict* dict, FuriString* result, size_t protocol_index) { furi_assert(protocol_index < dict->count); ProtocolRenderData fn = dict->base[protocol_index]->render_data; @@ -194,7 +194,7 @@ void protocol_dict_render_data(ProtocolDict* dict, string_t result, size_t proto } } -void protocol_dict_render_brief_data(ProtocolDict* dict, string_t result, size_t protocol_index) { +void protocol_dict_render_brief_data(ProtocolDict* dict, FuriString* result, size_t protocol_index) { furi_assert(protocol_index < dict->count); ProtocolRenderData fn = dict->base[protocol_index]->render_brief_data; diff --git a/lib/toolbox/protocols/protocol_dict.h b/lib/toolbox/protocols/protocol_dict.h index 3037ddd5..cd850395 100644 --- a/lib/toolbox/protocols/protocol_dict.h +++ b/lib/toolbox/protocols/protocol_dict.h @@ -58,9 +58,9 @@ bool protocol_dict_encoder_start(ProtocolDict* dict, size_t protocol_index); LevelDuration protocol_dict_encoder_yield(ProtocolDict* dict, size_t protocol_index); -void protocol_dict_render_data(ProtocolDict* dict, string_t result, size_t protocol_index); +void protocol_dict_render_data(ProtocolDict* dict, FuriString* result, size_t protocol_index); -void protocol_dict_render_brief_data(ProtocolDict* dict, string_t result, size_t protocol_index); +void protocol_dict_render_brief_data(ProtocolDict* dict, FuriString* result, size_t protocol_index); uint32_t protocol_dict_get_validate_count(ProtocolDict* dict, size_t protocol_index); diff --git a/lib/toolbox/stream/file_stream.c b/lib/toolbox/stream/file_stream.c index f7363c6b..06491216 100644 --- a/lib/toolbox/stream/file_stream.c +++ b/lib/toolbox/stream/file_stream.c @@ -173,17 +173,20 @@ static bool file_stream_delete_and_insert( Stream* scratch_stream = file_stream_alloc(_stream->storage); // TODO: we need something like "storage_open_tmpfile and storage_close_tmpfile" - string_t scratch_name; - string_t tmp_name; - string_init(tmp_name); + FuriString* scratch_name; + FuriString* tmp_name; + tmp_name = furi_string_alloc(); storage_get_next_filename( _stream->storage, STORAGE_ANY_PATH_PREFIX, ".scratch", ".pad", tmp_name, 255); - string_init_printf(scratch_name, ANY_PATH("%s.pad"), string_get_cstr(tmp_name)); - string_clear(tmp_name); + scratch_name = furi_string_alloc_printf(ANY_PATH("%s.pad"), furi_string_get_cstr(tmp_name)); + furi_string_free(tmp_name); do { if(!file_stream_open( - scratch_stream, string_get_cstr(scratch_name), FSAM_READ_WRITE, FSOM_CREATE_NEW)) + scratch_stream, + furi_string_get_cstr(scratch_name), + FSAM_READ_WRITE, + FSOM_CREATE_NEW)) break; size_t current_position = stream_tell(stream); @@ -225,8 +228,8 @@ static bool file_stream_delete_and_insert( } while(false); stream_free(scratch_stream); - storage_common_remove(_stream->storage, string_get_cstr(scratch_name)); - string_clear(scratch_name); + storage_common_remove(_stream->storage, furi_string_get_cstr(scratch_name)); + furi_string_free(scratch_name); return result; } diff --git a/lib/toolbox/stream/stream.c b/lib/toolbox/stream/stream.c index 088996f0..86d35c95 100644 --- a/lib/toolbox/stream/stream.c +++ b/lib/toolbox/stream/stream.c @@ -67,8 +67,8 @@ static bool stream_write_struct(Stream* stream, const void* context) { return (stream_write(stream, write_data->data, write_data->size) == write_data->size); } -bool stream_read_line(Stream* stream, string_t str_result) { - string_reset(str_result); +bool stream_read_line(Stream* stream, FuriString* str_result) { + furi_string_reset(str_result); const uint8_t buffer_size = 32; uint8_t buffer[buffer_size]; @@ -84,13 +84,13 @@ bool stream_read_line(Stream* stream, string_t str_result) { error = true; break; } - string_push_back(str_result, buffer[i]); + furi_string_push_back(str_result, buffer[i]); result = true; break; } else if(buffer[i] == '\r') { // Ignore } else { - string_push_back(str_result, buffer[i]); + furi_string_push_back(str_result, buffer[i]); } } @@ -99,7 +99,7 @@ bool stream_read_line(Stream* stream, string_t str_result) { } } while(true); - return string_size(str_result) != 0; + return furi_string_size(str_result) != 0; } bool stream_rewind(Stream* stream) { @@ -112,9 +112,10 @@ size_t stream_write_char(Stream* stream, char c) { return stream_write(stream, (const uint8_t*)&c, 1); } -size_t stream_write_string(Stream* stream, string_t string) { +size_t stream_write_string(Stream* stream, FuriString* string) { furi_assert(stream); - return stream_write(stream, (const uint8_t*)string_get_cstr(string), string_size(string)); + return stream_write( + stream, (const uint8_t*)furi_string_get_cstr(string), furi_string_size(string)); } size_t stream_write_cstring(Stream* stream, const char* string) { @@ -134,10 +135,10 @@ size_t stream_write_format(Stream* stream, const char* format, ...) { size_t stream_write_vaformat(Stream* stream, const char* format, va_list args) { furi_assert(stream); - string_t data; - string_init_vprintf(data, format, args); + FuriString* data; + data = furi_string_alloc_vprintf(format, args); size_t size = stream_write_string(stream, data); - string_clear(data); + furi_string_free(data); return size; } @@ -153,7 +154,7 @@ bool stream_insert_char(Stream* stream, char c) { return stream_delete_and_insert_char(stream, 0, c); } -bool stream_insert_string(Stream* stream, string_t string) { +bool stream_insert_string(Stream* stream, FuriString* string) { furi_assert(stream); return stream_delete_and_insert_string(stream, 0, string); } @@ -184,10 +185,10 @@ bool stream_delete_and_insert_char(Stream* stream, size_t delete_size, char c) { return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data); } -bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, string_t string) { +bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, FuriString* string) { furi_assert(stream); StreamWriteData write_data = { - .data = (uint8_t*)string_get_cstr(string), .size = string_size(string)}; + .data = (uint8_t*)furi_string_get_cstr(string), .size = furi_string_size(string)}; return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data); } @@ -213,12 +214,12 @@ bool stream_delete_and_insert_vaformat( const char* format, va_list args) { furi_assert(stream); - string_t data; - string_init_vprintf(data, format, args); + FuriString* data; + data = furi_string_alloc_vprintf(format, args); StreamWriteData write_data = { - .data = (uint8_t*)string_get_cstr(data), .size = string_size(data)}; + .data = (uint8_t*)furi_string_get_cstr(data), .size = furi_string_size(data)}; bool result = stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data); - string_clear(data); + furi_string_free(data); return result; } diff --git a/lib/toolbox/stream/stream.h b/lib/toolbox/stream/stream.h index c10e9f5e..fc385510 100644 --- a/lib/toolbox/stream/stream.h +++ b/lib/toolbox/stream/stream.h @@ -2,7 +2,6 @@ #include #include #include -#include #include #ifdef __cplusplus @@ -105,7 +104,7 @@ bool stream_delete_and_insert( * @return true if line lenght is not zero * @return false otherwise */ -bool stream_read_line(Stream* stream, string_t str_result); +bool stream_read_line(Stream* stream, FuriString* str_result); /** * Moves the rw pointer to the start @@ -127,7 +126,7 @@ size_t stream_write_char(Stream* stream, char c); * @param string string value * @return size_t how many bytes was written */ -size_t stream_write_string(Stream* stream, string_t string); +size_t stream_write_string(Stream* stream, FuriString* string); /** * Write const char* to the stream @@ -144,7 +143,8 @@ size_t stream_write_cstring(Stream* stream, const char* string); * @param ... * @return size_t how many bytes was written */ -size_t stream_write_format(Stream* stream, const char* format, ...); +size_t stream_write_format(Stream* stream, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); /** * Write formatted string to the stream, va_list version @@ -182,7 +182,7 @@ bool stream_insert_char(Stream* stream, char c); * @return true if the operation was successful * @return false on error */ -bool stream_insert_string(Stream* stream, string_t string); +bool stream_insert_string(Stream* stream, FuriString* string); /** * Insert const char* to the stream @@ -201,7 +201,8 @@ bool stream_insert_cstring(Stream* stream, const char* string); * @return true if the operation was successful * @return false on error */ -bool stream_insert_format(Stream* stream, const char* format, ...); +bool stream_insert_format(Stream* stream, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); /** * Insert formatted string to the stream, va_list version @@ -231,7 +232,7 @@ bool stream_delete_and_insert_char(Stream* stream, size_t delete_size, char c); * @return true if the operation was successful * @return false on error */ -bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, string_t string); +bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, FuriString* string); /** * Delete N chars from the stream and insert const char* to the stream @@ -252,7 +253,8 @@ bool stream_delete_and_insert_cstring(Stream* stream, size_t delete_size, const * @return true if the operation was successful * @return false on error */ -bool stream_delete_and_insert_format(Stream* stream, size_t delete_size, const char* format, ...); +bool stream_delete_and_insert_format(Stream* stream, size_t delete_size, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 3, 4))); /** * Delete N chars from the stream and insert formatted string to the stream, va_list version diff --git a/lib/toolbox/stream/string_stream.c b/lib/toolbox/stream/string_stream.c index f3e1364d..075f0b26 100644 --- a/lib/toolbox/stream/string_stream.c +++ b/lib/toolbox/stream/string_stream.c @@ -5,7 +5,7 @@ typedef struct { Stream stream_base; - string_t string; + FuriString* string; size_t index; } StringStream; @@ -39,14 +39,14 @@ const StreamVTable string_stream_vtable = { Stream* string_stream_alloc() { StringStream* stream = malloc(sizeof(StringStream)); - string_init(stream->string); + stream->string = furi_string_alloc(); stream->index = 0; stream->stream_base.vtable = &string_stream_vtable; return (Stream*)stream; } static void string_stream_free(StringStream* stream) { - string_clear(stream->string); + furi_string_free(stream->string); free(stream); } @@ -56,7 +56,7 @@ static bool string_stream_eof(StringStream* stream) { static void string_stream_clean(StringStream* stream) { stream->index = 0; - string_reset(stream->string); + furi_string_reset(stream->string); } static bool string_stream_seek(StringStream* stream, int32_t offset, StreamOffset offset_type) { @@ -79,8 +79,8 @@ static bool string_stream_seek(StringStream* stream, int32_t offset, StreamOffse } break; case StreamOffsetFromEnd: - if(((int32_t)string_size(stream->string) + offset) >= 0) { - stream->index = string_size(stream->string) + offset; + if(((int32_t)furi_string_size(stream->string) + offset) >= 0) { + stream->index = furi_string_size(stream->string) + offset; } else { result = false; stream->index = 0; @@ -88,7 +88,7 @@ static bool string_stream_seek(StringStream* stream, int32_t offset, StreamOffse break; } - int32_t diff = (stream->index - string_size(stream->string)); + int32_t diff = (stream->index - furi_string_size(stream->string)); if(diff > 0) { stream->index -= diff; result = false; @@ -102,7 +102,7 @@ static size_t string_stream_tell(StringStream* stream) { } static size_t string_stream_size(StringStream* stream) { - return string_size(stream->string); + return furi_string_size(stream->string); } static size_t string_stream_write(StringStream* stream, const char* data, size_t size) { @@ -117,7 +117,7 @@ static size_t string_stream_write(StringStream* stream, const char* data, size_t static size_t string_stream_read(StringStream* stream, char* data, size_t size) { size_t write_index = 0; - const char* cstr = string_get_cstr(stream->string); + const char* cstr = furi_string_get_cstr(stream->string); if(!string_stream_eof(stream)) { while(true) { @@ -145,17 +145,17 @@ static bool string_stream_delete_and_insert( remain_size = MIN(delete_size, remain_size); if(remain_size != 0) { - string_replace_at(stream->string, stream->index, remain_size, ""); + furi_string_replace_at(stream->string, stream->index, remain_size, ""); } } if(write_callback) { - string_t right; - string_init_set(right, &string_get_cstr(stream->string)[stream->index]); - string_left(stream->string, string_stream_tell(stream)); + FuriString* right; + right = furi_string_alloc_set(&furi_string_get_cstr(stream->string)[stream->index]); + furi_string_left(stream->string, string_stream_tell(stream)); result &= write_callback((Stream*)stream, ctx); - string_cat(stream->string, right); - string_clear(right); + furi_string_cat(stream->string, right); + furi_string_free(right); } return result; @@ -169,9 +169,9 @@ static bool string_stream_delete_and_insert( */ static size_t string_stream_write_char(StringStream* stream, char c) { if(string_stream_eof(stream)) { - string_push_back(stream->string, c); + furi_string_push_back(stream->string, c); } else { - string_set_char(stream->string, stream->index, c); + furi_string_set_char(stream->string, stream->index, c); } stream->index++; diff --git a/lib/toolbox/stream/string_stream.h b/lib/toolbox/stream/string_stream.h index 6cccfa6c..f882a246 100644 --- a/lib/toolbox/stream/string_stream.h +++ b/lib/toolbox/stream/string_stream.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "stream.h" #ifdef __cplusplus diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 1a542b2e..e8b44729 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -220,14 +220,14 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header, return 0; } - string_t full_extracted_fname; + FuriString* full_extracted_fname; if(header->type == MTAR_TDIR) { - string_init(full_extracted_fname); + full_extracted_fname = furi_string_alloc(); path_concat(op_params->work_dir, header->name, full_extracted_fname); bool create_res = - storage_simply_mkdir(archive->storage, string_get_cstr(full_extracted_fname)); - string_clear(full_extracted_fname); + storage_simply_mkdir(archive->storage, furi_string_get_cstr(full_extracted_fname)); + furi_string_free(full_extracted_fname); return create_res ? 0 : -1; } @@ -238,19 +238,19 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header, FURI_LOG_D(TAG, "Extracting %d bytes to '%s'", header->size, header->name); - string_t converted_fname; - string_init_set(converted_fname, header->name); + FuriString* converted_fname = furi_string_alloc_set(header->name); if(op_params->converter) { op_params->converter(converted_fname); } - string_init(full_extracted_fname); - path_concat(op_params->work_dir, string_get_cstr(converted_fname), full_extracted_fname); + full_extracted_fname = furi_string_alloc(); + path_concat(op_params->work_dir, furi_string_get_cstr(converted_fname), full_extracted_fname); - bool success = archive_extract_current_file(archive, string_get_cstr(full_extracted_fname)); + bool success = + archive_extract_current_file(archive, furi_string_get_cstr(full_extracted_fname)); - string_clear(converted_fname); - string_clear(full_extracted_fname); + furi_string_free(converted_fname); + furi_string_free(full_extracted_fname); return success ? 0 : -1; } @@ -333,32 +333,32 @@ bool tar_archive_add_dir(TarArchive* archive, const char* fs_full_path, const ch break; } - string_t element_name, element_fs_abs_path; - string_init(element_name); - string_init(element_fs_abs_path); + FuriString* element_name = furi_string_alloc(); + FuriString* element_fs_abs_path = furi_string_alloc(); path_concat(fs_full_path, name, element_fs_abs_path); if(strlen(path_prefix)) { path_concat(path_prefix, name, element_name); } else { - string_init_set(element_name, name); + furi_string_set(element_name, name); } if(file_info.flags & FSF_DIRECTORY) { - success = tar_archive_dir_add_element(archive, string_get_cstr(element_name)) && - tar_archive_add_dir( - archive, - string_get_cstr(element_fs_abs_path), - string_get_cstr(element_name)); + success = + tar_archive_dir_add_element(archive, furi_string_get_cstr(element_name)) && + tar_archive_add_dir( + archive, + furi_string_get_cstr(element_fs_abs_path), + furi_string_get_cstr(element_name)); } else { success = tar_archive_add_file( archive, - string_get_cstr(element_fs_abs_path), - string_get_cstr(element_name), + furi_string_get_cstr(element_fs_abs_path), + furi_string_get_cstr(element_name), file_info.size); } - string_clear(element_name); - string_clear(element_fs_abs_path); + furi_string_free(element_name); + furi_string_free(element_fs_abs_path); if(!success) { break; diff --git a/lib/toolbox/tar/tar_archive.h b/lib/toolbox/tar/tar_archive.h index ceaf82ee..ba2f7749 100644 --- a/lib/toolbox/tar/tar_archive.h +++ b/lib/toolbox/tar/tar_archive.h @@ -2,7 +2,6 @@ #include #include -#include #include #ifdef __cplusplus diff --git a/lib/update_util/lfs_backup.c b/lib/update_util/lfs_backup.c index 089f032d..7786524e 100644 --- a/lib/update_util/lfs_backup.c +++ b/lib/update_util/lfs_backup.c @@ -11,8 +11,8 @@ #define LFS_BACKUP_DEFAULT_LOCATION EXT_PATH(LFS_BACKUP_DEFAULT_FILENAME) -static void backup_name_converter(string_t filename) { - if(string_empty_p(filename) || (string_get_char(filename, 0) == '.')) { +static void backup_name_converter(FuriString* filename) { + if(furi_string_empty(filename) || (furi_string_get_char(filename, 0) == '.')) { return; } @@ -27,8 +27,8 @@ static void backup_name_converter(string_t filename) { }; for(size_t i = 0; i < COUNT_OF(names); i++) { - if(string_equal_str_p(filename, &names[i][1])) { - string_set_str(filename, names[i]); + if(furi_string_equal(filename, &names[i][1])) { + furi_string_set(filename, names[i]); return; } } diff --git a/lib/update_util/resources/manifest.c b/lib/update_util/resources/manifest.c index 4f8a7d1a..8b6a1b33 100644 --- a/lib/update_util/resources/manifest.c +++ b/lib/update_util/resources/manifest.c @@ -6,7 +6,7 @@ struct ResourceManifestReader { Storage* storage; Stream* stream; - string_t linebuf; + FuriString* linebuf; ResourceManifestEntry entry; }; @@ -16,16 +16,16 @@ ResourceManifestReader* resource_manifest_reader_alloc(Storage* storage) { resource_manifest->storage = storage; resource_manifest->stream = buffered_file_stream_alloc(resource_manifest->storage); memset(&resource_manifest->entry, 0, sizeof(ResourceManifestEntry)); - string_init(resource_manifest->entry.name); - string_init(resource_manifest->linebuf); + resource_manifest->entry.name = furi_string_alloc(); + resource_manifest->linebuf = furi_string_alloc(); return resource_manifest; } void resource_manifest_reader_free(ResourceManifestReader* resource_manifest) { furi_assert(resource_manifest); - string_clear(resource_manifest->linebuf); - string_clear(resource_manifest->entry.name); + furi_string_free(resource_manifest->linebuf); + furi_string_free(resource_manifest->entry.name); buffered_file_stream_close(resource_manifest->stream); stream_free(resource_manifest->stream); free(resource_manifest); @@ -45,7 +45,7 @@ bool resource_manifest_reader_open(ResourceManifestReader* resource_manifest, co ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* resource_manifest) { furi_assert(resource_manifest); - string_reset(resource_manifest->entry.name); + furi_string_reset(resource_manifest->entry.name); resource_manifest->entry.type = ResourceManifestEntryTypeUnknown; resource_manifest->entry.size = 0; memset(resource_manifest->entry.hash, 0, sizeof(resource_manifest->entry.hash)); @@ -56,9 +56,9 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res } /* Trim end of line */ - string_strim(resource_manifest->linebuf); + furi_string_trim(resource_manifest->linebuf); - char type_code = string_get_char(resource_manifest->linebuf, 0); + char type_code = furi_string_get_char(resource_manifest->linebuf, 0); switch(type_code) { case 'F': resource_manifest->entry.type = ResourceManifestEntryTypeFile; @@ -75,9 +75,9 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res F::: */ /* Remove entry type code */ - string_right(resource_manifest->linebuf, 2); + furi_string_right(resource_manifest->linebuf, 2); - if(string_search_char(resource_manifest->linebuf, ':') != + if(furi_string_search_char(resource_manifest->linebuf, ':') != sizeof(resource_manifest->entry.hash) * 2) { /* Invalid hash */ continue; @@ -85,27 +85,27 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res /* Read hash */ hex_chars_to_uint8( - string_get_cstr(resource_manifest->linebuf), resource_manifest->entry.hash); + furi_string_get_cstr(resource_manifest->linebuf), resource_manifest->entry.hash); /* Remove hash */ - string_right( + furi_string_right( resource_manifest->linebuf, sizeof(resource_manifest->entry.hash) * 2 + 1); - resource_manifest->entry.size = atoi(string_get_cstr(resource_manifest->linebuf)); + resource_manifest->entry.size = atoi(furi_string_get_cstr(resource_manifest->linebuf)); /* Remove size */ - size_t offs = string_search_char(resource_manifest->linebuf, ':'); - string_right(resource_manifest->linebuf, offs + 1); + size_t offs = furi_string_search_char(resource_manifest->linebuf, ':'); + furi_string_right(resource_manifest->linebuf, offs + 1); - string_set(resource_manifest->entry.name, resource_manifest->linebuf); + furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf); } else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) { /* Parse directory entry D: */ /* Remove entry type code */ - string_right(resource_manifest->linebuf, 2); + furi_string_right(resource_manifest->linebuf, 2); - string_set(resource_manifest->entry.name, resource_manifest->linebuf); + furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf); } return &resource_manifest->entry; diff --git a/lib/update_util/resources/manifest.h b/lib/update_util/resources/manifest.h index 092b7bad..8baa1613 100644 --- a/lib/update_util/resources/manifest.h +++ b/lib/update_util/resources/manifest.h @@ -2,7 +2,6 @@ #include -#include #include #include @@ -18,7 +17,7 @@ typedef enum { typedef struct { ResourceManifestEntryType type; - string_t name; + FuriString* name; uint32_t size; uint8_t hash[16]; } ResourceManifestEntry; diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 1b205d9c..795fdd5e 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -21,12 +21,12 @@ UpdateManifest* update_manifest_alloc() { UpdateManifest* update_manifest = malloc(sizeof(UpdateManifest)); - string_init(update_manifest->version); - string_init(update_manifest->firmware_dfu_image); - string_init(update_manifest->radio_image); - string_init(update_manifest->staged_loader_file); - string_init(update_manifest->resource_bundle); - string_init(update_manifest->splash_file); + update_manifest->version = furi_string_alloc(); + update_manifest->firmware_dfu_image = furi_string_alloc(); + update_manifest->radio_image = furi_string_alloc(); + update_manifest->staged_loader_file = furi_string_alloc(); + update_manifest->resource_bundle = furi_string_alloc(); + update_manifest->splash_file = furi_string_alloc(); update_manifest->target = 0; update_manifest->manifest_version = 0; memset(update_manifest->ob_reference.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); @@ -38,12 +38,12 @@ UpdateManifest* update_manifest_alloc() { void update_manifest_free(UpdateManifest* update_manifest) { furi_assert(update_manifest); - string_clear(update_manifest->version); - string_clear(update_manifest->firmware_dfu_image); - string_clear(update_manifest->radio_image); - string_clear(update_manifest->staged_loader_file); - string_clear(update_manifest->resource_bundle); - string_clear(update_manifest->splash_file); + furi_string_free(update_manifest->version); + furi_string_free(update_manifest->firmware_dfu_image); + furi_string_free(update_manifest->radio_image); + furi_string_free(update_manifest->staged_loader_file); + furi_string_free(update_manifest->resource_bundle); + furi_string_free(update_manifest->splash_file); free(update_manifest); } @@ -52,10 +52,10 @@ static bool furi_assert(update_manifest); furi_assert(flipper_file); - string_t filetype; + FuriString* filetype; // TODO: compare filetype? - string_init(filetype); + filetype = furi_string_alloc(); update_manifest->valid = flipper_format_read_header(flipper_file, filetype, &update_manifest->manifest_version) && flipper_format_read_string(flipper_file, MANIFEST_KEY_INFO, update_manifest->version) && @@ -68,7 +68,7 @@ static bool MANIFEST_KEY_LOADER_CRC, (uint8_t*)&update_manifest->staged_loader_crc, sizeof(uint32_t)); - string_clear(filetype); + furi_string_free(filetype); if(update_manifest->valid) { /* Optional fields - we can have dfu, radio, resources, or any combination */ @@ -114,9 +114,9 @@ static bool flipper_file, MANIFEST_KEY_SPLASH_FILE, update_manifest->splash_file); update_manifest->valid = - (!string_empty_p(update_manifest->firmware_dfu_image) || - !string_empty_p(update_manifest->radio_image) || - !string_empty_p(update_manifest->resource_bundle)); + (!furi_string_empty(update_manifest->firmware_dfu_image) || + !furi_string_empty(update_manifest->radio_image) || + !furi_string_empty(update_manifest->resource_bundle)); } return update_manifest->valid; diff --git a/lib/update_util/update_manifest.h b/lib/update_util/update_manifest.h index 8f385947..c26e4f87 100644 --- a/lib/update_util/update_manifest.h +++ b/lib/update_util/update_manifest.h @@ -6,7 +6,7 @@ extern "C" { #include #include -#include +#include #include /* Paths don't include /ext -- because at startup SD card is mounted as FS root */ @@ -28,20 +28,20 @@ _Static_assert(sizeof(UpdateManifestRadioVersion) == 6, "UpdateManifestRadioVers typedef struct { uint32_t manifest_version; - string_t version; + FuriString* version; uint32_t target; - string_t staged_loader_file; + FuriString* staged_loader_file; uint32_t staged_loader_crc; - string_t firmware_dfu_image; - string_t radio_image; + FuriString* firmware_dfu_image; + FuriString* radio_image; uint32_t radio_address; UpdateManifestRadioVersion radio_version; uint32_t radio_crc; - string_t resource_bundle; + FuriString* resource_bundle; FuriHalFlashRawOptionByteData ob_reference; FuriHalFlashRawOptionByteData ob_compare_mask; FuriHalFlashRawOptionByteData ob_write_mask; - string_t splash_file; + FuriString* splash_file; bool valid; } UpdateManifest; diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index 56f412a9..3a44605e 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -34,9 +33,9 @@ const char* update_operation_describe_preparation_result(const UpdatePrepareResu } } -static bool update_operation_get_current_package_path_rtc(Storage* storage, string_t out_path) { +static bool update_operation_get_current_package_path_rtc(Storage* storage, FuriString* out_path) { const uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); - string_set_str(out_path, UPDATE_ROOT_DIR); + furi_string_set(out_path, UPDATE_ROOT_DIR); if(update_index == UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC) { return true; } @@ -63,7 +62,7 @@ static bool update_operation_get_current_package_path_rtc(Storage* storage, stri free(name_buffer); storage_file_free(dir); if(!found) { - string_reset(out_path); + furi_string_reset(out_path); } return found; @@ -72,8 +71,8 @@ static bool update_operation_get_current_package_path_rtc(Storage* storage, stri #define UPDATE_FILE_POINTER_FN EXT_PATH(UPDATE_MANIFEST_POINTER_FILE_NAME) #define UPDATE_MANIFEST_MAX_PATH_LEN 256u -bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path) { - string_reset(out_path); +bool update_operation_get_current_package_manifest_path(Storage* storage, FuriString* out_path) { + furi_string_reset(out_path); if(storage_common_stat(storage, UPDATE_FILE_POINTER_FN, NULL) == FSE_OK) { char* manifest_name_buffer = malloc(UPDATE_MANIFEST_MAX_PATH_LEN); File* upd_file = NULL; @@ -91,23 +90,23 @@ bool update_operation_get_current_package_manifest_path(Storage* storage, string if(storage_common_stat(storage, manifest_name_buffer, NULL) != FSE_OK) { break; } - string_set_str(out_path, manifest_name_buffer); + furi_string_set(out_path, manifest_name_buffer); } while(0); free(manifest_name_buffer); storage_file_free(upd_file); } else { /* legacy, will be deprecated */ - string_t rtcpath; - string_init(rtcpath); + FuriString* rtcpath; + rtcpath = furi_string_alloc(); do { if(!update_operation_get_current_package_path_rtc(storage, rtcpath)) { break; } - path_concat(string_get_cstr(rtcpath), UPDATE_MANIFEST_DEFAULT_NAME, out_path); + path_concat(furi_string_get_cstr(rtcpath), UPDATE_MANIFEST_DEFAULT_NAME, out_path); } while(0); - string_clear(rtcpath); + furi_string_free(rtcpath); } - return !string_empty_p(out_path); + return !furi_string_empty(out_path); } static bool update_operation_persist_manifest_path(Storage* storage, const char* manifest_path) { @@ -141,8 +140,8 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { File* file = storage_file_alloc(storage); uint64_t free_int_space; - string_t stage_path; - string_init(stage_path); + FuriString* stage_path; + stage_path = furi_string_alloc(); do { if((storage_common_fs_info(storage, STORAGE_INT_PATH_PREFIX, NULL, &free_int_space) != FSE_OK) || @@ -171,9 +170,10 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { } path_extract_dirname(manifest_file_path, stage_path); - path_append(stage_path, string_get_cstr(manifest->staged_loader_file)); + path_append(stage_path, furi_string_get_cstr(manifest->staged_loader_file)); - if(!storage_file_open(file, string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { + if(!storage_file_open( + file, furi_string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { result = UpdatePrepareResultStageMissing; break; } @@ -193,7 +193,7 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); } while(false); - string_clear(stage_path); + furi_string_free(stage_path); storage_file_free(file); update_manifest_free(manifest); diff --git a/lib/update_util/update_operation.h b/lib/update_util/update_operation.h index 056520e1..65abf8e1 100644 --- a/lib/update_util/update_operation.h +++ b/lib/update_util/update_operation.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #ifdef __cplusplus @@ -19,7 +18,7 @@ extern "C" { * May be empty if update is in root update directory * @return bool if supplied path is valid and out_manifest_dir contains dir to apply */ -bool update_operation_get_package_dir_name(const char* full_path, string_t out_manifest_dir); +bool update_operation_get_package_dir_name(const char* full_path, FuriString* out_manifest_dir); /* When updating this enum, also update assets/protobuf/system.proto */ typedef enum { @@ -51,7 +50,7 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path); * @param out_path Path to manifest. Must be initialized * @return true if path was restored successfully */ -bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path); +bool update_operation_get_current_package_manifest_path(Storage* storage, FuriString* out_path); /* * Checks if an update operation step is pending after reset diff --git a/scripts/assets.py b/scripts/assets.py index 9b4ee5b6..75bebcfb 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -14,7 +14,7 @@ ICONS_TEMPLATE_H_HEADER = """#pragma once """ ICONS_TEMPLATE_H_ICON_NAME = "extern const Icon {name};\n" -ICONS_TEMPLATE_C_HEADER = """#include \"assets_icons.h\" +ICONS_TEMPLATE_C_HEADER = """#include "{assets_filename}.h" #include @@ -33,6 +33,13 @@ class Main(App): ) self.parser_icons.add_argument("input_directory", help="Source directory") self.parser_icons.add_argument("output_directory", help="Output directory") + self.parser_icons.add_argument( + "--filename", + help="Base filename for file with icon data", + required=False, + default="assets_icons", + ) + self.parser_icons.set_defaults(func=self.icons) self.parser_manifest = self.subparsers.add_parser( @@ -102,13 +109,15 @@ class Main(App): return extension in ICONS_SUPPORTED_FORMATS def icons(self): - self.logger.debug(f"Converting icons") + self.logger.debug("Converting icons") icons_c = open( - os.path.join(self.args.output_directory, "assets_icons.c"), + os.path.join(self.args.output_directory, f"{self.args.filename}.c"), "w", newline="\n", ) - icons_c.write(ICONS_TEMPLATE_C_HEADER) + icons_c.write( + ICONS_TEMPLATE_C_HEADER.format(assets_filename=self.args.filename) + ) icons = [] # Traverse icons tree, append image data to source file for dirpath, dirnames, filenames in os.walk(self.args.input_directory): @@ -194,7 +203,7 @@ class Main(App): # Create Public Header self.logger.debug(f"Creating header") icons_h = open( - os.path.join(self.args.output_directory, "assets_icons.h"), + os.path.join(self.args.output_directory, f"{self.args.filename}.h"), "w", newline="\n", ) diff --git a/site_scons/fbt/__init__.py b/scripts/fbt/__init__.py similarity index 100% rename from site_scons/fbt/__init__.py rename to scripts/fbt/__init__.py diff --git a/site_scons/fbt/appmanifest.py b/scripts/fbt/appmanifest.py similarity index 91% rename from site_scons/fbt/appmanifest.py rename to scripts/fbt/appmanifest.py index a1132eea..de7c6b68 100644 --- a/site_scons/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -23,6 +23,22 @@ class FlipperAppType(Enum): @dataclass class FlipperApplication: + @dataclass + class ExternallyBuiltFile: + path: str + command: str + + @dataclass + class Library: + name: str + fap_include_paths: List[str] = field(default_factory=lambda: ["."]) + sources: List[str] = field(default_factory=lambda: ["*.c*"]) + cflags: List[str] = field(default_factory=list) + cdefines: List[str] = field(default_factory=list) + cincludes: List[str] = field(default_factory=list) + + PRIVATE_FIELD_PREFIX = "_" + appid: str apptype: FlipperAppType name: Optional[str] = "" @@ -45,6 +61,9 @@ class FlipperApplication: fap_description: str = "" fap_author: str = "" fap_weburl: str = "" + fap_icon_assets: Optional[str] = None + fap_extbuild: List[ExternallyBuiltFile] = field(default_factory=list) + fap_private_libs: List[Library] = field(default_factory=list) # Internally used by fbt _appdir: Optional[object] = None _apppath: Optional[str] = None @@ -88,6 +107,12 @@ class AppManager: ), ) + def ExtFile(*args, **kw): + return FlipperApplication.ExternallyBuiltFile(*args, **kw) + + def Lib(*args, **kw): + return FlipperApplication.Library(*args, **kw) + try: with open(app_manifest_path, "rt") as manifest_file: exec(manifest_file.read()) diff --git a/site_scons/fbt/elfmanifest.py b/scripts/fbt/elfmanifest.py similarity index 100% rename from site_scons/fbt/elfmanifest.py rename to scripts/fbt/elfmanifest.py diff --git a/site_scons/fbt/sdk.py b/scripts/fbt/sdk.py similarity index 100% rename from site_scons/fbt/sdk.py rename to scripts/fbt/sdk.py diff --git a/site_scons/fbt/util.py b/scripts/fbt/util.py similarity index 58% rename from site_scons/fbt/util.py rename to scripts/fbt/util.py index 8d8af518..baa4ddfe 100644 --- a/site_scons/fbt/util.py +++ b/scripts/fbt/util.py @@ -41,25 +41,3 @@ def link_dir(target_path, source_path, is_windows): def single_quote(arg_list): return " ".join(f"'{arg}'" if " " in arg else str(arg) for arg in arg_list) - - -def link_elf_dir_as_latest(env, elf_node): - elf_dir = elf_node.Dir(".") - latest_dir = env.Dir("#build/latest") - print(f"Setting {elf_dir} as latest built dir (./build/latest/)") - return link_dir(latest_dir.abspath, elf_dir.abspath, env["PLATFORM"] == "win32") - - -def should_gen_cdb_and_link_dir(env, requested_targets): - explicitly_building_updater = False - # Hacky way to check if updater-related targets were requested - for build_target in requested_targets: - if "updater" in str(build_target): - explicitly_building_updater = True - - is_updater = not env["IS_BASE_FIRMWARE"] - # If updater is explicitly requested, link to the latest updater - # Otherwise, link to firmware - return (is_updater and explicitly_building_updater) or ( - not is_updater and not explicitly_building_updater - ) diff --git a/site_scons/fbt/version.py b/scripts/fbt/version.py similarity index 100% rename from site_scons/fbt/version.py rename to scripts/fbt/version.py diff --git a/site_scons/site_tools/blackmagic.py b/scripts/fbt_tools/blackmagic.py similarity index 100% rename from site_scons/site_tools/blackmagic.py rename to scripts/fbt_tools/blackmagic.py diff --git a/site_scons/site_tools/ccache.py b/scripts/fbt_tools/ccache.py similarity index 100% rename from site_scons/site_tools/ccache.py rename to scripts/fbt_tools/ccache.py diff --git a/site_scons/site_tools/crosscc.py b/scripts/fbt_tools/crosscc.py similarity index 100% rename from site_scons/site_tools/crosscc.py rename to scripts/fbt_tools/crosscc.py diff --git a/site_scons/site_tools/fbt_apps.py b/scripts/fbt_tools/fbt_apps.py similarity index 100% rename from site_scons/site_tools/fbt_apps.py rename to scripts/fbt_tools/fbt_apps.py diff --git a/site_scons/site_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py similarity index 82% rename from site_scons/site_tools/fbt_assets.py rename to scripts/fbt_tools/fbt_assets.py index 87794847..f058d15f 100644 --- a/site_scons/site_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -10,8 +10,8 @@ import subprocess def icons_emitter(target, source, env): target = [ - "compiled/assets_icons.c", - "compiled/assets_icons.h", + target[0].File(env.subst("${ICON_FILE_NAME}.c")), + target[0].File(env.subst("${ICON_FILE_NAME}.h")), ] source = env.GlobRecursive("*.*", env["ICON_SRC_DIR"]) return target, source @@ -99,17 +99,41 @@ def proto_ver_generator(target, source, env): file.write("\n".join(version_file_data)) +def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"): + # Gathering icons sources + icons_src = env.GlobRecursive("*.png", source_dir) + icons_src += env.GlobRecursive("frame_rate", source_dir) + + icons = env.IconBuilder( + target_dir, + ICON_SRC_DIR=source_dir, + ICON_FILE_NAME=icon_bundle_name, + ) + env.Depends(icons, icons_src) + return icons + + def generate(env): env.SetDefault( ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py", NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py", ) + env.AddMethod(CompileIcons) + + if not env["VERBOSE"]: + env.SetDefault( + ICONSCOMSTR="\tICONS\t${TARGET}", + PROTOCOMSTR="\tPROTO\t${SOURCE}", + DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}", + RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}", + PBVERCOMSTR="\tPBVER\t${TARGET}", + ) env.Append( BUILDERS={ "IconBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir}', + '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir} --filename ${ICON_FILE_NAME}', "${ICONSCOMSTR}", ), emitter=icons_emitter, diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py new file mode 100644 index 00000000..3e7b0701 --- /dev/null +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -0,0 +1,41 @@ +def generate(env, **kw): + env.SetDefault( + OPENOCD_GDB_PIPE=[ + "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" + ], + 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", + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_dist.py b/scripts/fbt_tools/fbt_dist.py similarity index 98% rename from site_scons/site_tools/fbt_dist.py rename to scripts/fbt_tools/fbt_dist.py index 2b5c83df..853013e9 100644 --- a/site_scons/site_tools/fbt_dist.py +++ b/scripts/fbt_tools/fbt_dist.py @@ -136,7 +136,6 @@ def generate(env): "CoproBuilder": Builder( action=Action( [ - Mkdir("$TARGET"), '${PYTHON3} "${ROOT_DIR.abspath}/scripts/assets.py" ' "copro ${COPRO_CUBE_DIR} " "${TARGET} ${COPRO_MCU_FAMILY} " @@ -145,7 +144,7 @@ def generate(env): '--stack_file="${COPRO_STACK_BIN}" ' "--stack_addr=${COPRO_STACK_ADDR} ", ], - "", + "\tCOPRO\t${TARGET}", ) ), } diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py new file mode 100644 index 00000000..34fb942a --- /dev/null +++ b/scripts/fbt_tools/fbt_extapps.py @@ -0,0 +1,259 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Errors import UserError +import SCons.Warnings + +import os +import pathlib +from fbt.elfmanifest import assemble_manifest_data +from fbt.appmanifest import FlipperApplication, FlipperManifestException +from fbt.sdk import SdkCache +import itertools + + +def BuildAppElf(env, app): + ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR") + app_work_dir = os.path.join(ext_apps_work_dir, app.appid) + + env.VariantDir(app_work_dir, app._appdir, duplicate=False) + + app_env = env.Clone(FAP_SRC_DIR=app._appdir, FAP_WORK_DIR=app_work_dir) + + app_alias = f"fap_{app.appid}" + + # Deprecation stub + legacy_app_taget_name = f"{app_env['FIRMWARE_BUILD_CFG']}_{app.appid}" + + def legacy_app_build_stub(**kw): + raise UserError( + f"Target name '{legacy_app_taget_name}' is deprecated, use '{app_alias}' instead" + ) + + app_env.PhonyTarget(legacy_app_taget_name, Action(legacy_app_build_stub, None)) + + externally_built_files = [] + if app.fap_extbuild: + for external_file_def in app.fap_extbuild: + externally_built_files.append(external_file_def.path) + app_env.Alias(app_alias, external_file_def.path) + app_env.AlwaysBuild( + app_env.Command( + external_file_def.path, + None, + Action( + external_file_def.command, + "" if app_env["VERBOSE"] else "\tEXTCMD\t${TARGET}", + ), + ) + ) + + if app.fap_icon_assets: + app_env.CompileIcons( + app_env.Dir(app_work_dir), + app._appdir.Dir(app.fap_icon_assets), + icon_bundle_name=f"{app.appid}_icons", + ) + + private_libs = [] + + for lib_def in app.fap_private_libs: + lib_src_root_path = os.path.join(app_work_dir, "lib", lib_def.name) + app_env.AppendUnique( + CPPPATH=list( + app_env.Dir(lib_src_root_path).Dir(incpath).srcnode() + for incpath in lib_def.fap_include_paths + ), + ) + + lib_sources = list( + itertools.chain.from_iterable( + app_env.GlobRecursive(source_type, lib_src_root_path) + for source_type in lib_def.sources + ) + ) + if len(lib_sources) == 0: + raise UserError(f"No sources gathered for private library {lib_def}") + + private_lib_env = app_env.Clone() + private_lib_env.AppendUnique( + CCFLAGS=[ + *lib_def.cflags, + ], + CPPDEFINES=lib_def.cdefines, + CPPPATH=list( + os.path.join(app._appdir.path, cinclude) + for cinclude in lib_def.cincludes + ), + ) + + lib = private_lib_env.StaticLibrary( + os.path.join(app_work_dir, lib_def.name), + lib_sources, + ) + private_libs.append(lib) + + app_sources = list( + itertools.chain.from_iterable( + app_env.GlobRecursive( + source_type, + app_work_dir, + exclude="lib", + ) + for source_type in app.sources + ) + ) + + app_env.Append( + LIBS=[*app.fap_libs, *private_libs], + CPPPATH=env.Dir(app_work_dir), + ) + + app_elf_raw = app_env.Program( + os.path.join(ext_apps_work_dir, f"{app.appid}_d"), + app_sources, + APP_ENTRY=app.entry_point, + ) + + app_env.Clean(app_elf_raw, [*externally_built_files, app_env.Dir(app_work_dir)]) + + app_elf_dump = app_env.ObjDump(app_elf_raw) + app_env.Alias(f"{app_alias}_list", app_elf_dump) + + app_elf_augmented = app_env.EmbedAppMetadata( + os.path.join(ext_apps_work_dir, app.appid), + app_elf_raw, + APP=app, + ) + + manifest_vals = { + k: v + for k, v in vars(app).items() + if not k.startswith(FlipperApplication.PRIVATE_FIELD_PREFIX) + } + + app_env.Depends( + app_elf_augmented, + [app_env["SDK_DEFINITION"], app_env.Value(manifest_vals)], + ) + if app.fap_icon: + app_env.Depends( + app_elf_augmented, + app_env.File(f"{app._apppath}/{app.fap_icon}"), + ) + + app_elf_import_validator = app_env.ValidateAppImports(app_elf_augmented) + app_env.AlwaysBuild(app_elf_import_validator) + app_env.Alias(app_alias, app_elf_import_validator) + return (app_elf_augmented, app_elf_raw, app_elf_import_validator) + + +def prepare_app_metadata(target, source, env): + sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=True) + + if not sdk_cache.is_buildable(): + raise UserError( + "SDK version is not finalized, please review changes and re-run operation" + ) + + app = env["APP"] + meta_file_name = source[0].path + ".meta" + with open(meta_file_name, "wb") as f: + # f.write(f"hello this is {app}") + f.write( + assemble_manifest_data( + app_manifest=app, + hardware_target=int(env.subst("$TARGET_HW")), + sdk_version=sdk_cache.version.as_int(), + ) + ) + + +def validate_app_imports(target, source, env): + sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=False) + app_syms = set() + with open(target[0].path, "rt") as f: + for line in f: + app_syms.add(line.split()[0]) + unresolved_syms = app_syms - sdk_cache.get_valid_names() + if unresolved_syms: + SCons.Warnings.warn( + SCons.Warnings.LinkWarning, + f"\033[93m{source[0].path}: app won't run. Unresolved symbols: \033[95m{unresolved_syms}\033[0m", + ) + + +def GetExtAppFromPath(env, app_dir): + if not app_dir: + raise UserError("APPSRC= not set") + + appmgr = env["APPMGR"] + + app = None + try: + # Maybe used passed an appid? + app = appmgr.get(app_dir) + except FlipperManifestException as _: + # Look up path components in known app dits + for dir_part in reversed(pathlib.Path(app_dir).parts): + if app := appmgr.find_by_appdir(dir_part): + break + + if not app: + raise UserError(f"Failed to resolve application for given APPSRC={app_dir}") + + app_elf = env["_extapps"]["compact"].get(app.appid, None) + if not app_elf: + raise UserError( + f"Application {app.appid} is not configured for building as external" + ) + + app_validator = env["_extapps"]["validators"].get(app.appid, None) + + return (app, app_elf[0], app_validator[0]) + + +def generate(env, **kw): + env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR")) + # env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), env.Dir("#"), duplicate=False) + + env.AddMethod(BuildAppElf) + env.AddMethod(GetExtAppFromPath) + env.Append( + BUILDERS={ + "EmbedAppMetadata": Builder( + action=[ + Action(prepare_app_metadata, "$APPMETA_COMSTR"), + Action( + "${OBJCOPY} " + "--remove-section .ARM.attributes " + "--add-section .fapmeta=${SOURCE}.meta " + "--set-section-flags .fapmeta=contents,noload,readonly,data " + "--strip-debug --strip-unneeded " + "--add-gnu-debuglink=${SOURCE} " + "${SOURCES} ${TARGET}", + "$APPMETAEMBED_COMSTR", + ), + ], + suffix=".fap", + src_suffix=".elf", + ), + "ValidateAppImports": Builder( + action=[ + Action( + "@${NM} -P -u ${SOURCE} > ${TARGET}", + None, # "$APPDUMP_COMSTR", + ), + Action( + validate_app_imports, + "$APPCHECK_COMSTR", + ), + ], + suffix=".impsyms", + src_suffix=".fap", + ), + } + ) + + +def exists(env): + return True diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py new file mode 100644 index 00000000..0475f51b --- /dev/null +++ b/scripts/fbt_tools/fbt_help.py @@ -0,0 +1,44 @@ +targets_help = """Configuration variables: +""" + +tail_help = """ + +TASKS: +Building: + firmware_all, fw_dist: + Build firmware; create distribution package + faps, fap_dist: + Build all FAP apps + fap_{APPID}, launch_app APPSRC={APPID}: + Build FAP app with appid={APPID}; upload & start it over USB + +Flashing & debugging: + flash, flash_blackmagic, jflash: + Flash firmware to target using debug probe + flash_usb, flash_usb_full: + Install firmware using self-update package + debug, debug_other, blackmagic: + Start GDB + +Other: + cli: + Open a Flipper CLI session over USB + firmware_cdb, updater_cdb: + Generate сompilation_database.json + lint, lint_py: + run linters + format, format_py: + run code formatters + +For more targets & info, see documentation/fbt.md +""" + + +def generate(env, **kw): + vars = kw["vars"] + basic_help = vars.GenerateHelpText(env) + env.Help(targets_help + basic_help + tail_help) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py similarity index 71% rename from site_scons/site_tools/fbt_sdk.py rename to scripts/fbt_tools/fbt_sdk.py index f6c2d452..ed0abdff 100644 --- a/site_scons/site_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -9,10 +9,32 @@ from SCons.Util import LogicalLines import os.path import posixpath import pathlib +import json from fbt.sdk import SdkCollector, SdkCache +def ProcessSdkDepends(env, filename): + try: + with open(filename, "r") as fin: + lines = LogicalLines(fin).readlines() + except IOError: + return [] + + _, depends = lines[0].split(":", 1) + depends = depends.split() + depends.pop(0) # remove the .c file + depends = list( + # Don't create dependency on non-existing files + # (e.g. when they were renamed since last build) + filter( + lambda file: file.exists(), + (env.File(f"#{path}") for path in depends), + ) + ) + return depends + + def prebuild_sdk_emitter(target, source, env): target.append(env.ChangeFileExtension(target[0], ".d")) target.append(env.ChangeFileExtension(target[0], ".i.c")) @@ -25,6 +47,25 @@ def prebuild_sdk_create_origin_file(target, source, env): sdk_c.write("\n".join(f"#include <{h.path}>" for h in env["SDK_HEADERS"])) +class SdkMeta: + def __init__(self, env): + self.env = env + + def save_to(self, json_manifest_path: str): + meta_contents = { + "sdk_symbols": self.env["SDK_DEFINITION"].name, + "cc_args": self._wrap_scons_vars("$CCFLAGS $_CCCOMCOM"), + "cpp_args": self._wrap_scons_vars("$CXXFLAGS $CCFLAGS $_CCCOMCOM"), + "linker_args": self._wrap_scons_vars("$LINKFLAGS"), + } + with open(json_manifest_path, "wt") as f: + json.dump(meta_contents, f, indent=4) + + def _wrap_scons_vars(self, vars: str): + expanded_vars = self.env.subst(vars, target=Entry("dummy")) + return expanded_vars.replace("\\", "/") + + class SdkTreeBuilder: def __init__(self, env, target, source) -> None: self.env = env @@ -34,8 +75,9 @@ class SdkTreeBuilder: self.header_depends = [] self.header_dirs = [] - self.target_sdk_dir = env.subst("f${TARGET_HW}_sdk") - self.sdk_deploy_dir = target[0].Dir(self.target_sdk_dir) + self.target_sdk_dir_name = env.subst("f${TARGET_HW}_sdk") + self.sdk_root_dir = target[0].Dir(".") + self.sdk_deploy_dir = self.sdk_root_dir.Dir(self.target_sdk_dir_name) def _parse_sdk_depends(self): deps_file = self.source[0] @@ -50,7 +92,7 @@ class SdkTreeBuilder: ) def _generate_sdk_meta(self): - filtered_paths = [self.target_sdk_dir] + filtered_paths = [self.target_sdk_dir_name] full_fw_paths = list( map( os.path.normpath, @@ -62,17 +104,18 @@ class SdkTreeBuilder: for dir in full_fw_paths: if dir in sdk_dirs: filtered_paths.append( - posixpath.normpath(posixpath.join(self.target_sdk_dir, dir)) + posixpath.normpath(posixpath.join(self.target_sdk_dir_name, dir)) ) sdk_env = self.env.Clone() sdk_env.Replace(CPPPATH=filtered_paths) - with open(self.target[0].path, "wt") as f: - cmdline_options = sdk_env.subst( - "$CCFLAGS $_CCCOMCOM", target=Entry("dummy") - ) - f.write(cmdline_options.replace("\\", "/")) - f.write("\n") + meta = SdkMeta(sdk_env) + meta.save_to(self.target[0].path) + + def emitter(self, target, source, env): + target_folder = target[0] + target = [target_folder.File("sdk.opts")] + return target, source def _create_deploy_commands(self): dirs_to_create = set( @@ -81,13 +124,17 @@ class SdkTreeBuilder: actions = [ Delete(self.sdk_deploy_dir), Mkdir(self.sdk_deploy_dir), + Copy( + self.sdk_root_dir, + self.env["SDK_DEFINITION"], + ), ] actions += [Mkdir(d) for d in dirs_to_create] actions += [ - Copy( - self.sdk_deploy_dir.File(h).path, - h, + Action( + Copy(self.sdk_deploy_dir.File(h).path, h), + # f"Copy {h} to {self.sdk_deploy_dir}", ) for h in self.header_depends ] @@ -108,6 +155,11 @@ def deploy_sdk_tree(target, source, env, for_signature): return sdk_tree.generate_actions() +def deploy_sdk_tree_emitter(target, source, env): + sdk_tree = SdkTreeBuilder(env, target, source) + return sdk_tree.emitter(target, source, env) + + def gen_sdk_data(sdk_cache: SdkCache): api_def = [] api_def.extend( @@ -165,6 +217,7 @@ def generate_sdk_symbols(source, target, env): def generate(env, **kw): + env.AddMethod(ProcessSdkDepends) env.Append( BUILDERS={ "SDKPrebuilder": Builder( @@ -183,6 +236,7 @@ def generate(env, **kw): ), "SDKTree": Builder( generator=deploy_sdk_tree, + emitter=deploy_sdk_tree_emitter, src_suffix=".d", ), "SDKSymUpdater": Builder( diff --git a/site_scons/site_tools/fbt_version.py b/scripts/fbt_tools/fbt_version.py similarity index 100% rename from site_scons/site_tools/fbt_version.py rename to scripts/fbt_tools/fbt_version.py diff --git a/site_scons/site_tools/fwbin.py b/scripts/fbt_tools/fwbin.py similarity index 100% rename from site_scons/site_tools/fwbin.py rename to scripts/fbt_tools/fwbin.py diff --git a/site_scons/site_tools/gdb.py b/scripts/fbt_tools/gdb.py similarity index 100% rename from site_scons/site_tools/gdb.py rename to scripts/fbt_tools/gdb.py diff --git a/site_scons/site_tools/jflash.py b/scripts/fbt_tools/jflash.py similarity index 100% rename from site_scons/site_tools/jflash.py rename to scripts/fbt_tools/jflash.py diff --git a/site_scons/site_tools/objdump.py b/scripts/fbt_tools/objdump.py similarity index 100% rename from site_scons/site_tools/objdump.py rename to scripts/fbt_tools/objdump.py diff --git a/site_scons/site_tools/openocd.py b/scripts/fbt_tools/openocd.py similarity index 100% rename from site_scons/site_tools/openocd.py rename to scripts/fbt_tools/openocd.py diff --git a/site_scons/site_tools/python3.py b/scripts/fbt_tools/python3.py similarity index 100% rename from site_scons/site_tools/python3.py rename to scripts/fbt_tools/python3.py diff --git a/site_scons/site_tools/sconsmodular.py b/scripts/fbt_tools/sconsmodular.py similarity index 100% rename from site_scons/site_tools/sconsmodular.py rename to scripts/fbt_tools/sconsmodular.py diff --git a/site_scons/site_tools/sconsrecursiveglob.py b/scripts/fbt_tools/sconsrecursiveglob.py similarity index 100% rename from site_scons/site_tools/sconsrecursiveglob.py rename to scripts/fbt_tools/sconsrecursiveglob.py diff --git a/site_scons/site_tools/strip.py b/scripts/fbt_tools/strip.py similarity index 100% rename from site_scons/site_tools/strip.py rename to scripts/fbt_tools/strip.py diff --git a/scripts/flipper/assets/copro.py b/scripts/flipper/assets/copro.py index 0c78e889..d39f3033 100644 --- a/scripts/flipper/assets/copro.py +++ b/scripts/flipper/assets/copro.py @@ -1,10 +1,9 @@ import logging -import datetime -import shutil import json -from os.path import basename - +from io import BytesIO +import tarfile import xml.etree.ElementTree as ET + from flipper.utils import * from flipper.assets.coprobin import CoproBinary, get_stack_type @@ -51,20 +50,19 @@ class Copro: raise Exception(f"Unsupported cube version") self.version = cube_version + @staticmethod + def _getFileName(name): + return os.path.join("core2_firmware", name) + def addFile(self, array, filename, **kwargs): source_file = os.path.join(self.mcu_copro, filename) - destination_file = os.path.join(self.output_dir, filename) - shutil.copyfile(source_file, destination_file) - array.append( - {"name": filename, "sha256": file_sha256(destination_file), **kwargs} - ) + self.output_tar.add(source_file, arcname=self._getFileName(filename)) + array.append({"name": filename, "sha256": file_sha256(source_file), **kwargs}) + + def bundle(self, output_file, stack_file_name, stack_type, stack_addr=None): + self.output_tar = tarfile.open(output_file, "w:gz", format=tarfile.USTAR_FORMAT) - def bundle(self, output_dir, stack_file_name, stack_type, stack_addr=None): - if not os.path.isdir(output_dir): - raise Exception(f'"{output_dir}" doesn\'t exists') - self.output_dir = output_dir stack_file = os.path.join(self.mcu_copro, stack_file_name) - manifest_file = os.path.join(self.output_dir, "Manifest.json") # Form Manifest manifest = dict(MANIFEST_TEMPLATE) manifest["manifest"]["timestamp"] = timestamp() @@ -105,6 +103,10 @@ class Copro: stack_file_name, address=f"0x{stack_addr:X}", ) - # Save manifest to - with open(manifest_file, "w", newline="\n") as file: - json.dump(manifest, file) + + # Save manifest + manifest_data = json.dumps(manifest, indent=4).encode("utf-8") + info = tarfile.TarInfo(self._getFileName("Manifest.json")) + info.size = len(manifest_data) + self.output_tar.addfile(info, BytesIO(manifest_data)) + self.output_tar.close() diff --git a/scripts/guruguru.py b/scripts/guruguru.py index 3560bcd9..c227e17e 100755 --- a/scripts/guruguru.py +++ b/scripts/guruguru.py @@ -17,7 +17,7 @@ class Main(App): async def rebuild(self, line): self.clearConsole() self.logger.info(f"Triggered by: {line}") - proc = await asyncio.create_subprocess_exec("make") + proc = await asyncio.create_subprocess_exec("./fbt") await proc.wait() await asyncio.sleep(1) self.is_building = False diff --git a/scripts/lint.py b/scripts/lint.py index 30a5699a..c178c876 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -54,6 +54,10 @@ class Main(App): output = [] for folder in folders: for dirpath, dirnames, filenames in os.walk(folder): + # Skipping 3rd-party code - usually resides in subfolder "lib" + if "lib" in dirnames: + dirnames.remove("lib") + for filename in filenames: ext = os.path.splitext(filename.lower())[1] if not ext in SOURCE_CODE_FILE_EXTENSIONS: diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 1e95ee2f..cb4f8f5a 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 from flipper.app import App -from os.path import join, exists -from os import makedirs +from os.path import join, exists, relpath +from os import makedirs, walk from update import Main as UpdateMain import shutil +import zipfile +import tarfile class ProjectDir: @@ -17,6 +19,9 @@ class ProjectDir: class Main(App): + DIST_FILE_PREFIX = "flipper-z-" + DIST_FOLDER_MAX_NAME_LENGTH = 80 + def init(self): self.subparsers = self.parser.add_subparsers(help="sub-command help") @@ -45,9 +50,13 @@ class Main(App): def get_project_filename(self, project, filetype): # Temporary fix project_name = project.project - if project_name == "firmware" and filetype != "elf": - project_name = "full" - return f"flipper-z-{self.target}-{project_name}-{self.args.suffix}.{filetype}" + if project_name == "firmware": + if filetype == "zip": + project_name = "sdk" + elif filetype != "elf": + project_name = "full" + + return f"{self.DIST_FILE_PREFIX}{self.target}-{project_name}-{self.args.suffix}.{filetype}" def get_dist_filepath(self, filename): return join(self.output_dir_path, filename) @@ -56,10 +65,28 @@ class Main(App): obj_directory = join("build", project.dir) for filetype in ("elf", "bin", "dfu", "json"): - shutil.copyfile( - join(obj_directory, f"{project.project}.{filetype}"), - self.get_dist_filepath(self.get_project_filename(project, filetype)), - ) + if exists(src_file := join(obj_directory, f"{project.project}.{filetype}")): + shutil.copyfile( + src_file, + self.get_dist_filepath( + self.get_project_filename(project, filetype) + ), + ) + if exists(sdk_folder := join(obj_directory, "sdk")): + with zipfile.ZipFile( + self.get_dist_filepath(self.get_project_filename(project, "zip")), + "w", + zipfile.ZIP_DEFLATED, + ) as zf: + for root, dirs, files in walk(sdk_folder): + for file in files: + zf.write( + join(root, file), + relpath( + join(root, file), + sdk_folder, + ), + ) def copy(self): self.projects = dict( @@ -103,9 +130,10 @@ class Main(App): ) if self.args.version: - bundle_dir = join( - self.output_dir_path, f"{self.target}-update-{self.args.suffix}" - ) + bundle_dir_name = f"{self.target}-update-{self.args.suffix}"[ + : self.DIST_FOLDER_MAX_NAME_LENGTH + ] + bundle_dir = join(self.output_dir_path, bundle_dir_name) bundle_args = [ "generate", "-d", @@ -131,10 +159,25 @@ class Main(App): ) ) bundle_args.extend(self.other_args) - self.logger.info( - f"Use this directory to self-update your Flipper:\n\t{bundle_dir}" - ) - return UpdateMain(no_exit=True)(bundle_args) + + if (bundle_result := UpdateMain(no_exit=True)(bundle_args)) == 0: + self.logger.info( + f"Use this directory to self-update your Flipper:\n\t{bundle_dir}" + ) + + # Create tgz archive + with tarfile.open( + join( + self.output_dir_path, + f"{self.DIST_FILE_PREFIX}{bundle_dir_name}.tgz", + ), + "w:gz", + compresslevel=9, + format=tarfile.USTAR_FORMAT, + ) as tar: + tar.add(bundle_dir, arcname=bundle_dir_name) + + return bundle_result return 0 diff --git a/scripts/update.py b/scripts/update.py index 52391965..3259c5b0 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -22,6 +22,7 @@ class Main(App): RESOURCE_TAR_MODE = "w:" RESOURCE_TAR_FORMAT = tarfile.USTAR_FORMAT RESOURCE_FILE_NAME = "resources.tar" + RESOURCE_ENTRY_NAME_MAX_LENGTH = 100 WHITELISTED_STACK_TYPES = set( map( @@ -76,9 +77,13 @@ class Main(App): self.parser_generate.set_defaults(func=self.generate) def generate(self): - stage_basename = basename(self.args.stage) - dfu_basename = basename(self.args.dfu) - radiobin_basename = basename(self.args.radiobin) + stage_basename = "updater.bin" # used to be basename(self.args.stage) + dfu_basename = ( + "firmware.dfu" if self.args.dfu else "" + ) # used to be basename(self.args.dfu) + radiobin_basename = ( + "radio.bin" if self.args.radiobin else "" + ) # used to be basename(self.args.radiobin) resources_basename = "" radio_version = 0 @@ -120,9 +125,10 @@ class Main(App): ) if self.args.resources: resources_basename = self.RESOURCE_FILE_NAME - self.package_resources( + if not self.package_resources( self.args.resources, join(self.args.directory, resources_basename) - ) + ): + return 3 if not self.layout_check(dfu_size, radio_addr): self.logger.warn("Memory layout looks suspicious") @@ -199,11 +205,28 @@ class Main(App): "Please confirm that you REALLY want to do that with --I-understand-what-I-am-doing=yes" ) + def _tar_filter(self, tarinfo: tarfile.TarInfo): + if len(tarinfo.name) > self.RESOURCE_ENTRY_NAME_MAX_LENGTH: + self.logger.error( + f"Cannot package resource: name '{tarinfo.name}' too long" + ) + raise ValueError("Resource name too long") + return tarinfo + def package_resources(self, srcdir: str, dst_name: str): - with tarfile.open( - dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT - ) as tarball: - tarball.add(srcdir, arcname="") + try: + with tarfile.open( + dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT + ) as tarball: + tarball.add( + srcdir, + arcname="", + filter=self._tar_filter, + ) + return True + except ValueError as e: + self.logger.error(f"Cannot package resources: {e}") + return False @staticmethod def copro_version_as_int(coprometa, stacktype): diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 2eeda247..324dfe33 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -34,6 +34,14 @@ AddOption( help="List of applications to forcefully build as standalone .elf", ) +AddOption( + "--proxy-env", + action="store", + dest="proxy_env", + default="", + help="Comma-separated list of additional environment variables to pass to child SCons processes", +) + # Construction environment variables @@ -73,46 +81,41 @@ vars.AddVariables( help="Enable debug tools to be built", default=False, ), -) - -vars.Add( - "DIST_SUFFIX", - help="Suffix for binaries in build output for dist targets", - default="local", -) - -vars.Add( - "UPDATE_VERSION_STRING", - help="Version string for updater package", - default="${DIST_SUFFIX}", -) - - -vars.Add( - "COPRO_CUBE_VERSION", - help="Cube version", - default="", -) - -vars.Add( - "COPRO_STACK_ADDR", - help="Core2 Firmware address", - default="0", -) - -vars.Add( - "COPRO_STACK_BIN", - help="Core2 Firmware file name", - default="", -) - -vars.Add( - "COPRO_DISCLAIMER", - help="Value to pass to bundling script to confirm dangerous operations", - default="", -) - -vars.AddVariables( + BoolVariable( + "FAP_EXAMPLES", + help="Enable example applications to be built", + default=False, + ), + ( + "DIST_SUFFIX", + "Suffix for binaries in build output for dist targets", + "local", + ), + ( + "UPDATE_VERSION_STRING", + "Version string for updater package", + "${DIST_SUFFIX}", + ), + ( + "COPRO_CUBE_VERSION", + "Cube version", + "", + ), + ( + "COPRO_STACK_ADDR", + "Core2 Firmware address", + "0", + ), + ( + "COPRO_STACK_BIN", + "Core2 Firmware file name", + "", + ), + ( + "COPRO_DISCLAIMER", + "Value to pass to bundling script to confirm dangerous operations", + "", + ), PathVariable( "COPRO_OB_DATA", help="Path to OB reference data", @@ -153,85 +156,75 @@ vars.AddVariables( validator=PathVariable.PathAccept, default="", ), -) - -vars.Add( - "FBT_TOOLCHAIN_VERSIONS", - help="Whitelisted toolchain versions (leave empty for no check)", - default=tuple(), -) - -vars.Add( - "OPENOCD_OPTS", - help="Options to pass to OpenOCD", - default="", -) - -vars.Add( - "BLACKMAGIC", - help="Blackmagic probe location", - default="auto", -) - -vars.Add( - "UPDATE_SPLASH", - help="Directory name with slideshow frames to render after installing update package", - default="update_default", -) - -vars.Add( - "LOADER_AUTOSTART", - help="Application name to automatically run on Flipper boot", - default="", -) - - -vars.Add( - "FIRMWARE_APPS", - help="Map of (configuration_name->application_list)", - default={ - "default": ( - # Svc - "basic_services", - # Apps - "main_apps", - "system_apps", - # Settings - "settings_apps", - # Plugins - # "basic_plugins", - # Debug - # "debug_apps", - ) - }, -) - -vars.Add( - "FIRMWARE_APP_SET", - help="Application set to use from FIRMWARE_APPS", - default="default", -) - -vars.Add( - "APPSRC", - help="Application source directory for app to build & upload", - default="", -) - -# List of tuples (directory, add_to_global_include_path) -vars.Add( - "APPDIRS", - help="Directories to search for firmware components & external apps", - default=[ - ("applications", False), - ("applications/services", True), - ("applications/main", True), - ("applications/settings", False), - ("applications/system", False), - ("applications/debug", False), - ("applications/plugins", False), - ("applications_user", False), - ], + ( + "FBT_TOOLCHAIN_VERSIONS", + "Whitelisted toolchain versions (leave empty for no check)", + tuple(), + ), + ( + "OPENOCD_OPTS", + "Options to pass to OpenOCD", + "", + ), + ( + "BLACKMAGIC", + "Blackmagic probe location", + "auto", + ), + ( + "UPDATE_SPLASH", + "Directory name with slideshow frames to render after installing update package", + "update_default", + ), + ( + "LOADER_AUTOSTART", + "Application name to automatically run on Flipper boot", + "", + ), + ( + "FIRMWARE_APPS", + "Map of (configuration_name->application_list)", + { + "default": ( + # Svc + "basic_services", + # Apps + "main_apps", + "system_apps", + # Settings + "settings_apps", + # Plugins + # "basic_plugins", + # Debug + # "debug_apps", + ) + }, + ), + ( + "FIRMWARE_APP_SET", + "Application set to use from FIRMWARE_APPS", + "default", + ), + ( + "APPSRC", + "Application source directory for app to build & upload", + "", + ), + # List of tuples (directory, add_to_global_include_path) + ( + "APPDIRS", + "Directories to search for firmware components & external apps", + [ + ("applications", False), + ("applications/services", True), + ("applications/main", True), + ("applications/settings", False), + ("applications/system", False), + ("applications/debug", False), + ("applications/plugins", False), + ("applications_user", False), + ], + ), ) Return("vars") diff --git a/site_scons/environ.scons b/site_scons/environ.scons index c61f2961..2d082838 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -1,6 +1,5 @@ -import SCons from SCons.Platform import TempFileMunge -from fbt import util +from fbt.util import tempfile_arg_esc_func, single_quote, wrap_tempfile import os import multiprocessing @@ -12,14 +11,24 @@ forward_os_env = { "PATH": os.environ["PATH"], } # Proxying CI environment to child processes & scripts -for env_value_name in ( +variables_to_forward = [ + # CI/CD variables "WORKFLOW_BRANCH_OR_TAG", "DIST_SUFFIX", + # Python & other tools "HOME", "APPDATA", "PYTHONHOME", "PYTHONNOUSERSITE", -): + "TMP", + "TEMP", + # Colors for tools + "TERM", +] +if proxy_env := GetOption("proxy_env"): + variables_to_forward.extend(proxy_env.split(",")) + +for env_value_name in variables_to_forward: if environ_value := os.environ.get(env_value_name, None): forward_os_env[env_value_name] = environ_value @@ -73,7 +82,7 @@ if not coreenv["VERBOSE"]: SetOption("num_jobs", multiprocessing.cpu_count()) # Avoiding re-scan of all sources on every startup SetOption("implicit_cache", True) -SetOption("implicit_deps_unchanged", True) +# SetOption("implicit_deps_unchanged", True) # More aggressive caching SetOption("max_drift", 1) # Random task queue - to discover isses with build logic faster @@ -81,10 +90,10 @@ SetOption("max_drift", 1) # Setting up temp file parameters - to overcome command line length limits -coreenv["TEMPFILEARGESCFUNC"] = util.tempfile_arg_esc_func -util.wrap_tempfile(coreenv, "LINKCOM") -util.wrap_tempfile(coreenv, "ARCOM") +coreenv["TEMPFILEARGESCFUNC"] = tempfile_arg_esc_func +wrap_tempfile(coreenv, "LINKCOM") +wrap_tempfile(coreenv, "ARCOM") -coreenv["SINGLEQUOTEFUNC"] = util.single_quote +coreenv["SINGLEQUOTEFUNC"] = single_quote Return("coreenv") diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 66002915..9edc6b5c 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -1,14 +1,27 @@ +from SCons.Errors import UserError + + Import("ENV") from fbt.appmanifest import FlipperAppType appenv = ENV.Clone( - tools=[("fbt_extapps", {"EXT_APPS_WORK_DIR": ENV.subst("${BUILD_DIR}/.extapps")})] + tools=[ + ( + "fbt_extapps", + { + "EXT_APPS_WORK_DIR": ENV.subst( + "${BUILD_DIR}/.extapps", + ) + }, + ), + "fbt_assets", + ] ) appenv.Replace( - LINKER_SCRIPT="application-ext", + LINKER_SCRIPT="application_ext", ) appenv.AppendUnique( @@ -83,7 +96,17 @@ if extra_app_list := GetOption("extra_ext_apps"): if appenv["FORCE"]: appenv.AlwaysBuild(extapps["compact"].values()) -Alias(appenv["FIRMWARE_BUILD_CFG"] + "_extapps", extapps["compact"].values()) + +# Deprecation stub +def legacy_app_build_stub(**kw): + raise UserError(f"Target name 'firmware_extapps' is deprecated, use 'faps' instead") + + +appenv.PhonyTarget("firmware_extapps", appenv.Action(legacy_app_build_stub, None)) + + +Alias("faps", extapps["compact"].values()) +Alias("faps", extapps["validators"].values()) if appsrc := appenv.subst("$APPSRC"): app_manifest, fap_file, app_validator = appenv.GetExtAppFromPath(appsrc) diff --git a/site_scons/fbt_extra/util.py b/site_scons/fbt_extra/util.py new file mode 100644 index 00000000..aa3d50b6 --- /dev/null +++ b/site_scons/fbt_extra/util.py @@ -0,0 +1,23 @@ +from fbt.util import link_dir + + +def link_elf_dir_as_latest(env, elf_node): + elf_dir = elf_node.Dir(".") + latest_dir = env.Dir("#build/latest") + print(f"Setting {elf_dir} as latest built dir (./build/latest/)") + return link_dir(latest_dir.abspath, elf_dir.abspath, env["PLATFORM"] == "win32") + + +def should_gen_cdb_and_link_dir(env, requested_targets): + explicitly_building_updater = False + # Hacky way to check if updater-related targets were requested + for build_target in requested_targets: + if "updater" in str(build_target): + explicitly_building_updater = True + + is_updater = not env["IS_BASE_FIRMWARE"] + # If updater is explicitly requested, link to the latest updater + # Otherwise, link to firmware + return (is_updater and explicitly_building_updater) or ( + not is_updater and not explicitly_building_updater + ) diff --git a/site_scons/site_tools/fbt_extapps.py b/site_scons/site_tools/fbt_extapps.py deleted file mode 100644 index fec24071..00000000 --- a/site_scons/site_tools/fbt_extapps.py +++ /dev/null @@ -1,165 +0,0 @@ -from SCons.Builder import Builder -from SCons.Action import Action -from SCons.Errors import UserError -import SCons.Warnings - -import os -import pathlib -from fbt.elfmanifest import assemble_manifest_data -from fbt.sdk import SdkCache -import itertools - - -def BuildAppElf(env, app): - work_dir = env.subst("$EXT_APPS_WORK_DIR") - - app_alias = f"{env['FIRMWARE_BUILD_CFG']}_{app.appid}" - app_original_elf = os.path.join(work_dir, f"{app.appid}_d") - app_sources = list( - itertools.chain.from_iterable( - env.GlobRecursive(source_type, os.path.join(work_dir, app._appdir.relpath)) - for source_type in app.sources - ) - ) - app_elf_raw = env.Program( - app_original_elf, - app_sources, - APP_ENTRY=app.entry_point, - LIBS=env["LIBS"] + app.fap_libs, - ) - - app_elf_dump = env.ObjDump(app_elf_raw) - env.Alias(f"{app_alias}_list", app_elf_dump) - - app_elf_augmented = env.EmbedAppMetadata( - os.path.join(env.subst("$PLUGIN_ELF_DIR"), app.appid), - app_elf_raw, - APP=app, - ) - - manifest_vals = vars(app) - manifest_vals = { - k: v for k, v in manifest_vals.items() if k not in ("_appdir", "_apppath") - } - - env.Depends( - app_elf_augmented, - [env["SDK_DEFINITION"], env.Value(manifest_vals)], - ) - if app.fap_icon: - env.Depends( - app_elf_augmented, - env.File(f"{app._apppath}/{app.fap_icon}"), - ) - env.Alias(app_alias, app_elf_augmented) - - app_elf_import_validator = env.ValidateAppImports(app_elf_augmented) - env.AlwaysBuild(app_elf_import_validator) - env.Alias(app_alias, app_elf_import_validator) - return (app_elf_augmented, app_elf_raw, app_elf_import_validator) - - -def prepare_app_metadata(target, source, env): - sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=True) - - if not sdk_cache.is_buildable(): - raise UserError( - "SDK version is not finalized, please review changes and re-run operation" - ) - - app = env["APP"] - meta_file_name = source[0].path + ".meta" - with open(meta_file_name, "wb") as f: - # f.write(f"hello this is {app}") - f.write( - assemble_manifest_data( - app_manifest=app, - hardware_target=int(env.subst("$TARGET_HW")), - sdk_version=sdk_cache.version.as_int(), - ) - ) - - -def validate_app_imports(target, source, env): - sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=False) - app_syms = set() - with open(target[0].path, "rt") as f: - for line in f: - app_syms.add(line.split()[0]) - unresolved_syms = app_syms - sdk_cache.get_valid_names() - if unresolved_syms: - SCons.Warnings.warn( - SCons.Warnings.LinkWarning, - f"{source[0].path}: app won't run. Unresolved symbols: {unresolved_syms}", - ) - - -def GetExtAppFromPath(env, app_dir): - if not app_dir: - raise UserError("APPSRC= not set") - - appmgr = env["APPMGR"] - - app = None - for dir_part in reversed(pathlib.Path(app_dir).parts): - if app := appmgr.find_by_appdir(dir_part): - break - if not app: - raise UserError(f"Failed to resolve application for given APPSRC={app_dir}") - - app_elf = env["_extapps"]["compact"].get(app.appid, None) - if not app_elf: - raise UserError( - f"Application {app.appid} is not configured for building as external" - ) - - app_validator = env["_extapps"]["validators"].get(app.appid, None) - - return (app, app_elf[0], app_validator[0]) - - -def generate(env, **kw): - env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR")) - env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), env.Dir("#"), duplicate=False) - - env.AddMethod(BuildAppElf) - env.AddMethod(GetExtAppFromPath) - env.Append( - BUILDERS={ - "EmbedAppMetadata": Builder( - action=[ - Action(prepare_app_metadata, "$APPMETA_COMSTR"), - Action( - "${OBJCOPY} " - "--remove-section .ARM.attributes " - "--add-section .fapmeta=${SOURCE}.meta " - "--set-section-flags .fapmeta=contents,noload,readonly,data " - "--strip-debug --strip-unneeded " - "--add-gnu-debuglink=${SOURCE} " - "${SOURCES} ${TARGET}", - "$APPMETAEMBED_COMSTR", - ), - ], - suffix=".fap", - src_suffix=".elf", - ), - "ValidateAppImports": Builder( - action=[ - Action( - "@${NM} -P -u ${SOURCE} > ${TARGET}", - None, # "$APPDUMP_COMSTR", - ), - Action( - validate_app_imports, - "$APPCHECK_COMSTR", - ), - ], - suffix=".impsyms", - src_suffix=".fap", - ), - } - ) - - -def exists(env): - return True