diff src/g23m-gprs/llc/llc_rxp.c @ 183:219afcfc6250

src/g23m-gprs: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Oct 2016 04:24:13 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/llc/llc_rxp.c	Thu Oct 13 04:24:13 2016 +0000
@@ -0,0 +1,632 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  
+|  Modul   :  
++----------------------------------------------------------------------------- 
+|  Copyright 2002 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This modul is part of the entity LLC and implements all 
+|             functions to handles the incoming primitives as described in 
+|             the SDL-documentation (RX-statemachine)
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifndef LLC_RXP_C
+#define LLC_RXP_C
+#endif
+
+#define ENTITY_LLC
+
+/*==== INCLUDES =============================================================*/
+
+#include "typedefs.h"   /* to get Condat data types */
+#include "vsi.h"        /* to get a lot of macros */
+#include "macdef.h"
+#include "gprs.h"
+#include "gsm.h"        /* to get a lot of macros */
+#include "cnf_llc.h"    /* to get cnf-definitions */
+#include "mon_llc.h"    /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "llc.h"        /* to get the global entity definitions */
+
+#include "llc_rxf.h"    /* to get local RX functions */
+#include "llc_us.h"     /* to get signal interface to U */
+#include "llc_uirxs.h"  /* to get signal interface to UIRX */
+#include "llc_irxs.h"   /* to get signal interface to IRX */
+ 
+#ifdef _SIMULATION_
+#include <string.h>     /* to get memcpy() */
+#endif
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+#ifdef _SIMULATION_
+LOCAL void rx_copy_test_primitive_data  (T_GRLC_UNITDATA_IND_TEST 
+                                         *grlc_unitdata_ind_test, 
+                                         T_GRLC_UNITDATA_IND *grlc_unitdata_ind);
+#endif
+
+#ifndef CF_FAST_EXEC
+
+GLOBAL void rx_grlc_xdata_ind             (T_GRLC_UNITDATA_IND *grlc_unitdata_ind);
+
+#endif /* CF_FAST_EXEC */
+
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_grlc_data_ind
++------------------------------------------------------------------------------
+| Description : Handles the primitive GRLC_DATA_IND
+|
+| Parameters  : *grlc_data_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void rx_grlc_data_ind ( T_GRLC_DATA_IND *grlc_data_ind )
+{ 
+  TRACE_FUNCTION( "grlc_data_ind" );
+  
+  switch( GET_STATE( RX ) )
+  {
+    case RX_TLLI_ASSIGNED:
+    {
+      /*
+       * Both primitives are treated the same way and contain the same 
+       * information.
+       */
+      PPASS (grlc_data_ind, grlc_unitdata_ind, GRLC_UNITDATA_IND);
+
+      /*
+       * Primitive is handled in rx_grlc_xdata_ind().
+       */
+      rx_grlc_xdata_ind (grlc_unitdata_ind);
+      break;
+    }
+    default:
+      PFREE_DESC (grlc_data_ind);
+      TRACE_ERROR( "GRLC_DATA_IND unexpected" );
+      break;
+  }
+
+} /* rx_grlc_data_ind() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_grlc_unitdata_ind
++------------------------------------------------------------------------------
+| Description : Handles the primitive GRLC_UNITDATA_IND
+|
+| Parameters  : *grlc_unitdata_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void rx_grlc_unitdata_ind ( T_GRLC_UNITDATA_IND *grlc_unitdata_ind )
+{ 
+  TRACE_FUNCTION( "grlc_unitdata_ind" );
+  
+  switch( GET_STATE( RX ) )
+  {
+    case RX_TLLI_ASSIGNED:
+      /*
+       * Primitive is handled in rx_grlc_xdata_ind().
+       */
+      rx_grlc_xdata_ind (grlc_unitdata_ind);
+      break;
+    default:
+      PFREE_DESC (grlc_unitdata_ind);
+      TRACE_ERROR( "GRLC_UNITDATA_IND unexpected" );
+      break;
+  }
+
+} /* rx_grlc_unitdata_ind() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_cci_decipher_cnf
++------------------------------------------------------------------------------
+| Description : Handles the primitive CCI_DECIPHER_CNF. 
+|               Note: The type LL_UNITDATA_IND is used instead to avoid PPASS
+.
+|
+| Parameters  : *ll_unitdata_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   defined(LL_2to1) */
+
+GLOBAL void rx_cci_decipher_cnf ( T_LL_UNITDATA_IND *ll_unitdata_ind)
+{
+  UBYTE             cipher;
+  T_PDU_TYPE        frame_type;
+  T_COMMAND         command;
+  T_BIT             cr_bit;
+  T_BIT             pf_bit;
+  T_FRAME_NUM       nr;
+  T_FRAME_NUM       ns;
+  BOOL              frame_ok;
+  UBYTE             frame_rej;
+  USHORT            frame_rej_ctrl_length;
+  USHORT            ctrl_len;
+
+
+  TRACE_FUNCTION( "rx_cci_decipher_cnf" );
+
+  cipher  = ll_unitdata_ind->cipher;
+
+  switch( GET_STATE( RX ) )
+  {
+    case RX_TLLI_ASSIGNED:
+      /* variable sapi is "misused" for fcs_check value */
+      if (ll_unitdata_ind->sapi EQ CCI_FCS_PASSED)
+      {
+
+        {
+          /*
+           * Label INTERPRET
+           */
+
+          rx_interpret_frame (&ll_unitdata_ind->sdu, &ll_unitdata_ind->sapi, 
+            &frame_type, &command, &cr_bit, &pf_bit, &nr, &ns, &frame_ok, 
+            &frame_rej, &frame_rej_ctrl_length, cipher);
+
+          SWITCH_LLC (ll_unitdata_ind->sapi);
+
+          /*
+           * In case of I-frames check, if the information field exceeds N201-I
+           */
+          if (frame_type == I_FRAME)
+          {
+            ctrl_len = I_CTRL_MIN_OCTETS;
+
+            /*
+             * Add sizeof SACK-Bitmap, if necessarry (add K+1)
+             */
+            if (command == I_SACK)
+            {
+              ctrl_len += (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf/8)+4] 
+                            & 0x1F) + 1;
+            }
+            
+            if (BYTELEN(ll_unitdata_ind->sdu.l_buf) > *(llc_data->n201_i) + ctrl_len)
+            {
+              frame_ok  = FALSE;
+              frame_rej = FRMR_W2;
+
+              TRACE_0_INFO("Received frame violates N201-I: send FRMR");
+            }
+          }
+
+          /*
+           * frame_ok includes: correct frame length, PD bit == 0, SAPI valid, 
+           * FCS correct, known PDU type.
+           */
+          if (frame_ok EQ TRUE)
+          {
+            rx_strip_llc_header (&ll_unitdata_ind->sdu, frame_type, command);
+
+            /*
+             * Label S_DATA
+             */
+
+            switch (frame_type)
+            {
+              case U_FRAME:
+                /*
+                 * Label U_FRAME
+                 */
+        
+                /*
+                 * Service u_frames receives the SDU within the allocated UNITDATA
+                 * primitive.
+                 */
+                sig_rx_u_data_ind (ll_unitdata_ind, command, cr_bit, pf_bit);
+                break;
+              case UI_FRAME:
+                /*
+                 * Label UI_FRAME
+                 */
+        
+                sig_rx_uirx_data_ind (ll_unitdata_ind, nr);
+                break;
+              case S_FRAME:
+                /*
+                 * No break. S frames and I frames are treated the same way.
+                 */
+              case I_FRAME:
+                /*
+                 * Label I_FRAME
+                 */
+
+                sig_rx_irx_data_ind (ll_unitdata_ind, 
+                                     command, frame_type, cr_bit, pf_bit, ns, nr);
+                break;
+              default:
+                PFREE (ll_unitdata_ind);
+                TRACE_ERROR ("unknown frame type");
+                break;
+            }
+          }
+          else /* frame_ok EQ FALSE */
+          {
+            /*
+             * Check if frame rejection condition occurred, and if U has to be
+             * informed.
+             */
+            if (frame_rej EQ FRAME_NOT_REJ)
+            {
+              TRACE_0_INFO("Frame ignored due to decode problem");
+              PFREE (ll_unitdata_ind);
+            }
+            else /* W1 bit and/or W3 bit set */
+            {
+              /*
+               * Inform U of the frame rejection condition.
+               */
+              TRACE_0_INFO("Frame rejected due to decode problem");
+              sig_rx_u_frmr_ind (ll_unitdata_ind, frame_type, frame_rej_ctrl_length,
+                cr_bit, frame_rej);
+            }
+          }
+        } /* end of validity range of ll_unitdata_ind */
+      }
+      else /* fcs_check EQ CCI_FCS_FAILED */
+      {
+#ifdef TRACE_EVE
+        UBYTE sapi;
+
+        rx_interpret_frame (&ll_unitdata_ind->sdu, &sapi, 
+          &frame_type, &command, &cr_bit, &pf_bit, &nr, &ns, &frame_ok, 
+          &frame_rej, &frame_rej_ctrl_length, cipher);
+#endif
+        TRACE_0_INFO("Frame discarded due to FCS");
+        PFREE (ll_unitdata_ind);
+      }
+      break;
+    default:
+      PFREE(ll_unitdata_ind);
+      TRACE_ERROR( "CCI_DECIPHER_CNF unexpected" );
+      break;
+  }
+
+} /* rx_cci_decipher_cnf() */
+
+/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_grlc_data_ind_test
++------------------------------------------------------------------------------
+| Description : Handles the primitive GRLC_DATA_IND_TEST
+|               NOTE: This is only necessary in simulation environment.
+|
+| Parameters  : *grlc_data_ind_test - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifdef _SIMULATION_
+GLOBAL void rx_grlc_data_ind_test ( T_GRLC_DATA_IND_TEST *grlc_data_ind_test )
+{
+  TRACE_FUNCTION( "grlc_data_ind_test" );
+  
+  switch( GET_STATE( RX ) )
+  {
+    case RX_TLLI_ASSIGNED:
+    {
+      /*
+       * Allocate a "normal" GRLC_UNITDATA_IND primitive and copy the data
+       * of the test primitive GRLC_DATA_IND_TEST (sdu) to 
+       * GRLC_UNITDATA_IND (desc_list).
+       */
+      PALLOC_DESC (grlc_unitdata_ind, GRLC_UNITDATA_IND);
+
+      grlc_unitdata_ind->tlli = grlc_data_ind_test->tlli;
+      rx_copy_test_primitive_data ((T_GRLC_UNITDATA_IND_TEST *)grlc_data_ind_test,
+        grlc_unitdata_ind);
+
+      /*
+       * Free the received test primitive.
+       */
+      PFREE (grlc_data_ind_test);
+
+      /*
+       * Primitive is handled in rx_grlc_xdata_ind().
+       */
+      rx_grlc_xdata_ind (grlc_unitdata_ind);
+      break;
+    }
+    default:
+      PFREE (grlc_data_ind_test);
+      TRACE_ERROR( "GRLC_DATA_IND_TEST unexpected" );
+      break;
+  }
+
+} /* rx_grlc_data_ind_test() */
+#endif /* _SIMULATION_ */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_grlc_unitdata_ind_test
++------------------------------------------------------------------------------
+| Description : Handles the primitive GRLC_UNITDATA_IND_TEST
+|               NOTE: This is only necessary in simulation environment.
+|
+| Parameters  : *grlc_unitdata_ind_test - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifdef _SIMULATION_
+GLOBAL void rx_grlc_unitdata_ind_test ( T_GRLC_UNITDATA_IND_TEST 
+                                      *grlc_unitdata_ind_test )
+{
+  TRACE_FUNCTION( "grlc_unitdata_ind_test" );
+  
+  switch( GET_STATE( RX ) )
+  {
+    case RX_TLLI_ASSIGNED:
+    {
+      /*
+       * Allocate a "normal" GRLC_UNITDATA_IND primitive and copy the data
+       * of the test primitive GRLC_UNITDATA_IND_TEST (sdu) to 
+       * GRLC_UNITDATA_IND (desc_list).
+       */
+      PALLOC_DESC (grlc_unitdata_ind, GRLC_UNITDATA_IND);
+
+      grlc_unitdata_ind->tlli = grlc_unitdata_ind_test->tlli;
+      rx_copy_test_primitive_data (grlc_unitdata_ind_test, grlc_unitdata_ind);
+
+      /*
+       * Free the received test primitive.
+       */
+      PFREE (grlc_unitdata_ind_test);
+
+      /*
+       * Primitive is handled in rx_grlc_xdata_ind().
+       */
+      rx_grlc_xdata_ind (grlc_unitdata_ind);
+      break;
+    }
+    default:
+      PFREE (grlc_unitdata_ind_test);
+      TRACE_ERROR( "GRLC_UNITDATA_IND_TEST unexpected" );
+      break;
+  }
+
+} /* rx_grlc_unitdata_ind_test() */
+#endif /* _SIMULATION_ */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_copy_test_primitive_data
++------------------------------------------------------------------------------
+| Description : Copies the data of a TEST primitive (sdu) to a normal 
+|               primitive (desc_list).
+|               ATTENTION: All other parameters of the primitives are left 
+|               untouched and are not copied by this function!
+|
+| Parameters  : *grlc_unitdata_ind_test  - source primitive
+|               *grlc_unitdata_ind       - destination primitive
+|
++------------------------------------------------------------------------------
+*/
+#ifdef _SIMULATION_
+LOCAL void rx_copy_test_primitive_data (T_GRLC_UNITDATA_IND_TEST 
+                                        *grlc_unitdata_ind_test, 
+                                        T_GRLC_UNITDATA_IND *grlc_unitdata_ind)
+{
+#define FRAG_LEN    80 /* value + 6 must fit in an pool with lots of entries */
+
+  T_sdu             *sdu;
+  T_desc            *desc;
+  T_desc            *last_desc = NULL;
+  int               sdu_index;
+  int               length;
+
+
+  sdu = &grlc_unitdata_ind_test->sdu;
+
+  /*
+   * Begin at the first relevant octet.
+   */
+  sdu_index = sdu->o_buf/8;
+
+  /*
+   * Initialise descriptor list length.
+   */
+  grlc_unitdata_ind->desc_list.list_len = 0;
+
+
+  /*
+   * Copy complete SDU to descriptor list using descriptors of max. 10 bytes.
+   */
+  while (sdu_index < sdu->l_buf/8)
+  {
+    /*
+     * Calculate length of descriptor data (= length of remaining sdu buffer
+     * with a maximum of FRAG_LEN)
+     */
+    length = (sdu_index+FRAG_LEN < sdu->l_buf/8) ? FRAG_LEN 
+                                                 : (sdu->l_buf/8 - sdu_index);
+
+    /*
+     * Allocate the necessary size for the data descriptor. The size is 
+     * calculated as follows:
+     * - take the size of a descriptor structure
+     * - subtract one because of the array buffer[1] to get the size of
+     *   descriptor control information
+     * - add number of octets of descriptor data
+     */
+    MALLOC (desc, (USHORT)(sizeof(T_desc) - 1 + length));
+
+    /*
+     * Fill descriptor control information.
+     */
+    desc->next  = (ULONG)NULL;
+    desc->len   = length;
+
+    /*
+     * Add length of descriptor data to list length.
+     */
+    grlc_unitdata_ind->desc_list.list_len  += length;
+
+    /*
+     * Copy user data from SDU to descriptor.
+     */
+    memcpy (desc->buffer, &sdu->buf[sdu_index], length);
+    sdu_index += length;
+
+    if (last_desc)
+    {
+      /*
+       * Add this descriptor (not the first) to the descriptor list.
+       */
+      last_desc->next = (ULONG)desc;
+    }
+    else
+    {
+      /*
+       * Insert first descriptor in descriptor list.
+       */
+      grlc_unitdata_ind->desc_list.first     = (ULONG)desc;
+    }
+
+    /*
+     * Store this descriptor for later use.
+     */
+    last_desc = desc;
+  }
+
+  return;
+} /* rx_copy_test_primitive_data */
+#endif /* _SIMULATION_ */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : rx_grlc_xdata_ind
++------------------------------------------------------------------------------
+| Description : Handles the primitives GRLC_DATA_IND / GRLC_UNITDATA_IND.
+|
+| Parameters  : *grlc_unitdata_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void rx_grlc_xdata_ind ( T_GRLC_UNITDATA_IND *grlc_unitdata_ind )
+{
+  T_PDU_TYPE        frame_type;
+  UBYTE             protected_mode;
+  UBYTE             sapi;
+  T_FRAME_NUM       ns;
+  BOOL              ciphering;
+  USHORT            header_size;
+  BOOL              frame_ok;
+
+
+  TRACE_FUNCTION( "grlc_xdata_ind" );
+
+  /*
+   * Unassigning old TLLI 
+   *
+   * GMM has to be informed, that new TLLI has been received. So GMM can unassign old TLLI 
+   * and old PTMSI in GRLC
+   * Old tlli will be unassigned here. Normally GMM has to sent LLGMM_ASSIGN_REQ with
+   * new_tlli != all 1's and old_tlli == all 1,s. See 04.64 cp. 6.1 <R.LLC.TLLI_ASS.A.002>
+   */
+#ifdef LL_2to1
+  if ( PS_TLLI_INVALID     != llc_data->tlli_old 
+#else
+  if ( LLGMM_TLLI_INVALID     != llc_data->tlli_old 
+#endif
+  &&   grlc_unitdata_ind->tlli != llc_data->tlli_old )
+  {
+    PALLOC ( llgmm_tlli_ind, LLGMM_TLLI_IND );
+      llgmm_tlli_ind->new_tlli = grlc_unitdata_ind->tlli;
+#ifdef LL_2to1
+      llc_data->tlli_old = PS_TLLI_INVALID;
+#else
+      llc_data->tlli_old = LLGMM_TLLI_INVALID;
+#endif
+    PSEND ( hCommGMM,   llgmm_tlli_ind);
+  }
+  rx_analyse_ctrl_field (grlc_unitdata_ind, &frame_type, &protected_mode,
+    &sapi, &ns, &ciphering, &header_size, &frame_ok);
+
+  if (frame_ok EQ TRUE)
+  {
+    /*
+     * Check, if the sapi of the frame is supported. If ok, switch context 
+     * and handle the frame.
+     */
+    switch (sapi)
+    {
+      case LL_SAPI_1:
+      case LL_SAPI_3:
+      case LL_SAPI_5:
+      case LL_SAPI_7:
+      case LL_SAPI_9:
+      case LL_SAPI_11:
+        SWITCH_LLC (sapi);
+        rx_send_decipher_req (grlc_unitdata_ind, frame_type, protected_mode, 
+          ns, header_size, ciphering);
+        /*
+         * Free only the primitive (desc_list copied in rx_send_decipher_req)
+         */
+        PFREE (grlc_unitdata_ind); /* Do not use PFREE_DESC here !*/
+        break;
+
+      default:
+        /*
+         * Ignore frame.
+         * Free prim and desc_list, because they are not used further
+         */
+        PFREE_DESC (grlc_unitdata_ind);
+        TRACE_0_INFO("Frame received for reserved SAPI");
+        break;
+    }
+  }
+  else /* frame_ok NEQ TRUE */
+  {
+    /*
+     * Free GRLC_UNITDATA_IND along with complete descriptor list.
+     */
+    PFREE_DESC (grlc_unitdata_ind);
+    TRACE_EVENT("Frame ignored!");
+  }
+
+  return;
+} /* rx_grlc_xdata_ind() */
+
+#endif /* CF_FAST_EXEC */
+