library/RLCMAC: Add partial support for EGPRS data block encoding/decoding

* RlcmacUlBlock and RlcmacDlBlock gain a new union field "egprs_data",
  which is chosen when msg contains an egprs data block. Hence one can
  use same structure for both gprs/egprs data and simply check
  "ischosen(block.data_egprs)" to know whether it contains egprs or gprs
  data block.
* C++ code in RLCMAC_EncDec.cc takes care of encoding and decoding of
  each data header type and exposes a generic ttcn3 struct
  "UlMacDataHeader" and "DlMacDataHeader". Decoded header type can be
  found in mac_hdr.header_type. This can be used t5ogether with CPS to
  get the MCS of the message received. Similarly, the encoder will use the
  same field to know how to encode the ttcn3 structure.
* In RLCMAC_EncDec.cc order of functions has been ordered to split
  between encoding and decoding, and inside these split between Ul and
  Dl messages.
* Only encoding of UL HeaderType3 and decoding of Dl HeaderType3 is
  implemented so far in RLCMAC_EncDec.cc. However, all code is already
  arranged and functions prepared (with FIXME fprintf) to easily add the
  missing header types once needed.
* Actually only the decoding of DL HeaderType3 has been tested to work so far.
  Encoding may still be missing to octet-align the data block after the header.
  All these wil lbe fixed once a test using them exists.

Change-Id: I2bc4f877a5e17c57ffa8cf05565dc8593b45aae8
diff --git a/library/RLCMAC_Types.ttcn b/library/RLCMAC_Types.ttcn
index 8688d36..e5c2464 100644
--- a/library/RLCMAC_Types.ttcn
+++ b/library/RLCMAC_Types.ttcn
@@ -41,11 +41,18 @@
 		return 0;
 	}
 
