Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSkorpionm <85568270+Skorpionm@users.noreply.github.com>2022-01-21 16:55:09 +0300
committerGitHub <noreply@github.com>2022-01-21 16:55:09 +0300
commitd4d87aa6a8edb051ae0a0c998ca887a095a7220e (patch)
tree888b9a97364881268e4d057d7b8b10341816b86b
parent32c92a80eaddcfa4eddf3333e1a258a821864760 (diff)
[FL-2045] SubGhz: new protocol (GSN , Beninca/Allmatic, Elmes) and validator (#958)
* SubGhz: add new method of obtaining a manufactory code subghz_protocol_keeloq_common_magic_xor_type1_learning * TextInput: checking for a lock on a file with the same name * TextInput: fix checking for a lock on a file with the same name * Assets: rename and recompile * TextInput: added picture and timer to turn off blob * TextInput: Fix graphics * TextInput: fix validator * Validators: Add validator is file * TextInput: fix callback validator_is_file_alloc * SubGhz: add propocol GNS (dimamic), Beninca/Alcatic, Elmes * SubGhz: fix function description * Gui: correct timer routine on deallocation * Format sources Co-authored-by: あく <alleteam@gmail.com>
-rwxr-xr-xapplications/gui/modules/text_input.c112
-rw-r--r--applications/gui/modules/text_input.h12
-rw-r--r--applications/gui/modules/validators.c42
-rw-r--r--applications/gui/modules/validators.h20
-rw-r--r--applications/subghz/scenes/subghz_scene_save_name.c16
-rw-r--r--applications/subghz/subghz_i.c2
-rw-r--r--assets/compiled/assets_icons.c8
-rw-r--r--assets/compiled/assets_icons.h2
-rw-r--r--assets/icons/Interface/Back3_45x8.pngbin0 -> 3630 bytes
-rw-r--r--assets/icons/Interface/WarningDolphin_45x42.pngbin0 -> 1139 bytes
-rw-r--r--assets/resources/subghz/keeloq_mfcodes72
-rw-r--r--assets/resources/subghz/keeloq_mfcodes_user2
-rw-r--r--lib/subghz/protocols/subghz_protocol_keeloq.c31
-rw-r--r--lib/subghz/protocols/subghz_protocol_keeloq_common.c14
-rw-r--r--lib/subghz/protocols/subghz_protocol_keeloq_common.h13
15 files changed, 300 insertions, 46 deletions
diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c
index 2b31f71b..e8351ce3 100755
--- a/applications/gui/modules/text_input.c
+++ b/applications/gui/modules/text_input.c
@@ -4,6 +4,7 @@
struct TextInput {
View* view;
+ osTimerId_t timer;
};
typedef struct {
@@ -23,6 +24,11 @@ typedef struct {
uint8_t selected_row;
uint8_t selected_column;
+
+ TextInputValidatorCallback validator_callback;
+ void* validator_callback_context;
+ string_t validator_text;
+ bool valadator_message_visible;
} TextInputModel;
static const uint8_t keyboard_origin_x = 1;
@@ -236,6 +242,17 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
}
}
}
+ if(model->valadator_message_visible) {
+ canvas_set_font(canvas, FontSecondary);
+ canvas_set_color(canvas, ColorWhite);
+ canvas_draw_box(canvas, 8, 10, 110, 48);
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
+ canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
+ canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
+ elements_multiline_text(canvas, 62, 20, string_get_cstr(model->validator_text));
+ canvas_set_font(canvas, FontKeyboard);
+ }
}
static void text_input_handle_up(TextInput* text_input) {
@@ -295,7 +312,13 @@ static void text_input_handle_ok(TextInput* text_input) {
uint8_t text_length = strlen(model->text_buffer);
if(selected == ENTER_KEY) {
- if(model->callback != 0 && text_length > 0) {
+ if(model->validator_callback && (!model->validator_callback(
+ model->text_buffer,
+ model->validator_text,
+ model->validator_callback_context))) {
+ model->valadator_message_visible = true;
+ osTimerStart(text_input->timer, osKernelGetTickFreq() * 4);
+ } else if(model->callback != 0 && text_length > 0) {
model->callback(model->callback_context);
}
} else if(selected == BACKSPACE_KEY) {
@@ -321,6 +344,16 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) {
bool consumed = false;
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ if(model->valadator_message_visible) {
+ if(event->key == InputKeyBack) {
+ consumed = true;
+ }
+ }
+ model->valadator_message_visible = false;
+ return false;
+ });
switch(event->key) {
case InputKeyUp:
text_input_handle_up(text_input);
@@ -351,7 +384,11 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) {
event->key == InputKeyBack) {
with_view_model(
text_input->view, (TextInputModel * model) {
- text_input_backspace_cb(model);
+ if(model->valadator_message_visible) {
+ model->valadator_message_visible = false;
+ } else {
+ text_input_backspace_cb(model);
+ }
return true;
});
@@ -361,6 +398,17 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) {
return consumed;
}
+void text_input_timer_callback(void* context) {
+ furi_assert(context);
+ TextInput* text_input = context;
+
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ model->valadator_message_visible = false;
+ return true;
+ });
+}
+
TextInput* text_input_alloc() {
TextInput* text_input = furi_alloc(sizeof(TextInput));
text_input->view = view_alloc();
@@ -369,6 +417,14 @@ TextInput* text_input_alloc() {
view_set_draw_callback(text_input->view, text_input_view_draw_callback);
view_set_input_callback(text_input->view, text_input_view_input_callback);
+ text_input->timer = osTimerNew(text_input_timer_callback, osTimerOnce, text_input, NULL);
+
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ string_init(model->validator_text);
+ return false;
+ });
+
text_input_clean(text_input);
return text_input;
@@ -376,7 +432,21 @@ TextInput* text_input_alloc() {
void text_input_free(TextInput* text_input) {
furi_assert(text_input);
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ string_clear(model->validator_text);
+ return false;
+ });
+
+ // Send stop command
+ osTimerStop(text_input->timer);
+ // Wait till timer stop
+ while(osTimerIsRunning(text_input->timer)) osDelay(1);
+ // Release allocated memory
+ osTimerDelete(text_input->timer);
+
view_free(text_input->view);
+
free(text_input);
}
@@ -393,6 +463,10 @@ void text_input_clean(TextInput* text_input) {
model->text_buffer_size = 0;
model->callback = NULL;
model->callback_context = NULL;
+ model->validator_callback = NULL;
+ model->validator_callback_context = NULL;
+ string_reset(model->validator_text);
+ model->valadator_message_visible = false;
return true;
});
}
@@ -425,10 +499,42 @@ void text_input_set_result_callback(
});
}
+void text_input_set_validator(
+ TextInput* text_input,
+ TextInputValidatorCallback callback,
+ void* callback_context) {
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ model->validator_callback = callback;
+ model->validator_callback_context = callback_context;
+ return true;
+ });
+}
+
+TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input) {
+ TextInputValidatorCallback validator_callback = NULL;
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ validator_callback = model->validator_callback;
+ return false;
+ });
+ return validator_callback;
+}
+
+void* text_input_get_validator_callback_context(TextInput* text_input) {
+ void* validator_callback_context = NULL;
+ with_view_model(
+ text_input->view, (TextInputModel * model) {
+ validator_callback_context = model->validator_callback_context;
+ return false;
+ });
+ return validator_callback_context;
+}
+
void text_input_set_header_text(TextInput* text_input, const char* text) {
with_view_model(
text_input->view, (TextInputModel * model) {
model->header = text;
return true;
});
-} \ No newline at end of file
+}
diff --git a/applications/gui/modules/text_input.h b/applications/gui/modules/text_input.h
index d7b32def..7b0dc5c0 100644
--- a/applications/gui/modules/text_input.h
+++ b/applications/gui/modules/text_input.h
@@ -6,6 +6,8 @@
#pragma once
#include <gui/view.h>
+#include "validators.h"
+#include <m-string.h>
#ifdef __cplusplus
extern "C" {
@@ -14,6 +16,7 @@ extern "C" {
/** Text input anonymous structure */
typedef struct TextInput TextInput;
typedef void (*TextInputCallback)(void* context);
+typedef bool (*TextInputValidatorCallback)(const char* text, string_t error, void* context);
/** Allocate and initialize text input
*
@@ -63,6 +66,15 @@ void text_input_set_result_callback(
size_t text_buffer_size,
bool clear_default_text);
+void text_input_set_validator(
+ TextInput* text_input,
+ TextInputValidatorCallback callback,
+ void* callback_context);
+
+TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input);
+
+void* text_input_get_validator_callback_context(TextInput* text_input);
+
/** Set text input header text
*
* @param text_input TextInput instance
diff --git a/applications/gui/modules/validators.c b/applications/gui/modules/validators.c
new file mode 100644
index 00000000..dc752e95
--- /dev/null
+++ b/applications/gui/modules/validators.c
@@ -0,0 +1,42 @@
+#include <furi.h>
+#include "validators.h"
+#include "applications/storage/storage.h"
+
+struct ValidatorIsFile {
+ const char* app_path_folder;
+ const char* app_extension;
+};
+
+bool validator_is_file_callback(const char* text, string_t error, void* context) {
+ furi_assert(context);
+ ValidatorIsFile* instance = context;
+ bool ret = true;
+ string_t path;
+ string_init_printf(path, "%s/%s%s", instance->app_path_folder, text, instance->app_extension);
+ Storage* storage = furi_record_open("storage");
+ if(storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK) {
+ ret = false;
+ string_printf(error, "This name\nexists!\nChoose\nanother one.");
+ } else {
+ ret = true;
+ }
+ string_clear(path);
+ furi_record_close("storage");
+
+ return ret;
+}
+
+ValidatorIsFile*
+ validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension) {
+ ValidatorIsFile* instance = furi_alloc(sizeof(ValidatorIsFile));
+
+ instance->app_path_folder = app_path_folder;
+ instance->app_extension = app_extension;
+
+ return instance;
+}
+
+void validator_is_file_free(ValidatorIsFile* instance) {
+ furi_assert(instance);
+ free(instance);
+}
diff --git a/applications/gui/modules/validators.h b/applications/gui/modules/validators.h
new file mode 100644
index 00000000..f62064b6
--- /dev/null
+++ b/applications/gui/modules/validators.h
@@ -0,0 +1,20 @@
+#pragma once
+
+// #include <gui/view.h>
+#include <m-string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef struct ValidatorIsFile ValidatorIsFile;
+
+ValidatorIsFile*
+ validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension);
+
+void validator_is_file_free(ValidatorIsFile* instance);
+
+bool validator_is_file_callback(const char* text, string_t error, void* context);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c
index f688d20d..c64d0d2c 100644
--- a/applications/subghz/scenes/subghz_scene_save_name.c
+++ b/applications/subghz/scenes/subghz_scene_save_name.c
@@ -1,10 +1,11 @@
#include "../subghz_i.h"
#include <lib/toolbox/random_name.h>
-#include "file_worker.h"
#include "../helpers/subghz_custom_event.h"
#include <lib/subghz/protocols/subghz_protocol_raw.h>
+#include <gui/modules/validators.h>
void subghz_scene_save_name_text_input_callback(void* context) {
+ furi_assert(context);
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneSaveName);
}
@@ -37,6 +38,11 @@ void subghz_scene_save_name_on_enter(void* context) {
subghz->file_name,
22, //Max len name
dev_name_empty);
+
+ ValidatorIsFile* validator_is_file =
+ validator_is_file_alloc_init(SUBGHZ_APP_PATH_FOLDER, SUBGHZ_APP_EXTENSION);
+ text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
+
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTextInput);
}
@@ -50,7 +56,9 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubghzCustomEventSceneSaveName) {
if(strcmp(subghz->file_name, "")) {
if(strcmp(subghz->file_name_tmp, "")) {
- subghz_rename_file(subghz);
+ if(!subghz_rename_file(subghz)) {
+ return false;
+ }
} else {
subghz_save_protocol_to_file(subghz, subghz->file_name);
}
@@ -79,6 +87,10 @@ void subghz_scene_save_name_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
+ void* validator_context = text_input_get_validator_callback_context(subghz->text_input);
+ text_input_set_validator(subghz->text_input, NULL, NULL);
+ validator_is_file_free(validator_context);
+
text_input_clean(subghz->text_input);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet);
diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c
index 2fce6f15..5a1f67fe 100644
--- a/applications/subghz/subghz_i.c
+++ b/applications/subghz/subghz_i.c
@@ -421,7 +421,7 @@ bool subghz_rename_file(SubGhz* subghz) {
FS_Error fs_result =
storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path));
- if(fs_result != FSE_OK && fs_result != FSE_EXIST) {
+ if(fs_result != FSE_OK) {
dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory");
ret = false;
}
diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c
index f5f7a6d3..71316998 100644
--- a/assets/compiled/assets_icons.c
+++ b/assets/compiled/assets_icons.c
@@ -245,6 +245,9 @@ const uint8_t *_I_ArrowUpEmpty_14x15[] = {_I_ArrowUpEmpty_14x15_0};
const uint8_t _I_ArrowUpFilled_14x15_0[] = {0x00,0xC0,0x00,0x20,0x01,0xD0,0x02,0xE8,0x05,0xF4,0x0B,0xFA,0x17,0x61,0x21,0xAF,0x3D,0x68,0x05,0xA8,0x05,0x68,0x05,0xA8,0x05,0xE8,0x05,0x08,0x04,0xF8,0x07,};
const uint8_t *_I_ArrowUpFilled_14x15[] = {_I_ArrowUpFilled_14x15_0};
+const uint8_t _I_Back3_45x8_0[] = {0x00,0x04,0x00,0x10,0x00,0x40,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x7F,0x00,0xFC,0x01,0xF0,0x07,0x86,0x20,0x18,0x82,0x60,0x08,0x04,0x71,0x10,0xC4,0x41,0x10,0x00,0x21,0x00,0x84,0x00,0x10,0x80,0x00,0x00,0x02,0x00,0x08,0x7E,0x00,0xF8,0x01,0xE0,0x07,};
+const uint8_t *_I_Back3_45x8[] = {_I_Back3_45x8_0};
+
const uint8_t _I_DoorLeft_70x55_0[] = {0x01,0x00,0x19,0x01,0x00,0x2c,0x32,0x01,0x03,0x04,0x2c,0x18,0x10,0xf0,0x40,0x47,0x82,0x06,0x81,0x03,0xff,0x80,0x08,0x1a,0x20,0x82,0x15,0x28,0x21,0x87,0x82,0x08,0x6f,0xc0,0xb1,0xe6,0x10,0x10,0x8b,0x46,0x20,0x43,0x55,0x8f,0x82,0x10,0x32,0x73,0x0a,0x09,0x89,0x6c,0x1e,0x09,0x00,0x18,0x60,0xf0,0x0c,0x84,0x93,0x82,0x03,0x18,0x0c,0x02,0x1d,0x00,0x90,0x52,0x70,0x50,0x1e,0x00,0x58,0x63,0x90,0x0a,0x06,0x4a,0x09,0x03,0xb0,0x02,0x06,0x70,0x62,0x49,0xf8,0x0c,0x66,0x3f,0xf0,0x41,0x63,0x04,0x43,0x00,0x99,0x60,0x00,0x85,0xc8,0x06,0x14,0xd0,0x80,0x3f,0xc8,0x0d,0xb8,0x10,0x70,0xf8,0x34,0x13,0x03,0x39,0x04,0x1c,0x42,0x19,0xf8,0xa0,0xc2,0x01,0x07,0xef,0x02,0x8c,0x80,0x10,0x9d,0x00,0x43,0xec,0x00,0xa3,0x10,0x04,0x25,0xce,0x19,0xfc,0x88,0x82,0x12,0x0c,0x35,0x10,0x42,0x4c,0xa1,0x90,0x3f,0xc0,0x21,0x22,0x39,0x82,0xc8,0x88,0xd2,0x11,0xf0,0x01,0x88,0xd5,0x18,0xe2,0x08,0x68,0x10,0x0c,0xa8,0x00,0x83,0x81,0xcc,0xd5,0xc3,0x80,0x84,0x82,0x0e,0xcc,0xc0,0x15,0x79,0x02,0x0b,0x98,0xf8,0x11,0x88,0x82,0x0f,0x31,0x19,0x02,0x08,0x2c,0x9f,0x6a,0x1d,0x20,0x41,0x31,0x4c,0x10,0x8d,0x73,0x04,0x23,0xa4,0xc4,0x6c,0xde,0x20,0x42,0xcc,0x01,0x07,0x07,0xff,0x80,0x06,0x3e,0x08,0x38,0x70,0x20,0xa1,0xe0,0x83,0x8e,0x01,0x0c,0xf0,0x73,0x80,0x43,0x70,0x05,0x08,0x00,0x2c,0x04,0xc4,0x46,0x53,0x09,0x98,0x24,0x80,0x65,0x80,0xb0,0xd9,0x84,0x65,0x32,0x06,0x17,0x0f,0x98,0x23,0x63,0xe1,0x88,0xc4,0x08,0x5f,0xc1,0x30,0x9d,0x84,0x4e,0x66,0x94,0x11,0x98,0x75,0x26,0x00,};
const uint8_t *_I_DoorLeft_70x55[] = {_I_DoorLeft_70x55_0};
@@ -263,6 +266,9 @@ const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0};
const uint8_t _I_PassportLeft_6x47_0[] = {0x01,0x00,0x1c,0x00,0x9e,0x40,0xa3,0x32,0x59,0x2c,0x66,0x03,0x01,0x82,0xc2,0x62,0x32,0x50,0x16,0xc8,0x60,0x30,0x28,0x24,0x32,0x39,0x3c,0x9e,0x4d,0x25,0x80,0x1a,};
const uint8_t *_I_PassportLeft_6x47[] = {_I_PassportLeft_6x47_0};
+const uint8_t _I_WarningDolphin_45x42_0[] = {0x01,0x00,0xc6,0x00,0x00,0x1c,0x22,0x04,0x05,0x7f,0xfc,0x1e,0x20,0x05,0x1e,0x04,0x02,0x30,0x05,0x29,0x84,0x02,0xc1,0x20,0x02,0x8c,0x22,0x01,0x80,0x02,0x94,0x10,0x32,0x30,0x10,0x10,0x87,0xca,0x84,0x03,0x10,0x42,0x81,0x48,0x28,0x38,0x08,0x04,0x3e,0x01,0x84,0x83,0xe0,0x30,0x11,0x08,0x05,0xa2,0x11,0x40,0xa0,0x4b,0xc6,0xc5,0x40,0xd0,0x56,0xe0,0x10,0x60,0x29,0x54,0xf0,0x10,0x18,0xf0,0x14,0x6b,0xf6,0x0c,0x04,0x3e,0x40,0x05,0x12,0x80,0xc1,0xe4,0x01,0xd2,0xf8,0x40,0xe4,0x18,0x09,0xf4,0x03,0xf1,0x01,0x90,0x40,0x28,0x30,0x0f,0xe4,0x00,0x16,0x24,0x11,0xbf,0x01,0x44,0xee,0x53,0xf0,0x29,0xf0,0x3e,0x02,0x91,0x3b,0x8c,0xc3,0x81,0x13,0x90,0x48,0x20,0x3f,0xf9,0xfc,0x42,0x60,0x05,0x10,0x98,0x81,0x56,0x11,0x38,0x02,0x9c,0x1a,0x31,0x1e,0x02,0x8f,0x02,0x03,0x1c,0x90,0xc0,0x7c,0x02,0xf1,0xce,0x02,0x07,0x01,0x1f,0x80,0x63,0xa8,0x08,0x71,0x3c,0x8e,0x39,0x24,0x40,0x51,0xc7,0x81,0x53,0x0f,0x3c,0x02,0x9d,0x1e,0x38,0x29,0x10,0x29,0x17,0xc8,0x0a,0x32,0x3a,0x00,0x14,0x4b,0xa2,0x05,0x58,0x98,0x15,0x22,0x20,0x54,0x84,0x81,0x50,};
+const uint8_t *_I_WarningDolphin_45x42[] = {_I_WarningDolphin_45x42_0};
+
const uint8_t _I_Back_15x10_0[] = {0x00,0x04,0x00,0x06,0x00,0xFF,0x0F,0x06,0x10,0x04,0x20,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x10,0xFE,0x0F,};
const uint8_t *_I_Back_15x10[] = {_I_Back_15x10_0};
@@ -748,12 +754,14 @@ const Icon I_ArrowDownEmpty_14x15 = {.width=14,.height=15,.frame_count=1,.frame_
const Icon I_ArrowDownFilled_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowDownFilled_14x15};
const Icon I_ArrowUpEmpty_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowUpEmpty_14x15};
const Icon I_ArrowUpFilled_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowUpFilled_14x15};
+const Icon I_Back3_45x8 = {.width=45,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Back3_45x8};
const Icon I_DoorLeft_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_70x55};
const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56};
const Icon I_DoorRight_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorRight_70x55};
const Icon I_LockPopup_100x49 = {.width=100,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_LockPopup_100x49};
const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17};
const Icon I_PassportLeft_6x47 = {.width=6,.height=47,.frame_count=1,.frame_rate=0,.frames=_I_PassportLeft_6x47};
+const Icon I_WarningDolphin_45x42 = {.width=45,.height=42,.frame_count=1,.frame_rate=0,.frames=_I_WarningDolphin_45x42};
const Icon I_Back_15x10 = {.width=15,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Back_15x10};
const Icon I_DolphinReadingSuccess_59x63 = {.width=59,.height=63,.frame_count=1,.frame_rate=0,.frames=_I_DolphinReadingSuccess_59x63};
const Icon I_Down_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Down_25x27};
diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h
index 3dac8eb1..c52821af 100644
--- a/assets/compiled/assets_icons.h
+++ b/assets/compiled/assets_icons.h
@@ -82,12 +82,14 @@ extern const Icon I_ArrowDownEmpty_14x15;
extern const Icon I_ArrowDownFilled_14x15;
extern const Icon I_ArrowUpEmpty_14x15;
extern const Icon I_ArrowUpFilled_14x15;
+extern const Icon I_Back3_45x8;
extern const Icon I_DoorLeft_70x55;
extern const Icon I_DoorLocked_10x56;
extern const Icon I_DoorRight_70x55;
extern const Icon I_LockPopup_100x49;
extern const Icon I_PassportBottom_128x17;
extern const Icon I_PassportLeft_6x47;
+extern const Icon I_WarningDolphin_45x42;
extern const Icon I_Back_15x10;
extern const Icon I_DolphinReadingSuccess_59x63;
extern const Icon I_Down_25x27;
diff --git a/assets/icons/Interface/Back3_45x8.png b/assets/icons/Interface/Back3_45x8.png
new file mode 100644
index 00000000..6cb945f6
--- /dev/null
+++ b/assets/icons/Interface/Back3_45x8.png
Binary files differ
diff --git a/assets/icons/Interface/WarningDolphin_45x42.png b/assets/icons/Interface/WarningDolphin_45x42.png
new file mode 100644
index 00000000..d766ffbb
--- /dev/null
+++ b/assets/icons/Interface/WarningDolphin_45x42.png
Binary files differ
diff --git a/assets/resources/subghz/keeloq_mfcodes b/assets/resources/subghz/keeloq_mfcodes
index a18dd590..c969b592 100644
--- a/assets/resources/subghz/keeloq_mfcodes
+++ b/assets/resources/subghz/keeloq_mfcodes
@@ -1,38 +1,40 @@
Filetype: Flipper SubGhz Keystore File
Version: 0
Encryption: 1
-IV: 7A 44 FE 5D C3 B3 65 13 73 A6 F4 2D 1E B6 7D F0
-89153B35033574AAA06D7E792CB92A486B37A2CCDF0B0152BF1A563E321518C8
-F6583A3E4148439E8A8D7ED6A095ACC0C3E22A48F1637E78DF023CAC9272934E
-AA0439E6B76CD43F3FCC27CF69C5F3B6508E8103B164E4ECDDF8B2FB222D46FF
-A9826C663033D25AE21CB8790406997ADCE84360B258F2B989D967009659859C
-3474E7BBFA0173928F414CFD5EE19B27A558D9C171D96FE7B7840A01323A7E7446FAE3E98EA9A8C69B4A6B781BD7906A
-2873939A8E0EAC16D748967E987BB0F1079C106E4235B7D35B4BF37F54B21F8E
-EF6F1DC0201FCB8CEBC5642A5194A1FDCFBE1FA772A79CEAD54D2F0DA3AC4F6C
-3F595EAA0E81E96C5D6DB41799D314E3E81E7F4197E19A3341C55592B1B6C4B0
-7B2D75FE11B27E99CA7610E47D712C8CFB619EC69EBC976A70CFD9574C9F4FF8
-39735CF1D009D132A33B9C546D95FA6D3E69BF3A57EF219392E57C9560E7B037
-D56FDDFB0C4E808143D3ED5F15D6FF47F6EDEBD01192FC7ACF3ACCE9FD5162FC297D0089D65ED2CBE3CE05DDA7B96446
-2750D4F0650061C3AF72C88FD080BE241F2BDD8D8C1B0EFE781120EBEFFE2C72D0EECC42CDDED50CFE4AC51C48AE68C6
-F8CE64921CB73015F2672A9EF0A8359269CAE0E515D6DBB3130CFC9E5E1A98AD
-ACF6ADB9E02D67B44EB6C6F126BF64BDAB37926B8BE39E27F323E8F5A0F8FC38
-FBB1302D697F94ECED681CE047819001EDE6E013850258F61E97091DD37D24F2
-D8CD53AB5A94898EB53D4FF46546ADBAA24691181A396052A58AAC657D6817AB
-43200E08C21747CABC59538888A259238E782545732A1A6EEE00A6929EC9DD97A8BA9812372374046AC66652CC561D60
-C38CBE29F22D0E83E58A52E94AA2485DA8E702FBDB89D27249473CB8A19AEF61
-9F0EB580F7474985E8460E1682451E213778B77A9CAB4734B75C5386851050BF
-2364EBB8237363B21226565675B9F47819C5BBC7E917C761BA3652D0A6ED7D3273EB8F3B7FBA68DE4143FB15BBEC35FB
-CCDE559A2901A8290D6B2E8EDF66612E4C90E2E7C63643C8C5F244E30874B41039E078089E2253DA73B3A6DD821A84CD
-33B239455FBE7AB8CE833C3B9C063EFEAE1FC7AC876AF3294C67D5B08BF7E9EC
-F0FBBCEFE99D25104022CD3621B21B5F84FFBC9A5E21B0AED2B1560B39524A5B
-E15B0614D9ECA17784E994652755559B7A3DA4B53CE6E63108BCFCD8024761DD
-9E244C80E72937274DD6B2787F1A75F278A2DF7CB3B89F7C2BF7CC8DBBF2A3F0
-689DCA188A40DFDD3575A9BD9D7AF2427D0CE707F591029463AEC6B8679969AC
-25D9B04D10AF541925901F55D8D7FA9C87523995F53183FB04F00C6023D5930A
-D11F70508485C019AFC5FDBE5FD7223710033483C803FC7C2C69BAAD6ACB7CA7
-C081A0ACEA8210AB117028EDFF15641EE287CB1CFF8332A9D208B7324523129E
-4C5B7C959C00A30F39A431B20EA1FEBDFB1C71C01CCC45DD883CD511360479BE
-ECC0A8237E19D3883A06C5A700647860B3D9E570976D3606A11A4005424FD935
-8F5D7B39696F6F5C2100FFDF71D1C8ECAD98BD1D4CEE7BA8C793815747CE6FD5
-52ED6DE1583093E8D8AB8D16C912F7E89F78A24CE36ED53D3E06D3F81BF62ED1
-416015A128EA3A008573DE760C6AE05BD958BFCB46351F614B617CEE55C5E294
+IV: 2A 44 FE 5A A3 63 F5 11 83 A6 FE DA 1E B7 3D F1
+BF22677F79DF533C83FFE485B5F9CFABA24352FDEBED14B6FFA16EE9F00D6AC4
+B9343EDBB8B8C6EEFDA7AE9934445E27B04950DBB4F31ECCD1735CCB8C1600DE
+54CC71AF6794D47FFC49823DA6C4CCAD94EC5540515FD6F537A078BFD736105C
+4A3A12125D4F1186369B3B0ECB86B28A6EE4A0AF49DD4C42743A5C2C9BD1F5FC
+190D7746CDC7782157E95532070BCFE8637CF9A7BE03F9382A435ACAAA7A5F5E6BEB8E34A320BDB6E492D793E470CAB4
+59ABF9B68B31BF9CCF2CCCC0A6B3182FA2772691A400B2BFB5E2490DA2BCD2A4
+304DF68472EC9C78341218C10242DC3D62887A5281B52061BC0C9D117CDE1185
+D146050F90D30FA166615706FBC8D5B3573BDCB081E2445930CE1B71F5BDB7AE
+9386C94D044CCCBEE7972319191933328A06B20138C432B86C76EB909BB06019
+CFC23206853E9D01C3986FD849908686A2442287277C06574928A362F988CE1B
+534B351BE03A98B56ED622D37B9BBCD871CA76EB6EF250B1615105FA496E991C8F195293F83EE38AE5831D95F45238E3
+AFF90EC99CF4278D79DA9B1163FF07C83203AD34F9C4228423B4B58FF3F6978C605CC282FB1E37C0946D86C51809222C
+44C9EF18971905D2207F62D3365CB4A31D449FA215F950CEB67368D13181959C
+0CF10950D8A3EDEEEEA9AA4E41354373584FBFE6BB2E8A52C3149757C133445C
+4FBE939E87B8438AFC86773DADA39FE3856A3518A5159C9BF6B2EFA752F5B3F5
+CBFD648024823A33481B8A7381CD28930765265A1CA9BBDE1879F0827273A860
+8D3C70EF2E4ED2EF23752046538BF30F6DA8266F2B10A4BAD8549B3D20298F08EF9E6C21F78DDA9CA6EBB1E3CDF82C78
+D31EBB7C994C397776777D4904661C6F8DF5CDA9F828CA19378CAA397555F8C0
+FDA58BA7B0CD5C9090FE891029A3773EA16DB77EB5FA06A4C443C01B537B2615
+5CEE7A27D0D1B1AB5BAAC93D78121BC6D5FCD589C093A22C71E81C390045C85FDE98C202340FDD2046FF906A035E31E9
+C3121624E5B91EDCF651B8A89C2EEF4379876D0E0D918596F3E5CED9F3C92AB689D609AA1FB5362F57738A0AF62E3C92
+25F715B4CEA880E4879C6C03DC61875A43FB314AB4F21AE1CF7C933172B4A29D
+574166A278E2FA4AB8A09078152929E631E4E182E20CCF803250A0A2D4BB62F3
+B0D1C7AA1752135BA7627D8F65EC9651B810EC29BA01C8D9BC5B3EB20B1A0939
+E3E9D30E4F7003E63917DF3B5FC4E03863E37AFD6C5987CCFEC8129C692474EF
+67A35F2E3C400953EC1CD1874A35A4734D3E9F116F7E334276BF898E48C21AFE
+BC8D612FA363AB364BB9D2701273C4FA587B2F8D8CD039DEFB72BAD00360149F
+9A88BBDA111C9185EE5BBA610574D46A4D53EC79B63D5FB57BAB5A6609F2160F
+9512A1F77A4C46BD7F79D792B1578AC1FA41F15F6D7C72BC952BD89262C85327
+182685E3E0A23055025F7218AB16F7AE3A7F9DD71761AAE3B5E4AB85E2EFBF929D640258AEBC9F0BB167985A1E4B132D
+1DD9156B6BF97424DC639708ACEE21DD1D64FC5BC0DD5252DDDDE7832C2B7B6F
+109BB4D660897DB00676093B585535D267426310CDE81F05793ACB46B9F6176E
+D7A2D468DF76A8E5C495D5280524B2996254B94458485B11CCAB36CD1EE3918F
+9F445C93FF382433015BEAE6D78F70AE2C02E0C961E1B9576D66E64978D984D0
+195CB755E6AC710B5AF10761AC2B13F8CA57355443B593BC59AAF3A819070568028BBAE75C0DA4BA6B90D63E679098B7
+C6ECD39EC47DFFD1ABC55F47AC8E2C26A8DB5EB8184153746F7D9AD5F0015E85
diff --git a/assets/resources/subghz/keeloq_mfcodes_user b/assets/resources/subghz/keeloq_mfcodes_user
index 910157d6..f013afa2 100644
--- a/assets/resources/subghz/keeloq_mfcodes_user
+++ b/assets/resources/subghz/keeloq_mfcodes_user
@@ -1,7 +1,7 @@
# for adding manufacture keys
# AABBCCDDEEFFAABB:X:NAME\r\n
# AABBCCDDEEFFAABB - man 64 bit
-# X - encryption method 1 - Simple Learning, 2 - Normal_Learning, 3 - Secure_Learning
+# X - encryption method 1 - Simple Learning, 2 - Normal_Learning, 3 - Secure_Learning, 4 - Magic_xor_type1 Learning
# 0 - iterates over both previous and man in direct and reverse byte sequence
# NAME - name (string without spaces) max 64 characters long
Filetype: Flipper SubGhz Keystore File
diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.c b/lib/subghz/protocols/subghz_protocol_keeloq.c
index 1db8da4d..bdecb4ee 100644
--- a/lib/subghz/protocols/subghz_protocol_keeloq.c
+++ b/lib/subghz/protocols/subghz_protocol_keeloq.c
@@ -115,6 +115,15 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
return 1;
}
break;
+ case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1:
+ man_learning = subghz_protocol_keeloq_common_magic_xor_type1_learning(
+ fix, manufacture_code->key);
+ decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning);
+ if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
+ instance->manufacture_name = string_get_cstr(manufacture_code->name);
+ return 1;
+ }
+ break;
case KEELOQ_LEARNING_UNKNOWN:
// Simple Learning
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
@@ -144,6 +153,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
instance->manufacture_name = string_get_cstr(manufacture_code->name);
return 1;
}
+
+ // Check for mirrored man
man_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
@@ -161,13 +172,30 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
}
// Check for mirrored man
-
man_learning = subghz_protocol_keeloq_common_secure_learning(fix, seed, man_rev);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
instance->manufacture_name = string_get_cstr(manufacture_code->name);
return 1;
}
+
+ // Magic xor type1 learning
+ man_learning = subghz_protocol_keeloq_common_magic_xor_type1_learning(
+ fix, manufacture_code->key);
+ decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning);
+ if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
+ instance->manufacture_name = string_get_cstr(manufacture_code->name);
+ return 1;
+ }
+
+ // Check for mirrored man
+ man_learning =
+ subghz_protocol_keeloq_common_magic_xor_type1_learning(fix, man_rev);
+ decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning);
+ if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
+ instance->manufacture_name = string_get_cstr(manufacture_code->name);
+ return 1;
+ }
break;
}
}
@@ -198,6 +226,7 @@ void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instan
} else {
subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop);
}
+
instance->common.serial = key_fix & 0x0FFFFFFF;
instance->common.btn = key_fix >> 28;
}
diff --git a/lib/subghz/protocols/subghz_protocol_keeloq_common.c b/lib/subghz/protocols/subghz_protocol_keeloq_common.c
index 0726a604..9f9d105b 100644
--- a/lib/subghz/protocols/subghz_protocol_keeloq_common.c
+++ b/lib/subghz/protocols/subghz_protocol_keeloq_common.c
@@ -53,7 +53,7 @@ inline uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, con
/** Secure Learning
* @param data - serial number (28bit)
- * @param seed - serial number (32bit)
+ * @param seed - seed number (32bit)
* @param key - manufacture (64bit)
* @return manufacture for this serial number (64bit)
*/
@@ -69,4 +69,16 @@ inline uint64_t subghz_protocol_keeloq_common_secure_learning(
k2 = subghz_protocol_keeloq_common_decrypt(seed, key);
return ((uint64_t)k1 << 32) | k2;
+}
+
+/** Magic_xor_type1 Learning
+ * @param data - serial number (28bit)
+ * @param xor - magic xor (64bit)
+ * @return manufacture for this serial number (64bit)
+ */
+
+inline uint64_t
+ subghz_protocol_keeloq_common_magic_xor_type1_learning(uint32_t data, uint64_t xor) {
+ data &= 0x0FFFFFFF;
+ return (((uint64_t)data << 32) | data) ^ xor;
} \ No newline at end of file
diff --git a/lib/subghz/protocols/subghz_protocol_keeloq_common.h b/lib/subghz/protocols/subghz_protocol_keeloq_common.h
index 906aad1f..110ce9f9 100644
--- a/lib/subghz/protocols/subghz_protocol_keeloq_common.h
+++ b/lib/subghz/protocols/subghz_protocol_keeloq_common.h
@@ -24,6 +24,7 @@
#define KEELOQ_LEARNING_SIMPLE 1u
#define KEELOQ_LEARNING_NORMAL 2u
#define KEELOQ_LEARNING_SECURE 3u
+#define KEELOQ_LEARNING_MAGIC_XOR_TYPE_1 4u
/** Simple Learning Encrypt
* @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
@@ -48,10 +49,18 @@ uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint
/** Secure Learning
* @param data - serial number (28bit)
- * @param seed - serial number (32bit)
+ * @param seed - seed number (32bit)
* @param key - manufacture (64bit)
* @return manufacture for this serial number (64bit)
*/
uint64_t
- subghz_protocol_keeloq_common_secure_learning(uint32_t data, uint32_t seed, const uint64_t key); \ No newline at end of file
+ subghz_protocol_keeloq_common_secure_learning(uint32_t data, uint32_t seed, const uint64_t key);
+
+/** Magic_xor_type1 Learning
+ * @param data - serial number (28bit)
+ * @param xor - magic xor (64bit)
+ * @return manufacture for this serial number (64bit)
+ */
+
+uint64_t subghz_protocol_keeloq_common_magic_xor_type1_learning(uint32_t data, uint64_t xor);