From 2282587c15291246baa608744e9bbcbaed9b2a6d Mon Sep 17 00:00:00 2001 From: noproto Date: Tue, 29 Oct 2024 14:07:16 -0400 Subject: [PATCH 01/10] Mark TODOs for next PR --- .../scenes/nfc_scene_mf_classic_dict_attack.c | 4 +-- .../protocols/mf_classic/mf_classic_poller.c | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) 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 526a89a74..024bc5c1e 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 @@ -5,8 +5,8 @@ #define TAG "NfcMfClassicDictAttack" -// TODO: Fix lag when leaving the dictionary attack view after Hardnested -// TODO: Re-enters backdoor detection between user and system dictionary if no backdoor is found +// TODO FL-3926: Fix lag when leaving the dictionary attack view after Hardnested +// TODO FL-3926: Re-enters backdoor detection between user and system dictionary if no backdoor is found typedef enum { DictAttackStateCUIDDictInProgress, diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index edfdb2a95..1eaf2579c 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -6,11 +6,11 @@ #define TAG "MfClassicPoller" -// TODO: Buffer writes for Hardnested, set state to Log when finished and sum property matches -// TODO: Store target key in CUID dictionary -// TODO: Dead code for malloc returning NULL? -// TODO: Auth1 static encrypted exists (rare) -// TODO: Use keys found by NFC plugins, cached keys +// TODO FL-3926: Buffer writes for Hardnested, set state to Log when finished and sum property matches +// TODO FL-3926: Store target key in CUID dictionary +// TODO FL-3926: Dead code for malloc returning NULL? +// TODO FL-3926: Auth1 static encrypted exists (rare) +// TODO FL-3926: Use keys found by NFC plugins, cached keys #define MF_CLASSIC_MAX_BUFF_SIZE (64) @@ -606,7 +606,7 @@ NfcCommand mf_classic_poller_handler_analyze_backdoor(MfClassicPoller* instance) } NfcCommand mf_classic_poller_handler_backdoor_read_sector(MfClassicPoller* instance) { - // TODO: Reauth not needed + // TODO FL-3926: Reauth not needed NfcCommand command = NfcCommandContinue; MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx; MfClassicError error = MfClassicErrorNone; @@ -1328,8 +1328,8 @@ static inline bool is_byte_found(uint8_t* found, uint8_t byte) { } NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* instance) { - // TODO: Handle when nonce is not collected (retry counter? Do not increment nested_target_key) - // TODO: Look into using MfClassicNt more + // TODO FL-3926: Handle when nonce is not collected (retry counter? Do not increment nested_target_key) + // TODO FL-3926: Look into using MfClassicNt more NfcCommand command = NfcCommandContinue; MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx; @@ -1563,8 +1563,8 @@ static MfClassicKey* search_dicts_for_nonce_key( } NfcCommand mf_classic_poller_handler_nested_dict_attack(MfClassicPoller* instance) { - // TODO: Handle when nonce is not collected (retry counter? Do not increment nested_target_key) - // TODO: Look into using MfClassicNt more + // TODO FL-3926: Handle when nonce is not collected (retry counter? Do not increment nested_target_key) + // TODO FL-3926: Look into using MfClassicNt more NfcCommand command = NfcCommandContinue; MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx; @@ -1722,7 +1722,7 @@ NfcCommand mf_classic_poller_handler_nested_log(MfClassicPoller* instance) { bool params_write_success = true; for(size_t i = 0; i < nonce_pair_count; i++) { MfClassicNestedNonce* nonce = &dict_attack_ctx->nested_nonce.nonces[i]; - // TODO: Avoid repeating logic here + // TODO FL-3926: Avoid repeating logic here uint8_t nonce_sector = nonce->key_idx / (weak_prng ? 4 : 2); MfClassicKeyType nonce_key_type = (nonce->key_idx % (weak_prng ? 4 : 2) < (weak_prng ? 2 : 1)) ? MfClassicKeyTypeA : @@ -1857,7 +1857,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance } else if(dict_attack_ctx->prng_type == MfClassicPrngTypeNoTag) { FURI_LOG_E(TAG, "No tag detected"); // Free nonce array - // TODO: Consider using .count here + // TODO FL-3926: Consider using .count here if(dict_attack_ctx->nested_nonce.nonces) { free(dict_attack_ctx->nested_nonce.nonces); dict_attack_ctx->nested_nonce.nonces = NULL; @@ -1868,7 +1868,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance } if(dict_attack_ctx->nested_nonce.nonces) { // Free nonce array - // TODO: Consider using .count here + // TODO FL-3926: Consider using .count here free(dict_attack_ctx->nested_nonce.nonces); dict_attack_ctx->nested_nonce.nonces = NULL; dict_attack_ctx->nested_nonce.count = 0; From eb1aabbec4819b02c430ad62013723063fe941ca Mon Sep 17 00:00:00 2001 From: noproto Date: Tue, 29 Oct 2024 14:56:40 -0400 Subject: [PATCH 02/10] Remove redundant assignment --- lib/nfc/protocols/mf_classic/mf_classic_poller.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index 1eaf2579c..1a4c93d41 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -1289,8 +1289,6 @@ NfcCommand mf_classic_poller_handler_nested_calibrate(MfClassicPoller* instance) float std_dev = sqrtf(variance); // Filter out values over 3 standard deviations away from the median - dict_attack_ctx->d_min = UINT16_MAX; - dict_attack_ctx->d_max = 0; for(uint8_t i = 0; i < valid_distances; i++) { if(fabsf((float)distances[i] - median) <= 3 * std_dev) { if(distances[i] < dict_attack_ctx->d_min) dict_attack_ctx->d_min = distances[i]; From c24007755a192ce4cd925e5c65a83a5b00813244 Mon Sep 17 00:00:00 2001 From: noproto Date: Tue, 29 Oct 2024 15:19:30 -0400 Subject: [PATCH 03/10] Fix size_t format specifier --- lib/nfc/protocols/mf_classic/mf_classic_poller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index 1a4c93d41..dd78b88f3 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -1704,7 +1704,7 @@ NfcCommand mf_classic_poller_handler_nested_log(MfClassicPoller* instance) { if(weak_prng && (!(static_encrypted)) && (dict_attack_ctx->nested_nonce.count != 2)) { FURI_LOG_E( TAG, - "MfClassicPollerStateNestedLog expected 2 nonces, received %u", + "MfClassicPollerStateNestedLog expected 2 nonces, received %zu", dict_attack_ctx->nested_nonce.count); break; } From 907019c136d57ef727e75291869a94e746db3af1 Mon Sep 17 00:00:00 2001 From: noproto Date: Tue, 29 Oct 2024 15:35:40 -0400 Subject: [PATCH 04/10] Simplify auth_passed condition --- lib/nfc/protocols/mf_classic/mf_classic_poller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index dd78b88f3..ec37c8015 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -1933,7 +1933,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance } if(!(dict_attack_ctx->auth_passed)) { dict_attack_ctx->attempt_count++; - } else if(dict_attack_ctx->auth_passed && !(initial_dict_attack_iter)) { + } else if(!(initial_dict_attack_iter)) { dict_attack_ctx->nested_target_key++; dict_attack_ctx->attempt_count = 0; } From 3c6a621da29378e34bf4b8caa739e84c4b717bda Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 05:30:33 +0300 Subject: [PATCH 05/10] merge fix [ci skip] with some parts from PR by Willy-JL https://github.com/flipperdevices/flipperzero-firmware/pull/3980/files --- .../examples/apps/Scripts/interactive.js | 93 ------- .../js_app/examples/apps/Scripts/load.js | 3 - .../js_app/examples/apps/Scripts/path.js | 9 - .../js_app/examples/apps/Scripts/storage.js | 29 --- .../examples/apps/Scripts/stringutils.js | 19 -- applications/system/js_app/js_thread.c | 25 -- .../system/js_app/packages/fz-sdk/global.d.ts | 43 +++- .../js_app/packages/fz-sdk/gui/index.d.ts | 22 +- .../{types => packages/fz-sdk}/i2c/index.d.ts | 0 .../packages/fz-sdk/notification/index.d.ts | 1 + .../{types => packages/fz-sdk}/spi/index.d.ts | 0 applications/system/js_app/types/global.d.ts | 226 ------------------ .../system/js_app/types/gui/byte_input.d.ts | 14 -- .../system/js_app/types/gui/file_picker.d.ts | 6 - .../system/js_app/types/gui/index.d.ts | 57 ----- 15 files changed, 61 insertions(+), 486 deletions(-) delete mode 100644 applications/system/js_app/examples/apps/Scripts/interactive.js delete mode 100644 applications/system/js_app/examples/apps/Scripts/load.js delete mode 100644 applications/system/js_app/examples/apps/Scripts/path.js delete mode 100644 applications/system/js_app/examples/apps/Scripts/storage.js delete mode 100644 applications/system/js_app/examples/apps/Scripts/stringutils.js rename applications/system/js_app/{types => packages/fz-sdk}/i2c/index.d.ts (100%) rename applications/system/js_app/{types => packages/fz-sdk}/spi/index.d.ts (100%) delete mode 100644 applications/system/js_app/types/global.d.ts delete mode 100644 applications/system/js_app/types/gui/byte_input.d.ts delete mode 100644 applications/system/js_app/types/gui/file_picker.d.ts delete mode 100644 applications/system/js_app/types/gui/index.d.ts diff --git a/applications/system/js_app/examples/apps/Scripts/interactive.js b/applications/system/js_app/examples/apps/Scripts/interactive.js deleted file mode 100644 index 40ca98c30..000000000 --- a/applications/system/js_app/examples/apps/Scripts/interactive.js +++ /dev/null @@ -1,93 +0,0 @@ -let eventLoop = require("event_loop"); -let gui = require("gui"); -let dialog = require("gui/dialog"); -let textInput = require("gui/text_input"); -let loading = require("gui/loading"); -let storage = require("storage"); - -// No eval() or exec() so need to run code from file, and filename must be unique -storage.makeDirectory("/ext/.tmp"); -storage.makeDirectory("/ext/.tmp/js"); -storage.rmrf("/ext/.tmp/js/repl") -storage.makeDirectory("/ext/.tmp/js/repl") -let ctx = { - tmpTemplate: "/ext/.tmp/js/repl/", - tmpNumber: 0, - persistentScope: {}, -}; - -let views = { - dialog: dialog.makeWith({ - header: "Interactive Console", - text: "Press OK to Start", - center: "Run Some JS" - }), - textInput: textInput.makeWith({ - header: "Type JavaScript Code:", - minLength: 0, - maxLength: 256, - defaultText: "2+2", - defaultTextClear: true, - }), - loading: loading.make(), -}; - -eventLoop.subscribe(views.dialog.input, function (_sub, button, gui, views) { - if (button === "center") { - gui.viewDispatcher.switchTo(views.textInput); - } -}, gui, views); - -eventLoop.subscribe(views.textInput.input, function (_sub, text, gui, views, ctx) { - gui.viewDispatcher.switchTo(views.loading); - - let path = ctx.tmpTemplate + (ctx.tmpNumber++).toString(); - let file = storage.openFile(path, "w", "create_always"); - file.write(text); - file.close(); - - // Hide GUI before running, we want to see console and avoid deadlock if code fails - gui.viewDispatcher.sendTo("back"); - let result = load(path, ctx.persistentScope); // Load runs JS and returns last value on stack - storage.remove(path); - - // Must convert to string explicitly - if (result === null) { // mJS: typeof null === "null", ECMAScript: typeof null === "object", IDE complains when checking "null" type - result = "null"; - } else if (typeof result === "string") { - result = "'" + result + "'"; - } else if (typeof result === "number") { - result = result.toString(); - } else if (typeof result === "bigint") { // mJS doesn't support BigInt() but might aswell check - result = "bigint"; - } else if (typeof result === "boolean") { - result = result ? "true" : "false"; - } else if (typeof result === "symbol") { // mJS doesn't support Symbol() but might aswell check - result = "symbol"; - } else if (typeof result === "undefined") { - result = "undefined"; - } else if (typeof result === "object") { - result = "object"; // JSON.stringify() is not implemented - } else if (typeof result === "function") { - result = "function"; - } else { - result = "unknown type: " + typeof result; - } - - gui.viewDispatcher.sendTo("front"); - views.dialog.set("header", "JS Returned:"); - views.dialog.set("text", result); - gui.viewDispatcher.switchTo(views.dialog); - views.textInput.set("defaultText", text); -}, gui, views, ctx); - -eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _, eventLoop) { - eventLoop.stop(); -}, eventLoop); - -gui.viewDispatcher.switchTo(views.dialog); - -// Message behind GUI if something breaks -print("If you're stuck here, something went wrong, re-run the script") -eventLoop.run(); -print("\n\nFinished correctly :)") diff --git a/applications/system/js_app/examples/apps/Scripts/load.js b/applications/system/js_app/examples/apps/Scripts/load.js deleted file mode 100644 index 82b2d2046..000000000 --- a/applications/system/js_app/examples/apps/Scripts/load.js +++ /dev/null @@ -1,3 +0,0 @@ -let math = load(__dirname + "/load_api.js"); -let result = math.add(5, 10); -print(result); diff --git a/applications/system/js_app/examples/apps/Scripts/path.js b/applications/system/js_app/examples/apps/Scripts/path.js deleted file mode 100644 index 0be31b81d..000000000 --- a/applications/system/js_app/examples/apps/Scripts/path.js +++ /dev/null @@ -1,9 +0,0 @@ -let storage = require("storage"); - -print("script has __dirname of" + __dirname); -print("script has __filename of" + __filename); -if (storage.fileExists(__dirname + "/math.js")) { - print("math.js exist here."); -} else { - print("math.js does not exist here."); -} diff --git a/applications/system/js_app/examples/apps/Scripts/storage.js b/applications/system/js_app/examples/apps/Scripts/storage.js deleted file mode 100644 index c0ec8bfa4..000000000 --- a/applications/system/js_app/examples/apps/Scripts/storage.js +++ /dev/null @@ -1,29 +0,0 @@ -let storage = require("storage"); -let path = "/ext/storage.test"; - -print("File exists:", storage.fileExists(path)); - -print("Writing..."); -let file = storage.openFile(path, "w", "create_always"); -file.write("Hello "); -file.close(); - -print("File exists:", storage.fileExists(path)); - -file = storage.openFile(path, "w", "open_append"); -file.write("World!"); -file.close(); - -print("Reading..."); -file = storage.openFile(path, "r", "open_existing"); -let text = file.read("ascii", 128); -file.close(); -print(text); - -print("Removing...") -storage.remove(path); - -print("Done") - -// You don't need to close the file after each operation, this is just to show some different ways to use the API -// There's also many more functions and options, check type definitions in firmware repo \ No newline at end of file diff --git a/applications/system/js_app/examples/apps/Scripts/stringutils.js b/applications/system/js_app/examples/apps/Scripts/stringutils.js deleted file mode 100644 index b2facb237..000000000 --- a/applications/system/js_app/examples/apps/Scripts/stringutils.js +++ /dev/null @@ -1,19 +0,0 @@ -let sampleText = "Hello, World!"; - -let lengthOfText = "Length of text: " + sampleText.length.toString(); -print(lengthOfText); - -let start = 7; -let end = 12; -let substringResult = sampleText.slice(start, end); -print(substringResult); - -let searchStr = "World"; -let result2 = sampleText.indexOf(searchStr).toString(); -print(result2); - -let upperCaseText = "Text in upper case: " + sampleText.toUpperCase(); -print(upperCaseText); - -let lowerCaseText = "Text in lower case: " + sampleText.toLowerCase(); -print(lowerCaseText); diff --git a/applications/system/js_app/js_thread.c b/applications/system/js_app/js_thread.c index b433e9edf..600c2676e 100644 --- a/applications/system/js_app/js_thread.c +++ b/applications/system/js_app/js_thread.c @@ -244,30 +244,6 @@ static int32_t js_thread(void* arg) { struct mjs* mjs = mjs_create(worker); worker->modules = js_modules_create(mjs, worker->resolver); mjs_val_t global = mjs_get_global(mjs); - if(worker->path) { - FuriString* dirpath = furi_string_alloc(); - path_extract_dirname(furi_string_get_cstr(worker->path), dirpath); - mjs_set( - mjs, - global, - "__filename", - ~0, - mjs_mk_string( - mjs, furi_string_get_cstr(worker->path), furi_string_size(worker->path), true)); - mjs_set( - mjs, - global, - "__dirname", - ~0, - mjs_mk_string(mjs, furi_string_get_cstr(dirpath), furi_string_size(dirpath), true)); - furi_string_free(dirpath); - } - mjs_set(mjs, global, "print", ~0, MJS_MK_FN(js_print)); - mjs_set(mjs, global, "delay", ~0, MJS_MK_FN(js_delay)); - mjs_set(mjs, global, "ffi_address", ~0, MJS_MK_FN(js_ffi_address)); - mjs_set(mjs, global, "require", ~0, MJS_MK_FN(js_require)); - mjs_set(mjs, global, "parseInt", ~0, MJS_MK_FN(js_parse_int)); - mjs_val_t console_obj = mjs_mk_object(mjs); if(worker->path) { @@ -292,7 +268,6 @@ static int32_t js_thread(void* arg) { JS_ASSIGN_MULTI(mjs, global) { JS_FIELD("print", MJS_MK_FN(js_print)); JS_FIELD("delay", MJS_MK_FN(js_delay)); - JS_FIELD("toString", MJS_MK_FN(js_global_to_string)); JS_FIELD("parseInt", MJS_MK_FN(js_parse_int)); JS_FIELD("ffi_address", MJS_MK_FN(js_ffi_address)); JS_FIELD("require", MJS_MK_FN(js_require)); diff --git a/applications/system/js_app/packages/fz-sdk/global.d.ts b/applications/system/js_app/packages/fz-sdk/global.d.ts index 953afc30d..d2e73f7de 100644 --- a/applications/system/js_app/packages/fz-sdk/global.d.ts +++ b/applications/system/js_app/packages/fz-sdk/global.d.ts @@ -120,6 +120,7 @@ declare function checkSdkCompatibility(expectedMajor: number, expectedMinor: num * recognized as a baseline feature. For more info, consult the module * documentation. * @param features Array of named features to query + * @version Added in JS SDK 0.1 */ declare function doesSdkSupport(features: string[]): boolean; @@ -131,6 +132,7 @@ declare function doesSdkSupport(features: string[]): boolean; * features that are now recognized as baseline features. For more * info, consult the module documentation. * @param features Array of named features to query + * @version Added in JS SDK 0.1 */ declare function checkSdkFeatures(features: string[]): void | never; @@ -150,15 +152,48 @@ declare function delay(ms: number): void; declare function print(...args: any[]): void; /** - * @brief Reads a JS value from a file + * @brief Converts a string to a number + * @param text The string to convert to a number + * @param base Integer base (`2`...`16`), default: 10 + * @version Added in JS SDK 0.1 + */ +declare function parseInt(text: string, base?: number): number; + +/** + * @brief Path to the directory containing the current script + * @version Added in JS SDK 0.1 + */ +declare const __dirname: string; + +/** + * @brief Path to the current script file + * @version Added in JS SDK 0.1 + */ +declare const __filename: string; + +/** + * @brief Runs a JS file and returns value from it * - * Reads a file at the specified path, interprets it as a JS value and returns - * said value. + * Reads a file at the specified path and runs it as JS, returning the last evaluated value. + * + * The result is cached and this filepath will not re-evaluated on future + * load() calls for this session. * * @param path The path to the file + * @param scope An object to use as global scope while running this file + * @version Added in JS SDK 0.1 + */ +declare function load(path: string, scope?: object): any; + +/** + * @brief Return 1-byte string whose ASCII code is the integer `n` + * + * If `n` is not numeric or outside of `0-255` range, `null` is returned + * + * @param n The ASCII code to convert to string * @version Added in JS SDK 0.1 */ -declare function load(path: string): any; +declare function chr(n: number): string | null; /** * @brief Loads a natively implemented module diff --git a/applications/system/js_app/packages/fz-sdk/gui/index.d.ts b/applications/system/js_app/packages/fz-sdk/gui/index.d.ts index 3184a5718..93a6846c2 100644 --- a/applications/system/js_app/packages/fz-sdk/gui/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/gui/index.d.ts @@ -30,7 +30,7 @@ * |----------------------|------------------| * | `button_menu` | ❌ | * | `button_panel` | ❌ | - * | `byte_input` | ❌ | + * | `byte_input` | ✅ | * | `dialog_ex` | ✅ (as `dialog`) | * | `empty_screen` | ✅ | * | `file_browser` | ❌ | @@ -122,11 +122,26 @@ import type { Contract } from "../event_loop"; type Properties = { [K: string]: any }; export declare class View { + /** + * Assign value to property by name + * @param property Name of the property + * @param value Value to assign + * @version Added in JS SDK 0.1 + */ set

