[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>
This commit is contained in:
		
							parent
							
								
									32c92a80ea
								
							
						
					
					
						commit
						d4d87aa6a8
					
				| @ -4,6 +4,7 @@ | |||||||
| 
 | 
 | ||||||
| struct TextInput { | struct TextInput { | ||||||
|     View* view; |     View* view; | ||||||
|  |     osTimerId_t timer; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -23,6 +24,11 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
|     uint8_t selected_row; |     uint8_t selected_row; | ||||||
|     uint8_t selected_column; |     uint8_t selected_column; | ||||||
|  | 
 | ||||||
|  |     TextInputValidatorCallback validator_callback; | ||||||
|  |     void* validator_callback_context; | ||||||
|  |     string_t validator_text; | ||||||
|  |     bool valadator_message_visible; | ||||||
| } TextInputModel; | } TextInputModel; | ||||||
| 
 | 
 | ||||||
| static const uint8_t keyboard_origin_x = 1; | 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) { | 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); |             uint8_t text_length = strlen(model->text_buffer); | ||||||
| 
 | 
 | ||||||
|             if(selected == ENTER_KEY) { |             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); |                     model->callback(model->callback_context); | ||||||
|                 } |                 } | ||||||
|             } else if(selected == BACKSPACE_KEY) { |             } else if(selected == BACKSPACE_KEY) { | ||||||
| @ -321,6 +344,16 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { | |||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event->type == InputTypeShort || event->type == InputTypeRepeat) { |     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) { |         switch(event->key) { | ||||||
|         case InputKeyUp: |         case InputKeyUp: | ||||||
|             text_input_handle_up(text_input); |             text_input_handle_up(text_input); | ||||||
| @ -351,7 +384,11 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { | |||||||
|        event->key == InputKeyBack) { |        event->key == InputKeyBack) { | ||||||
|         with_view_model( |         with_view_model( | ||||||
|             text_input->view, (TextInputModel * model) { |             text_input->view, (TextInputModel * model) { | ||||||
|  |                 if(model->valadator_message_visible) { | ||||||
|  |                     model->valadator_message_visible = false; | ||||||
|  |                 } else { | ||||||
|                     text_input_backspace_cb(model); |                     text_input_backspace_cb(model); | ||||||
|  |                 } | ||||||
|                 return true; |                 return true; | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -361,6 +398,17 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { | |||||||
|     return consumed; |     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_alloc() { | ||||||
|     TextInput* text_input = furi_alloc(sizeof(TextInput)); |     TextInput* text_input = furi_alloc(sizeof(TextInput)); | ||||||
|     text_input->view = view_alloc(); |     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_draw_callback(text_input->view, text_input_view_draw_callback); | ||||||
|     view_set_input_callback(text_input->view, text_input_view_input_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); |     text_input_clean(text_input); | ||||||
| 
 | 
 | ||||||
|     return text_input; |     return text_input; | ||||||
| @ -376,7 +432,21 @@ TextInput* text_input_alloc() { | |||||||
| 
 | 
 | ||||||
| void text_input_free(TextInput* text_input) { | void text_input_free(TextInput* text_input) { | ||||||
|     furi_assert(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); |     view_free(text_input->view); | ||||||
|  | 
 | ||||||
|     free(text_input); |     free(text_input); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -393,6 +463,10 @@ void text_input_clean(TextInput* text_input) { | |||||||
|             model->text_buffer_size = 0; |             model->text_buffer_size = 0; | ||||||
|             model->callback = NULL; |             model->callback = NULL; | ||||||
|             model->callback_context = 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; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| @ -425,6 +499,38 @@ 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) { | void text_input_set_header_text(TextInput* text_input, const char* text) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         text_input->view, (TextInputModel * model) { |         text_input->view, (TextInputModel * model) { | ||||||
|  | |||||||
| @ -6,6 +6,8 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
|  | #include "validators.h" | ||||||
|  | #include <m-string.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| @ -14,6 +16,7 @@ extern "C" { | |||||||
| /** Text input anonymous structure */ | /** Text input anonymous structure */ | ||||||
| typedef struct TextInput TextInput; | typedef struct TextInput TextInput; | ||||||
| typedef void (*TextInputCallback)(void* context); | typedef void (*TextInputCallback)(void* context); | ||||||
|  | typedef bool (*TextInputValidatorCallback)(const char* text, string_t error, void* context); | ||||||
| 
 | 
 | ||||||
| /** Allocate and initialize text input 
 | /** Allocate and initialize text input 
 | ||||||
|  *  |  *  | ||||||
| @ -63,6 +66,15 @@ void text_input_set_result_callback( | |||||||
|     size_t text_buffer_size, |     size_t text_buffer_size, | ||||||
|     bool clear_default_text); |     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
 | /** Set text input header text
 | ||||||
|  * |  * | ||||||
|  * @param      text_input  TextInput instance |  * @param      text_input  TextInput instance | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								applications/gui/modules/validators.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								applications/gui/modules/validators.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								applications/gui/modules/validators.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								applications/gui/modules/validators.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
| @ -1,10 +1,11 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include <lib/toolbox/random_name.h> | #include <lib/toolbox/random_name.h> | ||||||
| #include "file_worker.h" |  | ||||||
| #include "../helpers/subghz_custom_event.h" | #include "../helpers/subghz_custom_event.h" | ||||||
| #include <lib/subghz/protocols/subghz_protocol_raw.h> | #include <lib/subghz/protocols/subghz_protocol_raw.h> | ||||||
|  | #include <gui/modules/validators.h> | ||||||
| 
 | 
 | ||||||
| void subghz_scene_save_name_text_input_callback(void* context) { | void subghz_scene_save_name_text_input_callback(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneSaveName); |     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, |         subghz->file_name, | ||||||
|         22, //Max len name
 |         22, //Max len name
 | ||||||
|         dev_name_empty); |         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); |     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(event.event == SubghzCustomEventSceneSaveName) { | ||||||
|             if(strcmp(subghz->file_name, "")) { |             if(strcmp(subghz->file_name, "")) { | ||||||
|                 if(strcmp(subghz->file_name_tmp, "")) { |                 if(strcmp(subghz->file_name_tmp, "")) { | ||||||
|                     subghz_rename_file(subghz); |                     if(!subghz_rename_file(subghz)) { | ||||||
|  |                         return false; | ||||||
|  |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     subghz_save_protocol_to_file(subghz, subghz->file_name); |                     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; |     SubGhz* subghz = context; | ||||||
| 
 | 
 | ||||||
|     // Clear view
 |     // 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); |     text_input_clean(subghz->text_input); | ||||||
|     scene_manager_set_scene_state( |     scene_manager_set_scene_state( | ||||||
|         subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet); |         subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet); | ||||||
|  | |||||||
| @ -421,7 +421,7 @@ bool subghz_rename_file(SubGhz* subghz) { | |||||||
|     FS_Error fs_result = |     FS_Error fs_result = | ||||||
|         storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path)); |         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"); |         dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory"); | ||||||
|         ret = false; |         ret = false; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -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_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_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_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}; | 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_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_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_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}; | 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_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_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_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_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_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_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_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_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_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_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_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}; | const Icon I_Down_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Down_25x27}; | ||||||
|  | |||||||
| @ -82,12 +82,14 @@ extern const Icon I_ArrowDownEmpty_14x15; | |||||||
| extern const Icon I_ArrowDownFilled_14x15; | extern const Icon I_ArrowDownFilled_14x15; | ||||||
| extern const Icon I_ArrowUpEmpty_14x15; | extern const Icon I_ArrowUpEmpty_14x15; | ||||||
| extern const Icon I_ArrowUpFilled_14x15; | extern const Icon I_ArrowUpFilled_14x15; | ||||||
|  | extern const Icon I_Back3_45x8; | ||||||
| extern const Icon I_DoorLeft_70x55; | extern const Icon I_DoorLeft_70x55; | ||||||
| extern const Icon I_DoorLocked_10x56; | extern const Icon I_DoorLocked_10x56; | ||||||
| extern const Icon I_DoorRight_70x55; | extern const Icon I_DoorRight_70x55; | ||||||
| extern const Icon I_LockPopup_100x49; | extern const Icon I_LockPopup_100x49; | ||||||
| extern const Icon I_PassportBottom_128x17; | extern const Icon I_PassportBottom_128x17; | ||||||
| extern const Icon I_PassportLeft_6x47; | extern const Icon I_PassportLeft_6x47; | ||||||
|  | extern const Icon I_WarningDolphin_45x42; | ||||||
| extern const Icon I_Back_15x10; | extern const Icon I_Back_15x10; | ||||||
| extern const Icon I_DolphinReadingSuccess_59x63; | extern const Icon I_DolphinReadingSuccess_59x63; | ||||||
| extern const Icon I_Down_25x27; | extern const Icon I_Down_25x27; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/Back3_45x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Interface/Back3_45x8.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/WarningDolphin_45x42.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Interface/WarningDolphin_45x42.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.1 KiB | 
| @ -1,38 +1,40 @@ | |||||||
| Filetype: Flipper SubGhz Keystore File | Filetype: Flipper SubGhz Keystore File | ||||||
| Version: 0 | Version: 0 | ||||||
| Encryption: 1 | Encryption: 1 | ||||||
| IV: 7A 44 FE 5D C3 B3 65 13 73 A6 F4 2D 1E B6 7D F0 | IV: 2A 44 FE 5A A3 63 F5 11 83 A6 FE DA 1E B7 3D F1 | ||||||
| 89153B35033574AAA06D7E792CB92A486B37A2CCDF0B0152BF1A563E321518C8 | BF22677F79DF533C83FFE485B5F9CFABA24352FDEBED14B6FFA16EE9F00D6AC4 | ||||||
| F6583A3E4148439E8A8D7ED6A095ACC0C3E22A48F1637E78DF023CAC9272934E | B9343EDBB8B8C6EEFDA7AE9934445E27B04950DBB4F31ECCD1735CCB8C1600DE | ||||||
| AA0439E6B76CD43F3FCC27CF69C5F3B6508E8103B164E4ECDDF8B2FB222D46FF | 54CC71AF6794D47FFC49823DA6C4CCAD94EC5540515FD6F537A078BFD736105C | ||||||
| A9826C663033D25AE21CB8790406997ADCE84360B258F2B989D967009659859C | 4A3A12125D4F1186369B3B0ECB86B28A6EE4A0AF49DD4C42743A5C2C9BD1F5FC | ||||||
| 3474E7BBFA0173928F414CFD5EE19B27A558D9C171D96FE7B7840A01323A7E7446FAE3E98EA9A8C69B4A6B781BD7906A | 190D7746CDC7782157E95532070BCFE8637CF9A7BE03F9382A435ACAAA7A5F5E6BEB8E34A320BDB6E492D793E470CAB4 | ||||||
| 2873939A8E0EAC16D748967E987BB0F1079C106E4235B7D35B4BF37F54B21F8E | 59ABF9B68B31BF9CCF2CCCC0A6B3182FA2772691A400B2BFB5E2490DA2BCD2A4 | ||||||
| EF6F1DC0201FCB8CEBC5642A5194A1FDCFBE1FA772A79CEAD54D2F0DA3AC4F6C | 304DF68472EC9C78341218C10242DC3D62887A5281B52061BC0C9D117CDE1185 | ||||||
| 3F595EAA0E81E96C5D6DB41799D314E3E81E7F4197E19A3341C55592B1B6C4B0 | D146050F90D30FA166615706FBC8D5B3573BDCB081E2445930CE1B71F5BDB7AE | ||||||
| 7B2D75FE11B27E99CA7610E47D712C8CFB619EC69EBC976A70CFD9574C9F4FF8 | 9386C94D044CCCBEE7972319191933328A06B20138C432B86C76EB909BB06019 | ||||||
| 39735CF1D009D132A33B9C546D95FA6D3E69BF3A57EF219392E57C9560E7B037 | CFC23206853E9D01C3986FD849908686A2442287277C06574928A362F988CE1B | ||||||
| D56FDDFB0C4E808143D3ED5F15D6FF47F6EDEBD01192FC7ACF3ACCE9FD5162FC297D0089D65ED2CBE3CE05DDA7B96446 | 534B351BE03A98B56ED622D37B9BBCD871CA76EB6EF250B1615105FA496E991C8F195293F83EE38AE5831D95F45238E3 | ||||||
| 2750D4F0650061C3AF72C88FD080BE241F2BDD8D8C1B0EFE781120EBEFFE2C72D0EECC42CDDED50CFE4AC51C48AE68C6 | AFF90EC99CF4278D79DA9B1163FF07C83203AD34F9C4228423B4B58FF3F6978C605CC282FB1E37C0946D86C51809222C | ||||||
| F8CE64921CB73015F2672A9EF0A8359269CAE0E515D6DBB3130CFC9E5E1A98AD | 44C9EF18971905D2207F62D3365CB4A31D449FA215F950CEB67368D13181959C | ||||||
| ACF6ADB9E02D67B44EB6C6F126BF64BDAB37926B8BE39E27F323E8F5A0F8FC38 | 0CF10950D8A3EDEEEEA9AA4E41354373584FBFE6BB2E8A52C3149757C133445C | ||||||
| FBB1302D697F94ECED681CE047819001EDE6E013850258F61E97091DD37D24F2 | 4FBE939E87B8438AFC86773DADA39FE3856A3518A5159C9BF6B2EFA752F5B3F5 | ||||||
| D8CD53AB5A94898EB53D4FF46546ADBAA24691181A396052A58AAC657D6817AB | CBFD648024823A33481B8A7381CD28930765265A1CA9BBDE1879F0827273A860 | ||||||
| 43200E08C21747CABC59538888A259238E782545732A1A6EEE00A6929EC9DD97A8BA9812372374046AC66652CC561D60 | 8D3C70EF2E4ED2EF23752046538BF30F6DA8266F2B10A4BAD8549B3D20298F08EF9E6C21F78DDA9CA6EBB1E3CDF82C78 | ||||||
| C38CBE29F22D0E83E58A52E94AA2485DA8E702FBDB89D27249473CB8A19AEF61 | D31EBB7C994C397776777D4904661C6F8DF5CDA9F828CA19378CAA397555F8C0 | ||||||
| 9F0EB580F7474985E8460E1682451E213778B77A9CAB4734B75C5386851050BF | FDA58BA7B0CD5C9090FE891029A3773EA16DB77EB5FA06A4C443C01B537B2615 | ||||||
| 2364EBB8237363B21226565675B9F47819C5BBC7E917C761BA3652D0A6ED7D3273EB8F3B7FBA68DE4143FB15BBEC35FB | 5CEE7A27D0D1B1AB5BAAC93D78121BC6D5FCD589C093A22C71E81C390045C85FDE98C202340FDD2046FF906A035E31E9 | ||||||
| CCDE559A2901A8290D6B2E8EDF66612E4C90E2E7C63643C8C5F244E30874B41039E078089E2253DA73B3A6DD821A84CD | C3121624E5B91EDCF651B8A89C2EEF4379876D0E0D918596F3E5CED9F3C92AB689D609AA1FB5362F57738A0AF62E3C92 | ||||||
| 33B239455FBE7AB8CE833C3B9C063EFEAE1FC7AC876AF3294C67D5B08BF7E9EC | 25F715B4CEA880E4879C6C03DC61875A43FB314AB4F21AE1CF7C933172B4A29D | ||||||
| F0FBBCEFE99D25104022CD3621B21B5F84FFBC9A5E21B0AED2B1560B39524A5B | 574166A278E2FA4AB8A09078152929E631E4E182E20CCF803250A0A2D4BB62F3 | ||||||
| E15B0614D9ECA17784E994652755559B7A3DA4B53CE6E63108BCFCD8024761DD | B0D1C7AA1752135BA7627D8F65EC9651B810EC29BA01C8D9BC5B3EB20B1A0939 | ||||||
| 9E244C80E72937274DD6B2787F1A75F278A2DF7CB3B89F7C2BF7CC8DBBF2A3F0 | E3E9D30E4F7003E63917DF3B5FC4E03863E37AFD6C5987CCFEC8129C692474EF | ||||||
| 689DCA188A40DFDD3575A9BD9D7AF2427D0CE707F591029463AEC6B8679969AC | 67A35F2E3C400953EC1CD1874A35A4734D3E9F116F7E334276BF898E48C21AFE | ||||||
| 25D9B04D10AF541925901F55D8D7FA9C87523995F53183FB04F00C6023D5930A | BC8D612FA363AB364BB9D2701273C4FA587B2F8D8CD039DEFB72BAD00360149F | ||||||
| D11F70508485C019AFC5FDBE5FD7223710033483C803FC7C2C69BAAD6ACB7CA7 | 9A88BBDA111C9185EE5BBA610574D46A4D53EC79B63D5FB57BAB5A6609F2160F | ||||||
| C081A0ACEA8210AB117028EDFF15641EE287CB1CFF8332A9D208B7324523129E | 9512A1F77A4C46BD7F79D792B1578AC1FA41F15F6D7C72BC952BD89262C85327 | ||||||
| 4C5B7C959C00A30F39A431B20EA1FEBDFB1C71C01CCC45DD883CD511360479BE | 182685E3E0A23055025F7218AB16F7AE3A7F9DD71761AAE3B5E4AB85E2EFBF929D640258AEBC9F0BB167985A1E4B132D | ||||||
| ECC0A8237E19D3883A06C5A700647860B3D9E570976D3606A11A4005424FD935 | 1DD9156B6BF97424DC639708ACEE21DD1D64FC5BC0DD5252DDDDE7832C2B7B6F | ||||||
| 8F5D7B39696F6F5C2100FFDF71D1C8ECAD98BD1D4CEE7BA8C793815747CE6FD5 | 109BB4D660897DB00676093B585535D267426310CDE81F05793ACB46B9F6176E | ||||||
| 52ED6DE1583093E8D8AB8D16C912F7E89F78A24CE36ED53D3E06D3F81BF62ED1 | D7A2D468DF76A8E5C495D5280524B2996254B94458485B11CCAB36CD1EE3918F | ||||||
| 416015A128EA3A008573DE760C6AE05BD958BFCB46351F614B617CEE55C5E294 | 9F445C93FF382433015BEAE6D78F70AE2C02E0C961E1B9576D66E64978D984D0 | ||||||
|  | 195CB755E6AC710B5AF10761AC2B13F8CA57355443B593BC59AAF3A819070568028BBAE75C0DA4BA6B90D63E679098B7 | ||||||
|  | C6ECD39EC47DFFD1ABC55F47AC8E2C26A8DB5EB8184153746F7D9AD5F0015E85 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| # for adding manufacture keys | # for adding manufacture keys | ||||||
| # AABBCCDDEEFFAABB:X:NAME\r\n | # AABBCCDDEEFFAABB:X:NAME\r\n | ||||||
| # AABBCCDDEEFFAABB - man 64 bit | # 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 | #   	0 - iterates over both previous and man in direct and reverse byte sequence | ||||||
| # NAME - name (string without spaces) max 64 characters long | # NAME - name (string without spaces) max 64 characters long | ||||||
| Filetype: Flipper SubGhz Keystore File | Filetype: Flipper SubGhz Keystore File | ||||||
|  | |||||||
| @ -115,6 +115,15 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( | |||||||
|                     return 1; |                     return 1; | ||||||
|                 } |                 } | ||||||
|                 break; |                 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: |             case KEELOQ_LEARNING_UNKNOWN: | ||||||
|                 // Simple Learning
 |                 // Simple Learning
 | ||||||
|                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); |                 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); |                     instance->manufacture_name = string_get_cstr(manufacture_code->name); | ||||||
|                     return 1; |                     return 1; | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|  |                 // Check for mirrored man
 | ||||||
|                 man_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); |                 man_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); | ||||||
|                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning); |                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning); | ||||||
|                 if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { |                 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
 |                 // Check for mirrored man
 | ||||||
| 
 |  | ||||||
|                 man_learning = subghz_protocol_keeloq_common_secure_learning(fix, seed, man_rev); |                 man_learning = subghz_protocol_keeloq_common_secure_learning(fix, seed, man_rev); | ||||||
|                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning); |                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_learning); | ||||||
|                 if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { |                 if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { | ||||||
|                     instance->manufacture_name = string_get_cstr(manufacture_code->name); |                     instance->manufacture_name = string_get_cstr(manufacture_code->name); | ||||||
|                     return 1; |                     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; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -198,6 +226,7 @@ void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instan | |||||||
|     } else { |     } else { | ||||||
|         subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop); |         subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     instance->common.serial = key_fix & 0x0FFFFFFF; |     instance->common.serial = key_fix & 0x0FFFFFFF; | ||||||
|     instance->common.btn = key_fix >> 28; |     instance->common.btn = key_fix >> 28; | ||||||
| } | } | ||||||
|  | |||||||
| @ -53,7 +53,7 @@ inline uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, con | |||||||
| 
 | 
 | ||||||
| /** Secure Learning
 | /** Secure Learning
 | ||||||
|  * @param data - serial number (28bit) |  * @param data - serial number (28bit) | ||||||
|  * @param seed - serial number (32bit) |  * @param seed - seed number (32bit) | ||||||
|  * @param key - manufacture (64bit) |  * @param key - manufacture (64bit) | ||||||
|  * @return manufacture for this serial number (64bit) |  * @return manufacture for this serial number (64bit) | ||||||
|  */ |  */ | ||||||
| @ -70,3 +70,15 @@ inline uint64_t subghz_protocol_keeloq_common_secure_learning( | |||||||
| 
 | 
 | ||||||
|     return ((uint64_t)k1 << 32) | k2; |     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; | ||||||
|  | } | ||||||
| @ -24,6 +24,7 @@ | |||||||
| #define KEELOQ_LEARNING_SIMPLE 1u | #define KEELOQ_LEARNING_SIMPLE 1u | ||||||
| #define KEELOQ_LEARNING_NORMAL 2u | #define KEELOQ_LEARNING_NORMAL 2u | ||||||
| #define KEELOQ_LEARNING_SECURE 3u | #define KEELOQ_LEARNING_SECURE 3u | ||||||
|  | #define KEELOQ_LEARNING_MAGIC_XOR_TYPE_1 4u | ||||||
| 
 | 
 | ||||||
| /** Simple Learning Encrypt
 | /** Simple Learning Encrypt
 | ||||||
|  * @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter |  * @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
 | /** Secure Learning
 | ||||||
|  * @param data - serial number (28bit) |  * @param data - serial number (28bit) | ||||||
|  * @param seed - serial number (32bit) |  * @param seed - seed number (32bit) | ||||||
|  * @param key - manufacture (64bit) |  * @param key - manufacture (64bit) | ||||||
|  * @return manufacture for this serial number (64bit) |  * @return manufacture for this serial number (64bit) | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| uint64_t | uint64_t | ||||||
|     subghz_protocol_keeloq_common_secure_learning(uint32_t data, uint32_t seed, const uint64_t key); |     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); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm