aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/encoding.cpp82
1 files changed, 39 insertions, 43 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 48f38297..ca9e906e 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -828,6 +828,17 @@ static void write_packet_uplink_ack_gprs(
bitvec_write_field(dest, &wp, 0, 1); // 0: don't have REL 5
};
+/* Encode the Ack/Nack for EGPRS. 44.060
+ * The PCU encodes to receive block bitmap to the following rules:
+ * - always encode the lenght field
+ * - use compressed receive block bitmap if it's smaller than uncompressed
+ * receive block bitmap
+ * - use the remaining bits for an uncompressed receive block bitmap if needed
+ *
+ * Note: The spec also defines an Ack/Nack without length field, but the PCU's
+ * doesn't support this in UL. It would require a lot more code complexity
+ * and only saves 7 bit in lossy sitations.
+ */
static void write_packet_ack_nack_desc_egprs(
bitvec * dest, unsigned& wp,
gprs_rlc_ul_window *window, bool is_final, unsigned rest_bits)
@@ -849,12 +860,12 @@ static void write_packet_ack_nack_desc_egprs(
bitvec ucmp_vec;
bitvec crbb_vec;
uint8_t uclen_crbb = 0;
- bool len_coded = true;
uint8_t crbb_start_clr_code;
uint8_t i;
/* static size of 16 bits
- ..0. .... = ACKNACK: (Union)
+ ..1. .... = ACKNACK: (Union)
+ 0 0000 000 Length
Desc
...0 .... = FINAL_ACK_INDICATION: False
@@ -865,8 +876,9 @@ static void write_packet_ack_nack_desc_egprs(
.... ..10 0101 0001 1... .... = STARTING_SEQUENCE_NUMBER: 1187
- .0.. .... = CRBB Exist: 0 */
- rest_bits -= 16;
+ .0.. .... = CRBB Exist: 0
+ minimal size is 24 rest_bits */
+ rest_bits -= 24;
if (num_blocks > 0)
/* V(Q) is NACK and omitted -> SSN = V(Q) + 1 */
@@ -903,47 +915,31 @@ static void write_packet_ack_nack_desc_egprs(
crbb_len = crbb_vec.cur_bit;
}
- if (is_compressed == 0) {
- /* length field takes 8 bits*/
- if (num_blocks > rest_bits - 8) {
- eow = false;
- urbb_len = rest_bits;
- len_coded = false;
- } else if (num_blocks == rest_bits) {
- urbb_len = rest_bits;
- len_coded = false;
- } else
- urbb_len = num_blocks;
- len = urbb_len + 15;
+ if (is_compressed) {
+ /* 8 = 7 (CRBBlength) + 1 (CRBB starting color code) */
+ rest_bits -= 8;
} else {
- if (num_blocks > uclen_crbb) {
- eow = false;
- urbb_len = num_blocks - uclen_crbb;
- }
- /* Union bit takes 1 bit */
- /* Other fields in descr of compresed bitmap takes 23 bits
- * -8 = CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
- if (urbb_len > (rest_bits - crbb_len - 8)) {
- eow = false;
- len_coded = false;
- urbb_len = rest_bits - crbb_len - 8;
- /* -16 = ACKNACK Dissector length + CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
- } else if (urbb_len > (rest_bits - crbb_len - 16)) {
- eow = false;
- len_coded = false;
- urbb_len = rest_bits - crbb_len - 16;
- }
- len = urbb_len + crbb_len + 23;
+ uclen_crbb = 0;
+ crbb_len = 0;
}
- /* EGPRS Ack/Nack Description IE */
- if (len_coded == false) {
- bitvec_write_field(dest, &wp, 0, 1); // 0: don't have length
- } else {
- bitvec_write_field(dest, &wp, 1, 1); // 1: have length
- bitvec_write_field(dest, &wp, len, 8); // length
- }
+ if (num_blocks > uclen_crbb + rest_bits) {
+ eow = false;
+ urbb_len = rest_bits - crbb_len;
+ } else
+ urbb_len = num_blocks - uclen_crbb;
+
+ if (is_compressed)
+ len = urbb_len + crbb_len + 23;
+ else
+ len = urbb_len + 15;
+
+
+ /* EGPRS Ack/Nack Description IE
+ * do not support Ack/Nack without length */
+ bitvec_write_field(dest, &wp, 1, 1); // 1: have length
+ bitvec_write_field(dest, &wp, len, 8); // length
bitvec_write_field(dest, &wp, is_final, 1); // FINAL_ACK_INDICATION
bitvec_write_field(dest, &wp, bow, 1); // BEGINNING_OF_WINDOW
@@ -973,9 +969,9 @@ static void write_packet_ack_nack_desc_egprs(
}
LOGP(DRLCMACUL, LOGL_DEBUG,
"EGPRS URBB, urbb len = %d, SSN = %u, ESN_CRBB = %u, "
- "len present = %s,desc len = %d, "
+ "desc len = %d, "
"SNS = %d, WS = %d, V(Q) = %d, V(R) = %d%s%s\n",
- urbb_len, ssn, esn_crbb, len_coded ? "yes" : "No" , len,
+ urbb_len, ssn, esn_crbb, len,
window->sns(), window->ws(), window->v_q(), window->v_r(),
bow ? ", BOW" : "", eow ? ", EOW" : "");