<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmo-abis/+/18250">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add new TRAU frame sync code<br><br>This code is able to detect and sync against a variety of TRAU<br>frame sync patterns.  Focus is so far on those patterns present on<br>16k sub-slots, but 8k sub-slots are expected to be supported soon,<br>too.<br><br>A new codebase for this is required as the old OsmoNITB code had<br>conflated a 16k sub-slot multiplexer with TRAU frame synchronization,<br>so there was no way to separate those two parts and hence no way to<br>support 8k sub-slots.<br><br>Change-Id: Ia6fe6228b0b8b9a27999f37ce1115ed5558881ea<br>---<br>M include/Makefile.am<br>A include/osmocom/trau/trau_sync.h<br>M src/Makefile.am<br>A src/trau/trau_sync.c<br>A src/trau/ubit_buf.h<br>M tests/Makefile.am<br>M tests/testsuite.at<br>A tests/trau_sync/trau_sync_test.c<br>A tests/trau_sync/trau_sync_test.err<br>A tests/trau_sync/trau_sync_test.ok<br>10 files changed, 712 insertions(+), 4 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index aa735c5..2a99211 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -5,4 +5,5 @@</span><br><span>  osmocom/abis/subchan_demux.h osmocom/abis/e1_input.h                       \</span><br><span>  osmocom/abis/lapd.h osmocom/abis/lapd_pcap.h osmocom/trau/osmo_ortp.h     \</span><br><span>  osmocom/abis/unixsocket_proto.h \</span><br><span style="color: hsl(0, 100%, 40%);">- osmocom/trau/trau_frame.h</span><br><span style="color: hsl(120, 100%, 40%);">+ osmocom/trau/trau_frame.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmocom/trau/trau_sync.h</span><br><span>diff --git a/include/osmocom/trau/trau_sync.h b/include/osmocom/trau/trau_sync.h</span><br><span>new file mode 100644</span><br><span>index 0000000..46595be</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/trau/trau_sync.h</span><br><span>@@ -0,0 +1,19 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum osmo_tray_sync_pat_id {</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU_SYNCP_16_FR_EFR,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU_SYNCP_8_HR,</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_TRAU_SYNCP_8_AMR_LOW,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU_SYNCP_8_AMR_6K7,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU_SYNCP_8_AMR_7K4,</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%);">+typedef void (*frame_out_cb_t)(void *user_data, const ubit_t *bits, unsigned int num_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_fsm_inst *</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_trau_sync_alloc(void *ctx, const char *name, frame_out_cb_t frame_out_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+                    enum osmo_tray_sync_pat_id pat_id, void *user_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_trau_sync_rx_ubits(struct osmo_fsm_inst *fi, const ubit_t *bits, size_t n_bits);</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index d1743af..0134b00 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -36,4 +36,7 @@</span><br><span> libosmotrau_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(TRAU_LIBVERSION)</span><br><span> libosmotrau_la_LIBADD = $(COMMONLIBS) $(ORTP_LIBS)</span><br><span> libosmotrau_la_SOURCES = trau/osmo_ortp.c \</span><br><span style="color: hsl(0, 100%, 40%);">-                     trau/trau_frame.c</span><br><span style="color: hsl(120, 100%, 40%);">+                     trau/trau_frame.c \</span><br><span style="color: hsl(120, 100%, 40%);">+                   trau/trau_sync.c</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+noinst_HEADERS = trau/ubit_buf.h</span><br><span>diff --git a/src/trau/trau_sync.c b/src/trau/trau_sync.c</span><br><span>new file mode 100644</span><br><span>index 0000000..c4baad6</span><br><span>--- /dev/null</span><br><span>+++ b/src/trau/trau_sync.c</span><br><span>@@ -0,0 +1,522 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* GSM A-bis TRAU frame synchronization as per TS 48.060 / 48.061 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2020 by Harald Welte <laforge@gnumonks.org></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%);">+ * SPDX-License-Identifier: GPL-2.0+</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</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</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%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ubit_buf.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/trau/trau_sync.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define S(x)        (1 << (x))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_TRAU_BYTES      40</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define T_SYNC            1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct sync_pattern {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* provided by user */</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *name;                               /*!< human-readable name */</span><br><span style="color: hsl(120, 100%, 40%);">+        const uint8_t byte_pattern[MAX_TRAU_BYTES];     /*!< bytes to match against */</span><br><span style="color: hsl(120, 100%, 40%);">+     const uint8_t byte_mask[MAX_TRAU_BYTES];        /*!< mask applied before matching */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t byte_len;                               /*!< length of mask in bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* generated by code */</span><br><span style="color: hsl(120, 100%, 40%);">+       ubit_t ubit_pattern[MAX_TRAU_BYTES*8];          /*!< bits to match against */</span><br><span style="color: hsl(120, 100%, 40%);">+      ubit_t ubit_mask[MAX_TRAU_BYTES*8];             /*!< mask applied before matching */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t bitcount;                               /*!< number of high bits in mask */</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 sync_pattern sync_patterns[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  [OSMO_TRAU_SYNCP_16_FR_EFR] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* TS 08.60 Section 4.8.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "FR/EFR",</span><br><span style="color: hsl(120, 100%, 40%);">+           .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        0xff, 0xff, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_len = 40,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [OSMO_TRAU_SYNCP_8_HR] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* TS 08.61 Section 6.8.2.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "HR8",</span><br><span style="color: hsl(120, 100%, 40%);">+              .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x00, 0x80, 0x40, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        0xff, 0x80, 0xC0, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_len = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [OSMO_TRAU_SYNCP_8_AMR_LOW] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* TS 08.61 Section 6.8.2.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+              /* The frame synchronisation for No_Speech frames and the speech frames of the three lower codec modes */</span><br><span style="color: hsl(120, 100%, 40%);">+             .name = "AMR8_LOW",</span><br><span style="color: hsl(120, 100%, 40%);">+         .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x00, 0x80, 0x80, 0x40,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        0xff, 0x80, 0x80, 0xC0,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_len = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [OSMO_TRAU_SYNCP_8_AMR_6K7] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* The frame synchronisation for the speech frames for codec mode 6,70 kBit/s */</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "AMR8_67",</span><br><span style="color: hsl(120, 100%, 40%);">+          .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x00, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        0xff, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x80, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_len = 20</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    [OSMO_TRAU_SYNCP_8_AMR_7K4] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* The frame synchronisation for the speech frames for codec mode 7,40 kBit/s */</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "AMR8_74",</span><br><span style="color: hsl(120, 100%, 40%);">+          .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x20, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        0xe0, 0x80, 0x80, 0x80,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x00, 0x00, 0x00, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .byte_len = 20,</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%);">+#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+static struct sync_pattern rbs_ccu_sync_ind_16_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .name ="RBS_CCU_SYNC_IND_16",</span><br><span style="color: hsl(120, 100%, 40%);">+       .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+             0x00, 0x00, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               0x00, 0x00, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               0x01, 0x00, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                0xff, 0xff, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               0x01, 0x00, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+               0x01, 0x00, 0x01, 0x00,</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%);">+static struct sync_pattern rbs_ccu_data_ind_16_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+  .name ="RBS_CCU_DATA_IND_16",</span><br><span style="color: hsl(120, 100%, 40%);">+       .byte_pattern = {</span><br><span style="color: hsl(120, 100%, 40%);">+             0x00, 0x00, 0x01, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .byte_mask = {</span><br><span style="color: hsl(120, 100%, 40%);">+                0xff, 0xff, 0x01, 0x00,</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%);">+#endif</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 void expand_sync_pattern(struct sync_pattern *pat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_pbit2ubit(pat->ubit_pattern, pat->byte_pattern, pat->byte_len*8);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_pbit2ubit(pat->ubit_mask, pat->byte_mask, pat->byte_len*8);</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 unsigned int count_one_bits(const ubit_t *in, unsigned int in_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i, count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < in_bits; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (in[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                    count++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return count;</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 void sync_pattern_register(struct sync_pattern *p)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      expand_sync_pattern(p);</span><br><span style="color: hsl(120, 100%, 40%);">+       p->bitcount = count_one_bits(p->ubit_mask, p->byte_len*8);</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%);">+#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+/*! correlate pattern with unpacked bits from buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] pattern sync_pattern against which we shall compare</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bits unpacked bits to compare against pattern</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] num_bits number of unpacked bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns number of bits not matching pattern; -1 if insufficient bits available. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int correlate_pattern_ubits(const struct sync_pattern *pattern,</span><br><span style="color: hsl(120, 100%, 40%);">+                                const ubit_t *bits, size_t num_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int i, num_wrong = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (num_bits < pattern->byte_len*8)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1; /* insufficient data */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < pattern->byte_len *8; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* if mask doesn't contain '1', we can skip this octet */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!pattern->ubit_mask)</span><br><span style="color: hsl(120, 100%, 40%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (bits[i] != pattern->ubit_pattern[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                   num_wrong++;</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%);">+   return num_wrong;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct trau_rx_sync_state {</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! call-back to be called for every TRAU frame (called with</span><br><span style="color: hsl(120, 100%, 40%);">+   * bits=NULL in case of frame sync loss */</span><br><span style="color: hsl(120, 100%, 40%);">+    frame_out_cb_t out_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+        /*! opaque user data; passed to out_cb */</span><br><span style="color: hsl(120, 100%, 40%);">+     void *user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! history of received bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       ubit_t history[MAX_TRAU_BYTES*8+1]; /* +1 not required, but helps to expose bugs */</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! index of next-to-be-written ubit in history */</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int history_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+     /*! the pattern we are trying to sync to */</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct sync_pattern *pattern;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! number of consecutive frames without sync */</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int num_consecutive_errors;</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%);">+/* correlate the history (up to the last received bit) against the pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+static int correlate_history_against_pattern(struct trau_rx_sync_state *tss)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct sync_pattern *pattern = tss->pattern;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, start, num_wrong = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* compute index of first bit in history array */</span><br><span style="color: hsl(120, 100%, 40%);">+     start = (ARRAY_SIZE(tss->history) + tss->history_idx - pattern->byte_len*8)</span><br><span style="color: hsl(120, 100%, 40%);">+          % ARRAY_SIZE(tss->history);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(ARRAY_SIZE(tss->history) >= pattern->byte_len*8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < pattern->byte_len*8; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             unsigned int pos = (start + i) % ARRAY_SIZE(tss->history);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* if mask doesn't contain '1', we can skip this octet */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!pattern->ubit_mask[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (tss->history[pos] != pattern->ubit_pattern[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                      num_wrong++;</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%);">+   return num_wrong;</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%);">+/* add (append) one ubit to the history; wrap as needed */</span><br><span style="color: hsl(120, 100%, 40%);">+static void rx_history_add_bit(struct trau_rx_sync_state *tss, ubit_t bit)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     tss->history[tss->history_idx] = bit;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* simply wrap around at the end */</span><br><span style="color: hsl(120, 100%, 40%);">+   tss->history_idx = (tss->history_idx + 1) % ARRAY_SIZE(tss->history);</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%);">+/* append bits to history. We assume that this does NOT wrap */</span><br><span style="color: hsl(120, 100%, 40%);">+static void rx_history_add_bits(struct trau_rx_sync_state *tss, const ubit_t *bits, size_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int frame_bits_remaining = tss->pattern->byte_len*8 - tss->history_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(frame_bits_remaining >= n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(&tss->history[tss->history_idx], bits, n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+      tss->history_idx = tss->history_idx + n_bits;</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%);">+/* align the history, i.e. next received bit is start of frame */</span><br><span style="color: hsl(120, 100%, 40%);">+static void rx_history_align(struct trau_rx_sync_state *tss)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  ubit_t tmp[sizeof(tss->history)];</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t history_size = sizeof(tss->history);</span><br><span style="color: hsl(120, 100%, 40%);">+        size_t pattern_bits = tss->pattern->byte_len*8;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t first_bit = (history_size + tss->history_idx - pattern_bits) % history_size;</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* we need to shift the last received frame to the start of the history buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+        * do this in two steps: First copy to a local buffer on the stack, using modulo-arithmetic</span><br><span style="color: hsl(120, 100%, 40%);">+    * as index into the history.  Second, copy it back to history */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < pattern_bits; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+         tmp[i] = tss->history[(first_bit + i) % history_size];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(tss->history, tmp, history_size);</span><br><span style="color: hsl(120, 100%, 40%);">+   tss->history_idx = 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%);">+enum trau_sync_state {</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_FRAME_ALIGN,</span><br><span style="color: hsl(120, 100%, 40%);">+     FRAME_ALIGNED,</span><br><span style="color: hsl(120, 100%, 40%);">+        /* if at least 3 consecutive frames with each at least one framing error have been received */</span><br><span style="color: hsl(120, 100%, 40%);">+        FRAME_ALIGNMENT_LOST,</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%);">+enum trau_sync_event {</span><br><span style="color: hsl(120, 100%, 40%);">+   TRAUSYNC_E_RESET,</span><br><span style="color: hsl(120, 100%, 40%);">+     /*! a buffer of bits was received (msgb with ubits) */</span><br><span style="color: hsl(120, 100%, 40%);">+        TRAUSYNC_E_RX_BITS,</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 value_string trau_sync_event_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       { TRAUSYNC_E_RESET, "RESET" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { TRAUSYNC_E_RX_BITS, "RX_BITS" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { 0, NULL }</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%);">+static void trau_sync_wait_align(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct trau_rx_sync_state *tss = (struct trau_rx_sync_state *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ubit_buf *ubb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case TRAUSYNC_E_RX_BITS:</span><br><span style="color: hsl(120, 100%, 40%);">+              ubb = data;</span><br><span style="color: hsl(120, 100%, 40%);">+           /* append every bit individually + check if we have sync */</span><br><span style="color: hsl(120, 100%, 40%);">+           while (ubb_length(ubb) > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ubit_t bit = ubb_pull_ubit(ubb);</span><br><span style="color: hsl(120, 100%, 40%);">+                      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     rx_history_add_bit(tss, bit);</span><br><span style="color: hsl(120, 100%, 40%);">+                 rc = correlate_history_against_pattern(tss);</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (!rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            osmo_fsm_inst_state_chg(fi, FRAME_ALIGNED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* treat remainder of input bits in correct state */</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_inst_dispatch(fi, TRAUSYNC_E_RX_BITS, ubb);</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%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void trau_sync_aligned_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct trau_rx_sync_state *tss = (struct trau_rx_sync_state *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* dispatch aligned frame to user */</span><br><span style="color: hsl(120, 100%, 40%);">+  rx_history_align(tss);</span><br><span style="color: hsl(120, 100%, 40%);">+        tss->out_cb(tss->user_data, tss->history, tss->pattern->byte_len*8);</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 void trau_sync_aligned(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct trau_rx_sync_state *tss = (struct trau_rx_sync_state *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ubit_buf *ubb;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case TRAUSYNC_E_RX_BITS:</span><br><span style="color: hsl(120, 100%, 40%);">+              ubb = data;</span><br><span style="color: hsl(120, 100%, 40%);">+           while (ubb_length(ubb)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     unsigned int frame_bits_remaining = tss->pattern->byte_len*8 - tss->history_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (ubb_length(ubb) < frame_bits_remaining) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* frame not filled by this message; just add data */</span><br><span style="color: hsl(120, 100%, 40%);">+                         rx_history_add_bits(tss, ubb_data(ubb), ubb_length(ubb));</span><br><span style="color: hsl(120, 100%, 40%);">+                             ubb_pull(ubb, ubb_length(ubb));</span><br><span style="color: hsl(120, 100%, 40%);">+                       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* append as many bits as are missing in the current frame */</span><br><span style="color: hsl(120, 100%, 40%);">+                         rx_history_add_bits(tss, ubb_data(ubb), frame_bits_remaining);</span><br><span style="color: hsl(120, 100%, 40%);">+                                ubb_pull(ubb, frame_bits_remaining);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                /* check if we still have frame sync */</span><br><span style="color: hsl(120, 100%, 40%);">+                               rc = correlate_history_against_pattern(tss);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (rc > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      tss->num_consecutive_errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+                                     if (tss->num_consecutive_errors >= 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                         tss->history_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                                              /* send NULL frame to user */</span><br><span style="color: hsl(120, 100%, 40%);">+                                         tss->out_cb(tss->user_data, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                                           osmo_fsm_inst_state_chg(fi, FRAME_ALIGNMENT_LOST, 1, T_SYNC);</span><br><span style="color: hsl(120, 100%, 40%);">+                                         osmo_fsm_inst_dispatch(fi, TRAUSYNC_E_RX_BITS, ubb);</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%);">+                             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                                        tss->num_consecutive_errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                         /* dispatch aligned frame to user */</span><br><span style="color: hsl(120, 100%, 40%);">+                          tss->out_cb(tss->user_data, tss->history, tss->history_idx);</span><br><span style="color: hsl(120, 100%, 40%);">+                              tss->history_idx = 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%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void trau_sync_alignment_lost(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* we try to restore sync for some amount of time before generating an error */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case TRAUSYNC_E_RX_BITS:</span><br><span style="color: hsl(120, 100%, 40%);">+              trau_sync_wait_align(fi, event, data);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void trau_sync_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case TRAUSYNC_E_RESET:</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, WAIT_FRAME_ALIGN, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int trau_sync_timeout(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (fi->T) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case T_SYNC:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* if Tsync expires before frame synchronization is</span><br><span style="color: hsl(120, 100%, 40%);">+            * again obtained the TRAU initiates sending of the</span><br><span style="color: hsl(120, 100%, 40%);">+            * urgent alarm pattern described in clause 4.10.2. */</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, WAIT_FRAME_ALIGN, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(0);</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_fsm_state trau_sync_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     [WAIT_FRAME_ALIGN] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .name = "WAIT_FRAME_ALIGN",</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask = S(TRAUSYNC_E_RX_BITS),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask = S(FRAME_ALIGNED),</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = trau_sync_wait_align,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [FRAME_ALIGNED] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           .name = "FRAME_ALIGNED",</span><br><span style="color: hsl(120, 100%, 40%);">+            .in_event_mask = S(TRAUSYNC_E_RX_BITS),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask = S(FRAME_ALIGNMENT_LOST) | S(WAIT_FRAME_ALIGN),</span><br><span style="color: hsl(120, 100%, 40%);">+              .action = trau_sync_aligned,</span><br><span style="color: hsl(120, 100%, 40%);">+          .onenter = trau_sync_aligned_onenter,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    [FRAME_ALIGNMENT_LOST] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            .name = "FRAME_ALIGNMENT_LOST",</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask = S(TRAUSYNC_E_RX_BITS),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask = S(WAIT_FRAME_ALIGN) | S(FRAME_ALIGNED),</span><br><span style="color: hsl(120, 100%, 40%);">+             .action = trau_sync_alignment_lost,</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%);">+static struct osmo_fsm trau_sync_fsm = {</span><br><span style="color: hsl(120, 100%, 40%);">+    .name = "trau_sync",</span><br><span style="color: hsl(120, 100%, 40%);">+        .states = trau_sync_states,</span><br><span style="color: hsl(120, 100%, 40%);">+   .num_states = ARRAY_SIZE(trau_sync_states),</span><br><span style="color: hsl(120, 100%, 40%);">+   .allstate_event_mask = S(TRAUSYNC_E_RESET),</span><br><span style="color: hsl(120, 100%, 40%);">+   .allstate_action = trau_sync_allstate,</span><br><span style="color: hsl(120, 100%, 40%);">+        .timer_cb = trau_sync_timeout,</span><br><span style="color: hsl(120, 100%, 40%);">+        .log_subsys = DLGLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+       .event_names = trau_sync_event_names,</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%);">+struct osmo_fsm_inst *</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_trau_sync_alloc(void *ctx, const char *name, frame_out_cb_t frame_out_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+              enum osmo_tray_sync_pat_id pat_id, void *user_data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct trau_rx_sync_state *tss;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (pat_id >= ARRAY_SIZE(sync_patterns))</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%);">+        fi = osmo_fsm_inst_alloc(&trau_sync_fsm, ctx, NULL, LOGL_NOTICE, name);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!fi)</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  tss = talloc_zero(fi, struct trau_rx_sync_state);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!tss) {</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);</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%);">+     fi->priv = tss;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  tss->out_cb = frame_out_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+        tss->user_data = user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* FIXME: this must be configurable */</span><br><span style="color: hsl(120, 100%, 40%);">+        tss->pattern = &sync_patterns[pat_id];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return fi;</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%);">+void osmo_trau_sync_rx_ubits(struct osmo_fsm_inst *fi, const ubit_t *bits, size_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ubit_buf ubb;</span><br><span style="color: hsl(120, 100%, 40%);">+  ubb_init(&ubb, bits, n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_dispatch(fi, TRAUSYNC_E_RX_BITS, &ubb);</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 void __attribute__((constructor)) on_dso_load_sync(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < ARRAY_SIZE(sync_patterns); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            sync_pattern_register(&sync_patterns[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_register(&trau_sync_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/trau/ubit_buf.h b/src/trau/ubit_buf.h</span><br><span>new file mode 100644</span><br><span>index 0000000..224b44b</span><br><span>--- /dev/null</span><br><span>+++ b/src/trau/ubit_buf.h</span><br><span>@@ -0,0 +1,42 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Small helper inspired by msgb */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ubit_buf {</span><br><span style="color: hsl(120, 100%, 40%);">+     const ubit_t *buf;      /*!< start of underlying buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+ const ubit_t *data;     /*!< next to be consumed bit */</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t n_bits;          /*!< number of total bits iin buffer */</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%);">+/*! length of [remainig, to be processed] data in ubit_buf */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline size_t ubb_length(struct ubit_buf *ubb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return ubb->n_bits - (ubb->data - ubb->buf);</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%);">+/*! retrieve + remove a single ubit_t from start of ubit_buf */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline ubit_t ubb_pull_ubit(struct ubit_buf *ubb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(ubb->data < ubb->buf + ubb->n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+  return *ubb->data++;</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 inline void ubb_pull(struct ubit_buf *ubb, size_t count)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(ubb_length(ubb) >= count);</span><br><span style="color: hsl(120, 100%, 40%);">+     ubb->data += count;</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%);">+/*! get pointer to next to be consumed bit */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const ubit_t *ubb_data(struct ubit_buf *ubb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return ubb->data;</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 inline void ubb_init(struct ubit_buf *ubb, const ubit_t *bits, size_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ubb->buf = bits;</span><br><span style="color: hsl(120, 100%, 40%);">+   ubb->data = ubb->buf;</span><br><span style="color: hsl(120, 100%, 40%);">+   ubb->n_bits = n_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index bd95cf5..dcd9a4f 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -7,7 +7,8 @@</span><br><span>                 ipa_proxy_test        \</span><br><span>              subchan_demux/subchan_demux_test \</span><br><span>                   ipa_recv/ipa_recv_test \</span><br><span style="color: hsl(0, 100%, 40%);">-                rtp_test/rtp_test</span><br><span style="color: hsl(120, 100%, 40%);">+             rtp_test/rtp_test \</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_sync/trau_sync_test</span><br><span> </span><br><span> e1inp_ipa_bsc_test_SOURCES = e1inp_ipa_bsc_test.c</span><br><span> e1inp_ipa_bsc_test_LDADD = $(top_builddir)/src/libosmoabis.la \</span><br><span>@@ -36,6 +37,10 @@</span><br><span> rtp_test_rtp_test_LDADD = $(top_builddir)/src/libosmotrau.la \</span><br><span>                        $(LIBOSMOCORE_LIBS)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+trau_sync_trau_sync_test_SOURCES = trau_sync/trau_sync_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+trau_sync_trau_sync_test_LDADD = $(top_builddir)/src/libosmotrau.la \</span><br><span style="color: hsl(120, 100%, 40%);">+                 $(LIBOSMOCORE_LIBS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> # boilerplate for the tests</span><br><span> # The `:;' works around a Bash 3.2 bug when the output is not writeable.</span><br><span>@@ -59,7 +64,8 @@</span><br><span> EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \</span><br><span>        subchan_demux/subchan_demux_test.ok \</span><br><span>        ipa_recv/ipa_recv_test.ok \</span><br><span style="color: hsl(0, 100%, 40%);">-     rtp_test/rtp_test.ok</span><br><span style="color: hsl(120, 100%, 40%);">+  rtp_test/rtp_test.ok \</span><br><span style="color: hsl(120, 100%, 40%);">+        trau_sync/trau_sync_test.ok trau_sync/trau_sync_test.err</span><br><span> </span><br><span> TESTSUITE = $(srcdir)/testsuite</span><br><span> </span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index 5e87248..4faf429 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -29,3 +29,9 @@</span><br><span> AT_CHECK([$abs_top_builddir/tests/rtp_test/rtp_test], [ignore], [expout])</span><br><span> AT_CLEANUP</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([trau_sync])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([trau_sync])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/trau_sync/trau_sync_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/trau_sync/trau_sync_test.err > experr</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/trau_sync/trau_sync_test], [0], [expout], [experr])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span>diff --git a/tests/trau_sync/trau_sync_test.c b/tests/trau_sync/trau_sync_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..392a236</span><br><span>--- /dev/null</span><br><span>+++ b/tests/trau_sync/trau_sync_test.c</span><br><span>@@ -0,0 +1,85 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/application.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/trau/trau_sync.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void frame_out_cb(void *user_data, const ubit_t *bits, unsigned int num_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *str = user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("demux_bits_cb '%s': %s\n", str, osmo_ubit_dump(bits, num_bits));</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 uint8_t sync_pattern[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,</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%);">+#define ASSERT_STATE(fi, x) OSMO_ASSERT(!strcmp(osmo_fsm_inst_state_name(fi), x))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_body(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_fsm_inst *fi = osmo_trau_sync_alloc(NULL, "test", frame_out_cb, OSMO_TRAU_SYNCP_16_FR_EFR, "test");</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("\n==> %s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ubit_t bits[40*8];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* send some invalid data */</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(bits, 0, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_trau_sync_rx_ubits(fi, bits, 23);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* first valid frame */</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_pbit2ubit(bits, sync_pattern, sizeof(sync_pattern)*8);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNED");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* second valid frame */</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNED");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* send wrong frame */</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(bits, 1, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNED");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* intersperse a valid frame */</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_pbit2ubit(bits, sync_pattern, sizeof(sync_pattern)*8);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* second wrong frame - but not consecutive */</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(bits, 1, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNED");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* third wrong frame - second consecutive */</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNED");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* only from third consecutive invalid frame onwards we should loose alignment */</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_trau_sync_rx_ubits(fi, bits, sizeof(bits));</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_STATE(fi, "FRAME_ALIGNMENT_LOST");</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%);">+static const struct log_info_cat default_categories[] = {</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%);">+const struct log_info log_info = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .cat = default_categories,</span><br><span style="color: hsl(120, 100%, 40%);">+    .num_cat = ARRAY_SIZE(default_categories),</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 main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_init_logging2(NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fsm_log_addr(false);</span><br><span style="color: hsl(120, 100%, 40%);">+     log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);</span><br><span style="color: hsl(120, 100%, 40%);">+       test_body();</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/trau_sync/trau_sync_test.err b/tests/trau_sync/trau_sync_test.err</span><br><span>new file mode 100644</span><br><span>index 0000000..f3eac3c</span><br><span>--- /dev/null</span><br><span>+++ b/tests/trau_sync/trau_sync_test.err</span><br><span>@@ -0,0 +1,15 @@</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Allocated</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){WAIT_FRAME_ALIGN}: state_chg to FRAME_ALIGNED</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNED}: state_chg to FRAME_ALIGNMENT_LOST</span><br><span style="color: hsl(120, 100%, 40%);">+<0000> trau_sync(test){FRAME_ALIGNMENT_LOST}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>\ No newline at end of file</span><br><span>diff --git a/tests/trau_sync/trau_sync_test.ok b/tests/trau_sync/trau_sync_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..2555913</span><br><span>--- /dev/null</span><br><span>+++ b/tests/trau_sync/trau_sync_test.ok</span><br><span>@@ -0,0 +1,9 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+==> test_body</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 00000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 00000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 00000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111</span><br><span style="color: hsl(120, 100%, 40%);">+demux_bits_cb 'test': </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmo-abis/+/18250">change 18250</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/libosmo-abis/+/18250"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmo-abis </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia6fe6228b0b8b9a27999f37ce1115ed5558881ea </div>
<div style="display:none"> Gerrit-Change-Number: 18250 </div>
<div style="display:none"> Gerrit-PatchSet: 12 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>