<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>