Просмотр исходного кода

Message building: fields types and functions.

antirez 3 лет назад
Родитель
Сommit
03f56561ae

+ 81 - 27
app.h

@@ -30,7 +30,12 @@
 
 #define DEBUG_MSG 1
 
+/* Forward declarations. */
+
 typedef struct ProtoViewApp ProtoViewApp;
+typedef struct ProtoViewMsgInfo ProtoViewMsgInfo;
+
+/* ============================== enumerations ============================== */
 
 /* Subghz system state */
 typedef enum {
@@ -55,6 +60,8 @@ typedef enum {
     ViewGoPrev,
 } ProtoViewCurrentView;
 
+/* ================================== RX/TX ================================= */
+
 typedef struct {
     const char *name;               // Name to show to the user.
     const char *id;                 // Identifier in the Flipper API/file.
@@ -88,34 +95,8 @@ struct ProtoViewTxRx {
 
 typedef struct ProtoViewTxRx ProtoViewTxRx;
 
-/* This stucture is filled by the decoder for specific protocols with the
- * informations about the message. ProtoView will display such information
- * in the message info view. */
-#define PROTOVIEW_MSG_STR_LEN 32
-typedef struct ProtoViewMsgInfo {
-    char name[PROTOVIEW_MSG_STR_LEN]; /* Protocol name and version. */
-    char raw[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific raw representation.*/
-    /* The following is what the decoder wants to show to user. Each decoder
-     * can use the number of fileds it needs. */
-    char info1[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 1. */
-    char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */
-    char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */
-    char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */
-    /* Low level information of the detected signal: the following are filled
-     * by the protocol decoding function: */
-    uint32_t start_off;         /* Pulses start offset in the bitmap. */
-    uint32_t pulses_count;      /* Number of pulses of the full message. */
-    /* The following are passed already filled to the decoder. */
-    uint32_t short_pulse_dur;   /* Microseconds duration of the short pulse. */
-    /* The following are filled by ProtoView core after the decoder returned
-     * success. */
-    uint8_t *bits;              /* Bitmap with the signal. */
-    uint32_t bits_bytes;        /* Number of full bytes in the bitmap, that
-                                   is 'pulses_count/8' rounded to the next
-                                   integer. */
-} ProtoViewMsgInfo;
+/* ============================== Main app state ============================ */
 
-/* Our main application context. */
 #define ALERT_MAX_LEN 32
 struct ProtoViewApp {
     /* GUI */
@@ -174,6 +155,68 @@ struct ProtoViewApp {
                                 ProtoViewModulations table. */
 };
 
+/* =========================== Protocols decoders =========================== */
+
+/* This stucture is filled by the decoder for specific protocols with the
+ * informations about the message. ProtoView will display such information
+ * in the message info view. */
+#define PROTOVIEW_MSG_STR_LEN 32
+typedef struct ProtoViewMsgInfo {
+    char name[PROTOVIEW_MSG_STR_LEN]; /* Protocol name and version. */
+    char raw[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific raw representation.*/
+    /* The following is what the decoder wants to show to user. Each decoder
+     * can use the number of fileds it needs. */
+    char info1[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 1. */
+    char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */
+    char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */
+    char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */
+    /* Low level information of the detected signal: the following are filled
+     * by the protocol decoding function: */
+    uint32_t start_off;         /* Pulses start offset in the bitmap. */
+    uint32_t pulses_count;      /* Number of pulses of the full message. */
+    /* The following are passed already filled to the decoder. */
+    uint32_t short_pulse_dur;   /* Microseconds duration of the short pulse. */
+    /* The following are filled by ProtoView core after the decoder returned
+     * success. */
+    uint8_t *bits;              /* Bitmap with the signal. */
+    uint32_t bits_bytes;        /* Number of full bytes in the bitmap, that
+                                   is 'pulses_count/8' rounded to the next
+                                   integer. */
+} ProtoViewMsgInfo;
+
+/* This structures describe a set of protocol fields. It is used by decoders
+ * supporting message building to receive and return information about the
+ * protocol. */
+typedef enum {
+    FieldTypeStr,
+    FieldTypeSignedInt,
+    FieldTypeUnsignedInt,
+    FieldTypeBytes,
+    FieldTypeFloat,
+} ProtoViewFieldType;
+
+typedef struct {
+    ProtoViewFieldType type;
+    uint32_t len;       // Depends on type:
+                        // Bits for integers.
+                        // Number of characters for strings.
+                        // Number of nibbles for bytes (1 for each 4 bits).
+                        // Not used for floats.
+    char *name;         // Field name.
+    union {
+        char *str;          // String type.
+        int64_t value;      // Signed integer type.
+        uint64_t uvalue;    // Unsigned integer type.
+        uint8_t *bytes;     // Raw bytes type.
+        float fvalue;       // Float type.
+    };
+} ProtoViewField;
+
+typedef struct {
+    ProtoViewField **fields;
+    uint32_t numfields;
+} ProtoViewFieldSet;
+
 typedef struct ProtoViewDecoder {
     const char *name;   /* Protocol name. */
     /* The decode function takes a buffer that is actually a bitmap, with
@@ -184,6 +227,8 @@ typedef struct ProtoViewDecoder {
      * functions that perform bit extraction with bound checking, such as
      * bitmap_get() and so forth. */
     bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info);
+    void (*get_fields)(ProtoViewMsgInfo *info, ProtoViewFieldSet *fields);
+    void (*build_message)(RawSamplesBuffer *samples, ProtoViewFieldSet *fields);
 } ProtoViewDecoder;
 
 extern RawSamplesBuffer *RawSamples, *DetectedSamples;
@@ -242,5 +287,14 @@ void ui_dismiss_alert(ProtoViewApp *app);
 void ui_draw_alert_if_needed(Canvas *canvas, ProtoViewApp *app);
 void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color);
 
+/* fields.c */
+void fieldset_free_set(ProtoViewFieldSet *fs);
+ProtoViewFieldSet *fieldset_new(void);
+void fieldset_add_int(ProtoViewFieldSet *fs, const char *name, int64_t val, uint8_t bits);
+void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits);
+void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s);
+void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count);
+void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val);
+
 /* crc.c */
 uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly);

+ 90 - 0
fields.c

@@ -0,0 +1,90 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license.
+ *
+ * Protocol fields implementation. */
+
+#include "app.h"
+
+/* Create a new field of the specified type. Without populating its
+ * type-specific value. */
+static ProtoViewField *field_new(ProtoViewFieldType type, const char *name) {
+    ProtoViewField *f = malloc(sizeof(*f));
+    f->type = type;
+    f->name = strdup(name);
+    return f;
+}
+
+/* Free a field an associated data. */
+static void field_free(ProtoViewField *f) {
+    free(f->name);
+    switch(f->type) {
+    case FieldTypeStr: free(f->str); break;
+    case FieldTypeBytes: free(f->bytes); break;
+    default: break; // Nothing to free for other types.
+    }
+    free(f);
+}
+
+/* Free a field set and its contained fields. */
+void fieldset_free_set(ProtoViewFieldSet *fs) {
+    for (uint32_t j = 0; j < fs->numfields; j++)
+        field_free(fs->fields[j]);
+    free(fs->fields);
+    free(fs);
+}
+
+/* Allocate and init an empty field set. */
+ProtoViewFieldSet *fieldset_new(void) {
+    ProtoViewFieldSet *fs = malloc(sizeof(*fs));
+    fs->numfields = 0;
+    fs->fields = NULL;
+    return fs;
+}
+
+/* Append an already allocated field at the end of the specified field set. */
+static void fieldset_add_field(ProtoViewFieldSet *fs, ProtoViewField *field) {
+    fs->numfields++;
+    fs->fields = realloc(fs->fields,sizeof(ProtoViewField*)*fs->numfields);
+    fs->fields[fs->numfields-1] = field;
+}
+
+/* Allocate and append an integer field. */
+void fieldset_add_int(ProtoViewFieldSet *fs, const char *name, int64_t val, uint8_t bits) {
+    ProtoViewField *f = field_new(FieldTypeSignedInt,name);
+    f->value = val;
+    f->len = bits;
+    fieldset_add_field(fs,f);
+}
+
+/* Allocate and append an unsigned field. */
+void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) {
+    ProtoViewField *f = field_new(FieldTypeUnsignedInt,name);
+    f->uvalue = uval;
+    f->len = bits;
+    fieldset_add_field(fs,f);
+}
+
+/* Allocate and append a string field. */
+void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s) {
+    ProtoViewField *f = field_new(FieldTypeStr,name);
+    f->str = strdup(s);
+    f->len = strlen(s);
+    fieldset_add_field(fs,f);
+}
+
+/* Allocate and append a bytes field. */
+void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count) {
+    ProtoViewField *f = field_new(FieldTypeBytes,name);
+    f->bytes = malloc(count);
+    memcpy(f->bytes,bytes,count);
+    f->len = count;
+    fieldset_add_field(fs,f);
+}
+
+/* Allocate and append a float field. */
+void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val) {
+    ProtoViewField *f = field_new(FieldTypeFloat,name);
+    f->fvalue = val;
+    f->len = 0; // Not used for floats
+    fieldset_add_field(fs,f);
+}

