diff src/g23m-gprs/llc/llc_us.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/llc/llc_us.c	Sun Jul 15 04:40:46 2018 +0000
@@ -0,0 +1,1252 @@
+/*
++-----------------------------------------------------------------------------
+|  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 process internal signals as
+|             described in the SDL-documentation (U-statemachine)
++-----------------------------------------------------------------------------
+*/
+
+#ifndef LLC_US_C
+#define LLC_US_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_f.h"
+
+#include "llc_uf.h"     /* to get local U functions */
+#include "llc_ul.h"     /* to get local U labels */
+#include "llc_t200s.h"  /* to get signal interface to T200 */
+#include "llc_txs.h"    /* to get signal interface to TX */
+#include "llc_llmes.h"  /* to get signal interface to LLME */
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_llme_u_assign_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_LLME_U_ASSIGN_REQ
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_llme_u_assign_req (void)
+{
+  TRACE_ISIG( "sig_llme_u_assign_req" );
+
+  switch (GET_STATE(U))
+  {
+    case U_TLLI_UNASSIGNED:
+      u_init_sapi();
+      SET_STATE (U, U_ADM);
+      break;
+    default:
+      TRACE_ERROR( "SIG_LLME_U_ASSIGN_REQ unexpected" );
+      break;
+  }
+} /* sig_llme_u_assign_req() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_llme_u_unassign_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_LLME_U_UNASSIGN_REQ
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_llme_u_unassign_req (void)
+{
+  TRACE_ISIG( "sig_llme_u_unassign_req" );
+
+  switch (GET_STATE(U))
+  {
+    case U_TLLI_UNASSIGNED:
+      TRACE_ERROR( "SIG_LLME_U_UNASSIGN_REQ unexpected" );
+      break;
+
+    default:
+      sig_u_t200_stop_req();
+      SET_STATE (U, U_TLLI_UNASSIGNED);
+      break;
+  }
+} /* sig_llme_u_unassign_req() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rx_u_data_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RX_U_DATA_IND
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to an LL-UNITDATA-IND
+|                                 primitive
+|               command - contains the command within the primitive
+|               cr_bit - setting of the C/R bit
+|               pf_bit - setting of the P/F bit
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rx_u_data_ind (T_LL_UNITDATA_IND *ll_unitdata_ind,
+                               T_COMMAND command,
+                               T_BIT cr_bit,
+                               T_BIT pf_bit)
+{
+  BOOL              reset_received;
+  BOOL              xid_ind;
+  BOOL              rc_xid_valid;
+  BOOL              l3p_outstanding;
+
+
+  TRACE_ISIG( "sig_rx_u_data_ind" );
+
+  /*
+   * Set TLLI for current transaction.
+   */
+  llc_data->u->current_tlli = ll_unitdata_ind->tlli;
+
+  switch (GET_STATE(U))
+  {
+    case U_ADM:
+      if (cr_bit EQ SGSN_COMMAND)
+      {
+        /*
+         * Label ADM_COMMAND
+         */
+        switch (command)
+        {
+          case U_SABM: /* COMMAND ADM */
+            /*
+             * Label ADM_SABM
+             */
+            if (pf_bit EQ 1)
+            {
+              if ( (llc_data->current_sapi EQ LL_SAPI_1) ||
+                   (llc_data->current_sapi EQ LL_SAPI_7)  )
+              {
+                /*
+                 * ABM not possible on SAPI 1 and 7
+                 */
+                PFREE (ll_unitdata_ind);
+
+                u_send_dm (pf_bit);
+              }
+              else /* current_sapi is one of 3, 5, 9, or 11 */
+              {
+                rc_xid_valid = u_check_xid (&(ll_unitdata_ind->sdu),
+                  cr_bit, command);
+
+                PFREE (ll_unitdata_ind);
+
+                if (rc_xid_valid)
+                {
+                  /*
+                   * No check needed, reset_received cannot be TRUE
+                   * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless
+                   * (LL_ESTABLISH_IND contains N201-U/I).
+                   */
+                  u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+                  /*
+                   * Check XID/SABM collision issue - XID command shall
+                   * be treated as not transmitted.
+                   */
+                  if (llc_data->u->xid_pending)
+                  {
+                    llc_data->u->xid_pending = FALSE;
+
+                    sig_u_t200_stop_req();
+                  }
+
+                  /*
+                   * Label S_EST_IND
+                   */
+                  u_label_s_est_ind (pf_bit);
+                }
+              }
+            }
+            else /* pf_bit is not set */
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+
+          case U_XID: /* COMMAND  ADM */
+            /*
+             * Label XID
+             */
+            u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          case U_DISC: /* COMMAND ADM */
+            PFREE (ll_unitdata_ind);
+            if (pf_bit EQ 1)
+            {
+              u_send_dm (pf_bit);
+            }
+            break;
+
+          default:
+            if (pf_bit EQ 1)
+            {
+              llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+              /*
+               * Label FRMR_COND
+               */
+              u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+                llc_data->u->frmr_reason);
+            }
+            else
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+        }
+      }
+      else /* SGSN_RESPONSE */
+      {
+        /*
+         * Label ADM_RESPONSE
+         */
+        switch (command)
+        {
+          case U_UA: /* RESPONSE ADM */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI);
+            break;
+
+          case U_DM: /* RESPONSE ADM */
+            PFREE (ll_unitdata_ind);
+            break;
+
+          case U_XID: /* RESPONSE ADM */
+           /*
+            * Label XIDRES
+            */
+            u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          case U_FRMR: /* RESPONSE ADM */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED);
+            break;
+
+          default:
+            llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+            /*
+             * Label FRMR_COND
+             */
+            u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+              llc_data->u->frmr_reason);
+            break;
+        }
+      }
+      break; /* U_ADM */
+
+    case U_LOCAL_ESTABLISHMENT:
+      if (cr_bit EQ SGSN_COMMAND)
+      {
+        /*
+         * Label LEST_COMMAND
+         */
+        switch (command)
+        {
+          case U_SABM: /* COMMAND LOCAL_ESTABLISHMENT */
+            /*
+             * Label LEST_SABM
+             */
+
+            if (pf_bit EQ 1)
+            {
+              rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu, cr_bit,
+                command);
+
+              PFREE (ll_unitdata_ind);
+
+              if (rc_xid_valid)
+              {
+                if ((llc_data->decoded_l3_xid.valid EQ TRUE) AND
+                  !(llc_data->u->xid_tag_sent & (0x00000001L << XID_LAYER_3)))
+                {
+                  /*
+                   * No check needed, reset_received cannot be TRUE
+                   * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless
+                   * (LL_ESTABLISH_IND contains N201-U/I).
+                   */
+                  u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+                  /*
+                   * Label S_EST_IND
+                   */
+                  u_label_s_est_ind (pf_bit);
+                }
+              }
+            }
+            else /* pf_bit is not set */
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+
+          case U_DISC: /* COMMAND LOCAL_ESTABLISHMENT */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              PALLOC (ll_release_ind, LL_RELEASE_IND);
+
+              ll_release_ind->sapi  = llc_data->current_sapi;
+#ifdef LL_2to1
+              ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc;
+              ll_release_ind->ps_cause.value.llc_cause = LL_RELCS_NORMAL;
+#else
+              ll_release_ind->cause = LL_RELCS_NORMAL;
+#endif
+
+              TRACE_1_OUT_PARA("s:%d", ll_release_ind->sapi);
+              PSEND (hCommSNDCP, ll_release_ind);
+
+              u_send_dm (1);
+
+              SET_STATE (U, U_ADM);
+            }
+            break;
+
+          case U_XID: /* COMMAND  LOCAL_ESTABLISHMENT */
+            /*
+             * Label XID_SABM_SEND
+             */
+            u_label_xid_sabm_send (ll_unitdata_ind, cr_bit, pf_bit);
+            break;
+
+          default:
+            if (pf_bit EQ 1)
+            {
+              llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+
+              /*
+               * Label FRMR_COND
+               */
+              u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+                llc_data->u->frmr_reason);
+            }
+            else
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+        }
+      }
+      else /* SGSN_RESPONSE */
+      {
+        /*
+         * Label LEST_RESPONSE
+         */
+        switch (command)
+        {
+          case U_UA: /* RESPONSE LOCAL_ESTABLISHMENT */
+            /*
+             * Label LEST_UA
+             */
+
+            if (pf_bit EQ 1)
+            {
+              rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu,
+                                          cr_bit, command);
+
+              if (rc_xid_valid)
+              {
+                l3p_outstanding = (llc_data->u->xid_tag_sent & (0x1L << XID_LAYER_3)) ? TRUE : FALSE;
+
+                /*
+                 * An UA response frame should only be handled if the XID L3
+                 * para are included or not same as requested. Else ignore it!
+                 */
+                if (llc_data->decoded_l3_xid.valid == l3p_outstanding)
+                {
+                  /*
+                   * <R.LLC.ABMEST_R.A.018>
+                   */
+                  sig_u_t200_stop_req();
+
+                  /*
+                   * If an XID parameter is not included in the response and
+                   * if it was included in the request, the requested value is
+                   * implicit accepted.
+                   */
+                  u_handle_optimization ();
+
+                  /*
+                   * Reset_received cannot be TRUE, otherwise
+                   * frame would not be valid
+                   */
+                  u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+                  PFREE (ll_unitdata_ind);
+
+                  if (llc_data->u->release_requested == TRUE)
+                  {
+                    /*
+                     * Do not send any establish confirmation to L3 and start
+                     * release procedure
+                     */
+                    llc_data->u->retransmission_counter = 0;
+
+                    SET_STATE (U, U_LOCAL_RELEASE);
+
+                    /*
+                     * Send GRLC_DATA_REQ (DISC), start T200.
+                     */
+                    u_send_disc();
+                  }
+                  else
+                  {
+                    if (llc_data->u->ind_cnf_establishment EQ IND_ESTABLISHMENT)
+                    {
+                      u_send_ll_establish_ind ();
+
+                      SET_STATE (U, U_ESTABLISH_RES_PENDING);
+
+                      /*
+                       * start ABM (re-)establish when establish response is received
+                       */
+                    }
+                    else /* CNF_ESTABLISHMENT */
+                    {
+                      u_send_ll_establish_cnf ();
+
+                      SET_STATE (U, U_ABM);
+
+                      /*
+                       * inform LLME about (re-)establischment
+                       */
+                      sig_u_llme_abmest_ind();
+                    }
+                  }
+                }
+                else
+                {
+                  PFREE (ll_unitdata_ind);
+                }
+              }
+              else
+              {
+                PFREE (ll_unitdata_ind);
+
+                /*
+                 * request T200 to let the timer manually expire,
+                 * thus retransmitting the frame immediately
+                 */
+                sig_u_t200_expire_req ();
+
+                /* SET_STATE (U, SAME_STATE); */
+              }
+            }
+            else /* pf_bit == 0 */
+            {
+              PFREE (ll_unitdata_ind);
+
+              u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI);
+
+              /* SET_STATE (U, SAME_STATE); */
+            }
+            break;
+
+          case U_DM: /* RESPONSE LOCAL_ESTABLISHMENT */
+            /*
+             * Label LEST_DM
+             */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              sig_u_t200_stop_req();
+
+              if (llc_data->u->release_requested == TRUE)
+              {
+                u_send_ll_release_cnf ();
+              }
+              else
+              {
+                u_send_ll_release_ind (LL_RELCS_DM_RECEIVED);
+              }
+
+              SET_STATE (U, U_ADM);
+            }
+            break;
+
+          case U_XID: /* RESPONSE LOCAL_ESTABLISHMENT */
+           /*
+            * Label XIDRES
+            */
+            u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          case U_FRMR: /* RESPONSE LOCAL_ESTABLISHMENT */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED);
+            break;
+
+          default:
+            llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+
+            /*
+             * Label FRMR_COND
+             */
+            u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+              llc_data->u->frmr_reason);
+            break;
+        }
+      }
+      break; /* U_LOCAL_ESTABLISHMENT */
+
+    case U_ABM:
+      if (cr_bit EQ SGSN_COMMAND)
+      {
+        /*
+         * Label ABM_COMMAND
+         */
+        switch (command)
+        {
+          case U_SABM: /* COMMAND ABM */
+            /*
+             * Label ABM_REEST_PEER
+             */
+            if (pf_bit EQ 1)
+            {
+              u_send_llgmm_status_ind (LLGMM_ERRCS_PEER_REEST);
+
+              rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu,
+                cr_bit, command);
+
+              PFREE (ll_unitdata_ind);
+
+              if (rc_xid_valid)
+              {
+                /*
+                 * No check needed, reset_received cannot be TRUE
+                 * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless
+                 * (LL_ESTABLISH_IND contains N201-U/I).
+                 */
+                u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+                /*
+                 * Label S_EST_IND
+                 */
+                u_label_s_est_ind (pf_bit);
+              }
+            }
+            else /* pf_bit == 0 */
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+
+          case U_DISC: /* COMMAND ABM */
+            /*
+             * Label ABM_DISC
+             */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              PALLOC (ll_release_ind, LL_RELEASE_IND);
+
+              ll_release_ind->sapi  = llc_data->current_sapi;
+#ifdef LL_2to1
+              ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc;
+              ll_release_ind->ps_cause.value.llc_cause = LL_RELCS_NORMAL;
+#else
+              ll_release_ind->cause = LL_RELCS_NORMAL;
+#endif
+              TRACE_1_OUT_PARA("s:%d", ll_release_ind->sapi);
+              PSEND (hCommSNDCP, ll_release_ind);
+
+              SET_STATE (U, U_ADM);
+
+              sig_u_llme_abmrel_ind();
+
+              /*
+               * Send UA response without XID information field (= FALSE).
+               */
+              u_send_ua (pf_bit, FALSE);
+            }
+            break;
+
+          case U_XID: /* COMMAND  ABM */
+            /*
+             * Label XID
+             */
+            u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          default:
+            if (pf_bit EQ 1)
+            {
+              llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL_ABM;
+
+              /*
+               * Label FRMR_COND_REEST
+               */
+              u_label_frmr_cond_reest (ll_unitdata_ind, cr_bit,
+                llc_data->u->frmr_reason);
+            }
+            else
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+        }
+      }
+      else /* SGSN_RESPONSE */
+      {
+        /*
+         * Label ABM_RESPONSE
+         */
+        switch (command)
+        {
+          case U_UA: /* RESPONSE ABM */
+            /*
+             * Label ABM_UA
+             */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI);
+            break;
+
+          case U_DM: /* RESPONSE ABM */
+            /*
+             * Label ABM_DM
+             */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              u_send_llgmm_status_ind (LLGMM_ERRCS_DM1_RECEIVED);
+            }
+            else /* pf_bit == 0 */
+            {
+              u_send_llgmm_status_ind (LLGMM_ERRCS_DM0_RECEIVED_REEST);
+
+              llc_data->u->retransmission_counter = 0;
+
+              /*
+               * Send LL_ESTABLISH_IND after successful establishment.
+               */
+              llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT;
+
+              SET_STATE (U, U_LOCAL_ESTABLISHMENT);
+
+              sig_u_llme_abmrel_ind();
+
+              /*
+               * Re-establishment procedure: send GRLC_DATA_REQ (SABM),
+               * start T200.
+               */
+              u_send_sabm();
+            }
+            break;
+
+          case U_XID: /* RESPONSE ABM */
+           /*
+            * Label XIDRES
+            */
+            u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          case U_FRMR: /* RESPONSE ABM */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED);
+            break;
+
+          default:
+            llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL_ABM;
+
+            /*
+             * Label FRMR_COND_REEST
+             */
+            u_label_frmr_cond_reest (ll_unitdata_ind, cr_bit,
+              llc_data->u->frmr_reason);
+            break;
+        }
+      }
+      break; /* U_ABM */
+
+    case U_LOCAL_RELEASE:
+      if (cr_bit EQ SGSN_COMMAND)
+      {
+        /*
+         * Label LREL_COMMAND
+         */
+        switch (command)
+        {
+          case U_SABM: /* COMMAND LOCAL_RELEASE */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              /*
+               * Send DM response with F bit set to 1.
+               */
+              u_send_dm (1);
+            }
+            break;
+
+          case U_DISC: /* COMMAND LOCAL_RELEASE */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              /*
+               * Send UA response with F bit set to 1, but without information
+               * field (= FALSE).
+               */
+              u_send_ua (1, FALSE);
+            }
+            break;
+
+          case U_XID: /* COMMAND  LOCAL_RELEASE */
+            /*
+             * Label XID
+             */
+            u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          default:
+            if (pf_bit EQ 1)
+            {
+              llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+
+              /*
+               * Label FRMR_COND
+               */
+              u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+                llc_data->u->frmr_reason);
+            }
+            else
+            {
+              PFREE (ll_unitdata_ind);
+            }
+            break;
+        }
+      }
+      else /* SGSN_RESPONSE */
+      {
+        /*
+         * Label LREL_RESPONSE
+         */
+        switch (command)
+        {
+          case U_UA: /* RESPONSE LOCAL_RELEASE */
+            /*
+             * no break!
+             */
+          case U_DM: /* RESPONSE LOCAL_RELEASE */
+            /*
+             * Label LREL_UA_DM
+             */
+            PFREE (ll_unitdata_ind);
+
+            if (pf_bit EQ 1)
+            {
+              SET_STATE (U, U_ADM);
+
+              sig_u_t200_stop_req();
+
+              u_send_ll_release_cnf();
+            }
+            else /* pf_bit == 0 */
+            {
+              if (command EQ U_UA)
+              {
+                u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI);
+              }
+            }
+            break;
+
+          case U_XID: /* RESPONSE LOCAL_RELEASE */
+           /*
+            * Label XIDRES
+            */
+            u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit);
+            break;
+
+          case U_FRMR: /* RESPONSE LOCAL_RELEASE */
+            PFREE (ll_unitdata_ind);
+            u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED);
+            break;
+
+          default:
+            llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL;
+
+            /*
+             * Label FRMR_COND
+             */
+            u_label_frmr_cond (ll_unitdata_ind, cr_bit,
+              llc_data->u->frmr_reason);
+            break;
+        }
+      }
+      break; /* U_LOCAL_RELEASE */
+
+    default:
+      PFREE (ll_unitdata_ind);
+      TRACE_ERROR( "SIG_RX_U_DATA_IND unexpected" );
+      break;
+  }
+} /* sig_rx_u_data_ind() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rx_u_frmr_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RX_U_FRMR_IND
+|
+| Parameters  : ll_unitdata_ind   - valid pointer to the frame that caused the
+|                                   frame rejection condition
+|               pdu_type          - type of frame
+|               frmr_ctrl_length  - length of frame control field, if known
+|               cr_bit            - C/R bit setting of frame
+|               frmr_reason       - reason of frame rejection condition
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rx_u_frmr_ind (T_LL_UNITDATA_IND *ll_unitdata_ind,
+                               T_PDU_TYPE pdu_type,
+                               USHORT frmr_ctrl_length,
+                               T_BIT cr_bit,
+                               UBYTE frmr_reason)
+{
+  TRACE_ISIG( "sig_rx_u_frmr_ind" );
+
+  /*
+   * Set TLLI for current transaction.
+   */
+  llc_data->u->current_tlli = ll_unitdata_ind->tlli;
+
+  switch (GET_STATE (U))
+  {
+    case U_ADM:
+    case U_LOCAL_ESTABLISHMENT:
+    case U_ESTABLISH_RES_PENDING:
+    case U_REMOTE_ESTABLISHMENT:
+      /*
+       * No break!
+       */
+    case U_LOCAL_RELEASE:
+      u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND);
+
+      u_send_frmr (ll_unitdata_ind, pdu_type, frmr_ctrl_length,
+        llc_data->sapi->vs, llc_data->sapi->vr,
+        cr_bit, frmr_reason);
+
+      PFREE (ll_unitdata_ind);
+      break;
+    case U_ABM:
+      u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND_REEST);
+
+      SET_STATE (U, U_LOCAL_ESTABLISHMENT);
+
+      /*
+       * Set bit W4 in frmr_reason to indicate ABM mode.
+       */
+      frmr_reason |= FRMR_W4;
+
+      u_send_frmr (ll_unitdata_ind, pdu_type, frmr_ctrl_length,
+        llc_data->sapi->vs, llc_data->sapi->vr,
+        cr_bit, frmr_reason);
+
+      sig_u_llme_abmrel_ind();
+
+      PFREE (ll_unitdata_ind);
+
+      llc_data->u->retransmission_counter = 0;
+
+      /*
+       * Send LL_ESTABLISH_IND after successful establishment.
+       */
+      llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT;
+
+      /*
+       * Re-establishment procedure: send GRLC_DATA_REQ (SABM), start T200.
+       */
+      u_send_sabm();
+      break;
+    default:
+      PFREE (ll_unitdata_ind);
+      TRACE_ERROR( "SIG_RX_U_FRMR_IND unexpected" );
+      break;
+  }
+
+} /* sig_rx_u_frmr_ind() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_t200_u_expired_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_T200_U_EXPIRED_IND
+|
+| Parameters  : grlc_data_req - a valid pointer to the frame (primitive) that
+|                               is associated with the timer
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_t200_u_expired_ind
+(
+#ifndef LL_DESC
+  T_LL_UNITDATA_REQ  *ll_unitdesc_req,
+#else
+  T_LL_UNITDESC_REQ  *ll_unitdesc_req,
+#endif
+  UBYTE cause,
+  T_EXPIRY_MODE_TYPE mode
+)
+{
+  UBYTE  u_state;
+
+  TRACE_ISIG( "sig_t200_u_expired_ind" );
+
+  /*
+   * Set TLLI for current transaction.
+   */
+  llc_data->u->current_tlli = llc_data->tlli_new;
+
+  u_state = GET_STATE(U);
+  switch (u_state)
+  {
+    case U_LOCAL_ESTABLISHMENT:
+      /*
+       * First check if an L3 release requested is pendling
+       */
+      if (llc_data->u->release_requested == TRUE)
+      {
+        /*
+         * Do not restart timer. Send the release confirm.
+         */
+#ifdef LL_DESC
+        llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+        PFREE (ll_unitdesc_req);
+
+        u_send_ll_release_cnf();
+
+        SET_STATE (U, U_ADM);
+      }
+      else
+      {
+        /*
+         * Increment retransmission_counter.
+         */
+        llc_data->u->retransmission_counter++;
+
+        if (llc_data->u->retransmission_counter <= *(llc_data->n200))
+        {
+          /*
+           * T200 has to be started before the primitive is sent to TX, because
+           * the primitive is copied by t200_start() and it may not be valid
+           * anymore after sending to TX.
+           */
+          sig_u_t200_start_req (ll_unitdesc_req, cause);
+
+          sig_u_tx_data_req (ll_unitdesc_req, cause);
+        }
+        else /* retransmission_counter exceeds N200 */
+        {
+#ifdef LL_DESC
+          llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+          PFREE (ll_unitdesc_req);
+
+          /*
+           * Label LEST_N200
+           */
+
+          u_send_llgmm_status_ind (LLGMM_ERRCS_SABM_NO_PEER_RES);
+
+          if (mode == EXPIRY_TIMED)
+          {
+            u_send_ll_release_ind (LL_RELCS_NO_PEER_RES);
+          }
+          else /* EXPIRY_REQUESTED */
+          {
+            /*
+             * <R.LLC.ABMEST_R.A.015>
+             * vs. <R.LLC.ABMEST_R.A.030>
+             */
+            u_send_ll_release_ind (LL_RELCS_INVALID_XID);
+          }
+
+          SET_STATE (U, U_ADM);
+        }
+      }
+      break; /* U_LOCAL_ESTABLISHMENT */
+
+    case U_LOCAL_RELEASE:
+      /*
+       * First check if an L3 release requested is pendling
+       */
+      if (llc_data->u->release_requested == TRUE)
+      {
+        /*
+         * Do not restart timer. Send the release confirm.
+         */
+#ifdef LL_DESC
+        llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+        PFREE (ll_unitdesc_req);
+
+        u_send_ll_release_cnf();
+
+        SET_STATE (U, U_ADM);
+      }
+      else
+      {
+        /*
+         * Increment retransmission_counter.
+         */
+        llc_data->u->retransmission_counter++;
+
+        if (llc_data->u->retransmission_counter <= *(llc_data->n200))
+        {
+          /*
+           * T200 has to be started before the primitive is sent to TX, because
+           * the primitive is copied by t200_start() and it may not be valid
+           * anymore after sending to TX.
+           */
+          sig_u_t200_start_req (ll_unitdesc_req, cause);
+          sig_u_tx_data_req (ll_unitdesc_req, cause);
+        }
+        else /* retransmission_counter exceeds N200 */
+        {
+#ifdef LL_DESC
+          llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+          PFREE (ll_unitdesc_req);
+
+          SET_STATE (U, U_ADM);
+
+          u_send_llgmm_status_ind (LLGMM_ERRCS_DISC_NO_PEER_RES);
+          u_send_ll_release_cnf ();
+        }
+      }
+      break;
+
+    case U_ADM:
+    case U_ABM:
+      llc_data->u->retransmission_counter++;
+      if (llc_data->u->retransmission_counter <= *(llc_data->n200))
+      {
+        /* If T200 expires and needs to send SABM the state should
+         * be set properly
+         */
+        if (u_state == U_ADM AND
+            llc_data->u->xid_pending NEQ TRUE )
+        {
+          SET_STATE (U,U_LOCAL_ESTABLISHMENT);
+        }
+        /*
+         * T200 has to be started before the primitive is sent to TX, because
+         * the primitive is copied by t200_start() and it may not be valid
+         * anymore after sending to TX.
+         */
+        sig_u_t200_start_req (ll_unitdesc_req, cause);
+        sig_u_tx_data_req (ll_unitdesc_req, cause);
+
+        /* SET_STATE (U, SAME_STATE); */
+      }
+      else
+      {
+#ifdef LL_DESC
+        llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+        PFREE (ll_unitdesc_req);
+
+        /*
+         * Label XIDSENT_N200
+         */
+
+        u_send_llgmm_status_ind (LLGMM_ERRCS_XID_NO_PEER_RES);
+
+        if (llc_data->u->xid_pending)
+        {
+          llc_data->u->xid_pending = FALSE;
+        }
+
+        if (u_state == U_ADM)
+        {
+          if (llc_data->u->xid_tag_sent & (0x00000001L << XID_LAYER_3))
+          {
+            if (mode == EXPIRY_TIMED)
+            {
+              u_send_ll_status_ind (LL_ERRCS_NO_PEER_RES);
+            }
+            else /* EXPIRY_REQUESTED */
+            {
+              u_send_ll_status_ind (LL_ERRCS_INVALID_XID);
+            }
+          }
+
+          /* SET_STATE (U, SAME_STATE); */
+        }
+        else /* U_ABM */
+        {
+          if (mode == EXPIRY_TIMED)
+          {
+            u_send_ll_release_ind (LL_RELCS_NO_PEER_RES);
+          }
+          else /* EXPIRY_REQUESTED */
+          {
+            /*
+             * <R.LLC.XIDNEG_O.A.016>
+             * vs. <R.LLC.XIDNEG_O.A.022>
+             */
+            u_send_ll_release_ind (LL_RELCS_INVALID_XID);
+          }
+
+          SET_STATE (U, U_ADM);
+
+          sig_u_llme_abmrel_ind();
+        }
+      }
+      break;
+
+    default:
+#ifdef LL_DESC
+      llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first);
+#endif /* LL_DESC */
+      PFREE (ll_unitdesc_req);
+      TRACE_ERROR( "SIG_T200_U_EXPIRED_IND unexpected" );
+      break;
+  }
+} /* sig_t200_u_expired_ind() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_llme_u_reest_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_LLME_U_REEST_REQ
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_llme_u_reest_req ( void )
+{
+  TRACE_FUNCTION( "sig_llme_u_reest_req" );
+
+  switch (GET_STATE(U))
+  {
+    case U_ABM:
+      llc_data->u->retransmission_counter = 0;
+
+      /*
+       * Send LL_ESTABLISH_IND after successful re-establishment.
+       */
+      llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT;
+
+      SET_STATE (U, U_LOCAL_ESTABLISHMENT);
+
+      /*
+       * Send GRLC_DATA_REQ (SABM), start T200.
+       */
+      u_send_sabm();
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_LLME_U_REEST_REQ unexpected" );
+      break;
+  }
+
+} /* sig_llme_u_reest_req() */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_irx_u_no_frame_expected_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_IRX_U_NO_FRAME_EXPECTED_IND
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_irx_u_no_frame_expected_ind ( void )
+{
+  TRACE_FUNCTION( "sig_irx_u_no_frame_expected_ind" );
+
+  switch (GET_STATE(U))
+  {
+    case U_ADM:
+      /*
+       * An LLE shall transmit a DM resonse to any valid command received
+       * that it cannot action: GSM 04.64 Ver 6.7.0 Chapter 6.4.1.4
+       * Upon receiption of an I+S frame in ADM state, the MS shall send
+       * a DM response with F bit set 0.
+       */
+      u_send_dm (0);
+      break;
+
+    case U_LOCAL_ESTABLISHMENT:
+    case U_ESTABLISH_RES_PENDING:
+    case U_REMOTE_ESTABLISHMENT:
+      /*
+       * Ignore S- and I/S-frames received while ABM establishment. Do
+       * not send any response: GSM 04.64 Ver 6.7.0 Chapter 8.5.1.1
+       */
+      break;
+
+    case U_LOCAL_RELEASE:
+      /*
+       * Ignore S- and I/S-frames received while ABM termination. Do
+       * not send any response: GSM 04.64 Ver 6.7.0 Chapter 8.5.2.1
+       */
+      break;
+
+    case U_ABM:
+    default:
+      TRACE_ERROR( "SIG_IRX_U_NO_FRAME_EXPECTED_IND unexpected" );
+      break;
+  }
+
+} /* sig_irx_u_no_frame_expected_ind() */
+