From 75859e9a7eeb2fcd1c1bd0f15e931119dfdd1071 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 10 Jun 2023 04:45:11 +0300 Subject: [PATCH 1/5] Update changelog --- CHANGELOG.md | 61 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81527b72..0534ce4fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,37 @@ ### New changes * If you have copied any apps manually into `apps` folder - remove `apps` folder or that specific apps you copied on your microSD before installing this release to avoid issues due to OFW API version update! If you using regular builds or extra pack builds (e) without your manually added apps, all included apps will be installed automatically, no extra actions needed! +* Settings->LCD and Notifications will be resetted to default due to new Contrast setting from OFW ----- -* Only in release 052 -> **Multiple Extra pack apps was fixed!** -> TAMA P1, Flizzer Tracker, Video Player, Music Tracker -* NFC V: Remove delay from emulation loop. This improves compatibility when the reader is Android. -* Plugins: iButton Fuzzer -> Fix v2 key files load (all new saved files) -### Previous changes -* SubGHz Remote: Fixed BinRAW support, + many other fixes (by @gid9798 | PR #492) -* SubGHz: Fix KL: Stilmatic support + add manually support -* SubGHz: Keeloq mfname refactoring (by @gid9798 | PR #479) -* Desktop Clock: Some improvements and fixes (by @gid9798 | PR #490) -* LF RFID: Cleanup duplicated code (by @gid9798 | PR #493) -* NFC V: Code review fixes + some GUI rework (by @nvx & @xMasterX) -* NFC V: Fixed crash when exiting emulation and starting it again -* Infrared: Use Universal AC Remote from OFW, same for Audio remote, and rename buttons in OFW naming scheme -* Infrared: Update universal remote assets (by @amec0e) -* GUI Keyboard: Fix crash when renaming files with long file name (Fixed issue #489) -* Misc: Fix APP_IDs to match new regex (regex check will be added in OFW soon) -* Plugins: Protoview, WAV Player, DTMF Dolphin - fixed all known crashes, ported to latest hal bus system -* Plugins: ESP8266 Deauther - Crash fix (Fixed issue #497) -* Plugins: Update -> Mifare Nested [(by AloneLiberty)](https://github.com/AloneLiberty/FlipperNested) -* Plugins: Update -> TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -* Plugins: Update -> ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-wifi-marauder) -* Plugins: Update -> UART Terminal [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main) -* OFW: FuriHal: disable bus re-initialization on early init and extra asserts for AHB1,AHB2,AHB3 which must be left intact on entering to FUS -> **Fixes updater error 1-100** -* OFW: NFC: fix MFC timings -> **Fixes issues with Mifare Classic emulation that could happen after unlshd-049 release** -* OFW: Update dolphin.py -* OFW: NFC Magic: Fix gen1 writing with invalid BCC (lost fix from PR 2511) -* OFW: SubGhz: fix flipper crashes after exiting broadcast blocking message and crash cli +* Plugins: **New RFID 125KHz and iButton Fuzzers (remake from scratch + new features)** (by @gid9798 | PR #507) +* Plugins: SubGHz Bruteforcer -> Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + allow more repeats (by @gid9798 & @xMasterX) +* GUI: `Byte input` new feature: editor without keyboard (press Up until you get into new input, then use up/down to input values) (by @gid9798 | PR #509) +* Infrared: Update universal remote assets - add new ACs and TCL TV +* SubGHz: Remove broken modulation that was causing buffer overrun (fixes issue #506) +* SubGHz: Notifications fixes (by @wosk | PR #464) +* Plugins: Unitemp SCD30 support (PR in unitemp repo by @divinebird / fixed by @xMasterX) +* Plugins: Fix ProtoView issue #503 -> (Broken saved files with custom modulation) +* API: Add furi_hal_version_uid_default (+ Fix TOTP) (by @ClaraCrazy | PR #502) +* OFW: Fix reading Mifare Classic cards with unusual access conditions and fix emulation of unknown keys +* OFW: fbt: stable build dates +* OFW: weather_station: add oregon3 with THGR221 +* OFW: Services: simplify api (DOLPHIN_DEED->dolphin_deed - function instead of macros + remake all apps in extra pack and main fw to use new API) +* OFW: Core2, SRAM2: provide safety gap +* OFW: FuriHal: always clock SMPS from HSI +* OFW: ble: refactored bt gatt characteristics setup (+ remake of BT HID Led descriptor in new way to work with this changes) +* OFW: Scripts: WiFi board updater +* OFW: github: re-enabled f18 build +* OFW: added ISO15693 (NfcV) (was already added before, so we just updated it with latest changes) +* OFW: fbt: added Flipper selection when multiple are connected over USB +* OFW: fbt, ufbt: added checks for appid in app manifests +* OFW: Fix core2 permisions +* OFW: SubGhz: add subghz_protocol_registry external API (was already in our API but in different way) +* OFW: Furi: smaller critical enter and critical exit macro +* OFW: Serial_CLI: Fixing serial cli logger error so it sounds more concise +* OFW: Remove unused resources * OFW: Dolphin: new animation -* OFW: fbt: added hooks for build & dist environments; added FW_ORIGIN_* macro for apps & SDK -* OFW: FuriHal: add bus abstraction -> **Breaking API change, API version was changed from 27.x to 28.x** -* OFW: Implement support for reading Opal card (Sydney, Australia) -* OFW: BadUSB: script execution pause -* OFW: IR Universal AC: Add Carrier 42QHB12D8S +* OFW: f7: add PB9 to debug pins +* OFW: Settings: add contrast adjustment -> **Settings->LCD and Notifications will be resetted to default values one time after installing** +* OFW: FuriHal: add system setting to device info, bump device info version #### [🎲 Download latest extra apps pack](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip) From d87745f2bee5100d345dcaf0aa75436548a8eb28 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 10 Jun 2023 05:22:34 +0300 Subject: [PATCH 2/5] Update TOTP --- CHANGELOG.md | 9 +-- applications/external/totp/features_config.h | 5 ++ .../external/totp/services/crypto/crypto.c | 11 ++-- .../totp/services/idle_timeout/idle_timeout.c | 66 +++++++++++++++++++ .../totp/services/idle_timeout/idle_timeout.h | 44 +++++++++++++ applications/external/totp/totp_app.c | 38 +++++++---- .../external/totp/types/plugin_state.h | 9 +++ 7 files changed, 163 insertions(+), 19 deletions(-) create mode 100644 applications/external/totp/services/idle_timeout/idle_timeout.c create mode 100644 applications/external/totp/services/idle_timeout/idle_timeout.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 0534ce4fb..cd2eb93c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,13 @@ ----- * Plugins: **New RFID 125KHz and iButton Fuzzers (remake from scratch + new features)** (by @gid9798 | PR #507) * Plugins: SubGHz Bruteforcer -> Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + allow more repeats (by @gid9798 & @xMasterX) -* GUI: `Byte input` new feature: editor without keyboard (press Up until you get into new input, then use up/down to input values) (by @gid9798 | PR #509) -* Infrared: Update universal remote assets - add new ACs and TCL TV -* SubGHz: Remove broken modulation that was causing buffer overrun (fixes issue #506) -* SubGHz: Notifications fixes (by @wosk | PR #464) +* Plugins: Update TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) * Plugins: Unitemp SCD30 support (PR in unitemp repo by @divinebird / fixed by @xMasterX) * Plugins: Fix ProtoView issue #503 -> (Broken saved files with custom modulation) +* SubGHz: Remove broken modulation that was causing buffer overrun (fixes issue #506) +* SubGHz: Notifications fixes (by @wosk | PR #464) +* GUI: `Byte input` new feature: editor without keyboard (press Up until you get into new input, then use up/down to input values) (by @gid9798 | PR #509) +* Infrared: Update universal remote assets - add new ACs and TCL TV * API: Add furi_hal_version_uid_default (+ Fix TOTP) (by @ClaraCrazy | PR #502) * OFW: Fix reading Mifare Classic cards with unusual access conditions and fix emulation of unknown keys * OFW: fbt: stable build dates diff --git a/applications/external/totp/features_config.h b/applications/external/totp/features_config.h index 15e81b28a..59a1e0ecc 100644 --- a/applications/external/totp/features_config.h +++ b/applications/external/totp/features_config.h @@ -1,3 +1,8 @@ +// Application automatic lock timeout if user IDLE. (ticks) +#ifndef TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC +#define TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC (60) +#endif + // Include Bluetooth token input automation #define TOTP_BADBT_TYPE_ENABLED diff --git a/applications/external/totp/services/crypto/crypto.c b/applications/external/totp/services/crypto/crypto.c index 448529100..8c20fe785 100644 --- a/applications/external/totp/services/crypto/crypto.c +++ b/applications/external/totp/services/crypto/crypto.c @@ -6,10 +6,11 @@ #include "memset_s.h" #define CRYPTO_KEY_SLOT (2) -#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass" #define CRYPTO_VERIFY_KEY_LENGTH (16) #define CRYPTO_ALIGNMENT_FACTOR (16) +static const char* CRYPTO_VERIFY_KEY = "FFF_Crypto_pass"; + uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, const size_t plain_data_length, @@ -107,7 +108,7 @@ CryptoSeedIVResult plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; plugin_state->crypto_verify_data = totp_crypto_encrypt( - (uint8_t*)CRYPTO_VERIFY_KEY, + (const uint8_t*)CRYPTO_VERIFY_KEY, CRYPTO_VERIFY_KEY_LENGTH, &plugin_state->iv[0], &plugin_state->crypto_verify_data_length); @@ -122,7 +123,7 @@ CryptoSeedIVResult bool totp_crypto_verify_key(const PluginState* plugin_state) { size_t decrypted_key_length; - const uint8_t* decrypted_key = totp_crypto_decrypt( + uint8_t* decrypted_key = totp_crypto_decrypt( plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], @@ -133,5 +134,7 @@ bool totp_crypto_verify_key(const PluginState* plugin_state) { if(decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false; } + free(decrypted_key); + return key_valid; -} \ No newline at end of file +} diff --git a/applications/external/totp/services/idle_timeout/idle_timeout.c b/applications/external/totp/services/idle_timeout/idle_timeout.c new file mode 100644 index 000000000..9df1b5487 --- /dev/null +++ b/applications/external/totp/services/idle_timeout/idle_timeout.c @@ -0,0 +1,66 @@ +#include "idle_timeout.h" +#include +#include + +#define IDLE_TIMER_CHECK_PERIODICITY_SEC (1) +#define SEC_TO_TICKS(sec) ((sec)*1000) + +struct IdleTimeoutContext { + FuriTimer* timer; + bool activity_reported; + void* on_idle_callback_context; + IDLE_TIMEOUT_CALLBACK on_idle_callback; + uint16_t timeout_sec; + uint16_t idle_period_sec; + bool idle_handled; +}; + +static void idle_timer_callback(void* context) { + IdleTimeoutContext* instance = context; + if(instance->activity_reported) { + instance->idle_period_sec = 0; + instance->idle_handled = false; + instance->activity_reported = false; + } else if(!instance->idle_handled) { + if(instance->idle_period_sec >= instance->timeout_sec) { + instance->idle_handled = + instance->on_idle_callback(instance->on_idle_callback_context); + } else { + instance->idle_period_sec += IDLE_TIMER_CHECK_PERIODICITY_SEC; + } + } +} + +IdleTimeoutContext* idle_timeout_alloc( + uint16_t timeout_sec, + IDLE_TIMEOUT_CALLBACK on_idle_callback, + void* on_idle_callback_context) { + IdleTimeoutContext* instance = malloc(sizeof(IdleTimeoutContext)); + if(instance == NULL) return NULL; + + instance->timer = furi_timer_alloc(&idle_timer_callback, FuriTimerTypePeriodic, instance); + if(instance->timer == NULL) return NULL; + + instance->timeout_sec = timeout_sec; + instance->on_idle_callback = on_idle_callback; + instance->on_idle_callback_context = on_idle_callback_context; + return instance; +} + +void idle_timeout_start(IdleTimeoutContext* context) { + furi_timer_start(context->timer, SEC_TO_TICKS(IDLE_TIMER_CHECK_PERIODICITY_SEC)); +} + +void idle_timeout_stop(IdleTimeoutContext* context) { + furi_timer_stop(context->timer); +} + +void idle_timeout_report_activity(IdleTimeoutContext* context) { + context->activity_reported = true; +} + +void idle_timeout_free(IdleTimeoutContext* context) { + furi_timer_stop(context->timer); + furi_timer_free(context->timer); + free(context); +} diff --git a/applications/external/totp/services/idle_timeout/idle_timeout.h b/applications/external/totp/services/idle_timeout/idle_timeout.h new file mode 100644 index 000000000..12825e454 --- /dev/null +++ b/applications/external/totp/services/idle_timeout/idle_timeout.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +typedef struct IdleTimeoutContext IdleTimeoutContext; + +typedef bool (*IDLE_TIMEOUT_CALLBACK)(void* context); + +/** + * @brief Initializes a new instance of IDLE timeout + * @param timeout_sec IDLE timeout in seconds + * @param on_idle_callback callback function to trigger when IDLE timeout happened + * @param on_idle_callback_context callback function context + * @return IDLE timeout context + */ +IdleTimeoutContext* idle_timeout_alloc( + uint16_t timeout_sec, + IDLE_TIMEOUT_CALLBACK on_idle_callback, + void* on_idle_callback_context); + +/** + * @brief Starts IDLE timeout + * @param context IDLE timeout context + */ +void idle_timeout_start(IdleTimeoutContext* context); + +/** + * @brief Stops IDLE timeout + * @param context IDLE timeout context + */ +void idle_timeout_stop(IdleTimeoutContext* context); + +/** + * @brief Reports activity to IDLE timeout + * @param context IDLE timeout context + */ +void idle_timeout_report_activity(IdleTimeoutContext* context); + +/** + * @brief Disposes IDLE timeout and releases all the resources + * @param context IDLE timeout context + */ +void idle_timeout_free(IdleTimeoutContext* context); diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c index 57e5ff04f..642e27c61 100644 --- a/applications/external/totp/totp_app.c +++ b/applications/external/totp/totp_app.c @@ -18,8 +18,6 @@ #include "services/crypto/crypto.h" #include "cli/cli.h" -#define IDLE_TIMEOUT (60000) - static void render_callback(Canvas* const canvas, void* ctx) { furi_assert(ctx); PluginState* plugin_state = ctx; @@ -106,6 +104,17 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) { return true; } +static bool on_user_idle(void* context) { + PluginState* plugin_state = context; + if(plugin_state->current_scene != TotpSceneAuthentication && + plugin_state->current_scene != TotpSceneStandby) { + totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); + return true; + } + + return false; +} + static bool totp_plugin_state_init(PluginState* const plugin_state) { plugin_state->selected_font = 0; plugin_state->gui = furi_record_open(RECORD_GUI); @@ -128,10 +137,23 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { } #endif + if(plugin_state->pin_set) { + plugin_state->idle_timeout_context = + idle_timeout_alloc(TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC, &on_user_idle, plugin_state); + idle_timeout_start(plugin_state->idle_timeout_context); + } else { + plugin_state->idle_timeout_context = NULL; + } + return true; } static void totp_plugin_state_free(PluginState* plugin_state) { + if(plugin_state->idle_timeout_context != NULL) { + idle_timeout_stop(plugin_state->idle_timeout_context); + idle_timeout_free(plugin_state->idle_timeout_context); + } + furi_record_close(RECORD_GUI); furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_DIALOGS); @@ -185,14 +207,13 @@ int32_t totp_app() { PluginEvent event; bool processing = true; - uint32_t last_user_interaction_time = furi_get_tick(); while(processing) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); + FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever); if(furi_mutex_acquire(plugin_state->mutex, FuriWaitForever) == FuriStatusOk) { if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - last_user_interaction_time = furi_get_tick(); + if(event.type == EventTypeKey && plugin_state->idle_timeout_context != NULL) { + idle_timeout_report_activity(plugin_state->idle_timeout_context); } if(event.type == EventForceCloseApp) { @@ -200,11 +221,6 @@ int32_t totp_app() { } else { processing = totp_scene_director_handle_event(&event, plugin_state); } - } else if( - plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication && - plugin_state->current_scene != TotpSceneStandby && - furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); } view_port_update(view_port); diff --git a/applications/external/totp/types/plugin_state.h b/applications/external/totp/types/plugin_state.h index 97d126330..234894d58 100644 --- a/applications/external/totp/types/plugin_state.h +++ b/applications/external/totp/types/plugin_state.h @@ -6,6 +6,7 @@ #include "../features_config.h" #include "../ui/totp_scenes_enum.h" #include "../services/config/config_file_context.h" +#include "../services/idle_timeout/idle_timeout.h" #include "notification_method.h" #include "automation_method.h" #ifdef TOTP_BADBT_TYPE_ENABLED @@ -48,6 +49,9 @@ typedef struct { */ float timezone_offset; + /** + * @brief Config file context + */ ConfigFileContext* config_file_context; /** @@ -101,4 +105,9 @@ typedef struct { */ TotpBtTypeCodeWorkerContext* bt_type_code_worker_context; #endif + + /** + * @brief IDLE timeout context + */ + IdleTimeoutContext* idle_timeout_context; } PluginState; From f7195adbda9ed48c8aaed85e327cc12de143ee55 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 10 Jun 2023 06:01:23 +0300 Subject: [PATCH 3/5] OFW PR 2756 --- CHANGELOG.md | 1 + applications/services/dialogs/dialogs.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd2eb93c9..cc5af4149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * GUI: `Byte input` new feature: editor without keyboard (press Up until you get into new input, then use up/down to input values) (by @gid9798 | PR #509) * Infrared: Update universal remote assets - add new ACs and TCL TV * API: Add furi_hal_version_uid_default (+ Fix TOTP) (by @ClaraCrazy | PR #502) +* OFW PR 2756: fix: make dialog_file_browser_set_basic_options initialize all fields (by JarvisCraft) * OFW: Fix reading Mifare Classic cards with unusual access conditions and fix emulation of unknown keys * OFW: fbt: stable build dates * OFW: weather_station: add oregon3 with THGR221 diff --git a/applications/services/dialogs/dialogs.c b/applications/services/dialogs/dialogs.c index 3908ca31b..10c08a991 100644 --- a/applications/services/dialogs/dialogs.c +++ b/applications/services/dialogs/dialogs.c @@ -9,12 +9,13 @@ void dialog_file_browser_set_basic_options( const char* extension, const Icon* icon) { options->extension = extension; + options->base_path = NULL; options->skip_assets = true; + options->hide_dot_files = true; options->icon = icon; options->hide_ext = true; options->item_loader_callback = NULL; options->item_loader_context = NULL; - options->base_path = NULL; } static DialogsApp* dialogs_app_alloc() { From 26e38bc7925e751dfd97003e7ce6d4142407cdc2 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 10 Jun 2023 06:02:56 +0300 Subject: [PATCH 4/5] Upd readme --- ReadMe.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReadMe.md b/ReadMe.md index 0c545682c..6256d5905 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -57,6 +57,7 @@ Our Discord Community: * Sub-GHz -> Short press OK in frequency analyzer to save detected frequency for usage in Read modes * Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu and automatically use selected frequency * SubGHz -> New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON` +* SubGHz Bruteforcer plugin -> Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol * SubGHz -> Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk) * Sub-GHz -> External CC1101 module support (Hardware SPI used) * SubGHz -> **Hold right in received signal list to delete selected signal** From 451aa86c91cd109bfc448d9e6a2271e98c0025be Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 10 Jun 2023 21:02:52 +0300 Subject: [PATCH 5/5] Infrared RCA Protocol + Update docs Thanks to anonymous contributor for protocol implementation and testing --- ReadMe.md | 3 ++ .../file_formats/InfraredFileFormats.md | 17 +++++++ lib/infrared/encoder_decoder/infrared.c | 15 +++++++ lib/infrared/encoder_decoder/infrared.h | 1 + .../rca/infrared_decoder_rca.c | 45 +++++++++++++++++++ .../rca/infrared_encoder_rca.c | 37 +++++++++++++++ .../rca/infrared_protocol_rca.c | 40 +++++++++++++++++ .../rca/infrared_protocol_rca.h | 30 +++++++++++++ .../rca/infrared_protocol_rca_i.h | 30 +++++++++++++ 9 files changed, 218 insertions(+) create mode 100644 lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c create mode 100644 lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c create mode 100644 lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c create mode 100644 lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h create mode 100644 lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h diff --git a/ReadMe.md b/ReadMe.md index 6256d5905..19d74fed8 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -65,6 +65,7 @@ Our Discord Community: * SubGHz -> BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis) * SubGHz -> Debug mode counter increase settings (+1 -> +5, +10, default: +1) * SubGHz -> Debug PIN output settings for protocol development +* Infrared -> `RCA` Protocol * Infrared -> Debug TX PIN output settings * Other small fixes and changes throughout * See other changes in readme below @@ -198,6 +199,8 @@ Games: ## [- How to use Mifare Nested plugin to recover keys](https://github.com/AloneLiberty/FlipperNested#how-to-use-it) +## [- How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md) + ### **Sub-GHz** ## [- Transmission is blocked? - How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md) diff --git a/documentation/file_formats/InfraredFileFormats.md b/documentation/file_formats/InfraredFileFormats.md index 3c0acdcb7..c9b6a9536 100644 --- a/documentation/file_formats/InfraredFileFormats.md +++ b/documentation/file_formats/InfraredFileFormats.md @@ -1,5 +1,22 @@ # Infrared Flipper File Formats + +## Supported protocols list for `type: parsed` +``` + NEC + NECext + NEC42 + NEC42ext + Samsung32 + RC6 + RC5 + RC5X + SIRC + SIRC15 + SIRC20 + Kaseikyo + RCA +``` ## Infrared Remote File Format ### Example diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index fcfc5da2b..56f2c3f9e 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -11,6 +11,7 @@ #include "rc6/infrared_protocol_rc6.h" #include "sirc/infrared_protocol_sirc.h" #include "kaseikyo/infrared_protocol_kaseikyo.h" +#include "rca/infrared_protocol_rca.h" typedef struct { InfraredAlloc alloc; @@ -127,6 +128,20 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .free = infrared_encoder_kaseikyo_free}, .get_protocol_variant = infrared_protocol_kaseikyo_get_variant, }, + { + .decoder = + {.alloc = infrared_decoder_rca_alloc, + .decode = infrared_decoder_rca_decode, + .reset = infrared_decoder_rca_reset, + .check_ready = infrared_decoder_rca_check_ready, + .free = infrared_decoder_rca_free}, + .encoder = + {.alloc = infrared_encoder_rca_alloc, + .encode = infrared_encoder_rca_encode, + .reset = infrared_encoder_rca_reset, + .free = infrared_encoder_rca_free}, + .get_protocol_variant = infrared_protocol_rca_get_variant, + }, }; static int infrared_find_index_by_protocol(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index 3ab46cbbf..ada449b98 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -33,6 +33,7 @@ typedef enum { InfraredProtocolSIRC15, InfraredProtocolSIRC20, InfraredProtocolKaseikyo, + InfraredProtocolRCA, InfraredProtocolMAX, } InfraredProtocol; diff --git a/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c b/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c new file mode 100644 index 000000000..b6d02a38c --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c @@ -0,0 +1,45 @@ +#include "infrared_protocol_rca_i.h" +#include + +InfraredMessage* infrared_decoder_rca_check_ready(void* ctx) { + return infrared_common_decoder_check_ready(ctx); +} + +bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder) { + furi_assert(decoder); + + uint32_t* data = (void*)&decoder->data; + + uint8_t address = (*data & 0xF); + uint8_t command = (*data >> 4) & 0xFF; + uint8_t address_inverse = (*data >> 12) & 0xF; + uint8_t command_inverse = (*data >> 16) & 0xFF; + uint8_t inverse_address_inverse = (uint8_t)~address_inverse & 0xF; + uint8_t inverse_command_inverse = (uint8_t)~command_inverse; + + if((command == inverse_command_inverse) && (address == inverse_address_inverse)) { + decoder->message.protocol = InfraredProtocolRCA; + decoder->message.address = address; + decoder->message.command = command; + decoder->message.repeat = false; + return true; + } + + return false; +} + +void* infrared_decoder_rca_alloc(void) { + return infrared_common_decoder_alloc(&infrared_protocol_rca); +} + +InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration) { + return infrared_common_decode(decoder, level, duration); +} + +void infrared_decoder_rca_free(void* decoder) { + infrared_common_decoder_free(decoder); +} + +void infrared_decoder_rca_reset(void* decoder) { + infrared_common_decoder_reset(decoder); +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c b/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c new file mode 100644 index 000000000..f0be4a6a9 --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c @@ -0,0 +1,37 @@ +#include "infrared_protocol_rca_i.h" + +#include + +void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message) { + furi_assert(encoder_ptr); + furi_assert(message); + + InfraredCommonEncoder* encoder = encoder_ptr; + infrared_common_encoder_reset(encoder); + + uint32_t* data = (void*)encoder->data; + + uint8_t address = message->address; + uint8_t address_inverse = ~address; + uint8_t command = message->command; + uint8_t command_inverse = ~command; + + *data = address & 0xF; + *data |= command << 4; + *data |= (address_inverse & 0xF) << 12; + *data |= command_inverse << 16; + + encoder->bits_to_encode = encoder->protocol->databit_len[0]; +} + +void* infrared_encoder_rca_alloc(void) { + return infrared_common_encoder_alloc(&infrared_protocol_rca); +} + +void infrared_encoder_rca_free(void* encoder_ptr) { + infrared_common_encoder_free(encoder_ptr); +} + +InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level) { + return infrared_common_encode(encoder_ptr, duration, level); +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c new file mode 100644 index 000000000..8e1e76dbd --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_rca_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rca = { + .timings = + { + .preamble_mark = INFRARED_RCA_PREAMBLE_MARK, + .preamble_space = INFRARED_RCA_PREAMBLE_SPACE, + .bit1_mark = INFRARED_RCA_BIT1_MARK, + .bit1_space = INFRARED_RCA_BIT1_SPACE, + .bit0_mark = INFRARED_RCA_BIT0_MARK, + .bit0_space = INFRARED_RCA_BIT0_SPACE, + .preamble_tolerance = INFRARED_RCA_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_RCA_BIT_TOLERANCE, + .silence_time = INFRARED_RCA_SILENCE, + .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, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rca = { + .name = "RCA", + .address_length = 4, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_RCA_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRCA) + return &infrared_protocol_variant_rca; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h new file mode 100644 index 000000000..d9cae48e4 --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RCA protocol description +* https://www.sbprojects.net/knowledge/ir/rca.php +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble +* mark space Modulation up to period repeat repeat +* mark space +* +* 4000 4000 24 bit ...8000 4000 4000 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ +* +***************************************************************************************************/ + +void* infrared_decoder_rca_alloc(void); +void infrared_decoder_rca_reset(void* decoder); +void infrared_decoder_rca_free(void* decoder); +InfraredMessage* infrared_decoder_rca_check_ready(void* decoder); +InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rca_alloc(void); +InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rca_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h new file mode 100644 index 000000000..9ec4fe3b1 --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RCA_PREAMBLE_MARK 4000 +#define INFRARED_RCA_PREAMBLE_SPACE 4000 +#define INFRARED_RCA_BIT1_MARK 500 +#define INFRARED_RCA_BIT1_SPACE 2000 +#define INFRARED_RCA_BIT0_MARK 500 +#define INFRARED_RCA_BIT0_SPACE 1000 +#define INFRARED_RCA_REPEAT_PERIOD 8000 +#define INFRARED_RCA_SILENCE INFRARED_RCA_REPEAT_PERIOD + +#define INFRARED_RCA_MIN_SPLIT_TIME INFRARED_RCA_REPEAT_PAUSE_MIN +#define INFRARED_RCA_REPEAT_PAUSE_MIN 4000 +#define INFRARED_RCA_REPEAT_PAUSE_MAX 150000 +#define INFRARED_RCA_REPEAT_COUNT_MIN 1 +#define INFRARED_RCA_REPEAT_MARK INFRARED_RCA_PREAMBLE_MARK +#define INFRARED_RCA_REPEAT_SPACE INFRARED_RCA_PREAMBLE_SPACE +#define INFRARED_RCA_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RCA_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_rca; + +bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_rca_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_rca_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level);