Преглед изворни кода

SubGhz: add protocol "Linear Delta-3" (#2239)

* SubGhz: add protocol "Linear Delta-3"
* SubGhz: fix Leniar Delta 3
* BadUSB: mask pvs studio warning for valid code

Co-authored-by: SkorP <skorpionm@yandex.ru>
Co-authored-by: あく <alleteam@gmail.com>
Co-authored-by: Skorpionm <85568270+Skorpionm@users.noreply.github.com>
Brandon Weeks пре 2 година
родитељ
комит
8288a08eb3

+ 17 - 1
applications/debug/unit_tests/subghz/subghz_test.c

@@ -13,7 +13,7 @@
 #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
 #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
 #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
-#define TEST_RANDOM_COUNT_PARSE 273
+#define TEST_RANDOM_COUNT_PARSE 295
 #define TEST_TIMEOUT 10000
 
 static SubGhzEnvironment* environment_handler;
@@ -489,6 +489,14 @@ MU_TEST(subghz_decoder_linear_test) {
         "Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
 }
 
+MU_TEST(subghz_decoder_linear_delta3_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/linear_delta3_raw.sub"),
+            SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
+}
+
 MU_TEST(subghz_decoder_megacode_test) {
     mu_assert(
         subghz_decoder_test(
@@ -647,6 +655,12 @@ MU_TEST(subghz_encoder_linear_test) {
         "Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
 }
 
+MU_TEST(subghz_encoder_linear_delta3_test) {
+    mu_assert(
+        subghz_encoder_test(EXT_PATH("unit_tests/subghz/linear_delta3.sub")),
+        "Test encoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
+}
+
 MU_TEST(subghz_encoder_megacode_test) {
     mu_assert(
         subghz_encoder_test(EXT_PATH("unit_tests/subghz/megacode.sub")),
@@ -772,6 +786,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_decoder_somfy_telis_test);
     MU_RUN_TEST(subghz_decoder_star_line_test);
     MU_RUN_TEST(subghz_decoder_linear_test);
+    MU_RUN_TEST(subghz_decoder_linear_delta3_test);
     MU_RUN_TEST(subghz_decoder_megacode_test);
     MU_RUN_TEST(subghz_decoder_secplus_v1_test);
     MU_RUN_TEST(subghz_decoder_secplus_v2_test);
@@ -796,6 +811,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_encoder_nice_flo_test);
     MU_RUN_TEST(subghz_encoder_keelog_test);
     MU_RUN_TEST(subghz_encoder_linear_test);
+    MU_RUN_TEST(subghz_encoder_linear_delta3_test);
     MU_RUN_TEST(subghz_encoder_megacode_test);
     MU_RUN_TEST(subghz_encoder_holtek_test);
     MU_RUN_TEST(subghz_encoder_secplus_v1_test);

+ 1 - 1
applications/main/bad_usb/bad_usb_script.c

@@ -694,7 +694,7 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
     }
 
     File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
-    if(!furi_string_empty(layout_path)) {
+    if(!furi_string_empty(layout_path)) { //-V1051
         if(storage_file_open(
                layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
             uint16_t layout[128];

+ 7 - 0
assets/unit_tests/subghz/linear_delta3.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: LinearDelta3
+Bit: 8
+Key: 00 00 00 00 00 00 00 D0

Разлика између датотеке није приказан због своје велике величине
+ 5 - 0
assets/unit_tests/subghz/linear_delta3_raw.sub


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
assets/unit_tests/subghz/test_random_raw.sub


+ 359 - 0
lib/subghz/protocols/linear_delta3.c

@@ -0,0 +1,359 @@
+#include "linear_delta3.h"
+
+#include "../blocks/const.h"
+#include "../blocks/decoder.h"
+#include "../blocks/encoder.h"
+#include "../blocks/generic.h"
+#include "../blocks/math.h"
+
+#define TAG "SubGhzProtocolLinearDelta3"
+
+#define DIP_PATTERN "%c%c%c%c%c%c%c%c"
+#define DATA_TO_DIP(dip)                                                                    \
+    (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'),     \
+        (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), \
+        (dip & 0x0002 ? '1' : '0'), (dip & 0x0001 ? '1' : '0')
+
+static const SubGhzBlockConst subghz_protocol_linear_delta3_const = {
+    .te_short = 500,
+    .te_long = 2000,
+    .te_delta = 150,
+    .min_count_bit_for_found = 8,
+};
+
+struct SubGhzProtocolDecoderLinearDelta3 {
+    SubGhzProtocolDecoderBase base;
+
+    SubGhzBlockDecoder decoder;
+    SubGhzBlockGeneric generic;
+
+    uint32_t last_data;
+};
+
+struct SubGhzProtocolEncoderLinearDelta3 {
+    SubGhzProtocolEncoderBase base;
+
+    SubGhzProtocolBlockEncoder encoder;
+    SubGhzBlockGeneric generic;
+};
+
+typedef enum {
+    LinearDecoderStepReset = 0,
+    LinearDecoderStepSaveDuration,
+    LinearDecoderStepCheckDuration,
+} LinearDecoderStep;
+
+const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder = {
+    .alloc = subghz_protocol_decoder_linear_delta3_alloc,
+    .free = subghz_protocol_decoder_linear_delta3_free,
+
+    .feed = subghz_protocol_decoder_linear_delta3_feed,
+    .reset = subghz_protocol_decoder_linear_delta3_reset,
+
+    .get_hash_data = subghz_protocol_decoder_linear_delta3_get_hash_data,
+    .serialize = subghz_protocol_decoder_linear_delta3_serialize,
+    .deserialize = subghz_protocol_decoder_linear_delta3_deserialize,
+    .get_string = subghz_protocol_decoder_linear_delta3_get_string,
+};
+
+const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder = {
+    .alloc = subghz_protocol_encoder_linear_delta3_alloc,
+    .free = subghz_protocol_encoder_linear_delta3_free,
+
+    .deserialize = subghz_protocol_encoder_linear_delta3_deserialize,
+    .stop = subghz_protocol_encoder_linear_delta3_stop,
+    .yield = subghz_protocol_encoder_linear_delta3_yield,
+};
+
+const SubGhzProtocol subghz_protocol_linear_delta3 = {
+    .name = SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME,
+    .type = SubGhzProtocolTypeStatic,
+    .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
+            SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
+
+    .decoder = &subghz_protocol_linear_delta3_decoder,
+    .encoder = &subghz_protocol_linear_delta3_encoder,
+};
+
+void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolEncoderLinearDelta3* instance =
+        malloc(sizeof(SubGhzProtocolEncoderLinearDelta3));
+
+    instance->base.protocol = &subghz_protocol_linear_delta3;
+    instance->generic.protocol_name = instance->base.protocol->name;
+
+    instance->encoder.repeat = 10;
+    instance->encoder.size_upload = 16;
+    instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
+    instance->encoder.is_running = false;
+    return instance;
+}
+
+void subghz_protocol_encoder_linear_delta3_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolEncoderLinearDelta3* instance = context;
+    free(instance->encoder.upload);
+    free(instance);
+}
+
+/**
+ * Generating an upload from data.
+ * @param instance Pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ * @return true On success
+ */
+static bool
+    subghz_protocol_encoder_linear_delta3_get_upload(SubGhzProtocolEncoderLinearDelta3* instance) {
+    furi_assert(instance);
+    size_t index = 0;
+    size_t size_upload = (instance->generic.data_count_bit * 2);
+    if(size_upload > instance->encoder.size_upload) {
+        FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
+        return false;
+    } else {
+        instance->encoder.size_upload = size_upload;
+    }
+
+    //Send key data
+    for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) {
+        if(bit_read(instance->generic.data, i - 1)) {
+            //send bit 1
+            instance->encoder.upload[index++] =
+                level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short);
+            instance->encoder.upload[index++] = level_duration_make(
+                false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 7);
+        } else {
+            //send bit 0
+            instance->encoder.upload[index++] =
+                level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long);
+            instance->encoder.upload[index++] =
+                level_duration_make(false, (uint32_t)subghz_protocol_linear_delta3_const.te_long);
+        }
+    }
+    //Send end bit
+    if(bit_read(instance->generic.data, 0)) {
+        //send bit 1
+        instance->encoder.upload[index++] =
+            level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short);
+        //Send PT_GUARD
+        instance->encoder.upload[index] = level_duration_make(
+            false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 73);
+    } else {
+        //send bit 0
+        instance->encoder.upload[index++] =
+            level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long);
+        //Send PT_GUARD
+        instance->encoder.upload[index] = level_duration_make(
+            false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 70);
+    }
+
+    return true;
+}
+
+bool subghz_protocol_encoder_linear_delta3_deserialize(
+    void* context,
+    FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolEncoderLinearDelta3* instance = context;
+    bool res = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            FURI_LOG_E(TAG, "Deserialize error");
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_linear_delta3_const.min_count_bit_for_found) {
+            FURI_LOG_E(TAG, "Wrong number of bits in key");
+            break;
+        }
+        //optional parameter parameter
+        flipper_format_read_uint32(
+            flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
+
+        if(!subghz_protocol_encoder_linear_delta3_get_upload(instance)) break;
+        instance->encoder.is_running = true;
+
+        res = true;
+    } while(false);
+
+    return res;
+}
+
+void subghz_protocol_encoder_linear_delta3_stop(void* context) {
+    SubGhzProtocolEncoderLinearDelta3* instance = context;
+    instance->encoder.is_running = false;
+}
+
+LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context) {
+    SubGhzProtocolEncoderLinearDelta3* instance = context;
+
+    if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
+        instance->encoder.is_running = false;
+        return level_duration_reset();
+    }
+
+    LevelDuration ret = instance->encoder.upload[instance->encoder.front];
+
+    if(++instance->encoder.front == instance->encoder.size_upload) {
+        instance->encoder.repeat--;
+        instance->encoder.front = 0;
+    }
+
+    return ret;
+}
+
+void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolDecoderLinearDelta3* instance =
+        malloc(sizeof(SubGhzProtocolDecoderLinearDelta3));
+    instance->base.protocol = &subghz_protocol_linear_delta3;
+    instance->generic.protocol_name = instance->base.protocol->name;
+    return instance;
+}
+
+void subghz_protocol_decoder_linear_delta3_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    free(instance);
+}
+
+void subghz_protocol_decoder_linear_delta3_reset(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    instance->decoder.parser_step = LinearDecoderStepReset;
+    instance->last_data = 0;
+}
+
+void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    switch(instance->decoder.parser_step) {
+    case LinearDecoderStepReset:
+        if((!level) &&
+           (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 70) <
+            subghz_protocol_linear_delta3_const.te_delta * 24)) {
+            //Found header Linear
+            instance->decoder.decode_data = 0;
+            instance->decoder.decode_count_bit = 0;
+            instance->decoder.parser_step = LinearDecoderStepSaveDuration;
+        }
+        break;
+    case LinearDecoderStepSaveDuration:
+        if(level) {
+            instance->decoder.te_last = duration;
+            instance->decoder.parser_step = LinearDecoderStepCheckDuration;
+        } else {
+            instance->decoder.parser_step = LinearDecoderStepReset;
+        }
+        break;
+    case LinearDecoderStepCheckDuration:
+        if(!level) {
+            if(duration >= (subghz_protocol_linear_delta3_const.te_short * 10)) {
+                instance->decoder.parser_step = LinearDecoderStepReset;
+                if(DURATION_DIFF(
+                       instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) <
+                   subghz_protocol_linear_delta3_const.te_delta) {
+                    subghz_protocol_blocks_add_bit(&instance->decoder, 1);
+                } else if(
+                    DURATION_DIFF(
+                        instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) <
+                    subghz_protocol_linear_delta3_const.te_delta) {
+                    subghz_protocol_blocks_add_bit(&instance->decoder, 0);
+                }
+                if(instance->decoder.decode_count_bit ==
+                   subghz_protocol_linear_delta3_const.min_count_bit_for_found) {
+                    if((instance->last_data == instance->decoder.decode_data) &&
+                       instance->last_data) {
+                        instance->generic.serial = 0x0;
+                        instance->generic.btn = 0x0;
+
+                        instance->generic.data = instance->decoder.decode_data;
+                        instance->generic.data_count_bit = instance->decoder.decode_count_bit;
+
+                        if(instance->base.callback)
+                            instance->base.callback(&instance->base, instance->base.context);
+                    }
+                    instance->decoder.parser_step = LinearDecoderStepSaveDuration;
+                    instance->last_data = instance->decoder.decode_data;
+                }
+                break;
+            }
+
+            if((DURATION_DIFF(
+                    instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) <
+                subghz_protocol_linear_delta3_const.te_delta) &&
+               (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 7) <
+                subghz_protocol_linear_delta3_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 1);
+                instance->decoder.parser_step = LinearDecoderStepSaveDuration;
+            } else if(
+                (DURATION_DIFF(
+                     instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) <
+                 subghz_protocol_linear_delta3_const.te_delta) &&
+                (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_long) <
+                 subghz_protocol_linear_delta3_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 0);
+                instance->decoder.parser_step = LinearDecoderStepSaveDuration;
+            } else {
+                instance->decoder.parser_step = LinearDecoderStepReset;
+            }
+
+        } else {
+            instance->decoder.parser_step = LinearDecoderStepReset;
+        }
+        break;
+    }
+}
+
+uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    return subghz_protocol_blocks_get_hash_data(
+        &instance->decoder, (instance->decoder.decode_count_bit / 8));
+}
+
+bool subghz_protocol_decoder_linear_delta3_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzRadioPreset* preset) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
+}
+
+bool subghz_protocol_decoder_linear_delta3_deserialize(
+    void* context,
+    FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+    bool ret = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_linear_delta3_const.min_count_bit_for_found) {
+            FURI_LOG_E(TAG, "Wrong number of bits in key");
+            break;
+        }
+        ret = true;
+    } while(false);
+    return ret;
+}
+
+void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output) {
+    furi_assert(context);
+    SubGhzProtocolDecoderLinearDelta3* instance = context;
+
+    uint32_t data = instance->generic.data & 0xFF;
+
+    furi_string_cat_printf(
+        output,
+        "%s %dbit\r\n"
+        "Key:0x%lX\r\n"
+        "DIP:" DIP_PATTERN "\r\n",
+        instance->generic.protocol_name,
+        instance->generic.data_count_bit,
+        data,
+        DATA_TO_DIP(data));
+}

