From e4f315188b640734baed80d7d19fd273697e4312 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 07:37:28 +0300 Subject: [PATCH 01/12] fbt format --- applications/main/lfrfid/lfrfid.c | 3 +-- .../main/nfc/helpers/protocol_support/emv/emv_render.c | 3 ++- .../main/nfc/plugins/supported_cards/social_moscow.c | 2 +- applications/main/subghz/views/subghz_frequency_analyzer.c | 3 ++- applications/system/hid_app/views/hid_numpad.c | 3 +-- .../system/js_app/modules/js_usbdisk/mass_storage_usb.c | 6 ++++-- lib/lfrfid/lfrfid_worker_modes.c | 3 ++- lib/lfrfid/protocols/protocol_em4100.c | 3 +-- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index ce80321bc..a405c0f85 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -18,8 +18,7 @@ const uint32_t default_passwords[] = { 0xA0000000, 0xA0A1A2A3, 0xA5B4C3D2, 0xAA55AA55, 0xAA55BBBB, 0xAAAAAAAA, 0xAABBCCDD, 0xABCD1234, 0xB0000000, 0xB0B1B2B3, 0xB5F44686, 0xBBBBBBBB, 0xBBCCDDEE, 0xC0000000, 0xC0F5009A, 0xC6EF3720, 0xCCCCCCCC, 0xCCDDEEFF, 0xD0000000, 0xDDDDDDDD, 0xDEADC0DE, 0xE0000000, 0xE4204998, 0xE9920427, - 0xEEEEEEEE, 0xF0000000, 0xF1EA5EED, 0xF9DCEBA0, 0xFABADA11, 0xFEEDBEEF, 0xFFFFFFFF -}; + 0xEEEEEEEE, 0xF0000000, 0xF1EA5EED, 0xF9DCEBA0, 0xFABADA11, 0xFEEDBEEF, 0xFFFFFFFF}; const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len) { *len = sizeof(default_passwords) / sizeof(uint32_t); diff --git a/applications/main/nfc/helpers/protocol_support/emv/emv_render.c b/applications/main/nfc/helpers/protocol_support/emv/emv_render.c index ba6866a50..9a586fe4b 100644 --- a/applications/main/nfc/helpers/protocol_support/emv/emv_render.c +++ b/applications/main/nfc/helpers/protocol_support/emv/emv_render.c @@ -68,7 +68,8 @@ void nfc_render_emv_application(const EmvApplication* apl, FuriString* str) { const uint8_t len = apl->aid_len; furi_string_cat_printf(str, "AID: "); - for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%02X", apl->aid[i]); + for(uint8_t i = 0; i < len; i++) + furi_string_cat_printf(str, "%02X", apl->aid[i]); furi_string_cat_printf(str, "\n"); } diff --git a/applications/main/nfc/plugins/supported_cards/social_moscow.c b/applications/main/nfc/plugins/supported_cards/social_moscow.c index 55ca6a1ec..cce74946d 100644 --- a/applications/main/nfc/plugins/supported_cards/social_moscow.c +++ b/applications/main/nfc/plugins/supported_cards/social_moscow.c @@ -59,7 +59,7 @@ static const MfClassicKeyPair social_moscow_4k_keys[] = { {.a = 0xa229e68ad9e5, .b = 0x49c2b5296ef4}, {.a = 0xa229e68ad9e5, .b = 0x49c2b5296ef4}, }; -#define TOPBIT(X) (1 << ((X)-1)) +#define TOPBIT(X) (1 << ((X) - 1)) void from_days_to_datetime(uint16_t days, DateTime* datetime, uint16_t start_year) { uint32_t timestamp = days * 24 * 60 * 60; diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index d2c19576c..74060a929 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -402,7 +402,8 @@ uint32_t round_int(uint32_t value, uint8_t n) { value /= 10; if(i >= 5) value++; } - while(on--) value *= 10; + while(on--) + value *= 10; return value; } diff --git a/applications/system/hid_app/views/hid_numpad.c b/applications/system/hid_app/views/hid_numpad.c index 7e528e3fb..d78c291e0 100644 --- a/applications/system/hid_app/views/hid_numpad.c +++ b/applications/system/hid_app/views/hid_numpad.c @@ -289,8 +289,7 @@ HidNumpad* hid_numpad_alloc(Hid* bt_hid) { view_set_draw_callback(hid_numpad->view, hid_numpad_draw_callback); view_set_input_callback(hid_numpad->view, hid_numpad_input_callback); - with_view_model( - hid_numpad->view, HidNumpadModel * model, { model->y = 0; }, true); + with_view_model(hid_numpad->view, HidNumpadModel * model, { model->y = 0; }, true); return hid_numpad; } diff --git a/applications/system/js_app/modules/js_usbdisk/mass_storage_usb.c b/applications/system/js_app/modules/js_usbdisk/mass_storage_usb.c index b96b4fecc..bae1b6654 100644 --- a/applications/system/js_app/modules/js_usbdisk/mass_storage_usb.c +++ b/applications/system/js_app/modules/js_usbdisk/mass_storage_usb.c @@ -456,14 +456,16 @@ MassStorageUsb* mass_storage_usb_start(const char* filename, SCSIDeviceFunc fn) struct usb_string_descriptor* str_prod_descr = malloc(len * 2 + 2); str_prod_descr->bLength = len * 2 + 2; str_prod_descr->bDescriptorType = USB_DTYPE_STRING; - for(uint8_t i = 0; i < len; i++) str_prod_descr->wString[i] = name[i]; + for(uint8_t i = 0; i < len; i++) + str_prod_descr->wString[i] = name[i]; mass->usb.str_prod_descr = str_prod_descr; len = strlen(filename); struct usb_string_descriptor* str_serial_descr = malloc(len * 2 + 2); str_serial_descr->bLength = len * 2 + 2; str_serial_descr->bDescriptorType = USB_DTYPE_STRING; - for(uint8_t i = 0; i < len; i++) str_serial_descr->wString[i] = filename[i]; + for(uint8_t i = 0; i < len; i++) + str_serial_descr->wString[i] = filename[i]; mass->usb.str_serial_descr = str_serial_descr; mass->fn = fn; diff --git a/lib/lfrfid/lfrfid_worker_modes.c b/lib/lfrfid/lfrfid_worker_modes.c index b0ed99096..ec72542d5 100644 --- a/lib/lfrfid/lfrfid_worker_modes.c +++ b/lib/lfrfid/lfrfid_worker_modes.c @@ -52,7 +52,8 @@ void lfrfid_worker_delay(LFRFIDWorker* worker, uint32_t milliseconds) { void t5577_trace(LFRFIDT5577 t5577, const char* message) { if(furi_log_get_level() == FuriLogLevelTrace) { FURI_LOG_T(TAG, "%s", message); - for(uint8_t i = 0; i < 8; i++) FURI_LOG_T(TAG, "\nBlock %u %08lX", i, t5577.block[i]); + for(uint8_t i = 0; i < 8; i++) + FURI_LOG_T(TAG, "\nBlock %u %08lX", i, t5577.block[i]); FURI_LOG_T(TAG, "Mask: %u", t5577.mask); FURI_LOG_T(TAG, "Blocks to write: %lu", t5577.blocks_to_write); } diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c index 1b04b2a8c..b5b5106c6 100644 --- a/lib/lfrfid/protocols/protocol_em4100.c +++ b/lib/lfrfid/protocols/protocol_em4100.c @@ -352,8 +352,7 @@ void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) { data[2], (uint16_t)((data[3] << 8) | (data[4])), protocol->clock_per_bit, - (uint32_t)((data[2] << 16) | (data[3] << 8) | (data[4])) - ); + (uint32_t)((data[2] << 16) | (data[3] << 8) | (data[4]))); }; const ProtocolBase protocol_em4100 = { From 3b74c0733f63d09e5b5413bdde88038c3fa71667 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 07:51:20 +0300 Subject: [PATCH 02/12] js subghz module fixes and improvements by @Willy-JL --- .../apps/Scripts/js_examples/subghz.js | 14 +- .../js_app/modules/js_subghz/js_subghz.c | 302 +++++++++++++----- 2 files changed, 233 insertions(+), 83 deletions(-) diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js b/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js index 39dadf070..b5e54bac6 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js @@ -29,9 +29,17 @@ changeFrequency(433920000); printRXline(); delay(1000); -let result = subghz.transmitFile("/ext/subghz/0.sub"); -print(result ? "Send success" : "Send failed"); +print("Sending 0.sub") +subghz.transmitFile("/ext/subghz/0.sub"); +// Can also specify repeat count: subghz.transmitFile(path, repeat) +// If not provided, defaults to 1 repeat for RAW and 10 repeats for parsed +// These 10 repeats by default are to simulate holding the button on remote +print("Send success"); delay(1000); changeFrequency(315000000); -printRXline(); \ No newline at end of file +printRXline(); + +// Optional, done automatically at script end +subghz.end() +// But can be used to setup again, which will retry to detect external modules \ No newline at end of file diff --git a/applications/system/js_app/modules/js_subghz/js_subghz.c b/applications/system/js_app/modules/js_subghz/js_subghz.c index f170aa04b..30f1ae81e 100644 --- a/applications/system/js_app/modules/js_subghz/js_subghz.c +++ b/applications/system/js_app/modules/js_subghz/js_subghz.c @@ -7,7 +7,7 @@ #include -#define tag "js_subghz" +#define TAG "js_subghz" typedef enum { JsSubghzRadioStateRX, @@ -22,7 +22,6 @@ typedef struct { JsSubghzRadioState state; } JsSubghzInst; -// from subghz cli static FuriHalSubGhzPreset js_subghz_get_preset_name(const char* preset_name) { FuriHalSubGhzPreset preset = FuriHalSubGhzPresetIDLE; if(!strcmp(preset_name, "FuriHalSubGhzPresetOok270Async")) { @@ -36,7 +35,7 @@ static FuriHalSubGhzPreset js_subghz_get_preset_name(const char* preset_name) { } else if(!strcmp(preset_name, "FuriHalSubGhzPresetCustom")) { preset = FuriHalSubGhzPresetCustom; } else { - FURI_LOG_I(tag, "unknown preset"); + FURI_LOG_I(TAG, "unknown preset"); } return preset; } @@ -46,27 +45,37 @@ static void js_subghz_set_rx(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); - if(js_subghz->state == JsSubghzRadioStateRX) { + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); mjs_return(mjs, MJS_UNDEFINED); return; } - subghz_devices_set_rx(js_subghz->radio_device); - js_subghz->state = JsSubghzRadioStateRX; + if(js_subghz->state != JsSubghzRadioStateRX) { + subghz_devices_set_rx(js_subghz->radio_device); + js_subghz->state = JsSubghzRadioStateRX; + } + + mjs_return(mjs, MJS_UNDEFINED); } -static void js_subgjz_set_idle(struct mjs* mjs) { +static void js_subghz_set_idle(struct mjs* mjs) { mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); - if(js_subghz->state == JsSubghzRadioStateIDLE) { + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); mjs_return(mjs, MJS_UNDEFINED); return; } - subghz_devices_idle(js_subghz->radio_device); - js_subghz->state = JsSubghzRadioStateIDLE; + if(js_subghz->state != JsSubghzRadioStateIDLE) { + subghz_devices_idle(js_subghz->radio_device); + js_subghz->state = JsSubghzRadioStateIDLE; + } + + mjs_return(mjs, MJS_UNDEFINED); } static void js_subghz_get_rssi(struct mjs* mjs) { @@ -74,6 +83,12 @@ static void js_subghz_get_rssi(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + if(js_subghz->state != JsSubghzRadioStateRX) { mjs_return(mjs, MJS_UNDEFINED); return; @@ -88,6 +103,12 @@ static void js_subghz_get_state(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + const char* state; switch(js_subghz->state) { case JsSubghzRadioStateRX: @@ -112,6 +133,12 @@ static void js_subghz_is_external(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + mjs_return(mjs, mjs_mk_boolean(mjs, js_subghz->is_external)); } @@ -120,6 +147,12 @@ static void js_subghz_set_frequency(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + if(js_subghz->state != JsSubghzRadioStateIDLE) { mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not in IDLE state"); mjs_return(mjs, MJS_UNDEFINED); @@ -150,6 +183,12 @@ static void js_subghz_get_frequency(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + mjs_return(mjs, mjs_mk_number(mjs, (double)js_subghz->frequency)); } @@ -158,8 +197,13 @@ static void js_subghz_transmit_file(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); - mjs_val_t file = mjs_arg(mjs, 0); + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + mjs_val_t file = mjs_arg(mjs, 0); if(!mjs_is_string(file)) { mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "File must be a string"); mjs_return(mjs, MJS_UNDEFINED); @@ -173,9 +217,25 @@ static void js_subghz_transmit_file(struct mjs* mjs) { return; } + // Repeat works weirdly: + // - "Repeat" in parsed protocol is like holding Send in Sub-GHz app + // This is necessary as most receivers require hearing signals multiple times + // - "repeat" as variable and loop in this code applies to RAW files only + // parsed files handle repeat in protocol layer instead + // We keep 0 as default, or literal value if specified by user + // If user did not specify, -1 is detected below, and we use: + // - 1 repeat for RAW + // - 10 repeats for parsed, which is passed to protocol, and we loop once here + uint32_t repeat = 0; + mjs_val_t repeat_arg = mjs_arg(mjs, 1); + if(mjs_is_number(repeat_arg)) { + int32_t repeat_val = mjs_get_int32(mjs, repeat_arg); + repeat = MAX(repeat_val, 0); + } + Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_file = flipper_format_file_alloc(storage); - FlipperFormat* fff_data_raw = flipper_format_string_alloc(); + FlipperFormat* fff_raw = NULL; if(!flipper_format_file_open_existing(fff_file, file_path)) { flipper_format_free(fff_file); @@ -187,10 +247,10 @@ static void js_subghz_transmit_file(struct mjs* mjs) { SubGhzEnvironment* environment = subghz_environment_alloc(); if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) { - FURI_LOG_I(tag, "Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n"); + FURI_LOG_W(TAG, "Load_keystore keeloq_mfcodes - failed to load"); } if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) { - FURI_LOG_I(tag, "Load_keystore keeloq_mfcodes_user \033[0;33mAbsent\033[0m\r\n"); + FURI_LOG_W(TAG, "Load_keystore keeloq_mfcodes_user - failed to load"); } subghz_environment_set_alutech_at_4n_rainbow_table_file_name( environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); @@ -200,119 +260,167 @@ static void js_subghz_transmit_file(struct mjs* mjs) { FuriString* temp_str = furi_string_alloc(); SubGhzTransmitter* transmitter = NULL; - bool is_init_protocol = true; - bool is_sent = false; + uint32_t temp_data32 = 0; uint32_t frequency = 0; - uint32_t repeat = 10; + bool is_sent = false; do { - //Load frequency - if(!flipper_format_read_uint32(fff_file, "Frequency", &frequency, 1)) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to read frequency from file"); - mjs_return(mjs, MJS_UNDEFINED); + if(!flipper_format_read_header(fff_file, temp_str, &temp_data32)) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Missing or incorrect header"); break; } - if(!subghz_devices_is_frequency_valid(js_subghz->radio_device, frequency)) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Invalid frequency"); - mjs_return(mjs, MJS_UNDEFINED); + if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + temp_data32 == SUBGHZ_KEY_FILE_VERSION) { + } else { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Type or version mismatch"); + break; + } + if(!flipper_format_read_uint32(fff_file, "Frequency", &frequency, 1)) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Missing Frequency"); + break; + } + + if(subghz_devices_check_tx(js_subghz->radio_device, frequency) != SubGhzTxAllowed) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Unsupported frequency"); break; } if(!flipper_format_read_string(fff_file, "Preset", temp_str)) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to read preset from file"); - mjs_return(mjs, MJS_UNDEFINED); + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Missing Preset"); + break; + } + + FuriHalSubGhzPreset preset = js_subghz_get_preset_name(furi_string_get_cstr(temp_str)); + if(preset == FuriHalSubGhzPresetIDLE) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Unknown preset"); break; } subghz_devices_reset(js_subghz->radio_device); + subghz_devices_idle(js_subghz->radio_device); - if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Custom presets are not supported (yet)"); - mjs_return(mjs, MJS_UNDEFINED); - break; + if(preset == FuriHalSubGhzPresetCustom) { + uint8_t* custom_preset_data; + if(!flipper_format_get_value_count(fff_file, "Custom_preset_data", &temp_data32) || + !temp_data32 || (temp_data32 % 2)) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Custom_preset_data size error"); + break; + } + custom_preset_data = malloc(temp_data32); + if(!flipper_format_read_hex( + fff_file, "Custom_preset_data", custom_preset_data, temp_data32)) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Custom_preset_data read error"); + break; + } + subghz_devices_load_preset(js_subghz->radio_device, preset, custom_preset_data); + free(custom_preset_data); } else { - subghz_devices_load_preset( - js_subghz->radio_device, - js_subghz_get_preset_name(furi_string_get_cstr(temp_str)), - NULL); + subghz_devices_load_preset(js_subghz->radio_device, preset, NULL); } js_subghz->frequency = subghz_devices_set_frequency(js_subghz->radio_device, frequency); if(!flipper_format_read_string(fff_file, "Protocol", temp_str)) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to read protocol from file"); - mjs_return(mjs, MJS_UNDEFINED); + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Missing protocol"); break; } - SubGhzProtocolStatus status; - bool is_raw = false; - - if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { + bool is_raw = furi_string_equal(temp_str, "RAW"); + if(is_raw) { + fff_raw = flipper_format_string_alloc(); subghz_protocol_raw_gen_fff_data( - fff_data_raw, file_path, subghz_devices_get_name(js_subghz->radio_device)); - is_raw = true; + fff_raw, file_path, subghz_devices_get_name(js_subghz->radio_device)); + // One repeat by default + if(!repeat) { + repeat = 1; + } + } else { + // Simulate holding button by default + if(!repeat) { + repeat = 10; + } + // Pass repeat value to protocol layer + flipper_format_insert_or_update_uint32(fff_file, "Repeat", &repeat, 1); + // Repeat variable applies to high-level code here, should only loop once + repeat = 1; } transmitter = subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str)); - if(transmitter == NULL) { - is_init_protocol = false; + if(!transmitter) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to init transmitter"); + break; } - if(is_init_protocol) { - status = subghz_transmitter_deserialize(transmitter, is_raw ? fff_data_raw : fff_file); - if(status != SubGhzProtocolStatusOk) { - FURI_LOG_I(tag, "failed to deserialize transmitter"); - is_init_protocol = false; - } - } else { - FURI_LOG_I(tag, "failed to allocate transmitter"); - subghz_devices_idle(js_subghz->radio_device); - js_subghz->state = JsSubghzRadioStateIDLE; + SubGhzProtocolStatus status = + subghz_transmitter_deserialize(transmitter, is_raw ? fff_raw : fff_file); + if(status != SubGhzProtocolStatusOk) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to deserialize protocol"); + break; } - } while(false); + // Must close file here, otherwise RAW protocol cannot open + flipper_format_file_close(fff_file); - if(is_init_protocol) { if(!js_subghz->is_external) { furi_hal_power_suppress_charge_enter(); } + subghz_devices_set_tx(js_subghz->radio_device); + FURI_LOG_I(TAG, "Transmitting file %s", file_path); - FURI_LOG_I(tag, "transmitting file %s", file_path); - - do { - furi_delay_ms(200); - if(subghz_devices_start_async_tx( + while(repeat) { + if(!subghz_devices_start_async_tx( js_subghz->radio_device, subghz_transmitter_yield, transmitter)) { - while(!subghz_devices_is_async_complete_tx(js_subghz->radio_device)) { - furi_delay_ms(333); - } - subghz_devices_stop_async_tx(js_subghz->radio_device); - is_sent = true; - } else { - FURI_LOG_E(tag, "failed to start async tx"); + is_sent = false; + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Failed to start async tx"); + break; } + while(!subghz_devices_is_async_complete_tx(js_subghz->radio_device)) { + furi_delay_ms(100); + } + subghz_devices_stop_async_tx(js_subghz->radio_device); + subghz_transmitter_stop(transmitter); + is_sent = true; + repeat--; - } while(repeat && !strcmp(furi_string_get_cstr(temp_str), "RAW")); - - subghz_devices_idle(js_subghz->radio_device); - js_subghz->state = JsSubghzRadioStateIDLE; + // Only RAW is repeated with this loop, check comments above + if(!is_raw) { + break; + } + if(repeat) { + subghz_transmitter_deserialize(transmitter, fff_raw); + furi_delay_ms(200); + } + } if(!js_subghz->is_external) { furi_hal_power_suppress_charge_exit(); } - } + } while(false); + subghz_devices_idle(js_subghz->radio_device); + js_subghz->state = JsSubghzRadioStateIDLE; + + if(transmitter) { + subghz_transmitter_free(transmitter); + } furi_string_free(temp_str); + subghz_environment_free(environment); + + if(fff_raw) { + flipper_format_free(fff_raw); + } flipper_format_free(fff_file); - flipper_format_free(fff_data_raw); furi_record_close(RECORD_STORAGE); - subghz_environment_reset_keeloq(environment); - subghz_environment_free(environment); - subghz_transmitter_free(transmitter); - - mjs_return(mjs, mjs_mk_boolean(mjs, is_sent)); + if(is_sent) { + // Return true for backwards compatibility + // Now it will just error if something goes wrong, not return false + mjs_return(mjs, mjs_mk_boolean(mjs, true)); + } else { + // Broke out of do...while with an mJS error + mjs_return(mjs, MJS_UNDEFINED); + } } static void js_subghz_setup(struct mjs* mjs) { @@ -320,6 +428,12 @@ static void js_subghz_setup(struct mjs* mjs) { JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); furi_assert(js_subghz); + if(js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is already setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + js_subghz->radio_device = radio_device_loader_set(js_subghz->radio_device, SubGhzRadioDeviceTypeExternalCC1101); @@ -338,6 +452,28 @@ static void js_subghz_setup(struct mjs* mjs) { mjs_return(mjs, MJS_UNDEFINED); } +static void js_subghz_end(struct mjs* mjs) { + mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0); + JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst); + furi_assert(js_subghz); + + if(!js_subghz->radio_device) { + mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Radio is not setup"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + subghz_devices_sleep(js_subghz->radio_device); + radio_device_loader_end(js_subghz->radio_device); + js_subghz->radio_device = NULL; + + js_subghz->is_external = false; + js_subghz->state = -1; + js_subghz->frequency = 0; + + mjs_return(mjs, MJS_UNDEFINED); +} + static void* js_subghz_create(struct mjs* mjs, mjs_val_t* object) { JsSubghzInst* js_subghz = malloc(sizeof(JsSubghzInst)); mjs_val_t subghz_obj = mjs_mk_object(mjs); @@ -346,8 +482,9 @@ static void* js_subghz_create(struct mjs* mjs, mjs_val_t* object) { mjs_set(mjs, subghz_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, js_subghz)); mjs_set(mjs, subghz_obj, "setup", ~0, MJS_MK_FN(js_subghz_setup)); + mjs_set(mjs, subghz_obj, "end", ~0, MJS_MK_FN(js_subghz_end)); mjs_set(mjs, subghz_obj, "setRx", ~0, MJS_MK_FN(js_subghz_set_rx)); - mjs_set(mjs, subghz_obj, "setIdle", ~0, MJS_MK_FN(js_subgjz_set_idle)); + mjs_set(mjs, subghz_obj, "setIdle", ~0, MJS_MK_FN(js_subghz_set_idle)); mjs_set(mjs, subghz_obj, "getRssi", ~0, MJS_MK_FN(js_subghz_get_rssi)); mjs_set(mjs, subghz_obj, "getState", ~0, MJS_MK_FN(js_subghz_get_state)); mjs_set(mjs, subghz_obj, "getFrequency", ~0, MJS_MK_FN(js_subghz_get_frequency)); @@ -363,6 +500,11 @@ static void* js_subghz_create(struct mjs* mjs, mjs_val_t* object) { static void js_subghz_destroy(void* inst) { JsSubghzInst* js_subghz = inst; + if(js_subghz->radio_device) { + subghz_devices_sleep(js_subghz->radio_device); + radio_device_loader_end(js_subghz->radio_device); + } + subghz_devices_deinit(); free(js_subghz); From ed767b8286322a3a59ec9a79dd26ecca167fa923 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:01:12 +0300 Subject: [PATCH 03/12] oops --- applications/system/js_app/modules/js_subghz/js_subghz.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/applications/system/js_app/modules/js_subghz/js_subghz.c b/applications/system/js_app/modules/js_subghz/js_subghz.c index 30f1ae81e..dc93867de 100644 --- a/applications/system/js_app/modules/js_subghz/js_subghz.c +++ b/applications/system/js_app/modules/js_subghz/js_subghz.c @@ -282,11 +282,6 @@ static void js_subghz_transmit_file(struct mjs* mjs) { break; } - if(subghz_devices_check_tx(js_subghz->radio_device, frequency) != SubGhzTxAllowed) { - mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Unsupported frequency"); - break; - } - if(!flipper_format_read_string(fff_file, "Preset", temp_str)) { mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Missing Preset"); break; From 96b1ca97dc80e9269bcff52f7278710a9f3ed885 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:10:00 +0300 Subject: [PATCH 04/12] subghz add novoferm support --- .../main/subghz/helpers/subghz_custom_event.h | 1 + .../resources/subghz/assets/keeloq_mfcodes | 113 +++++++++--------- .../subghz/scenes/subghz_scene_set_type.c | 11 ++ lib/subghz/protocols/keeloq.c | 3 + 4 files changed, 72 insertions(+), 56 deletions(-) diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index 2bf308e28..be943bbde 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -93,6 +93,7 @@ typedef enum { SetTypeElmesElectronic, SetTypeNormstahl_433_92, SetTypeJCM_433_92, + SetTypeNovoferm_433_92, SetTypeFAACRCXT_433_92, SetTypeFAACRCXT_868, SetTypeGeniusBravo433, diff --git a/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes b/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes index 27ab5aaaf..0db72444e 100644 --- a/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes +++ b/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes @@ -1,59 +1,60 @@ Filetype: Flipper SubGhz Keystore File Version: 0 Encryption: 1 -IV: AD 0B A4 A1 51 C0 C0 41 36 78 26 82 17 24 9D 62 -0D18FF475E57A67CC5C0B430664E8EF6E07CB6AF72454995F17DE84E2E876D87 -C9BC55E1E3A9B312E341D7E2663C66C2479D5C51AE2EB83BAE47D8C6C79DB8A0 -776E01A7B4FCB929FA59CFE1F16D2D600F6FD9FD8BE1E9E41667144E61E023E4 -C354F854F14AAC08C6A51606582CD73EECEED54779927DC1E04A0D72C4E6A58E -09BA4DC551CDB0141F4A053133DBF9B7B99CBAA402C7B6B2AC8ADB516CA2FCB29FF9744DD95FB009BED6A09AE3303317 -675777F65042358100A9A2BE142C42E10CC5CF98CA6BFF82284FFD9BF7E7FB11 -4739972DCC08EFF0E8547694A67E116F3EC8638F286E333E7D89F2D61218F65D -FE8D5A0A9ED36545004CEE70D3C1FE477F34212364CF7C9EBA0FDD4F6B8F1D3E -453D5C6FE0EA7FD779B54696E66DE6BD6AEF3B1EE347142A3DB7505609077219 -A52339EE40D046E7DF6C130CEC7F9F686753A73A5F72EF344E01B00C3A3CF5F2 -94029CE386CC0403984F7C9D80B40FF12BE6E50412891FD45B347742340D1E6E679102DEC6F7D36C36863701A2BBDA7B -793633A3D97D704779E2E841A5F616ED0BB0BD50740C0B196D72C6C6453124183CA93ADCAC1A5042EBD579AC238B9DBC -B1C6EBB7320CAE97E28A244228B288BEEA44C9FD262E2C448219DAC6E194CB14 -A6C374B3FB7E8BB6F3052ED9DB67E5BCFA6CCC42F5A0D7F20BEDB7C0B58592A5 -DF4FCBDCA3414B7551797A856048625186B2EC7B836EB35B4B080CEE4A72C39F -4127F58BDEB18D79EA8317B1858F7575CF4B648E3C53338975B4A093FA9730C0 -294659EBD39D7CC01DC4E0E3B0B90A3555704E736D3BE4485BAAACBC58A84652CF3A7DA3C271E3198C72561332F2A141 -9E2CC77756BE7AB3D500C0B4A91271C0A4DED5BCB78484217EA922B7878AA8F5 -BF13D9949C783CF6B2F0E489A6912E56DDD9183D651D7F36FD0342981596A85C -8441C62006E1334FC31F53DAFF5281260C463AF3E92B1E797CB67882C49566846825606804C14C49FFD440F4E05CE692 -BE7E62E9CFA1C703CCB971F2B0C6C0F339C78A951CA8DB287B40C3BA76EA7179E8B62C29EAC8293FD218CF981BB84BEF -DA53C52101FAC8FD8F9545768CF1DB59F3B31C9249A2FC64B66DB259C721ABE1 -C9842AD0A8A8E94FCE94F46BDE89DAA8D11C41F9C83A7F6394D595028829AB92 -904A94542BCD85F72D470640A220FD28EBC337C0673C189C96BFB8CE373B4F84 -EEEE187B03FE77B955F22214707017DB8A60B2E3979D5C2F6BED61D0623D4D50 -CEF91BE6EBD8F331E2422B6B948053E8DA143F3DD907C922E0328D49B0ADA8A6 -A6F0F8A4F03B45062CEA86B291E80EE15906C0B226ABDB77E222EB95B026952D -62280870E48A2E8B8A18AD5DFF0089E927BEACE1F81A8BB1A8A2BE8EB0E92BFD -C9A3DE8165D47D1D41715F00192313755226C1B0A3D04BCD7A121B1CB4999FBD -3CAEEB62FCF601F34D3320E3EACE9EFC5D627BF69FEE965F8B84A258A765B6FE -8D83CC36514CE5CC46B181AE28089BE5BC99CE3096C569751B4E07A7D956AFA3 -0F81DDB18F60E238C7FF751E70431AA5328EFDBBDFF03D5F360A524AA968CEE9 -1F1E498A279E9BA15CB6BB836E90FEE522F2BE16572A4D057DF9C2B104487458 -68C60FF95056BE4D814CE9B8A4175625DB3E365712C2D3E42CEEBA2E0977CDB9 -D95FB21943FCAD5A21F157E629314986D92F568FD3067B65911135E6335FB7E8 -17908EF142C4B6740CBE7DCA43DA3C23C7912739299786473A994E5752E7E9459B23653EE0D7775FCECB7B7608CB0495 -6D17B6BA17DBFFAA4E90953CE6A73AB967076B8FBC14A9361D93A01C0850CC38 -8723740BCC0A5CCEE52B6EF73DD441672FB6728965CC588044C78D495AB0675F -CA548FA44A444C8F45490A11DBC8FB24E6DB38F910EC60520A3890C8B45664FE -591356440344AAFEC21FAA0C85B6A8F354D45074932E37E0972F851E08937469 -DE3A54CAAC8014625EE502F547A93754AFAD0A7EB6028599D03CCB0473BC8D5C -B2C2F6F971034E1591AD374793D6D17A595D6544DF5A9585780C6B2E3505BCFF -54447BE6C626D1CA37FD799B76B35ED266D12757B5DA1AB9277F671BBF7F07B461D0CE26593F1372354979E836972F85 -45FBD88AA7C26B967BC3638F6083A6B83AA82D5B974B37DF1C3F52839DDA020C -33B9890FBE46FDB7AEE404B71C893DC20059F96224CF48F284A66D3A8D91918E -CCEA5BC148BC84DB4825320A2B8D39A30BAB4641FFEE33BD4B8700339F15892D -4BC4E0D1263E9B02DA401C884923778D1A6FACACFFE7F660381ECD64CCA5CCD2 -0284EA911FB1B37F623F92B1662E10D79AEBD0009C107A9C554D417F7553B28E -FE48F26C44FA4C3EB3B2F3497FE99AC30A0A7BF9FF261740E177D7A2A5BD7880 -1EA96FEBB62543A8731D19BBDD1C7FE323CADBAB7242E5A8F4B1D706964B4C32 -4AB7EEF02FD59EA5D16837A50282A6254B93A34F31FE9335DA9FABEF76EA714591029C64967506B99860358E5CBF4EDA -A0F25C5387FE9B871E246F33FE64396A5DC0A9BC9AD9DF9E219F3482ADD6497E -0130F99FA395F4364491E6718B53E9D6983B68E29A70035B158CA7629C31C33E -3CDAEDA88534C2E31D1235C99DEC466221C89F63E1F8F59C9CE224573E39E2D4 -F5ED2863D8B51DA620484CDE23D590F4A208DA6D155E645FCD6BCF5FEB39EE551EAE9C0366F7FFD4CBF1DCA063D154E1 +IV: 41 72 65 20 79 6F 75 20 61 20 46 75 72 72 79 3F +8B441920A9F30EA40001F37E0F3C0D72161467678511928D219A7DBC42F8D9B7 +1ADE5B8541491C46674EECC05A1C4297CB28259954FD7C6DA0EAADE8D57773FC +0497A50135FA4468B49694974DAADEF2A9CC2B7BAFC8465E0AA58E940C085850 +4BC77520AE09B4F6A5A5365B6B9C16CA53566E096159A98EF0AB6E7FE5C2DD1C +B674AC1674312E74471E44917F6FC049DAB48BBB65B84F14A4CD64223A49E93DC0C507B8E17BFFDCBB67B55F1B4091C6 +FBBE4E4F703A9C1F17268F73EC00A3F76517A4470783363102D2B7647F0F2E7F +21BE8A51F32CE62DA6B5E207E627D224639877860C71933C4F54AC7BD742B265 +74E3EA89CC7AA99855C1BC87734506413B882CF36D68C3329022415EB29D1360 +567937E84052F230610B3A2FC26CA1BE32B9617F7554EF5E6E7CB35A76718ADA +4C34F7FE5D6EAE40B0EB6BAB7DE4F0D059C32E4F312F9C62F2C50C54C5486276 +74C8656F8EA033C60F3183FA0923C9AF1EB6689FAACC39E6548ECE16E3312D39DCF45AC6EC70A70421FBFFA43D91E19E +275903678A81B6E62CD2BB4C50E93CB3E4B092E2894EBAA04AC4E0244E4D5BA9FCDFC6BCF845EA41DF0691BF2AEDF300 +BFE52324D666ADEB3D33D94331376B33A3D31566331DE0F372548FE7255F8085 +8E1B2E82B4C78360B3174741FB8031EE0DFEB479859BE8708F8AF40C5228BFDF +6014A4A9D9703DAC11DA6B93FB7A0E0E0856E9379148F3CC125D77BA4C3D4931 +B8C22EA72B35E60A7A3DD02956D2375EE7C07E243F17F413CA4AC3A1445AA250 +B545037B8798370A8638B7ADCBE9EEF748F73C89EB5E04B460057BAFA52B1D7DF29B009FBB3FA07CE87247D185BE4926 +09AEA3223E4FFB06333425BA977403E7C2F9B5F121FDA8313E73FE98D0041425 +E7A97F65883E4D3CDA02483738219E219EED0681C2BB140EF3E5D02230433D42 +4AE67B9EA288183047A9498F58978E7C41BB8905533F42FF5B94E41AFEFF0EB4907A8C472B9E32F6D659CFA6C391179B +1F9752FBA7A7A00D518D91BA8A8C1ADEF2EDF6282A5AFB2E4332B4351CF67F18317D2BCFF2DA6B5216EA138A4CCBDB81 +EDC508FE0D0E894B529C5E4AB82A7188072592BE9D4D9A3D2485822A9F4C5A67 +780582645A71D3A9841B0E8F5E84A2285F783872102AA1A98A956B98AEA19421 +37E2858B90868BCAA6B3198C3B205DC1413A9D378AF1671BEA3B8F47FCE1C5CE +229719C5AFE1E567B8BD5F07EFF89C30B11CB79C9C841FFE7B53404CA5422EDB +CDA16E59B8C24DBE95ABF978CAD4D04A4F124DED1965124F92AACA4C5AEB8721 +5C61D5C655DD9EB78C4F8E965101F98D7899155D2379EF6553FA9DEA0302A232 +7D3DCFDE942398244624C7ABFE08363404BA688EDA39D45A05BB6FB982BB9042 +ECCB10BCB2A8CF2093C61634E9AFEE9B69EB4A7C8B7139061730B5FA869F65BF +7AE6C19ED3C97F45D1167FC9EF52CCE321EA002D31D8AEA94106A2F711626551 +793A984F6EBD35253C319FAB671348A4C6843AEA7CCCD5A52ACA9BBE96484B5E +BB3ADBB5FD60F0FB01E5A8B1610D30A24975DC67ED1B70472E509218E213393E +BB971C6304723B9928F50FA2E5C30A48ED5527556EE1BA5A7EA75AB7A4ED4137 +489579673025F7A351072EB8D5C7FC1DBF651AA6233FB01D99DAC4BDC0A60F2F +ACA000B78B091A9B2621A9FA1A50FA6A3B63DDDF7D966224837028F93D570C08 +C1EB4EA179EC0437D5B0E72C47AAD06803F7619C53D3D2FEF38DD3C068118766B73202B75C534C6249312245218C9285 +639C6F53600C0F01410361164FEF715DB8E08C68D68B8AE76CF2D09A0C6C4CA1 +F5F2D77DD3AF60489312055EBA3B511F7D9E312F02465639FFF3E71A862BB9EB +3EC1F7B2C43646249C4D14B4B1B85B3416B8D3B0B8DA9E87BD6199DC27BD45C2 +AA24DB7345317FE980C917909F364EAA13591A664E0893271E9DBCC250782EA5 +32C18DBA479AD57BFF9FE7B7BD1022D4969D8E2EC99BC0799148809796E227D5 +494B44697DACDFDBBFEB0FDBEF6E9B5D7291B6CB43B4C93088F3ED8632AF23B5 +B79CC1A90C7AC36DA2F318BF69E6BB1FAC32C178453663069C0CF2C4AE77B211 +A059D006EF98446BDF9E1F5E09641A641CA88348E79499D79BCFDE6646C716A0BE2253421858D327E796EB5237B6E2C4 +9E90AE6138A3676E3E5058FF277331032CD6BBF114768104A33D684B0825C5A5 +7477B55332666FC6B1279F5FDF84DCA01176498984809B74E17AB726F888000F +6A0300B90BC11127A031E62537468A1CA7A0775BE85ED12069074E26181FBA50 +4DAF986F9A850EB18F0FE3B88B9796D80EEC3984C92F4F8B32D513A176CCAA9A +EB84517DCAA7D10A6E7C4D0A7995AE278AAF3FDE52DAE30C7FD3FB853C799369 +0941FB8965604ABC852B94F29396783783632E4C80AEE665E42C233B6E7AA7D0 +71FEF69734589BE3C0893A1584FC1C0A75A5D4BF88CFF323C8C68E0EEC06993C +790A26B77912EE07BABCDF478D8E492422B73465DC209E5DBC8E31F43AA2DA7448EAB6312AC1DC4FE3F20D7A2EC93968 +CE0AA966F33B7AC9E9982D2241524F2FC7613DAAC6C5C768AAAE29A630B414CE +93FA632D945E18DE6358D4F443CB6F023C640407B7FAD6E8AF6EF15139B044E3 +059ABA7A866A865159D4E0B3E30FA1900BAB2BAB82A1D1F9D74CAEC11FA95393 +9C5A4CF1D49E0F741577BAB868575739AEBBDC15D7178C87A46EA3B3E7E856EFD815AD5F998778E8FBAA2832F387B967 diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index b88e449b1..7a99607ac 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -40,6 +40,7 @@ static const char* submenu_names[SetTypeMAX] = { [SetTypeElmesElectronic] = "KL: Elmes (PL) 433MHz", [SetTypeNormstahl_433_92] = "KL: Normstahl 433MHz", [SetTypeJCM_433_92] = "KL: JCM Tech 433MHz", + [SetTypeNovoferm_433_92] = "KL: Novoferm 433MHz", [SetTypeFAACRCXT_433_92] = "KL: FAAC RC,XT 433MHz", [SetTypeFAACRCXT_868] = "KL: FAAC RC,XT 868MHz", [SetTypeGeniusBravo433] = "KL: Genius Bravo 433MHz", @@ -615,6 +616,16 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .keeloq.cnt = 0x03, .keeloq.manuf = "JCM_Tech"}; break; + case SetTypeNovoferm_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF) | 0x018F0000, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Novoferm"}; + break; case SetTypeFAACRCXT_433_92: gen_info = (GenInfo){ .type = GenKeeloq, diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 0da58a78c..fed56cbf6 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -431,6 +431,9 @@ static bool if((strcmp(instance->manufacture_name, "FAAC_RC,XT") == 0)) { klq_last_custom_btn = 0xB; } + if((strcmp(instance->manufacture_name, "Novoferm") == 0)) { + klq_last_custom_btn = 0x9; + } btn = subghz_protocol_keeloq_get_btn_code(klq_last_custom_btn); From 92c997b9a7c35995db5827f76bd7e1d9d884cfa2 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:20:42 +0300 Subject: [PATCH 05/12] fix decoderaw scene --- applications/main/subghz/scenes/subghz_scene_decode_raw.c | 2 -- applications/main/subghz/scenes/subghz_scene_save_success.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_decode_raw.c b/applications/main/subghz/scenes/subghz_scene_decode_raw.c index 331c7c704..85a524117 100644 --- a/applications/main/subghz/scenes/subghz_scene_decode_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_decode_raw.c @@ -207,8 +207,6 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) { subghz_txrx_set_rx_callback(subghz->txrx, NULL, subghz); - subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); - if(subghz_file_encoder_worker_is_running(subghz->decode_raw_file_worker_encoder)) { subghz_file_encoder_worker_stop(subghz->decode_raw_file_worker_encoder); } diff --git a/applications/main/subghz/scenes/subghz_scene_save_success.c b/applications/main/subghz/scenes/subghz_scene_save_success.c index 70b6a2fc3..9a71c74a7 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_success.c +++ b/applications/main/subghz/scenes/subghz_scene_save_success.c @@ -50,6 +50,8 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event) subghz_file_encoder_worker_free(subghz->decode_raw_file_worker_encoder); subghz->state_notifications = SubGhzNotificationStateIDLE; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); + scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); if(!scene_manager_search_and_switch_to_previous_scene( From f21ba616cd89a15d302faa9db014ef7c50ec331f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:41:45 +0300 Subject: [PATCH 06/12] fm238 mod for sommer add manually for rare cases --- .../main/subghz/helpers/subghz_custom_event.h | 2 ++ .../subghz/scenes/subghz_scene_set_type.c | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index be943bbde..ec68bcf80 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -83,6 +83,8 @@ typedef enum { SetTypeCenturion433, SetTypeSommer_FM_434, SetTypeSommer_FM_868, + SetTypeSommer_FM238_434, + SetTypeSommer_FM238_868, SetTypeStilmatic, SetTypeIronLogic, SetTypeDeaMio433, diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 7a99607ac..4ff108beb 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -30,6 +30,8 @@ static const char* submenu_names[SetTypeMAX] = { [SetTypeCenturion433] = "KL: Centurion 433MHz", [SetTypeSommer_FM_434] = "KL: Sommer 434MHz", [SetTypeSommer_FM_868] = "KL: Sommer 868MHz", + [SetTypeSommer_FM238_434] = "KL: Sommer fm2 434Mhz", + [SetTypeSommer_FM238_868] = "KL: Sommer fm2 868Mhz", [SetTypeStilmatic] = "KL: Stilmatic 433MHz", [SetTypeIronLogic] = "KL: IronLogic 433MHz", [SetTypeDeaMio433] = "KL: DEA Mio 433MHz", @@ -446,7 +448,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .type = GenKeeloq, .mod = "FM476", .freq = 434420000, - .keeloq.serial = (key & 0x0000FFFF) | 0x07150000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, .keeloq.btn = 0x02, .keeloq.cnt = 0x03, .keeloq.manuf = "Sommer(fsk476)"}; @@ -456,7 +458,27 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .type = GenKeeloq, .mod = "FM476", .freq = 868800000, - .keeloq.serial = (key & 0x0000FFFF) | 0x07150000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_434: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 434420000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00000000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 868800000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00000000, .keeloq.btn = 0x02, .keeloq.cnt = 0x03, .keeloq.manuf = "Sommer(fsk476)"}; From 94cbaed6553e38c2df7ae5a67dde5f0ddcd81dc7 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:42:59 +0300 Subject: [PATCH 07/12] remove broken preset mod --- applications/main/subghz/subghz.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index c4169530d..7a5fad74c 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -68,10 +68,6 @@ static void subghz_load_custom_presets(SubGhzSetting* setting) { // Pagers {"Pagers", "02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00"}, - - // # HND - FM preset - {"HND_1", - "02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"}, }; FlipperFormat* fff_temp = flipper_format_string_alloc(); From 0390bd3ff9480ae719f9f504302ba7baef4384d3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:08:23 +0300 Subject: [PATCH 08/12] subghz add manually fixes and improvements --- .../main/subghz/scenes/subghz_scene_set_type.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 4ff108beb..5bf2d1976 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -46,7 +46,7 @@ static const char* submenu_names[SetTypeMAX] = { [SetTypeFAACRCXT_433_92] = "KL: FAAC RC,XT 433MHz", [SetTypeFAACRCXT_868] = "KL: FAAC RC,XT 868MHz", [SetTypeGeniusBravo433] = "KL: Genius Bravo 433MHz", - [SetTypeNiceMHouse_433_92] = "KL: Nice Mhouse 433MHz", + [SetTypeNiceMHouse_433_92] = "KL: Mhouse 433MHz", [SetTypeNiceSmilo_433_92] = "KL: Nice Smilo 433MHz", [SetTypeNiceFlorS_433_92] = "Nice FloR-S 433MHz", [SetTypeNiceOne_433_92] = "Nice One 433MHz", @@ -399,7 +399,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .mod = "AM650", .freq = 433920000, .keeloq.serial = (key & 0x000FFFFF) | 0x00600000, - .keeloq.btn = 0x04, + .keeloq.btn = 0x08, .keeloq.cnt = 0x03, .keeloq.manuf = "Aprimatic"}; break; @@ -468,7 +468,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .type = GenKeeloq, .mod = "FM238", .freq = 434420000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00000000, + .keeloq.serial = key & 0x0000FFFF, .keeloq.btn = 0x02, .keeloq.cnt = 0x03, .keeloq.manuf = "Sommer(fsk476)"}; @@ -478,7 +478,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .type = GenKeeloq, .mod = "FM238", .freq = 868800000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00000000, + .keeloq.serial = key & 0x0000FFFF, .keeloq.btn = 0x02, .keeloq.cnt = 0x03, .keeloq.manuf = "Sommer(fsk476)"}; @@ -499,7 +499,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .mod = "AM650", .freq = 433920000, .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, + .keeloq.btn = 0x04, .keeloq.cnt = 0x03, .keeloq.manuf = "Came_Space"}; break; @@ -604,7 +604,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .mod = "AM650", .freq = 433920000, .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, + .keeloq.btn = 0x09, .keeloq.cnt = 0x03, .keeloq.manuf = "NICE_MHOUSE"}; break; @@ -673,8 +673,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .type = GenKeeloq, .mod = "AM650", .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x04, .keeloq.cnt = 0x03, .keeloq.manuf = "Normstahl"}; break; From 4b7875376b9488bcfd7f4d51f28678b02c922a6e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:08:48 +0300 Subject: [PATCH 09/12] keeloq custom buttons improvements --- lib/subghz/protocols/keeloq.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index fed56cbf6..7a497cc09 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -425,14 +425,15 @@ static bool uint8_t klq_last_custom_btn = 0xA; if((strcmp(instance->manufacture_name, "BFT") == 0) || (strcmp(instance->manufacture_name, "Aprimatic") == 0) || - (strcmp(instance->manufacture_name, "Dea_Mio") == 0)) { + (strcmp(instance->manufacture_name, "Dea_Mio") == 0) || + (strcmp(instance->manufacture_name, "NICE_MHOUSE") == 0)) { klq_last_custom_btn = 0xF; - } - if((strcmp(instance->manufacture_name, "FAAC_RC,XT") == 0)) { + } else if((strcmp(instance->manufacture_name, "FAAC_RC,XT") == 0)) { klq_last_custom_btn = 0xB; - } - if((strcmp(instance->manufacture_name, "Novoferm") == 0)) { + } else if((strcmp(instance->manufacture_name, "Novoferm") == 0)) { klq_last_custom_btn = 0x9; + } else if((strcmp(instance->manufacture_name, "NICE_Smilo") == 0)) { + klq_last_custom_btn = 0xB; } btn = subghz_protocol_keeloq_get_btn_code(klq_last_custom_btn); From 54192afe56964f41403e1db6a98444db5eadb94c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:40:09 +0300 Subject: [PATCH 10/12] hormann_ecostar add manually support and custom button --- .../main/subghz/helpers/subghz_custom_event.h | 1 + .../main/subghz/scenes/subghz_scene_set_type.c | 11 +++++++++++ lib/subghz/protocols/keeloq.c | 2 ++ 3 files changed, 14 insertions(+) diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index ec68bcf80..c84bed3fc 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -96,6 +96,7 @@ typedef enum { SetTypeNormstahl_433_92, SetTypeJCM_433_92, SetTypeNovoferm_433_92, + SetTypeHormannEcoStar_433_92, SetTypeFAACRCXT_433_92, SetTypeFAACRCXT_868, SetTypeGeniusBravo433, diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 5bf2d1976..324cc48f0 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -43,6 +43,7 @@ static const char* submenu_names[SetTypeMAX] = { [SetTypeNormstahl_433_92] = "KL: Normstahl 433MHz", [SetTypeJCM_433_92] = "KL: JCM Tech 433MHz", [SetTypeNovoferm_433_92] = "KL: Novoferm 433MHz", + [SetTypeHormannEcoStar_433_92] = "KL: Hor. EcoStar 433MHz", [SetTypeFAACRCXT_433_92] = "KL: FAAC RC,XT 433MHz", [SetTypeFAACRCXT_868] = "KL: FAAC RC,XT 868MHz", [SetTypeGeniusBravo433] = "KL: Genius Bravo 433MHz", @@ -648,6 +649,16 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .keeloq.cnt = 0x03, .keeloq.manuf = "Novoferm"}; break; + case SetTypeHormannEcoStar_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x02200000, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "EcoStar"}; + break; case SetTypeFAACRCXT_433_92: gen_info = (GenInfo){ .type = GenKeeloq, diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 7a497cc09..ca9f7a64f 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -434,6 +434,8 @@ static bool klq_last_custom_btn = 0x9; } else if((strcmp(instance->manufacture_name, "NICE_Smilo") == 0)) { klq_last_custom_btn = 0xB; + } else if((strcmp(instance->manufacture_name, "EcoStar") == 0)) { + klq_last_custom_btn = 0x6; } btn = subghz_protocol_keeloq_get_btn_code(klq_last_custom_btn); From b11f18c553c1b6c1ec153e755b6f4557f8a84665 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:40:40 +0300 Subject: [PATCH 11/12] hormann hsm static code btn decode fix??? [ci skip] --- lib/subghz/protocols/hormann.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index fc490e9d1..70954bb39 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -285,7 +285,7 @@ void subghz_protocol_decoder_hormann_feed(void* context, bool level, uint32_t du * @param instance Pointer to a SubGhzBlockGeneric* instance */ static void subghz_protocol_hormann_check_remote_controller(SubGhzBlockGeneric* instance) { - instance->btn = (instance->data >> 4) & 0xF; + instance->btn = (instance->data >> 8) & 0xF; } uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context) { From 8b3b1fbc2c2c4d918b0a0a782fc1e4eee5c770b6 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 8 Jul 2024 17:43:29 +0300 Subject: [PATCH 12/12] upd changelog --- CHANGELOG.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce5e4ffa..f4bbd42a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,36 @@ ## Main changes +- SubGHz: + - **Novoferm** remotes full support + - Fix Decode scene in RAW files + - Add manually -> Add Sommer FM238 option for cases when default option doesn't work (named as Sommer fm2) + - Remove broken preset modulation + - Normstahl, Sommer, MHouse, Aprimatic -> Fixes for button codes and more in Add manually + - Custom button improvements for MHouse, Novoferm, Nice Smilo + - Hormann EcoStar -> Add manually support, and custom button support + - Hormann HSM 44bit static -> Button code decoding fix - NFC: - OFW: Ultralight C authentication with des key - EMV Transactions less nested, hide if unavailable (by @Willy-JL | PR #771) - LF RFID: - Update T5577 password list (by @korden32 | PR #774) - Add DEZ 8 display form for EM4100 (by @korden32 | PR #776 & (#777 by @mishamyte)) -* JS: Refactor widget and keyboard modules, fix crash (by @Willy-JL | PR #770) +- JS: + - Refactor widget and keyboard modules, fix crash (by @Willy-JL | PR #770) + - SubGHz module fixes and improvements (by @Willy-JL) +* OFW: Fix iButton/LFRFID Add Manually results being discarded * OFW: Event Loop Timers * OFW: Updater: resource compression * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes -* NFC: Cache plugin name not full path, saves some RAM (by @Willy-JL) +* OFW: Updater: reset various debug flags on production build flash (was done in same way in UL before) +* OFW: Fix PVS Warnings +* OFW: CCID: Improve request and response data handling +* OFW: Furi: count ISR time. Cli: show ISR time in top. +* OFW: toolchain: v37 +* OFW: NFC: Cache plugin name not full path, saves some RAM (by @Willy-JL) * OFW: copro: bumped to 1.20.0 * OFW: input_srv: Put input state data on the stack of the service * OFW: Coalesce some allocations -* OFW: Fix iButton/LFRFID Add Manually results being discarded * OFW: updater: slightly smaller image * OFW: Updater: Fix double dir cleanup * OFW: cli: storage: minor subcommand lookup refactor