<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10189">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;">port rest octets encoding code from osmo-bsc<br><br>As part of fixing issue OS#3075, we want to migrate support<br>for encoding system information from osmo-bsc to libosmocore.<br><br>This change ports osmo-bsc code for encoding SI rest octets.<br><br>The conversion was a bit tricky in some places because some<br>functions receive a 'struct gsm_bts' parameter in osmo-bsc.<br>In this libosmocore version, such functions expect parameters<br>which correspond to the individual fields of 'struct gsm_bts'<br>which are used by these functions.<br><br>Several structs from osmo-bsc's system_information.h are now<br>also declared in libosmocore headers, with an added osmo_ prefix<br>to avoid collisions with existing definitions in osmo-bsc.<br><br>Some helpers were ported from osmo-bsc's system_information.c<br>to libosmocore's gsm48_rest_octets.c. Contrary to osmo-bsc's<br>implementation they are now only visible within this file.<br><br>Unfortunately, this code ported from osmo-bsc lacks unit tests.<br><br>Change-Id: I47888965ab11bba1186c21987f1365c9270abeab<br>Related: OS#3075<br>---<br>M include/Makefile.am<br>M include/osmocom/gprs/protocol/gsm_04_60.h<br>A include/osmocom/gsm/gsm48_rest_octets.h<br>A src/gsm/gsm48_rest_octets.c<br>M src/gsm/libosmogsm.map<br>5 files changed, 1,084 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index 6da5ab6..25a6d75 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -93,6 +93,7 @@</span><br><span>                        osmocom/gsm/gsm48.h \</span><br><span>                        osmocom/gsm/gsm48_arfcn_range_encode.h \</span><br><span>                        osmocom/gsm/gsm48_ie.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/gsm/gsm48_rest_octets.h \</span><br><span>                        osmocom/gsm/gsm_utils.h \</span><br><span>                        osmocom/gsm/gsup.h \</span><br><span>                        osmocom/gsm/gsup_sms.h \</span><br><span>diff --git a/include/osmocom/gprs/protocol/gsm_04_60.h b/include/osmocom/gprs/protocol/gsm_04_60.h</span><br><span>index 5d5fca9..f592b14 100644</span><br><span>--- a/include/osmocom/gprs/protocol/gsm_04_60.h</span><br><span>+++ b/include/osmocom/gprs/protocol/gsm_04_60.h</span><br><span>@@ -312,3 +312,42 @@</span><br><span> #endif</span><br><span> } __attribute__ ((packed));</span><br><span> #endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */</span><br><span style="color: hsl(120, 100%, 40%);">+enum osmo_gprs_nmo {</span><br><span style="color: hsl(120, 100%, 40%);">+   GPRS_NMO_I      = 0,    /* CS pagin on GPRS paging or traffic channel */</span><br><span style="color: hsl(120, 100%, 40%);">+      GPRS_NMO_II     = 1,    /* all paging on CCCH */</span><br><span style="color: hsl(120, 100%, 40%);">+      GPRS_NMO_III    = 2,    /* no paging coordination */</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%);">+/* TS 04.60 12.24 */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gprs_cell_options {</span><br><span style="color: hsl(120, 100%, 40%);">+     enum osmo_gprs_nmo nmo;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* T3168: wait for packet uplink assignment message */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t t3168; /* in milliseconds */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T3192: wait for release of the TBF after reception of the final block */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t t3192; /* in milliseconds */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t drx_timer_max;/* in seconds */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t bs_cv_max;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t  supports_egprs_11bit_rach;</span><br><span style="color: hsl(120, 100%, 40%);">+   bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t ext_info_present;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              uint8_t egprs_supported;</span><br><span style="color: hsl(120, 100%, 40%);">+              uint8_t use_egprs_p_ch_req;</span><br><span style="color: hsl(120, 100%, 40%);">+           uint8_t bep_period;</span><br><span style="color: hsl(120, 100%, 40%);">+           uint8_t pfc_supported;</span><br><span style="color: hsl(120, 100%, 40%);">+                uint8_t dtm_supported;</span><br><span style="color: hsl(120, 100%, 40%);">+                uint8_t bss_paging_coordination;</span><br><span style="color: hsl(120, 100%, 40%);">+      } ext_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%);">+/* TS 04.60 Table 12.9.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gprs_power_ctrl_pars {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t alpha;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t t_avg_w;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t t_avg_t;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t pc_meas_chan;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t n_avg_i;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span>diff --git a/include/osmocom/gsm/gsm48_rest_octets.h b/include/osmocom/gsm/gsm48_rest_octets.h</span><br><span>new file mode 100644</span><br><span>index 0000000..6280b6a</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/gsm/gsm48_rest_octets.h</span><br><span>@@ -0,0 +1,87 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/sysinfo.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gprs/protocol/gsm_04_60.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:</span><br><span style="color: hsl(120, 100%, 40%);">+   4-bit index is used (2#1111 = 10#15) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SI2Q_MAX_NUM 16</span><br><span style="color: hsl(120, 100%, 40%);">+/* length in bits (for single SI2quater message) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SI2Q_MAX_LEN 160</span><br><span style="color: hsl(120, 100%, 40%);">+#define SI2Q_MIN_LEN 18</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* generate SI1 rest octets */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2quater(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count, const uint16_t *uarfcn_list,</span><br><span style="color: hsl(120, 100%, 40%);">+                         size_t *u_offset, size_t uarfcn_length, uint16_t *scramble_list,</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct osmo_earfcn_si2q *si2quater_neigh_list, size_t *e_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2ter(uint8_t *data);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2bis(uint8_t *data);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si6(uint8_t *data, bool is1800_net);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gsm48_si_selection_params {</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t penalty_time:5,</span><br><span style="color: hsl(120, 100%, 40%);">+                temp_offs:3,</span><br><span style="color: hsl(120, 100%, 40%);">+                  cell_resel_off:6,</span><br><span style="color: hsl(120, 100%, 40%);">+             cbq:1,</span><br><span style="color: hsl(120, 100%, 40%);">+                present: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%);">+struct osmo_gsm48_si_power_offset {</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t power_offset:2,</span><br><span style="color: hsl(120, 100%, 40%);">+                present: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%);">+struct osmo_gsm48_si3_gprs_ind {</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t si13_position:1,</span><br><span style="color: hsl(120, 100%, 40%);">+               ra_colour:3,</span><br><span style="color: hsl(120, 100%, 40%);">+          present: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%);">+struct osmo_gsm48_lsa_params {</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t prio_thr:3,</span><br><span style="color: hsl(120, 100%, 40%);">+           lsa_offset:3,</span><br><span style="color: hsl(120, 100%, 40%);">+                 mcc:12,</span><br><span style="color: hsl(120, 100%, 40%);">+               mnc:12;</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int present;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gsm48_si_ro_info {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_gsm48_si_selection_params selection_params;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_gsm48_si_power_offset power_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+       bool si2ter_indicator;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool early_cm_ctrl;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              uint8_t where:3,</span><br><span style="color: hsl(120, 100%, 40%);">+                       present:1;</span><br><span style="color: hsl(120, 100%, 40%);">+   } scheduling;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_gsm48_si3_gprs_ind gprs_ind;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* SI 3 specific */</span><br><span style="color: hsl(120, 100%, 40%);">+   bool early_cm_restrict_3g;</span><br><span style="color: hsl(120, 100%, 40%);">+    bool si2quater_indicator;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* SI 4 specific */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_gsm48_lsa_params lsa_params;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t cell_id;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t break_ind;      /* do we have SI7 + SI8 ? */</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%);">+/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si3(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si4(uint8_t *data, const struct osmo_gsm48_si_ro_info *si4, int len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gsm48_si13_info {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_gprs_cell_options cell_opts;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_gprs_power_ctrl_pars pwr_ctrl_pars;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t bcch_change_mark;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t si_change_field;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t rac;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t spgc_ccch_sup;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t net_ctrl_ord;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t prio_acc_thr;</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%);">+/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si13(uint8_t *data, const struct osmo_gsm48_si13_info *si13);</span><br><span>diff --git a/src/gsm/gsm48_rest_octets.c b/src/gsm/gsm48_rest_octets.c</span><br><span>new file mode 100644</span><br><span>index 0000000..619dc6d</span><br><span>--- /dev/null</span><br><span>+++ b/src/gsm/gsm48_rest_octets.c</span><br><span>@@ -0,0 +1,949 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface,</span><br><span style="color: hsl(120, 100%, 40%);">+ * rest octet handling according to</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2009 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 Affero 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 <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bitvec.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/bitvec_gsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/sysinfo.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm48_arfcn_range_encode.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm48_rest_octets.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* generate SI1 rest octets */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (nch_pos) {</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_uint(&bv, *nch_pos, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is1800_net)</span><br><span style="color: hsl(120, 100%, 40%);">+               bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_spare_padding(&bv, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     return bv.data_len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append Repeated E-UTRAN Neighbour Cell to bitvec: see 3GPP TS 44.018 Table 10.5.2.33b.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool append_eutran_neib_cell(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       uint8_t budget)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned i, skip = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int16_t rem = budget - 6; /* account for mandatory stop bit and THRESH_E-UTRAN_high */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t earfcn_budget;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (budget <= 6)</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(budget <= SI2Q_MAX_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* first we have to properly adjust budget requirements */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/</span><br><span style="color: hsl(120, 100%, 40%);">+           rem -= 4;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          rem--;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */</span><br><span style="color: hsl(120, 100%, 40%);">+          rem -= 6;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          rem--;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */</span><br><span style="color: hsl(120, 100%, 40%);">+               rem -= 6;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          rem--;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rem < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* now we can proceed with actually adding EARFCNs within adjusted budget limit */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < e->length; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (e->arfcn[i] != OSMO_EARFCN_INVALID) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (skip < *e_offset) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            skip++; /* ignore EARFCNs added on previous calls */</span><br><span style="color: hsl(120, 100%, 40%);">+                  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              earfcn_budget = 17; /* compute budget per-EARFCN */</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                                     earfcn_budget++;</span><br><span style="color: hsl(120, 100%, 40%);">+                              else</span><br><span style="color: hsl(120, 100%, 40%);">+                                  earfcn_budget += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                         if (rem - earfcn_budget < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                                else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        (*e_offset)++;</span><br><span style="color: hsl(120, 100%, 40%);">+                                        rem -= earfcn_budget;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                       if (rem < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                               return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                       bitvec_set_bit(bv, 1); /* EARFCN: */</span><br><span style="color: hsl(120, 100%, 40%);">+                                  bitvec_set_uint(bv, e->arfcn[i], 16);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                    if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                                             bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                                        else { /* Measurement Bandwidth: 9.1.54 */</span><br><span style="color: hsl(120, 100%, 40%);">+                                            bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                                                bitvec_set_uint(bv, e->meas_bw[i], 3);</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%);">+             }</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%);">+   /* stop bit - end of EARFCN + Measurement Bandwidth sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (e->prio_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, e->prio, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* THRESH_E-UTRAN_high */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_uint(bv, e->thresh_hi, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (e->thresh_lo_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* THRESH_E-UTRAN_low: */</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, e->thresh_lo, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (e->qrxlm_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* E-UTRAN_QRXLEVMIN: */</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, e->qrxlm, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset, uint8_t budget)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ bool appended;</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int old = bv->cur_bit; /* save current position to make rollback possible */</span><br><span style="color: hsl(120, 100%, 40%);">+      int rem = budget - 25;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rem <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(budget <= SI2Q_MAX_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Additions in Rel-5: */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No 3G Additional Measurement Param. Descr. */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Additions in Rel-6: */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* 3G_CCN_ACTIVE */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Additions in Rel-7: */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No 700_REPORTING_OFFSET */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No 810_REPORTING_OFFSET */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Additions in Rel-8: */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Priority and E-UTRAN Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* No Serving Cell Priority Parameters Descr. */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No 3G Priority Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* E-UTRAN Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* E-UTRAN_CCN_ACTIVE */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* E-UTRAN_Start: 9.1.54 */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* E-UTRAN_Stop: 9.1.54 */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* No E-UTRAN Measurement Parameters Descr. */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No GPRS E-UTRAN Measurement Param. Descr. */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Note: each of next 3 "repeated" structures might be repeated any</span><br><span style="color: hsl(120, 100%, 40%);">+    (0, 1, 2...) times - we only support 1 and 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Repeated E-UTRAN Neighbour Cells */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      appended = append_eutran_neib_cell(bv, e, e_offset, rem);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!appended) { /* appending is impossible within current budget: rollback */</span><br><span style="color: hsl(120, 100%, 40%);">+                bv->cur_bit = old;</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Note: following 2 repeated structs are not supported ATM */</span><br><span style="color: hsl(120, 100%, 40%);">+        /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Priority and E-UTRAN Parameters Description ends here */</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No 3G CSG Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No E-UTRAN CSG Description */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No Additions in Rel-9: */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(bv, L);</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 range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,</span><br><span style="color: hsl(120, 100%, 40%);">+                   int f0, uint8_t *chan_list)</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%);">+     * Manipulate the ARFCN list according to the rules in J4 depending</span><br><span style="color: hsl(120, 100%, 40%);">+    * on the selected range.</span><br><span style="color: hsl(120, 100%, 40%);">+      */</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc, f0_included;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc < 0)</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%);">+  /* Select the range and the amount of bits needed */</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (r) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case OSMO_GSM48_ARFCN_RANGE_128:</span><br><span style="color: hsl(120, 100%, 40%);">+              return osmo_gsm48_range_enc_range128(chan_list, f0, w);</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_GSM48_ARFCN_RANGE_256:</span><br><span style="color: hsl(120, 100%, 40%);">+              return osmo_gsm48_range_enc_range256(chan_list, f0, w);</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_GSM48_ARFCN_RANGE_512:</span><br><span style="color: hsl(120, 100%, 40%);">+              return osmo_gsm48_range_enc_range512(chan_list, f0, w);</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_GSM48_ARFCN_RANGE_1024:</span><br><span style="color: hsl(120, 100%, 40%);">+             return osmo_gsm48_range_enc_range1024(chan_list, f0, f0_included, w);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ERANGE;</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 f0_included;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);</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 p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned range1024_p(unsigned n)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (n) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0: return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     case 1: return 10;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 2: return 19;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 3: return 28;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 4: return 36;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 5: return 44;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 6: return 52;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 7: return 60;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 8: return 67;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 9: return 74;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 10: return 81;</span><br><span style="color: hsl(120, 100%, 40%);">+   case 11: return 88;</span><br><span style="color: hsl(120, 100%, 40%);">+   case 12: return 95;</span><br><span style="color: hsl(120, 100%, 40%);">+   case 13: return 102;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 14: return 109;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 15: return 116;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 16: return 122;</span><br><span style="color: hsl(120, 100%, 40%);">+  default: 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%);">+/* Estimate how many bits it'll take to append single FDD UARFCN */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t chan_list[16] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+        int tmp[sc_len], f0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(tmp, sc, sizeof(tmp));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       f0 = f0_helper(tmp, length, chan_list);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (f0 < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return f0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 21 + range1024_p(length);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append single FDD UARFCN */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t chan_list[16] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+        int f0 = f0_helper(sc, length, chan_list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (f0 < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return f0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Repeated UTRAN FDD Neighbour Cells */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* FDD-ARFCN */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_uint(bv, u, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FDD_Indic0: parameter value '0000000000' is a member of the set? */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(bv, f0);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* NR_OF_FDD_CELLS */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(bv, length, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     f0 = bv->cur_bit;</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);</span><br><span style="color: hsl(120, 100%, 40%);">+       bv->cur_bit = f0 + range1024_p(length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 21 + range1024_p(length);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    size_t uarfcn_length, size_t *u_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                               uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i, k, rc, a[uarfcn_length];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (budget < 23)</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%);">+     /* copy corresponding Scrambling Codes: range encoder make in-place modifications */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* estimate bit length requirements */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return rc; /* range encoder failure */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (budget - rc <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOMEM; /* we have ran out of budget in current SI2q */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* compute next offset */</span><br><span style="color: hsl(120, 100%, 40%);">+     *u_offset += k;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return budget - append_utran_fdd(bv, uarfcn, a, k);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append multiple FDD UARFCNs */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                                size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(budget <= SI2Q_MAX_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (budget <= 7)</span><br><span style="color: hsl(120, 100%, 40%);">+           return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* 3G Neighbour Cell Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No Index_Start_3G */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No Absolute_Index_Start_EMR */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* UTRAN FDD Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* No Bandwidth_FDD */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = *u_offset; i <= uarfcn_length; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+               if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */</span><br><span style="color: hsl(120, 100%, 40%);">+                        rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (rem < 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%);">+                      if (i < uarfcn_length) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           cu = uarfcn_list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                          st = i;</span><br><span style="color: hsl(120, 100%, 40%);">+                       } else</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%);">+   /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* UTRAN TDD Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(bv, 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 size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned i, ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!e)</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%);">+   for (i = 0; i < e->length; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+         if (e->arfcn[i] != OSMO_EARFCN_INVALID)</span><br><span style="color: hsl(120, 100%, 40%);">+                    ret++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return ret;</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%);">+/* generate SI2quater rest octets: 3GPP TS 44.018 Â§ 10.5.2.33b */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2quater(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count, const uint16_t *uarfcn_list,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     size_t *u_offset, size_t uarfcn_length, uint16_t *scramble_list,</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct osmo_earfcn_si2q *si2quater_neigh_list, size_t *e_offset)</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%);">+       struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (si2q_count < si2q_index)</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%);">+     bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 20;</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_zero(&bv);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* BA_IND: Set to '0' as that's what we use for SI2xxx type,</span><br><span style="color: hsl(120, 100%, 40%);">+       * whereas '1' is used for SI5xxx type messages. The point here</span><br><span style="color: hsl(120, 100%, 40%);">+        * is to be able to correlate whether a given MS measurement</span><br><span style="color: hsl(120, 100%, 40%);">+   * report was using the neighbor cells advertised in SI2 or in</span><br><span style="color: hsl(120, 100%, 40%);">+         * SI5, as those two could very well be different */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* 3G_BA_IND */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(&bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* MP_CHANGE_MARK */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* SI2quater_INDEX */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(&bv, si2q_index, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* SI2quater_COUNT */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(&bv, si2q_count, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* No Measurement_Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No GPRS_Real Time Difference Description */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No GPRS_BSIC Description */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No GPRS_REPORT PRIORITY Description */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No GPRS_MEASUREMENT_Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No NC Measurement Parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No extension (length) */</span><br><span style="color: hsl(120, 100%, 40%);">+   bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc > 0 && uarfcn_length - *u_offset > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+     else /* No 3G Neighbour Cell Description */</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* No 3G Measurement Parameters Description */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* No GPRS_3G_MEASUREMENT Parameters Descr. */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = SI2Q_MAX_LEN - bv.cur_bit;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+          append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+   else /* No Additions in Rel-5: */</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return bv.data_len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append selection parameters to bitvec */</span><br><span style="color: hsl(120, 100%, 40%);">+static void append_selection_params(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                             const struct osmo_gsm48_si_selection_params *sp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (sp->present) {</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, sp->cbq);</span><br><span style="color: hsl(120, 100%, 40%);">+               bitvec_set_uint(bv, sp->cell_resel_off, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, sp->temp_offs, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_uint(bv, sp->penalty_time, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append power offset to bitvec */</span><br><span style="color: hsl(120, 100%, 40%);">+static void append_power_offset(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const struct osmo_gsm48_si_power_offset *po)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (po->present) {</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, po->power_offset, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Append GPRS indicator to bitvec */</span><br><span style="color: hsl(120, 100%, 40%);">+static void append_gprs_ind(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const struct osmo_gsm48_si3_gprs_ind *gi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (gi->present) {</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, gi->ra_colour, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+             /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(bv, gi->si13_position);</span><br><span style="color: hsl(120, 100%, 40%);">+     } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, L);</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%);">+/* Generate SI2ter Rest Octests 3GPP TS 44.018 Table 10.5.2.33a.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2ter(uint8_t *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* No SI2ter_MP_CHANGE_MARK */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return bv.data_len;</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%);">+/* Generate SI2bis Rest Octests 3GPP TS 44.018 Table 10.5.2.33.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si2bis(uint8_t *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return bv.data_len;</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%);">+/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si3(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Optional Selection Parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+   append_selection_params(&bv, &si3->selection_params);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Optional Power Offset */</span><br><span style="color: hsl(120, 100%, 40%);">+   append_power_offset(&bv, &si3->power_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Do we have a SI2ter on the BCCH? */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (si3->si2ter_indicator)</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Early Classmark Sending Control */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (si3->early_cm_ctrl)</span><br><span style="color: hsl(120, 100%, 40%);">+            bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Do we have a SI Type 9 on the BCCH? */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (si3->scheduling.present) {</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_uint(&bv, si3->scheduling.where, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* GPRS Indicator */</span><br><span style="color: hsl(120, 100%, 40%);">+  append_gprs_ind(&bv, &si3->gprs_ind);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* 3G Early Classmark Sending Restriction. If H, then controlled by</span><br><span style="color: hsl(120, 100%, 40%);">+    * early_cm_ctrl above */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (si3->early_cm_restrict_3g)</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (si3->si2quater_indicator) {</span><br><span style="color: hsl(120, 100%, 40%);">+            bitvec_set_bit(&bv, H); /* indicator struct present */</span><br><span style="color: hsl(120, 100%, 40%);">+            bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */</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%);">+   bitvec_spare_padding(&bv, (bv.data_len*8)-1);</span><br><span style="color: hsl(120, 100%, 40%);">+     return bv.data_len;</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 append_lsa_params(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const struct osmo_gsm48_lsa_params *lsa_params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       /* FIXME */</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si4(uint8_t *data, const struct osmo_gsm48_si_ro_info *si4, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* SI4 Rest Octets O */</span><br><span style="color: hsl(120, 100%, 40%);">+       append_selection_params(&bv, &si4->selection_params);</span><br><span style="color: hsl(120, 100%, 40%);">+      append_power_offset(&bv, &si4->power_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+      append_gprs_ind(&bv, &si4->gprs_ind);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (0 /* FIXME */) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* H and SI4 Rest Octets S */</span><br><span style="color: hsl(120, 100%, 40%);">+         bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* LSA Parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (si4->lsa_params.present) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                   append_lsa_params(&bv, &si4->lsa_params);</span><br><span style="color: hsl(120, 100%, 40%);">+          } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Cell Identity */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                   bitvec_set_uint(&bv, si4->cell_id, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* LSA ID Information */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+           } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* L and break indicator */</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(&bv, si4->break_ind ? H : L);</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 bv.data_len;</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%);">+/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+<SI6 rest octets> ::=</span><br><span style="color: hsl(120, 100%, 40%);">+{L | H <PCH and NCH info>}</span><br><span style="color: hsl(120, 100%, 40%);">+{L | H <VBS/VGCS options : bit(2)>}</span><br><span style="color: hsl(120, 100%, 40%);">+{ < DTM_support : bit == L > I < DTM_support : bit == H ></span><br><span style="color: hsl(120, 100%, 40%);">+< RAC : bit (8) ></span><br><span style="color: hsl(120, 100%, 40%);">+< MAX_LAPDm : bit (3) > }</span><br><span style="color: hsl(120, 100%, 40%);">+< Band indicator ></span><br><span style="color: hsl(120, 100%, 40%);">+{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }</span><br><span style="color: hsl(120, 100%, 40%);">+<implicit spare >;</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si6(uint8_t *data, bool is1800_net)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* no PCH/NCH info */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* no VBS/VGCS options */</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* no DTM_support */</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* band indicator */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (is1800_net)</span><br><span style="color: hsl(120, 100%, 40%);">+               bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* no GPRS_MS_TXPWR_MAX_CCH */</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return bv.data_len;</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%);">+/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:</span><br><span style="color: hsl(120, 100%, 40%);">+   < GPRS Mobile Allocation IE > ::=</span><br><span style="color: hsl(120, 100%, 40%);">+     < HSN : bit (6) ></span><br><span style="color: hsl(120, 100%, 40%);">+     { 0 | 1 < RFL number list : < RFL number list struct > > }</span><br><span style="color: hsl(120, 100%, 40%);">+     { 0 < MA_LENGTH : bit (6) ></span><br><span style="color: hsl(120, 100%, 40%);">+         < MA_BITMAP: bit (val(MA_LENGTH) + 1) ></span><br><span style="color: hsl(120, 100%, 40%);">+     | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     < RFL number list struct > :: =</span><br><span style="color: hsl(120, 100%, 40%);">+       < RFL_NUMBER : bit (4) ></span><br><span style="color: hsl(120, 100%, 40%);">+       { 0 | 1 < RFL number list struct > } ;</span><br><span style="color: hsl(120, 100%, 40%);">+     < ARFCN index list struct > ::=</span><br><span style="color: hsl(120, 100%, 40%);">+       < ARFCN_INDEX : bit(6) ></span><br><span style="color: hsl(120, 100%, 40%);">+       { 0 | 1 < ARFCN index list struct > } ;</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int append_gprs_mobile_alloc(struct bitvec *bv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Hopping Sequence Number */</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(bv, 0, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* We want to use a RFL number list */</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                /* FIXME: RFL number list */</span><br><span style="color: hsl(120, 100%, 40%);">+  } else</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* We want to use a MA_BITMAP */</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                /* FIXME: MA_LENGTH, MA_BITMAP, ... */</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* We want to provide an ARFCN index list */</span><br><span style="color: hsl(120, 100%, 40%);">+                  bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+           } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode_t3192(unsigned int t3192)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        /* See also 3GPP TS 44.060</span><br><span style="color: hsl(120, 100%, 40%);">+       Table 12.24.2: GPRS Cell Options information element details */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (t3192 == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 80)</span><br><span style="color: hsl(120, 100%, 40%);">+              return 4;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 120)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 5;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 160)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 6;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 200)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 7;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 500)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 1000)</span><br><span style="color: hsl(120, 100%, 40%);">+            return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (t3192 <= 1500)</span><br><span style="color: hsl(120, 100%, 40%);">+            return 2;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</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%);">+static int encode_drx_timer(unsigned int drx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (drx == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx == 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx == 2)</span><br><span style="color: hsl(120, 100%, 40%);">+            return 2;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx <= 4)</span><br><span style="color: hsl(120, 100%, 40%);">+         return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx <= 8)</span><br><span style="color: hsl(120, 100%, 40%);">+         return 4;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx <= 16)</span><br><span style="color: hsl(120, 100%, 40%);">+                return 5;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx <= 32)</span><br><span style="color: hsl(120, 100%, 40%);">+                return 6;</span><br><span style="color: hsl(120, 100%, 40%);">+     else if (drx <= 64)</span><br><span style="color: hsl(120, 100%, 40%);">+                return 7;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</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%);">+/* GPRS Cell Options as per TS 04.60 Chapter 12.24</span><br><span style="color: hsl(120, 100%, 40%);">+      < GPRS Cell Options IE > ::=</span><br><span style="color: hsl(120, 100%, 40%);">+            < NMO : bit(2) ></span><br><span style="color: hsl(120, 100%, 40%);">+                < T3168 : bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+              < T3192 : bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+              < DRX_TIMER_MAX: bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+               < ACCESS_BURST_TYPE: bit ></span><br><span style="color: hsl(120, 100%, 40%);">+              < CONTROL_ACK_TYPE : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+              < BS_CV_MAX: bit(4) ></span><br><span style="color: hsl(120, 100%, 40%);">+           { 0 | 1 < PAN_DEC : bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+                    < PAN_INC : bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+                    < PAN_MAX : bit(3) ></span><br><span style="color: hsl(120, 100%, 40%);">+            { 0 | 1 < Extension Length : bit(6) ></span><br><span style="color: hsl(120, 100%, 40%);">+                   < bit (val(Extension Length) + 1</span><br><span style="color: hsl(120, 100%, 40%);">+                   & { < Extension Information > ! { bit ** = <no string> } } ;</span><br><span style="color: hsl(120, 100%, 40%);">+  < Extension Information > ::=</span><br><span style="color: hsl(120, 100%, 40%);">+           { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+                  < BEP_PERIOD : bit(4) > }</span><br><span style="color: hsl(120, 100%, 40%);">+               < PFC_FEATURE_MODE : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+              < DTM_SUPPORT : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+           <BSS_PAGING_COORDINATION: bit ></span><br><span style="color: hsl(120, 100%, 40%);">+         <spare bit > ** ;</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int append_gprs_cell_opt(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                              const struct osmo_gprs_cell_options *gco)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int t3192, drx_timer_max;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   t3192 = encode_t3192(gco->t3192);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (t3192 < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return t3192;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       drx_timer_max = encode_drx_timer(gco->drx_timer_max);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (drx_timer_max < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return drx_timer_max;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_uint(bv, gco->nmo, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* See also 3GPP TS 44.060</span><br><span style="color: hsl(120, 100%, 40%);">+       Table 12.24.2: GPRS Cell Options information element details */</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    bitvec_set_uint(bv, t3192, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_uint(bv, drx_timer_max, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* ACCESS_BURST_TYPE: Hard-code 8bit */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* CONTROL_ACK_TYPE: */</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);</span><br><span style="color: hsl(120, 100%, 40%);">+  bitvec_set_uint(bv, gco->bs_cv_max, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* hard-code no PAN_{DEC,INC,MAX} */</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* copied from ip.access BSC protocol trace */</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_uint(bv, 1, 3);      /* DEC */</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_uint(bv, 1, 3);      /* INC */</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_uint(bv, 15, 3);     /* MAX */</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 (!gco->ext_info_present) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* no extension information */</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* extension information */</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!gco->ext_info.egprs_supported) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* 6bit length of extension */</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_uint(bv, (1 + 3)-1, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* EGPRS supported in the cell */</span><br><span style="color: hsl(120, 100%, 40%);">+                     bitvec_set_bit(bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* 6bit length of extension */</span><br><span style="color: hsl(120, 100%, 40%);">+                        bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* EGPRS supported in the cell */</span><br><span style="color: hsl(120, 100%, 40%);">+                     bitvec_set_bit(bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* 1bit EGPRS PACKET CHANNEL REQUEST */</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (gco->supports_egprs_11bit_rach == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         bitvec_set_bit(bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    gco->ext_info.use_egprs_p_ch_req);</span><br><span style="color: hsl(120, 100%, 40%);">+                 } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              bitvec_set_bit(bv, 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%);">+                   /* 4bit BEP PERIOD */</span><br><span style="color: hsl(120, 100%, 40%);">+                 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             bitvec_set_bit(bv, gco->ext_info.pfc_supported);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(bv, gco->ext_info.dtm_supported);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);</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 append_gprs_pwr_ctrl_pars(struct bitvec *bv,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    const struct osmo_gprs_power_ctrl_pars *pcp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(bv, pcp->alpha, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+        bitvec_set_uint(bv, pcp->t_avg_w, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_uint(bv, pcp->t_avg_t, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      bitvec_set_uint(bv, pcp->pc_meas_chan, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ bitvec_set_uint(bv, pcp->n_avg_i, 4);</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%);">+/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_gsm48_rest_octets_si13(uint8_t *data, const struct osmo_gsm48_si13_info *si13)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct bitvec bv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&bv, 0, sizeof(bv));</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data_len = 20;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* No rest octets */</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, L);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(&bv, H);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_uint(&bv, si13->bcch_change_mark, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+               bitvec_set_uint(&bv, si13->si_change_field, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      bitvec_set_bit(&bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                   bitvec_set_uint(&bv, si13->bcch_change_mark, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+                       append_gprs_mobile_alloc(&bv);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* PBCCH not present in cell:</span><br><span style="color: hsl(120, 100%, 40%);">+            it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_bit(&bv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_uint(&bv, si13->rac, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+            bitvec_set_bit(&bv, si13->spgc_ccch_sup);</span><br><span style="color: hsl(120, 100%, 40%);">+              bitvec_set_uint(&bv, si13->prio_acc_thr, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+           append_gprs_cell_opt(&bv, &si13->cell_opts);</span><br><span style="color: hsl(120, 100%, 40%);">+               append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */</span><br><span style="color: hsl(120, 100%, 40%);">+           bitvec_set_bit(&bv, H);     /* added Release 99 */</span><br><span style="color: hsl(120, 100%, 40%);">+                /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS</span><br><span style="color: hsl(120, 100%, 40%);">+             * was only added in this Release */</span><br><span style="color: hsl(120, 100%, 40%);">+          bitvec_set_bit(&bv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     bitvec_spare_padding(&bv, (bv.data_len*8)-1);</span><br><span style="color: hsl(120, 100%, 40%);">+     return bv.data_len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index 922ac01..a903787 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -273,6 +273,14 @@</span><br><span> gsm48_push_l3hdr;</span><br><span> gsm48_att_tlvdef;</span><br><span> gsm48_cc_msg_name;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si1;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si2quater;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si2ter;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si2bis;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si6;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si3;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si4;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_rest_octets_si13;</span><br><span> gsm48_rr_msg_name;</span><br><span> gsm48_cc_state_name;</span><br><span> gsm48_construct_ra;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10189">change 10189</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/10189"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I47888965ab11bba1186c21987f1365c9270abeab </div>
<div style="display:none"> Gerrit-Change-Number: 10189 </div>
<div style="display:none"> Gerrit-PatchSet: 8 </div>
<div style="display:none"> Gerrit-Owner: Stefan Sperling <stsp@stsp.name> </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: Max <msuraev@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Stefan Sperling <stsp@stsp.name> </div>
<div style="display:none"> Gerrit-CC: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>