<p>fixeria has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmocom-bb/+/19459">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">layer23/mobile: implement handling of TCH test loop commands<br><br>For more information, see 3GPP TS 44.014, sections:<br><br>  - 5.1 "Single-slot TCH loops", and<br>  - 8 "Message definitions and contents".<br><br>This feature has nothing to do with the Mobility Management, so<br>let's handle GSM48_PDISC_TEST messages in the Radio Resources<br>layer implementation (gsm48_mm.c -> gsm48_rr.c).<br><br>Change-Id: If8efc57c7017aa8ea47b37c472d1bbb1914389ca<br>---<br>M src/host/layer23/include/osmocom/bb/common/l1ctl.h<br>M src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h<br>M src/host/layer23/src/common/l1ctl.c<br>M src/host/layer23/src/mobile/Makefile.am<br>A src/host/layer23/src/mobile/gsm414.c<br>M src/host/layer23/src/mobile/gsm48_mm.c<br>M src/host/layer23/src/mobile/gsm48_rr.c<br>7 files changed, 239 insertions(+), 15 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/59/19459/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/host/layer23/include/osmocom/bb/common/l1ctl.h b/src/host/layer23/include/osmocom/bb/common/l1ctl.h</span><br><span>index e4dbded..02ffa34 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/common/l1ctl.h</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/l1ctl.h</span><br><span>@@ -49,7 +49,7 @@</span><br><span> </span><br><span> /* Transmit TCH_MODE_REQ */</span><br><span> int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode,</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t audio_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+                    uint8_t audio_mode, uint8_t tch_loop_mode);</span><br><span> </span><br><span> /* Transmit ECHO_REQ */</span><br><span> int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len);</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h</span><br><span>index 6996ff3..9b499a6 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h</span><br><span>@@ -188,6 +188,9 @@</span><br><span>       /* audio flow */</span><br><span>     uint8_t                 audio_mode;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       /* 3GPP TS 44.014 TCH test loop mode (L1CTL specific format) */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t                 tch_loop_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* sapi 3 */</span><br><span>         uint8_t                 sapi3_state;</span><br><span>         uint8_t                 sapi3_link_id;</span><br><span>diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c</span><br><span>index 54c7452..a0c156f 100644</span><br><span>--- a/src/host/layer23/src/common/l1ctl.c</span><br><span>+++ b/src/host/layer23/src/common/l1ctl.c</span><br><span>@@ -461,7 +461,7 @@</span><br><span> </span><br><span> /* Transmit L1CTL_TCH_MODE_REQ */</span><br><span> int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode,</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t audio_mode)</span><br><span style="color: hsl(120, 100%, 40%);">+                     uint8_t audio_mode, uint8_t tch_loop_mode)</span><br><span> {</span><br><span>    struct msgb *msg;</span><br><span>    struct l1ctl_tch_mode_req *req;</span><br><span>@@ -475,6 +475,7 @@</span><br><span>        req = (struct l1ctl_tch_mode_req *) msgb_put(msg, sizeof(*req));</span><br><span>     req->tch_mode = tch_mode;</span><br><span>         req->audio_mode = audio_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+      req->loop_mode = tch_loop_mode;</span><br><span> </span><br><span>       return osmo_send_l1(ms, msg);</span><br><span> }</span><br><span>diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am</span><br><span>index 4e80e4e..783ae16 100644</span><br><span>--- a/src/host/layer23/src/mobile/Makefile.am</span><br><span>+++ b/src/host/layer23/src/mobile/Makefile.am</span><br><span>@@ -4,7 +4,7 @@</span><br><span> </span><br><span> noinst_LIBRARIES = libmobile.a</span><br><span> libmobile_a_SOURCES = gsm322.c gsm480_ss.c gsm411_sms.c gsm48_cc.c gsm48_mm.c \</span><br><span style="color: hsl(0, 100%, 40%);">-  gsm48_rr.c mnccms.c settings.c subscriber.c support.c \</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_rr.c gsm414.c mnccms.c settings.c subscriber.c support.c \</span><br><span>     transaction.c vty_interface.c voice.c mncc_sock.c primitives.c</span><br><span> </span><br><span> bin_PROGRAMS = mobile</span><br><span>diff --git a/src/host/layer23/src/mobile/gsm414.c b/src/host/layer23/src/mobile/gsm414.c</span><br><span>new file mode 100644</span><br><span>index 0000000..2f630df</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/layer23/src/mobile/gsm414.c</span><br><span>@@ -0,0 +1,220 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de></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%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm48.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/rsl.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_04_14.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_08_58.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <l1ctl_proto.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                struct msgb *msg, uint8_t link_id);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gsm48_l3_msgb_alloc(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define loop_mode_name(mode) \</span><br><span style="color: hsl(120, 100%, 40%);">+     get_value_string(loop_mode_names, mode)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct value_string loop_mode_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     { L1CTL_TCH_LOOP_OPEN,  "(OPEN)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { L1CTL_TCH_LOOP_A,     "A" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_B,     "B" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_C,     "C" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_D,     "D" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_E,     "E" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_F,     "F" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { L1CTL_TCH_LOOP_I,     "I" },</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%);">+static struct msgb *alloc_gsm414_msg(uint8_t msg_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gsm48_hdr *ngh;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *nmsg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  nmsg = gsm48_l3_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nmsg == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ngh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*ngh));</span><br><span style="color: hsl(120, 100%, 40%);">+      ngh->proto_discr = GSM48_PDISC_TEST;</span><br><span style="color: hsl(120, 100%, 40%);">+       ngh->msg_type = msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return nmsg;</span><br><span 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_close_tch_loop(struct osmocom_ms *ms, const struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_rrlayer *rr = &ms->rrlayer;</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int msg_len = msgb_l3len(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *nmsg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Make sure that we have an active connection */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rr->state != GSM48_RR_ST_DEDICATED) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DMM, LOGL_NOTICE, "TCH loop requires an active connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Make sure that the established channel is either TCH/F or TCH/H */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((rr->cd_now.chan_nr & 0xf8) != RSL_CHAN_Bm_ACCHs</span><br><span style="color: hsl(120, 100%, 40%);">+    && (rr->cd_now.chan_nr & 0xf0) != RSL_CHAN_Lm_ACCHs) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DMM, LOGL_NOTICE, "TCH loop requires a TCH/F or TCH/H connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Check if a loop is already closed */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rr->tch_loop_mode != L1CTL_TCH_LOOP_OPEN) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DMM, LOGL_NOTICE, "TCH loop has already been closed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((msg_len - sizeof(*gh)) < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Parse type of the TCH test loop, convert to L1CTL format */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t gsm414_loop_mode = (gh->data[0] >> 1) & 0x1f;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* NOTE: some bits are not specified, so they can be 0 or 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (gsm414_loop_mode == GSM414_LOOP_A)</span><br><span style="color: hsl(120, 100%, 40%);">+                rr->tch_loop_mode = L1CTL_TCH_LOOP_A;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if (gsm414_loop_mode == GSM414_LOOP_B)</span><br><span style="color: hsl(120, 100%, 40%);">+           rr->tch_loop_mode = L1CTL_TCH_LOOP_B;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if ((gsm414_loop_mode & 0x1e) == GSM414_LOOP_C)</span><br><span style="color: hsl(120, 100%, 40%);">+              rr->tch_loop_mode = L1CTL_TCH_LOOP_C;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if ((gsm414_loop_mode & 0x1c) == GSM414_LOOP_D)</span><br><span style="color: hsl(120, 100%, 40%);">+              rr->tch_loop_mode = L1CTL_TCH_LOOP_D;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if ((gsm414_loop_mode & 0x1c) == GSM414_LOOP_E)</span><br><span style="color: hsl(120, 100%, 40%);">+              rr->tch_loop_mode = L1CTL_TCH_LOOP_E;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if ((gsm414_loop_mode & 0x1c) == GSM414_LOOP_F)</span><br><span style="color: hsl(120, 100%, 40%);">+              rr->tch_loop_mode = L1CTL_TCH_LOOP_F;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if ((gsm414_loop_mode & 0x1c) == GSM414_LOOP_I)</span><br><span style="color: hsl(120, 100%, 40%);">+              rr->tch_loop_mode = L1CTL_TCH_LOOP_I;</span><br><span style="color: hsl(120, 100%, 40%);">+      else {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DMM, LOGL_NOTICE, "Unhandled 3GPP TS 44.014 TCH loop "</span><br><span style="color: hsl(120, 100%, 40%);">+              "mode=0x%02x => rejecting\n", gsm414_loop_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+            gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N);</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%);">+   LOGP(DMM, LOGL_NOTICE, "(%s) Closing 3GPP TS 44.014 TCH loop mode '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+       rsl_chan_nr_str(rr->cd_now.chan_nr), loop_mode_name(rr->tch_loop_mode));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Instruct the L1 to enable received TCH loopback mode</span><br><span style="color: hsl(120, 100%, 40%);">+        * FIXME: delay applying this mode, so we can send the ACK first */</span><br><span style="color: hsl(120, 100%, 40%);">+   l1ctl_tx_tch_mode_req(ms, rr->cd_now.mode, rr->audio_mode, rr->tch_loop_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Craft and send the ACKnowledgement */</span><br><span style="color: hsl(120, 100%, 40%);">+      nmsg = alloc_gsm414_msg(GSM414_MT_CLOSE_TCH_LOOP_ACK);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (nmsg == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int handle_open_tch_loop(struct osmocom_ms *ms, const struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gsm48_rrlayer *rr = &ms->rrlayer;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *nmsg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Make sure that we have an active connection */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rr->state != GSM48_RR_ST_DEDICATED) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DMM, LOGL_NOTICE, "TCH loop requires an active connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Make sure that the established channel is either TCH/F or TCH/H */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((rr->cd_now.chan_nr & 0xf8) != RSL_CHAN_Bm_ACCHs</span><br><span style="color: hsl(120, 100%, 40%);">+    && (rr->cd_now.chan_nr & 0xf0) != RSL_CHAN_Lm_ACCHs) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DMM, LOGL_NOTICE, "TCH loop requires a TCH/F or TCH/H connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Check if a loop actually needs to be closed */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rr->tch_loop_mode == L1CTL_TCH_LOOP_OPEN) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DMM, LOGL_NOTICE, "TCH loop has not been closed (already open)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(DMM, LOGL_NOTICE, "(%s) Opening 3GPP TS 44.014 TCH loop mode '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+       rsl_chan_nr_str(rr->cd_now.chan_nr), loop_mode_name(rr->tch_loop_mode));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Instruct the L1 to disable the TCH loopback mode */</span><br><span style="color: hsl(120, 100%, 40%);">+        l1ctl_tx_tch_mode_req(ms, rr->cd_now.mode, rr->audio_mode, L1CTL_TCH_LOOP_OPEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Only the loop mode C needs to be ACKnowledged */</span><br><span style="color: hsl(120, 100%, 40%);">+   bool needs_ack = rr->tch_loop_mode == L1CTL_TCH_LOOP_C;</span><br><span style="color: hsl(120, 100%, 40%);">+    rr->tch_loop_mode = L1CTL_TCH_LOOP_OPEN;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!needs_ack)</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%);">+   /* Craft and send the ACKnowledgement */</span><br><span style="color: hsl(120, 100%, 40%);">+      nmsg = alloc_gsm414_msg(GSM414_MT_OPEN_LOOP_CMD);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nmsg == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     msgb_put_u8(nmsg, GSM414_OPEN_LOOP_ACK_IE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 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 gsm414_rcv_test(struct osmocom_ms *ms, const struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DMM, LOGL_INFO, "Received 3GPP TS 44.014 message '%s' (0x%02x)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+          get_value_string(gsm414_msgt_names, gh->msg_type), gh->msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* TODO: check if the test SIM (special EF.ADM) is inserted */</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (gh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM414_MT_CLOSE_TCH_LOOP_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+            return handle_close_tch_loop(ms, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+        case GSM414_MT_OPEN_LOOP_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+         return handle_open_tch_loop(ms, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DMM, LOGL_NOTICE, "Unhandled 3GPP TS 44.014 message '%s' (0x%02x)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               get_value_string(gsm414_msgt_names, gh->msg_type), gh->msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+          gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_MSG_TYPE_N);</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>diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c</span><br><span>index 52c6fe9..49cc2bc 100644</span><br><span>--- a/src/host/layer23/src/mobile/gsm48_mm.c</span><br><span>+++ b/src/host/layer23/src/mobile/gsm48_mm.c</span><br><span>@@ -4076,14 +4076,9 @@</span><br><span>           msgb_free(msg);</span><br><span>              return rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM48_PDISC_TEST: /* test TS 04.14 */</span><br><span style="color: hsl(0, 100%, 40%);">-              LOGP(DMM, LOGL_NOTICE, "Test protocol 0x%02x according to "</span><br><span style="color: hsl(0, 100%, 40%);">-                   "TS 04.14 is not supported.\n", pdisc);</span><br><span style="color: hsl(0, 100%, 40%);">-               goto status;</span><br><span>         default:</span><br><span>             LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n",</span><br><span>                      pdisc);</span><br><span style="color: hsl(0, 100%, 40%);">-status:</span><br><span>               msgb_free(msg);</span><br><span>              return gsm48_mm_tx_mm_status(ms,</span><br><span>                     GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED);</span><br><span>diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c</span><br><span>index 0449ee3..64d64f1 100644</span><br><span>--- a/src/host/layer23/src/mobile/gsm48_rr.c</span><br><span>+++ b/src/host/layer23/src/mobile/gsm48_rr.c</span><br><span>@@ -93,6 +93,7 @@</span><br><span> static int gsm48_rr_set_mode(struct osmocom_ms *ms, uint8_t chan_nr,</span><br><span>     uint8_t mode);</span><br><span> static int gsm48_rr_rel_cnf(struct osmocom_ms *ms, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm414_rcv_test(struct osmocom_ms *ms, const struct msgb *msg);</span><br><span> </span><br><span> /*</span><br><span>  * support</span><br><span>@@ -516,8 +517,8 @@</span><br><span> }</span><br><span> </span><br><span> /* push rsl header and send (RSL-SAP) */</span><br><span style="color: hsl(0, 100%, 40%);">-static int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                               struct msgb *msg, uint8_t link_id)</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct msgb *msg, uint8_t link_id)</span><br><span> {</span><br><span>   struct gsm48_rrlayer *rr = &ms->rrlayer;</span><br><span> </span><br><span>@@ -879,7 +880,7 @@</span><br><span>  */</span><br><span> </span><br><span> /* send rr status request */</span><br><span style="color: hsl(0, 100%, 40%);">-static int gsm48_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause)</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause)</span><br><span> {</span><br><span>     struct msgb *nmsg;</span><br><span>   struct gsm48_hdr *gh;</span><br><span>@@ -3433,7 +3434,7 @@</span><br><span>        /* setting (new) timing advance */</span><br><span>   LOGP(DRR, LOGL_INFO, "setting TCH mode to %d, audio mode to %d\n",</span><br><span>                 mode, rr->audio_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-       l1ctl_tx_tch_mode_req(ms, mode, rr->audio_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+   l1ctl_tx_tch_mode_req(ms, mode, rr->audio_mode, rr->tch_loop_mode);</span><br><span> </span><br><span>        return 0;</span><br><span> }</span><br><span>@@ -4627,9 +4628,9 @@</span><br><span>       struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span>         struct gsm48_rr_hdr *rrh;</span><br><span>    uint8_t pdisc = gh->proto_discr & 0x0f;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc = -EINVAL;</span><br><span> </span><br><span>        if (pdisc == GSM48_PDISC_RR) {</span><br><span style="color: hsl(0, 100%, 40%);">-          int rc = -EINVAL;</span><br><span>            uint8_t skip_ind = (gh->proto_discr & 0xf0) >> 4;</span><br><span> </span><br><span>           /* ignore if skip indicator is not B'0000' */</span><br><span>@@ -4676,6 +4677,10 @@</span><br><span> </span><br><span>           msgb_free(msg);</span><br><span>              return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (pdisc == GSM48_PDISC_TEST) {</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = gsm414_rcv_test(ms, msg);</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>   }</span><br><span> </span><br><span>        /* pull off RSL header up to L3 message */</span><br><span>@@ -5505,6 +5510,7 @@</span><br><span>   start_rr_t_meas(rr, 1, 0);</span><br><span> </span><br><span>       rr->audio_mode = AUDIO_TX_MICROPHONE | AUDIO_RX_SPEAKER;</span><br><span style="color: hsl(120, 100%, 40%);">+   rr->tch_loop_mode = L1CTL_TCH_LOOP_OPEN;</span><br><span> </span><br><span>      return 0;</span><br><span> }</span><br><span>@@ -5707,6 +5713,5 @@</span><br><span>        && ch_type != RSL_CHAN_Lm_ACCHs)</span><br><span>            return 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return l1ctl_tx_tch_mode_req(ms, rr->cd_now.mode, mode);</span><br><span style="color: hsl(120, 100%, 40%);">+   return l1ctl_tx_tch_mode_req(ms, rr->cd_now.mode, mode, rr->tch_loop_mode);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmocom-bb/+/19459">change 19459</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmocom-bb/+/19459"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If8efc57c7017aa8ea47b37c472d1bbb1914389ca </div>
<div style="display:none"> Gerrit-Change-Number: 19459 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>