diff src/g23m-gsm/sms/sms_cp.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_cp.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,1981 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :  GSM-F&D (8411)
+|  Modul   :  SMS_CP
++-----------------------------------------------------------------------------
+|  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 control protocol
+|             of the component SMS.
++-----------------------------------------------------------------------------
+*/
+
+#ifndef SMS_CP_C
+#define SMS_CP_C
+
+#define ENTITY_SMS
+
+/*==== INCLUDES ===================================================*/
+
+#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 ===================================================*/
+  
+/* Implements Measure# 4 */  
+/*
++------------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                         |
+| STATE   : code                ROUTINE : cp_send_err_ind_errcs          |
++------------------------------------------------------------------------+  
+
+  PURPOSE : This routine process the signal CP_DATA_IND_CP_ERROR for the 
+            cases CP_MM_CONNECTION_ESTABLISHED and  CP_WAIT_FOR_ACK    
+            
+*/
+
+LOCAL void cp_send_err_ind_errcs(UBYTE errcs)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION("cp_send_err_ind_errcs()");
+  /*
+   * Check if the cmms_mode is enabled or not
+   * If enabled dont release the MM connection
+   */
+  if(!CMMS_ACTIVE)
+  {
+    cp_send_release_req (SMS_INST.ti); 
+    SMS_INST_SET_STATE (STATE_CP, CP_IDLE); 
+    SMS_INST.r_flag = FALSE; 
+  }
+  else
+  {
+    sms_data->cmms_release_pending = TRUE;
+  }
+ 
+  rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET,
+                SMSCP_ORIGINATING_ENTITY, errcs));  
+  
+}
+
+/* Implements Measure# 3 */
+/*
++------------------------------------------------------------------------- -+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                            |
+| STATE   : code                ROUTINE : cp_send_err_ind_msg_type_unknown  |
++---------------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_IND_CP_UNKNOWN for the 
+            cases CP_MM_CONNECTION_ESTABLISHED and CP_WAIT_FOR_ACK
+            
+*/
+
+LOCAL void cp_send_err_ind_msg_type_unknown(void)
+{
+  GET_INSTANCE_DATA; 
+  TRACE_FUNCTION("cp_send_err_ind_msg_type_unknown()");
+  
+  cp_build_cp_error (SMS_CP_CS_MSG_TYPE_NON_EXIST);
+  
+  /*
+   * Check if the cmms_mode is enabled or not
+   * If enabled dont release the MM connection
+   */
+  if(!CMMS_ACTIVE)
+  {
+    cp_send_release_req (SMS_INST.ti);
+    SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+    SMS_INST.r_flag = FALSE;
+  }
+  else
+  {
+    sms_data->cmms_release_pending = TRUE;
+  }
+
+  rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                SMSCP_ORIGINATING_ENTITY, SMS_CP_CS_MSG_TYPE_NON_EXIST));  
+  
+}
+
+/* Implements Measure# 8 */
+/*
++------------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                         |
+| STATE   : code                ROUTINE : cp_send_err_ind_msg_not_comp   |
++------------------------------------------------------------------------+  
+
+  PURPOSE : This routine process the signals CP_DATA_IND_CP_ACK and CP_DATA_IND_CP_DATA
+            for the cases CP_MM_CONNECTION_ESTABLISHED and CP_WAIT_FOR_ACK
+            
+*/
+
+LOCAL void cp_send_err_ind_msg_not_comp (void)
+{
+  GET_INSTANCE_DATA; 
+  TRACE_FUNCTION("cp_send_err_ind_msg_not_comp()");
+  
+  cp_build_cp_error (SMS_CP_CS_MSG_NOT_COMP);
+  
+  cp_send_release_req (SMS_INST.ti);
+  SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+  SMS_INST.r_flag = FALSE;
+  
+  rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                SMSCP_ORIGINATING_ENTITY, SMS_CP_CS_MSG_NOT_COMP));  
+  
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_init                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize the control protocol.
+
+*/
+
+GLOBAL void cp_init (void)
+{
+  GET_INSTANCE_DATA;	
+
+  TRACE_FUNCTION ("cp_init()");
+
+  memset (sms_data, 0, sizeof (T_SMS_DATA));
+
+  sms_data->data[0].state[STATE_CP] = CP_IDLE;
+  sms_data->data[1].state[STATE_CP] = CP_IDLE;
+
+  /*
+   * Initialize the timer_values with default values
+   */
+  sms_data->timer_values[TC1M] = TC1M_VALUE;
+  sms_data->timer_values[TR1M] = TR1M_VALUE;
+  sms_data->timer_values[TR2M] = TR2M_VALUE;
+  sms_data->timer_values[TRAM] = TRAM_VALUE;
+  sms_data->timer_values[TLCT] = TLCT_VALUE;
+  sms_data->timer_values[TMMS] = TMMS_VALUE;
+
+#if defined (GPRS)
+  {
+    int i;
+    /*
+     * default for MO SM: CCT preferred,
+     * no LLC flow information known yet
+     */
+    SMS_ROUTE_PREF(sms_data) = GPRS_SMS_CCT_PREF;
+    SMS_LLC_FLOW(sms_data)   = SMS_LLC_UNKNOWN;
+    SMS_SMS_FLOW(sms_data)   = SMS_FLOW_UNKNOWN;
+
+    /*
+     * initialize downlink info of each instance
+     */
+    for (i = 0; i < MAX_SMS_CALLS; i++)
+    {
+      sms_data->data[i].downlink = SMS_DOWNLINK_NONE;
+      sms_data->data[i].ack_type = SMS_CP_NONE;
+      sms_data->data[i].cp_cause = NOT_PRESENT_8BIT;
+      sms_data->data[i].cp_user_data_dl = NULL;
+    }
+  }
+#endif
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_add_pd_ti               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Add Protocol Discriminator and Transaction Identifier to
+            the SDU and modify its parameters accordingly.
+*/
+void cp_add_pd_ti (UBYTE ti,
+                   T_sdu *sdu)
+{
+  if (sdu NEQ NULL)
+  {
+    sdu->o_buf -= BSIZE_TI_PD;
+    sdu->l_buf += BSIZE_TI_PD;
+    sdu->buf[BYTELEN_POS(sdu->o_buf)] = PD_SMS | (ti << 4);
+
+    memset (sdu->buf, 0, BYTELEN(sdu->o_buf));
+  }
+}
+
+#if defined (GPRS)
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_init_ll_unitdata_req    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize a ll_unitdata_req.
+
+*/
+void cp_init_ll_unitdata_req (T_LL_UNITDATA_REQ * unitdata_req)
+{
+  unitdata_req->sapi              = LL_SAPI_7;
+  unitdata_req->tlli              = LL_TLLI_INVALID;
+  unitdata_req->ll_qos.delay      = LL_DELAY_SUB;
+  unitdata_req->ll_qos.relclass   = LL_RLC_PROT;
+  unitdata_req->ll_qos.peak       = LL_PEAK_SUB;
+  unitdata_req->ll_qos.preced     = LL_PRECED_SUB;
+  unitdata_req->ll_qos.mean       = LL_MEAN_SUB;
+  unitdata_req->radio_prio        = LL_RADIO_PRIO_1;
+  unitdata_req->cipher            = LL_CIPHER_OFF;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_send_getunitdata_req    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize ready to receive protocol.
+
+*/
+
+GLOBAL void cp_send_getunitdata_req (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_send_getunitdata_req()");
+
+  if (SMS_SMS_FLOW(sms_data) NEQ SMS_FLOW_AVAILABLE)
+  {
+    PALLOC (get_unitdata_req, LL_GETUNITDATA_REQ);
+
+    memset (get_unitdata_req, 0, sizeof (T_LL_GETUNITDATA_REQ));
+    get_unitdata_req->sapi = LL_SAPI_7;
+    get_unitdata_req->tlli = LL_TLLI_INVALID;
+    SMS_SMS_FLOW(sms_data) = SMS_FLOW_AVAILABLE;
+
+    PSENDX (LLC, get_unitdata_req);
+  }
+}
+#endif /* GPRS */
+
+/*---- PRIMITIVES --------------------------------------------------*/
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_mmsms_error_ind         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the primitive MMSMS_ERROR_IND.
+
+*/
+
+GLOBAL void cp_mmsms_error_ind (T_MMSMS_ERROR_IND *error_ind)
+{
+  register T_SMS_DATA *sms_data = GET_SMS_INSTANCE (error_ind->ti);
+
+  TRACE_FUNCTION_P1 ("cp_mmsms_error_ind(TI=%u)", error_ind->ti);
+
+  if (sms_data)
+  {
+    TRACE_EVENT_P1 ("MMSMS_ERROR_IND.CAUSE: 0x%4.4hX", error_ind->cause);
+
+    SMS_EM_LOSS_OF_MM_CONNECTION;
+
+    cp_send_release_req (error_ind->ti);
+
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+    case CP_MM_CONNECTION_PENDING:
+      {
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.ti = error_ind->ti;
+
+        /* This is meant for SMS over GSM as preference and GPRS as fallback.
+         */
+
+#ifdef GPRS
+        if(sms_data->mo_dst_pref EQ GPRS_SMS_CCT_PREF)
+        {
+          TRACE_FUNCTION ("GSM Failed trying with GPRS ");
+          rl_establish_cnf(FALSE);
+        }
+        else
+#endif
+        {
+          SMS_INST.r_flag = FALSE;
+          /*
+           * RL_ERROR_IND =>
+           */
+          rl_error_ind (error_ind->cause);
+        }
+        break;
+      }
+
+    case CP_WAIT_FOR_ACK:
+     /*
+      * stop timer TC1M
+      */
+      sms_timer_stop(TC1M);
+
+      SMS_RETX(sms_data)   = 0;
+      SMS_INST.r_flag = FALSE;
+      SMS_INST.ti = error_ind->ti;
+    
+      /*FALLTHROUGH*/ /*lint -fallthrough*/
+
+    case CP_MM_CONNECTION_ESTABLISHED:
+
+      SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+      rl_error_ind (error_ind->cause);
+      break;
+
+    default:
+      SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+      FREE_SMS_INSTANCE (error_ind->ti);
+      break;
+    }
+  }
+  PFREE (error_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_mmsms_establish_cnf     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the primitive MMSMS_ESTABLISH_CNF.
+
+*/
+
+GLOBAL void cp_mmsms_establish_cnf (T_MMSMS_ESTABLISH_CNF *establish_cnf)
+{
+  register T_SMS_DATA *sms_data = GET_SMS_INSTANCE (establish_cnf->ti);
+
+  TRACE_FUNCTION_P1 ("cp_mmsms_establish_cnf(TI=%u)", establish_cnf->ti);
+
+  SMS_EM_MM_CONNECTION_ESTABLISHED;
+
+  if (sms_data)
+  {
+   /*
+    * set TI
+    */
+    sms_data->data[INST_MO].ti = establish_cnf->ti;
+   /*
+    * reset ack pending
+    */
+    SMS_INST.cp_ack_pending = FALSE;
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_MM_CONNECTION_PENDING:
+      {
+        /*
+         * CP state transition
+         */
+         SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_ESTABLISHED);
+        /*
+         * RL_ESTABLISH_CNF =>
+         */
+         rl_establish_cnf(TRUE);
+         break;
+      }
+      default:
+        TRACE_ERROR("MMSMS_ESTABLISH_CNF in wrong state received!");
+        break;
+    }
+  }
+  PFREE (establish_cnf);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_mmsms_release_ind       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the primitive MMSMS_RELEASE_IND.
+
+*/
+
+GLOBAL void cp_mmsms_release_ind (T_MMSMS_RELEASE_IND *release_ind)
+{
+  register T_SMS_DATA *sms_data = GET_SMS_INSTANCE (release_ind->ti);
+
+  TRACE_FUNCTION_P1 ("cp_mmsms_release_ind(TI=%u)", release_ind->ti);
+
+  if (sms_data)
+  {
+    TRACE_EVENT_P1 ("MMSMS_RELEASE_IND: cause=0x%4.4hX", 
+                    release_ind->cause);
+
+    SMS_EM_MM_CONNECTION_FAILED;
+
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_PENDING:
+   /* ------------------------------------ */
+      {
+        /*
+         * safe TI
+         */
+        SMS_INST.ti = release_ind->ti;
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+
+        /* This is meant for SMS over GSM as preference and GPRS as fallback.
+         */
+
+#ifdef GPRS
+        if(sms_data->mo_dst_pref EQ GPRS_SMS_CCT_PREF)
+        {
+           TRACE_FUNCTION ("GSM Failed trying with GPRS ");
+           rl_establish_cnf(FALSE);
+        }
+        else
+#endif
+        {
+           SMS_INST.r_flag = FALSE;
+           /* RL_ERROR_IND */
+           rl_error_ind (release_ind->cause);
+         }
+         break;
+   	}
+
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+       /*
+        * CP state transition CP_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.r_flag = FALSE;
+       /*
+        * RL_ERROR_IND =>
+        */
+        rl_error_ind (release_ind->cause);
+        break;
+      }
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+       /*
+        * CP state transition CP_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_RETX(sms_data)   = 0;
+        SMS_INST.r_flag = FALSE;
+       /*
+        * RL_ERROR_IND =>
+        */
+        rl_error_ind (release_ind->cause);
+        break;
+      }
+   /* ------------------------------------ */
+      default:
+   /* ------------------------------------ */
+       /*
+        * CP state transition CP_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        FREE_SMS_INSTANCE (release_ind->ti);
+        break;
+    }    
+  }
+  PFREE (release_ind);
+}
+
+/*---- SIGNALS -----------------------------------------------------*/
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_abort_req               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_ABORT_REQ.
+
+*/
+
+GLOBAL void cp_abort_req (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_abort_req(TI=%u)",SMS_INST.ti);
+
+
+  SMS_EM_ABORT_OF_MM_CONNECTION;
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+        CCD_START;
+       /*
+        * check whether CP ACK needs to be send
+        */
+        if (SMS_INST.cp_ack_pending EQ TRUE)
+        {
+          cp_build_cp_ack ();
+        }
+       /*
+        * generate CP_ERROR
+        */
+        cp_build_cp_error (SMS_CP_CS_PROTOCOL_ERROR);
+       /*
+        * release connection
+        */
+        SMS_INST.r_flag = FALSE;
+        cp_send_release_req (SMS_INST.ti);
+        CCD_END;
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_PENDING:
+   /* ------------------------------------ */
+      {
+       /*
+        * release connection
+        */
+        SMS_INST.r_flag = FALSE;
+        cp_send_release_req (SMS_INST.ti);
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        CCD_START;
+       /*
+        * check whether CP ACK needs to be send
+        */
+        if (SMS_INST.cp_ack_pending EQ TRUE)
+        {
+          cp_build_cp_ack ();
+        }
+       /*
+        * generate CP_ERROR
+        */
+        cp_build_cp_error (SMS_CP_CS_PROTOCOL_ERROR);
+       /*
+        * release connection
+        */
+        SMS_INST.r_flag = FALSE;
+        cp_send_release_req (SMS_INST.ti);
+
+        CCD_END;
+        break;
+      }
+
+#if defined (GPRS)
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        cp_error_req_gsms (SMS_CP_CS_PROTOCOL_ERROR, FALSE);
+        break;
+      }
+#endif /* GPRS */
+    }
+#if defined (GPRS)
+    if (SMS_CP_ACK_TYPE(sms_data) EQ SMS_CP_NONE)
+#endif /* GPRS */
+    {
+      SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_ind_cp_ack         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_IND_CP_ACK.
+
+*/
+
+GLOBAL void cp_data_ind_cp_ack (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_data_ind_cp_ack(TI=%u)", SMS_INST.ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+        /* Implements Measure# 8 */
+        cp_send_err_ind_msg_not_comp ();  
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+          sms_timer_stop(TC1M);
+
+
+        if (SMS_INST.r_flag)
+        {
+          SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+          SMS_INST.r_flag   = FALSE;
+
+          cp_send_release_req (SMS_INST.ti);
+          FREE_SMS_INSTANCE (SMS_INST.ti);
+        }
+        else
+        {
+          SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_ESTABLISHED);
+        }
+        break;
+      }
+
+#if defined (GPRS)
+    /* ------------------------------------ */
+     case CP_GSMS_IDLE:
+   /* ------------------------------------ */
+      {
+        if (SMS_INST.r_flag)
+        {
+          SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+          SMS_INST.r_flag   = FALSE;
+          FREE_SMS_INSTANCE (SMS_INST.ti);
+        }
+        else
+        {
+          cp_error_req_gsms (SMS_CP_CS_MSG_NOT_COMP, TRUE);
+        }
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        if (SMS_INST.r_flag)
+        {
+          SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+          SMS_INST.r_flag   = FALSE;
+          FREE_SMS_INSTANCE (SMS_INST.ti);
+        }
+        else
+        {
+          SMS_INST_SET_STATE (STATE_CP, CP_GSMS_MO_WAIT_FOR_CP_DATA);
+        }
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        if (SMS_INST.r_flag)
+        {
+          SMS_INST.r_flag   = FALSE;
+        }
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+   /* ------------------------------------ */
+      {
+        cp_error_req_gsms (SMS_CP_CS_MSG_NOT_COMP, FALSE);
+        rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                                SMSCP_ORIGINATING_ENTITY, SMS_CP_CS_MSG_NOT_COMP));
+
+        break;
+      }
+#endif /* GPRS */
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_ind_cp_data        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_IND_CP_DATA.
+
+*/
+GLOBAL void cp_data_ind_cp_data (T_D_CP_DATA *cp_data)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_data_ind_cp_data(TI=%u)", SMS_INST.ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+        if (SMS_INST.r_flag)
+        {
+          /* Nothing expected anymore */
+
+         /*
+          * stop timer TC1M
+          */
+          sms_timer_stop(TC1M);
+          /* Implements Measure# 8 */
+          cp_send_err_ind_msg_not_comp ();  
+          break;
+        }
+        else
+        {
+          TRACE_EVENT ("CP ACK lost");
+          cp_data_ind_cp_ack ();
+        }
+      }
+      /*FALLTHROUGH*/ /*lint -fallthrough*/
+
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+       /*
+        * remember to cp ack
+        */
+        SMS_INST.cp_ack_pending = TRUE;
+       /*
+        * RL_DATA_IND =>
+        */
+        rl_data_ind (&cp_data->cp_user_data_dl);
+        break;
+      }
+
+#if defined (GPRS)
+   /* ------------------------------------ */
+      case CP_GSMS_IDLE:
+   /* ------------------------------------ */
+      {
+        if (SMS_LLC_FLOW(sms_data) EQ SMS_LLC_AVAILABLE)
+        {
+          cp_build_cp_ack ();
+        }
+        else
+        {
+          SMS_CP_ACK_TYPE(sms_data) = SMS_CP_ACK;
+          SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY_WAITING;
+        }
+        SMS_INST_SET_STATE (STATE_CP, CP_GSMS_MT_WAIT_FOR_RP_ACK);
+        rl_data_ind (&cp_data->cp_user_data_dl);
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+   /* ------------------------------------ */
+      {
+        if (SMS_LLC_FLOW(sms_data) EQ SMS_LLC_AVAILABLE)
+        {
+         /* 
+          * generate CP_ACK
+          */
+          cp_build_cp_ack ();
+         /*
+          * RL_DATA_IND =>
+          */
+          rl_data_ind (&cp_data->cp_user_data_dl);
+        }
+        else
+        {
+          if (SMS_CP_UDL(sms_data) EQ NULL)
+          {
+            MALLOC(SMS_CP_UDL(sms_data), sizeof(T_cp_user_data_dl));
+          }
+          memcpy (SMS_CP_UDL(sms_data), &cp_data->cp_user_data_dl,
+                  sizeof(T_cp_user_data_dl));
+          SMS_CP_ACK_TYPE(sms_data) = SMS_CP_ACK;
+          SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY_WAITING;
+          SMS_INST_SET_STATE (STATE_CP, CP_GSMS_IDLE);
+          SMS_INST.r_flag = TRUE;
+        }
+        break;
+      }
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        cp_error_req_gsms (SMS_CP_CS_MSG_NOT_COMP, FALSE);
+
+        rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                                SMSCP_ORIGINATING_ENTITY, SMS_CP_CS_MSG_NOT_COMP));
+        break;
+      }
+#endif /* GPRS */
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_ind_cp_error       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_IND_CP_ERROR.
+            The cause value is marked as CP-ERROR
+*/
+GLOBAL void cp_data_ind_cp_error (UBYTE      errcs)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_data_ind_cp_error(TI=%u)", SMS_INST.ti);
+  TRACE_EVENT_P1 ("CP Error Cause = %d", (int)errcs);
+
+  if (sms_data)
+  {
+    TRACE_EVENT_P1 ("CP_ERROR.CAUSE rcvd: 0x%2.2X", (int)errcs);
+
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+        /* Implements Measure# 4 */      
+        cp_send_err_ind_errcs(errcs);
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        /* Implements Measure# 4 */
+        cp_send_err_ind_errcs(errcs);
+        break;
+      }
+
+#if defined (GPRS)
+   /* ------------------------------------ */
+      case CP_GSMS_IDLE:
+   /* ------------------------------------ */
+      {
+        SMS_INST.r_flag = FALSE;
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+
+        /* FREE_SMS_INSTANCE (SMS_INST.ti); */
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+   /* ------------------------------------ */
+      {
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.r_flag = FALSE;
+
+        rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET,
+                                SMSCP_ORIGINATING_ENTITY, errcs));
+        /* FREE_SMS_INSTANCE (SMS_INST.ti); */
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+
+        SMS_INST.r_flag = FALSE;
+        rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_NET,
+                      SMSCP_ORIGINATING_ENTITY, errcs));
+
+        /*FREE_SMS_INSTANCE (SMS_INST.ti);*/
+        break;
+      }
+#endif /* GPRS */
+
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_ind_cp_unknown     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_IND_CP_UNKNOWN.
+
+*/
+GLOBAL void cp_data_ind_cp_unknown (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_data_ind_cp_unknown(TI=%u)", SMS_INST.ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+   /* ------------------------------------ */
+      case CP_MM_CONNECTION_ESTABLISHED:
+   /* ------------------------------------ */
+      {
+        /* Implements Measure# 3 */
+        cp_send_err_ind_msg_type_unknown();  
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_WAIT_FOR_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+        /* Implements Measure# 3 */  
+        cp_send_err_ind_msg_type_unknown();  
+        break;
+      }
+
+#if defined (GPRS)
+   /* ------------------------------------ */
+      case CP_GSMS_IDLE:
+   /* ------------------------------------ */
+      {
+        cp_error_req_gsms (SMS_CP_CS_MSG_TYPE_NON_EXIST, TRUE);
+        break;
+      }
+
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_CP_ACK:
+   /* ------------------------------------ */
+      {
+       /*
+        * stop timer TC1M
+        */
+        sms_timer_stop(TC1M);
+      }
+      /*FALLTHROUGH*/ /*lint -fallthrough*/
+   /* ------------------------------------ */
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+   /* ------------------------------------ */
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+   /* ------------------------------------ */
+      {
+        cp_error_req_gsms (SMS_CP_CS_MSG_TYPE_NON_EXIST, FALSE);
+        rl_error_ind (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS,
+                                SMSCP_ORIGINATING_ENTITY, SMS_CP_CS_MSG_TYPE_NON_EXIST));
+
+        break;
+      }
+#endif /* GPRS */
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_establish_req           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_ESTABLISH_REQ.
+
+*/
+
+GLOBAL void cp_establish_req (UBYTE ti)
+{
+  GET_INSTANCE_DATA;
+    TRACE_FUNCTION_P1 ("cp_establish_req(TI=%u)",ti);
+
+#if defined (GPRS)
+    /*
+     * send data on selected downlink
+     */
+    if (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS)
+    {
+#endif /* GPRS */
+
+     /*
+      * GSM - establish connection
+      */
+      switch (SMS_INST_GET_STATE (STATE_CP))
+      {
+     /* ------------------------------------ */
+        case CP_IDLE:
+     /* ------------------------------------ */
+        default:
+     /* ------------------------------------ */
+        {
+          PALLOC (establish_req, MMSMS_ESTABLISH_REQ);
+
+          SMS_EM_MM_CONNECTION_ESTABLISHMENT;
+
+          establish_req->ti = ti;
+
+          SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_PENDING);
+
+          PSENDX (MM, establish_req);
+          break;
+        }
+     /* ------------------------------------ */
+        //default:
+     /* ------------------------------------ */
+        //   TRACE_ERROR("CP_ESTABLISH_REQ in wrong state received!");
+      }
+#if defined (GPRS)
+    }
+    else if (SMS_INST.downlink EQ SMS_DOWNLINK_LL_CHECK)
+    {
+     /*
+      * GMMSMS_REG_STATE_REQ ==>
+      */
+      PALLOC (reg_state_req, GMMSMS_REG_STATE_REQ);
+      PSENDX (GMM, reg_state_req);
+     /*
+      * CP state transition
+      */
+      SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_PENDING);
+     /*
+      * set TI
+      */
+      sms_data->data[INST_MO].ti = ti;
+    }
+    else
+    {
+     /*
+      * set TI
+      */
+      sms_data->data[INST_MO].ti = ti;
+     /*
+      * GPRS - do nothing
+      */
+      rl_establish_cnf(TRUE); /* synchronous call back */
+    }
+#endif /* GPRS */
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_req                |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_REQ.
+
+*/
+
+GLOBAL void cp_data_req (T_U_CP_DATA *cp_data)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_data_req(TI=%u)",SMS_INST.ti);
+
+  if (sms_data)
+  {
+    /*
+     * U_CP_DATA contains a maximum of 252 Bytes
+     */
+    PALLOC_SDU (data_req, MMSMS_DATA_REQ, LEN_U_CP_DATA);
+
+    data_req->sdu.o_buf = ENCODE_OFFSET;
+
+    cp_data->msg_type = U_CP_DATA;
+
+    ccd_codeMsg (CCDENT_SMS,
+                 UPLINK,
+                 (T_MSGBUF *)&data_req->sdu,
+                 (UBYTE *)cp_data,
+                 NOT_PRESENT_8BIT);
+
+    cp_add_pd_ti (SMS_CP_REF(sms_data), &data_req->sdu);
+#if defined (GPRS)
+    /*
+     * send data on selected downlink
+     */
+    if (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS)
+    {
+#endif /* GPRS */
+
+      switch (SMS_INST_GET_STATE (STATE_CP))
+      {
+     /* ------------------------------------ */
+        case CP_MM_CONNECTION_ESTABLISHED:
+     /* ------------------------------------ */
+        {
+          USHORT bsize_message = D_SDU_OFF (data_req)+
+                                 D_SDU_LEN (data_req);
+          PALLOC_SDU (tx_data_req, MMSMS_DATA_REQ, bsize_message);
+         /*
+          * check whether CP ACK needs to be send
+          */
+          if (SMS_INST.cp_ack_pending EQ TRUE)
+          {
+            cp_build_cp_ack ();
+          }
+         /*
+          * reset retry counter
+          */
+          SMS_RETX(sms_data) = 0;
+         /*
+          * save data req
+          */
+          if (SMS_DATA_REQ(sms_data) NEQ NULL)
+            PFREE (SMS_DATA_REQ(sms_data));
+          SMS_DATA_REQ(sms_data) = data_req;
+         /*
+          * CP state transition CP_WAIT_FOR_ACK
+          */
+          SMS_INST_SET_STATE (STATE_CP, CP_WAIT_FOR_ACK);
+
+          SMS_EM_SEND_CP_DATA;
+
+#if FALSE
+          PCOPY (tx_data_req, data_req);
+#else
+          SMS_SDU_COPY (tx_data_req, data_req, MMSMS_DATA_REQ);
+#endif
+          TRACE_BINDUMP(sms_handle,
+                        TC_USER4,
+                        "U_CP_DATA",
+                        (&(tx_data_req->sdu.buf[0]) + ((tx_data_req->sdu.o_buf >> 3) -1)),
+                        ((tx_data_req->sdu.l_buf >> 3) + 1));
+          PSENDX (MM, tx_data_req);
+         /*
+          * start timer TC1M
+          */
+          sms_timer_start(TC1M);
+          break;
+        }
+
+     /* ------------------------------------ */
+        default:
+     /* ------------------------------------ */
+        {
+          TRACE_ERROR("CP_DATA_REQ in wrong state received!");
+          PFREE (data_req);
+          break;
+        }
+      }
+
+#if defined (GPRS)
+    }
+    else
+      cp_data_req_gsms (data_req);
+#endif /* GPRS */
+
+  }
+}
+
+#if defined (GPRS)
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_send_data_gsms          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Send CP_DATA_REQ on LL downlink. LLC availability to be
+            checked by the caller
+*/
+
+GLOBAL void cp_send_data_gsms (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_send_data_gsms()");
+
+  if (sms_data)
+  {
+    USHORT bsize_message = ENCODE_OFFSET +
+                           D_SDU_LEN (SMS_DATA_REQ(sms_data));
+    PALLOC_SDU (unitdata_req, LL_UNITDATA_REQ, bsize_message);
+
+    /*
+     * copy stored mo message sdu to unitdata sdu buffer
+     */
+    SMS_SDU_COPY (unitdata_req, SMS_DATA_REQ(sms_data), LL_UNITDATA_REQ);
+
+    cp_init_ll_unitdata_req (unitdata_req);
+    TRACE_BINDUMP(sms_handle,
+                  TC_USER4,
+                  "U_CP_DATA",
+                  (&(unitdata_req->sdu.buf[0]) + ((unitdata_req->sdu.o_buf >> 3) -1)),
+                  ((unitdata_req->sdu.l_buf >> 3) + 1));
+    PSENDX (LLC, unitdata_req);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_data_req_gsms           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_DATA_REQ on LL downlink.
+
+*/
+
+GLOBAL void cp_data_req_gsms (T_MMSMS_DATA_REQ *data_req)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_data_req_gsms()");
+
+  if (sms_data)
+  {
+    /*
+     * check if LL is still registered
+     */
+    if (SMS_INST.downlink EQ SMS_DOWNLINK_LL_CHECK)
+    {
+      PALLOC (reg_state_req, GMMSMS_REG_STATE_REQ);
+      memset (reg_state_req, 0, sizeof (T_GMMSMS_REG_STATE_REQ));
+      PSENDX (GMM, reg_state_req);
+
+      SMS_INST_SET_STATE (STATE_CP, CP_GSMS_IDLE);
+    }
+
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_IDLE:
+      case CP_GSMS_IDLE:
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+      {
+        /*
+         * save message for later usage
+         */
+        if (SMS_DATA_REQ(sms_data) NEQ NULL)
+        {
+          PFREE (SMS_DATA_REQ(sms_data));
+        }
+        SMS_DATA_REQ(sms_data) = data_req;
+
+        /*
+         * send message if flow control allows
+         */
+        if (SMS_INST.downlink EQ SMS_DOWNLINK_LL)
+        {
+          if (SMS_LLC_FLOW(sms_data) EQ SMS_LLC_AVAILABLE)
+          {
+            cp_send_data_gsms ();
+            SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY;
+          }
+          else
+          {
+            SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY_WAITING;
+          }
+          if ((SMS_INST_GET_STATE (STATE_CP)) EQ CP_GSMS_MT_WAIT_FOR_RP_ACK)
+          {
+            SMS_INST_SET_STATE (STATE_CP, CP_GSMS_MT_WAIT_FOR_CP_ACK);
+          }
+          else if ((SMS_INST_GET_STATE (STATE_CP)) EQ CP_GSMS_MO_WAIT_FOR_CP_DATA)
+          {
+            SMS_INST_SET_STATE (STATE_CP, CP_GSMS_IDLE);
+          }
+          else
+          {
+            SMS_INST_SET_STATE (STATE_CP, CP_GSMS_MO_WAIT_FOR_CP_ACK);
+          }
+          SMS_RETX(sms_data) = 0;
+         /*
+          * start timer TC1M
+          */
+          sms_timer_start(TC1M);
+        }
+        break;
+      }
+
+      default:
+      {
+        PFREE (data_req);
+        break;
+      }
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_error_req_gsms          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Sending CP-ERROR over GPRS with consideration of LLC
+            flow control.
+*/
+
+GLOBAL void cp_error_req_gsms (UBYTE      cause,
+                               BOOL       free_ti)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_error_req_gsms()");
+
+  if (sms_data)
+  {
+    if (SMS_LLC_FLOW(sms_data) EQ SMS_LLC_AVAILABLE)
+    {
+      CCD_START;
+      cp_build_cp_error (cause);
+      CCD_END;
+
+      SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+      SMS_INST.r_flag = FALSE;
+      if(free_ti)
+      {
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+      }
+      sms_data->llc_flow = SMS_LLC_BUSY;
+    }
+    else
+    {
+      SMS_CP_ACK_TYPE(sms_data) = SMS_CP_ERROR;
+      SMS_CP_CAUSE(sms_data) = cause;
+
+      SMS_INST_SET_STATE (STATE_CP, CP_GSMS_IDLE);
+      SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY_WAITING;
+    }
+  }
+}
+#endif /* GPRS */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_est_ind_cp_ack          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_EST_IND_CP_ACK.
+
+*/
+
+GLOBAL void cp_est_ind_cp_ack (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_est_ind_cp_ack(TI=%u)",SMS_INST.ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_IDLE:
+      {
+        cp_build_cp_error (SMS_CP_CS_MSG_NOT_COMP);
+
+        SMS_INST.r_flag = FALSE;
+        /*FALLTHROUGH*/ /*lint -fallthrough*/
+      default:
+        cp_send_release_req (SMS_INST.ti);
+
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+      }
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_est_ind_cp_data         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_EST_IND_CP_DATA.
+
+*/
+
+GLOBAL void cp_est_ind_cp_data (T_D_CP_DATA *cp_data)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_est_ind_cp_data(TI=%u)",SMS_INST.ti);
+
+  switch (SMS_INST_GET_STATE (STATE_CP))
+  {
+    case CP_IDLE:
+    {
+     /*
+      * generate CP_ACK
+      */
+      cp_build_cp_ack ();
+     /*
+      * CP state transition CP_MM_CONNECTION_ESTABLISHED
+      */
+      SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_ESTABLISHED);
+     /*
+      * r flag
+      */
+      SMS_INST.r_flag         = FALSE;
+     /*
+      * RL_DATA_IND =>
+      */
+      rl_data_ind (&cp_data->cp_user_data_dl);
+      break;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_est_ind_cp_error        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_EST_IND_CP_ERROR.
+
+*/
+
+GLOBAL void cp_est_ind_cp_error (UBYTE      cp_error)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_est_ind_cp_error(TI=%u)", SMS_INST.ti);
+  TRACE_EVENT_P1 ("CP Error Cause = %d", (int)cp_error);
+
+  if (sms_data)
+  {
+    TRACE_EVENT_P1 ("CP_ERROR.CAUSE rcvd: 0x%2.2X", (int)cp_error);
+
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_IDLE:
+      {
+        SMS_INST.r_flag = FALSE;
+
+        cp_send_release_req (SMS_INST.ti);
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+      }
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_est_ind_cp_unknown      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_EST_IND_CP_UNKNOWN.
+
+*/
+
+GLOBAL void cp_est_ind_cp_unknown (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_est_ind_cp_unknown(TI=%u)", SMS_INST.ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_IDLE:
+      {
+        cp_build_cp_error (SMS_CP_CS_INFO_NON_EXIST);
+
+        SMS_INST.r_flag = FALSE;
+
+        cp_send_release_req (SMS_INST.ti);
+
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+      }
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_release_req             |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal CP_RELEASE_REQ.
+
+*/
+
+GLOBAL void cp_release_req (UBYTE ti)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION_P1 ("cp_release_req(TI=%u)", ti);
+
+  if (sms_data)
+  {
+    switch (SMS_INST_GET_STATE (STATE_CP))
+    {
+      case CP_IDLE:
+        SMS_INST.r_flag = FALSE;
+        FREE_SMS_INSTANCE (ti);
+        break;
+
+      case CP_WAIT_FOR_ACK:
+        SMS_INST.r_flag = TRUE;
+        break;
+
+      case CP_MM_CONNECTION_PENDING:
+       /*
+        * new connection establishment pending 
+        * while releasing old connection
+        * (-> concat sms)
+        */
+       /*
+        * check whether CP ACK needs to be send
+        */
+        if (SMS_INST.cp_ack_pending EQ TRUE)
+        {
+          cp_build_cp_ack ();
+        }
+       /*
+        * release connection
+        */
+        SMS_INST.r_flag = FALSE;
+        cp_send_release_req (ti);
+        break;
+
+      case CP_MM_CONNECTION_ESTABLISHED:
+       /*
+        * check whether CP ACK needs to be send
+        */
+        if (SMS_INST.cp_ack_pending EQ TRUE)
+        {
+          cp_build_cp_ack ();
+        }
+       /*
+        * CP state transition CP_IDLE
+        */
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+       /*
+        * release connection
+        */
+        SMS_INST.r_flag = FALSE;
+        cp_send_release_req (ti);
+        break;
+
+#ifdef GPRS
+      case CP_GSMS_IDLE:
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.r_flag = FALSE;
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+
+      case CP_GSMS_MO_WAIT_FOR_CP_ACK:
+      case CP_GSMS_MT_WAIT_FOR_CP_ACK:
+        SMS_INST.r_flag = TRUE;
+        break;
+
+      case CP_GSMS_MO_WAIT_FOR_CP_DATA:
+      case CP_GSMS_MT_WAIT_FOR_RP_ACK:
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.r_flag = FALSE;
+        FREE_SMS_INSTANCE (SMS_INST.ti);
+        break;
+#endif /* #ifdef GPRS */
+
+      default:
+        break;
+    }
+  }
+}
+
+#if defined (GPRS)
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_gmmsms_reg_state_cnf    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the signal GMMSMS_REG_STATE_CNF (GSMS only).
+
+*/
+GLOBAL void cp_gmmsms_reg_state_cnf (T_GMMSMS_REG_STATE_CNF *reg_state_cnf)
+{
+  GET_INSTANCE_DATA;
+
+  TRACE_FUNCTION ("cp_gmmsms_reg_state_cnf()");
+
+  if (sms_data EQ NULL)
+  {
+     TRACE_ERROR("Horror: sms_data=NULL");
+     return;
+  }
+
+  if (SMS_INST_GET_STATE (STATE_CP) EQ CP_MM_CONNECTION_PENDING)
+  {
+     /*
+      * CP state transition
+      */
+      SMS_INST_SET_STATE (STATE_CP, CP_GSMS_IDLE);
+      if (reg_state_cnf->reg_state EQ SMS_RS_REGISTERED)
+      {
+         TRACE_EVENT("downlink = SMS_DOWNLINK_LL");
+         SMS_INST.downlink = SMS_DOWNLINK_LL;
+         cp_send_getunitdata_req ();
+        /*
+         * RL_ESTABLISH_CNF =>
+         */
+         rl_establish_cnf(TRUE);
+      }
+      else
+      {
+        /*
+         * RL_ESTABLISH_CNF =>
+         */
+         rl_establish_cnf(FALSE);
+      }
+  }
+  else if (SMS_INST_GET_STATE (STATE_CP) EQ CP_GSMS_IDLE)
+  {
+    if (reg_state_cnf->reg_state EQ SMS_RS_REGISTERED)
+    {
+      SMS_INST.downlink = SMS_DOWNLINK_LL;
+      cp_send_getunitdata_req ();
+
+      if (SMS_LLC_FLOW(sms_data) EQ SMS_LLC_AVAILABLE)
+      {
+        /*
+         * using LL is possible, send message
+         */
+        cp_send_data_gsms ();
+        SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY;
+      }
+      else
+      {
+        SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY_WAITING;
+      }
+      SMS_INST_SET_STATE (STATE_CP, CP_GSMS_MO_WAIT_FOR_CP_ACK);
+      SMS_RETX(sms_data) = 0;
+     /*
+      * start timer TC1M
+      */
+      sms_timer_start(TC1M);
+    }
+    else
+    {
+      SMS_LLC_FLOW(sms_data) = SMS_LLC_UNKNOWN;
+
+      if (sms_data->mo_dst_pref EQ GPRS_SMS_GPRS_PREF)
+      {
+        /*
+         * unsing the preferred downlink LL failed, use CSD
+         */
+
+        PALLOC (establish_req, MMSMS_ESTABLISH_REQ);
+        TRACE_EVENT("GPRS not registered, fallback to CSD");
+
+        establish_req->ti = SMS_INST.ti;
+
+        SMS_INST.downlink = SMS_DOWNLINK_MMSMS;
+        SMS_INST_SET_STATE (STATE_CP, CP_MM_CONNECTION_PENDING);
+
+        PSENDX (MM, establish_req);
+      }
+      else
+      {
+        /*
+         * only GPRS is configured to be used, abort
+         */
+        cp_send_release_req (SMS_INST.ti);
+
+        SMS_INST_SET_STATE (STATE_CP, CP_IDLE);
+        SMS_INST.r_flag = FALSE;
+        
+        SMS_INST.downlink = SMS_DOWNLINK_NONE;
+
+        rl_error_ind (SMS_CAUSE_NO_SERVICE);
+        
+        /* FREE_SMS_INSTANCE (SMS_INST.ti); */
+      }
+    }
+  }
+  PFREE (reg_state_cnf);
+}
+#endif /* GPRS */
+
+/*---- FUNCTIONS ---------------------------------------------------*/
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_build_cp_ack            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function CP_BUILD_CP_ACK.
+            (GPRS: the appropriate downlink is determined first)
+*/
+GLOBAL void cp_build_cp_ack (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_build_cp_ack()");
+
+ /*
+  * reset cp ack pending
+  */
+  SMS_INST.cp_ack_pending = FALSE;
+
+#if defined (GPRS)
+  if (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS)
+#endif /* GPRS */
+  {
+    PALLOC_SDU (data_req, MMSMS_DATA_REQ, ENCODE_OFFSET+BSIZE_B_CP_ACK);
+
+    data_req->sdu.o_buf = ENCODE_OFFSET;
+    data_req->sdu.l_buf = BSIZE_B_CP_ACK;
+
+    data_req->sdu.buf[BYTELEN_POS(data_req->sdu.o_buf)] = B_CP_ACK;
+    cp_add_pd_ti (SMS_CP_REF(sms_data), &data_req->sdu);
+
+    SMS_EM_SEND_CP_ACKNOWLEDGE;
+    TRACE_BINDUMP(sms_handle,
+                  TC_USER4,
+                  "B_CP_ACK",
+                  (&(data_req->sdu.buf[0]) + ((data_req->sdu.o_buf >> 3) -1)),
+                  ((data_req->sdu.l_buf >> 3) + 1));
+    PSENDX (MM, data_req);
+    return;
+  }
+
+#if defined (GPRS)
+  if ((SMS_INST.downlink EQ SMS_DOWNLINK_LL) /*AND
+      (sms_data->llc_flow EQ SMS_LLC_AVAILABLE)*/)
+  {
+    /*
+     * build cp_ack for LL downlink
+     */
+    PALLOC_SDU (unitdata_req, LL_UNITDATA_REQ, ENCODE_OFFSET+BSIZE_B_CP_ACK);
+
+    unitdata_req->sdu.o_buf = ENCODE_OFFSET;
+    unitdata_req->sdu.l_buf = BSIZE_B_CP_ACK;
+
+    unitdata_req->sdu.buf[BYTELEN_POS(unitdata_req->sdu.o_buf)] = B_CP_ACK;
+    cp_add_pd_ti (SMS_CP_REF(sms_data), &unitdata_req->sdu);
+
+    cp_init_ll_unitdata_req (unitdata_req);
+
+    SMS_LLC_FLOW(sms_data) = SMS_LLC_BUSY;
+    TRACE_BINDUMP(sms_handle,
+                  TC_USER4,
+                  "B_CP_ACK",
+                  (&(unitdata_req->sdu.buf[0]) + ((unitdata_req->sdu.o_buf >> 3) -1)),
+                  ((unitdata_req->sdu.l_buf >> 3) + 1));
+    PSENDX (LLC, unitdata_req);
+  }
+#endif /* GPRS */
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_build_cp_error          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Processing the function CP_BUILD_CP_ERROR.
+
+*/
+GLOBAL void cp_build_cp_error (UBYTE      error)
+{
+  GET_INSTANCE_DATA;
+  if (sms_data)
+  {
+    TRACE_EVENT_P1 ("CP_ERROR.CAUSE sent: 0x%2.2X", (int)error);
+
+#if defined (GPRS)
+    if (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS)
+#endif /* GPRS */
+
+    {
+      MCAST (cp_error, B_CP_ERROR);
+      PALLOC_MSG (data_req, MMSMS_DATA_REQ, B_CP_ERROR);
+
+      TRACE_FUNCTION ("cp_build_cp_error()");
+
+      SMS_EM_SEND_CP_ERROR;
+
+     /*
+      * check whether CP ACK needs to be send
+      */
+      if (SMS_INST.cp_ack_pending EQ TRUE)
+      {
+        cp_build_cp_ack ();
+      }
+
+      data_req->sdu.o_buf = ENCODE_OFFSET;
+
+      cp_error->msg_type = B_CP_ERROR;
+      cp_error->cp_cause = error;
+
+      ccd_codeMsg (CCDENT_SMS,
+                   UPLINK,
+                   (T_MSGBUF *) &data_req->sdu,
+                   (UBYTE *) _decodedMsg,
+                   NOT_PRESENT_8BIT);
+
+      cp_add_pd_ti (SMS_CP_REF(sms_data), &data_req->sdu);
+      TRACE_BINDUMP(sms_handle,
+                    TC_USER4,
+                    "B_CP_ERROR",
+                    (&(data_req->sdu.buf[0]) + ((data_req->sdu.o_buf >> 3) -1)),
+                    ((data_req->sdu.l_buf >> 3) + 1));
+      PSENDX (MM, data_req);
+      return;
+    }
+
+#if defined (GPRS)
+    if ((SMS_INST.downlink EQ SMS_DOWNLINK_LL) /*&&
+        (sms_data->llc_flow EQ SMS_LLC_AVAILABLE)*/)
+    {
+      /*
+       * build cp_error for LL downlink
+       */
+      MCAST (cp_error, B_CP_ERROR);
+
+      PALLOC_MSG (unitdata_req, LL_UNITDATA_REQ, B_CP_ERROR);
+
+      TRACE_FUNCTION ("cp_build_cp_error() - LL downlink");
+
+      unitdata_req->sdu.o_buf = ENCODE_OFFSET;
+
+      cp_error->msg_type = B_CP_ERROR;
+      cp_error->cp_cause = error;
+
+      ccd_codeMsg (CCDENT_SMS,
+                   UPLINK,
+                   (T_MSGBUF *) &unitdata_req->sdu,
+                   (UBYTE *) _decodedMsg,
+                   NOT_PRESENT_8BIT);
+
+      cp_add_pd_ti (SMS_CP_REF(sms_data), &unitdata_req->sdu);
+      cp_init_ll_unitdata_req (unitdata_req);
+      TRACE_BINDUMP(sms_handle,
+                    TC_USER4,
+                    "B_CP_ERROR",
+                    (&(unitdata_req->sdu.buf[0]) + ((unitdata_req->sdu.o_buf >> 3) -1)),
+                    ((unitdata_req->sdu.l_buf >> 3) + 1));
+      PSENDX (LLC, unitdata_req);
+    }
+#endif /* GPRS */
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (8410)       MODULE  : SMS_CP                     |
+| STATE   : code                ROUTINE : cp_send_release_req        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Send a MMSMS_RELEASE_REQ.
+            (GPRS: only if this is not an LL downlink)
+
+*/
+GLOBAL void cp_send_release_req ( UBYTE ti)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("cp_send_release_req()");
+
+  if (sms_data)
+  {
+#if defined (GPRS)
+    if (SMS_INST.downlink EQ SMS_DOWNLINK_MMSMS)
+    {
+#endif
+      PALLOC (release_req, MMSMS_RELEASE_REQ);
+
+      release_req->ti = ti;
+
+      PSENDX (MM, release_req);
+
+#if defined (GPRS)
+    }
+#endif
+  }
+}
+
+#endif