+ 4 - 1
protocols/b4b1.c

@@ -46,5 +46,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder B4B1Decoder = {
-    "B4B1", decode
+    .name = "B4B1",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/keeloq.c

@@ -87,5 +87,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder KeeloqDecoder = {
-    "Keeloq", decode
+    .name = "Keeloq",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/oregon2.c

@@ -63,5 +63,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder Oregon2Decoder = {
-    "Oregon2", decode
+    .name = "Oregon2",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/citroen.c

@@ -59,5 +59,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder CitroenTPMSDecoder = {
-    "Citroen TPMS", decode
+    .name = "Citroen TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/ford.c

@@ -63,5 +63,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder FordTPMSDecoder = {
-    "Ford TPMS", decode
+    .name = "Ford TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/renault.c

@@ -65,5 +65,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder RenaultTPMSDecoder = {
-    "Renault TPMS", decode
+    .name = "Renault TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/schrader.c

@@ -64,5 +64,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder SchraderTPMSDecoder = {
-    "Schrader TPMS", decode
+    .name = "Schrader TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/schrader_eg53ma4.c

@@ -62,5 +62,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder SchraderEG53MA4TPMSDecoder = {
-    "Schrader EG53MA4 TPMS", decode
+    .name = "Schrader EG53MA4 TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };

+ 4 - 1
protocols/tpms/toyota.c

@@ -87,5 +87,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 }
 
 ProtoViewDecoder ToyotaTPMSDecoder = {
-    "Toyota TPMS", decode
+    .name = "Toyota TPMS",
+    .decode = decode,
+    .get_fields = NULL,
+    .build_message = NULL
 };