+ 111 - 0
lib/subghz/protocols/linear_delta3.h

@@ -0,0 +1,111 @@
+#pragma once
+
+#include "base.h"
+
+#define SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME "LinearDelta3"
+
+typedef struct SubGhzProtocolDecoderLinearDelta3 SubGhzProtocolDecoderLinearDelta3;
+typedef struct SubGhzProtocolEncoderLinearDelta3 SubGhzProtocolEncoderLinearDelta3;
+
+extern const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder;
+extern const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder;
+extern const SubGhzProtocol subghz_protocol_linear_delta3;
+
+/**
+ * Allocate SubGhzProtocolEncoderLinearDelta3.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolEncoderLinearDelta3* pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ */
+void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolEncoderLinearDelta3.
+ * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ */
+void subghz_protocol_encoder_linear_delta3_free(void* context);
+
+/**
+ * Deserialize and generating an upload to send.
+ * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_encoder_linear_delta3_deserialize(
+    void* context,
+    FlipperFormat* flipper_format);
+
+/**
+ * Forced transmission stop.
+ * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ */
+void subghz_protocol_encoder_linear_delta3_stop(void* context);
+
+/**
+ * Getting the level and duration of the upload to be loaded into DMA.
+ * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance
+ * @return LevelDuration 
+ */
+LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context);
+
+/**
+ * Allocate SubGhzProtocolDecoderLinearDelta3.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolDecoderLinearDelta3* pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ */
+void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolDecoderLinearDelta3.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ */
+void subghz_protocol_decoder_linear_delta3_free(void* context);
+
+/**
+ * Reset decoder SubGhzProtocolDecoderLinearDelta3.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ */
+void subghz_protocol_decoder_linear_delta3_reset(void* context);
+
+/**
+ * Parse a raw sequence of levels and durations received from the air.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ * @param level Signal level true-high false-low
+ * @param duration Duration of this level in, us
+ */
+void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration);
+
+/**
+ * Getting the hash sum of the last randomly received parcel.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ * @return hash Hash sum
+ */
+uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context);
+
+/**
+ * Serialize data SubGhzProtocolDecoderLinearDelta3.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @param preset The modulation on which the signal was received, SubGhzRadioPreset
+ * @return true On success
+ */
+bool subghz_protocol_decoder_linear_delta3_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzRadioPreset* preset);
+
+/**
+ * Deserialize data SubGhzProtocolDecoderLinearDelta3.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_decoder_linear_delta3_deserialize(
+    void* context,
+    FlipperFormat* flipper_format);
+
+/**
+ * Getting a textual representation of the received data.
+ * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance
+ * @param output Resulting text
+ */
+void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output);

