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;
+}