From e0469ae1ed219f1985f7779de3abf34c7237bb3a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:25:55 +0300 Subject: [PATCH 01/13] Adding F13-F24 function key support to BadUSB https://github.com/flipperdevices/flipperzero-firmware/pull/3468/files --- .../main/bad_usb/helpers/ducky_script_keycodes.c | 12 ++++++++++++ applications/system/js_app/modules/js_badusb.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/applications/main/bad_usb/helpers/ducky_script_keycodes.c b/applications/main/bad_usb/helpers/ducky_script_keycodes.c index da2fc22f79..56b5144d48 100644 --- a/applications/main/bad_usb/helpers/ducky_script_keycodes.c +++ b/applications/main/bad_usb/helpers/ducky_script_keycodes.c @@ -64,6 +64,18 @@ static const DuckyKey ducky_keys[] = { {"F10", HID_KEYBOARD_F10}, {"F11", HID_KEYBOARD_F11}, {"F12", HID_KEYBOARD_F12}, + {"F13", HID_KEYBOARD_F13}, + {"F14", HID_KEYBOARD_F14}, + {"F15", HID_KEYBOARD_F15}, + {"F16", HID_KEYBOARD_F16}, + {"F17", HID_KEYBOARD_F17}, + {"F18", HID_KEYBOARD_F18}, + {"F19", HID_KEYBOARD_F19}, + {"F20", HID_KEYBOARD_F20}, + {"F21", HID_KEYBOARD_F21}, + {"F22", HID_KEYBOARD_F22}, + {"F23", HID_KEYBOARD_F23}, + {"F24", HID_KEYBOARD_F24}, }; uint16_t ducky_get_keycode_by_name(const char* param) { diff --git a/applications/system/js_app/modules/js_badusb.c b/applications/system/js_app/modules/js_badusb.c index 389539be58..349fde7ba2 100644 --- a/applications/system/js_app/modules/js_badusb.c +++ b/applications/system/js_app/modules/js_badusb.c @@ -52,6 +52,18 @@ static const struct { {"F10", HID_KEYBOARD_F10}, {"F11", HID_KEYBOARD_F11}, {"F12", HID_KEYBOARD_F12}, + {"F13", HID_KEYBOARD_F13}, + {"F14", HID_KEYBOARD_F14}, + {"F15", HID_KEYBOARD_F15}, + {"F16", HID_KEYBOARD_F16}, + {"F17", HID_KEYBOARD_F17}, + {"F18", HID_KEYBOARD_F18}, + {"F19", HID_KEYBOARD_F19}, + {"F20", HID_KEYBOARD_F20}, + {"F21", HID_KEYBOARD_F21}, + {"F22", HID_KEYBOARD_F22}, + {"F23", HID_KEYBOARD_F23}, + {"F24", HID_KEYBOARD_F24}, {"NUM0", HID_KEYPAD_0}, {"NUM1", HID_KEYPAD_1}, From 760deb66c5bcb748ee48269560f30fbb00533c8b Mon Sep 17 00:00:00 2001 From: Jaroslav Nesterov Date: Thu, 21 Mar 2024 02:18:02 +0400 Subject: [PATCH 02/13] Add support for DEFAULT_STRING_DELAY in Bad USB App (#3476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for `DEFAULT_STRING_DELAY` in bad_usb * Format Sources Co-authored-by: あく --- applications/main/bad_usb/helpers/ducky_script.c | 6 +++++- .../main/bad_usb/helpers/ducky_script_commands.c | 16 +++++++++++++++- .../main/bad_usb/helpers/ducky_script_i.h | 1 + documentation/file_formats/BadUsbScriptFormat.md | 10 ++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/applications/main/bad_usb/helpers/ducky_script.c b/applications/main/bad_usb/helpers/ducky_script.c index 0d8c77c01a..2b3d998a47 100644 --- a/applications/main/bad_usb/helpers/ducky_script.c +++ b/applications/main/bad_usb/helpers/ducky_script.c @@ -436,6 +436,7 @@ static int32_t bad_usb_worker(void* context) { bad_usb->st.line_cur = 0; bad_usb->defdelay = 0; bad_usb->stringdelay = 0; + bad_usb->defstringdelay = 0; bad_usb->repeat_cnt = 0; bad_usb->key_hold_nb = 0; bad_usb->file_end = false; @@ -459,6 +460,7 @@ static int32_t bad_usb_worker(void* context) { bad_usb->st.line_cur = 0; bad_usb->defdelay = 0; bad_usb->stringdelay = 0; + bad_usb->defstringdelay = 0; bad_usb->repeat_cnt = 0; bad_usb->file_end = false; storage_file_seek(script_file, 0, true); @@ -586,9 +588,11 @@ static int32_t bad_usb_worker(void* context) { continue; } } else if(worker_state == BadUsbStateStringDelay) { // State: print string with delays + uint32_t delay = (bad_usb->stringdelay == 0) ? bad_usb->defstringdelay : + bad_usb->stringdelay; uint32_t flags = bad_usb_flags_get( WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect, - bad_usb->stringdelay); + delay); if(!(flags & FuriFlagError)) { if(flags & WorkerEvtEnd) { diff --git a/applications/main/bad_usb/helpers/ducky_script_commands.c b/applications/main/bad_usb/helpers/ducky_script_commands.c index a5bc7c8cf9..fdf963b404 100644 --- a/applications/main/bad_usb/helpers/ducky_script_commands.c +++ b/applications/main/bad_usb/helpers/ducky_script_commands.c @@ -46,6 +46,17 @@ static int32_t ducky_fnc_strdelay(BadUsbScript* bad_usb, const char* line, int32 return 0; } +static int32_t ducky_fnc_defstrdelay(BadUsbScript* bad_usb, const char* line, int32_t param) { + UNUSED(param); + + line = &line[ducky_get_command_len(line) + 1]; + bool state = ducky_get_number(line, &bad_usb->defstringdelay); + if(!state) { + return ducky_error(bad_usb, "Invalid number %s", line); + } + return 0; +} + static int32_t ducky_fnc_string(BadUsbScript* bad_usb, const char* line, int32_t param) { line = &line[ducky_get_command_len(line) + 1]; furi_string_set_str(bad_usb->string_print, line); @@ -53,7 +64,8 @@ static int32_t ducky_fnc_string(BadUsbScript* bad_usb, const char* line, int32_t furi_string_cat(bad_usb->string_print, "\n"); } - if(bad_usb->stringdelay == 0) { // stringdelay not set - run command immediately + if(bad_usb->stringdelay == 0 && + bad_usb->defstringdelay == 0) { // stringdelay not set - run command immediately bool state = ducky_string(bad_usb, furi_string_get_cstr(bad_usb->string_print)); if(!state) { return ducky_error(bad_usb, "Invalid string %s", line); @@ -161,6 +173,8 @@ static const DuckyCmd ducky_commands[] = { {"DEFAULTDELAY", ducky_fnc_defdelay, -1}, {"STRINGDELAY", ducky_fnc_strdelay, -1}, {"STRING_DELAY", ducky_fnc_strdelay, -1}, + {"DEFAULT_STRING_DELAY", ducky_fnc_defstrdelay, -1}, + {"DEFAULTSTRINGDELAY", ducky_fnc_defstrdelay, -1}, {"REPEAT", ducky_fnc_repeat, -1}, {"SYSRQ", ducky_fnc_sysrq, -1}, {"ALTCHAR", ducky_fnc_altchar, -1}, diff --git a/applications/main/bad_usb/helpers/ducky_script_i.h b/applications/main/bad_usb/helpers/ducky_script_i.h index 84c7ef9de6..9c1025b00b 100644 --- a/applications/main/bad_usb/helpers/ducky_script_i.h +++ b/applications/main/bad_usb/helpers/ducky_script_i.h @@ -30,6 +30,7 @@ struct BadUsbScript { uint32_t defdelay; uint32_t stringdelay; + uint32_t defstringdelay; uint16_t layout[128]; FuriString* line; diff --git a/documentation/file_formats/BadUsbScriptFormat.md b/documentation/file_formats/BadUsbScriptFormat.md index 3bda306172..cc919da094 100644 --- a/documentation/file_formats/BadUsbScriptFormat.md +++ b/documentation/file_formats/BadUsbScriptFormat.md @@ -97,10 +97,12 @@ Will wait indefinitely for a button to be pressed ## String delay Delay between keypresses. -| Command | Parameters | Notes | -| ------------ | ----------------- | --------------------------------------------- | -| STRING_DELAY | Delay value in ms | Applied once to next appearing STRING command | -| STRINGDELAY | Delay value in ms | Same as STRING_DELAY | +| Command | Parameters | Notes | +| -------------------- | ----------------- | --------------------------------------------- | +| STRING_DELAY | Delay value in ms | Applied once to next appearing STRING command | +| STRINGDELAY | Delay value in ms | Same as STRING_DELAY | +| DEFAULT_STRING_DELAY | Delay value in ms | Apply to every appearing STRING command | +| DEFAULTSTRINGDELAY | Delay value in ms | Same as DEFAULT_STRING_DELAY | ### Repeat From 6d9a2cc6994dedb6ffce8008463bafd57260b1b6 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:27:02 +0300 Subject: [PATCH 03/13] fbt/ufbt: Ensure POSIX paths are passed to GDB on all platforms https://github.com/flipperdevices/flipperzero-firmware/pull/3360/files --- SConstruct | 2 -- scripts/fbt/util.py | 25 +++++++++++++++++++++ scripts/fbt_tools/fbt_debugopts.py | 18 +++++++-------- scripts/fbt_tools/fbt_sdk.py | 6 ++--- scripts/ufbt/SConstruct | 35 +++++++++++++++--------------- site_scons/environ.scons | 3 ++- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/SConstruct b/SConstruct index be107eeb1d..52d286953c 100644 --- a/SConstruct +++ b/SConstruct @@ -229,7 +229,6 @@ firmware_debug = distenv.PhonyTarget( source=firmware_env["FW_ELF"], GDBOPTS="${GDBOPTS_BASE}", GDBREMOTE="${OPENOCD_GDB_PIPE}", - FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")), ) distenv.Depends(firmware_debug, firmware_flash) @@ -239,7 +238,6 @@ distenv.PhonyTarget( source=firmware_env["FW_ELF"], GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", GDBREMOTE="${BLACKMAGIC_ADDR}", - FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")), ) # Debug alien elf diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index 6b1f9dc6cf..f08c8f4fa2 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -1,5 +1,9 @@ import os import re +import subprocess +import sys +import webbrowser +from pathlib import Path, PurePosixPath import SCons from SCons.Errors import StopError @@ -80,6 +84,27 @@ def resolve_real_dir_node(node): raise StopError(f"Can't find absolute path for {node.name} ({node})") +class PosixPathWrapper: + def __init__(self, pathobj): + self.pathobj = pathobj + + @staticmethod + def fixup_separators(path): + if SCons.Platform.platform_default() == "win32": + return path.replace(os.path.sep, os.path.altsep) + return path + + @staticmethod + def fix_path(path): + return str(PurePosixPath(Path(path).as_posix())) + + def __call__(self, target, source, env, for_signature): + if for_signature: + return self.pathobj + + return self.fix_path(env.subst(self.pathobj)) + + def path_as_posix(path): if SCons.Platform.platform_default() == "win32": return path.replace(os.path.sep, os.path.altsep) diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index 392465a518..77b63e2034 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -18,7 +18,7 @@ def GetDevices(env): def generate(env, **kw): env.AddMethod(GetDevices) env.SetDefault( - FBT_DEBUG_DIR="${FBT_SCRIPT_DIR}/debug", + FBT_DEBUG_DIR="${POSIXPATH('$FBT_SCRIPT_DIR')}/debug", ) if (adapter_serial := env.subst("$SWD_TRANSPORT_SERIAL")) != "auto": @@ -36,11 +36,11 @@ def generate(env, **kw): env.SetDefault( OPENOCD_GDB_PIPE=[ - "|openocd -c 'gdb_port pipe; log_output ${FBT_DEBUG_DIR}/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" + "|openocd -c 'gdb_port pipe; log_output ${POSIXPATH('$FBT_DEBUG_DIR')}/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" ], GDBOPTS_BASE=[ "-ex", - "source ${FBT_DEBUG_DIR}/gdbinit", + "source ${POSIXPATH('$FBT_DEBUG_DIR')}/gdbinit", "-ex", "target extended-remote ${GDBREMOTE}", ], @@ -57,17 +57,17 @@ def generate(env, **kw): ], GDBPYOPTS=[ "-ex", - "source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py", + "source ${POSIXPATH('$FBT_DEBUG_DIR')}/FreeRTOS/FreeRTOS.py", "-ex", - "source ${FBT_DEBUG_DIR}/flipperapps.py", + "source ${POSIXPATH('$FBT_DEBUG_DIR')}/flipperapps.py", "-ex", - "source ${FBT_DEBUG_DIR}/flipperversion.py", + "source ${POSIXPATH('$FBT_DEBUG_DIR')}/flipperversion.py", "-ex", - "fap-set-debug-elf-root ${FBT_FAP_DEBUG_ELF_ROOT}", + "fap-set-debug-elf-root ${POSIXPATH('$FBT_FAP_DEBUG_ELF_ROOT')}", "-ex", - "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py", + "source ${POSIXPATH('$FBT_DEBUG_DIR')}/PyCortexMDebug/PyCortexMDebug.py", "-ex", - "svd_load ${SVD_FILE}", + "svd_load ${POSIXPATH('$SVD_FILE')}", "-ex", "compare-sections", "-ex", diff --git a/scripts/fbt_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py index 17acc8cf1a..a3f7faa577 100644 --- a/scripts/fbt_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -6,7 +6,7 @@ from fbt.sdk.cache import SdkCache from fbt.sdk.collector import SdkCollector -from fbt.util import path_as_posix +from fbt.util import PosixPathWrapper from SCons.Action import Action from SCons.Builder import Builder from SCons.Errors import UserError @@ -80,7 +80,7 @@ def _wrap_scons_vars(self, vars: str): vars, target=Entry(self.MAP_FILE_SUBST), ) - return path_as_posix(expanded_vars) + return PosixPathWrapper.fixup_separators(expanded_vars) class SdkTreeBuilder: @@ -149,7 +149,7 @@ def _generate_sdk_meta(self): meta.save_to(self.target[0].path) def build_sdk_file_path(self, orig_path: str) -> str: - return path_as_posix( + return PosixPathWrapper.fix_path( posixpath.normpath( posixpath.join( self.SDK_DIR_SUBST, diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 8178a83da4..11fefd22b5 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -47,7 +47,7 @@ from fbt.appmanifest import FlipperApplication, FlipperAppType from fbt.sdk.cache import SdkCache from fbt.util import ( FORWARDED_ENV_VARIABLES, - path_as_posix, + PosixPathWrapper, resolve_real_dir_node, single_quote, tempfile_arg_esc_func, @@ -89,6 +89,7 @@ env = core_env.Clone( ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), ], FBT_FAP_DEBUG_ELF_ROOT=ufbt_build_dir, + POSIXPATH=PosixPathWrapper, TEMPFILE=TempFileMunge, MAXLINELENGTH=2048, PROGSUFFIX=".elf", @@ -128,7 +129,7 @@ dist_env = env.Clone( "-c", "transport select hla_swd", "-f", - "${FBT_DEBUG_DIR}/stm32wbx.cfg", + "${POSIXPATH('$FBT_DEBUG_DIR')}/stm32wbx.cfg", "-c", "stm32wbx.cpu configure -rtos auto", ], @@ -161,7 +162,6 @@ firmware_debug = dist_env.PhonyTarget( source=dist_env["FW_ELF"], GDBOPTS="${GDBOPTS_BASE}", GDBREMOTE="${OPENOCD_GDB_PIPE}", - FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(dist_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")), ) dist_env.PhonyTarget( @@ -170,15 +170,14 @@ dist_env.PhonyTarget( source=dist_env["FW_ELF"], GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", GDBREMOTE="${BLACKMAGIC_ADDR}", - FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(dist_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")), ) # Debug alien elf debug_other_opts = [ "-ex", - "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py", + "source ${POSIXPATH('FBT_DEBUG_DIR')}/PyCortexMDebug/PyCortexMDebug.py", "-ex", - "source ${FBT_DEBUG_DIR}/flipperversion.py", + "source ${POSIXPATH('FBT_DEBUG_DIR')}/flipperversion.py", "-ex", "fw-version", ] @@ -371,10 +370,6 @@ dist_env.PhonyTarget( # Prepare vscode environment -def _path_as_posix(path): - return pathlib.Path(path).as_posix() - - vscode_dist = [] project_template_dir = dist_env["UFBT_SCRIPT_ROOT"].Dir("project_template") for template_file in project_template_dir.Dir(".vscode").glob("*"): @@ -387,20 +382,24 @@ for template_file in project_template_dir.Dir(".vscode").glob("*"): "@UFBT_TOOLCHAIN_ARM_TOOLCHAIN_DIR@": pathlib.Path( dist_env.WhereIs("arm-none-eabi-gcc") ).parent.as_posix(), - "@UFBT_TOOLCHAIN_GCC@": _path_as_posix( + "@UFBT_TOOLCHAIN_GCC@": PosixPathWrapper.fix_path( dist_env.WhereIs("arm-none-eabi-gcc") ), - "@UFBT_TOOLCHAIN_GDB_PY@": _path_as_posix( + "@UFBT_TOOLCHAIN_GDB_PY@": PosixPathWrapper.fix_path( dist_env.WhereIs("arm-none-eabi-gdb-py3") ), - "@UFBT_TOOLCHAIN_OPENOCD@": _path_as_posix(dist_env.WhereIs("openocd")), - "@UFBT_APP_DIR@": _path_as_posix(original_app_dir.abspath), - "@UFBT_ROOT_DIR@": _path_as_posix(Dir("#").abspath), - "@UFBT_DEBUG_DIR@": _path_as_posix(dist_env["FBT_DEBUG_DIR"].abspath), - "@UFBT_DEBUG_ELF_DIR@": _path_as_posix( + "@UFBT_TOOLCHAIN_OPENOCD@": PosixPathWrapper.fix_path( + dist_env.WhereIs("openocd") + ), + "@UFBT_APP_DIR@": PosixPathWrapper.fix_path(original_app_dir.abspath), + "@UFBT_ROOT_DIR@": PosixPathWrapper.fix_path(Dir("#").abspath), + "@UFBT_DEBUG_DIR@": dist_env.subst("FBT_DEBUG_DIR"), + "@UFBT_DEBUG_ELF_DIR@": PosixPathWrapper.fix_path( dist_env["FBT_FAP_DEBUG_ELF_ROOT"].abspath ), - "@UFBT_FIRMWARE_ELF@": _path_as_posix(dist_env["FW_ELF"].abspath), + "@UFBT_FIRMWARE_ELF@": PosixPathWrapper.fix_path( + dist_env["FW_ELF"].abspath + ), }, ) ) diff --git a/site_scons/environ.scons b/site_scons/environ.scons index ece8de2122..3f2d3450e1 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -3,6 +3,7 @@ import os from fbt.util import ( FORWARDED_ENV_VARIABLES, + PosixPathWrapper, resolve_real_dir_node, single_quote, tempfile_arg_esc_func, @@ -26,7 +27,6 @@ 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 - coreenv = VAR_ENV.Clone( tools=[ "fbt_tweaks", @@ -43,6 +43,7 @@ coreenv = VAR_ENV.Clone( "ccache", ], TEMPFILE=TempFileMunge, + POSIXPATH=PosixPathWrapper, MAXLINELENGTH=2048, PROGSUFFIX=".elf", ENV=forward_os_env, From 09c46a33817474946b6c586a7d240eefb49b912b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:30:55 +0300 Subject: [PATCH 04/13] Fix DIP decoding for Linear Delta-3 by brandonweeks https://github.com/flipperdevices/flipperzero-firmware/pull/3528/files --- lib/subghz/protocols/linear_delta3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/subghz/protocols/linear_delta3.c b/lib/subghz/protocols/linear_delta3.c index 97ac5cc5a6..321d25d41a 100644 --- a/lib/subghz/protocols/linear_delta3.c +++ b/lib/subghz/protocols/linear_delta3.c @@ -10,9 +10,9 @@ #define DIP_PATTERN "%c%c%c%c%c%c%c%c" #define DATA_TO_DIP(dip) \ - (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), \ - (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), \ - (dip & 0x0002 ? '1' : '0'), (dip & 0x0001 ? '1' : '0') + (dip & 0x0080 ? '0' : '1'), (dip & 0x0040 ? '0' : '1'), (dip & 0x0020 ? '0' : '1'), \ + (dip & 0x0010 ? '0' : '1'), (dip & 0x0008 ? '0' : '1'), (dip & 0x0004 ? '0' : '1'), \ + (dip & 0x0002 ? '0' : '1'), (dip & 0x0001 ? '0' : '1') static const SubGhzBlockConst subghz_protocol_linear_delta3_const = { .te_short = 500, From 6d73b266d5d479377d23dac689133a7b52f4bb8e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Mar 2024 22:47:24 +0300 Subject: [PATCH 05/13] Fixes for text box and uart echo thanks Willy-JL ! --- applications/debug/uart_echo/uart_echo.c | 7 ++++--- applications/services/gui/modules/text_box.c | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/applications/debug/uart_echo/uart_echo.c b/applications/debug/uart_echo/uart_echo.c index 0291c9e79d..9c65910a04 100644 --- a/applications/debug/uart_echo/uart_echo.c +++ b/applications/debug/uart_echo/uart_echo.c @@ -283,13 +283,14 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) { static void uart_echo_app_free(UartEchoApp* app) { furi_assert(app); + furi_hal_serial_async_rx_stop(app->serial_handle); + furi_hal_serial_deinit(app->serial_handle); + furi_hal_serial_control_release(app->serial_handle); + furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); furi_thread_free(app->worker_thread); - furi_hal_serial_deinit(app->serial_handle); - furi_hal_serial_control_release(app->serial_handle); - // Free views view_dispatcher_remove_view(app->view_dispatcher, 0); diff --git a/applications/services/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c index c0110806a7..ff728108f5 100644 --- a/applications/services/gui/modules/text_box.c +++ b/applications/services/gui/modules/text_box.c @@ -102,9 +102,11 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { model->text_pos = (char*)model->text; if(model->focus == TextBoxFocusEnd && line_num > 5) { // Set text position to 5th line from the end - for(uint8_t i = 0; i < line_num - 5; i++) { - while(*model->text_pos++ != '\n') { - }; + const char* end = model->text + furi_string_size(model->text_formatted); + for(size_t i = 0; i < line_num - 5; i++) { + while(model->text_pos < end) { + if(*model->text_pos++ == '\n') break; + } } model->scroll_num = line_num - 4; model->scroll_pos = line_num - 5; From c1441b1331c2e336661b67c74d488449eb377755 Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 21 Mar 2024 12:43:30 +0000 Subject: [PATCH 06/13] nfc app: fix navigation in select protocol scene --- applications/main/nfc/scenes/nfc_scene_select_protocol.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/applications/main/nfc/scenes/nfc_scene_select_protocol.c b/applications/main/nfc/scenes/nfc_scene_select_protocol.c index 52b2664ec6..af644035e8 100644 --- a/applications/main/nfc/scenes/nfc_scene_select_protocol.c +++ b/applications/main/nfc/scenes/nfc_scene_select_protocol.c @@ -57,6 +57,11 @@ bool nfc_scene_select_protocol_on_event(void* context, SceneManagerEvent event) scene_manager_set_scene_state( instance->scene_manager, NfcSceneSelectProtocol, event.event); consumed = true; + } else if(event.type == SceneManagerEventTypeBack) { + if(scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDetect)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, NfcSceneStart); + } } return consumed; } From 34fac96ef6c09490fbf9dd3a85e4e4512b5b1e4f Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 21 Mar 2024 13:14:36 +0000 Subject: [PATCH 07/13] nfc app: fix text box position and size on emulation screen --- .../main/nfc/helpers/protocol_support/nfc_protocol_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c index 549f1ca945..d7adf9d807 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c @@ -604,7 +604,7 @@ static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) { } widget_add_text_box_element( - widget, 56, 33, 71, 25, AlignCenter, AlignTop, furi_string_get_cstr(temp_str), false); + widget, 50, 33, 78, 31, AlignCenter, AlignTop, furi_string_get_cstr(temp_str), false); furi_string_free(temp_str); From d1d3c43939b91c466cbf366f420d81e2c596f337 Mon Sep 17 00:00:00 2001 From: Egor Koleda Date: Fri, 22 Mar 2024 15:25:52 +0300 Subject: [PATCH 08/13] Add support for Pioneer SR IR remotes (#3308) * add support for Pioneer SR IR remotes * fix minor issues * fix repeat * Fix protocol enumeration order * Add unit tests for Pioneer IR protocol * Clean up raw test data * Add encoder/decoder tests, modify parser * Remove dead code * Use loops where appropriate Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Co-authored-by: Georgii Surkov --- .../debug/unit_tests/infrared/infrared_test.c | 76 +++---- .../unit_tests/infrared/test_pioneer.irtest | 205 ++++++++++++++++++ .../common/infrared_common_i.h | 1 - lib/infrared/encoder_decoder/infrared.c | 15 ++ lib/infrared/encoder_decoder/infrared.h | 2 + .../kaseikyo/infrared_protocol_kaseikyo.c | 1 - .../nec/infrared_protocol_nec.c | 1 - .../pioneer/infrared_decoder_pioneer.c | 57 +++++ .../pioneer/infrared_encoder_pioneer.c | 61 ++++++ .../pioneer/infrared_protocol_pioneer.c | 40 ++++ .../pioneer/infrared_protocol_pioneer.h | 36 +++ .../pioneer/infrared_protocol_pioneer_i.h | 25 +++ .../rca/infrared_protocol_rca.c | 1 - .../samsung/infrared_protocol_samsung.c | 1 - .../sirc/infrared_protocol_sirc.c | 1 - 15 files changed, 480 insertions(+), 43 deletions(-) create mode 100644 applications/debug/unit_tests/resources/unit_tests/infrared/test_pioneer.irtest create mode 100644 lib/infrared/encoder_decoder/pioneer/infrared_decoder_pioneer.c create mode 100644 lib/infrared/encoder_decoder/pioneer/infrared_encoder_pioneer.c create mode 100644 lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.c create mode 100644 lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.h create mode 100644 lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer_i.h diff --git a/applications/debug/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/infrared/infrared_test.c index 294c2da9a5..ba57b78aad 100644 --- a/applications/debug/unit_tests/infrared/infrared_test.c +++ b/applications/debug/unit_tests/infrared/infrared_test.c @@ -426,53 +426,53 @@ MU_TEST(infrared_test_decoder_mixed) { infrared_test_run_decoder(InfraredProtocolSIRC, 3); infrared_test_run_decoder(InfraredProtocolKaseikyo, 1); infrared_test_run_decoder(InfraredProtocolRCA, 1); + infrared_test_run_decoder(InfraredProtocolPioneer, 6); } MU_TEST(infrared_test_decoder_nec) { - infrared_test_run_decoder(InfraredProtocolNEC, 1); - infrared_test_run_decoder(InfraredProtocolNEC, 2); - infrared_test_run_decoder(InfraredProtocolNEC, 3); + for(uint32_t i = 1; i <= 3; ++i) { + infrared_test_run_decoder(InfraredProtocolNEC, i); + } } MU_TEST(infrared_test_decoder_unexpected_end_in_sequence) { - infrared_test_run_decoder(InfraredProtocolNEC, 1); - infrared_test_run_decoder(InfraredProtocolNEC, 1); - infrared_test_run_decoder(InfraredProtocolNEC, 2); - infrared_test_run_decoder(InfraredProtocolNEC, 2); + for(uint32_t i = 1; i <= 2; ++i) { + infrared_test_run_decoder(InfraredProtocolNEC, i); + infrared_test_run_decoder(InfraredProtocolNEC, i); + } } MU_TEST(infrared_test_decoder_necext1) { - infrared_test_run_decoder(InfraredProtocolNECext, 1); - infrared_test_run_decoder(InfraredProtocolNECext, 1); + for(uint32_t i = 0; i < 2; ++i) { + UNUSED(i); + infrared_test_run_decoder(InfraredProtocolNECext, 1); + } } MU_TEST(infrared_test_decoder_long_packets_with_nec_start) { - infrared_test_run_decoder(InfraredProtocolNEC42ext, 1); - infrared_test_run_decoder(InfraredProtocolNEC42ext, 2); + for(uint32_t i = 1; i <= 2; ++i) { + infrared_test_run_decoder(InfraredProtocolNEC42ext, i); + } } MU_TEST(infrared_test_encoder_sirc) { - infrared_test_run_encoder(InfraredProtocolSIRC, 1); - infrared_test_run_encoder(InfraredProtocolSIRC, 2); + for(uint32_t i = 1; i <= 2; ++i) { + infrared_test_run_encoder(InfraredProtocolSIRC, i); + } } MU_TEST(infrared_test_decoder_sirc) { - infrared_test_run_decoder(InfraredProtocolSIRC, 3); - infrared_test_run_decoder(InfraredProtocolSIRC, 1); - infrared_test_run_decoder(InfraredProtocolSIRC, 2); - infrared_test_run_decoder(InfraredProtocolSIRC, 4); - infrared_test_run_decoder(InfraredProtocolSIRC, 5); + for(uint32_t i = 1; i <= 5; ++i) { + infrared_test_run_decoder(InfraredProtocolSIRC, 5); + } } MU_TEST(infrared_test_decoder_rc5) { infrared_test_run_decoder(InfraredProtocolRC5X, 1); - infrared_test_run_decoder(InfraredProtocolRC5, 1); - infrared_test_run_decoder(InfraredProtocolRC5, 2); - infrared_test_run_decoder(InfraredProtocolRC5, 3); - infrared_test_run_decoder(InfraredProtocolRC5, 4); - infrared_test_run_decoder(InfraredProtocolRC5, 5); - infrared_test_run_decoder(InfraredProtocolRC5, 6); - infrared_test_run_decoder(InfraredProtocolRC5, 7); + + for(uint32_t i = 1; i <= 7; ++i) { + infrared_test_run_decoder(InfraredProtocolRC5, i); + } } MU_TEST(infrared_test_encoder_rc5x) { @@ -492,21 +492,21 @@ MU_TEST(infrared_test_encoder_rc6) { } MU_TEST(infrared_test_decoder_kaseikyo) { - infrared_test_run_decoder(InfraredProtocolKaseikyo, 1); - infrared_test_run_decoder(InfraredProtocolKaseikyo, 2); - infrared_test_run_decoder(InfraredProtocolKaseikyo, 3); - infrared_test_run_decoder(InfraredProtocolKaseikyo, 4); - infrared_test_run_decoder(InfraredProtocolKaseikyo, 5); - infrared_test_run_decoder(InfraredProtocolKaseikyo, 6); + for(uint32_t i = 1; i <= 6; ++i) { + infrared_test_run_decoder(InfraredProtocolKaseikyo, i); + } } MU_TEST(infrared_test_decoder_rca) { - infrared_test_run_decoder(InfraredProtocolRCA, 1); - infrared_test_run_decoder(InfraredProtocolRCA, 2); - infrared_test_run_decoder(InfraredProtocolRCA, 3); - infrared_test_run_decoder(InfraredProtocolRCA, 4); - infrared_test_run_decoder(InfraredProtocolRCA, 5); - infrared_test_run_decoder(InfraredProtocolRCA, 6); + for(uint32_t i = 1; i <= 6; ++i) { + infrared_test_run_decoder(InfraredProtocolRCA, i); + } +} + +MU_TEST(infrared_test_decoder_pioneer) { + for(uint32_t i = 1; i <= 11; ++i) { + infrared_test_run_decoder(InfraredProtocolPioneer, i); + } } MU_TEST(infrared_test_encoder_decoder_all) { @@ -520,6 +520,7 @@ MU_TEST(infrared_test_encoder_decoder_all) { infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1); infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1); infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1); + infrared_test_run_encoder_decoder(InfraredProtocolPioneer, 1); } MU_TEST_SUITE(infrared_test) { @@ -539,6 +540,7 @@ MU_TEST_SUITE(infrared_test) { MU_RUN_TEST(infrared_test_decoder_necext1); MU_RUN_TEST(infrared_test_decoder_kaseikyo); MU_RUN_TEST(infrared_test_decoder_rca); + MU_RUN_TEST(infrared_test_decoder_pioneer); MU_RUN_TEST(infrared_test_decoder_mixed); MU_RUN_TEST(infrared_test_encoder_decoder_all); } diff --git a/applications/debug/unit_tests/resources/unit_tests/infrared/test_pioneer.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_pioneer.irtest new file mode 100644 index 0000000000..f05b33eec7 --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/infrared/test_pioneer.irtest @@ -0,0 +1,205 @@ +Filetype: IR tests file +Version: 1 +# +name: decoder_input1 +type: raw +data: 25557 8437 4188 571 1538 595 1514 567 1542 570 1539 573 501 565 1544 568 506 571 1539 573 501 565 509 568 508 569 506 571 1538 574 501 565 1543 569 506 571 504 573 1536 566 1544 568 506 592 1517 574 1535 567 507 570 505 572 1537 575 500 566 508 600 1509 572 503 574 501 565 1544 568 1540 593 +# +name: decoder_expected1 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AF 00 00 00 +command: 36 00 00 00 +repeat: false +# +name: decoder_input2 +type: raw +data: 25609 8444 4152 564 1568 544 1565 547 1561 541 1568 544 530 547 1536 566 510 567 1567 545 529 548 526 540 535 542 508 569 1539 573 527 539 1543 569 506 571 504 573 1561 541 508 569 507 570 1538 564 1545 567 507 570 505 572 1537 565 509 568 1541 571 1538 564 511 566 509 568 1539 573 1537 596 +# +name: decoder_expected2 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AF 00 00 00 +command: 32 00 00 00 +repeat: false +# +name: decoder_input3 +type: raw +data: 25582 8448 4176 571 1537 565 1544 568 1540 572 1537 575 500 566 1542 570 505 572 1537 575 500 566 508 569 506 571 504 573 1536 565 510 567 1542 570 504 573 1536 566 1543 569 506 571 504 573 1536 566 1543 569 506 571 504 573 502 575 500 566 1542 570 1539 573 502 575 500 566 1542 570 1540 572 +# +name: decoder_expected3 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AF 00 00 00 +command: 33 00 00 00 +repeat: false +# +name: decoder_input4 +type: raw +data: 25594 8443 4181 568 1542 570 505 572 1538 564 1545 567 508 569 1540 572 504 573 1536 566 510 567 1542 571 505 572 504 573 1562 540 510 567 1543 570 506 571 504 573 503 574 501 565 510 567 509 568 507 570 1539 573 502 565 1545 568 1542 571 1539 573 1536 566 1544 569 1541 572 503 574 1537 565 +# +name: decoder_expected4 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 40 00 00 00 +repeat: false +# +name: decoder_input5 +type: raw +data: 25556 8475 4150 597 1512 600 476 601 1509 603 1506 595 480 597 1512 600 476 601 1508 594 482 595 1515 597 478 599 477 600 1510 602 473 604 1506 595 480 597 1513 599 476 601 475 602 474 603 472 594 482 595 1514 598 477 600 476 601 1508 594 1516 596 1513 599 1510 602 1507 595 480 597 1513 599 +# +name: decoder_expected5 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 41 00 00 00 +repeat: false +# +name: decoder_input6 +type: raw +data: 25567 8471 4155 604 1506 596 480 597 1513 599 1510 603 473 594 1515 597 478 599 1511 602 474 603 1507 595 480 597 479 598 1511 602 474 603 1506 596 480 597 478 599 1511 602 474 603 472 594 481 596 479 598 1512 601 474 603 1506 596 479 598 1511 602 1508 594 1515 598 1512 600 475 602 1507 595 +# +name: decoder_expected6 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 42 00 00 00 +repeat: false +# +name: decoder_input7 +type: raw +data: 25584 8444 4180 569 1541 572 504 573 1536 566 1544 569 507 570 1539 574 501 566 1569 596 455 570 1540 573 502 575 501 565 1544 569 507 570 1565 548 503 574 1535 567 1543 570 506 571 529 548 502 565 511 566 1543 601 475 571 504 573 503 574 1536 566 1543 570 1539 574 1536 566 509 568 1541 572 +# +name: decoder_expected7 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 43 00 00 00 +repeat: false +# +name: decoder_input8 +type: raw +data: 25562 8445 4181 568 1543 570 505 572 1538 575 1535 567 508 569 1539 573 503 595 1514 567 508 600 1509 572 503 595 481 596 1513 568 507 601 1508 573 502 575 501 566 1543 570 506 571 504 573 1536 566 510 567 508 600 475 571 1539 573 502 575 1534 568 1542 571 505 572 1537 575 1534 568 1542 571 +# +name: decoder_expected8 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 12 00 00 00 +repeat: false +# +name: decoder_input9 +type: raw +data: 25558 8470 4152 597 1513 600 476 601 1508 594 1515 598 478 599 1509 593 483 594 1515 598 478 599 1510 603 474 592 482 595 1514 599 477 600 1509 593 483 594 481 596 1513 600 476 601 1508 594 1515 598 478 599 476 601 474 593 1517 596 479 598 1512 601 474 603 472 594 1515 598 1511 602 1508 594 +# +name: decoder_expected9 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 1A 00 00 00 +repeat: false +# +name: decoder_input10 +type: raw +data: 25587 8442 4179 601 1507 595 481 565 1544 600 1509 593 482 595 1513 568 507 570 1539 594 481 565 1544 600 476 570 505 593 1516 597 479 598 1511 591 484 593 481 575 1534 600 476 570 1539 595 480 597 478 599 476 570 505 593 1517 564 511 597 1511 602 474 572 1537 597 1513 600 1509 572 1537 565 +# +name: decoder_expected10 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 0A 00 00 00 +repeat: false +# +name: decoder_input11 +type: raw +data: 25554 8474 4149 600 1510 603 472 594 1515 597 1512 601 475 602 1507 595 480 597 1513 599 475 602 1508 594 481 596 479 598 1512 601 474 603 1506 596 479 598 1512 601 1508 594 481 596 1513 599 476 601 474 603 472 594 481 596 480 597 478 599 1510 603 473 593 1515 597 1512 601 1509 603 1506 596 +# +name: decoder_expected11 +type: parsed_array +count: 1 +# +protocol: Pioneer +address: AD 00 00 00 +command: 0B 00 00 00 +repeat: false +# +name: encoder_decoder_input1 +type: parsed_array +count: 11 +# +protocol: Pioneer +address: AF 00 00 00 +command: 36 00 00 00 +repeat: false +# +protocol: Pioneer +address: AF 00 00 00 +command: 32 00 00 00 +repeat: false +# +protocol: Pioneer +address: AF 00 00 00 +command: 33 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 40 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 41 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 42 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 43 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 12 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 1A 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 0A 00 00 00 +repeat: false +# +protocol: Pioneer +address: AD 00 00 00 +command: 0B 00 00 00 +repeat: false +# diff --git a/lib/infrared/encoder_decoder/common/infrared_common_i.h b/lib/infrared/encoder_decoder/common/infrared_common_i.h index f34e81edae..05c5faf8d2 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_i.h +++ b/lib/infrared/encoder_decoder/common/infrared_common_i.h @@ -18,7 +18,6 @@ typedef InfraredStatus ( typedef struct { InfraredTimings timings; bool manchester_start_from_space; - bool no_stop_bit; uint8_t databit_len[4]; InfraredCommonDecode decode; InfraredCommonDecodeRepeat decode_repeat; diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index 56f2c3f9ee..c2e48ac32e 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -12,6 +12,7 @@ #include "sirc/infrared_protocol_sirc.h" #include "kaseikyo/infrared_protocol_kaseikyo.h" #include "rca/infrared_protocol_rca.h" +#include "pioneer/infrared_protocol_pioneer.h" typedef struct { InfraredAlloc alloc; @@ -114,6 +115,20 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .free = infrared_encoder_sirc_free}, .get_protocol_variant = infrared_protocol_sirc_get_variant, }, + { + .decoder = + {.alloc = infrared_decoder_pioneer_alloc, + .decode = infrared_decoder_pioneer_decode, + .reset = infrared_decoder_pioneer_reset, + .check_ready = infrared_decoder_pioneer_check_ready, + .free = infrared_decoder_pioneer_free}, + .encoder = + {.alloc = infrared_encoder_pioneer_alloc, + .encode = infrared_encoder_pioneer_encode, + .reset = infrared_encoder_pioneer_reset, + .free = infrared_encoder_pioneer_free}, + .get_protocol_variant = infrared_protocol_pioneer_get_variant, + }, { .decoder = {.alloc = infrared_decoder_kaseikyo_alloc, diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index ada449b983..377ce0ef27 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -34,6 +34,8 @@ typedef enum { InfraredProtocolSIRC20, InfraredProtocolKaseikyo, InfraredProtocolRCA, + InfraredProtocolPioneer, + /* Add new protocols here */ InfraredProtocolMAX, } InfraredProtocol; diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c index 0c61be3bf8..63179cff39 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c @@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_kaseikyo = { .min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME, }, .databit_len[0] = 48, - .no_stop_bit = false, .decode = infrared_common_decode_pdwm, .encode = infrared_common_encode_pdwm, .interpret = infrared_decoder_kaseikyo_interpret, diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c index 3444f78b61..bfd6d55fba 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c @@ -16,7 +16,6 @@ const InfraredCommonProtocolSpec infrared_protocol_nec = { }, .databit_len[0] = 42, .databit_len[1] = 32, - .no_stop_bit = false, .decode = infrared_common_decode_pdwm, .encode = infrared_common_encode_pdwm, .interpret = infrared_decoder_nec_interpret, diff --git a/lib/infrared/encoder_decoder/pioneer/infrared_decoder_pioneer.c b/lib/infrared/encoder_decoder/pioneer/infrared_decoder_pioneer.c new file mode 100644 index 0000000000..43c843bab3 --- /dev/null +++ b/lib/infrared/encoder_decoder/pioneer/infrared_decoder_pioneer.c @@ -0,0 +1,57 @@ +#include "infrared_protocol_pioneer_i.h" +#include + +InfraredMessage* infrared_decoder_pioneer_check_ready(void* ctx) { + return infrared_common_decoder_check_ready(ctx); +} + +bool infrared_decoder_pioneer_interpret(InfraredCommonDecoder* decoder) { + furi_assert(decoder); + + uint32_t* data = (void*)&decoder->data[0]; + uint8_t address = 0; + uint8_t command = 0; + InfraredProtocol protocol = InfraredProtocolUnknown; + + if(decoder->databit_cnt == decoder->protocol->databit_len[0] || + decoder->databit_cnt == decoder->protocol->databit_len[1]) { + address = *data & 0xFF; + uint8_t real_address_checksum = ~address; + uint8_t address_checksum = (*data >> 8) & 0xFF; + command = (*data >> 16) & 0xFF; + uint8_t real_command_checksum = ~command; + uint8_t command_checksum = (*data >> 24) & 0xFF; + if(address_checksum != real_address_checksum) { + return false; + } + if(command_checksum != real_command_checksum) { + return false; + } + protocol = InfraredProtocolPioneer; + } else { + return false; + } + + decoder->message.protocol = protocol; + decoder->message.address = address; + decoder->message.command = command; + decoder->message.repeat = false; + + return true; +} + +void* infrared_decoder_pioneer_alloc(void) { + return infrared_common_decoder_alloc(&infrared_protocol_pioneer); +} + +InfraredMessage* infrared_decoder_pioneer_decode(void* decoder, bool level, uint32_t duration) { + return infrared_common_decode(decoder, level, duration); +} + +void infrared_decoder_pioneer_free(void* decoder) { + infrared_common_decoder_free(decoder); +} + +void infrared_decoder_pioneer_reset(void* decoder) { + infrared_common_decoder_reset(decoder); +} diff --git a/lib/infrared/encoder_decoder/pioneer/infrared_encoder_pioneer.c b/lib/infrared/encoder_decoder/pioneer/infrared_encoder_pioneer.c new file mode 100644 index 0000000000..b72643d753 --- /dev/null +++ b/lib/infrared/encoder_decoder/pioneer/infrared_encoder_pioneer.c @@ -0,0 +1,61 @@ +#include "infrared_protocol_pioneer_i.h" +#include + +void infrared_encoder_pioneer_reset(void* encoder_ptr, const InfraredMessage* message) { + furi_assert(encoder_ptr); + furi_assert(message); + + InfraredCommonEncoder* encoder = encoder_ptr; + infrared_common_encoder_reset(encoder); + + uint8_t* data = encoder->data; + + if(message->protocol == InfraredProtocolPioneer) { + data[0] = message->address & 0xFF; + data[1] = ~(message->address & 0xFF); + data[2] = message->command & 0xFF; + data[3] = ~(message->command & 0xFF); + data[4] = 0; + encoder->bits_to_encode = encoder->protocol->databit_len[0]; + } else { + furi_crash(); + } +} + +void* infrared_encoder_pioneer_alloc(void) { + return infrared_common_encoder_alloc(&infrared_protocol_pioneer); +} + +void infrared_encoder_pioneer_free(void* encoder_ptr) { + infrared_common_encoder_free(encoder_ptr); +} + +InfraredStatus infrared_encoder_pioneer_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level) { + furi_assert(encoder); + + *duration = INFRARED_PIONEER_SILENCE; + *level = false; + + encoder->timings_sum = 0; + encoder->timings_encoded = 1; + encoder->bits_encoded = 0; + encoder->state = InfraredCommonEncoderStatePreamble; + + return InfraredStatusOk; +} + +InfraredStatus + infrared_encoder_pioneer_encode(void* encoder_ptr, uint32_t* duration, bool* level) { + InfraredCommonEncoder* encoder = encoder_ptr; + + InfraredStatus status = infrared_common_encode(encoder, duration, level); + if((status == InfraredStatusOk) && (encoder->bits_encoded == encoder->bits_to_encode)) { + furi_assert(!*level); + status = InfraredStatusDone; + encoder->state = InfraredCommonEncoderStateEncodeRepeat; + } + return status; +} diff --git a/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.c b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.c new file mode 100644 index 0000000000..dec60f17f1 --- /dev/null +++ b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_pioneer_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_pioneer = { + .timings = + { + .preamble_mark = INFRARED_PIONEER_PREAMBLE_MARK, + .preamble_space = INFRARED_PIONEER_PREAMBLE_SPACE, + .bit1_mark = INFRARED_PIONEER_BIT1_MARK, + .bit1_space = INFRARED_PIONEER_BIT1_SPACE, + .bit0_mark = INFRARED_PIONEER_BIT0_MARK, + .bit0_space = INFRARED_PIONEER_BIT0_SPACE, + .preamble_tolerance = INFRARED_PIONEER_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_PIONEER_BIT_TOLERANCE, + .silence_time = INFRARED_PIONEER_SILENCE, + .min_split_time = INFRARED_PIONEER_MIN_SPLIT_TIME, + }, + .databit_len[0] = 33, + .databit_len[1] = 32, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_pioneer_interpret, + .decode_repeat = NULL, + .encode_repeat = infrared_encoder_pioneer_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_pioneer = { + .name = "Pioneer", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_PIONEER_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_PIONEER_DUTY_CYCLE, + .repeat_count = INFRARED_PIONEER_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_pioneer_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolPioneer) + return &infrared_protocol_variant_pioneer; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.h b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.h new file mode 100644 index 0000000000..d350cdaee2 --- /dev/null +++ b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer.h @@ -0,0 +1,36 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* Pioneer SR protocol description +* http://www.adrian-kingston.com/IRFormatPioneer.htm +**************************************************************************************************** +* Preamble Preamble Pulse Width Modulation Pause Entirely repeat +* mark space up to period message.. +* +* 8500 4250 33 bits (500, 1500) ...26000 8500 4250 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _ +* +* In 33 bits of data there is: +* - 8 bits address +* - 8 bits address inverse +* - 8 bits command +* - 8 bits command inverse +* - 1 stop bit +***************************************************************************************************/ + +void* infrared_decoder_pioneer_alloc(void); +void infrared_decoder_pioneer_reset(void* decoder); +InfraredMessage* infrared_decoder_pioneer_check_ready(void* decoder); +void infrared_decoder_pioneer_free(void* decoder); +InfraredMessage* infrared_decoder_pioneer_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_pioneer_alloc(void); +void infrared_encoder_pioneer_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_pioneer_free(void* decoder); +InfraredStatus + infrared_encoder_pioneer_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_pioneer_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer_i.h b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer_i.h new file mode 100644 index 0000000000..2ff7f7e3a0 --- /dev/null +++ b/lib/infrared/encoder_decoder/pioneer/infrared_protocol_pioneer_i.h @@ -0,0 +1,25 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_PIONEER_CARRIER_FREQUENCY 40000 +#define INFRARED_PIONEER_DUTY_CYCLE 0.33 +#define INFRARED_PIONEER_PREAMBLE_MARK 8500 +#define INFRARED_PIONEER_PREAMBLE_SPACE 4225 +#define INFRARED_PIONEER_BIT1_MARK 500 +#define INFRARED_PIONEER_BIT1_SPACE 1500 +#define INFRARED_PIONEER_BIT0_MARK 500 +#define INFRARED_PIONEER_BIT0_SPACE 500 +#define INFRARED_PIONEER_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_PIONEER_BIT_TOLERANCE 120 // us +#define INFRARED_PIONEER_SILENCE 26000 +#define INFRARED_PIONEER_MIN_SPLIT_TIME (INFRARED_PIONEER_SILENCE) +#define INFRARED_PIONEER_REPEAT_COUNT_MIN 2 + +extern const InfraredCommonProtocolSpec infrared_protocol_pioneer; + +bool infrared_decoder_pioneer_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_pioneer_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); \ No newline at end of file diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c index 8e1e76dbd3..f4a34ae2e0 100644 --- a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c @@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_rca = { .min_split_time = INFRARED_RCA_MIN_SPLIT_TIME, }, .databit_len[0] = 24, - .no_stop_bit = false, .decode = infrared_common_decode_pdwm, .encode = infrared_common_encode_pdwm, .interpret = infrared_decoder_rca_interpret, diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c index ca78726acf..5877911cdb 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c @@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_samsung32 = { .min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME, }, .databit_len[0] = 32, - .no_stop_bit = false, .decode = infrared_common_decode_pdwm, .encode = infrared_common_encode_pdwm, .interpret = infrared_decoder_samsung32_interpret, diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c index b527fba980..f5950b88d7 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c @@ -17,7 +17,6 @@ const InfraredCommonProtocolSpec infrared_protocol_sirc = { .databit_len[0] = 20, .databit_len[1] = 15, .databit_len[2] = 12, - .no_stop_bit = true, .decode = infrared_common_decode_pdwm, .encode = infrared_common_encode_pdwm, .interpret = infrared_decoder_sirc_interpret, From 46a90ec97f2965f173ace28b023d8745bfe5d8c3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Mar 2024 23:43:09 +0300 Subject: [PATCH 09/13] BLE/GAP fixes by hedger https://github.com/flipperdevices/flipperzero-firmware/pull/3533/files --- SConstruct | 2 +- scripts/fbt/util.py | 9 +++++---- targets/f18/api_symbols.csv | 4 ++-- targets/f7/api_symbols.csv | 2 +- targets/f7/ble_glue/ble_event_thread.c | 2 +- targets/f7/ble_glue/ble_glue.c | 4 ++-- targets/f7/ble_glue/furi_ble/event_dispatcher.c | 10 +++++----- targets/f7/ble_glue/furi_ble/gatt.c | 2 +- targets/f7/ble_glue/gap.c | 10 ++++++---- 9 files changed, 24 insertions(+), 21 deletions(-) diff --git a/SConstruct b/SConstruct index 52d286953c..83ee626f1b 100644 --- a/SConstruct +++ b/SConstruct @@ -7,7 +7,7 @@ # construction of certain targets behind command-line options. import os -from fbt.util import path_as_posix +from fbt.util import open_browser_action DefaultEnvironment(tools=[]) diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index f08c8f4fa2..27b488f737 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -105,7 +105,8 @@ def __call__(self, target, source, env, for_signature): return self.fix_path(env.subst(self.pathobj)) -def path_as_posix(path): - if SCons.Platform.platform_default() == "win32": - return path.replace(os.path.sep, os.path.altsep) - return path +def open_browser_action(target, source, env): + if sys.platform == "darwin": + subprocess.run(["open", source[0].abspath]) + else: + webbrowser.open(source[0].abspath) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 8f6b8530e1..e11c857590 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -639,8 +639,8 @@ Function,+,ble_glue_is_alive,_Bool, Function,+,ble_glue_is_radio_stack_ready,_Bool, Function,+,ble_glue_reinit_c2,_Bool, Function,+,ble_glue_set_key_storage_changed_callback,void,"BleGlueKeyStorageChangedCallback, void*" -Function,+,ble_glue_start,_Bool, -Function,+,ble_glue_stop,void, +Function,-,ble_glue_start,_Bool, +Function,-,ble_glue_stop,void, Function,+,ble_glue_wait_for_c2_start,_Bool,int32_t Function,-,ble_profile_hid_consumer_key_press,_Bool,"FuriHalBleProfileBase*, uint16_t" Function,-,ble_profile_hid_consumer_key_release,_Bool,"FuriHalBleProfileBase*, uint16_t" diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 8ca458eed7..3d9160c9c1 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -689,7 +689,7 @@ Function,-,ble_app_get_key_storage_buff,void,"uint8_t**, uint16_t*" Function,-,ble_app_init,_Bool, Function,-,ble_event_app_notification,BleEventFlowStatus,void* Function,-,ble_event_dispatcher_init,void, -Function,+,ble_event_dispatcher_process_event,BleEventFlowStatus,void* +Function,-,ble_event_dispatcher_process_event,BleEventFlowStatus,void* Function,+,ble_event_dispatcher_register_svc_handler,GapSvcEventHandler*,"BleSvcEventHandlerCb, void*" Function,-,ble_event_dispatcher_reset,void, Function,+,ble_event_dispatcher_unregister_svc_handler,void,GapSvcEventHandler* diff --git a/targets/f7/ble_glue/ble_event_thread.c b/targets/f7/ble_glue/ble_event_thread.c index 6f9a1cdcd3..deafbb9a48 100644 --- a/targets/f7/ble_glue/ble_event_thread.c +++ b/targets/f7/ble_glue/ble_event_thread.c @@ -80,7 +80,7 @@ void ble_event_thread_stop(void) { } FuriThreadId thread_id = furi_thread_get_id(event_thread); - furi_assert(thread_id); + furi_check(thread_id); furi_thread_flags_set(thread_id, BLE_EVENT_THREAD_FLAG_KILL_THREAD); furi_thread_join(event_thread); furi_thread_free(event_thread); diff --git a/targets/f7/ble_glue/ble_glue.c b/targets/f7/ble_glue/ble_glue.c index 91cb020d72..9d5a1e3f91 100644 --- a/targets/f7/ble_glue/ble_glue.c +++ b/targets/f7/ble_glue/ble_glue.c @@ -224,7 +224,7 @@ bool ble_glue_wait_for_c2_start(int32_t timeout_ms) { } bool ble_glue_start(void) { - furi_assert(ble_glue); + furi_check(ble_glue); if(ble_glue->status != BleGlueStatusC2Started) { return false; @@ -243,7 +243,7 @@ bool ble_glue_start(void) { } void ble_glue_stop(void) { - furi_assert(ble_glue); + furi_check(ble_glue); ble_event_thread_stop(); // Free resources diff --git a/targets/f7/ble_glue/furi_ble/event_dispatcher.c b/targets/f7/ble_glue/furi_ble/event_dispatcher.c index ce3661d6d9..19f60afb54 100644 --- a/targets/f7/ble_glue/furi_ble/event_dispatcher.c +++ b/targets/f7/ble_glue/furi_ble/event_dispatcher.c @@ -50,14 +50,14 @@ BleEventFlowStatus ble_event_dispatcher_process_event(void* payload) { } void ble_event_dispatcher_init(void) { - furi_assert(!initialized); - - GapSvcEventHandlerList_init(handlers); - initialized = true; + if(!initialized) { + GapSvcEventHandlerList_init(handlers); + initialized = true; + } } void ble_event_dispatcher_reset(void) { - furi_assert(initialized); + furi_check(initialized); furi_check(GapSvcEventHandlerList_size(handlers) == 0); GapSvcEventHandlerList_clear(handlers); diff --git a/targets/f7/ble_glue/furi_ble/gatt.c b/targets/f7/ble_glue/furi_ble/gatt.c index dcea5f9873..bbcf86b0e5 100644 --- a/targets/f7/ble_glue/furi_ble/gatt.c +++ b/targets/f7/ble_glue/furi_ble/gatt.c @@ -90,7 +90,7 @@ bool ble_gatt_characteristic_update( uint16_t svc_handle, BleGattCharacteristicInstance* char_instance, const void* source) { - furi_assert(char_instance); + furi_check(char_instance); const BleGattCharacteristicParams* char_descriptor = char_instance->characteristic; FURI_LOG_D(TAG, "Updating %s char", char_descriptor->name); diff --git a/targets/f7/ble_glue/gap.c b/targets/f7/ble_glue/gap.c index faac3be456..361da67494 100644 --- a/targets/f7/ble_glue/gap.c +++ b/targets/f7/ble_glue/gap.c @@ -75,7 +75,7 @@ static inline void fetch_rssi() { } static void gap_verify_connection_parameters(Gap* gap) { - furi_assert(gap); + furi_check(gap); FURI_LOG_I( TAG, @@ -515,6 +515,8 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) { return false; } + furi_check(gap == NULL); + gap = malloc(sizeof(Gap)); gap->config = config; // Create advertising timer @@ -532,13 +534,13 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) { gap->conn_rssi = 127; gap->time_rssi_sample = 0; + // Command queue allocation + gap->command_queue = furi_message_queue_alloc(8, sizeof(GapCommand)); + // Thread configuration gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap); furi_thread_start(gap->thread); - // Command queue allocation - gap->command_queue = furi_message_queue_alloc(8, sizeof(GapCommand)); - uint8_t adv_service_uid[2]; gap->service.adv_svc_uuid_len = 1; adv_service_uid[0] = gap->config->adv_service_uuid & 0xff; From c3236560372f15ffa3fd3eb53e55cb8c49174d73 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:18:26 +0300 Subject: [PATCH 10/13] js modules updates by Willy-JL --- applications/system/js_app/application.fam | 8 + .../js_app/examples/apps/Scripts/textbox.js | 24 +++ .../system/js_app/modules/js_blebeacon.c | 6 +- .../system/js_app/modules/js_keyboard.c | 6 +- .../system/js_app/modules/js_submenu.c | 6 +- .../system/js_app/modules/js_textbox.c | 202 ++++++++++++++++++ 6 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 applications/system/js_app/examples/apps/Scripts/textbox.js create mode 100644 applications/system/js_app/modules/js_textbox.c diff --git a/applications/system/js_app/application.fam b/applications/system/js_app/application.fam index 961834dcc5..98feabb6de 100644 --- a/applications/system/js_app/application.fam +++ b/applications/system/js_app/application.fam @@ -94,3 +94,11 @@ App( requires=["js_app"], sources=["modules/js_gpio.c"], ) + +App( + appid="js_textbox", + apptype=FlipperAppType.PLUGIN, + entry_point="js_textbox_ep", + requires=["js_app"], + sources=["modules/js_textbox.c"], +) diff --git a/applications/system/js_app/examples/apps/Scripts/textbox.js b/applications/system/js_app/examples/apps/Scripts/textbox.js new file mode 100644 index 0000000000..a260e8a21e --- /dev/null +++ b/applications/system/js_app/examples/apps/Scripts/textbox.js @@ -0,0 +1,24 @@ +let textbox = require("textbox"); + +// Set config before setting text +// Focus (start / end), Font (text / hex) +textbox.setConfig("end", "text"); + +let text = "Example dynamic updating textbox\n"; +textbox.setText(text); + +// Non-blocking, can keep updating text after, can close in JS or in GUI +textbox.show(); + +let i = 0; +while (textbox.isOpen() && i < 20) { + print("console", i++); + text += "textbox " + to_string(i) + "\n"; + textbox.setText(text); + delay(500); +} + +// If not closed by user (instead i < 20 is false above), close forcefully +if (textbox.isOpen()) { + textbox.close(); +} diff --git a/applications/system/js_app/modules/js_blebeacon.c b/applications/system/js_app/modules/js_blebeacon.c index 4b661a2cf6..7dc212b6a4 100644 --- a/applications/system/js_app/modules/js_blebeacon.c +++ b/applications/system/js_app/modules/js_blebeacon.c @@ -19,9 +19,9 @@ typedef struct { static JsBlebeaconInst* get_this_ctx(struct mjs* mjs) { mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); - JsBlebeaconInst* storage = mjs_get_ptr(mjs, obj_inst); - furi_assert(storage); - return storage; + JsBlebeaconInst* blebeacon = mjs_get_ptr(mjs, obj_inst); + furi_assert(blebeacon); + return blebeacon; } static void ret_bad_args(struct mjs* mjs, const char* error) { diff --git a/applications/system/js_app/modules/js_keyboard.c b/applications/system/js_app/modules/js_keyboard.c index 6d7ce0e579..2bfb296e00 100644 --- a/applications/system/js_app/modules/js_keyboard.c +++ b/applications/system/js_app/modules/js_keyboard.c @@ -20,9 +20,9 @@ static void ret_bad_args(struct mjs* mjs, const char* error) { static JsKeyboardInst* get_this_ctx(struct mjs* mjs) { mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); - JsKeyboardInst* storage = mjs_get_ptr(mjs, obj_inst); - furi_assert(storage); - return storage; + JsKeyboardInst* keyboard = mjs_get_ptr(mjs, obj_inst); + furi_assert(keyboard); + return keyboard; } static void keyboard_callback(void* context) { diff --git a/applications/system/js_app/modules/js_submenu.c b/applications/system/js_app/modules/js_submenu.c index 1d2f5db554..8c8d95fab1 100644 --- a/applications/system/js_app/modules/js_submenu.c +++ b/applications/system/js_app/modules/js_submenu.c @@ -12,9 +12,9 @@ typedef struct { static JsSubmenuInst* get_this_ctx(struct mjs* mjs) { mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); - JsSubmenuInst* storage = mjs_get_ptr(mjs, obj_inst); - furi_assert(storage); - return storage; + JsSubmenuInst* submenu = mjs_get_ptr(mjs, obj_inst); + furi_assert(submenu); + return submenu; } static void ret_bad_args(struct mjs* mjs, const char* error) { diff --git a/applications/system/js_app/modules/js_textbox.c b/applications/system/js_app/modules/js_textbox.c new file mode 100644 index 0000000000..199cd2a0eb --- /dev/null +++ b/applications/system/js_app/modules/js_textbox.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include "../js_modules.h" + +typedef struct { + TextBox* text_box; + ViewDispatcher* view_dispatcher; + FuriThread* thread; +} JsTextboxInst; + +static JsTextboxInst* get_this_ctx(struct mjs* mjs) { + mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); + JsTextboxInst* textbox = mjs_get_ptr(mjs, obj_inst); + furi_assert(textbox); + return textbox; +} + +static void ret_bad_args(struct mjs* mjs, const char* error) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "%s", error); + mjs_return(mjs, MJS_UNDEFINED); +} + +static bool check_arg_count(struct mjs* mjs, size_t count) { + size_t num_args = mjs_nargs(mjs); + if(num_args != count) { + ret_bad_args(mjs, "Wrong argument count"); + return false; + } + return true; +} + +static void js_textbox_set_config(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 2)) return; + + TextBoxFocus set_focus = TextBoxFocusStart; + mjs_val_t focus_arg = mjs_arg(mjs, 0); + const char* focus = mjs_get_string(mjs, &focus_arg, NULL); + if(!focus) { + ret_bad_args(mjs, "Focus must be a string"); + return; + } else { + if(!strncmp(focus, "start", strlen("start"))) { + set_focus = TextBoxFocusStart; + } else if(!strncmp(focus, "end", strlen("end"))) { + set_focus = TextBoxFocusEnd; + } else { + ret_bad_args(mjs, "Bad focus value"); + return; + } + } + + TextBoxFont set_font = TextBoxFontText; + mjs_val_t font_arg = mjs_arg(mjs, 1); + const char* font = mjs_get_string(mjs, &font_arg, NULL); + if(!font) { + ret_bad_args(mjs, "Font must be a string"); + return; + } else { + if(!strncmp(font, "text", strlen("text"))) { + set_font = TextBoxFontText; + } else if(!strncmp(font, "hex", strlen("hex"))) { + set_font = TextBoxFontHex; + } else { + ret_bad_args(mjs, "Bad font value"); + return; + } + } + + text_box_set_focus(textbox->text_box, set_focus); + text_box_set_font(textbox->text_box, set_font); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_textbox_set_text(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 1)) return; + + mjs_val_t text_arg = mjs_arg(mjs, 0); + const char* text = mjs_get_string(mjs, &text_arg, NULL); + if(!text) { + ret_bad_args(mjs, "Text must be a string"); + return; + } + + text_box_set_text(textbox->text_box, text); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_textbox_is_open(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 0)) return; + + mjs_return(mjs, mjs_mk_boolean(mjs, !!textbox->thread)); +} + +static void textbox_deinit(void* context) { + JsTextboxInst* textbox = context; + furi_thread_join(textbox->thread); + furi_thread_free(textbox->thread); + textbox->thread = NULL; + + view_dispatcher_remove_view(textbox->view_dispatcher, 0); + view_dispatcher_free(textbox->view_dispatcher); + textbox->view_dispatcher = NULL; + furi_record_close(RECORD_GUI); + + text_box_reset(textbox->text_box); +} + +static void textbox_callback(void* context, uint32_t arg) { + UNUSED(arg); + textbox_deinit(context); +} + +static bool textbox_exit(void* context) { + JsTextboxInst* textbox = context; + view_dispatcher_stop(textbox->view_dispatcher); + furi_timer_pending_callback(textbox_callback, textbox, 0); + return true; +} + +static int32_t textbox_thread(void* context) { + ViewDispatcher* view_dispatcher = context; + view_dispatcher_run(view_dispatcher); + return 0; +} + +static void js_textbox_show(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 0)) return; + + Gui* gui = furi_record_open(RECORD_GUI); + textbox->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(textbox->view_dispatcher); + view_dispatcher_add_view(textbox->view_dispatcher, 0, text_box_get_view(textbox->text_box)); + view_dispatcher_set_event_callback_context(textbox->view_dispatcher, textbox); + view_dispatcher_set_navigation_event_callback(textbox->view_dispatcher, textbox_exit); + view_dispatcher_attach_to_gui(textbox->view_dispatcher, gui, ViewDispatcherTypeFullscreen); + view_dispatcher_switch_to_view(textbox->view_dispatcher, 0); + + textbox->thread = + furi_thread_alloc_ex("JsTextbox", 1024, textbox_thread, textbox->view_dispatcher); + furi_thread_start(textbox->thread); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_textbox_close(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 0)) return; + + if(textbox->thread) { + view_dispatcher_stop(textbox->view_dispatcher); + textbox_deinit(textbox); + } + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void* js_textbox_create(struct mjs* mjs, mjs_val_t* object) { + JsTextboxInst* textbox = malloc(sizeof(JsTextboxInst)); + mjs_val_t textbox_obj = mjs_mk_object(mjs); + mjs_set(mjs, textbox_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, textbox)); + mjs_set(mjs, textbox_obj, "setConfig", ~0, MJS_MK_FN(js_textbox_set_config)); + mjs_set(mjs, textbox_obj, "setText", ~0, MJS_MK_FN(js_textbox_set_text)); + mjs_set(mjs, textbox_obj, "isOpen", ~0, MJS_MK_FN(js_textbox_is_open)); + mjs_set(mjs, textbox_obj, "show", ~0, MJS_MK_FN(js_textbox_show)); + mjs_set(mjs, textbox_obj, "close", ~0, MJS_MK_FN(js_textbox_close)); + textbox->text_box = text_box_alloc(); + *object = textbox_obj; + return textbox; +} + +static void js_textbox_destroy(void* inst) { + JsTextboxInst* textbox = inst; + if(textbox->thread) { + view_dispatcher_stop(textbox->view_dispatcher); + textbox_deinit(textbox); + } + text_box_free(textbox->text_box); + free(textbox); +} + +static const JsModuleDescriptor js_textbox_desc = { + "textbox", + js_textbox_create, + js_textbox_destroy, +}; + +static const FlipperAppPluginDescriptor textbox_plugin_descriptor = { + .appid = PLUGIN_APP_ID, + .ep_api_version = PLUGIN_API_VERSION, + .entry_point = &js_textbox_desc, +}; + +const FlipperAppPluginDescriptor* js_textbox_ep(void) { + return &textbox_plugin_descriptor; +} From 385c3c1c013c7f648e23d2fa6c914b48c654c6d3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:32:47 +0300 Subject: [PATCH 11/13] Sync textbox changes with OFW PR 3536 by Willy-JL https://github.com/flipperdevices/flipperzero-firmware/pull/3536/files --- applications/services/gui/modules/text_box.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/applications/services/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c index ff728108f5..55649c5f65 100644 --- a/applications/services/gui/modules/text_box.c +++ b/applications/services/gui/modules/text_box.c @@ -100,18 +100,19 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { line_num++; model->text = furi_string_get_cstr(model->text_formatted); model->text_pos = (char*)model->text; - if(model->focus == TextBoxFocusEnd && line_num > 5) { + uint8_t lines_on_screen = 56 / canvas_current_font_height(canvas); + if(model->focus == TextBoxFocusEnd && line_num > lines_on_screen) { // Set text position to 5th line from the end const char* end = model->text + furi_string_size(model->text_formatted); - for(size_t i = 0; i < line_num - 5; i++) { + for(size_t i = 0; i < line_num - lines_on_screen; i++) { while(model->text_pos < end) { if(*model->text_pos++ == '\n') break; } } - model->scroll_num = line_num - 4; - model->scroll_pos = line_num - 5; + model->scroll_num = line_num - (lines_on_screen - 1); + model->scroll_pos = line_num - lines_on_screen; } else { - model->scroll_num = MAX(line_num - 4, 0u); + model->scroll_num = MAX(line_num - (lines_on_screen - 1), 0u); model->scroll_pos = 0; } } From aaa7c81f999b9350ecd1e5e01b41bf1c14f1ab75 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:48:55 +0300 Subject: [PATCH 12/13] js modules updates 2 by Willy-JL --- .../js_app/examples/apps/Scripts/textbox.js | 16 ++- .../js_app/examples/apps/Scripts/uart_echo.js | 5 +- .../system/js_app/modules/js_badusb.c | 1 + .../system/js_app/modules/js_serial.c | 98 +++++++++++++++++-- .../system/js_app/modules/js_textbox.c | 32 +++++- 5 files changed, 133 insertions(+), 19 deletions(-) diff --git a/applications/system/js_app/examples/apps/Scripts/textbox.js b/applications/system/js_app/examples/apps/Scripts/textbox.js index a260e8a21e..bb6c4fc23a 100644 --- a/applications/system/js_app/examples/apps/Scripts/textbox.js +++ b/applications/system/js_app/examples/apps/Scripts/textbox.js @@ -1,11 +1,15 @@ let textbox = require("textbox"); -// Set config before setting text +// You should set config before adding text // Focus (start / end), Font (text / hex) textbox.setConfig("end", "text"); -let text = "Example dynamic updating textbox\n"; -textbox.setText(text); +// Can make sure it's empty before showing, in case of reusing in same script +// (Closing textbox already empties the text, but maybe you added more in a loop for example) +textbox.emptyText(); + +// Add default text +textbox.addText("Example dynamic updating textbox\n"); // Non-blocking, can keep updating text after, can close in JS or in GUI textbox.show(); @@ -13,8 +17,10 @@ textbox.show(); let i = 0; while (textbox.isOpen() && i < 20) { print("console", i++); - text += "textbox " + to_string(i) + "\n"; - textbox.setText(text); + + // Add text to textbox buffer + textbox.addText("textbox " + to_string(i) + "\n"); + delay(500); } diff --git a/applications/system/js_app/examples/apps/Scripts/uart_echo.js b/applications/system/js_app/examples/apps/Scripts/uart_echo.js index 60d44d078d..1cc0d8e62e 100644 --- a/applications/system/js_app/examples/apps/Scripts/uart_echo.js +++ b/applications/system/js_app/examples/apps/Scripts/uart_echo.js @@ -8,4 +8,7 @@ while (1) { let data_view = Uint8Array(rx_data); print("0x" + to_hex_string(data_view[0])); } -} \ No newline at end of file +} + +// There's also serial.end(), so you can serial.setup() again in same script +// You can also use serial.readAny(timeout), will avoid starving your loop with single byte reads diff --git a/applications/system/js_app/modules/js_badusb.c b/applications/system/js_app/modules/js_badusb.c index 349fde7ba2..a380141e84 100644 --- a/applications/system/js_app/modules/js_badusb.c +++ b/applications/system/js_app/modules/js_badusb.c @@ -81,6 +81,7 @@ static void js_badusb_quit_free(JsBadusbInst* badusb) { if(badusb->usb_if_prev) { furi_hal_hid_kb_release_all(); furi_check(furi_hal_usb_set_config(badusb->usb_if_prev, NULL)); + badusb->usb_if_prev = NULL; } if(badusb->hid_cfg) { free(badusb->hid_cfg); diff --git a/applications/system/js_app/modules/js_serial.c b/applications/system/js_app/modules/js_serial.c index 4f1b14f98c..a7d1398956 100644 --- a/applications/system/js_app/modules/js_serial.c +++ b/applications/system/js_app/modules/js_serial.c @@ -1,4 +1,5 @@ #include +#include #include #include "../js_modules.h" #include @@ -88,14 +89,49 @@ static void js_serial_setup(struct mjs* mjs) { return; } - serial->rx_stream = furi_stream_buffer_alloc(RX_BUF_LEN, 1); + expansion_disable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + serial->serial_handle = furi_hal_serial_control_acquire(serial_id); if(serial->serial_handle) { + serial->rx_stream = furi_stream_buffer_alloc(RX_BUF_LEN, 1); furi_hal_serial_init(serial->serial_handle, baudrate); furi_hal_serial_async_rx_start( serial->serial_handle, js_serial_on_async_rx, serial, false); serial->setup_done = true; + } else { + expansion_enable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + } +} + +static void js_serial_deinit(JsSerialInst* js_serial) { + if(js_serial->setup_done) { + furi_hal_serial_async_rx_stop(js_serial->serial_handle); + furi_hal_serial_deinit(js_serial->serial_handle); + furi_hal_serial_control_release(js_serial->serial_handle); + js_serial->serial_handle = NULL; + furi_stream_buffer_free(js_serial->rx_stream); + + expansion_enable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + + js_serial->setup_done = false; + } +} + +static void js_serial_end(struct mjs* mjs) { + mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); + JsSerialInst* serial = mjs_get_ptr(mjs, obj_inst); + furi_assert(serial); + + if(!serial->setup_done) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Serial is not configured"); + mjs_return(mjs, MJS_UNDEFINED); + return; } + + js_serial_deinit(serial); } static void js_serial_write(struct mjs* mjs) { @@ -345,6 +381,55 @@ static void js_serial_read_bytes(struct mjs* mjs) { free(read_buf); } +static char* js_serial_receive_any(JsSerialInst* serial, size_t* len, uint32_t timeout) { + uint32_t flags = ThreadEventCustomDataRx; + if(furi_stream_buffer_is_empty(serial->rx_stream)) { + flags = js_flags_wait(serial->mjs, ThreadEventCustomDataRx, timeout); + } + if(flags & ThreadEventCustomDataRx) { // New data received + *len = furi_stream_buffer_bytes_available(serial->rx_stream); + if(!*len) return NULL; + char* buf = malloc(*len); + furi_stream_buffer_receive(serial->rx_stream, buf, *len, 0); + return buf; + } + return NULL; +} + +static void js_serial_read_any(struct mjs* mjs) { + mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); + JsSerialInst* serial = mjs_get_ptr(mjs, obj_inst); + furi_assert(serial); + if(!serial->setup_done) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Serial is not configured"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + uint32_t timeout = FuriWaitForever; + + do { + size_t num_args = mjs_nargs(mjs); + if(num_args == 1) { + mjs_val_t timeout_arg = mjs_arg(mjs, 0); + if(!mjs_is_number(timeout_arg)) { + break; + } + timeout = mjs_get_int32(mjs, timeout_arg); + } + } while(0); + + size_t bytes_read = 0; + char* read_buf = js_serial_receive_any(serial, &bytes_read, timeout); + + mjs_val_t return_obj = MJS_UNDEFINED; + if(bytes_read > 0 && read_buf) { + return_obj = mjs_mk_string(mjs, read_buf, bytes_read, true); + } + mjs_return(mjs, return_obj); + free(read_buf); +} + static bool js_serial_expect_parse_string(struct mjs* mjs, mjs_val_t arg, PatternArray_t patterns) { size_t str_len = 0; @@ -578,10 +663,12 @@ static void* js_serial_create(struct mjs* mjs, mjs_val_t* object) { mjs_val_t serial_obj = mjs_mk_object(mjs); mjs_set(mjs, serial_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, js_serial)); mjs_set(mjs, serial_obj, "setup", ~0, MJS_MK_FN(js_serial_setup)); + mjs_set(mjs, serial_obj, "end", ~0, MJS_MK_FN(js_serial_end)); mjs_set(mjs, serial_obj, "write", ~0, MJS_MK_FN(js_serial_write)); mjs_set(mjs, serial_obj, "read", ~0, MJS_MK_FN(js_serial_read)); mjs_set(mjs, serial_obj, "readln", ~0, MJS_MK_FN(js_serial_readln)); mjs_set(mjs, serial_obj, "readBytes", ~0, MJS_MK_FN(js_serial_read_bytes)); + mjs_set(mjs, serial_obj, "readAny", ~0, MJS_MK_FN(js_serial_read_any)); mjs_set(mjs, serial_obj, "expect", ~0, MJS_MK_FN(js_serial_expect)); *object = serial_obj; @@ -590,14 +677,7 @@ static void* js_serial_create(struct mjs* mjs, mjs_val_t* object) { static void js_serial_destroy(void* inst) { JsSerialInst* js_serial = inst; - if(js_serial->setup_done) { - furi_hal_serial_async_rx_stop(js_serial->serial_handle); - furi_hal_serial_deinit(js_serial->serial_handle); - furi_hal_serial_control_release(js_serial->serial_handle); - js_serial->serial_handle = NULL; - } - - furi_stream_buffer_free(js_serial->rx_stream); + js_serial_deinit(js_serial); free(js_serial); } diff --git a/applications/system/js_app/modules/js_textbox.c b/applications/system/js_app/modules/js_textbox.c index 199cd2a0eb..cf4e8dbbfc 100644 --- a/applications/system/js_app/modules/js_textbox.c +++ b/applications/system/js_app/modules/js_textbox.c @@ -7,6 +7,7 @@ typedef struct { TextBox* text_box; ViewDispatcher* view_dispatcher; FuriThread* thread; + FuriString* text; } JsTextboxInst; static JsTextboxInst* get_this_ctx(struct mjs* mjs) { @@ -74,18 +75,37 @@ static void js_textbox_set_config(struct mjs* mjs) { mjs_return(mjs, MJS_UNDEFINED); } -static void js_textbox_set_text(struct mjs* mjs) { +static void js_textbox_add_text(struct mjs* mjs) { JsTextboxInst* textbox = get_this_ctx(mjs); if(!check_arg_count(mjs, 1)) return; mjs_val_t text_arg = mjs_arg(mjs, 0); - const char* text = mjs_get_string(mjs, &text_arg, NULL); + size_t text_len = 0; + const char* text = mjs_get_string(mjs, &text_arg, &text_len); if(!text) { ret_bad_args(mjs, "Text must be a string"); return; } - text_box_set_text(textbox->text_box, text); + size_t new_len = furi_string_size(textbox->text) + text_len; + if(new_len >= 4096) { + furi_string_right(textbox->text, new_len / 2); + } + + furi_string_cat(textbox->text, text); + + text_box_set_text(textbox->text_box, furi_string_get_cstr(textbox->text)); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_textbox_empty_text(struct mjs* mjs) { + JsTextboxInst* textbox = get_this_ctx(mjs); + if(!check_arg_count(mjs, 0)) return; + + furi_string_reset(textbox->text); + + text_box_set_text(textbox->text_box, furi_string_get_cstr(textbox->text)); mjs_return(mjs, MJS_UNDEFINED); } @@ -109,6 +129,7 @@ static void textbox_deinit(void* context) { furi_record_close(RECORD_GUI); text_box_reset(textbox->text_box); + furi_string_reset(textbox->text); } static void textbox_callback(void* context, uint32_t arg) { @@ -166,11 +187,13 @@ static void* js_textbox_create(struct mjs* mjs, mjs_val_t* object) { mjs_val_t textbox_obj = mjs_mk_object(mjs); mjs_set(mjs, textbox_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, textbox)); mjs_set(mjs, textbox_obj, "setConfig", ~0, MJS_MK_FN(js_textbox_set_config)); - mjs_set(mjs, textbox_obj, "setText", ~0, MJS_MK_FN(js_textbox_set_text)); + mjs_set(mjs, textbox_obj, "addText", ~0, MJS_MK_FN(js_textbox_add_text)); + mjs_set(mjs, textbox_obj, "emptyText", ~0, MJS_MK_FN(js_textbox_empty_text)); mjs_set(mjs, textbox_obj, "isOpen", ~0, MJS_MK_FN(js_textbox_is_open)); mjs_set(mjs, textbox_obj, "show", ~0, MJS_MK_FN(js_textbox_show)); mjs_set(mjs, textbox_obj, "close", ~0, MJS_MK_FN(js_textbox_close)); textbox->text_box = text_box_alloc(); + textbox->text = furi_string_alloc(); *object = textbox_obj; return textbox; } @@ -182,6 +205,7 @@ static void js_textbox_destroy(void* inst) { textbox_deinit(textbox); } text_box_free(textbox->text_box); + furi_string_free(textbox->text); free(textbox); } From 8d75af84578be6cb1d5bb38eb33056b3c6d099d2 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 24 Mar 2024 00:17:02 +0300 Subject: [PATCH 13/13] update changelog --- CHANGELOG.md | 14 +++++++++++--- applications/main/nfc/application.fam | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 611a000315..5823efded7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ * NFC: **EMV Fixes and imporvements** (old saved files may be not compatible now) (by @wosk & @Leptopt1los | PR #702) * NFC: **Parsers refactoring** (by @Leptopt1los) * NFC: **Kazan parser improved** - token parse option added (by @Leptopt1los) -* NFC: Update ndef parser, mf classic dict changes (by @Willy-JL) +* NFC: **Update ndef parser**, mf classic dict changes (by @Willy-JL) * RFID: Test swap of em4100 t5577 blocks (details in issue 3463 OFW) * Infrared: Update universal remote assets (by @amec0e | PR #718 #719) * SubGHz: Add 430.50 mhz (by @MizumasuShoichi | PR #721) @@ -13,11 +13,19 @@ * HID App: merge official fw hid app keyboard changes * Misc: Use non prefixed names for regular files with random name * Misc: Revert usb cdc config changes to verify issue (storage timeout during firmware update) (OFW 3452) +* Misc: Fixes for text box and uart echo demo app, remove duplicated emv parser plugin (by @Willy-JL) * Expansion `is_connected` API to check for VGM (by @HaxSam) -* New JavaScript Modules `UsbDisk`,`badusb.quit() + altstring`,`SubGHz`,`Submenu`,`BleBeacon`,`Keyboard`,`Math`,`GPIO` (by @Willy-JL, @Spooks4576, @Sil333033, @oldip) +* New JavaScript Modules `UsbDisk`,`badusb.quit() + altstring`,`SubGHz`,`Submenu`,`BleBeacon`,`Keyboard`,`Math`,`GPIO`, `textbox` (by @Willy-JL, @Spooks4576, @Sil333033, @oldip) +* Apps: **BadBT renamed and moved from Apps-Bluetooth to Apps-Tools as BadKB** * Apps: Added **FindMy Flipper** app -* Apps: NFC Magic - **Gen4 improvements, Gen2 writing support** +* Apps: NFC Magic - **Gen4 improvements** * Apps: **Check out Apps updates by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) +* OFW: BLE/GAP fixes +* OFW: Add support for Pioneer SR IR remotes +* OFW: fbt/ufbt: Ensure POSIX paths are passed to GDB on all platforms +* OFW: Add support for DEFAULT_STRING_DELAY in Bad USB App +* OFW: Adding F13-F24 function key support to BadUSB +* OFW PR 3532: NFC UI fixes (by gornekich) * OFW PR 3504: NFC: **Slix privacy password reveal and Desfire detect fix** (by gornekich) * OFW: **Infrared fixes and more** * OFW: NFC Parsers cosmetic fixes diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 6a09fdc759..f036feaeee 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -232,7 +232,7 @@ App( apptype=FlipperAppType.PLUGIN, entry_point="emv_plugin_ep", targets=["f7"], - requires=["nfc", "storage"], + requires=["nfc"], sources=["plugins/supported_cards/emv.c", "helpers/nfc_emv_parser.c"], )