diff src/g23m-gsm/sms/sms_rl.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gsm/sms/sms_rl.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,1326 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  GSM-F&D (8411)
+|  Modul   :  SMS_RL
++----------------------------------------------------------------------------- 
+|  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 defines the functions for the relay layer
+|             of the component SMS.
++----------------------------------------------------------------------------- 
+*/   
+
+#ifndef SMS_RL_C
+#define SMS_RL_C
+
+#define ENTITY_SMS
+
+/*==== INCLUDES ===================================================*/
+
+#define SAP_RR    /* get RR causes until all causes are in one document */
+#define SAP_MMCM  /* same reason */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "typedefs.h"
+#include "pcm.h"
+#include "vsi.h"
+#include "custom.h"
+#include "gsm.h"
+#include "message.h"
+#include "ccdapi.h"
+#include "prim.h"
+#include "cus_sms.h"
+#include "cnf_sms.h"
+#include "mon_sms.h"
+#include "pei.h"
+#include "tok.h"
+#include "sms.h"
+#include "sms_em.h"
+
+/*==== EXPORT ======================================================*/
+
+/*==== PRIVAT ======================================================*/
+
+/*==== VARIABLES ===================================================*/
+
+/*==== FUNCTIONS ===================================================*/
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_init                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize the relay layer.
+
+*/
+
+GLOBAL void rl_init (void)
+{
+  GET_INSTANCE_DATA;    
+
+  TRACE_FUNCTION ("rl_init()");
+
+  sms_data->data[0].state[STATE_RL] = RL_IDLE;
+  sms_data->data[1].state[STATE_RL] = RL_IDLE;
+}
+
+/*---- SIGNALS -----------------------------------------------------*/
+
+#ifdef GPRS
+GLOBAL void rl_proceed (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_proceed()");
+
+  if (SMS_INST_GET_STATE (STATE_RL) EQ RL_WAIT_FOR_SEND_ERROR)
+  {
+    SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+
+    tl_report_ind (NULL, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                   SMSRP_ORIGINATING_ENTITY, SMS_RP_CS_PROTOCOL_ERROR));
+  }
+}
+#endif
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_data_ind                |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_DATA_IND.
+
+*/
+
+GLOBAL void rl_data_ind (T_cp_user_data_dl *cp_user_data_dl)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_data_ind()");
+
+  if (sms_data)
+  {
+    if (cp_user_data_dl->rp_mti EQ RP_ERROR_DL)
+      TRACE_EVENT_P1 ("RP_ERROR.CAUSE rcvd: 0x%2.2X",
+                      (int)cp_user_data_dl->rp_error.rp_cause.rp_cause_value);
+
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+   /* ------------------------------------- */
+      case RL_ESTABLISHED:
+   /* ------------------------------------- */
+      case RL_IDLE:
+   /* ------------------------------------- */
+      {
+        SMS_RP_REF(sms_data) = cp_user_data_dl->reference;
+        if (cp_user_data_dl->rp_mti EQ RP_DATA_DL)
+        {
+         /*
+          * RL state transition RL_WAIT_FOR_SEND_ACK
+          */
+          SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_SEND_ACK);
+         /*
+          * start timer TR2M
+          */
+          sms_timer_start(TR2M);
+
+          SMS_EM_RECEIVE_RP_DATA;
+         /*
+          * TL_DATA_IND =>
+          */
+          tl_data_ind (&cp_user_data_dl->rp_data_dl);
+        }
+        else
+        {
+          MCAST (cp_data, U_CP_DATA);
+          /*
+           * If Message Id is unknwon then send RP-ERROR with cause #97
+           */
+          if(cp_user_data_dl->rp_mti > 0x06)
+          {
+            rl_build_rp_error (cp_user_data_dl->reference,
+                               SMS_RP_CS_MSG_NON_EXIST,
+                               cp_data, NULL);
+          }
+          else
+          {
+            rl_build_rp_error (cp_user_data_dl->reference,
+                               SMS_RP_CS_MSG_NOT_COMP,
+                               cp_data, NULL);
+          }
+
+          SMS_EM_SEND_RP_ERROR;
+
+          cp_data_req (cp_data);
+         /*
+          * CP_RELEASE_REQ =>
+          */
+          TRACE_EVENT("CP_RELEASE_REQ_1");
+      
+          cp_release_req (SMS_INST.ti);
+         /*
+          * free instance
+          */
+          FREE_SMS_INSTANCE (SMS_INST.ti);
+        }
+        break;
+      }
+
+   /* ------------------------------------- */
+      case RL_WAIT_FOR_ACK:
+   /* ------------------------------------- */
+
+        TRACE_FUNCTION ("rl_data_ind(): RP_WAIT_FOR_ACK");
+
+        switch (cp_user_data_dl->rp_mti)
+        {
+          case RP_ACK_DL:
+            TRACE_FUNCTION ("rl_data_ind(): RP_ACK_DL");
+           /*
+            * stop timer TR1M
+            */
+            sms_timer_stop(TR1M);
+           /*
+            * RL state transition RL_IDLE
+            */
+            SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+
+            /* 
+             * if CMMS mode is 1 or 2 then only make cmm_release_pending TRUE
+             */
+            if(CMMS_ACTIVE)
+            {
+               sms_data->cmms_release_pending = TRUE;
+            }
+
+           /*
+            * TL_REPORT_IND =>
+            */
+            tl_report_ind (((cp_user_data_dl->rp_ack.v_rp_user_data)?
+                            &cp_user_data_dl->rp_ack.rp_user_data:
+                            NULL), SMS_NO_ERROR);           
+
+            /* Since the transmission is successful, the data stored for 
+               retransmission can be freed */
+            if (SMS_DATA_REQ(sms_data) NEQ NULL)
+            {
+              PFREE (SMS_DATA_REQ(sms_data));
+              SMS_DATA_REQ(sms_data) = NULL;
+            }
+
+            SMS_EM_RECEIVE_RP_AKNOWLEDGE;
+
+            break;
+
+          case RP_ERROR_DL:
+            /* When an RP-error with appropriate case value is 
+            * is received, Retransmission of SMS is started
+            */
+          {
+#ifdef REL99
+            BOOL retrans_flag = FALSE;
+#endif
+            TRACE_FUNCTION ("rl_data_ind(): RP_ERROR_DL");
+           /*
+            * stop timer TR1M
+            */
+            sms_timer_stop(TR1M);
+           /* 
+            * if CMMS mode is 1 or 2 then only make cmm_release_pending TRUE
+            */
+            if(CMMS_ACTIVE)
+            {
+               sms_data->cmms_release_pending = TRUE;
+            }
+#ifdef REL99
+            /*
+             * This is done for Retransmission for the causes
+             * listed in the table 8.4/3gPP TS 24.011(Part 1)
+             */
+             if (SMS_INST.tl_retx < TL_MAX_RETANS)
+            {             
+              /* Check whether the cause value satisfies the one for retransmission 
+               *  listed in the table 8.4/3gPP TS 24.011(Part 1)
+               */  
+              switch(cp_user_data_dl->rp_error.rp_cause.rp_cause_value)
+              {
+                case SMS_RP_CS_UNASSIGNED_NUMBER:         
+                case SMS_RP_CS_OPERATOR_DET_BARRED:       
+                case SMS_RP_CS_CALL_BARRED:      
+                case SMS_RP_CS_SM_TRANSFER_REJECTED:
+                case SMS_RP_CS_MEM_CAP_EXCEEDED:
+                case SMS_RP_CS_UNIDENT_SUBSCRIBER:
+                case SMS_RP_CS_FACILITY_REJECTED:
+                case SMS_RP_CS_UNKNOWN_SUBSCRIBER:
+                case SMS_RP_CS_NET_OUT_OF_ORDER:
+                case SMS_RP_CS_NO_RESOURCES:
+                case SMS_RP_CS_FAC_NOT_SUBSCRIBED:
+                case SMS_RP_CS_FAC_NOT_IMPL:
+                case SMS_RP_CS_INV_SM_TR_REF_VAL:
+                case SMS_RP_CS_SEM_INC_MSG:
+                case SMS_RP_CS_INV_MAND_INFO:
+                case SMS_RP_CS_MSG_NON_EXIST:
+                case SMS_RP_CS_INFO_NON_EXIST:
+                case SMS_RP_CS_PROTOCOL_ERROR:
+                case SMS_RP_CS_INTERWORKING:
+                  retrans_flag = FALSE;
+                  break;
+                /* All values other than the ones above are treated as temporary
+                  failures. This includes SMS_RP_CS_DEST_OUT_OF_ORDER, 
+                  SMS_RP_CS_TEMP_FAILURE, SMS_RP_CS_CONGESTION, 
+                  SMS_RP_CS_MSG_NOT_COMP and others non-standard values
+                  are taken as temporary error */
+                default:
+                  retrans_flag = TRUE;
+                  break;
+              }
+            }
+            if(retrans_flag EQ TRUE)
+            {
+              TRACE_EVENT ("Retransmission cause received");
+              cp_release_req(SMS_INST.ti);
+              TIMERSTART (SMS_INST_TR1M, 20000);
+              TRACE_EVENT ("Delay expiry TR1M, retransmit");
+            }
+            else
+#endif
+            {
+              /*
+               * RL state transition RL_IDLE
+               */
+              SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+              tl_report_ind (((cp_user_data_dl->rp_error.v_rp_user_data)?
+                            &cp_user_data_dl->rp_error.rp_user_data: NULL),
+                           CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET, SMSRP_ORIGINATING_ENTITY,
+                           cp_user_data_dl->rp_error.rp_cause.rp_cause_value));
+               SMS_EM_RECEIVE_RP_ERROR;
+             }
+          }
+          break;
+
+
+          default:
+            TRACE_FUNCTION ("rl_data_ind(): default");
+
+           /*
+            * stop timer TR1M
+            */
+            sms_timer_stop(TR1M);
+
+            {
+              MCAST (cp_data_ul, U_CP_DATA);
+              /*
+               * If Message Id is unknwon then send RP-ERROR with cause #97
+               */
+              if(cp_user_data_dl->rp_mti > 0x06)
+              {
+                rl_build_rp_error (cp_user_data_dl->reference,
+                                   SMS_RP_CS_MSG_NON_EXIST,
+                                   cp_data_ul, NULL);
+              }
+              else
+              {
+                rl_build_rp_error (cp_user_data_dl->reference,
+                                   SMS_RP_CS_PROTOCOL_ERROR,
+                                   cp_data_ul, NULL);
+              }
+
+              cp_data_req (cp_data_ul);
+            }
+#ifdef GPRS   /* interworking from flow control */
+            if (SMS_LLC_FLOW(sms_data) NEQ SMS_LLC_BUSY_WAITING)
+#endif
+            {
+              SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+
+              /* 
+               * if CMMS mode is 1 or 2 and current link used is GSM then only
+               * make cmm_release_pending TRUE
+               */
+#ifdef GPRS
+              if(CMMS_ACTIVE AND (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS))
+              {
+                 sms_data->cmms_release_pending = TRUE;
+              }
+#endif
+              /*
+              * TL_REPORT_IND =>
+              */
+             /*
+              * If Message Id is unknwon then send TL REPORT IND with cause #97
+              */
+              if(cp_user_data_dl->rp_mti > 0x06)
+              {
+                tl_report_ind (NULL, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                               SMSRP_ORIGINATING_ENTITY, SMS_RP_CS_MSG_NON_EXIST));
+              }
+              else
+              {
+                tl_report_ind (NULL, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                               SMSRP_ORIGINATING_ENTITY, SMS_RP_CS_PROTOCOL_ERROR));
+              }
+             
+            }
+#ifdef GPRS
+            else
+            {
+              SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_SEND_ERROR);
+            }
+#endif
+
+            SMS_EM_RECEIVE_UNKNOWN_2;
+
+            break;
+        }
+
+        break;
+
+      case RL_WAIT_FOR_SEND_ACK:
+        TRACE_FUNCTION ("rl_data_ind(): RP_WAIT_FOR_SEND_ACK");
+        {
+          MCAST (cp_data_ul, U_CP_DATA);
+         /*
+          * If Message Id is unknwon then send RP-ERROR with cause #97
+          */
+          if(cp_user_data_dl->rp_mti > 0x06)
+          {
+            rl_build_rp_error (cp_user_data_dl->reference,
+                               SMS_RP_CS_MSG_NON_EXIST,
+                               cp_data_ul, NULL);
+          }
+          else
+          {
+            rl_build_rp_error (cp_user_data_dl->reference,
+                               SMS_RP_CS_PROTOCOL_ERROR,
+                               cp_data_ul, NULL);
+          }
+          cp_data_req (cp_data_ul);
+
+        }
+        break;
+
+   /* ------------------------------------- */
+      case RL_WAIT_FOR_SMMA_ACK:
+   /* ------------------------------------- */
+
+        TRACE_FUNCTION ("rl_data_ind(): RP_WAIT_FOR_SMMA_ACK");
+
+        switch (cp_user_data_dl->rp_mti)
+        {
+          case RP_ACK_DL:
+            TRACE_FUNCTION ("rl_data_ind(): RP_ACK_DL");
+           /*
+            * stop timer TR1M
+            */
+            sms_timer_stop(TR1M);
+
+            SMS_INST.retrans  = FALSE;
+           /*
+            * RL state transition RL_IDLE
+            */
+            SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+           /*
+            * TL_REPORT_IND =>
+            */
+            tl_report_ind (NULL, SMS_NO_ERROR);
+            break;
+
+          case RP_ERROR_DL:
+            TRACE_FUNCTION ("rl_data_ind(): RP_ERROR_DL");
+
+            if (rl_temp_failure (cp_user_data_dl->rp_error.
+                                 rp_cause.rp_cause_value))
+            {
+              if (SMS_INST.retrans)
+              {
+               /*
+                * RL state transition RL_IDLE
+                */
+                SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+                SMS_INST.retrans = FALSE;
+
+               /*
+                * TL_REPORT_IND =>
+                */
+                tl_report_ind (NULL,
+                               CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET, SMSRP_ORIGINATING_ENTITY,
+                               cp_user_data_dl->rp_error.rp_cause.rp_cause_value));
+                sms_timer_stop(TR1M);
+
+                tl_sms_memo_exceeded (TRUE);
+               /*
+                * stop timer TR1M
+                */
+              }
+              else
+              {
+                SMS_INST.retrans  = TRUE;
+               /*
+                * RL state transition RL_WAIT_FOR_RETRANS_TIMER
+                */
+                SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_RETRANS_TIMER);
+               /*
+                * stop timer TR1M
+                */
+                sms_timer_stop(TR1M);
+               /*
+                * start timer TRAM
+                */
+                sms_timer_start(TRAM);
+               /*
+                * CP_RELEASE_REQ =>
+                */
+                TRACE_EVENT("CP_RELEASE_REQ_11");
+                cp_release_req (SMS_INST.ti);
+        
+              }
+            }
+            else
+            {
+             /*
+              * stop timer TR1M
+              */
+
+              sms_timer_stop(TR1M);
+              SMS_INST.retrans  = FALSE;
+             /*
+              * RL state transition RL_IDLE
+              */
+              SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+             /*
+              * TL_REPORT_IND =>
+              */
+          
+              tl_report_ind (NULL,
+                             CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET, SMSRP_ORIGINATING_ENTITY,
+                             cp_user_data_dl->rp_error.rp_cause.rp_cause_value));
+
+              tl_sms_memo_exceeded (TRUE);
+                  
+            }
+            break;
+
+          default:
+            TRACE_FUNCTION ("rl_data_ind(): default");
+           /*
+            * stop timer TR1M
+            */
+            sms_timer_stop(TR1M);
+
+            SMS_INST.retrans  = FALSE;
+           /*
+            * RL state transition RL_IDLE
+            */
+            SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+           /*
+            * If Message Id is unknwon then send RP-ERROR with cause #97
+            */
+            if(cp_user_data_dl->rp_mti > 0x06)
+            {
+              MCAST (cp_data, U_CP_DATA);
+              rl_build_rp_error (cp_user_data_dl->reference,
+                                 SMS_RP_CS_MSG_NON_EXIST,
+                                 cp_data, NULL);
+              SMS_EM_SEND_RP_ERROR;
+              cp_data_req (cp_data);
+              tl_report_ind (NULL, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                             SMSRP_ORIGINATING_ENTITY, SMS_RP_CS_MSG_NON_EXIST));
+            }
+            break;
+        }
+        break;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_establish_req           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_ESTABLISH_REQ.
+
+*/
+
+GLOBAL void rl_establish_req (UBYTE ti)
+{
+  GET_INSTANCE_DATA;
+    TRACE_FUNCTION_P1 ("rl_establish_req(TI=%u)", ti);
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_IDLE:
+       /*
+        * RL state transition RL_ESTABLISH
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_ESTABLISH);
+       /*
+        * CP_ESTABLISH_REQ =>
+        */
+        cp_establish_req(ti);
+       /*
+        * start timer TR1M
+        */
+        sms_data->timer_ti = ti;
+        sms_timer_start(TR1M);
+        break;
+      default:
+        TRACE_ERROR("RL_ESTABLISH_REQ in wrong state received!");
+   }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_establish_cnf           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_ESTABLISH_CNF.
+
+*/
+
+GLOBAL void rl_establish_cnf (BOOL         success)
+{
+   GET_INSTANCE_DATA;
+    TRACE_FUNCTION ("rl_establish_cnf()");
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_ESTABLISH:
+       /*
+        * stop timer TR1M
+        */
+        sms_timer_stop(TR1M);
+        if (success EQ TRUE)
+        {
+          /*
+           * RL state transition RL_ESTABLISHED
+           */
+           SMS_INST_SET_STATE (STATE_RL, RL_ESTABLISHED);
+        }
+        else
+        {
+          /*
+           * RL state transition RL_IDLE
+           */
+           SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+        }
+       /*
+        * TL_ESTABLISH_CNF =>
+        */
+        tl_establish_cnf(success);
+        break;
+      default:
+        TRACE_ERROR("RL_ESTABLISH_CNF in wrong state received!");
+   }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_release_req             |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_RELEASE_REQ.
+
+*/
+
+GLOBAL void rl_release_req ( UBYTE  ti)
+{
+    TRACE_FUNCTION_P1 ("rl_release_req(TI=%u)", ti);
+   /*
+    * CP_RELEASE_REQ =>
+    */
+    TRACE_EVENT("CP_RELEASE_REQ_13");
+    cp_release_req(ti);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_data_req                |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_DATA_REQ.
+
+*/
+GLOBAL BOOL rl_data_req (UBYTE       msg_ref,
+                         T_U_CP_DATA *cp_data)
+{
+  GET_INSTANCE_DATA;    
+  TRACE_FUNCTION ("rl_data_req()");
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_ESTABLISHED:
+      {
+        SMS_INST.msg_ref  = msg_ref;
+       /*
+        * RL state transtion RL_WAIT_FOR_ACK
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_ACK);
+
+        SMS_EM_SEND_RP_DATA;
+
+        cp_data->cp_user_data_ul.rp_mti = RP_DATA_UL;
+        cp_data->cp_user_data_ul.reference = msg_ref;
+       /*
+        * CP_DATA_REQ =>
+        */
+        cp_data_req (cp_data);
+       /*
+        * start timer TR1M
+        */
+        sms_timer_start(TR1M);
+
+        return TRUE;
+      }
+      default:
+        TRACE_ERROR("RL_DATA_REQ in wrong state received!");
+        break;
+    }
+  }
+  return FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_error_ind               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_ERROR_IND.
+
+*/
+
+GLOBAL void rl_error_ind (USHORT     cause)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_error_ind()");
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+   /* --------------------------------- */
+      case RL_ESTABLISH:
+   /* --------------------------------- */
+
+        if ( SMS_INST.tl_retx < TL_MAX_RETANS )
+        {
+          switch ( cause )
+          {
+            case MMCM_MMCS_MESSAGE_INCOMPAT:
+            case RRCS_NORM:
+              /* 
+               * start timer TR1M with value
+               */
+              TIMERSTART ( SMS_INST_TR1M, 20000 );
+              TRACE_EVENT ( "Delay expiry TR1M, retransmit" );
+              return;
+
+            default: /* No retransmission */
+              break;
+          }
+        }
+
+       /*
+        * stop timer TR1M
+        */
+        sms_timer_stop(TR1M);
+       /*FALLTHROUGH*/ /*lint -fallthrough*/
+   /* --------------------------------- */
+      case RL_ESTABLISHED:
+   /* --------------------------------- */
+       /*
+        * RL state transition RL_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+       /*
+        * free instance
+        */
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+       /*
+        * TL_REPORT_IND
+        */
+        tl_report_ind (NULL, cause);
+        break;
+
+   /* --------------------------------- */
+      case RL_WAIT_FOR_ACK:
+   /* --------------------------------- */
+        TRACE_FUNCTION ("rl_error_ind(): RL_WAIT_FOR_ACK");
+        /* 
+         * The following code is to implement a subset of 
+         * 3GPP 23.040 Release 1999 subclause 9.2.3.6.
+         * For certain errors the SMS SUBMIT / SMS COMMAND is repeated
+         * after timeout of TR1M.
+         */
+        TRACE_EVENT_P2 ("TL retrans #%d, error_cs %04x",
+                        SMS_INST.tl_retx,
+                        cause);
+
+        if (SMS_INST.tl_retx < TL_MAX_RETANS)
+        {
+          switch (cause)
+          {
+            case SMS_CAUSE_NET_TIMEOUT:
+             /* 11.10 test case 34.2.2 step 68 */
+             /*
+              * start timer TR1M with value
+              */
+              TIMERSTART (SMS_INST_TR1M, 20000);
+              TRACE_EVENT ("Delay expiry TR1M, retransmit");
+              return;
+
+            case RRCS_NORM:
+            case MMCM_MMCS_MESSAGE_INCOMPAT: /* Make cingular happy, #19189 */
+              TRACE_EVENT ("Retransmission after TR1M");
+              return;
+
+            default: /* No retransmission */
+              break;
+          }
+        }
+       /*
+        * stop timer TR1M
+        */
+        sms_timer_stop(TR1M);
+       /*
+        * RL state transition RL_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+       /*
+        * free instance
+        */
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+       /*
+        * TL_REPORT_IND =>
+        */
+        tl_report_ind (NULL, cause);
+        break;
+
+   /* --------------------------------- */
+      case RL_WAIT_FOR_SEND_ACK:
+   /* --------------------------------- */
+
+        TRACE_FUNCTION ("rl_error_ind(): RL_WAIT_FOR_SEND_ACK");
+       /*
+        * free instance
+        */
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+       /*
+        * stop timer TR2M
+        */
+        sms_timer_stop(TR2M);
+       /*
+        * RL state transition RL_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+       /*
+        * TL_REPORT_IND =>
+        */
+        tl_report_ind (NULL, cause);
+        break;
+
+   /* --------------------------------- */
+        case RL_WAIT_FOR_SMMA_ACK:
+   /* --------------------------------- */
+
+        TRACE_FUNCTION ("rl_error_ind(): RL_WAIT_FOR_SMMA_ACK");
+        
+        // FREE_SMS_INSTANCE (SMS_INST.ti);
+
+        if (SMS_INST.retrans)
+        {
+         /*
+          * RL state transition RL_IDLE
+          */
+          SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+          SMS_INST.retrans = FALSE;
+         /*
+          * TL_REPORT_IND =>
+          */
+          tl_report_ind (NULL, SMS_CAUSE_NET_TIMEOUT);
+         /*
+          * stop timer TR1M
+          */
+          sms_timer_stop(TR1M);
+          tl_sms_memo_exceeded (TRUE);
+
+        }
+        else
+        {
+          SMS_INST.retrans  = TRUE;
+         /*
+          * RL state transition RL_WAIT_FOR_RETRANS_TIMER
+          */
+          SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_RETRANS_TIMER);
+         /*
+          * stop timer TR1M
+          */
+          sms_timer_stop(TR1M);
+         /*
+          * start timer TRAM
+          */
+          sms_timer_start(TRAM);
+         /*
+          * CP_RELEASE_REQ =>
+          */
+          TRACE_EVENT("CP_RELEASE_REQ_15");
+          cp_release_req (SMS_INST.ti);
+
+         /*
+          * free instance
+          */
+          FREE_SMS_INSTANCE (SMS_INST.ti);
+        }
+
+        break;
+    
+
+      default:
+        
+        if(CMMS_ACTIVE)
+        {
+           tl_cmms_end();
+        }
+       /*
+        * free instance
+        */
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+       /*
+        * RL state transition RL_IDLE
+        */
+        
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+        break;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_mem_avail_req           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_MEM_AVAIL_REQ.
+
+*/
+
+GLOBAL BOOL rl_mem_avail_req (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_mem_avail_req()");
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_ESTABLISHED:
+      {
+        CCD_START;
+        {
+          MCAST (cp_data, U_CP_DATA);
+         /*
+          * RL state transition RL_WAIT_FOR_SMMA_ACK
+          */
+          SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_SMMA_ACK);
+          SMS_RP_REF(sms_data) = SMS_INST.tp_mr;
+
+          rl_build_rp_smma (SMS_RP_REF(sms_data), cp_data);
+
+          CCD_END;
+         /*
+          * CP_DATA_REQ =>
+          */
+          cp_data_req (cp_data);
+        }
+       /*
+        * start timer TR1M
+        */
+        sms_timer_start(TR1M);    
+        return TRUE;
+
+      default:
+        TRACE_ERROR("RL_MEM_AVAIL_REQ in wrong state received!");
+        break;
+      }
+    }
+  }
+  return FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_start_tram_req          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_START_TRAM_REQ.
+
+*/
+
+GLOBAL void rl_start_tram_req (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_start_tram_req()");
+          
+  SMS_INST.retrans  = TRUE;
+ /*
+  * RL state transition RL_WAIT_FOR_RETRANS_TIMER
+  */
+  SMS_INST_SET_STATE (STATE_RL, RL_WAIT_FOR_RETRANS_TIMER);
+ /*
+  * start timer TRAM
+  */
+  sms_timer_start(TRAM);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_build_rp_ack            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function RL_BUILD_RP_ACK.
+
+*/
+
+LOCAL void rl_build_rp_ack (UBYTE          msg_ref,
+                            T_U_CP_DATA    *cp_data,
+                            T_rp_user_data *rp_user_data)
+{
+  TRACE_FUNCTION ("rl_build_rp_ack()");
+
+  memset (&cp_data->cp_user_data_ul.rp_ack, 0, sizeof (T_rp_ack));
+
+  cp_data->msg_type                  = U_CP_DATA;
+  cp_data->cp_user_data_ul.rp_mti    = RP_ACK_UL;
+  cp_data->cp_user_data_ul.reference = msg_ref;
+
+  cp_data->cp_user_data_ul.v_rp_data_ul  = FALSE;
+  cp_data->cp_user_data_ul.v_rp_error    = FALSE;
+  cp_data->cp_user_data_ul.v_rp_ack      = TRUE;
+
+  if (rp_user_data NEQ NULL AND rp_user_data->v_tpdu)
+  {
+    memcpy (&cp_data->cp_user_data_ul.rp_ack.rp_user_data,
+            rp_user_data, sizeof (T_rp_user_data));
+    cp_data->cp_user_data_ul.rp_ack.v_rp_user_data = TRUE;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_report_req_ack          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_REPORT_REQ_ACK.
+
+*/
+
+GLOBAL void rl_report_req_ack (T_rp_user_data *rp_user_data)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_report_req_ack()");
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_WAIT_FOR_SEND_ACK:
+      {
+        MCAST (cp_data, U_CP_DATA);
+       /*
+        * stop timer TR2M
+        */
+        sms_timer_stop(TR2M);
+
+        rl_build_rp_ack (SMS_RP_REF(sms_data), cp_data, rp_user_data);
+       /*
+        * RL state transition RL_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+       /*
+        * CP_DATA / RP_ACK ==>
+        */
+        cp_data_req (cp_data);
+       /*
+        * CP_RELEASE_REQ =>
+        */
+        TRACE_EVENT("CP_RELEASE_REQ_16");
+        cp_release_req (SMS_INST.ti);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_build_rp_error          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function RL_BUILD_RP_ERROR.
+
+*/
+
+GLOBAL void rl_build_rp_error (UBYTE          msg_ref,
+                               USHORT         error,
+                               T_U_CP_DATA    *cp_data,
+                               T_rp_user_data *rp_user_data)
+{
+  TRACE_FUNCTION ("rl_build_rp_error()");
+  TRACE_EVENT_P1 ("RP_ERROR.CAUSE sent: 0x%2.2X", (int)error);
+
+  memset (&cp_data->cp_user_data_ul.rp_error, 0, sizeof (T_rp_error));
+
+  cp_data->msg_type                  = U_CP_DATA;
+  cp_data->cp_user_data_ul.rp_mti    = RP_ERROR_UL;
+  cp_data->cp_user_data_ul.reference = msg_ref;
+
+  cp_data->cp_user_data_ul.v_rp_data_ul  = FALSE;
+  cp_data->cp_user_data_ul.v_rp_ack      = FALSE;
+  cp_data->cp_user_data_ul.v_rp_error    = TRUE;
+
+  cp_data->cp_user_data_ul.rp_error.
+           rp_cause.v_rp_cause_value = TRUE;
+  if (error < 128)              /* GSM 04.11 cause */
+  {
+    cp_data->cp_user_data_ul.rp_error.
+             rp_cause.rp_cause_value = (UBYTE)error;
+  }
+  else
+  {
+    cp_data->cp_user_data_ul.rp_error.
+             rp_cause.rp_cause_value = SMS_RP_CS_PROTOCOL_ERROR;
+    cp_data->cp_user_data_ul.rp_error.
+             v_rp_user_data = TRUE;
+  }
+  if (rp_user_data NEQ NULL AND rp_user_data->v_tpdu)
+  {
+    memcpy (&cp_data->cp_user_data_ul.rp_error.rp_user_data,
+            rp_user_data, sizeof (T_rp_user_data));
+    cp_data->cp_user_data_ul.rp_error.v_rp_user_data = TRUE;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_report_req_error        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal RL_REPORT_REQ_ERROR.
+
+*/
+
+GLOBAL void rl_report_req_error (USHORT         cause,
+                                 T_rp_user_data *rp_user_data)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("rl_report_req_error()");
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_RL))
+    {
+      case RL_WAIT_FOR_SEND_ACK:
+      {
+        MCAST (cp_data, U_CP_DATA);
+       /*
+        * stop timer TR2M
+        */
+        sms_timer_stop(TR2M);
+
+        rl_build_rp_error (SMS_RP_REF(sms_data), cause,
+                           cp_data, rp_user_data);
+       /*
+        * RL state transition RL_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_RL, RL_IDLE);
+       /*
+        * CP_DATA / RP_ERROR ==>
+        */
+        cp_data_req (cp_data);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+}
+
+#if defined (GPRS)
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_build_rp_error_gprs     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function RL_BUILD_RP_ERROR for GSMS.
+
+*/
+
+GLOBAL void rl_build_rp_error_gprs (UBYTE              ti,
+                                    T_LL_UNITDATA_REQ  *data_req,
+                                    USHORT             error,
+                                    UBYTE              msg_ref,
+                                    T_U_CP_DATA        *cp_data,
+                                    T_stk_cmd          *stk_cmd)
+{
+  TRACE_FUNCTION ("rl_build_rp_error_gprs()");
+  TRACE_EVENT_P1 ("RP_ERROR.CAUSE sent: 0x%4.2X", (int)error);
+
+  data_req->sdu.o_buf = ENCODE_OFFSET;
+
+  cp_data->msg_type                  = U_CP_DATA;
+  cp_data->cp_user_data_ul.rp_mti    = RP_ERROR_UL;
+  cp_data->cp_user_data_ul.reference = msg_ref;
+
+  cp_data->cp_user_data_ul.v_rp_data_ul  = FALSE;
+  cp_data->cp_user_data_ul.v_rp_error    = TRUE;
+
+  memset (&cp_data->cp_user_data_ul.rp_error.rp_cause, 0,
+          sizeof (T_rp_cause));
+
+  cp_data->cp_user_data_ul.rp_error.
+           rp_cause.v_rp_cause_value = TRUE;
+  if (error < 128)              /* GSM 04.11 cause */
+  {
+    cp_data->cp_user_data_ul.rp_error.
+             rp_cause.rp_cause_value = (UBYTE)error;
+    cp_data->cp_user_data_ul.rp_error.
+             v_rp_user_data = FALSE;
+  }
+  else
+  {
+    cp_data->cp_user_data_ul.rp_error.
+             rp_cause.rp_cause_value = SMS_RP_CS_PROTOCOL_ERROR;
+    cp_data->cp_user_data_ul.rp_error.
+             v_rp_user_data = TRUE;
+    memset (&cp_data->cp_user_data_ul.rp_error.rp_user_data,
+            0, sizeof (T_rp_user_data));
+    if (error >= 256)           /* no GSM 03.40 cause */
+      error = SMS_FCS_UNSPECIFIED;
+    cp_data->cp_user_data_ul.rp_error.rp_user_data.
+             v_tpdu = TRUE;
+  /*
+    cp_data->cp_user_data_ul.rp_error.rp_user_data.
+             sms_deliver_rep_err.tp_fcs = (UBYTE)error;
+   */
+  }
+
+  ccd_codeMsg (CCDENT_SMS,
+               UPLINK,
+               (T_MSGBUF *) &data_req->sdu,
+               (UBYTE *) cp_data,
+               NOT_PRESENT_8BIT);
+  /*lint -e415 -e416 Likely creation/access of out-of-bounds pointer */
+  data_req->sdu.buf[3] = (ti << 4) + PD_SMS;
+  data_req->sdu.o_buf  = ENCODE_OFFSET - BSIZE_TI_PD;
+  data_req->sdu.l_buf += BSIZE_TI_PD;
+
+  if (stk_cmd NEQ NULL)
+  {
+    /*
+     * response from a SIM Toolkit command
+     */
+    if (stk_cmd->l_cmd NEQ 0)
+    {
+      /*
+       * response TPDU available
+       */
+      /* change length of rp-error */
+      data_req->sdu.buf[5] += ((stk_cmd->l_cmd >> 3) + 2);
+      /* add IEI for rp user data */
+      data_req->sdu.buf[10] = 0x41;
+      /* add length for rp user data */
+      data_req->sdu.buf [11] = stk_cmd->l_cmd >> 3;
+      /* add TPDU */
+      memcpy (&data_req->sdu.buf [12],
+              &stk_cmd->cmd[stk_cmd->o_cmd>>3],
+              stk_cmd->l_cmd>>3);
+      /* modify length of CP Data */
+      data_req->sdu.l_buf += (stk_cmd->l_cmd + 16);
+    }
+  }
+  /*lint +e415 +e416 Likely creation/access of out-of-bounds pointer */
+}
+#endif /* GPRS */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_build_rp_smma           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function RL_BUILD_RP_SMMA.
+
+*/
+
+GLOBAL void rl_build_rp_smma (UBYTE       msg_ref,
+                              T_U_CP_DATA *cp_data)
+{
+  TRACE_FUNCTION ("rl_build_rp_smma()");
+
+  cp_data->cp_user_data_ul.rp_mti    = RP_SMMA_UL;
+  cp_data->cp_user_data_ul.reference = msg_ref;
+
+  cp_data->cp_user_data_ul.v_rp_data_ul = FALSE;
+  cp_data->cp_user_data_ul.v_rp_error = FALSE;
+  cp_data->cp_user_data_ul.v_rp_ack = FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_RL                     |
+| STATE   : code                ROUTINE : rl_temp_failure            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function RL_TEMP_FAILURE.
+            This is valid for memory available notification attempt.
+            [04.11 Table 8.4 part 3]
+*/
+
+GLOBAL UBYTE rl_temp_failure (UBYTE cause)
+{
+  TRACE_FUNCTION ("rl_temp_failure()");
+
+  switch (cause)
+  {
+    case SMS_RP_CS_UNKNOWN_SUBSCRIBER:
+    case SMS_RP_CS_FAC_NOT_IMPL:
+    case SMS_RP_CS_SEM_INC_MSG:
+    case SMS_RP_CS_INV_MAND_INFO:
+    case SMS_RP_CS_MSG_NON_EXIST:
+    case SMS_RP_CS_MSG_NOT_COMP:
+    case SMS_RP_CS_INFO_NON_EXIST:
+    case SMS_RP_CS_PROTOCOL_ERROR:
+    case SMS_RP_CS_INTERWORKING:
+      return FALSE; /* Non-temporary */
+
+    default:
+      return TRUE;  /* Temporary */
+  }
+}
+
+#endif /* #ifndef SMS_RL_C */