From c1a009aed0e335badc4a004d1243c01dd8a6390a Mon Sep 17 00:00:00 2001 From: Anna Antonenko Date: Tue, 10 Sep 2024 19:58:44 +0300 Subject: [PATCH 1/5] fix: exit screen stopping bridge prematurely --- applications/main/gpio/gpio_custom_event.h | 1 + .../gpio/scenes/gpio_scene_exit_confirm.c | 7 +++-- .../main/gpio/scenes/gpio_scene_usb_uart.c | 26 ++++++++++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/applications/main/gpio/gpio_custom_event.h b/applications/main/gpio/gpio_custom_event.h index 72b8feccd..b18ad698a 100644 --- a/applications/main/gpio/gpio_custom_event.h +++ b/applications/main/gpio/gpio_custom_event.h @@ -10,4 +10,5 @@ typedef enum { GpioUsbUartEventConfig, GpioUsbUartEventConfigSet, + GpioUsbUartEventStop, } GpioCustomEvent; diff --git a/applications/main/gpio/scenes/gpio_scene_exit_confirm.c b/applications/main/gpio/scenes/gpio_scene_exit_confirm.c index efb0734a3..32977e516 100644 --- a/applications/main/gpio/scenes/gpio_scene_exit_confirm.c +++ b/applications/main/gpio/scenes/gpio_scene_exit_confirm.c @@ -24,10 +24,9 @@ bool gpio_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DialogExResultRight) { - consumed = scene_manager_previous_scene(app->scene_manager); - } else if(event.event == DialogExResultLeft) { - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, GpioSceneStart); + consumed = scene_manager_previous_scene(app->scene_manager); + if(consumed && event.event == DialogExResultLeft) { + view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventStop); } } else if(event.type == SceneManagerEventTypeBack) { consumed = true; diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart.c b/applications/main/gpio/scenes/gpio_scene_usb_uart.c index 9a3514ca4..6c6fdb23d 100644 --- a/applications/main/gpio/scenes/gpio_scene_usb_uart.c +++ b/applications/main/gpio/scenes/gpio_scene_usb_uart.c @@ -8,6 +8,11 @@ typedef struct { static SceneUsbUartBridge* scene_usb_uart; +typedef enum { + UsbUartSceneStateInitialize, + UsbUartSceneStateKeep, +} UsbUartSceneState; + void gpio_scene_usb_uart_callback(GpioCustomEvent event, void* context) { furi_assert(context); GpioApp* app = context; @@ -16,8 +21,9 @@ void gpio_scene_usb_uart_callback(GpioCustomEvent event, void* context) { void gpio_scene_usb_uart_on_enter(void* context) { GpioApp* app = context; - uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart); - if(prev_state == 0) { + UsbUartSceneState state = + scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart); + if(state == UsbUartSceneStateInitialize) { scene_usb_uart = malloc(sizeof(SceneUsbUartBridge)); scene_usb_uart->cfg.vcp_ch = 0; scene_usb_uart->cfg.uart_ch = 0; @@ -39,10 +45,18 @@ void gpio_scene_usb_uart_on_enter(void* context) { bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) { GpioApp* app = context; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, 1); - scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCfg); + if(event.event == GpioUsbUartEventConfig) { + scene_manager_set_scene_state( + app->scene_manager, GpioSceneUsbUart, UsbUartSceneStateKeep); + scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCfg); + } else if(event.event == GpioUsbUartEventStop) { + scene_manager_set_scene_state( + app->scene_manager, GpioSceneUsbUart, UsbUartSceneStateInitialize); + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, GpioSceneStart); + } return true; } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, UsbUartSceneStateKeep); scene_manager_next_scene(app->scene_manager, GpioSceneExitConfirm); return true; } else if(event.type == SceneManagerEventTypeTick) { @@ -61,8 +75,8 @@ bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) { void gpio_scene_usb_uart_on_exit(void* context) { GpioApp* app = context; - uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioSceneUsbUart); - if(prev_state == 0) { + uint32_t state = scene_manager_get_scene_state(app->scene_manager, GpioSceneUsbUart); + if(state == UsbUartSceneStateInitialize) { usb_uart_disable(app->usb_uart_bridge); free(scene_usb_uart); } From 117e1789c11a09dbe65d351956210bff029ab610 Mon Sep 17 00:00:00 2001 From: chrostino <100096435+chrostino@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:30:58 +0200 Subject: [PATCH 2/5] Update SubGHzRemoteProg.md Improved the description steps to create a new remote BFT Mitto with more detailed and accurate instructions --- documentation/SubGHzRemoteProg.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/SubGHzRemoteProg.md b/documentation/SubGHzRemoteProg.md index 1c14678f5..9594b9e6c 100644 --- a/documentation/SubGHzRemoteProg.md +++ b/documentation/SubGHzRemoteProg.md @@ -101,7 +101,9 @@ How to create new remote and bind it to receiver (will not conflict with origina 4. Original Remote: Press hidden button on back of remote with a pin or paper clip OR press Button 1 & 2 together until remote LED lights. 5. Original Remote: Momentarily press button that opens device 6. Long press (Right Arrow) - (0xF button - Btn:F) on Flipper for like 3-5 sec -7. Done? +7. Press the button you want to bind to open the device on the flipper +8. Press (Right Arrow) - (0xF button - Btn:F) again +9. Done? OR @@ -174,4 +176,4 @@ garage/gate. - [Somfy Telis](https://pushstack.wordpress.com/somfy-rts-protocol/) - [BFT Mitto](https://www.retroremotes.com.au/wp-content/uploads/2017/03/BFT-MITTO-2-4-19-6-17.pdf) - [NICE FLOX2R Receiver Programming](https://apollogateopeners.com/store/pdf/apollo-flor-s-receiver-programming-guide.pdf) -- [Nice Flor S Programming](https://motepro.com.au/Instructions/Nice.pdf) \ No newline at end of file +- [Nice Flor S Programming](https://motepro.com.au/Instructions/Nice.pdf) From 1ca240b6241bb13086e56f119ad4bac394bd0585 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:59:41 +0300 Subject: [PATCH 3/5] princeton custom buttons support [ci skip] --- lib/subghz/protocols/princeton.c | 152 +++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 728187c0f..f271de250 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -6,6 +6,8 @@ #include "../blocks/generic.h" #include "../blocks/math.h" +#include "../blocks/custom_btn_i.h" + /* * Help * https://phreakerclub.com/447 @@ -105,6 +107,109 @@ void subghz_protocol_encoder_princeton_free(void* context) { free(instance); } +// Get custom button code +static uint8_t subghz_protocol_princeton_get_btn_code(void) { + uint8_t custom_btn_id = subghz_custom_btn_get(); + uint8_t original_btn_code = subghz_custom_btn_get_original(); + uint8_t btn = original_btn_code; + + // Set custom button + if((custom_btn_id == SUBGHZ_CUSTOM_BTN_OK) && (original_btn_code != 0)) { + // Restore original button code + btn = original_btn_code; + } else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_UP) { + switch(original_btn_code) { + case 0x1: + btn = 0x2; + break; + case 0x2: + btn = 0x1; + break; + case 0x4: + btn = 0x2; + break; + case 0x8: + btn = 0x2; + break; + case 0xF: + btn = 0x2; + break; + + default: + btn = 0x2; + break; + } + } else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_DOWN) { + switch(original_btn_code) { + case 0x1: + btn = 0x4; + break; + case 0x2: + btn = 0x4; + break; + case 0x4: + btn = 0x1; + break; + case 0x8: + btn = 0x1; + break; + case 0xF: + btn = 0x1; + break; + + default: + btn = 0x1; + break; + } + } else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_LEFT) { + switch(original_btn_code) { + case 0x1: + btn = 0x8; + break; + case 0x2: + btn = 0x8; + break; + case 0x4: + btn = 0x8; + break; + case 0x8: + btn = 0x4; + break; + case 0xF: + btn = 0x4; + break; + + default: + btn = 0x4; + break; + } + } else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_RIGHT) { + switch(original_btn_code) { + case 0x1: + btn = 0xF; + break; + case 0x2: + btn = 0xF; + break; + case 0x4: + btn = 0xF; + break; + case 0x8: + btn = 0xF; + break; + case 0xF: + btn = 0x8; + break; + + default: + btn = 0x8; + break; + } + } + + return btn; +} + /** * Generating an upload from data. * @param instance Pointer to a SubGhzProtocolEncoderPrinceton instance @@ -114,6 +219,13 @@ static bool subghz_protocol_encoder_princeton_get_upload(SubGhzProtocolEncoderPrinceton* instance) { furi_assert(instance); + // Generate new key using custom or default button + instance->generic.btn = subghz_protocol_princeton_get_btn_code(); + + // Reconstruction of the data + instance->generic.data = + ((uint64_t)instance->generic.serial << 4 | (uint64_t)instance->generic.btn); + size_t index = 0; size_t size_upload = (instance->generic.data_count_bit * 2) + 2; if(size_upload > instance->encoder.size_upload) { @@ -147,6 +259,21 @@ static bool return true; } +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric* instance) { + instance->serial = instance->data >> 4; + instance->btn = instance->data & 0xF; + + // Save original button for later use + if(subghz_custom_btn_get_original() == 0) { + subghz_custom_btn_set_original(instance->btn); + } + subghz_custom_btn_set_max(4); +} + SubGhzProtocolStatus subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); @@ -184,10 +311,26 @@ SubGhzProtocolStatus flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + // Get button and serial before calling get_upload + subghz_protocol_princeton_check_remote_controller(&instance->generic); + if(!subghz_protocol_encoder_princeton_get_upload(instance)) { ret = SubGhzProtocolStatusErrorEncoderGetUpload; break; } + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + 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"); + break; + } instance->encoder.is_running = true; } while(false); @@ -316,15 +459,6 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t } } -/** - * Analysis of received data - * @param instance Pointer to a SubGhzBlockGeneric* instance - */ -static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric* instance) { - instance->serial = instance->data >> 4; - instance->btn = instance->data & 0xF; -} - uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; From f9f2938bd4a451f34c96b05ebe7662fe7ed7730e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 11 Sep 2024 02:28:00 +0300 Subject: [PATCH 4/5] upd changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a7c51ae4..5ca8f32a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - GangQi (static 34 bit) with button parsing and add manually support (thanks to @mishamyte for captures and testing) - Hollarm (static 42 bit) with button parsing and add manually support (thanks to @mishamyte for captures) - Hay21 (dynamic 21 bit) with button parsing + - Princeton custom buttons support (0x1, 0x2, 0x4, 0x8, 0xF) - 125kHz RFID: - OFW: Fix detection of GProx II cards and false detection of other cards (by @Astrrra) - OFW: Fix Guard GProxII False Positive and 36-bit Parsing (by @zinongli) @@ -18,8 +19,10 @@ * OFW: Infrared: Universal AC - Add Airwell AW-HKD012-N91 * OFW: Broken file interaction fixes * OFW: Add the Procrastination animation +* OFW PR 3892: Fix USB-UART bridge exit screen stopping the bridge prematurely (by @portasynthinca3) * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes +* Docs: Improved the description steps to create a new remote BFT Mitto with more detailed and accurate instructions (by @chrostino | PR #805) * OFW: FuriTimer: Use an event instead of a volatile bool to wait for deletion * OFW: Threading, Timers improvements * OFW: Replace all calls to strncpy with strlcpy, use strdup more, expose strlcat From c2f6ce7e54856e03a959c977739bfe32ffddae0f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 11 Sep 2024 03:00:09 +0300 Subject: [PATCH 5/5] upd readme [ci skip] --- ReadMe.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index b2911d14d..4c3807688 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -105,10 +105,14 @@ Thanks to Official team (to their SubGHz Developer, Skorp) for implementing supp Keeloq [Not ALL systems supported for decode or emulation!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m) -Encoders or emulation (+ programming mode) support made by @xMasterX: +Decoders/Encoders or emulation (+ programming mode) support made by @xMasterX: +- Marantec24 (static 24 bit) with add manually support +- GangQi (static 34 bit) with button parsing and add manually support (thanks to @mishamyte for captures and testing, thanks @Skorpionm for help) +- Hollarm (static 42 bit) with button parsing and add manually support (thanks to @mishamyte for captures, thanks @Skorpionm for help) +- Hay21 (dynamic 21 bit) with button parsing - Nero Radio 57bit (+ 56bit support) - CAME 12bit/24bit encoder fixes (Fixes are now merged in OFW) -- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm +- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm, Sommer Protocols support made by Skorp (original implementation) and @xMasterX (current version): - CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)