edge: Handle EGPRS PACKET DOWNLINK ACK NACK
Currently this message is ignored.
Support decoding and handling of this message. Use a bitvec for the
decoder that just represents a BSN sequence without any encoding
details (first bit -> first BSN). Return the corresponding BSN range
(snsmod(bsn_begin + bits_in_bitvec) = bsn_end), so snsmod(bsn_end-1)
is the last BSN if there is at least 1. If bsn_begin == bsn_end, no
BSNs has been added.
Note that this bitvec is not yet used for RBB handling. It just calls
the old rcvd_dl_ack with a faked (all bits are 1) RBB map.
Sponsored-by: On-Waves ehf
diff --git a/src/decoding.cpp b/src/decoding.cpp
index cb1b34d..f4cd880 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -493,3 +493,94 @@
Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
return buffer;
}
+
+static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
+ gprs_rlc_dl_window *window)
+{
+ int num_blocks, i;
+
+ num_blocks = window->mod_sns(window->v_s() - window->v_a());
+ for (i = 0; i < num_blocks; i++)
+ bitvec_set_bit(bits, ONE);
+
+ *bsn_begin = window->v_a();
+ *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
+ return num_blocks;
+}
+
+int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
+ bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
+{
+ int urbb_len = desc->URBB_LENGTH;
+ int crbb_len = 0;
+ int num_blocks = 0;
+ struct bitvec urbb;
+ int i;
+ bool have_bitmap;
+ int implicitly_acked_blocks;
+ int ssn = desc->STARTING_SEQUENCE_NUMBER;
+
+ if (desc->FINAL_ACK_INDICATION)
+ return handle_final_ack(bits, bsn_begin, bsn_end, window);
+
+ if (desc->Exist_CRBB)
+ crbb_len = desc->CRBB_LENGTH;
+
+ have_bitmap = (urbb_len + crbb_len) > 0;
+
+ /*
+ * bow & bitmap present:
+ * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
+ * bow & not bitmap present:
+ * V(A)-> [ 11111...11111 ] . SSN .... V(S)
+ * not bow & bitmap present:
+ * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
+ * not bow & not bitmap present:
+ * V(A)-> ... [] . SSN .... V(S)
+ */
+
+ if (desc->BEGINNING_OF_WINDOW) {
+ implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
+
+ for (i = 0; i < implicitly_acked_blocks; i++)
+ bitvec_set_bit(bits, ONE);
+
+ num_blocks += implicitly_acked_blocks;
+ }
+
+ if (have_bitmap) {
+ /* next bit refers to V(Q) and thus is always zero (and not
+ * transmitted) */
+ bitvec_set_bit(bits, ZERO);
+ num_blocks += 1;
+
+ if (crbb_len > 0) {
+ int old_len = bits->cur_bit;
+ /*
+ decode_t4_rle(bits, desc->CRBB, desc->CRBB_LENGTH,
+ desc->CRBB_STARTING_COLOR_CODE);
+ */
+
+ num_blocks += (bits->cur_bit - old_len);
+ }
+
+ urbb.cur_bit = 0;
+ urbb.data = (uint8_t *)desc->URBB;
+ urbb.data_len = sizeof(desc->URBB);
+
+ for (i = urbb_len; i > 0; i--) {
+ /*
+ * Set bit at the appropriate position (see 3GPP TS
+ * 44.060 12.3.1)
+ */
+ int is_ack = bitvec_get_bit_pos(&urbb, i-1);
+ bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
+ }
+ num_blocks += urbb_len;
+ }
+
+ *bsn_begin = window->v_a();
+ *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
+
+ return num_blocks;
+}