aboutsummaryrefslogtreecommitdiffstats
path: root/src/encoding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding.cpp')
-rw-r--r--src/encoding.cpp145
1 files changed, 112 insertions, 33 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 2648b027..e7e13ac1 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -35,7 +35,72 @@ extern "C" {
#include <errno.h>
#include <string.h>
+#define CHECK(rc) { if (rc < 0) return rc; }
+#define SET_X(bv, x) { if (bitvec_set_bit(bv, x) < 0) return -EOWNERDEAD; }
+#define SET_0(bv) SET_X(bv, ZERO)
+#define SET_1(bv) SET_X(bv, ONE)
+#define SET_L(bv) SET_X(bv, L)
+#define SET_H(bv) SET_X(bv, H)
+
+/* 3GPP TS 44.018 § 10.5.2.16:
+ { 0 | 1 < ALPHA : bit (4) > }
+ < GAMMA : bit (5) >
+*/
+static int write_alpha_gamma(bitvec *dest, uint8_t alpha, uint8_t gamma)
+{
+ int rc;
+
+ if (alpha) {
+ SET_1(dest);
+ rc = bitvec_set_u64(dest, alpha, 4, false);
+ CHECK(rc);
+ } else
+ SET_0(dest);
+
+ rc = bitvec_set_u64(dest, gamma, 5, false);
+ CHECK(rc);
+
+ return 0;
+}
+
+/* TBF_STARTING_TIME -- same as 3GPP TS 44.018 §10.5.2.38 Starting Time without tag: */
+static int write_tbf_start_time(bitvec *dest, uint32_t fn)
+{
+ int rc;
+
+ /* Set values according to 3GPP TS 44.018 Table 10.5.2.38.1 */
+
+ /* T1' */
+ rc = bitvec_set_u64(dest, (fn / (26 * 51)) % 32, 5, false);
+ CHECK(rc);
+
+ /* T3 */
+ rc = bitvec_set_u64(dest, fn % 51, 6, false);
+ CHECK(rc);
+
+ /* T2 */
+ rc = bitvec_set_u64(dest, fn % 26, 5, false);
+ CHECK(rc);
+
+ return rc;
+}
+
/* { 0 | 1 < TIMING_ADVANCE_INDEX : bit (4) > } */
+static int write_ta_index(bitvec *dest, int8_t tai)
+{
+ int rc;
+
+ if (tai < 0) /* No TIMING_ADVANCE_INDEX: */
+ SET_0(dest);
+
+ /* TIMING_ADVANCE_INDEX: */
+ SET_1(dest);
+ rc = bitvec_set_u64(dest, tai, 4, false);
+ CHECK(rc);
+
+ return 0;
+}
+
static inline bool write_tai(bitvec *dest, unsigned& wp, int8_t tai)
{
if (tai < 0) { /* No TIMING_ADVANCE_INDEX: */
@@ -88,43 +153,55 @@ static inline void write_ta_ie(bitvec *dest, unsigned& wp,
}
static int write_ia_rest_downlink(const gprs_rlcmac_dl_tbf *tbf, bitvec * dest, bool polling, bool ta_valid,
- uint32_t fn, uint8_t alpha, uint8_t gamma, int8_t ta_idx, unsigned& wp)
+ uint32_t fn, uint8_t alpha, uint8_t gamma, int8_t ta_idx)
{
int rc = 0;
- bitvec_write_field(dest, &wp, 3, 2); // "HH"
- bitvec_write_field(dest, &wp, 1, 2); // "01" Packet Downlink Assignment
- bitvec_write_field(dest, &wp,tbf->tlli(),32); // TLLI
- bitvec_write_field(dest, &wp,0x1,1); // switch TFI : on
- bitvec_write_field(dest, &wp,tbf->tfi(),5); // TFI
- bitvec_write_field(dest, &wp,0x0,1); // RLC acknowledged mode
- if (alpha) {
- bitvec_write_field(dest, &wp,0x1,1); // ALPHA = present
- bitvec_write_field(dest, &wp,alpha,4); // ALPHA
- } else {
- bitvec_write_field(dest, &wp,0x0,1); // ALPHA = not present
- }
- bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
- bitvec_write_field(dest, &wp,polling,1); // Polling Bit
- bitvec_write_field(dest, &wp, ta_valid, 1); // N. B: NOT related to TAI!
- write_tai(dest, wp, ta_idx);
+ SET_H(dest); SET_H(dest);
+ SET_0(dest); SET_1(dest); /* 00 Packet Downlink Assignment */
+
+ rc = bitvec_set_u64(dest, tbf->tlli(), 32, false); /* TLLI */
+ CHECK(rc);
+
+ SET_1(dest);
+ rc = bitvec_set_u64(dest, tbf->tfi(), 5, false); /* TFI_ASSIGNMENT */
+ CHECK(rc);
+
+ /* RLC acknowledged mode */
+ SET_0(dest); /* RLC_MODE */
+
+ rc = write_alpha_gamma(dest, alpha, gamma);
+ CHECK(rc);
+
+ rc = bitvec_set_bit(dest, (bit_value)polling); /* POLLING */
+ CHECK(rc);
+
+ /* N. B: NOT related to TAI! */
+ rc = bitvec_set_bit(dest, (bit_value)ta_valid); /* TA_VALID */
+ CHECK(rc);
+
+ rc = write_ta_index(dest, ta_idx);
+ CHECK(rc);
+
if (polling) {
- bitvec_write_field(dest, &wp,0x1,1); // TBF Starting TIME present
- bitvec_write_field(dest, &wp,(fn / (26 * 51)) % 32,5); // T1'
- bitvec_write_field(dest, &wp,fn % 51,6); // T3
- bitvec_write_field(dest, &wp,fn % 26,5); // T2
- } else {
- bitvec_write_field(dest, &wp,0x0,1); // TBF Starting TIME present
- }
- bitvec_write_field(dest, &wp,0x0,1); // P0 not present
- // bitvec_write_field(dest, &wp,0x1,1); // P0 not present
- // bitvec_write_field(dest, &wp,,0xb,4);
+ SET_1(dest);
+ rc = write_tbf_start_time(dest, fn);
+ CHECK(rc);
+ } else
+ SET_0(dest);
+
+ SET_0(dest); /* No P0 nor PR_MODE */
+
if (tbf->is_egprs_enabled()) {
- bitvec_write_field(dest, &wp, 1, 1); // "H"
- write_ws(dest, &wp, tbf->window_size()); // EGPRS Window Size
- bitvec_write_field(dest, &wp, 0x0, 2); // LINK_QUALITY_MEASUREMENT_MODE
- bitvec_write_field(dest, &wp, 0, 1); // BEP_PERIOD2 not present
- }
+ SET_H(dest);
+ rc = bitvec_set_u64(dest, enc_ws(tbf->window_size()), 5, false); /* EGPRS Window Size */
+ CHECK(rc);
+
+ /* The mobile station shall not report measurements: (see 3GPP TS 44.060 Table 11.2.7.1) */
+ SET_0(dest); SET_0(dest); /* LINK_QUALITY_MEASUREMENT_MODE */
+ SET_1(dest); /* No BEP_PERIOD2 */
+ } else
+ SET_L(dest); /* No Additions for Rel-6 */
return rc;
}
@@ -393,8 +470,10 @@ int Encoding::write_immediate_assignment(
LOGP(DRLCMACDL, LOGL_ERROR, "Cannot encode DL IMMEDIATE ASSIGNMENT without TBF\n");
return -EINVAL;
}
+
+ dest->cur_bit = wp;
rc = write_ia_rest_downlink(as_dl_tbf(tbf), dest, polling, gsm48_ta_is_valid(ta), fn, alpha, gamma,
- ta_idx, wp);
+ ta_idx);
} else if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) || (burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
bitvec_write_field(dest, &wp, 1, 2); /* LH */
bitvec_write_field(dest, &wp, 0, 2); /* 0 EGPRS Uplink Assignment */