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