diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2016-01-13 13:55:44 +0100 |
---|---|---|
committer | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2016-02-08 00:45:34 +0100 |
commit | ae9c575d2c2e7f906c41d28682445e6c8cb53f03 (patch) | |
tree | b9236fb18dc558431e8fa398b530de4fcb06641f /src/decoding.cpp | |
parent | c2141c6064ddf5283937c7f77468bf2396787804 (diff) |
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
Diffstat (limited to 'src/decoding.cpp')
-rw-r--r-- | src/decoding.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/decoding.cpp b/src/decoding.cpp index cb1b34d4..f4cd8802 100644 --- a/src/decoding.cpp +++ b/src/decoding.cpp @@ -493,3 +493,94 @@ const uint8_t *Decoding::rlc_get_data_aligned( 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; +} |