(property: P, value: Props[P]): void; } export declare class ViewFactory> { + /** + * Create view instance with default values, can be changed later with set() + * @version Added in JS SDK 0.1 + */ make(): V; + /** + * Create view instance with custom values, can be changed later with set() + * @param initial Dictionary of property names to values + * @version Added in JS SDK 0.1 + */ makeWith(initial: Partial): V; } @@ -144,6 +159,11 @@ declare class ViewDispatcher { * @version Added in JS SDK 0.1 */ navigation: Contract; + /** + * View object currently shown + * @version Added in JS SDK 0.1 + */ + currentView: View; /** * Sends a number to the custom event handler * @param event number to send diff --git a/applications/system/js_app/types/i2c/index.d.ts b/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts similarity index 100% rename from applications/system/js_app/types/i2c/index.d.ts rename to applications/system/js_app/packages/fz-sdk/i2c/index.d.ts diff --git a/applications/system/js_app/packages/fz-sdk/notification/index.d.ts b/applications/system/js_app/packages/fz-sdk/notification/index.d.ts index 2199a1479..499994d3a 100644 --- a/applications/system/js_app/packages/fz-sdk/notification/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/notification/index.d.ts @@ -14,6 +14,7 @@ export declare function success(): void; /** * @brief Signals failure to the user via the color LED, speaker and vibration * motor + * @version Added in JS SDK 0.1 */ export declare function error(): void; diff --git a/applications/system/js_app/types/spi/index.d.ts b/applications/system/js_app/packages/fz-sdk/spi/index.d.ts similarity index 100% rename from applications/system/js_app/types/spi/index.d.ts rename to applications/system/js_app/packages/fz-sdk/spi/index.d.ts diff --git a/applications/system/js_app/types/global.d.ts b/applications/system/js_app/types/global.d.ts deleted file mode 100644 index a55dae7d9..000000000 --- a/applications/system/js_app/types/global.d.ts +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @brief Pauses JavaScript execution for a while - * @param ms How many milliseconds to pause the execution for - */ -declare function delay(ms: number): void; - -/** - * @brief Prints to the GUI console view - * @param args The arguments are converted to strings, concatenated without any - * spaces in between and printed to the console view - */ -declare function print(...args: any[]): void; - -/** - * @brief Converts a string to a number - * @param text The string to convert to a number - * @param base Integer base (`2`...`16`), default: 10 - */ -declare function parseInt(text: string, base?: number): number; - -/** - * @brief Path to the directory containing the current script - */ -declare const __dirname: string; - -/** - * @brief Path to the current script file - */ -declare const __filename: string; - -/** - * @brief Reads a JS value from a file - * - * Reads a file at the specified path and runs it as JS, returning the last evaluated value. - * - * The result is cached and this filepath will not re-evaluated on future - * load() calls for this session. - * - * @param path The path to the file - * @param scope An object to use as global scope while running this file - */ -declare function load(path: string, scope?: object): any; - -/** - * @brief Return 1-byte string whose ASCII code is the integer `n` - * - * If `n` is not numeric or outside of `0-255` range, `null` is returned - * - * @param n The ASCII code to convert to string - */ -declare function chr(n: number): string | null; - -/** - * @brief mJS Foreign Pointer type - * - * JavaScript code cannot do anything with values of `RawPointer` type except - * acquire them from native code and pass them right back to other parts of - * native code. These values cannot be turned into something meaningful, nor can - * be they modified. - */ -declare type RawPointer = symbol & { "__tag__": "raw_ptr" }; -// introducing a nominal type in a hacky way; the `__tag__` property doesn't really exist. - -/** - * @brief Holds raw bytes - */ -declare class ArrayBuffer { - /** - * @brief The pointer to the byte buffer - * @note Like other `RawPointer` values, this value is essentially useless - * to JS code. - */ - getPtr: RawPointer; - /** - * @brief The length of the buffer in bytes - */ - byteLength: number; - /** - * @brief Creates an `ArrayBuffer` that contains a sub-part of the buffer - * @param start The index of the byte in the source buffer to be used as the - * start for the new buffer - * @param end The index of the byte in the source buffer that follows the - * byte to be used as the last byte for the new buffer - */ - slice(start: number, end?: number): ArrayBuffer; -} - -declare function ArrayBuffer(): ArrayBuffer; - -declare type ElementType = "u8" | "i8" | "u16" | "i16" | "u32" | "i32"; - -declare class TypedArray { - /** - * @brief The length of the buffer in bytes - */ - byteLength: number; - /** - * @brief The length of the buffer in typed elements - */ - length: number; - /** - * @brief The underlying `ArrayBuffer` - */ - buffer: ArrayBuffer; -} - -declare class Uint8Array extends TypedArray<"u8"> { } -declare class Int8Array extends TypedArray<"i8"> { } -declare class Uint16Array extends TypedArray<"u16"> { } -declare class Int16Array extends TypedArray<"i16"> { } -declare class Uint32Array extends TypedArray<"u32"> { } -declare class Int32Array extends TypedArray<"i32"> { } - -declare function Uint8Array(data: ArrayBuffer | number | number[]): Uint8Array; -declare function Int8Array(data: ArrayBuffer | number | number[]): Int8Array; -declare function Uint16Array(data: ArrayBuffer | number | number[]): Uint16Array; -declare function Int16Array(data: ArrayBuffer | number | number[]): Int16Array; -declare function Uint32Array(data: ArrayBuffer | number | number[]): Uint32Array; -declare function Int32Array(data: ArrayBuffer | number | number[]): Int32Array; - -declare const console: { - /** - * @brief Prints to the UART logs at the `[I]` level - * @param args The arguments are converted to strings, concatenated without any - * spaces in between and printed to the logs - */ - log(...args: any[]): void; - /** - * @brief Prints to the UART logs at the `[D]` level - * @param args The arguments are converted to strings, concatenated without any - * spaces in between and printed to the logs - */ - debug(...args: any[]): void; - /** - * @brief Prints to the UART logs at the `[W]` level - * @param args The arguments are converted to strings, concatenated without any - * spaces in between and printed to the logs - */ - warn(...args: any[]): void; - /** - * @brief Prints to the UART logs at the `[E]` level - * @param args The arguments are converted to strings, concatenated without any - * spaces in between and printed to the logs - */ - error(...args: any[]): void; -}; - -declare class Array { - /** - * @brief Takes items out of the array - * - * Removes elements from the array and returns them in a new array - * - * @param start The index to start taking elements from - * @param deleteCount How many elements to take - * @returns The elements that were taken out of the original array as a new - * array - */ - splice(start: number, deleteCount: number): T[]; - /** - * @brief Adds a value to the end of the array - * @param value The value to add - * @returns New length of the array - */ - push(value: T): number; - /** - * @brief How many elements there are in the array - */ - length: number; -} - -declare class String { - /** - * @brief How many characters there are in the string - */ - length: number; - /** - * @brief Returns the character code at an index in the string - * @param index The index to consult - */ - charCodeAt(index: number): number; - /** - * See `charCodeAt` - */ - at(index: number): number; - /** - * @brief Return index of first occurence of substr within the string or `-1` if not found - * @param substr The string to search for - * @param fromIndex The index to start searching from - */ - indexOf(substr: string, fromIndex?: number): number; - /** - * @brief Return a substring between two indices - * @param start The index to start substring at - * @param end The index to end substring at - */ - slice(start: number, end?: number): string; - /** - * @brief Return this string transformed to upper case - */ - toUpperCase(): string; - /** - * @brief Return this string transformed to lower case - */ - toLowerCase(): string; -} - -declare class Boolean { } - -declare class Function { } - -declare class Number { - /** - * @brief Converts this number to a string - * @param base Integer base (`2`...`16`), default: 10 - */ - toString(base?: number): string; -} - -declare class Object { } - -declare class RegExp { } - -declare interface IArguments { } - -declare type Partial = { [K in keyof O]?: O[K] }; diff --git a/applications/system/js_app/types/gui/byte_input.d.ts b/applications/system/js_app/types/gui/byte_input.d.ts deleted file mode 100644 index 92bd4c5a8..000000000 --- a/applications/system/js_app/types/gui/byte_input.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { View, ViewFactory } from "."; -import type { Contract } from "../event_loop"; - -type Props = { - header: string, - length: number, - defaultData: Uint8Array | ArrayBuffer, -} -declare class ByteInput extends View { - input: Contract; -} -declare class ByteInputFactory extends ViewFactory { } -declare const factory: ByteInputFactory; -export = factory; diff --git a/applications/system/js_app/types/gui/file_picker.d.ts b/applications/system/js_app/types/gui/file_picker.d.ts deleted file mode 100644 index 2051e1432..000000000 --- a/applications/system/js_app/types/gui/file_picker.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @brief Displays a file picker and returns the selected file, or undefined if cancelled - * @param basePath The path to start at - * @param extension The file extension(s) to show (like `.sub`, `.iso|.img`, `*`) - */ -export declare function pickFile(basePath: string, extension: string): string | undefined; diff --git a/applications/system/js_app/types/gui/index.d.ts b/applications/system/js_app/types/gui/index.d.ts deleted file mode 100644 index d4cdc6bc9..000000000 --- a/applications/system/js_app/types/gui/index.d.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Contract } from "../event_loop"; - -type Properties = { [K: string]: any }; - -export declare class View { - /** - * Assign value to property by name - * @param property Name of the property - * @param value Value to assign - */ - set

(property: P, value: Props[P]): void; -} - -export declare class ViewFactory> { - /** - * Create view instance with default values, can be changed later with set() - */ - make(): V; - /** - * Create view instance with custom values, can be changed later with set() - * @param initial Dictionary of property names to values - */ - makeWith(initial: Partial): V; -} - -declare class ViewDispatcher { - /** - * Event source for `sendCustom` events - */ - custom: Contract; - /** - * Event source for navigation events (back key presses) - */ - navigation: Contract; - /** - * View object currently shown - */ - currentView: View; - /** - * Sends a number to the custom event handler - * @param event number to send - */ - sendCustom(event: number): void; - /** - * Switches to a view - * @param assoc View-ViewDispatcher association as returned by `add` - */ - switchTo(assoc: View): void; - /** - * Sends this ViewDispatcher to the front or back, above or below all other - * GUI viewports - * @param direction Either `"front"` or `"back"` - */ - sendTo(direction: "front" | "back"): void; -} - -export const viewDispatcher: ViewDispatcher; From 7ce036fd9b0ec8eaca04a4ba73958e98cc90608a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 05:39:30 +0300 Subject: [PATCH 06/10] missing parts [ci skip] --- applications/system/js_app/js_modules.h | 2 +- applications/system/js_app/modules/js_badusb.c | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/applications/system/js_app/js_modules.h b/applications/system/js_app/js_modules.h index 1dfd59521..fffee31dc 100644 --- a/applications/system/js_app/js_modules.h +++ b/applications/system/js_app/js_modules.h @@ -9,7 +9,7 @@ #define PLUGIN_APP_ID "js" #define PLUGIN_API_VERSION 1 -#define JS_SDK_VENDOR "flipperdevices" +#define JS_SDK_VENDOR "unleashed" #define JS_SDK_MAJOR 0 #define JS_SDK_MINOR 1 diff --git a/applications/system/js_app/modules/js_badusb.c b/applications/system/js_app/modules/js_badusb.c index daf744843..7a42d0a3a 100644 --- a/applications/system/js_app/modules/js_badusb.c +++ b/applications/system/js_app/modules/js_badusb.c @@ -204,22 +204,6 @@ static void js_badusb_quit(struct mjs* mjs) { mjs_return(mjs, MJS_UNDEFINED); } -static void js_badusb_quit(struct mjs* mjs) { - mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); - JsBadusbInst* badusb = mjs_get_ptr(mjs, obj_inst); - furi_assert(badusb); - - if(badusb->usb_if_prev == NULL) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "HID is not started"); - mjs_return(mjs, MJS_UNDEFINED); - return; - } - - js_badusb_quit_free(badusb); - - mjs_return(mjs, MJS_UNDEFINED); -} - static void js_badusb_is_connected(struct mjs* mjs) { mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); JsBadusbInst* badusb = mjs_get_ptr(mjs, obj_inst); From 91af1cdd46e7203d80cb37af4e131fae6e2bb663 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:00:46 +0300 Subject: [PATCH 07/10] restore require func --- applications/system/js_app/js_modules.h | 7 ++++--- applications/system/js_app/modules/js_flipper.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/applications/system/js_app/js_modules.h b/applications/system/js_app/js_modules.h index fffee31dc..656a7b7b6 100644 --- a/applications/system/js_app/js_modules.h +++ b/applications/system/js_app/js_modules.h @@ -9,9 +9,10 @@ #define PLUGIN_APP_ID "js" #define PLUGIN_API_VERSION 1 -#define JS_SDK_VENDOR "unleashed" -#define JS_SDK_MAJOR 0 -#define JS_SDK_MINOR 1 +#define JS_SDK_VENDOR_FIRMWARE "unleashed" +#define JS_SDK_VENDOR "flipperdevices" +#define JS_SDK_MAJOR 0 +#define JS_SDK_MINOR 1 /** * @brief Returns the foreign pointer in `obj["_"]` diff --git a/applications/system/js_app/modules/js_flipper.c b/applications/system/js_app/modules/js_flipper.c index eeaa2c8a0..228cd0661 100644 --- a/applications/system/js_app/modules/js_flipper.c +++ b/applications/system/js_app/modules/js_flipper.c @@ -37,7 +37,7 @@ void* js_flipper_create(struct mjs* mjs, mjs_val_t* object, JsModules* modules) JS_FIELD("getModel", MJS_MK_FN(js_flipper_get_model)); JS_FIELD("getName", MJS_MK_FN(js_flipper_get_name)); JS_FIELD("getBatteryCharge", MJS_MK_FN(js_flipper_get_battery)); - JS_FIELD("firmwareVendor", mjs_mk_string(mjs, JS_SDK_VENDOR, ~0, false)); + JS_FIELD("firmwareVendor", mjs_mk_string(mjs, JS_SDK_VENDOR_FIRMWARE, ~0, false)); JS_FIELD("jsSdkVersion", sdk_vsn); } From 9180364e42160e9fde2f862d54eb59fcbbb9ede3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:02:46 +0300 Subject: [PATCH 08/10] upd readmes [ci skip] --- CHANGELOG.md | 2 +- ReadMe.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff636a393..0049a481c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -123,7 +123,7 @@ |cloudtips|only RU payments accepted|

