<p>Daniel Willmann <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13356">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Harald Welte: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Initial commit for OC-2G support.<br><br>From-Commit: b77fd00608dd<br>From-Remote: https://gitlab.com/nrw_noa/osmo-pcu<br>Change-Id: I7cd89a549c9463e81893ca7dd925299f728e4453<br>---<br>M configure.ac<br>M src/Makefile.am<br>A src/osmo-bts-oc2g/oc2g_l1_hw.c<br>A src/osmo-bts-oc2g/oc2g_l1_if.c<br>A src/osmo-bts-oc2g/oc2g_l1_if.h<br>A src/osmo-bts-oc2g/oc2gbts.c<br>A src/osmo-bts-oc2g/oc2gbts.h<br>7 files changed, 1,145 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configure.ac b/configure.ac</span><br><span>index c3e2df8..149162e 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -139,6 +139,25 @@</span><br><span> CPPFLAGS="$oldCPPFLAGS"</span><br><span> fi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AC_MSG_CHECKING([whether to enable direct PHY access for PDCH of NuRAN Wireless OC-2G BTS])</span><br><span style="color: hsl(120, 100%, 40%);">+AC_ARG_ENABLE(oc2gbts-phy,</span><br><span style="color: hsl(120, 100%, 40%);">+ AC_HELP_STRING([--enable-oc2gbts-phy],</span><br><span style="color: hsl(120, 100%, 40%);">+ [enable code for OC-2G PHY [default=no]]),</span><br><span style="color: hsl(120, 100%, 40%);">+ [enable_oc2gbts_phy="$enableval"],[enable_oc2gbts_phy="no"])</span><br><span style="color: hsl(120, 100%, 40%);">+AC_ARG_WITH([oc2g], [AS_HELP_STRING([--with-oc2g=INCLUDE_DIR], [Location of the OC-2G API header files])],</span><br><span style="color: hsl(120, 100%, 40%);">+ [oc2g_incdir="$withval"],[oc2g_incdir="$incdir"])</span><br><span style="color: hsl(120, 100%, 40%);">+AC_SUBST([OC2G_INCDIR], $oc2g_incdir)</span><br><span style="color: hsl(120, 100%, 40%);">+AC_MSG_RESULT([$enable_oc2gbts_phy])</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CONDITIONAL(ENABLE_OC2GBTS_PHY, test "x$enable_oc2gbts_phy" = "xyes")</span><br><span style="color: hsl(120, 100%, 40%);">+if test "$enable_oc2g" = "yes"; then</span><br><span style="color: hsl(120, 100%, 40%);">+ oldCPPFLAGS=$CPPFLAGS</span><br><span style="color: hsl(120, 100%, 40%);">+ CPPFLAGS="$CPPFLAGS -I$OC2G_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"</span><br><span style="color: hsl(120, 100%, 40%);">+ AC_CHECK_HEADER([nrw/oc2g/oc2g.h],[],</span><br><span style="color: hsl(120, 100%, 40%);">+ [AC_MSG_ERROR([nrw/oc2g/oc2g.h can not be found in $oc2g_incdir])],</span><br><span style="color: hsl(120, 100%, 40%);">+ [#include <nrw/oc2g/oc2g.h>])</span><br><span style="color: hsl(120, 100%, 40%);">+ CPPFLAGS=$oldCPPFLAGS</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AC_ARG_ENABLE([vty_tests],</span><br><span> AC_HELP_STRING([--enable-vty-tests],</span><br><span> [Include the VTY tests in make check [default=no]]),</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index 51b047e..233e24d 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -29,6 +29,10 @@</span><br><span> AM_CPPFLAGS += -DENABLE_DIRECT_PHY</span><br><span> endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+if ENABLE_OC2GBTS_PHY</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CPPFLAGS += -DENABLE_DIRECT_PHY</span><br><span style="color: hsl(120, 100%, 40%);">+endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AM_CXXFLAGS = -Wall -ldl -pthread</span><br><span> AM_LDFLAGS = -lrt</span><br><span> </span><br><span>@@ -159,6 +163,26 @@</span><br><span> osmo-bts-litecell15/lc15bts.c</span><br><span> endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+if ENABLE_OC2GBTS_PHY</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CPPFLAGS += -I$(OC2G_INCDIR) -I$(srcdir)/osmo-bts-oc2g</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+EXTRA_DIST = \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_if.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_if.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_hw.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2gbts.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2gbts.h</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+noinst_HEADERS += \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_if.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2gbts.h</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_pcu_SOURCES += \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_if.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2g_l1_hw.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo-bts-oc2g/oc2gbts.c</span><br><span style="color: hsl(120, 100%, 40%);">+endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> osmo_pcu_LDADD = \</span><br><span> libgprs.la \</span><br><span> $(LIBOSMOGB_LIBS) \</span><br><span>diff --git a/src/osmo-bts-oc2g/oc2g_l1_hw.c b/src/osmo-bts-oc2g/oc2g_l1_hw.c</span><br><span>new file mode 100644</span><br><span>index 0000000..aaa543f</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bts-oc2g/oc2g_l1_hw.c</span><br><span>@@ -0,0 +1,213 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Interface handler for Nuran Wireless Litecell 1.5 L1 (real hardware) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * based on:</span><br><span style="color: hsl(120, 100%, 40%);">+ * femto_l1_hw.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2011 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 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 Affero 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 <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <limits.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/stat.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/write_queue.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm_utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/oc2g.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1prim.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1const.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gprs_debug.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "oc2g_l1_if.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "oc2gbts.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/oc2g_dsp2arm_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/oc2g_arm2dsp_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp_trx"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *rd_devnames[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME,</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 char *wr_devnames[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+ [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME,</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%);">+/* callback when there's something to read from the l1 msg_queue */</span><br><span style="color: hsl(120, 100%, 40%);">+static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ //struct msgb *msg = l1p_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_alloc_headroom(sizeof(Oc2g_Prim_t) + 128,</span><br><span style="color: hsl(120, 100%, 40%);">+ 128, "1l_fd");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct oc2gl1_hdl *fl1h = ofd->data;</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%);">+ msg->l1h = msg->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != -1)</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_ERROR, "error reading from L1 msg_queue: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_put(msg, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (ofd->priv_nr) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MQ_SYS_WRITE:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != sizeof(Oc2g_Prim_t))</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_NOTICE, "%u != "</span><br><span style="color: hsl(120, 100%, 40%);">+ "sizeof(Litecell15_Prim_t)\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return l1if_handle_sysprim(fl1h, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ case MQ_L1_WRITE:</span><br><span style="color: hsl(120, 100%, 40%);">+ case MQ_TCH_WRITE:</span><br><span style="color: hsl(120, 100%, 40%);">+ case MQ_PDTCH_WRITE:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != sizeof(GsmL1_Prim_t))</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_NOTICE, "%u != "</span><br><span style="color: hsl(120, 100%, 40%);">+ "sizeof(GsmL1_Prim_t)\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The compiler can't know that priv_nr is an enum. Assist. */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_FATAL, "writing on a wrong queue: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ofd->priv_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</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%);">+/* callback when we can write to one of the l1 msg_queue devices */</span><br><span style="color: hsl(120, 100%, 40%);">+static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</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%);">+ rc = write(ofd->fd, msg->l1h, msgb_l1len(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_ERROR, "error writing to L1 msg_queue: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (rc < msg->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_ERROR, "short write to L1 msg_queue: "</span><br><span style="color: hsl(120, 100%, 40%);">+ "%u < %u\n", rc, msg->len);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</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 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%);">+int l1if_transport_open(int q, struct oc2gl1_hdl *hdl)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[PATH_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Step 1: Open all msg_queue file descriptors */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *read_ofd = &hdl->read_ofd[q];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_wqueue *wq = &hdl->write_q[q];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *write_ofd = &hdl->write_q[q].bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(buf, sizeof(buf)-1, "%s%d", rd_devnames[q], hdl->hw_info.trx_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf[sizeof(buf)-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = open(buf, O_RDONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue %s: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ buf, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->fd = rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->priv_nr = q;</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->data = hdl;</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->cb = l1if_fd_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->when = BSC_FD_READ;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_fd_register(read_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ close(read_ofd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+ snprintf(buf, sizeof(buf)-1, "%s%d", wr_devnames[q], hdl->hw_info.trx_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf[sizeof(buf)-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = open(buf, O_WRONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue %s: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ buf, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ goto out_read;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_wqueue_init(wq, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ wq->write_cb = l1fd_write_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->fd = rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->priv_nr = q;</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->data = hdl;</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->when = BSC_FD_WRITE;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_fd_register(write_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ close(write_ofd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ goto out_read;</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 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+out_read:</span><br><span style="color: hsl(120, 100%, 40%);">+ close(hdl->read_ofd[q].fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(&hdl->read_ofd[q]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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 l1if_transport_close(int q, struct oc2gl1_hdl *hdl)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *read_ofd = &hdl->read_ofd[q];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *write_ofd = &hdl->write_q[q].bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(read_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+ close(read_ofd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ read_ofd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(write_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+ close(write_ofd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ write_ofd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/osmo-bts-oc2g/oc2g_l1_if.c b/src/osmo-bts-oc2g/oc2g_l1_if.c</span><br><span>new file mode 100644</span><br><span>index 0000000..23661cb</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bts-oc2g/oc2g_l1_if.c</span><br><span>@@ -0,0 +1,386 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * based on:</span><br><span style="color: hsl(120, 100%, 40%);">+ * femto_l1_if.c</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 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 Affero 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%);">+#include "oc2g_l1_if.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/oc2g.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1prim.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1const.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/gsmtap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <gprs_debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <pcu_l1_if.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/pcu/pcuif_proto.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <bts.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern void *tall_pcu_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t l1if_ts_to_hLayer2(uint8_t trx, uint8_t ts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return (ts << 16) | (trx << 24);</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%);">+/* allocate a msgb containing a GsmL1_Prim_t */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *l1p_msgb_alloc(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg)</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return msg;</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 l1if_req_pdch(struct oc2gl1_hdl *fl1h, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_wqueue *wqueue = &fl1h->write_q[MQ_PDTCH_WRITE];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_wqueue_enqueue(wqueue, msg) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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 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 void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct oc2gl1_hdl *gl1)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->id = id;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphInitReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ //prim->u.mphInitReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphCloseReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphCloseReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConnectReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphConnectReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDisconnectReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphDisconnectReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphActivateReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphActivateReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDeactivateReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphDeactivateReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConfigReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphConfigReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphMeasureReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.mphMeasureReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphInitCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphCloseCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConnectCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDisconnectCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphActivateCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDeactivateCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConfigCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphMeasureCnf:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphTimeInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphSyncInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhEmptyFrameReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.phEmptyFrameReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhDataReq:</span><br><span style="color: hsl(120, 100%, 40%);">+ prim->u.phDataReq.hLayer1 = (HANDLE)gl1->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhConnectInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhReadyToSendInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhDataInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhRaInd:</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%);">+ LOGP(DL1IF, LOGL_ERROR, "unknown L1 primitive %u\n", id);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return &prim->u;</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%);">+/* connect PDTCH */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_connect_pdch(void *obj, uint8_t ts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct oc2gl1_hdl *fl1h = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = l1p_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_MphConnectReq_t *cr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h);</span><br><span style="color: hsl(120, 100%, 40%);">+ cr->u8Tn = ts;</span><br><span style="color: hsl(120, 100%, 40%);">+ cr->logChComb = GsmL1_LogChComb_XIII;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return l1if_req_pdch(fl1h, msg);</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 handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1h,</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_PhReadyToSendInd_t *rts_ind)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_time g_time;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm_fn2gsmtime(&g_time, rts_ind->u32Fn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DL1IF, "Rx PH-RTS.ind %02u/%02u/%02u SAPI=%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ g_time.t1, g_time.t2, g_time.t3,</span><br><span style="color: hsl(120, 100%, 40%);">+ get_value_string(oc2gbts_l1sapi_names, rts_ind->sapi));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (rts_ind->sapi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Pdtch:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Pacch:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = pcu_rx_rts_req_pdtch(fl1h->trx_no, rts_ind->u8Tn,</span><br><span style="color: hsl(120, 100%, 40%);">+ rts_ind->u32Fn, rts_ind->u8BlockNbr);</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Ptcch:</span><br><span style="color: hsl(120, 100%, 40%);">+ // FIXME</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</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 rc;</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 get_meas(struct pcu_l1_meas *meas, const GsmL1_MeasParam_t *l1_meas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->rssi = (int8_t) (l1_meas->fRssi);</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->have_rssi = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->ber = (uint8_t) (l1_meas->fBer * 100);</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->have_ber = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->bto = (int16_t) (l1_meas->i16BurstTiming);</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->have_bto = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->link_qual = (int16_t) (l1_meas->fLinkQuality);</span><br><span style="color: hsl(120, 100%, 40%);">+ meas->have_link_qual = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int handle_ph_data_ind(struct oc2gl1_hdl *fl1h,</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_PhDataInd_t *data_ind, struct msgb *l1p_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct pcu_l1_meas meas = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DL1IF, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ get_value_string(oc2gbts_l1sapi_names, data_ind->sapi),</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->hLayer2,</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_hexdump(data_ind->msgUnitParam.u8Buffer,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->msgUnitParam.u8Size));</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%);">+ * TODO: Add proper bad frame handling here. This could be used</span><br><span style="color: hsl(120, 100%, 40%);">+ * to switch the used CS. Avoid a crash with the PCU right now</span><br><span style="color: hsl(120, 100%, 40%);">+ * feed "0 - 1" amount of data.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (data_ind->msgUnitParam.u8Size == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->msgUnitParam.u8Size-1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ get_meas(&meas, &data_ind->measParam);</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_update_tbf_ta("PH-DATA", data_ind->u32Fn, fl1h->trx_no,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->u8Tn, qta2ta(meas.bto));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (data_ind->sapi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Pdtch:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Pacch:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* drop incomplete UL block */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (data_ind->msgUnitParam.u8Buffer[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ != GsmL1_PdtchPlType_Full)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* PDTCH / PACCH frame handling */</span><br><span style="color: hsl(120, 100%, 40%);">+ pcu_rx_data_ind_pdtch(fl1h->trx_no, data_ind->u8Tn,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->msgUnitParam.u8Buffer + 1,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->msgUnitParam.u8Size - 1,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_ind->u32Fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ &meas);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_Sapi_Ptcch:</span><br><span style="color: hsl(120, 100%, 40%);">+ // FIXME</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%);">+ LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ get_value_string(oc2gbts_l1sapi_names, data_ind->sapi));</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(alarm_sig_data.spare, &data_ind->sapi, sizeof(unsigned int));</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_RX_UNKN_L1_SAP_ALARM, &alarm_sig_data);</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%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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 MIN_QUAL_RACH 5.0f</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ra_ind->measParam.fLinkQuality < MIN_QUAL_RACH)</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%);">+ DEBUGP(DL1IF, "Rx PH-RA.ind");</span><br><span style="color: hsl(120, 100%, 40%);">+ bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn,</span><br><span style="color: hsl(120, 100%, 40%);">+ qta2ta(ra_ind->measParam.i16BurstTiming));</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* handle any random indication from the L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_handle_l1prim(int wq, struct oc2gl1_hdl *fl1h, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_Prim_t *l1p = msgb_l1prim(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ get_value_string(oc2gbts_l1prim_names, l1p->id), wq);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (l1p->id) {</span><br><span style="color: hsl(120, 100%, 40%);">+#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphTimeInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = handle_mph_time_ind(fl1h, &l1p->u.mphTimeInd);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphSyncInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhConnectInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhReadyToSendInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = handle_ph_readytosend_ind(fl1h, &l1p->u.phReadyToSendInd);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhDataInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = handle_ph_data_ind(fl1h, &l1p->u.phDataInd, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhRaInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = handle_ph_ra_ind(fl1h, &l1p->u.phRaInd);</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_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_RX_UNKN_L1_PRIM_ALARM, &alarm_sig_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</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%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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 l1if_handle_sysprim(struct oc2gl1_hdl *fl1h, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOTSUP;</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%);">+/* send packet data request to L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct oc2gl1_hdl *fl1h = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_Prim_t *l1p;</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_PhDataReq_t *data_req;</span><br><span style="color: hsl(120, 100%, 40%);">+ GsmL1_MsgUnitParam_t *msu_param;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_time g_time;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm_fn2gsmtime(&g_time, fn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DL1IF, "TX packet data %02u/%02u/%02u is_ptcch=%d ts=%d "</span><br><span style="color: hsl(120, 100%, 40%);">+ "block_nr=%d, arfcn=%d, len=%d\n", g_time.t1, g_time.t2,</span><br><span style="color: hsl(120, 100%, 40%);">+ g_time.t3, is_ptcch, ts, block_nr, arfcn, len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = l1p_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ l1p = msgb_l1prim(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ l1p->id = GsmL1_PrimId_PhDataReq;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req = &l1p->u.phDataReq;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->hLayer1 = (HANDLE)fl1h->hLayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->sapi = (is_ptcch) ? GsmL1_Sapi_Ptcch : GsmL1_Sapi_Pdtch;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->subCh = GsmL1_SubCh_NA;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->u8BlockNbr = block_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->u8Tn = ts;</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->u32Fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+ msu_param = &data_req->msgUnitParam;</span><br><span style="color: hsl(120, 100%, 40%);">+ msu_param->u8Size = len;</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(msu_param->u8Buffer, data, len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gsmtap_send(fl1h->gsmtap, arfcn, data_req->u8Tn, GSMTAP_CHANNEL_PACCH,</span><br><span style="color: hsl(120, 100%, 40%);">+ 0, data_req->u32Fn, 0, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->msgUnitParam.u8Buffer,</span><br><span style="color: hsl(120, 100%, 40%);">+ data_req->msgUnitParam.u8Size);</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%);">+ /* transmit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_PDTCH_WRITE], msg) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_PDTCH_QUEUE_FULL_ALARM, &alarm_sig_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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 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%);">+void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct oc2gl1_hdl *fl1h;</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%);">+ fl1h = talloc_zero(tall_pcu_ctx, struct oc2gl1_hdl);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fl1h)</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%);">+ fl1h->hLayer1 = hlayer1;</span><br><span style="color: hsl(120, 100%, 40%);">+ fl1h->trx_no = trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* hardware queues are numbered starting from 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+ fl1h->hw_info.trx_nr = trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DL1IF, "PCU: Using TRX HW#%u\n", fl1h->hw_info.trx_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = l1if_transport_open(MQ_PDTCH_WRITE, fl1h);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ alarm_sig_data.spare[0] = trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_FAIL_OPEN_L1_ALARM, &alarm_sig_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(fl1h);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fl1h->gsmtap = gsmtap_source_init("localhost", GSMTAP_UDP_PORT, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fl1h->gsmtap)</span><br><span style="color: hsl(120, 100%, 40%);">+ gsmtap_source_add_sink(fl1h->gsmtap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fl1h;</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 l1if_close_pdch(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct oc2gl1_hdl *fl1h = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fl1h)</span><br><span style="color: hsl(120, 100%, 40%);">+ l1if_transport_close(MQ_PDTCH_WRITE, fl1h);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(fl1h);</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>diff --git a/src/osmo-bts-oc2g/oc2g_l1_if.h b/src/osmo-bts-oc2g/oc2g_l1_if.h</span><br><span>new file mode 100644</span><br><span>index 0000000..1e09f02</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bts-oc2g/oc2g_l1_if.h</span><br><span>@@ -0,0 +1,106 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * based on:</span><br><span style="color: hsl(120, 100%, 40%);">+ * femto_l1_if.h</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 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 Affero 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%);">+#ifndef _OC2G_L1_IF_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define _OC2G_L1_IF_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/write_queue.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/gsmtap_util.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm_utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "oc2gbts.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_SYS_READ,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_L1_READ,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_TCH_READ,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_PDTCH_READ,</span><br><span style="color: hsl(120, 100%, 40%);">+ _NUM_MQ_READ</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 {</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_SYS_WRITE,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_L1_WRITE,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_TCH_WRITE,</span><br><span style="color: hsl(120, 100%, 40%);">+ MQ_PDTCH_WRITE,</span><br><span style="color: hsl(120, 100%, 40%);">+ _NUM_MQ_WRITE</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 oc2gl1_hdl {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_time gsm_time;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t hLayer1; /* handle to the L1 instance in the DSP */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t dsp_trace_f;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head wlc_list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsmtap_inst *gsmtap;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t gsmtap_sapi_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t trx_no;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_timer_list alive_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int alive_prim_cnt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd read_ofd[_NUM_MQ_READ]; /* osmo file descriptors */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_wqueue write_q[_NUM_MQ_WRITE];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ int trx_nr; /* <1-2> */</span><br><span style="color: hsl(120, 100%, 40%);">+ } hw_info;</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 msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)</span><br><span style="color: hsl(120, 100%, 40%);">+#define msgb_sysprim(msg) ((Oc2g_Prim_t *)(msg)->l1h)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int l1if_compl_cb(struct msgb *l1_msg, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* send a request primitive to the L1 and schedule completion call-back */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg,</span><br><span style="color: hsl(120, 100%, 40%);">+ int is_system_prim, l1if_compl_cb *cb, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_reset(struct oc2gl1_hdl *hdl);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_activate_rf(struct oc2gl1_hdl *hdl, int on);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_set_trace_flags(struct oc2gl1_hdl *hdl, uint32_t flags);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_set_txpower(struct oc2gl1_hdl *fl1h, float tx_power);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *l1p_msgb_alloc(void);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *sysp_msgb_alloc(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t l1if_lchan_to_hLayer2(struct gsm_lchan *lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *l1if_hLayer2_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_handle_sysprim(struct oc2gl1_hdl *fl1h, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_handle_l1prim(int wq, struct oc2gl1_hdl *fl1h, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* tch.c */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan);</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%);">+ * The implementation of these functions is selected by either compiling and</span><br><span style="color: hsl(120, 100%, 40%);">+ * linking sysmo_l1_hw.c or sysmo_l1_fwd.c</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_transport_open(int q, struct oc2gl1_hdl *hdl);</span><br><span style="color: hsl(120, 100%, 40%);">+int l1if_transport_close(int q, struct oc2gl1_hdl *hdl);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* _OC2G_L1_IF_H */</span><br><span>diff --git a/src/osmo-bts-oc2g/oc2gbts.c b/src/osmo-bts-oc2g/oc2gbts.c</span><br><span>new file mode 100644</span><br><span>index 0000000..edd7f5b</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bts-oc2g/oc2gbts.c</span><br><span>@@ -0,0 +1,333 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* NuRAN Wireless OC-2G L1 API related definitions */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * based on:</span><br><span style="color: hsl(120, 100%, 40%);">+ * sysmobts.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2011 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 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 Affero 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 "oc2gbts.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/oc2g.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1const.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1dbg.h></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 l1prim_type oc2gbts_get_l1prim_type(GsmL1_PrimId_t id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphInitReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphCloseReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConnectReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDisconnectReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphActivateReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDeactivateReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConfigReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphMeasureReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphInitCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphCloseCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConnectCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDisconnectCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphActivateCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDeactivateCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConfigCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphMeasureCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhEmptyFrameReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhDataReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphTimeInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphSyncInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhConnectInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhReadyToSendInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhDataInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_PhRaInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ default: return L1P_T_INVALID;</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%);">+const struct value_string oc2gbts_l1prim_names[GsmL1_PrimId_NUM+1] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphInitReq, "MPH-INIT.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphCloseReq, "MPH-CLOSE.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphConnectReq, "MPH-CONNECT.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphDisconnectReq,"MPH-DISCONNECT.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphActivateReq, "MPH-ACTIVATE.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphDeactivateReq,"MPH-DEACTIVATE.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphConfigReq, "MPH-CONFIG.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphMeasureReq, "MPH-MEASURE.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphInitCnf, "MPH-INIT.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphCloseCnf, "MPH-CLOSE.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphConnectCnf, "MPH-CONNECT.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphDisconnectCnf,"MPH-DISCONNECT.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphActivateCnf, "MPH-ACTIVATE.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphDeactivateCnf,"MPH-DEACTIVATE.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphConfigCnf, "MPH-CONFIG.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphMeasureCnf, "MPH-MEASURE.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphTimeInd, "MPH-TIME.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_MphSyncInd, "MPH-SYNC.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhEmptyFrameReq, "PH-EMPTY_FRAME.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhDataReq, "PH-DATA.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhConnectInd, "PH-CONNECT.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhReadyToSendInd,"PH-READY_TO_SEND.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhDataInd, "PH-DATA.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_PrimId_PhRaInd, "PH-RA.ind" },</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%);">+GsmL1_PrimId_t oc2gbts_get_l1prim_conf(GsmL1_PrimId_t id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphInitReq: return GsmL1_PrimId_MphInitCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphCloseReq: return GsmL1_PrimId_MphCloseCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConnectReq: return GsmL1_PrimId_MphConnectCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDisconnectReq: return GsmL1_PrimId_MphDisconnectCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphActivateReq: return GsmL1_PrimId_MphActivateCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphDeactivateReq: return GsmL1_PrimId_MphDeactivateCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphConfigReq: return GsmL1_PrimId_MphConfigCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GsmL1_PrimId_MphMeasureReq: return GsmL1_PrimId_MphMeasureCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ default: return -1; // Weak</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%);">+enum l1prim_type oc2gbts_get_sysprim_type(Oc2g_PrimId_t id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SystemInfoReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SystemInfoCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SystemFailureInd: return L1P_T_IND;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_ActivateRfReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_ActivateRfCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_DeactivateRfReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_DeactivateRfCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetTraceFlagsReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_Layer1ResetReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_Layer1ResetCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetCalibTblReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetCalibTblCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_MuteRfReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_MuteRfCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetRxAttenReq: return L1P_T_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetRxAttenCnf: return L1P_T_CONF;</span><br><span style="color: hsl(120, 100%, 40%);">+ default: return L1P_T_INVALID;</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%);">+const struct value_string oc2gbts_sysprim_names[Oc2g_PrimId_NUM+1] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SystemInfoReq, "SYSTEM-INFO.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_ActivateRfReq, "ACTIVATE-RF.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_Layer1ResetReq, "LAYER1-RESET.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SetCalibTblReq, "SET-CALIB.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SetCalibTblCnf, "SET-CALIB.cnf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_MuteRfReq, "MUTE-RF.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_MuteRfCnf, "MUTE-RF.cnf" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { Oc2g_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" },</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%);">+Oc2g_PrimId_t oc2gbts_get_sysprim_conf(Oc2g_PrimId_t id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SystemInfoReq: return Oc2g_PrimId_SystemInfoCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_ActivateRfReq: return Oc2g_PrimId_ActivateRfCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_DeactivateRfReq: return Oc2g_PrimId_DeactivateRfCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_Layer1ResetReq: return Oc2g_PrimId_Layer1ResetCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetCalibTblReq: return Oc2g_PrimId_SetCalibTblCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_MuteRfReq: return Oc2g_PrimId_MuteRfCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ case Oc2g_PrimId_SetRxAttenReq: return Oc2g_PrimId_SetRxAttenCnf;</span><br><span style="color: hsl(120, 100%, 40%);">+ default: return -1; // Weak</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%);">+const struct value_string oc2gbts_l1sapi_names[GsmL1_Sapi_NUM+1] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Idle, "IDLE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Fcch, "FCCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Sch, "SCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Sacch, "SACCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Sdcch, "SDCCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Bcch, "BCCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pch, "PCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Agch, "AGCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Cbch, "CBCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Rach, "RACH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_TchF, "TCH/F" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_FacchF,"FACCH/F" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_TchH, "TCH/H" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_FacchH,"FACCH/H" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Nch, "NCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pdtch, "PDTCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pacch, "PACCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pbcch, "PBCCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pagch, "PAGCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Ppch, "PPCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Pnch, "PNCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Ptcch, "PTCCH" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Sapi_Prach, "PRACH" },</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%);">+const struct value_string oc2gbts_l1status_names[GSML1_STATUS_NUM+1] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Success, "Success" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Generic, "Generic error" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_NoMemory, "Not enough memory" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Timeout, "Timeout" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_InvalidParam, "Invalid parameter" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Busy, "Resource busy" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_NoRessource, "No more resources" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Uninitialized, "Trying to use uninitialized resource" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_NullInterface, "Trying to call a NULL interface" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_NullFctnPtr, "Trying to call a NULL function ptr" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_BadCrc, "Bad CRC" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_BadUsf, "Bad USF" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_InvalidCPS, "Invalid CPS field" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_UnexpectedBurst, "Unexpected burst" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_UnavailCodec, "AMR codec is unavailable" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_CriticalError, "Critical error" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_OverheatError, "Overheat error" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_DeviceError, "Device error" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_FacchError, "FACCH / TCH order error" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_AlreadyDeactivated,"Lchan already deactivated" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_TxBurstFifoOvrn, "FIFO overrun" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_TxBurstFifoUndr, "FIFO underrun" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_NotSynchronized, "Not synchronized" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_Unsupported, "Unsupported feature" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Status_ClockError, "System clock error" },</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%);">+const struct value_string oc2gbts_tracef_names[29] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_DEBUG, "DEBUG" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1WARNING, "L1_WARNING" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_ERROR, "ERROR" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1RXMSG, "L1_RX_MSG" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1TXMSG, "L1_TX_MSG" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHCNF, "MPH_CNF" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHIND, "MPH_IND" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHREQ, "MPH_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHIND, "PH_IND" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHREQ, "PH_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHYRF, "PHY_RF" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHYRFMSGBYTE, "PHY_MSG_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MODE, "MODE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TDMAINFO, "TDMA_INFO" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_BADCRC, "BAD_CRC" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHINDBYTE, "PH_IND_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHREQBYTE, "PH_REQ_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_DEVICEMSG, "DEVICE_MSG" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_RACHINFO, "RACH_INFO" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_LOGCHINFO, "LOG_CH_INFO" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MEMORY, "MEMORY" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PROFILING, "PROFILING" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TESTCOMMENT, "TEST_COMMENT" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TEST, "TEST" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_STATUS, "STATUS" },</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%);">+const struct value_string oc2gbts_tracef_docs[29] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_DEBUG, "Debug Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1WARNING, "L1 Warning Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_ERROR, "Error Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1RXMSG, "L1_RX_MSG Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1TXMSG, "L1_TX_MSG Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHCNF, "MphConfirmation Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHIND, "MphIndication Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MPHREQ, "MphRequest Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHIND, "PhIndication Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHREQ, "PhRequest Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHYRF, "PhyRF Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHYRFMSGBYTE, "PhyRF Message Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MODE, "Mode Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TDMAINFO, "TDMA Info Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_BADCRC, "Bad CRC Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHINDBYTE, "PH_IND_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PHREQBYTE, "PH_REQ_BYTE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_DEVICEMSG, "Device Message Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_RACHINFO, "RACH Info" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_LOGCHINFO, "LOG_CH_INFO" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_MEMORY, "Memory Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_PROFILING, "Profiling Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TESTCOMMENT, "Test Comments" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_TEST, "Test Region" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { DBG_STATUS, "Status Region" },</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%);">+const struct value_string oc2gbts_tch_pl_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_NA, "N/A" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Fr, "FR" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Hr, "HR" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Efr, "EFR" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr, "AMR(IF2)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_SidBad, "AMR(SID BAD)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_Onset, "AMR(ONSET)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_Ratscch, "AMR(RATSCCH)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_SidUpdateInH, "AMR(SID_UPDATE INH)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_SidFirstP1, "AMR(SID_FIRST P1)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_SidFirstP2, "AMR(SID_FIRST P2)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_SidFirstInH, "AMR(SID_FIRST INH)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_RatscchMarker, "AMR(RATSCCH MARK)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_TchPlType_Amr_RatscchData, "AMR(RATSCCH DATA)" },</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%);">+const struct value_string oc2gbts_dir_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Dir_TxDownlink, "TxDL" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Dir_TxUplink, "TxUL" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Dir_RxUplink, "RxUL" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Dir_RxDownlink, "RxDL" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_Dir_TxDownlink|GsmL1_Dir_RxUplink, "BOTH" },</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%);">+const struct value_string oc2gbts_chcomb_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_0, "dummy" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_I, "tch_f" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_II, "tch_h" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_IV, "ccch" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_V, "ccch_sdcch4" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_VII, "sdcch8" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { GsmL1_LogChComb_XIII, "pdtch" },</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%);">+const uint8_t pdch_msu_size[_NUM_PDCH_CS] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_CS_1] = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_CS_2] = 34,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_CS_3] = 40,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_CS_4] = 54,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_1] = 27,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_2] = 33,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_3] = 42,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_4] = 49,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_5] = 60,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_6] = 78,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_7] = 118,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_8] = 142,</span><br><span style="color: hsl(120, 100%, 40%);">+ [PDCH_MCS_9] = 154</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span>diff --git a/src/osmo-bts-oc2g/oc2gbts.h b/src/osmo-bts-oc2g/oc2gbts.h</span><br><span>new file mode 100644</span><br><span>index 0000000..24deae7</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bts-oc2g/oc2gbts.h</span><br><span>@@ -0,0 +1,64 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef OC2GBTS_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define OC2GBTS_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/oc2g.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <nrw/oc2g/gsml1const.h></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%);">+ * Depending on the firmware version either GsmL1_Prim_t or Oc2g_Prim_t</span><br><span style="color: hsl(120, 100%, 40%);">+ * is the bigger struct. For earlier firmware versions the GsmL1_Prim_t was the</span><br><span style="color: hsl(120, 100%, 40%);">+ * bigger struct.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define OC2GBTS_PRIM_SIZE \</span><br><span style="color: hsl(120, 100%, 40%);">+ (OSMO_MAX(sizeof(Oc2g_Prim_t), sizeof(GsmL1_Prim_t)) + 128)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum l1prim_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ L1P_T_INVALID, /* this must be 0 to detect uninitialized elements */</span><br><span style="color: hsl(120, 100%, 40%);">+ L1P_T_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+ L1P_T_CONF,</span><br><span style="color: hsl(120, 100%, 40%);">+ L1P_T_IND,</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 l1prim_type oc2gbts_get_l1prim_type(GsmL1_PrimId_t id);</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_l1prim_names[GsmL1_PrimId_NUM+1];</span><br><span style="color: hsl(120, 100%, 40%);">+GsmL1_PrimId_t oc2gbts_get_l1prim_conf(GsmL1_PrimId_t id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum l1prim_type oc2gbts_get_sysprim_type(Oc2g_PrimId_t id);</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_sysprim_names[Oc2g_PrimId_NUM+1];</span><br><span style="color: hsl(120, 100%, 40%);">+Oc2g_PrimId_t oc2gbts_get_sysprim_conf(Oc2g_PrimId_t id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_l1sapi_names[GsmL1_Sapi_NUM+1];</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_l1status_names[GSML1_STATUS_NUM+1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_tracef_names[29];</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_tracef_docs[29];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_tch_pl_names[15];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_clksrc_names[10];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string oc2gbts_dir_names[6];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum pdch_cs {</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_CS_1,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_CS_2,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_CS_3,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_CS_4,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_1,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_2,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_3,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_4,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_5,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_6,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_7,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_8,</span><br><span style="color: hsl(120, 100%, 40%);">+ PDCH_MCS_9,</span><br><span style="color: hsl(120, 100%, 40%);">+ _NUM_PDCH_CS</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 uint8_t pdch_msu_size[_NUM_PDCH_CS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* LC15BTS_H */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13356">change 13356</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/13356"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I7cd89a549c9463e81893ca7dd925299f728e4453 </div>
<div style="display:none"> Gerrit-Change-Number: 13356 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Daniel Willmann <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Daniel Willmann <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Pau Espin Pedrol <pespin@sysmocom.de> </div>