+	type enumerated EgprsHeaderType {
+		RLCMAC_HDR_TYPE_1,
+		RLCMAC_HDR_TYPE_2,
+		RLCMAC_HDR_TYPE_3
+	};
+
 	type enumerated CodingScheme {
 		CS_1,
 		CS_2,
 		CS_3,
 		CS_4,
+		MCS_0,
 		MCS_1,
 		MCS_2,
 		MCS_3,
@@ -238,6 +245,52 @@
 	external function dec_RlcmacDlDataBlock(in octetstring stream) return RlcmacDlDataBlock;
 
 
+	/* a single RLC block / LLC-segment */
+	type record EgprsLlcBlockHdr {
+		uint7_t		length_ind,
+		/* 0 = another extension octet after LLC PDU, 1 = no more extension octets */
+		boolean		e
+	} with {
+		variant (e) "FIELDLENGTH(1)"
+		encode "RAW"
+	};
+
+	external function enc_EgprsLlcBlockHdr(in EgprsLlcBlockHdr si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_EgprsLlcBlockHdr(in octetstring stream) return EgprsLlcBlockHdr
+		with { extension "prototype(convert) decode(RAW)" };
+
+	type record EgprsLlcBlock {
+		/* Header is only present if LI field was present */
+		EgprsLlcBlockHdr	hdr optional,
+		octetstring 		payload
+	} with { variant "" };
+	type record of EgprsLlcBlock EgprsLlcBlocks;
+
+	/* TS 44.060 10.3a.1.1 EGPRS downlink RLC data block, manual c++ encoder/decoder */
+	type record EgprsDlMacDataHeader {
+		EgprsHeaderType	header_type, /* Set internally by decoder */
+		uint5_t		tfi,
+		MacRrbp		rrbp,
+		BIT2		esp,
+		uint3_t		usf,
+		uint14_t	bsn1,
+		uint8_t		bsn2_offset,
+		uint2_t		pr, /* power reduction */
+		uint2_t		spb,
+		uint4_t		cps
+	} with { variant "" };
+	/* Manual C++ Decoder: */
+	type record RlcmacDlEgprsDataBlock {
+		EgprsDlMacDataHeader	mac_hdr,
+		boolean			fbi,
+		boolean			e,
+		EgprsLlcBlocks		blocks
+	} with {
+		variant (fbi) "FIELDLENGTH(1)"
+		variant (e) "FIELDLENGTH(1)"
+	};
+
 	/* TS 44.060 10.2.2 */
 	type record UlMacDataHeader {
 		/* Octet 0 */
@@ -268,6 +321,35 @@
 		variant (m) "FIELDLENGTH(1)"
 	};
 
+	/* TS 44.060 10.3a.1.1 10.3a.4 EGPRS Uplink RLC/MAC header, manual c++ encoder/decoder */
+	type record EgprsUlMacDataHeader {
+		EgprsHeaderType	header_type, /* Set internally by decoder */
+		uint5_t		tfi,
+		uint4_t		countdown,
+		BIT1		foi_si,
+		BIT1		r_ri,
+		uint11_t	bsn1,
+		uint4_t		cps,
+		boolean		pfi_ind,
+		BIT1		rsb,
+		BIT2		spb
+	} with {
+		variant (pfi_ind) "FIELDLENGTH(1)"
+	};
+	/* Manual C++ Decoder:  10.3a.2.1 EGPRS Uplink RLC data block */
+	type record RlcmacUlEgprsDataBlock {
+		EgprsUlMacDataHeader	mac_hdr,
+		boolean			tlli_ind,
+		boolean			e,
+		/* Octet 3 ... M (optional): manual C++ Decoder */
+		GprsTlli		tlli optional,
+		RlcMacUlPfi		pfi optional,
+		EgprsLlcBlocks		blocks
+	} with {
+		variant (tlli_ind) "FIELDLENGTH(1)"
+		variant (e) "FIELDLENGTH(1)"
+	};
+
 	/* TS 44.060 10.2.2 */
 	type record RlcmacUlDataBlock {
 		/* MAC header */
@@ -286,11 +368,16 @@
 
 	type union RlcmacUlBlock {
 		RlcmacUlDataBlock	data,
+		RlcmacUlEgprsDataBlock	data_egprs,
 		RlcmacUlCtrlBlock	ctrl
 	} with {
 		variant "TAG(data, mac_hdr.payload_type = MAC_PT_RLC_DATA;
-			     ctrl, mac_hdr.payload_type = MAC_PT_RLCMAC_NO_OPT;
-			     ctrl, mac_hdr.payload_type = MAC_PT_RLCMAC_OPT)"
+			     ctrl, {mac_hdr.payload_type = MAC_PT_RLCMAC_NO_OPT,
+				    mac_hdr.payload_type = MAC_PT_RLCMAC_OPT};
+			     data_egprs, {mac_hdr.header_type = RLCMAC_HDR_TYPE_1,
+					  mac_hdr.header_type = RLCMAC_HDR_TYPE_2,
+					  mac_hdr.header_type = RLCMAC_HDR_TYPE_3}
+			     )"
 	};
 
 	/* as the sub-types (RlcmacDl*Block) are not using the RAW coder, we cannot
@@ -301,11 +388,16 @@
 
 	type union RlcmacDlBlock {
 		RlcmacDlDataBlock	data,
+		RlcmacDlEgprsDataBlock	data_egprs,
 		RlcmacDlCtrlBlock	ctrl
 	} with {
 		variant "TAG(data, mac_hdr.mac_hdr.payload_type = MAC_PT_RLC_DATA;
-			     ctrl, mac_hdr.payload_type = MAC_PT_RLCMAC_NO_OPT;
-			     ctrl, mac_hdr.payload_type = MAC_PT_RLCMAC_OPT)"
+			     ctrl, {mac_hdr.payload_type = MAC_PT_RLCMAC_NO_OPT,
+				    mac_hdr.payload_type = MAC_PT_RLCMAC_OPT};
+			     data_egprs, {mac_hdr.header_type = RLCMAC_HDR_TYPE_1,
+					  mac_hdr.header_type = RLCMAC_HDR_TYPE_2,
+					  mac_hdr.header_type = RLCMAC_HDR_TYPE_3}
+			     )"
 	};
 
 	/* as the sub-types (RlcmacDl*Block) are not using the RAW coder, we cannot
@@ -546,6 +638,15 @@
 		}
 	}
 
+	template RlcmacDlBlock tr_RLCMAC_DATA_EGPRS := {
+		data_egprs := {
+			mac_hdr := ?,
+			fbi := ?,
+			e := ?,
+			blocks := ?
+		}
+	}
+
 	/* Template for Uplink MAC Control Header */
 	template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := {
 		payload_type := pt,