QR image
|https://pay.cloudtips.ru/p/7b3e9d65| |YooMoney|only RU payments accepted|
QR image
|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209| |USDT|(TRC20)|
QR image
|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`| -|ETH|(BSC/ERC20-Tokens)|
QR image
|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)| +|ETH|(BSC/ERC20-Tokens)|
QR image
|`0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`| |BTC||
QR image
|`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`| |SOL|(Solana/Tokens)|
QR image
|`DSgwouAEgu8iP5yr7EHHDqMNYWZxAqXWsTEeqCAXGLj8`| |DOGE||
QR image
|`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`| diff --git a/ReadMe.md b/ReadMe.md index 61fe9ca7b..f01dd4898 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -155,7 +155,7 @@ You can support us by using links or addresses below: |cloudtips|only RU payments accepted|
QR image
|https://pay.cloudtips.ru/p/7b3e9d65| |YooMoney|only RU payments accepted|
QR image
|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209| |USDT|(TRC20)|
QR image
|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`| -|ETH|(BSC/ERC20-Tokens)|
QR image
|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)| +|ETH|(BSC/ERC20-Tokens)|
QR image
|`0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`| |BTC||
QR image
|`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`| |SOL|(Solana/Tokens)|
QR image
|`DSgwouAEgu8iP5yr7EHHDqMNYWZxAqXWsTEeqCAXGLj8`| |DOGE||
QR image
|`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`| From 2d601651c6b8df7c90099d9ac89098fc657db939 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:49:59 +0300 Subject: [PATCH 09/10] some subghz cleanup --- lib/subghz/protocols/alutech_at_4n.c | 24 ++++++++++++++++------- lib/subghz/protocols/keeloq.c | 22 ++++++++++----------- lib/subghz/protocols/kinggates_stylo_4k.c | 9 +++++++-- lib/subghz/protocols/nice_flor_s.c | 11 ++++++++--- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c index d0c410e1c..71e1aca32 100644 --- a/lib/subghz/protocols/alutech_at_4n.c +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -306,16 +306,22 @@ bool subghz_protocol_alutech_at_4n_create_data( instance->generic.serial = serial; instance->generic.cnt = cnt; instance->generic.data_count_bit = 72; - bool res = subghz_protocol_alutech_at_4n_gen_data(instance, btn); - if(res) { + if(subghz_protocol_alutech_at_4n_gen_data(instance, btn)) { if((subghz_block_generic_serialize(&instance->generic, flipper_format, preset) != - SubGhzProtocolStatusOk) || - !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { + SubGhzProtocolStatusOk)) { + FURI_LOG_E(TAG, "Serialize error"); + return false; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + return false; + } + if(!flipper_format_insert_or_update_uint32(flipper_format, "CRC", &instance->crc, 1)) { FURI_LOG_E(TAG, "Unable to add CRC"); - res = false; + return false; } } - return res; + return true; } /** @@ -665,8 +671,12 @@ SubGhzProtocolStatus subghz_protocol_decoder_alutech_at_4n_serialize( SubGhzProtocolDecoderAlutech_at_4n* instance = context; SubGhzProtocolStatus res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; + } if((res == SubGhzProtocolStatusOk) && - !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { + !flipper_format_insert_or_update_uint32(flipper_format, "CRC", &instance->crc, 1)) { FURI_LOG_E(TAG, "Unable to add CRC"); res = SubGhzProtocolStatusErrorParserOthers; } diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 60ff2f0f1..12d739dec 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -355,12 +355,12 @@ bool subghz_protocol_keeloq_create_data( instance->generic.cnt = cnt; instance->manufacture_name = manufacture_name; instance->generic.data_count_bit = 64; - bool res = subghz_protocol_keeloq_gen_data(instance, btn, false); - if(res) { - return SubGhzProtocolStatusOk == - subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(subghz_protocol_keeloq_gen_data(instance, btn, false)) { + return ( + subghz_block_generic_serialize(&instance->generic, flipper_format, preset) == + SubGhzProtocolStatusOk); } - return res; + return false; } bool subghz_protocol_keeloq_bft_create_data( @@ -380,13 +380,13 @@ bool subghz_protocol_keeloq_bft_create_data( instance->generic.seed = seed; instance->manufacture_name = manufacture_name; instance->generic.data_count_bit = 64; - // roguuemaster don't steal.!!!! - bool res = subghz_protocol_keeloq_gen_data(instance, btn, false); - if(res) { - return SubGhzProtocolStatusOk == - subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + // hehehehe + if(subghz_protocol_keeloq_gen_data(instance, btn, false)) { + return ( + subghz_block_generic_serialize(&instance->generic, flipper_format, preset) == + SubGhzProtocolStatusOk); } - return res; + return false; } /** diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c index 0f7ae06d5..56795d2dd 100644 --- a/lib/subghz/protocols/kinggates_stylo_4k.c +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -307,7 +307,7 @@ SubGhzProtocolStatus subghz_protocol_encoder_kinggates_stylo_4k_deserialize( key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data_2 >> i * 8) & 0xFF; } if(!flipper_format_update_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Unable to add Key"); + FURI_LOG_E(TAG, "Unable to update Data"); break; } @@ -522,8 +522,13 @@ SubGhzProtocolStatus subghz_protocol_decoder_kinggates_stylo_4k_serialize( key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data_2 >> (i * 8)) & 0xFF; } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; + } + if((ret == SubGhzProtocolStatusOk) && - !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + !flipper_format_insert_or_update_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Data"); ret = SubGhzProtocolStatusErrorParserOthers; } diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 8953e0d9e..8694ec4c1 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -267,7 +267,7 @@ SubGhzProtocolStatus key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Unable to add Key"); + FURI_LOG_E(TAG, "Unable to update Key"); break; } @@ -278,7 +278,7 @@ SubGhzProtocolStatus } uint32_t temp = (instance->generic.data_2 >> 4) & 0xFFFFF; if(!flipper_format_update_uint32(flipper_format, "Data", &temp, 1)) { - FURI_LOG_E(TAG, "Unable to add Data"); + FURI_LOG_E(TAG, "Unable to update Data"); } } @@ -707,8 +707,13 @@ SubGhzProtocolStatus subghz_protocol_decoder_nice_flor_s_serialize( SubGhzProtocolStatus ret = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; + } if((ret == SubGhzProtocolStatusOk) && - !flipper_format_write_uint32(flipper_format, "Data", (uint32_t*)&instance->data, 1)) { + !flipper_format_insert_or_update_uint32( + flipper_format, "Data", (uint32_t*)&instance->data, 1)) { FURI_LOG_E(TAG, "Unable to add Data"); ret = SubGhzProtocolStatusErrorParserOthers; } From e8dc0ea5d8077a0ea6a3a67893e3f47070a9b86c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:53:02 +0300 Subject: [PATCH 10/10] upd changelog --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0049a481c..e88a22b2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Hollarm add more button codes (thanks to @mishamyte for captures) - Misc: - Add extra settings to disable GPIO pins control used for external modules amplifiers and/or LEDs (in radio settings menu with debug ON) + - Code cleanup and fix for rare dupicated "Data" field cases - NFC: - Read Ultralight block by block (**fix password protected MFUL reading issue**) (by @mishamyte | PR #825 #826) - **Update NDEF parser** (SLIX and MFC support) (by @luu176 and @jaylikesbunda and @Willy-JL) @@ -39,7 +40,14 @@ * OFW: Require PIN on boot * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes -* OFW PR 3971: Fix JS memory corruption (in gpio module) (by @portasynthinca3) +* OFW: fix: npm deps +* OFW: 目覚め時計 +* OFW: JS: Backport and more additions & fixes +* OFW: nfc: add Caltrain zones for Clipper +* OFW: Update unit tests docs +* OFW: Fix JS memory corruption (in gpio module) +* OFW: Full-fledged JS SDK + npm packages +* OFW: FurEventLoop: add support for FuriEventFlag, simplify API * OFW: lib: digital_signal: digital_sequence: add furi_hal.h wrapped in ifdefs * OFW: Add warning about stealth mode in vibro CLI * OFW: Small fixes in the wifi devboard docs