+ 37 - 12
lib/subghz/protocols/protocol_items.c

@@ -1,19 +1,44 @@
 #include "protocol_items.h"
 
 const SubGhzProtocol* subghz_protocol_registry_items[] = {
-    &subghz_protocol_gate_tx,       &subghz_protocol_keeloq,      &subghz_protocol_star_line,
-    &subghz_protocol_nice_flo,      &subghz_protocol_came,        &subghz_protocol_faac_slh,
-    &subghz_protocol_nice_flor_s,   &subghz_protocol_came_twee,   &subghz_protocol_came_atomo,
-    &subghz_protocol_nero_sketch,   &subghz_protocol_ido,         &subghz_protocol_kia,
-    &subghz_protocol_hormann,       &subghz_protocol_nero_radio,  &subghz_protocol_somfy_telis,
-    &subghz_protocol_somfy_keytis,  &subghz_protocol_scher_khan,  &subghz_protocol_princeton,
-    &subghz_protocol_raw,           &subghz_protocol_linear,      &subghz_protocol_secplus_v2,
-    &subghz_protocol_secplus_v1,    &subghz_protocol_megacode,    &subghz_protocol_holtek,
-    &subghz_protocol_chamb_code,    &subghz_protocol_power_smart, &subghz_protocol_marantec,
-    &subghz_protocol_bett,          &subghz_protocol_doitrand,    &subghz_protocol_phoenix_v2,
-    &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan,    &subghz_protocol_intertechno_v3,
-    &subghz_protocol_clemsa,        &subghz_protocol_ansonic,     &subghz_protocol_smc5326,
+    &subghz_protocol_gate_tx,
+    &subghz_protocol_keeloq,
+    &subghz_protocol_star_line,
+    &subghz_protocol_nice_flo,
+    &subghz_protocol_came,
+    &subghz_protocol_faac_slh,
+    &subghz_protocol_nice_flor_s,
+    &subghz_protocol_came_twee,
+    &subghz_protocol_came_atomo,
+    &subghz_protocol_nero_sketch,
+    &subghz_protocol_ido,
+    &subghz_protocol_kia,
+    &subghz_protocol_hormann,
+    &subghz_protocol_nero_radio,
+    &subghz_protocol_somfy_telis,
+    &subghz_protocol_somfy_keytis,
+    &subghz_protocol_scher_khan,
+    &subghz_protocol_princeton,
+    &subghz_protocol_raw,
+    &subghz_protocol_linear,
+    &subghz_protocol_secplus_v2,
+    &subghz_protocol_secplus_v1,
+    &subghz_protocol_megacode,
+    &subghz_protocol_holtek,
+    &subghz_protocol_chamb_code,
+    &subghz_protocol_power_smart,
+    &subghz_protocol_marantec,
+    &subghz_protocol_bett,
+    &subghz_protocol_doitrand,
+    &subghz_protocol_phoenix_v2,
+    &subghz_protocol_honeywell_wdb,
+    &subghz_protocol_magellan,
+    &subghz_protocol_intertechno_v3,
+    &subghz_protocol_clemsa,
+    &subghz_protocol_ansonic,
+    &subghz_protocol_smc5326,
     &subghz_protocol_holtek_th12x,
+    &subghz_protocol_linear_delta3,
 };
 
 const SubGhzProtocolRegistry subghz_protocol_registry = {

+ 1 - 0
lib/subghz/protocols/protocol_items.h

@@ -21,6 +21,7 @@
 #include "gate_tx.h"
 #include "raw.h"
 #include "linear.h"
+#include "linear_delta3.h"
 #include "secplus_v2.h"
 #include "secplus_v1.h"
 #include "megacode.h"

Неке датотеке нису приказане због велике количине промена