<p>Neels Hofmeyr would like tnt, Vadim Yanitskiy, Harald Welte and Jenkins Builder to <strong>review</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13256">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Revert "assignment_fsm: Properly support assigning signalling mode TCH/x"<br><br>This commit breaks voice channel assignment. It results in the<br>Assignment Complete sent to the MSC for a voice lchan lacking<br>AoIP Transport Layer Address, Speech Version and Speech Codec.<br>Hence the MSC cannot complete the Assignment for a voice call.<br>Let's revisit this patch, test thoroughly and re-merge later.<br><br>This reverts commit 4d3a21269b25e7164a94fa8ce3ad67ff80904aee.<br><br>Reason for revert: <INSERT REASONING HERE><br><br>Change-Id: I72aaa03539919e7e85b5b75b133326cec5e68bc9<br>---<br>M include/osmocom/bsc/gsm_data.h<br>M include/osmocom/bsc/lchan_select.h<br>M src/osmo-bsc/assignment_fsm.c<br>M src/osmo-bsc/codec_pref.c<br>M src/osmo-bsc/handover_fsm.c<br>M src/osmo-bsc/lchan_select.c<br>M src/osmo-bsc/osmo_bsc_bssap.c<br>M tests/codec_pref/codec_pref_test.c<br>8 files changed, 134 insertions(+), 169 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/56/13256/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index fb0735a..c4315c0 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -98,15 +98,9 @@</span><br><span>         SUBSCR_SCCP_ST_CONNECTED</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum channel_rate {</span><br><span style="color: hsl(0, 100%, 40%);">-   CH_RATE_SDCCH,</span><br><span style="color: hsl(0, 100%, 40%);">-  CH_RATE_HALF,</span><br><span style="color: hsl(0, 100%, 40%);">-   CH_RATE_FULL,</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct channel_mode_and_rate {</span><br><span>    enum gsm48_chan_mode chan_mode;</span><br><span style="color: hsl(0, 100%, 40%);">- enum channel_rate chan_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+  bool full_rate;</span><br><span>      uint16_t s15_s0;</span><br><span> };</span><br><span> </span><br><span>@@ -121,9 +115,12 @@</span><br><span>    char msc_rtp_addr[INET_ADDRSTRLEN];</span><br><span>  uint16_t msc_rtp_port;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* Rate/codec setting in preference order (need at least 1 !) */</span><br><span style="color: hsl(0, 100%, 40%);">-        int n_ch_mode_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct channel_mode_and_rate ch_mode_rate[3];</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Prefered rate/codec setting (mandatory) */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct channel_mode_and_rate ch_mode_rate_pref;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Alternate rate/codec setting (optional) */</span><br><span style="color: hsl(120, 100%, 40%);">+ bool ch_mode_rate_alt_present;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct channel_mode_and_rate ch_mode_rate_alt;</span><br><span> };</span><br><span> </span><br><span> /* State of an ongoing Assignment, while the assignment_fsm is still busy. This serves as state separation to keep the</span><br><span>diff --git a/include/osmocom/bsc/lchan_select.h b/include/osmocom/bsc/lchan_select.h</span><br><span>index 865181b..4aecdf6 100644</span><br><span>--- a/include/osmocom/bsc/lchan_select.h</span><br><span>+++ b/include/osmocom/bsc/lchan_select.h</span><br><span>@@ -3,4 +3,4 @@</span><br><span> </span><br><span> struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type);</span><br><span> struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+                                         enum gsm48_chan_mode chan_mode, bool full_rate);</span><br><span>diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c</span><br><span>index 2180791..aa696ac 100644</span><br><span>--- a/src/osmo-bsc/assignment_fsm.c</span><br><span>+++ b/src/osmo-bsc/assignment_fsm.c</span><br><span>@@ -251,15 +251,17 @@</span><br><span> static bool lchan_type_compat_with_mode(enum gsm_chan_t type, const struct channel_mode_and_rate *ch_mode_rate)</span><br><span> {</span><br><span>        enum gsm48_chan_mode chan_mode = ch_mode_rate->chan_mode;</span><br><span style="color: hsl(0, 100%, 40%);">-    enum channel_rate chan_rate = ch_mode_rate->chan_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool full_rate = ch_mode_rate->full_rate;</span><br><span> </span><br><span>     switch (chan_mode) {</span><br><span>         case GSM48_CMODE_SIGN:</span><br><span>               switch (type) {</span><br><span style="color: hsl(0, 100%, 40%);">-         case GSM_LCHAN_TCH_F: return chan_rate == CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-         case GSM_LCHAN_TCH_H: return chan_rate == CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-         case GSM_LCHAN_SDCCH: return chan_rate == CH_RATE_SDCCH;</span><br><span style="color: hsl(0, 100%, 40%);">-                default: return false;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         case GSM_LCHAN_SDCCH:</span><br><span style="color: hsl(120, 100%, 40%);">+                 return true;</span><br><span style="color: hsl(120, 100%, 40%);">+          default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      return false;</span><br><span>                }</span><br><span> </span><br><span>        case GSM48_CMODE_SPEECH_V1:</span><br><span>@@ -267,12 +269,12 @@</span><br><span>  case GSM48_CMODE_DATA_3k6:</span><br><span>   case GSM48_CMODE_DATA_6k0:</span><br><span>           /* these services can all run on TCH/H, but we may have</span><br><span style="color: hsl(0, 100%, 40%);">-          * an explicit override by the 'chan_rate' argument */</span><br><span style="color: hsl(120, 100%, 40%);">+                 * an explicit override by the 'full_rate' argument */</span><br><span>               switch (type) {</span><br><span>              case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(0, 100%, 40%);">-                   return chan_rate == CH_RATE_FULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                     return full_rate;</span><br><span>            case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(0, 100%, 40%);">-                   return chan_rate == CH_RATE_HALF;</span><br><span style="color: hsl(120, 100%, 40%);">+                     return !full_rate;</span><br><span>           default:</span><br><span>                     return false;</span><br><span>                }</span><br><span>@@ -318,34 +320,45 @@</span><br><span>  * sure that both are consistent. */</span><br><span> static int check_requires_voice_stream(struct gsm_subscriber_connection *conn)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        bool requires_voice_pref = false, requires_voice_alt;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool result_requires_voice_alt;</span><br><span style="color: hsl(120, 100%, 40%);">+       bool result_requires_voice_pref;</span><br><span>     struct assignment_request *req = &conn->assignment.req;</span><br><span>       struct osmo_fsm_inst *fi = conn->fi;</span><br><span style="color: hsl(0, 100%, 40%);">- int i, rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span> </span><br><span>  /* When the assignment request indicates that there is an alternate</span><br><span>   * rate available (e.g. "Full or Half rate channel, Half rate</span><br><span>    * preferred..."), then both must be either voice or either signalling,</span><br><span>          * a mismatch is not permitted */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   for (i = 0; i < req->n_ch_mode_rate; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               rc = check_requires_voice(&requires_voice_alt, req->ch_mode_rate[i].chan_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-          if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,</span><br><span style="color: hsl(0, 100%, 40%);">-                                        "Channel mode not supported (prev level %d): %s", i,</span><br><span style="color: hsl(0, 100%, 40%);">-                                  gsm48_chan_mode_name(req->ch_mode_rate[i].chan_mode));</span><br><span style="color: hsl(0, 100%, 40%);">-                       return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Check the prefered setting */</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = check_requires_voice(&result_requires_voice_pref, req->ch_mode_rate_pref.chan_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Prefered channel mode not supported: %s",</span><br><span style="color: hsl(120, 100%, 40%);">+                          gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode));</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%);">+     conn->assignment.requires_voice_stream = result_requires_voice_pref;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             if (i==0)</span><br><span style="color: hsl(0, 100%, 40%);">-                       requires_voice_pref = requires_voice_alt;</span><br><span style="color: hsl(0, 100%, 40%);">-               else if (requires_voice_alt != requires_voice_pref) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,</span><br><span style="color: hsl(0, 100%, 40%);">-                                        "Inconsistent channel modes: %s != %s",</span><br><span style="color: hsl(0, 100%, 40%);">-                                       gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode),</span><br><span style="color: hsl(0, 100%, 40%);">-                                        gsm48_chan_mode_name(req->ch_mode_rate[i].chan_mode));</span><br><span style="color: hsl(0, 100%, 40%);">-                       return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* If there is an alternate setting, check that one as well */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!req->ch_mode_rate_alt_present)</span><br><span style="color: hsl(120, 100%, 40%);">+                return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = check_requires_voice(&result_requires_voice_alt, req->ch_mode_rate_alt.chan_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Alternate channel mode not supported: %s",</span><br><span style="color: hsl(120, 100%, 40%);">+                         gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode));</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 both settings match */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (result_requires_voice_pref != result_requires_voice_alt) {</span><br><span style="color: hsl(120, 100%, 40%);">+                assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Inconsistent channel modes: %s != %s",</span><br><span style="color: hsl(120, 100%, 40%);">+                             gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                            gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode));</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span>        return 0;</span><br><span>@@ -357,20 +370,18 @@</span><br><span> static bool reuse_existing_lchan(struct gsm_subscriber_connection *conn)</span><br><span> {</span><br><span>   struct assignment_request *req = &conn->assignment.req;</span><br><span style="color: hsl(0, 100%, 40%);">-  int i;</span><br><span> </span><br><span>   if (!conn->lchan)</span><br><span>                 return false;</span><br><span> </span><br><span>    /* Check if the currently existing lchan is compatible with the</span><br><span>       * preferred rate/codec. */</span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 0; i < req->n_ch_mode_rate; i++)</span><br><span style="color: hsl(0, 100%, 40%);">-         if (lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate[i])) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       conn->lchan->ch_mode_rate = req->ch_mode_rate[i];</span><br><span style="color: hsl(0, 100%, 40%);">-                      break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (i == req->n_ch_mode_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+      if (lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate_pref))</span><br><span style="color: hsl(120, 100%, 40%);">+             conn->lchan->ch_mode_rate = req->ch_mode_rate_pref;</span><br><span style="color: hsl(120, 100%, 40%);">+  else if (req->ch_mode_rate_alt_present</span><br><span style="color: hsl(120, 100%, 40%);">+              && lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate_alt))</span><br><span style="color: hsl(120, 100%, 40%);">+              conn->lchan->ch_mode_rate = req->ch_mode_rate_alt;</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span>                 return false;</span><br><span> </span><br><span>    if (conn->lchan->tch_mode != conn->lchan->ch_mode_rate.chan_mode) {</span><br><span>@@ -388,14 +399,8 @@</span><br><span> void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts *bts,</span><br><span>                       struct assignment_request *req)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  static const char *rate_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-             [CH_RATE_SDCCH] = "SDCCH",</span><br><span style="color: hsl(0, 100%, 40%);">-            [CH_RATE_HALF] = "HR",</span><br><span style="color: hsl(0, 100%, 40%);">-                [CH_RATE_FULL] = "FR",</span><br><span style="color: hsl(0, 100%, 40%);">-        };</span><br><span>   struct osmo_fsm_inst *fi;</span><br><span>    struct lchan_activate_info info;</span><br><span style="color: hsl(0, 100%, 40%);">-        int i;</span><br><span> </span><br><span>   OSMO_ASSERT(conn);</span><br><span>   OSMO_ASSERT(conn->fi);</span><br><span>@@ -438,13 +443,17 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Try to allocate a new lchan in order of preference */</span><br><span style="color: hsl(0, 100%, 40%);">-        for (i = 0; i < req->n_ch_mode_rate; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               conn->assignment.new_lchan = lchan_select_by_chan_mode(bts,</span><br><span style="color: hsl(0, 100%, 40%);">-              req->ch_mode_rate[i].chan_mode, req->ch_mode_rate[i].chan_rate);</span><br><span style="color: hsl(0, 100%, 40%);">-              conn->lchan->ch_mode_rate = req->ch_mode_rate[i];</span><br><span style="color: hsl(0, 100%, 40%);">-              if (conn->assignment.new_lchan)</span><br><span style="color: hsl(0, 100%, 40%);">-                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Try to allocate a new lchan with the preferred codec/rate choice */</span><br><span style="color: hsl(120, 100%, 40%);">+        conn->assignment.new_lchan =</span><br><span style="color: hsl(120, 100%, 40%);">+           lchan_select_by_chan_mode(bts, req->ch_mode_rate_pref.chan_mode, req->ch_mode_rate_pref.full_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+ conn->lchan->ch_mode_rate = req->ch_mode_rate_pref;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* In case the lchan allocation fails, we try with the alternat codec/</span><br><span style="color: hsl(120, 100%, 40%);">+         * rate choice (if possible) */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!conn->assignment.new_lchan && req->ch_mode_rate_alt_present) {</span><br><span style="color: hsl(120, 100%, 40%);">+             conn->assignment.new_lchan =</span><br><span style="color: hsl(120, 100%, 40%);">+                   lchan_select_by_chan_mode(bts, req->ch_mode_rate_alt.chan_mode, req->ch_mode_rate_alt.full_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+           conn->lchan->ch_mode_rate = req->ch_mode_rate_alt;</span><br><span>  }</span><br><span> </span><br><span>        /* Check whether the lchan allocation was successful or not and tear</span><br><span>@@ -453,22 +462,21 @@</span><br><span>                 assignment_count_result(BSC_CTR_ASSIGNMENT_NO_CHANNEL);</span><br><span>              assignment_fail(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,</span><br><span>                           "BSSMAP Assignment Command:"</span><br><span style="color: hsl(0, 100%, 40%);">-                          " No lchan available for: pref=%s:%s / alt1=%s:%s / alt2=%s:%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                            gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode),</span><br><span style="color: hsl(0, 100%, 40%);">-                                rate_names[req->ch_mode_rate[0].chan_rate],</span><br><span style="color: hsl(0, 100%, 40%);">-                          req->n_ch_mode_rate >= 1 ? gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode) : "",</span><br><span style="color: hsl(0, 100%, 40%);">-                                req->n_ch_mode_rate >= 1 ? rate_names[req->ch_mode_rate[0].chan_rate] : "",</span><br><span style="color: hsl(0, 100%, 40%);">-                          req->n_ch_mode_rate >= 2 ? gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode) : "",</span><br><span style="color: hsl(0, 100%, 40%);">-                                req->n_ch_mode_rate >= 2 ? rate_names[req->ch_mode_rate[0].chan_rate] : ""</span><br><span style="color: hsl(0, 100%, 40%);">-           );</span><br><span style="color: hsl(120, 100%, 40%);">+                            " No lchan available for: preferred=%s%s / alternate=%s%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                               gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                            req->ch_mode_rate_pref.full_rate ? ",FR" : ",HR",</span><br><span style="color: hsl(120, 100%, 40%);">+                              req->ch_mode_rate_alt_present ?</span><br><span style="color: hsl(120, 100%, 40%);">+                                    gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode) : "none",</span><br><span style="color: hsl(120, 100%, 40%);">+                          req->ch_mode_rate_alt_present ?</span><br><span style="color: hsl(120, 100%, 40%);">+                                    (req->ch_mode_rate_alt.full_rate ? ",FR" : ",HR") : "");</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span>        assignment_fsm_update_id(conn);</span><br><span style="color: hsl(0, 100%, 40%);">- LOG_ASSIGNMENT(conn, LOGL_INFO, "Starting Assignment: chan_mode=%s, chan_type=%s,"</span><br><span style="color: hsl(120, 100%, 40%);">+  LOG_ASSIGNMENT(conn, LOGL_INFO, "Starting Assignment: chan_mode=%s, full_rate=%d,"</span><br><span>                        " aoip=%s MSC-rtp=%s:%u\n",</span><br><span>                        gsm48_chan_mode_name(conn->lchan->ch_mode_rate.chan_mode),</span><br><span style="color: hsl(0, 100%, 40%);">-                rate_names[conn->lchan->ch_mode_rate.chan_rate],</span><br><span style="color: hsl(120, 100%, 40%);">+                conn->lchan->ch_mode_rate.full_rate,</span><br><span>                   req->aoip ? "yes" : "no", req->msc_rtp_addr, req->msc_rtp_port);</span><br><span> </span><br><span>     assignment_fsm_state_chg(ASSIGNMENT_ST_WAIT_LCHAN_ACTIVE);</span><br><span>diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c</span><br><span>index 659853c..a94d6a8 100644</span><br><span>--- a/src/osmo-bsc/codec_pref.c</span><br><span>+++ b/src/osmo-bsc/codec_pref.c</span><br><span>@@ -281,7 +281,6 @@</span><br><span> {</span><br><span>       unsigned int i;</span><br><span>      uint8_t perm_spch;</span><br><span style="color: hsl(0, 100%, 40%);">-      bool full_rate;</span><br><span>      bool match = false;</span><br><span>  const struct gsm0808_speech_codec *sc_match = NULL;</span><br><span>  uint16_t amr_s15_s0_supported;</span><br><span>@@ -296,16 +295,15 @@</span><br><span>               perm_spch = audio_support_to_gsm88(msc->audio_support[i]);</span><br><span> </span><br><span>            /* Determine if the result is a half or full rate codec */</span><br><span style="color: hsl(0, 100%, 40%);">-              rc = full_rate_from_perm_spch(&full_rate, perm_spch);</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = full_rate_from_perm_spch(&ch_mode_rate->full_rate, perm_spch);</span><br><span>           if (rc < 0)</span><br><span>                       return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-         ch_mode_rate->chan_rate = full_rate ? CH_RATE_FULL : CH_RATE_HALF;</span><br><span> </span><br><span>            /* If we have a preference for FR or HR in our request, we</span><br><span>            * discard the potential match */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (rate_pref == RATE_PREF_HR && ch_mode_rate->chan_rate == CH_RATE_FULL)</span><br><span style="color: hsl(120, 100%, 40%);">+          if (rate_pref == RATE_PREF_HR && ch_mode_rate->full_rate)</span><br><span>                         continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               if (rate_pref == RATE_PREF_FR && ch_mode_rate->chan_rate == CH_RATE_HALF)</span><br><span style="color: hsl(120, 100%, 40%);">+          if (rate_pref == RATE_PREF_FR && !ch_mode_rate->full_rate)</span><br><span>                        continue;</span><br><span> </span><br><span>                /* Check this permitted speech value against the BTS specific parameters.</span><br><span>@@ -323,8 +321,8 @@</span><br><span> </span><br><span>  /* Exit without result, in case no match can be deteched */</span><br><span>  if (!match) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ch_mode_rate->full_rate = false;</span><br><span>          ch_mode_rate->chan_mode = GSM48_CMODE_SIGN;</span><br><span style="color: hsl(0, 100%, 40%);">-          ch_mode_rate->chan_rate = CH_RATE_SDCCH;</span><br><span>          ch_mode_rate->s15_s0 = 0;</span><br><span>                 return -1;</span><br><span>   }</span><br><span>diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c</span><br><span>index 77f8138..a3d25d6 100644</span><br><span>--- a/src/osmo-bsc/handover_fsm.c</span><br><span>+++ b/src/osmo-bsc/handover_fsm.c</span><br><span>@@ -569,11 +569,10 @@</span><br><span>           }</span><br><span> </span><br><span>                LOG_HO(conn, LOGL_DEBUG, "BTS %u: Found matching audio type: %s %s (for %s)\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      bts->nr, gsm48_chan_mode_name(ch_mode_rate.chan_mode),</span><br><span style="color: hsl(0, 100%, 40%);">-                       ch_mode_rate.chan_rate == CH_RATE_FULL ?  "full-rate" : "half-rate",</span><br><span style="color: hsl(120, 100%, 40%);">+                      bts->nr, gsm48_chan_mode_name(ch_mode_rate.chan_mode), ch_mode_rate.full_rate? "full-rate" : "half-rate",</span><br><span>                     gsm0808_channel_type_name(&req->ct));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         lchan = lchan_select_by_chan_mode(bts, ch_mode_rate.chan_mode, ch_mode_rate.chan_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+               lchan = lchan_select_by_chan_mode(bts, ch_mode_rate.chan_mode, ch_mode_rate.full_rate);</span><br><span>              if (!lchan) {</span><br><span>                        LOG_HO(conn, LOGL_DEBUG, "BTS %u has no matching free channels\n", bts->nr);</span><br><span>                    continue;</span><br><span>diff --git a/src/osmo-bsc/lchan_select.c b/src/osmo-bsc/lchan_select.c</span><br><span>index 0a9752e..0f4dd65 100644</span><br><span>--- a/src/osmo-bsc/lchan_select.c</span><br><span>+++ b/src/osmo-bsc/lchan_select.c</span><br><span>@@ -128,31 +128,22 @@</span><br><span> }</span><br><span> </span><br><span> struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+                                          enum gsm48_chan_mode chan_mode, bool full_rate)</span><br><span> {</span><br><span>     enum gsm_chan_t type;</span><br><span> </span><br><span>    switch (chan_mode) {</span><br><span>         case GSM48_CMODE_SIGN:</span><br><span style="color: hsl(0, 100%, 40%);">-          switch (chan_rate) {</span><br><span style="color: hsl(0, 100%, 40%);">-            case CH_RATE_SDCCH: type = GSM_LCHAN_SDCCH; break;</span><br><span style="color: hsl(0, 100%, 40%);">-              case CH_RATE_HALF:  type = GSM_LCHAN_TCH_H; break;</span><br><span style="color: hsl(0, 100%, 40%);">-              case CH_RATE_FULL:  type = GSM_LCHAN_TCH_F; break;</span><br><span style="color: hsl(0, 100%, 40%);">-              default: return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(120, 100%, 40%);">+             type = GSM_LCHAN_SDCCH;</span><br><span>              break;</span><br><span>       case GSM48_CMODE_SPEECH_EFR:</span><br><span>                 /* EFR works over FR channels only */</span><br><span style="color: hsl(0, 100%, 40%);">-           if (chan_rate != CH_RATE_FULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!full_rate)</span><br><span>                      return NULL;</span><br><span>                 /* fall through */</span><br><span>   case GSM48_CMODE_SPEECH_V1:</span><br><span>  case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(0, 100%, 40%);">-            switch (chan_rate) {</span><br><span style="color: hsl(0, 100%, 40%);">-            case CH_RATE_HALF:  type = GSM_LCHAN_TCH_H; break;</span><br><span style="color: hsl(0, 100%, 40%);">-              case CH_RATE_FULL:  type = GSM_LCHAN_TCH_F; break;</span><br><span style="color: hsl(0, 100%, 40%);">-              default: return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(120, 100%, 40%);">+             type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;</span><br><span>                break;</span><br><span>       default:</span><br><span>             return NULL;</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>index 5c8ce97..85aab22 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>@@ -626,48 +626,60 @@</span><br><span> static int select_codecs(struct assignment_request *req, struct gsm0808_channel_type *ct,</span><br><span>                    struct gsm_subscriber_connection *conn)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   int rc, i, nc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span>      struct bsc_msc_data *msc;</span><br><span> </span><br><span>        msc = conn->sccp.msc;</span><br><span style="color: hsl(120, 100%, 40%);">+      req->ch_mode_rate_alt_present = false;</span><br><span> </span><br><span>        switch (ct->ch_rate_type) {</span><br><span>       case GSM0808_SPEECH_FULL_BM:</span><br><span style="color: hsl(0, 100%, 40%);">-            rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                       RATE_PREF_FR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span>             break;</span><br><span>       case GSM0808_SPEECH_HALF_LM:</span><br><span style="color: hsl(0, 100%, 40%);">-            rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                       RATE_PREF_HR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span>             break;</span><br><span>       case GSM0808_SPEECH_PERM:</span><br><span>    case GSM0808_SPEECH_PERM_NO_CHANGE:</span><br><span>  case GSM0808_SPEECH_FULL_PREF_NO_CHANGE:</span><br><span>     case GSM0808_SPEECH_FULL_PREF:</span><br><span style="color: hsl(0, 100%, 40%);">-          rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                       RATE_PREF_FR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-                rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+           if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+                                        RATE_PREF_HR);</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%);">+             rc = match_codec_pref(&req->ch_mode_rate_alt, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                RATE_PREF_HR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  req->ch_mode_rate_alt_present = true;</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = 0;</span><br><span>              break;</span><br><span>       case GSM0808_SPEECH_HALF_PREF_NO_CHANGE:</span><br><span>     case GSM0808_SPEECH_HALF_PREF:</span><br><span style="color: hsl(0, 100%, 40%);">-          rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                       RATE_PREF_HR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-                rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+                                        RATE_PREF_FR);</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%);">+             rc = match_codec_pref(&req->ch_mode_rate_alt, ct, &conn->codec_list, msc, conn_get_bts(conn),</span><br><span>                                RATE_PREF_FR);</span><br><span style="color: hsl(0, 100%, 40%);">-            nc += (rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  req->ch_mode_rate_alt_present = true;</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = 0;</span><br><span>              break;</span><br><span>       default:</span><br><span>             rc = -EINVAL;</span><br><span>                break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!nc) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc < 0) {</span><br><span>             LOGP(DMSC, LOGL_ERROR, "No supported audio type found for channel_type ="</span><br><span>               " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[%s] }\n",</span><br><span>                ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));</span><br><span>@@ -676,69 +688,29 @@</span><br><span>           return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   for (i = 0; i < nc; i++ ) {</span><br><span style="color: hsl(0, 100%, 40%);">-          DEBUGP(DMSC, "Found matching audio type (pref=%d): %s %s for channel_type ="</span><br><span style="color: hsl(120, 100%, 40%);">+        if (req->ch_mode_rate_alt_present) {</span><br><span style="color: hsl(120, 100%, 40%);">+               DEBUGP(DMSC, "Found matching audio type (preferred): %s %s for channel_type ="</span><br><span>                    " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  i,</span><br><span style="color: hsl(0, 100%, 40%);">-                      req->ch_mode_rate[i].chan_rate == CH_RATE_FULL ? "full rate" : "half rate",</span><br><span style="color: hsl(0, 100%, 40%);">-                      get_value_string(gsm48_chan_mode_names, req->ch_mode_rate[i].chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                   req->ch_mode_rate_pref.full_rate ? "full rate" : "half rate",</span><br><span style="color: hsl(120, 100%, 40%);">+                  get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_pref.chan_mode),</span><br><span>                        ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(120, 100%, 40%);">+             DEBUGP(DMSC, "Found matching audio type (alternative): %s %s for channel_type ="</span><br><span style="color: hsl(120, 100%, 40%);">+                   " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                req->ch_mode_rate_alt.full_rate ? "full rate" : "half rate",</span><br><span style="color: hsl(120, 100%, 40%);">+                   get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_alt.chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                  ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              DEBUGP(DMSC, "Found matching audio type: %s %s for channel_type ="</span><br><span style="color: hsl(120, 100%, 40%);">+                 " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                req->ch_mode_rate_pref.full_rate ? "full rate" : "half rate",</span><br><span style="color: hsl(120, 100%, 40%);">+                  get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_pref.chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                 ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        req->n_ch_mode_rate = nc;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int select_sign_chan(struct assignment_request *req, struct gsm0808_channel_type *ct)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int i, nc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  switch (ct->ch_rate_type) {</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_ANY:</span><br><span style="color: hsl(0, 100%, 40%);">-          req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;</span><br><span style="color: hsl(0, 100%, 40%);">-           req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-            req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_SDCCH:</span><br><span style="color: hsl(0, 100%, 40%);">-                req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;</span><br><span style="color: hsl(0, 100%, 40%);">-           break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_SDCCH_FULL_BM:</span><br><span style="color: hsl(0, 100%, 40%);">-                req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;</span><br><span style="color: hsl(0, 100%, 40%);">-           req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_SDCCH_HALF_LM:</span><br><span style="color: hsl(0, 100%, 40%);">-                req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;</span><br><span style="color: hsl(0, 100%, 40%);">-           req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_FULL_BM:</span><br><span style="color: hsl(0, 100%, 40%);">-              req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_HALF_LM:</span><br><span style="color: hsl(0, 100%, 40%);">-              req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_FULL_PREF:</span><br><span style="color: hsl(0, 100%, 40%);">-    case GSM0808_SIGN_FULL_PREF_NO_CHANGE:</span><br><span style="color: hsl(0, 100%, 40%);">-          req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GSM0808_SIGN_HALF_PREF:</span><br><span style="color: hsl(0, 100%, 40%);">-    case GSM0808_SIGN_HALF_PREF_NO_CHANGE:</span><br><span style="color: hsl(0, 100%, 40%);">-          req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;</span><br><span style="color: hsl(0, 100%, 40%);">-            req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  default:</span><br><span style="color: hsl(0, 100%, 40%);">-                break;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (i = 0; i < nc; i++)</span><br><span style="color: hsl(0, 100%, 40%);">-             req->ch_mode_rate[i].chan_mode = GSM48_CMODE_SIGN;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   req->n_ch_mode_rate = nc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return nc > 0 ? 0 : -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*</span><br><span>  * Handle the assignment request message.</span><br><span>  *</span><br><span>@@ -756,6 +728,7 @@</span><br><span>      uint8_t cause;</span><br><span>       int rc;</span><br><span>      struct assignment_request req = {};</span><br><span style="color: hsl(120, 100%, 40%);">+   struct channel_mode_and_rate ch_mode_rate_pref = {};</span><br><span> </span><br><span>     if (!conn) {</span><br><span>                 LOGP(DMSC, LOGL_ERROR,</span><br><span>@@ -876,15 +849,14 @@</span><br><span>               }</span><br><span>            break;</span><br><span>       case GSM0808_CHAN_SIGN:</span><br><span style="color: hsl(0, 100%, 40%);">-         req = (struct assignment_request){</span><br><span style="color: hsl(0, 100%, 40%);">-                      .aoip = aoip,</span><br><span style="color: hsl(120, 100%, 40%);">+         ch_mode_rate_pref = (struct channel_mode_and_rate) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  .chan_mode = GSM48_CMODE_SIGN,</span><br><span>               };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          rc = select_sign_chan(&req, &ct);</span><br><span style="color: hsl(0, 100%, 40%);">-               if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        cause = GSM0808_CAUSE_INCORRECT_VALUE;</span><br><span style="color: hsl(0, 100%, 40%);">-                  goto reject;</span><br><span style="color: hsl(0, 100%, 40%);">-            }</span><br><span style="color: hsl(120, 100%, 40%);">+             req = (struct assignment_request){</span><br><span style="color: hsl(120, 100%, 40%);">+                    .aoip = aoip,</span><br><span style="color: hsl(120, 100%, 40%);">+                 .ch_mode_rate_pref = ch_mode_rate_pref,</span><br><span style="color: hsl(120, 100%, 40%);">+               };</span><br><span>           break;</span><br><span>       default:</span><br><span>             cause = GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS;</span><br><span>diff --git a/tests/codec_pref/codec_pref_test.c b/tests/codec_pref/codec_pref_test.c</span><br><span>index ce82f3d..bb5468a 100644</span><br><span>--- a/tests/codec_pref/codec_pref_test.c</span><br><span>+++ b/tests/codec_pref/codec_pref_test.c</span><br><span>@@ -407,7 +407,7 @@</span><br><span> </span><br><span>       rc = match_codec_pref(&ch_mode_rate, ct, scl, msc, bts, RATE_PREF_NONE);</span><br><span>         printf(" * result: rc=%i, full_rate=%i, s15_s0=%04x, chan_mode=%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-        rc, ch_mode_rate.chan_rate == CH_RATE_FULL, ch_mode_rate.s15_s0, gsm48_chan_mode_name(ch_mode_rate.chan_mode));</span><br><span style="color: hsl(120, 100%, 40%);">+               rc, ch_mode_rate.full_rate, ch_mode_rate.s15_s0, gsm48_chan_mode_name(ch_mode_rate.chan_mode));</span><br><span> </span><br><span>   printf("\n");</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13256">change 13256</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/13256"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I72aaa03539919e7e85b5b75b133326cec5e68bc9 </div>
<div style="display:none"> Gerrit-Change-Number: 13256 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@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: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: tnt <tnt@246tNt.com> </div>
<div style="display:none"> Gerrit-CC: Max <msuraev@sysmocom.de> </div>