src added
diff --git a/src/LLC_EncDec.cc b/src/LLC_EncDec.cc
new file mode 100644
index 0000000..b96b961
--- /dev/null
+++ b/src/LLC_EncDec.cc
@@ -0,0 +1,317 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000-2017 Ericsson Telecom AB
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// which accompanies this distribution, and is available at
+// http://www.eclipse.org/legal/epl-v10.html
+///////////////////////////////////////////////////////////////////////////////
+//
+//  File:               LLC_EncDec.cc
+//  Rev:                R2A
+//  Prodnr:             CNL 113 577
+//  Updated:            2008-01-22
+//  Contact:            http://ttcn.ericsson.se
+//  Reference:          3GPP TS 44.064 7.1.0
+ 
+#include "LLC_Types.hh"
+#include <string.h>
+
+// GIVEN IN CODE RECEIVED FROM ERV
+#define CRC_POLY_LLC2  0xad85dd
+
+// GIVEN IN SPECIFICATION
+//#define CRC_POLY_LLC2  0xbba1b5
+
+#define TABLE_LENGTH  256
+
+// For UI frames if PM bit is 0 (unprotected) then CRC will be calculated over Header + N202 octets
+#define N202 4
+
+unsigned int mCRCTable[TABLE_LENGTH];
+
+
+static void BuildCrc24Table()
+{
+ unsigned int i,j;
+ unsigned int reg;
+
+  //TRACE_FUNC( "BuildCrc24Table" );
+
+  for( i = 0; i < TABLE_LENGTH; i++ )
+  {
+    reg = i;
+    for( j = 8; j > 0; j-- )
+    {
+      if( reg & 1 )
+      {
+        
+	reg = (reg>>1) ^ (unsigned int) CRC_POLY_LLC2;
+      }
+      else
+      {
+        reg >>= 1;
+      }
+    }
+    reg &= 0x00ffffffL;
+   
+      mCRCTable[i] = (unsigned int)reg;
+      //TTCN_Logger::begin_event(TTCN_DEBUG);
+     
+      //TTCN_Logger::log_event("mCRCTable[%d]= %d",i,mCRCTable[i]);
+  
+     // TTCN_Logger::end_event();
+
+  }
+}
+
+//---------------------------------------------------------------------------------------
+
+unsigned int  Calculate_CRC(TTCN_Buffer& pdu)
+{
+
+const unsigned char* loc_pdu = pdu.get_data();
+
+ //TTCN_Logger::begin_event(TTCN_DEBUG);
+     
+     //for (size_t i =0; i< pdu.get_len();i++)
+    // {
+     // TTCN_Logger::log_event("%02x ",loc_pdu[i]);
+    // }
+     
+//TTCN_Logger::log_event("\n");      
+     
+//TTCN_Logger::end_event();
+
+BuildCrc24Table();
+
+//TTCN_Logger::begin_event(TTCN_DEBUG);
+//TTCN_Logger::log_event("mCRCTable[%d]= %d\n",255,mCRCTable[255]);
+//TTCN_Logger::log_event("mCRCTable[%d]= 0x%08x (%u)",255,mCRCTable[255]);
+//TTCN_Logger::log_event("\n");      
+//TTCN_Logger::end_event();
+
+unsigned int reg = 0xFFFFFF;
+
+unsigned int length = pdu.get_len();
+
+
+      
+if (  ((loc_pdu[1] >>5) & 0x07) == 0x06 )      //UI frame
+{ 
+ if ((loc_pdu[2] & 0x01) == 0x00)              // PM bit is 0 (unprotected)         
+  { 
+     if(length  > 3 + N202)                     // pdu length is longer than header + N202    
+     {
+     length = 3 + N202;                         // length = header length + N202    
+          
+     }	
+   }              
+}
+
+   
+
+while ( length--)
+  {
+    reg =
+      ((reg>>8) & 0x00ffff)^mCRCTable[(reg^*((unsigned char*)loc_pdu++)) & 0xffL];
+  }
+   //TTCN_Logger::log(TTCN_DEBUG, "reg:%08x\n",reg);	
+   // 1's complement of FCS 
+  reg ^= 0xffffffL;
+  
+  reg = ((reg >> 16) & 0x000000ff)+ ((reg)  & 0x0000ff00) + ((reg <<16 )& 0x00ff0000);
+ //unsigned int tempint = *(unsigned int*)loc_crcBuffer;
+ //reg =  (unsigned int*)loc_crcBuffer ;
+ //TTCN_Logger::log(TTCN_DEBUG, "reg:%08x\n",reg);	
+	
+return  reg & 0x00ffffffL;	
+}
+//---------------------------------------------------------------------------------------
+
+namespace LLC__Types {
+
+OCTETSTRING enc__PDU__LLC(const PDU__LLC& pdu)
+{
+	TTCN_Buffer bb;
+	PDU__LLC pdu2(pdu);
+	
+	if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__U)
+	{
+
+          if (pdu2.pDU__LLC__U().information__field__U().get_selection() ==  Information__field__U::ALT_uA)
+           {int record_of_size = pdu2.pDU__LLC__U().information__field__U().uA().size_of();
+       
+            for (int  i = 0; i < (record_of_size) ; i++)
+	      { 
+	      // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM 
+	      // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+	         if ( pdu2.pDU__LLC__U().information__field__U().uA()[i].typefield() == int2bit(11,5) )
+	          {  
+		   if( pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__Data().l3param().lengthof() > 3)
+		   {		  
+		   pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__length().long__len() = 
+		   pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__Data().l3param().lengthof();		   
+		   }		 		 		  
+		  }
+	      } 
+           }
+
+           if (pdu2.pDU__LLC__U().information__field__U().get_selection() ==  Information__field__U::ALT_sABM)
+        {int record_of_size = pdu2.pDU__LLC__U().information__field__U().sABM().size_of();
+       
+            for (int  i = 0; i < (record_of_size) ; i++)
+	      { 
+	      // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM 
+	      // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+	         if ( pdu2.pDU__LLC__U().information__field__U().sABM()[i].typefield() == int2bit(11,5) )
+	          {  
+		   if( pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__Data().l3param().lengthof() > 3)
+		   {		  
+		   pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__length().long__len() = 
+		   pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__Data().l3param().lengthof();		   
+		   }		 		 		  
+		  }
+	      } 
+           }
+		
+            if (pdu2.pDU__LLC__U().information__field__U().get_selection() ==  Information__field__U::ALT_xID)
+       {int record_of_size = pdu2.pDU__LLC__U().information__field__U().xID().size_of();
+       
+            for (int  i = 0; i < (record_of_size) ; i++)
+	      { 
+	      // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM 
+	      // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+	         if ( pdu2.pDU__LLC__U().information__field__U().xID()[i].typefield() == int2bit(11,5) )
+	          {  
+		   if( pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__Data().l3param().lengthof() > 3)
+		   {		  
+		   pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__length().long__len() = 
+		   pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__Data().l3param().lengthof();		   
+		   }		 		 		  
+		  }
+	      } 
+           }			
+	}
+	
+	
+	if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__U)
+	 {
+	    if ( pdu2.pDU__LLC__U().fCS().ispresent())
+	    {
+	        if ( pdu2.pDU__LLC__U().fCS() == int2oct(0,3) )  // IF ENCODER NEEDS TO GENERATE CRC
+	          {      
+                    pdu2.pDU__LLC__U().fCS() = OMIT_VALUE;
+	            pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+	            unsigned int crcBuffer = Calculate_CRC(bb);
+		    bb.put_os(int2oct(crcBuffer,3));		
+	            return OCTETSTRING (bb.get_len(), bb.get_data());
+	
+		  }
+	    
+	     else {	// IF ENCODER SENDS OUT NONZERO CRC GIVEN IN TTCN TEMPLATE
+	         pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);	
+	         return OCTETSTRING (bb.get_len(), bb.get_data());
+	          }    	    
+	    }	
+	    else {	//FCS OMIT
+	            pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+	            unsigned int crcBuffer = Calculate_CRC(bb);
+		    bb.put_os(int2oct(crcBuffer,3));		
+	            return OCTETSTRING (bb.get_len(), bb.get_data());
+		    
+	         }
+	 }
+	
+	
+	
+	else if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__UI)
+	    {
+	      if ( pdu2.pDU__LLC__UI().fCS().ispresent())
+	       {
+	          if ( pdu2.pDU__LLC__UI().fCS() == int2oct(0,3) )   // IF ENCODER NEEDS TO GENERATE CRC 
+	          {      
+		    pdu2.pDU__LLC__UI().fCS() = OMIT_VALUE;
+	            pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+	            unsigned int crcBuffer = Calculate_CRC(bb);
+		    bb.put_os(int2oct(crcBuffer,3));		
+	            return OCTETSTRING (bb.get_len(), bb.get_data()); 
+		  
+		  }
+		  
+	     else {	// IF ENCODER SENDS OUT NONZERO CRC GIVEN IN TTCN TEMPLATE
+	          pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW); 	
+	          return OCTETSTRING (bb.get_len(), bb.get_data());	    
+	          }
+	       }
+	     else {	//FCS OMIT
+	            pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+	            unsigned int crcBuffer = Calculate_CRC(bb);
+		    bb.put_os(int2oct(crcBuffer,3));		
+	            return OCTETSTRING (bb.get_len(), bb.get_data()); 
+	          }		
+	    }
+	else {TTCN_error("Can not encode LLC PDU");  //Neither UI NOR U
+	
+	      return  OCTETSTRING (bb.get_len(), bb.get_data()); // this is dummy to avoid warning during compilation
+	    }
+	//pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);	
+	//unsigned int crcBuffer = Calculate_CRC(bb);
+		
+	//bb.put_os( int2oct(crcBuffer,3));
+	
+	
+	//return OCTETSTRING (bb.get_len(), bb.get_data());
+		
+}
+
+
+OCTETSTRING enc__PDU__LLC(const PDU__LLC_template& pdu)
+{
+  return enc__PDU__LLC(pdu.valueof());
+}
+
+
+PDU__LLC dec__PDU__LLC(const OCTETSTRING& stream)
+{
+	PDU__LLC retv;
+	TTCN_Buffer bb;
+        OCTETSTRING crc = int2oct(0,3);
+	
+	size_t datalength = stream.lengthof()-3;
+	const unsigned char * CRC_AS_RECEIVED = (const unsigned char *)stream+datalength;
+	bb.put_s(datalength,(const unsigned char *)stream);
+	
+	unsigned int CRC_CALCULATED = Calculate_CRC(bb);
+     
+      // COMPARE CRC RECEIVED IN LLC PDU WITH CRC CALCULATED FROM LLC PDU	
+	if(
+	  (CRC_AS_RECEIVED[ 0 ] != (CRC_CALCULATED & 0xff0000  ) >> 16) ||
+          (CRC_AS_RECEIVED[ 1 ] != (CRC_CALCULATED & 0xff00    ) >> 8) ||
+          (CRC_AS_RECEIVED[ 2 ] != (CRC_CALCULATED & 0xff      )     )
+	  ) 
+	{
+	     TTCN_warning("CRC ERROR IN LLC PDU");  // CRC IS NOT AS EXPECTED
+	     crc=OCTETSTRING(3,CRC_AS_RECEIVED);
+	}
+	 // CRC IS 
+         // FILL CRC octets with zeroes if CRC is OK
+	
+	retv.decode(PDU__LLC_descr_, bb, TTCN_EncDec::CT_RAW);
+	 
+	if (retv.get_selection() == PDU__LLC::ALT_pDU__LLC__UI){
+	   retv.pDU__LLC__UI().fCS() = crc;
+	} 
+	    
+	if (retv.get_selection() == PDU__LLC::ALT_pDU__LLC__U){
+	retv.pDU__LLC__U().fCS() = crc;
+	} 
+	
+	
+	return retv;
+	   
+
+}
+
+}//namespace
diff --git a/src/LLC_Types.ttcn b/src/LLC_Types.ttcn
new file mode 100644
index 0000000..d07a77f
--- /dev/null
+++ b/src/LLC_Types.ttcn
@@ -0,0 +1,328 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000-2017 Ericsson Telecom AB
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// which accompanies this distribution, and is available at
+// http://www.eclipse.org/legal/epl-v10.html
+///////////////////////////////////////////////////////////////////////////////
+//
+//  File:               LLC_Types.ttcn
+//  Description:        This module contains the Logical Link Control protocol (LLC)
+//                      44.064 v7.1.0 with attributes for RAW encoding/decoding.
+//  Rev:                R2A
+//  Prodnr:             CNL 113 577
+//  Updated:            2008-01-22
+//  Contact:            http://ttcn.ericsson.se
+//  Reference:          3GPP TS 44.064 7.1.0
+ 
+module LLC_Types
+{    
+
+import from General_Types all;
+
+external function enc_PDU_LLC(in PDU_LLC pdu) return octetstring;
+external function dec_PDU_LLC(in octetstring stream) return PDU_LLC;
+
+type record Version
+{
+  integer 	version_value (0..15),
+  BIT4		spare
+
+} with {
+  variant (version_value) "FIELDLENGTH(4)";
+}
+
+type octetstring IOV_UI length(4) 
+
+
+type octetstring IOV_I length(4)
+
+
+type record T200
+{
+  BIT4		spare,
+  integer 	t200Value
+} with {
+  variant (t200Value) "FIELDLENGTH(12)";
+  variant (t200Value) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+
+type record N200
+{
+  integer 	retransmissions (0..15),
+  BIT4		spare
+} with {
+  variant (retransmissions) "FIELDLENGTH(4)";
+}     
+
+
+type record N201_U
+{
+  BIT5		spare,
+  integer 	n201UValue
+} with {
+  variant (n201UValue) "FIELDLENGTH(11)";
+  variant (n201UValue) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+
+type record N201_I
+{
+  BIT5		spare,
+  integer 	n201IValue
+}
+with {
+  variant (n201IValue) "FIELDLENGTH(11)";
+  variant (n201IValue) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+type record MD
+{
+  BIT1		spare,
+  integer 	mDValue
+} with {
+  variant (mDValue) "FIELDLENGTH(15)";
+  variant (mDValue) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+
+type record MU
+{
+  BIT1		spare,
+  integer 	mUValue
+} with {
+  variant (mUValue) "FIELDLENGTH(15)";
+  variant (mUValue) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+type integer KD with {variant  "FIELDLENGTH(8)";};	
+
+type integer KU with {variant  "FIELDLENGTH(8)";};	
+
+type octetstring L3param;
+
+type octetstring Reset_LLC length(0);
+
+type union XID_Data
+{
+  Version		version,
+  IOV_UI		iOV_UI,
+  IOV_I		iOV_I,
+  T200		t200,
+  N200		n200,
+  N201_U		n201_U,
+  N201_I		n201_I,
+  MD		mD,	
+  MU		mU,
+  KD		kD,
+  KU		kU,
+  L3param		l3param,
+  Reset_LLC		reset    	
+}
+
+
+type union  XID_length
+{
+  integer short_len,
+  integer long_len
+}with {
+  variant (short_len) "FIELDLENGTH(2)";
+  variant (long_len)  "FIELDLENGTH(8)";
+  variant (long_len)  "BYTEORDER(last)";
+  variant (short_len) "FIELDORDER(msb)";
+  variant (long_len)  "FIELDORDER(msb)";
+
+}
+
+
+type record XID
+{
+  BIT1	  xl,
+  BIT5     typefield,
+  XID_length  xID_length,
+  //Header_XID      header_XID,
+  XID_Data	xID_Data      
+} with { 
+  variant (xID_Data) "CROSSTAG( version, 	typefield = '00000'B;
+				     iOV_UI, 	typefield = '00001'B;
+				     iOV_I, 	typefield = '00010'B;
+				     t200, 	typefield = '00011'B;
+				     n200, 	typefield = '00100'B;
+				     n201_U, 	typefield = '00101'B;
+				     n201_I, 	typefield = '00110'B;
+				     mD, 	typefield = '00111'B;
+				     mU, 	typefield = '01000'B;
+				     kD, 	typefield = '01001'B;
+				     kU, 	typefield = '01010'B;
+				     l3param, 	typefield = '01011'B;
+				     reset, 	typefield = '01100'B;
+				     
+					 )";
+  variant  "FIELDORDER(msb)";
+  variant (xID_length) "CROSSTAG( short_len, 	xl = '0'B;
+				                long_len, 	xl = '1'B;)";
+  variant (xID_length) "LENGTHTO (xID_Data)"
+
+  variant (xID_length) "PADDING(yes)" 
+};
+
+
+type record RejectedFrameControlField_UI
+{
+  Control_field_UI	control_field,
+  OCT4			spare
+}
+
+
+type record RejectedFrameControlField_U
+{
+  Control_field_U		control_field,
+  OCT5			spare
+}		
+
+
+type union RejectedFrameControlField 
+{
+  RejectedFrameControlField_UI 	rejectedFrameControlField_UI,
+  RejectedFrameControlField_U	rejectedFrameControlField_U
+} with {
+  variant "TAG(rejectedFrameControlField_UI,  control_field.format = '110'B;
+		     rejectedFrameControlField_U,   control_field.format = '111'B;
+ 			)";
+};
+
+
+type record of XID UA_Information;
+
+type record of XID SABM_Information;
+
+type record of XID XID_Information;
+
+
+type octetstring DM_Information length(0);
+
+
+type record FRMR_Information
+{
+  RejectedFrameControlField   rejectedFrameControlField,
+  BIT4 			    spare1,
+  BIT9 			    vS,
+  BIT1			    spare2,
+  BIT9			    vR,
+  BIT1			    cR,
+  BIT4			    spare3,
+  BIT1			    w4,
+  BIT1			    w3,
+  BIT1			    w2,
+  BIT1			    w1
+} with {
+  variant (vS) "BYTEORDER(last)";
+  variant (vR) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+};
+
+
+type record Address_field
+{
+  BIT4		sAPI,
+  BIT2		spare,    // '00'B
+  BIT1		cR,      
+  BIT1		pD	  //'0' for LLC
+}
+
+type record Control_field_U
+{
+  BIT4		mBits,	
+  BIT1		pF,
+  BIT3 		format   // '111'B
+}
+
+
+
+type record Control_field_UI
+
+{
+  BIT3 		format,        // '110'B
+  BIT2 		spare, 
+  integer		nU,     //BIT9
+  BIT1		e,
+  BIT1		pM
+} with {
+
+  variant (nU) "FIELDLENGTH(9)";
+  variant (nU) "BYTEORDER(last)";
+  variant  "FIELDORDER(msb)";
+}
+
+
+type union Information_field_U
+{
+  UA_Information		uA,
+  SABM_Information	sABM,
+  FRMR_Information	fRMR,
+  DM_Information		dM,
+  XID_Information		xID  
+};
+
+
+type record PDU_LLC_UI
+{
+  Address_field 		address_field,
+  Control_field_UI 	control_field,
+  octetstring 		information_field_UI, 
+  OCT3			fCS    optional 
+  // fCS ENCODING:
+  //'000000'O in send template -> generate CRC, 
+  // omit in send template -> generate CRC, 
+  // otherwise send out fCS in send template
+  // 
+  // DECODING:
+  // decoder generates '000000'O if CRC OK
+}
+
+
+
+type record PDU_LLC_U
+{
+  Address_field 		address_field,
+  Control_field_U 	control_field,
+  Information_field_U	information_field_U,	
+  OCT3			fCS    optional  
+  // ENCODING:
+  //'000000'O in send template -> generate CRC, 
+  // omit in send template -> generate CRC, 
+  // otherwise send out fCS in send template
+  // 
+  // DECODING:
+  // decoder generates '000000'O if CRC OK
+} with { 
+  variant (information_field_U) "CROSSTAG( uA, 	control_field.mBits = '0110'B;
+				  	      	sABM, 	control_field.mBits = '0111'B;
+				   		fRMR, 	control_field.mBits = '1000'B;
+						dM, 	control_field.mBits = '0001'B;
+						xID, 	control_field.mBits = '1011'B;	
+					 )";
+};
+
+
+type union PDU_LLC
+{
+  PDU_LLC_UI pDU_LLC_UI,
+  PDU_LLC_U  pDU_LLC_U
+} with   { variant "TAG (              
+		pDU_LLC_UI,       		control_field.format ='110'B;	
+		pDU_LLC_U,       		control_field.format ='111'B;
+                         )"
+};
+
+
+
+}with{ encode "RAW"}// end of module