<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/15026">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">codec/ecu: Introduce new generic Error Concealment Unit abstraction<br><br>We don't want to expose the details of a given ECU implementation to<br>the user (e.g. osmo-bts), but have a generic abstraction layer where<br>an ECU implementation can simply register a few call-back functions<br>with the generic core.<br><br>As the developer and copyright holder of the related code, I hereby<br>state that any ECU implementation using 'struct osmo_ecu_ops' and<br>registering with the 'osmo_ecu_register()' function shall not be<br>considered as a derivative work under any applicable copyright law;<br>the copyleft terms of GPLv2 shall hence not apply to any such ECU<br>implementation.<br><br>The intent of the above exception is to allow anyone to combine<br>third party Error Concealment Unit implementations with libosmocore,<br>including but not limited to such published by ETSI.<br><br>Change-Id: I4d33c9c7c2d4c7462ff38a49c178b65accae1915<br>---<br>M include/osmocom/codec/ecu.h<br>M src/codec/Makefile.am<br>A src/codec/ecu.c<br>M src/codec/ecu_fr.c<br>M tests/codec/codec_ecu_fr_test.c<br>M tests/codec/codec_ecu_fr_test.ok<br>6 files changed, 445 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/26/15026/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/codec/ecu.h b/include/osmocom/codec/ecu.h</span><br><span>index f7a29a0..a566712 100644</span><br><span>--- a/include/osmocom/codec/ecu.h</span><br><span>+++ b/include/osmocom/codec/ecu.h</span><br><span>@@ -13,3 +13,57 @@</span><br><span> </span><br><span> void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, uint8_t *frame);</span><br><span> int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum osmo_ecu_codec {</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ECU_CODEC_HR,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ECU_CODEC_FR,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ECU_CODEC_EFR,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ECU_CODEC_AMR,</span><br><span style="color: hsl(120, 100%, 40%);">+   _NUM_OSMO_ECU_CODECS</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Generic ECU abstraction layer below</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* As the developer and copyright holder of the related code, I hereby</span><br><span style="color: hsl(120, 100%, 40%);">+ * state that any ECU implementation using 'struct osmo_ecu_ops' and</span><br><span style="color: hsl(120, 100%, 40%);">+ * registering with the 'osmo_ecu_register()' function shall not be</span><br><span style="color: hsl(120, 100%, 40%);">+ * considered as a derivative work under any applicable copyright law;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the copyleft terms of GPLv2 shall hence not apply to any such ECU</span><br><span style="color: hsl(120, 100%, 40%);">+ * implementation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The intent of the above exception is to allow anyone to combine third</span><br><span style="color: hsl(120, 100%, 40%);">+ * party Error Concealment Unit implementations with libosmocodec.</span><br><span style="color: hsl(120, 100%, 40%);">+ * including but not limited to such published by ETSI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   -- Harald Welte <laforge@gnumonks.org> on August 1, 2019.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ecu_state {</span><br><span style="color: hsl(120, 100%, 40%);">+   enum osmo_ecu_codec codec;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* initialize an ECU instance */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ecu_state *osmo_ecu_init(void *ctx, enum osmo_ecu_codec codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* destroy an ECU instance */</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_ecu_destroy(struct osmo_ecu_state *st);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* process a received frame a substitute/erroneous frame */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_frame_in(struct osmo_ecu_state *st, bool bfi,</span><br><span style="color: hsl(120, 100%, 40%);">+                const uint8_t *frame, unsigned int frame_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* generate output data for a substitute/erroneous frame */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ecu_ops {</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_ecu_state * (*init)(void *ctx, enum osmo_ecu_codec codec);</span><br><span style="color: hsl(120, 100%, 40%);">+        void (*destroy)(struct osmo_ecu_state *);</span><br><span style="color: hsl(120, 100%, 40%);">+     int (*frame_in)(struct osmo_ecu_state *st, bool bfi,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint8_t *frame, unsigned int frame_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+      int (*frame_out)(struct osmo_ecu_state *st, uint8_t *frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_register(const struct osmo_ecu_ops *ops, enum osmo_ecu_codec codec);</span><br><span>diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am</span><br><span>index b522d43..c9d7a22 100644</span><br><span>--- a/src/codec/Makefile.am</span><br><span>+++ b/src/codec/Makefile.am</span><br><span>@@ -13,6 +13,6 @@</span><br><span> </span><br><span> lib_LTLIBRARIES = libosmocodec.la</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu_fr.c</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu.c ecu_fr.c</span><br><span> libosmocodec_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined</span><br><span> libosmocodec_la_LIBADD = $(top_builddir)/src/libosmocore.la</span><br><span>diff --git a/src/codec/ecu.c b/src/codec/ecu.c</span><br><span>new file mode 100644</span><br><span>index 0000000..db7148c</span><br><span>--- /dev/null</span><br><span>+++ b/src/codec/ecu.c</span><br><span>@@ -0,0 +1,118 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Core infrastructure for ECU implementations */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* As the developer and copyright holder of the related code, I hereby</span><br><span style="color: hsl(120, 100%, 40%);">+ * state that any ECU implementation using 'struct osmo_ecu_ops' and</span><br><span style="color: hsl(120, 100%, 40%);">+ * registering with the 'osmo_ecu_register()' function shall not be</span><br><span style="color: hsl(120, 100%, 40%);">+ * considered as a derivative work under any applicable copyright law;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the copyleft terms of GPLv2 shall hence not apply to any such ECU</span><br><span style="color: hsl(120, 100%, 40%);">+ * implementation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The intent of the above exception is to allow anyone to combine third</span><br><span style="color: hsl(120, 100%, 40%);">+ * party Error Concealment Unit implementations with libosmocodec.</span><br><span style="color: hsl(120, 100%, 40%);">+ * including but not limited to such published by ETSI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   -- Harald Welte <laforge@gnumonks.org> on August 1, 2019.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/codec/ecu.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_ecu_ops *g_ecu_ops[_NUM_OSMO_ECU_CODECS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * high-level API for users</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! initialize an ECU instance for given codec.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from which to allocate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \parma[in] codec codec for which to initialize/create ECU */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ecu_state *osmo_ecu_init(void *ctx, enum osmo_ecu_codec codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (codec >= ARRAY_SIZE(g_ecu_ops))</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!g_ecu_ops[codec] || !g_ecu_ops[codec]->init)</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return g_ecu_ops[codec]->init(ctx, codec);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! destroy an ECU instance */</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_ecu_destroy(struct osmo_ecu_state *st)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (st->codec >= ARRAY_SIZE(g_ecu_ops))</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!g_ecu_ops[st->codec])</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!g_ecu_ops[st->codec]->destroy)</span><br><span style="color: hsl(120, 100%, 40%);">+             talloc_free(st);</span><br><span style="color: hsl(120, 100%, 40%);">+      else</span><br><span style="color: hsl(120, 100%, 40%);">+          g_ecu_ops[st->codec]->destroy(st);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! process a received frame a substitute/erroneous frame.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] st  ECU state/instance on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bfi Bad Frame Indication</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] frame received codec frame to be processed</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] frame_bytes number of bytes available in frame */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_frame_in(struct osmo_ecu_state *st, bool bfi,</span><br><span style="color: hsl(120, 100%, 40%);">+                      const uint8_t *frame, unsigned int frame_bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (st->codec >= ARRAY_SIZE(g_ecu_ops))</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!g_ecu_ops[st->codec])</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EBUSY;</span><br><span style="color: hsl(120, 100%, 40%);">+        return g_ecu_ops[st->codec]->frame_in(st, bfi, frame, frame_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! generate output data for a substitute/erroneous frame.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] st ECU state/instance on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] frame_out buffer for generated output frame</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return number of bytes written to frame_out; negative on error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (st->codec >= ARRAY_SIZE(g_ecu_ops))</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!g_ecu_ops[st->codec])</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EBUSY;</span><br><span style="color: hsl(120, 100%, 40%);">+        return g_ecu_ops[st->codec]->frame_out(st, frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * low-level API for ECU implementations</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! register an ECU implementation for a given codec */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ecu_register(const struct osmo_ecu_ops *ops, enum osmo_ecu_codec codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (codec >= ARRAY_SIZE(g_ecu_ops))</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (g_ecu_ops[codec])</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EBUSY;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      g_ecu_ops[codec] = ops;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/codec/ecu_fr.c b/src/codec/ecu_fr.c</span><br><span>index 20a0f89..a32ea2e 100644</span><br><span>--- a/src/codec/ecu_fr.c</span><br><span>+++ b/src/codec/ecu_fr.c</span><br><span>@@ -164,3 +164,54 @@</span><br><span> </span><br><span>         return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Integration with ECU core</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_ecu_state *ecu_fr_init(void *ctx, enum osmo_ecu_codec codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_ecu_state *st;</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t size = sizeof(*st) + sizeof(struct osmo_ecu_fr_state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       st = talloc_named_const(ctx, size, "ecu_state_FR");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!st)</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(st, 0, size);</span><br><span style="color: hsl(120, 100%, 40%);">+  st->codec = codec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return st;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int ecu_fr_frame_in(struct osmo_ecu_state *st, bool bfi, const uint8_t *frame,</span><br><span style="color: hsl(120, 100%, 40%);">+                           unsigned int frame_bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_ecu_fr_state *fr = (struct osmo_ecu_fr_state *) &st->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bfi)</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_ecu_fr_reset(fr, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int ecu_fr_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_ecu_fr_state *fr = (struct osmo_ecu_fr_state *) &st->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (osmo_ecu_fr_conceal(fr, frame_out) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+          return GSM_FR_BYTES;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_ecu_ops osmo_ecu_ops_fr = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .init = ecu_fr_init,</span><br><span style="color: hsl(120, 100%, 40%);">+  .frame_in = ecu_fr_frame_in,</span><br><span style="color: hsl(120, 100%, 40%);">+  .frame_out = ecu_fr_frame_out,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static __attribute__((constructor)) void on_dso_load_ecu_fr(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_ecu_register(&osmo_ecu_ops_fr, OSMO_ECU_CODEC_FR);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/codec/codec_ecu_fr_test.c b/tests/codec/codec_ecu_fr_test.c</span><br><span>index 3561c44..6520935 100644</span><br><span>--- a/tests/codec/codec_ecu_fr_test.c</span><br><span>+++ b/tests/codec/codec_ecu_fr_test.c</span><br><span>@@ -113,6 +113,8 @@</span><br><span>        int i, rc;</span><br><span>   int j = 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        printf("=> Testing FR concealment (simple, consecutive bad frames)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       while (sample_frame_hex[j] != NULL) {</span><br><span>                /* Parse frame from string to hex */</span><br><span>                 osmo_hexparse(sample_frame_hex[j], frame, GSM_FR_BYTES);</span><br><span>@@ -148,6 +150,8 @@</span><br><span>       unsigned int frame_len;</span><br><span>      int rc, i = 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    printf("\n=> Testing FR concealment (realistic, various bad frames)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      while (fr_frames_hex[i] != NULL) {</span><br><span>           /* Debug print */</span><br><span>            printf("Frame No. %03i:\n", i);</span><br><span>@@ -174,11 +178,52 @@</span><br><span>    }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Simulate a real life situation: voice frames with a few dropouts, using generic core */</span><br><span style="color: hsl(120, 100%, 40%);">+void test_fr_concealment_realistic_core()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_ecu_state *state = osmo_ecu_init(NULL, OSMO_ECU_CODEC_FR);</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t frame[GSM_FR_BYTES];</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int frame_len;</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc, i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\n=> Testing FR concealment (realistic, using ECU abstraction)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(frame);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (fr_frames_hex[i] != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Debug print */</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("Frame No. %03i:\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Good or bad frame? */</span><br><span style="color: hsl(120, 100%, 40%);">+              frame_len = strlen(fr_frames_hex[i]) / 2;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (frame_len == GSM_FR_BYTES) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf(" * input:  %s\n", fr_frames_hex[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+                        osmo_hexparse(fr_frames_hex[i], frame, GSM_FR_BYTES);</span><br><span style="color: hsl(120, 100%, 40%);">+                 osmo_ecu_frame_in(state, false, frame, GSM_FR_BYTES);</span><br><span style="color: hsl(120, 100%, 40%);">+         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf(" * input:  (bad)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                       memset(frame, 0x00, GSM_FR_BYTES);</span><br><span style="color: hsl(120, 100%, 40%);">+                    osmo_ecu_frame_in(state, true, frame, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = osmo_ecu_frame_out(state, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+                        OSMO_ASSERT(rc == GSM_FR_BYTES);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Print result */</span><br><span style="color: hsl(120, 100%, 40%);">+            printf(" * output: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_hexdump_nospc(frame, GSM_FR_BYTES));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Go to the next frame */</span><br><span style="color: hsl(120, 100%, 40%);">+            i++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>     /* Perform actual tests */</span><br><span>   test_fr_concealment();</span><br><span>       test_fr_concealment_realistic();</span><br><span style="color: hsl(120, 100%, 40%);">+      test_fr_concealment_realistic_core();</span><br><span> </span><br><span>    return 0;</span><br><span> }</span><br><span>diff --git a/tests/codec/codec_ecu_fr_test.ok b/tests/codec/codec_ecu_fr_test.ok</span><br><span>index 3cc35af..30163a9 100644</span><br><span>--- a/tests/codec/codec_ecu_fr_test.ok</span><br><span>+++ b/tests/codec/codec_ecu_fr_test.ok</span><br><span>@@ -1,3 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=> Testing FR concealment (simple, consecutive bad frames)</span><br><span> Start with: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da, XMAXC: [3f, 3f, 3f, 3f]</span><br><span> conceal: 00, result: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da XMAXC: [3f, 3f, 3f, 3f]</span><br><span> conceal: 01, result: d9ec9be212901d802335598c501d805bad3d4ba01d809b69df5a501d809cd1b4da XMAXC: [3b, 3b, 3b, 3b]</span><br><span>@@ -40,6 +41,181 @@</span><br><span> conceal: 17, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]</span><br><span> conceal: 18, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]</span><br><span> conceal: 19, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=> Testing FR concealment (realistic, various bad frames)</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 000:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 001:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8eb83699a66c036ec89b7246e6034dc8d48948620589b7256e3a6603b2371b8da</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8eb83699a66c036ec89b7246e6034dc8d48948620589b7256e3a6603b2371b8da</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 002:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d967abaa1cbe4035238da6ace4c036d46ec69ba600391c4eb8a2b040591c6a3924</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d967abaa1cbe4035238da6ace4c036d46ec69ba600391c4eb8a2b040591c6a3924</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 003:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8e8a42662c240472469b91bd2e0452291b6dba600495b8e38dcb020491a71c91b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8e8a42662c240472469b91bd2e0452291b6dba600495b8e38dcb020491a71c91b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 004:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  da2aac1ddbb00036e46e26dcec6039138db923822047137248e3560048e38dc8e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: da2aac1ddbb00036e46e26dcec6039138db923822047137248e3560048e38dc8e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 005:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d929ab2a9b5240395b6dc72ba020469c8d551c5440349c9148e36a4036a372471b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d929ab2a9b5240395b6dc72ba020469c8d551c5440349c9148e36a4036a372471b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 006:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9eb93215bb8a0271c69c724682036db71c71a94a0372491b72bee4044eb71b923</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9eb93215bb8a0271c69c724682036db71c71a94a0372491b72bee4044eb71b923</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 007:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9ab9aa19abc40391b6e5ae2ee40471b91c6dbe820492291b8e4b84036e47238db</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9ab9aa19abc40391b6e5ae2ee40471b91c6dbe820492291b8e4b84036e47238db</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 008:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d96b9be9db782044e371b55cb200389491c69b8ea034e271c8d3808038ec6db8e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d96b9be9db782044e371b55cb200389491c69b8ea034e271c8d3808038ec6db8e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 009:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 010:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 011:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9ea9c219ce60046e38d3724e0c034e56e36eb7e0038d471b8dcb260491b8dbb23</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9ea9c219ce60046e38d3724e0c034e56e36eb7e0038d471b8dcb260491b8dbb23</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 012:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9e89be9d9e0a0391b6dd6a4624029247138e3a2a04713922524de0036db69d91c</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9e89be9d9e0a0391b6dd6a4624029247138e3a2a04713922524de0036db69d91c</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 013:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9699422a2b6a048dd90c91c6a802b6259395c8880575b4a58e4ac20269d7248d4</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9699422a2b6a048dd90c91c6a802b6259395c8880575b4a58e4ac20269d7248d4</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 014:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d967ac5b1baae0371c71b8ab9c804a9e8e58a55a8038626ec8dcb640395c7244dc</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d967ac5b1baae0371c71b8ab9c804a9e8e58a55a8038626ec8dcb640395c7244dc</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 015:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9e8a3e262e68027638db52b88a038634e471a7ec049136e3b1bc8402923adcad2</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9e8a3e262e68027638db52b88a038634e471a7ec049136e3b1bc8402923adcad2</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 016:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8eab36e1bbe0046e34d491b608035137658d3524044e48e375cdac0472b9238d4</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8eab36e1bbe0046e34d491b608035137658d3524044e48e375cdac0472b9238d4</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 017:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 018:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 019:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 020:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8e6a2e1d3d2605b1376c8d35280392451391cbc80392a71b6db8aa049238dc8ab</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8e6a2e1d3d2605b1376c8d35280392451391cbc80392a71b6db8aa049238dc8ab</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 021:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9a87ba1a3982048eb8a471cac00472b4e391bbc40292489b71cc200495b8d3ae3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9a87ba1a3982048eb8a471cac00472b4e391bbc40292489b71cc200495b8d3ae3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 022:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9278b2a1ba4c0475b8dc722d6e0491b5228da70204ae36dc71d94a056a29236e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9278b2a1ba4c0475b8dc722d6e0491b5228da70204ae36dc71d94a056a29236e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 023:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9ec9be2129520392335598c50c04b5bad3d4ba680789b69df5a5aa0469cd1b4da</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9ec9be2129520392335598c50c04b5bad3d4ba680789b69df5a5aa0469cd1b4da</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 024:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8ea932623e660669b8e4a9dd8a03aa32a76e466e028d396cc9bbe4047256dc8e5</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8ea932623e660669b8e4a9dd8a03aa32a76e466e028d396cc9bbe4047256dc8e5</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 025:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d96a94215aa0403aab713f22e8e024e68db91ab6a027abd1a55b6e804aec9146e4</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d96a94215aa0403aab713f22e8e024e68db91ab6a027abd1a55b6e804aec9146e4</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 026:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d867ac21e270a0350d6ac91a724037247246d2a6c0396c89d6dc562049244e48d5</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d867ac21e270a0350d6ac91a724037247246d2a6c0396c89d6dc562049244e48d5</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 027:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8a9b460d3b48026a4ad471b7c20452491b69bbc803ae48db722ee00292491a8db</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8a9b460d3b48026a4ad471b7c20452491b69bbc803ae48db722ee00292491a8db</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 028:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d928a3e1d3b24036e37244abf02047634d371b74c047637148a29ac03b234e38e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d928a3e1d3b24036e37244abf02047634d371b74c047637148a29ac03b234e38e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 029:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9ab9b21d2e0c0471c693aec54e044dbae46dc7c20391badb724ee8038e469bb15</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9ab9b21d2e0c0471c693aec54e044dbae46dc7c20391badb724ee8038e469bb15</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 030:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 031:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 032:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 033:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 034:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 035:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 036:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d00000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 037:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d92c8b6d5aee4034ebb22724862047145634a5c0a038e371b8e4a880485c89dd25</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d92c8b6d5aee4034ebb22724862047145634a5c0a038e371b8e4a880485c89dd25</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 038:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8e78b29e3c6c038dba9d91beca04723ad491cda80471471b6ec7ae03b1396b91b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8e78b29e3c6c038dba9d91beca04723ad491cda80471471b6ec7ae03b1396b91b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 039:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8a78b25e37a0022dd8a46dc68a0351bad391bde2046e56dd8dc96c038e396d89b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8a78b25e37a0022dd8a46dc68a0351bad391bde2046e56dd8dc96c038e396d89b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 040:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8a88c255ab6e038e38e48dbde8038ad8dc8db8ec0376372b564b44038e49234dc</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8a88c255ab6e038e38e48dbde8038ad8dc8db8ec0376372b564b44038e49234dc</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 041:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 042:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8ee9bea5ae4003ae371b713eae05adc91995a5ea064dcc9571e786026ed51c52c</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8ee9bea5ae4003ae371b713eae05adc91995a5ea064dcc9571e786026ed51c52c</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 043:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 044:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d92aab696190c046e26e392cae0026a376a8dc662048d291b75b54c04ad3ae3b1b</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d92aab696190c046e26e392cae0026a376a8dc662048d291b75b54c04ad3ae3b1b</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 045:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8e7a469627a6038e289cb1baca0569b8db6dddec026dc8e38e5dc803722722d23</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8e7a469627a6038e289cb1baca0569b8db6dddec026dc8e38e5dc803722722d23</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 046:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 047:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  (bad)</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 048:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d7299c19a3be8024e58ea7a49f20a522963ad976e0a76ecd92b38500cb62aa4c94</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d7299c19a3be8024e58ea7a49f20a522963ad976e0a76ecd92b38500cb62aa4c94</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 049:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d7eb6c6262eee02b2c42e79a60a0aa55aed68a7f00ad358e10fad960e55a39396d</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d7eb6c6262eee02b2c42e79a60a0aa55aed68a7f00ad358e10fad960e55a39396d</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 050:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d970858dd2ab61d91355ebc15ca1a6a7ca48a05cc0dae66f2523c2a1bad3825daa</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d970858dd2ab61d91355ebc15ca1a6a7ca48a05cc0dae66f2523c2a1bad3825daa</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 051:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d8f0844a23ad20da50d6de025e81c37392b9039cc0c764c1bd1e94c1b699736a98</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d8f0844a23ad20da50d6de025e81c37392b9039cc0c764c1bd1e94c1b699736a98</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 052:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 053:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 054:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 055:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763</span><br><span style="color: hsl(120, 100%, 40%);">+Frame No. 056:</span><br><span style="color: hsl(120, 100%, 40%);">+ * input:  d2577a1cda50004924924924500049249249245000492492492450004923924924</span><br><span style="color: hsl(120, 100%, 40%);">+ * output: d2577a1cda50004924924924500049249249245000492492492450004923924924</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=> Testing FR concealment (realistic, using ECU abstraction)</span><br><span> Frame No. 000:</span><br><span>  * input:  d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723</span><br><span>  * output: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/15026">change 15026</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/15026"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I4d33c9c7c2d4c7462ff38a49c178b65accae1915 </div>
<div style="display:none"> Gerrit-Change-Number: 15026 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>