<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%);">+[0;m<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){WAIT_FRAME_ALIGN}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){WAIT_FRAME_ALIGN}: state_chg to FRAME_ALIGNED</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNED}: state_chg to FRAME_ALIGNMENT_LOST</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m<0000> trau_sync(test){FRAME_ALIGNMENT_LOST}: Received Event RX_BITS</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m</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>