view src/aci2/aci/ati_sms.c @ 680:ee3ac8c617cb

armio.c: set GPIO2 output high initially On TI-canonical platforms GPIO2 is DCD modem control output. In TI's original code the AI_InitIOConfig() function called from Init_Target() would configure GPIO2 as an output and set the initial output value to low, but then the init code in uartfax.c called from Init_Serial_Flows() would immediately change it to high, corresponding to DCD not asserted. The result is a momentary asserted-state glitch on the DCD output. The present change eliminates this glitch, setting DCD output to not-asserted initially like it should be.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 25 Jun 2020 03:17:43 +0000
parents 93999a60b835
children
line wrap: on
line source

/*
+----------------------------------------------------------------------------- 
|  Project :  GSM-F&D (8411)
|  Modul   :  ATI
+----------------------------------------------------------------------------- 
|  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 :  AT Command Interpreter: SMS related functions.
+----------------------------------------------------------------------------- 
*/ 

#ifndef ATI_SMS_C
#define ATI_SMS_C

#undef DUMMY_ATI_STRINGS

#include "aci_all.h"

#include "aci_cmh.h"
#include "ati_cmd.h"
#include "aci_io.h"
#include "aci_cmd.h"
#include "l4_tim.h"

#include "aci_mem.h"

#include "aci_lst.h"
#include "conc_sms.h"
#include "aci_prs.h"

#include "ati_int.h"

#include "cmh_sms.h"
#include "psa.h"
#include "psa_sms.h"
#include "aci.h"

#ifdef FF_ATI_BAT

#include "typedefs.h"
#include "gdd.h"
#include "bat.h"

#include "ati_bat.h"

#endif /*FF_ATI_BAT*/

EXTERN T_SMS_SHRD_PRM smsShrdPrm;

const SMS_Memory sms_mem [] =
{
  {"ME",  SMS_STOR_Me},
  {"SM",  SMS_STOR_Sm},
  {0,0}
};

#if defined (SMS_PDU_SUPPORT)
LOCAL T_ATI_RSLT atPlusCMGSText (char *cl, UBYTE srcId);
LOCAL T_ATI_RSLT atPlusCMGWText (char *cl, UBYTE srcId);
LOCAL T_ATI_RSLT atPlusCMGCText (char *cl, UBYTE srcId);
LOCAL T_ATI_RSLT atPlusCNMAText (char *cl, UBYTE srcId);
#endif

/* move the define into aci_cmd.h */

GLOBAL void         cmd_clearCnmiBuf    (void);

LOCAL  T_CNMI_BUFFER    cnmiBuf;
GLOBAL BOOL             cnmiFlushInProgress   = FALSE;
GLOBAL S16              waitForCnmaFromBuffer_SrcId = CMD_SRC_NONE;
LOCAL  CHAR daBuf[MAX_SMS_NUM_LEN];

EXTERN SHORT  cmhSMS_getPrfRge ( void );
EXTERN BOOL check_str(char * string,char * sample);

#ifdef _SIMULATION_
GLOBAL char subBuf[MAX_SUBADDR_LEN];
#endif /* _SIMULATION_ */

GLOBAL SHORT  toda_val;
GLOBAL SHORT  fo, ct, pid, mn;

GLOBAL UBYTE  cpmsCallType = NONE_CALL;

/*
 *
 ----------------------------SMS Commands-----------------------------------
 *
 */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSMS         |
+--------------------------------------------------------------------+

  PURPOSE : +CSMS command (Select Message Service)
*/

GLOBAL T_ATI_RSLT atPlusCSMS (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = AT_FAIL;
  T_ACI_CSMS_SERV service;

  TRACE_FUNCTION("atPlusCSMS()");

  /*input functionality*/
  cl = parse (cl,"d",&service);
  if ( !cl OR service > 1)
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return (ATI_FAIL);
  }
  ret = sAT_PlusCSMS(srcId,service);
  if (ret EQ AT_FAIL)
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
  return (ATI_CMPL);
}

GLOBAL T_ATI_RSLT queatPlusCSMS (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = AT_FAIL;
  T_ACI_CSMS_SERV service;
  T_ACI_CSMS_SUPP mt;
  T_ACI_CSMS_SUPP mo;
  T_ACI_CSMS_SUPP bm;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);


  ret = qAT_PlusCSMS(srcId,&service,&mt,&mo,&bm);
  if (ret EQ AT_CMPL)
  {
    sprintf(g_sa,"+CSMS: %d,%d,%d,%d",service,mt,mo,bm);
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  if (ret EQ AT_EXCT)
  {
    src_params->curAtCmd    = AT_CMD_CSMS;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCPMS         |
+--------------------------------------------------------------------+

  PURPOSE : +CPMS command (Select Preferred Message Storage)
*/

GLOBAL T_ATI_RSLT atPlusCPMS (char *cl, UBYTE srcId)
{
  CHAR*              me         = "+CPMS: ";
  CHAR               memstr1[3] = {0};
  CHAR               memstr2[3] = {0};
  CHAR               memstr3[3] = {0};
  T_ACI_RETURN       ret = AT_FAIL;
  T_ACI_SMS_STOR_OCC mem1;
  T_ACI_SMS_STOR_OCC mem2;
  T_ACI_SMS_STOR_OCC mem3;
  BOOL               f1         = TRUE;
  BOOL               f2         = TRUE;
  BOOL               f3         = TRUE;
  SHORT              i;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCPMS()");

  mem1.mem = SMS_STOR_NotPresent;
  mem2.mem = SMS_STOR_NotPresent;
  mem3.mem = SMS_STOR_NotPresent;

  /*input functionality*/
  cl = parse ( cl, "sss", (LONG)3, memstr1,
                          (LONG)3, memstr2,
                          (LONG)3, memstr3 );

  strupper ( memstr1 );
  strupper ( memstr2 );
  strupper ( memstr3 );

  for ( i=0; sms_mem[i].name NEQ NULL; i++ )
  {
    if ( ( strcmp ( sms_mem[i].name, memstr1 ) EQ 0 ) AND f1 )
    {
      mem1.mem = sms_mem[i].stor;
      f1       = FALSE;
    }

    if ( ( strcmp ( sms_mem[i].name, memstr2 ) EQ 0 ) AND f2 )
    {
      mem2.mem = sms_mem[i].stor;
      f2       = FALSE;
    }

    if ( ( strcmp ( sms_mem[i].name, memstr3 ) EQ 0 ) AND f3 )
    {
      mem3.mem = sms_mem[i].stor;
      f3       = FALSE;
    }
  }

  if (!cl OR f1 /*OR f2 OR f3*/ )
  {
    cmdCmsError ( CMS_ERR_OpNotAllowed );
    return (ATI_FAIL);
  }

#ifdef FF_ATI_BAT
{
  T_BAT_cmd_send     cmd;
  T_BAT_cmd_set_plus_cpms cpms;
  cmd.ctrl_params              = BAT_CMD_SET_PLUS_CPMS;
  cmd.params.ptr_set_plus_cpms = &cpms;

  cpms.mem1 = (T_BAT_plus_cpms_mem1)mem1.mem;
  cpms.mem2 = (T_BAT_plus_cpms_mem2)mem2.mem;
  cpms.mem3 = (T_BAT_plus_cpms_mem3)mem3.mem;
  
  TRACE_FUNCTION("atPlusCPMS() calls bat_send() <=== as APPLICATION");
  bat_send(ati_bat_get_client(srcId), &cmd);

  return (AT_EXCT);
}
#else /* FF_ATI_BAT */

  ret = sAT_PlusCPMS ( srcId, mem1.mem, mem2.mem, mem3.mem );

  switch(ret)
  {
    case(AT_CMPL):
    {
      src_params->curAtCmd     = AT_CMD_NONE;
      return (ATI_CMPL);
    }
    default:
    {
      cmdCmsError (CMS_ERR_NotPresent);  // use aciErrDesc
      return (ATI_FAIL);
    }
  }
  #endif /* FF_ATI_BAT */
}

GLOBAL T_ATI_RSLT queatPlusCPMS (char *cl, UBYTE srcId)
{
  T_ACI_RETURN       ret;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  /*returns current Memory setting*/
  ret = qAT_PlusCPMS ( srcId );

  if ( ret EQ AT_CMPL )
  {
    src_params->curAtCmd     = AT_CMD_NONE;
    return (ATI_CMPL);
  }
  else if ( ret EQ AT_EXCT )
  {
    src_params->curAtCmd     = AT_CMD_CPMS;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError ( CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGF         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGF command (Select Message Format)
*/

GLOBAL T_ATI_RSLT atPlusCMGF (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = AT_FAIL;
  T_ACI_CMGF_MOD mode=CMGF_MOD_NotPresent;

  TRACE_FUNCTION("atPlusCMGF()");

  /*
   * input functionality
   */
  cl = parse(cl,"d",&mode);
  if ( cl)
  {
    switch (mode)
    {
      case CMGF_MOD_Pdu:  /* PDU mode */
#if !defined (SMS_PDU_SUPPORT)
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
#else
         break;
#endif
       case CMGF_MOD_Txt:  /* Text Mode */
       default:
         break;
     }
   }
   else
   {
     /*
      * parse problems
      */
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return (ATI_FAIL);
   }
   /*
    * Parameter is allowed then set
    */
   ret = sAT_PlusCMGF (srcId,mode);
   if (ret EQ AT_FAIL)
   {
     cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
     return (ATI_FAIL);
   }
   return (map_aci_2_ati_rslt(ret));
}

GLOBAL T_ATI_RSLT queatPlusCMGF (char *cl, UBYTE srcId)
{
  char *me="+CMGF: ";
  T_ACI_RETURN ret = AT_FAIL;
  T_ACI_CMGF_MOD mode=CMGF_MOD_NotPresent;

  TRACE_FUNCTION("queatPlusCMGF()");

  /*
   * returns current message format PDU/TEXT
   */
  ret = qAT_PlusCMGF(srcId, &mode);
  if (ret EQ AT_CMPL)
  {
    sprintf(g_sa,"%s%d",me,mode);
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSCA         |
+--------------------------------------------------------------------+

  PURPOSE : +CSCA command (Select Message Service Centre)
*/

GLOBAL T_ATI_RSLT atPlusCSCA (char *cl, UBYTE srcId)
{
  T_ACI_RETURN  ret = ATI_FAIL;
  T_ACI_TOA     tosca;
  T_ACI_TOA    *p_tosca;
  SHORT         octet=0;
  CHAR          sca[MAX_SMS_NUM_LEN];

  memset (sca, 0, sizeof(sca));
  p_tosca=&tosca;

  TRACE_FUNCTION("atPlusCSCA()");

  /*input functionality*/
  cl = parse (cl,"sr",(LONG)MAX_SMS_NUM_LEN,sca,&octet);
  if ( !cl OR octet > 0xC9 OR sca[0] EQ '\0')
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
  if(octet EQ 0)
    p_tosca=NULL;
  else
  {
    tosca=toa_demerge(octet);
    if (tosca.ton < 0 OR tosca.npi < 0)
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
  }
#ifdef FF_ATI_BAT
{
  T_BAT_cmd_send     cmd;
  T_BAT_cmd_set_plus_csca csca;
  
  cmd.ctrl_params              = BAT_CMD_SET_PLUS_CSCA;
  cmd.params.ptr_set_plus_csca = &csca;

  csca.c_sca = strlen(sca);  
  memcpy(csca.sca, sca, csca.c_sca);
  csca.tosca = octet;  

  TRACE_FUNCTION("atPlusCSCA() calls bat_send() <=== as APPLICATION");
  bat_send(ati_bat_get_client(srcId), &cmd);

  return (AT_EXCT);
}
#else /* FF_ATI_BAT */
 
  ret = sAT_PlusCSCA(srcId,sca,p_tosca);
  if (ret EQ AT_FAIL)
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
  return (map_aci_2_ati_rslt(ret));
#endif /* FF_ATI_BAT */
}

GLOBAL T_ATI_RSLT queatPlusCSCA (char *cl, UBYTE srcId)
{
#ifdef FF_ATI_BAT
  T_BAT_cmd_send     cmd;
  T_BAT_no_parameter dummy;
  
  cmd.ctrl_params              = BAT_CMD_QUE_PLUS_CSCA;
  dummy.bat_dummy              = 0xFF;
  cmd.params.ptr_que_plus_csca = &dummy;

  TRACE_FUNCTION("queatPlusCSCA() calls bat_send() <=== as APPLICATION");
  bat_send(ati_bat_get_client(srcId), &cmd);

  return (AT_EXCT);

#else /* FF_ATI_BAT */

  T_ACI_RETURN  ret = AT_FAIL;
  T_ACI_TOA     tosca;
  SHORT         octet=0;
  CHAR          sca[MAX_SMS_NUM_LEN];

  ret = qAT_PlusCSCA (srcId,sca,&tosca);
  if (ret EQ AT_CMPL)
  {
    octet=toa_merge(tosca);
    sprintf(g_sa, "+CSCA: \"%s%s\",%d", (tosca.ton EQ TON_International)?"+":"", sca, octet);
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
#endif /* FF_ATI_BAT */  
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : aci_decodeVpabs    |
+--------------------------------------------------------------------+

  PURPOSE : This function decodes a given string to the T_ACI_VP_ABS
            enumeration type.
*/
LOCAL BOOL aci_decodeVpabs ( CHAR*         vpabs_str,
                             T_ACI_VP_ABS* vpabs_enum )
{
  if ( strlen( vpabs_str ) NEQ 20 OR

       vpabs_str[2]  NEQ '/' OR vpabs_str[5]  NEQ '/' OR
       vpabs_str[8]  NEQ ',' OR vpabs_str[11] NEQ ':' OR
       vpabs_str[14] NEQ ':' OR

       ( vpabs_str[17] NEQ '+' AND vpabs_str[17] NEQ '-' ) OR

       vpabs_str[18] < '0' OR vpabs_str[18] > '9' OR
       vpabs_str[19] < '0' OR vpabs_str[19] > '9'             )

    return FALSE;

  vpabs_enum->year  [0] = vpabs_str[0]  - 0x30;
  vpabs_enum->year  [1] = vpabs_str[1]  - 0x30;

  vpabs_enum->month [0] = vpabs_str[3]  - 0x30;
  vpabs_enum->month [1] = vpabs_str[4]  - 0x30;

  vpabs_enum->day   [0] = vpabs_str[6]  - 0x30;
  vpabs_enum->day   [1] = vpabs_str[7]  - 0x30;

  vpabs_enum->hour  [0] = vpabs_str[9]  - 0x30;
  vpabs_enum->hour  [1] = vpabs_str[10] - 0x30;

  vpabs_enum->minute[0] = vpabs_str[12] - 0x30;
  vpabs_enum->minute[1] = vpabs_str[13] - 0x30;

  vpabs_enum->second[0] = vpabs_str[15] - 0x30;
  vpabs_enum->second[1] = vpabs_str[16] - 0x30;

  vpabs_enum->timezone  = (SHORT) atoi( &vpabs_str[17] );

  return TRUE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : aci_decodeVpenh    |
+--------------------------------------------------------------------+

  PURPOSE : This function decodes a given string to the T_ACI_VP_ENH
            type.
*/
LOCAL BOOL aci_decodeVpenh ( CHAR*         vpenh_str,
                             T_ACI_VP_ENH* vpenh )
{
  UBYTE shift_byte = 0;

  if (vpenh_str[0] EQ '\0')
  {
    return FALSE;
  }

  /* functionality indicator */
  vpenh->func_ind = (vpenh_str[0]  - 0x30) << 4;
  vpenh->func_ind += (vpenh_str[1]  - 0x30);

  /* extension octet */
  if (vpenh->func_ind & TP_VPF_ENH_EXT_BIT_MASK)
  {
    shift_byte = 2;
    vpenh->ext_oct = (vpenh_str[2]  - 0x30) << 4;
    vpenh->ext_oct += (vpenh_str[3]  - 0x30);
  }

  if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) > TP_VPF_ENH_HRS)
  {
    return FALSE;
  }

  /* process validity period values */
  if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_REL)
  {
    utl_HexStrToBin ((UBYTE*)&vpenh_str[2+shift_byte], 2, &vpenh->val.vpenh_relative, 1);
  }
  else if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_SEC)
  {
    utl_HexStrToBin ((UBYTE*)&vpenh_str[2+shift_byte], 2, &vpenh->val.vpenh_seconds, 1);
  }
  else if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_HRS)
  {
    vpenh->val.vpenh_hours.hour  [0] = vpenh_str[3+shift_byte] - 0x30;
    vpenh->val.vpenh_hours.hour  [1] = vpenh_str[2+shift_byte] - 0x30;

    vpenh->val.vpenh_hours.minute[0] = vpenh_str[5+shift_byte] - 0x30;
    vpenh->val.vpenh_hours.minute[1] = vpenh_str[4+shift_byte] - 0x30;

    vpenh->val.vpenh_hours.second[0] = vpenh_str[7+shift_byte] - 0x30;
    vpenh->val.vpenh_hours.second[1] = vpenh_str[6+shift_byte] - 0x30;
  }

  return TRUE;
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSMP         |
+--------------------------------------------------------------------+

  PURPOSE : +CSMP command (Select Text Mode Parameters)
*/

GLOBAL T_ATI_RSLT atPlusCSMP (char *cl, UBYTE srcId)
{

  char*         me            = "+CSMP: ";
  T_ACI_RETURN  ret           = AT_FAIL;
  SHORT         fo            = ACI_NumParmNotPresent,
                vprel         = ACI_NumParmNotPresent,
                pid           = ACI_NumParmNotPresent,
                dcs           = ACI_NumParmNotPresent;
  USHORT        i             = 0;
  char          vpabs_str[25] = {'\0'},
                vpenh_str[15] = {'\0'},
                fo_str[4];

  T_ACI_VP_ABS  vpabs;
  T_ACI_VP_ABS* pVpabs        = NULL;
  T_ACI_VP_ENH  vpenh;

  TRACE_FUNCTION("atPlusCSMP()");

   /*input functionality*/
   while (*cl NEQ ',' AND *cl NEQ '\0' AND i < sizeof(fo_str) - 1)
   {
     fo_str[i]=*cl;
     cl++;
     i++;
   }
   if (*cl)
   {
     cl++;
   }
   fo_str[i]='\0';
   if (strlen (fo_str) > 0)
   {
     fo=atoi(fo_str);
   }
   if (fo > 255)
   {
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return 0;
   }
   if (fo NEQ ACI_NumParmNotPresent AND
       (fo & TP_VPF_MASK) EQ TP_VPF_ABSOLUTE)
   {
     pVpabs = &vpabs;

     cl = parse(cl,"srr",(LONG)25,vpabs_str,&pid,&dcs);

     if (!cl OR strlen(vpabs_str) > 20 OR pid > 255 OR
         dcs > 255 OR !aci_decodeVpabs (vpabs_str, &vpabs))
     {
       cmdCmsError(CMS_ERR_OpNotAllowed);
       return (ATI_FAIL);
     }
   }
   else if (fo NEQ ACI_NumParmNotPresent AND
       (fo & TP_VPF_MASK) EQ TP_VPF_ENHANCED)
   {
     cl = parse(cl,"srr",(LONG)19,vpenh_str,&pid,&dcs);
     if (!cl OR strlen(vpenh_str) > 14 OR pid > 255 OR
         dcs > 255 OR !aci_decodeVpenh (vpenh_str, &vpenh))
     {
       cmdCmsError(CMS_ERR_OpNotAllowed);
       return (ATI_FAIL);
     }
   }
   else if (fo NEQ ACI_NumParmNotPresent AND
       (fo & TP_VPF_MASK) EQ TP_VPF_RELATIVE)
   {
     cl = parse(cl,"rrr",&vprel,&pid,&dcs);
   }
   else
   {
     if (*cl EQ '\"')
     {
       pVpabs = &vpabs;

       cl = parse(cl,"srr",(LONG)25,vpabs_str,&pid,&dcs);

       if (!cl OR strlen(vpabs_str) > 20 OR pid > 255 OR
           dcs > 255 OR !aci_decodeVpabs (vpabs_str, &vpabs))
       {
         cmdCmsError(CMS_ERR_OpNotAllowed);
         return (ATI_FAIL);
       }
     }
     else
     {
       cl = parse(cl,"rrr",&vprel,&pid,&dcs);

       if ( !cl OR vprel > 255 OR pid > 255 OR dcs > 255)
       {
         cmdCmsError(CMS_ERR_OpNotAllowed);
         return (ATI_FAIL);
       }
     }
   }
   ret = sAT_PlusCSMP(srcId,fo,vprel,pVpabs,&vpenh,pid,dcs);
   if (ret EQ AT_FAIL)
   {
     cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
     return (ATI_FAIL);
   }
   return (map_aci_2_ati_rslt(ret));
}

GLOBAL T_ATI_RSLT queatPlusCSMP (char *cl, UBYTE srcId)
{
  char*         me            = "+CSMP: ";
  T_ACI_RETURN  ret           = AT_FAIL;
  SHORT         fo            = ACI_NumParmNotPresent,
                vprel         = ACI_NumParmNotPresent,
                pid           = ACI_NumParmNotPresent,
                dcs           = ACI_NumParmNotPresent,
                i             = 0;
  char          vpabs_str[25] = {'\0'};
  char          vpenh_str[15] = {'\0'};
  T_ACI_VP_ABS  vpabs;
  T_ACI_VP_ENH  vpenh;

  TRACE_FUNCTION("queatPlusCSMP()");

  ret = qAT_PlusCSMP(srcId,&fo,&vprel,&vpabs,&vpenh,&pid,&dcs);
  if (ret EQ AT_CMPL)
  {
    if ((fo & TP_VPF_MASK) EQ TP_VPF_ABSOLUTE)   /*Bits 4,3 -> 11*/
    {
      sprintf(vpabs_str,"\"%d%d/%d%d/%d%d,%d%d:%d%d:%d%d%+03d\"",
              vpabs.year  [0], vpabs.year  [1],
              vpabs.month [0], vpabs.month [1],
              vpabs.day   [0], vpabs.day   [1],
              vpabs.hour  [0], vpabs.hour  [1],
              vpabs.minute[0], vpabs.minute[1],
              vpabs.second[0], vpabs.second[1],
              vpabs.timezone);
      sprintf(g_sa,"%s%d,%s,%d,%d",me,fo,vpabs_str,pid,dcs);
    }
    else if ((fo & TP_VPF_MASK) EQ TP_VPF_ENHANCED)
    {
      aci_encodeVpenh ( vpenh_str, &vpenh );
      sprintf(g_sa,"%s%d,\"%s\",%d,%d",me,fo,vpenh_str,pid,dcs);
    }
    else if ((fo & TP_VPF_MASK) EQ TP_VPF_RELATIVE) /*Bits 4,3 -> 10*/
    {
      sprintf(g_sa,"%s%d,%d,%d,%d",me,fo,vprel,pid,dcs);
    }
    else
    {
      sprintf(g_sa,"%s%d,,%d,%d",me,fo,pid,dcs);
    }
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSDH         |
+--------------------------------------------------------------------+

  PURPOSE : +CSDH command (Show Text Mode Parameters)
*/

GLOBAL T_ATI_RSLT atPlusCSDH (char *cl, UBYTE srcId)
{

  T_ACI_CSDH_SHOW ena = CSDH_SHOW_Disable;

  TRACE_FUNCTION("atPlusCSDH()");

   /*input functionality*/
   cl = parse(cl,"d",&ena);
   if ( !cl )
   {
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return (ATI_FAIL);
   }
   ati_user_output_cfg[srcId].CSDH_stat=ena;
   return (ATI_CMPL);
}

GLOBAL T_ATI_RSLT tesatPlusCSDH (char *cl, UBYTE srcId)
{
  return(atPlusCSDH (cl, srcId));
}

GLOBAL T_ATI_RSLT queatPlusCSDH (char *cl, UBYTE srcId)
{
  sprintf(g_sa,"+CSDH: %d",ati_user_output_cfg[srcId].CSDH_stat);
  io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
  return (ATI_CMPL);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSCB         |
+--------------------------------------------------------------------+

  PURPOSE : +CSCB command (select cell broadcast message type)
*/

GLOBAL T_ATI_RSLT atPlusCSCB (char *cl, UBYTE srcId)
{
  char            *me="+CSCB: ";
  T_ACI_RETURN    ret = AT_FAIL;
  T_ACI_CSCB_MOD  mode;
  char            mids_str[6*MAX_CBM_TYPES]={0};    /* CHECK IF LONG ENOUGH !!*/
  char            dcss_str[4*MAX_CBM_TYPES]={0};
  CHAR            buf[6]={0};
  USHORT          mids[MAX_CBM_TYPES];
  UBYTE           dcss[MAX_CBM_TYPES];
  SHORT           pos=0,i=0,j=0;

#ifdef FF_ATI_BAT
  T_BAT_cmd_set_plus_cscb cscb;
#endif


  TRACE_FUNCTION("atPlusCSCB()");

   /*input functionality*/
   cl = parse(cl,"dss",&mode,(LONG)sizeof(mids_str),mids_str,(LONG)sizeof(dcss_str),dcss_str);
   if ( !cl )
   {
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return (ATI_FAIL);
   }
   i = j = 0;
   memset (mids, NOT_PRESENT_8BIT, sizeof (mids));
   while (mids_str[i] NEQ '\0' AND j < MAX_CBM_TYPES - 1)
   {
     pos=0;
     while (mids_str[i] >= '0'  AND  mids_str[i] <= '9')
     {
       if (pos >= 5)
       {
         cmdCmsError(CMS_ERR_OpNotAllowed);
         return (ATI_FAIL);
       }
       buf[pos++]=mids_str[i];
       i++;
     }
     buf[pos]='\0';
     if (mids_str[i] NEQ ','  AND  mids_str[i] NEQ '-'  AND  mids_str[i] NEQ '\0')
     {
       cmdCmsError(CMS_ERR_OpNotAllowed);
       return (ATI_FAIL);
     }
     else
     {
       if (mids_str[i] EQ ',' OR mids_str[i] EQ '\0')
       {
         i++;
         mids[j++]=atoi(buf);
         mids[j++]=atoi(buf);
       }
       else
       {
         i++;
         mids[j++]=atoi(buf);
         pos=0;
         while (mids_str[i] NEQ ','  AND  mids_str[i] NEQ '\0')
         {
           if (pos >= 5)
           {
             cmdCmsError(CMS_ERR_OpNotAllowed);
             return (ATI_FAIL);
           }
           buf[pos++]=mids_str[i];
           i++;
         }
         i++;
         mids[j++]=atoi(buf);
       }
     }
   }
 
   if (compact(&mids_str[i],(USHORT)strlen(&mids_str[i])) NEQ 0)
   {
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return (ATI_FAIL);
   }

#ifdef FF_ATI_BAT
   memset(cscb.mids, NOT_PRESENT_8BIT, sizeof(cscb.mids));
   cscb.v_mids = j ? TRUE : FALSE;
   cscb.c_mids = (U8)j;
   memcpy(cscb.mids, mids, j*2);
#endif

   i = j = 0;
   memset (dcss, NOT_PRESENT_8BIT, sizeof (dcss));
   while (dcss_str[i] NEQ '\0' AND j < MAX_CBM_TYPES - 1)
   {
     pos=0;
     while (dcss_str[i] >= '0'  AND  dcss_str[i] <= '9')
     {
       if (pos >= 3)
       {
         cmdCmsError(CMS_ERR_OpNotAllowed);
         return (ATI_FAIL);
       }
       buf[pos++]=dcss_str[i];
       i++;
     }
     buf[pos]='\0';
     if (dcss_str[i] NEQ ','  AND  dcss_str[i] NEQ '-'  AND  dcss_str[i] NEQ '\0')
     {
       cmdCmsError(CMS_ERR_OpNotAllowed);
       return (ATI_FAIL);
     }
     else
     {
       if (dcss_str[i] EQ ',' OR dcss_str[i] EQ '\0')
       {
         i++;
         dcss[j++]=atoi(buf);
         dcss[j++]=atoi(buf);
       }
       else
       {
         i++;
         dcss[j++]=atoi(buf);
         pos=0;
         while (dcss_str[i] NEQ ','  AND  dcss_str[i] NEQ '\0')
         {
           if (pos >= 3)
           {
             cmdCmsError(CMS_ERR_OpNotAllowed);
             return (ATI_FAIL);
           }
           buf[pos++]=dcss_str[i];
           i++;
         }
         i++;
         dcss[j++]=atoi(buf);
       }
     }
   }
   if (compact(&dcss_str[i],(USHORT)strlen(&dcss_str[i])) NEQ 0)
   {
     cmdCmsError(CMS_ERR_OpNotAllowed);
     return (ATI_FAIL);
   }
   
#ifdef FF_ATI_BAT
   {
      T_BAT_cmd_send cmd;

      cmd.ctrl_params = BAT_CMD_SET_PLUS_CSCB;
      cmd.params.ptr_set_plus_cscb = &cscb;

      cscb.mode = (T_BAT_VAL_plus_cscb_mode)mode;
            
      memset(cscb.dcss, NOT_PRESENT_8BIT, sizeof(cscb.dcss));
      cscb.v_dcss = j ? TRUE : FALSE;;
      cscb.c_dcss = (U8)j;
      memcpy(cscb.dcss, dcss, cscb.c_dcss);
      
      
      TRACE_FUNCTION("atPlusCSCB() calls bat_send() <=== as APPLICATION");
      bat_send(ati_bat_get_client(srcId), &cmd);
      return (AT_EXCT);
   }
#else /* FF_ATI_BAT */
   ret=sAT_PlusCSCB(srcId,mode,mids,dcss);
   if (ret EQ AT_FAIL)
   {
     cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
     return (ATI_FAIL);
   }
   return (map_aci_2_ati_rslt(ret));
#endif /* FF_ATI_BAT */
}

GLOBAL T_ATI_RSLT queatPlusCSCB (char *cl, UBYTE srcId)
{
#ifdef FF_ATI_BAT
  T_BAT_cmd_send     cmd;
  T_BAT_no_parameter dummy;
  
  cmd.ctrl_params              = BAT_CMD_QUE_PLUS_CSCB;
  dummy.bat_dummy              = 0xFF;
  cmd.params.ptr_que_plus_cscb = &dummy;

  TRACE_FUNCTION("queatPlusCSCB() calls bat_send() <=== as APPLICATION");
  bat_send(ati_bat_get_client(srcId), &cmd);

  return (AT_EXCT);

#else /* FF_ATI_BAT */
  T_ACI_CSCB_MOD  mode;
  char            mids_str[6*MAX_CBM_TYPES+1]={'\0'}; /* +1 for '\0' */  /* CHECK IF LONG ENOUGH !!*/
  char            dcss_str[4*MAX_CBM_TYPES+1]={'\0'};
  USHORT          mids[MAX_CBM_TYPES];
  UBYTE           dcss[MAX_CBM_TYPES];
  SHORT           pos=0,i=0;
  T_ACI_RETURN    ret = AT_FAIL;

  TRACE_FUNCTION("queatPlusCSCB()");

  ret = qAT_PlusCSCB(srcId, &mode,mids,dcss);
  if (ret EQ AT_CMPL)
  {
    /*
     *-----------------------------------------------------------
     * assemble the string for message identifiers
     *-----------------------------------------------------------
     */
    pos = i = 0;
    while( mids[i]   NEQ 0xFFFF   AND
           mids[i+1] NEQ 0xFFFF   AND
           i < MAX_CBM_TYPES - 1    )
    {
      if ( mids[i] EQ mids[i+1] )
        pos += sprintf ( mids_str + pos, "%d,", mids[i] );
      else
        pos += sprintf ( mids_str + pos, "%d-%d,", mids[i], mids[i+1] );  /* "65534-65535," max 12 chars */

      i += 2;
    }

    /*lint -e(661) -e(662) */   /* lint 7.5 has here some problems ... */
    if ( pos > 0 )              /* remove the last ',' */
    {
        mids_str[pos-1] = '\0';
    }

    /*
     *-----------------------------------------------------------
     * assemble the string for data coding schemes
     *-----------------------------------------------------------
     */
    pos = i = 0;
    while( dcss[i]   NEQ 0xFF    AND
           dcss[i+1] NEQ 0xFF    AND
           i < MAX_CBM_TYPES - 1     )
    {
      if ( dcss[i] EQ dcss[i+1] )
        pos += sprintf ( dcss_str + pos, "%d,", dcss[i] );
      else
        pos += sprintf ( dcss_str + pos, "%d-%d,", dcss[i], dcss[i+1] );

      i += 2;
    }

    /*lint -e(661) -e(662) */
    if ( pos > 0 )    /* remove the last ',' */
    {
      dcss_str[pos-1] = '\0';
    }

    sprintf(g_sa,"+CSCB: %d,\"%s\",\"%s\"",mode,mids_str,dcss_str);
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
#endif /* FF_ATI_BAT */
}

#ifdef FF_HOMEZONE
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPercentCBHZ      |
+--------------------------------------------------------------------+

  PURPOSE : %CBHZ command (set homezone activity)
*/

GLOBAL T_ATI_RSLT setatPercentCBHZ (char *cl, UBYTE srcId)
{
  T_ACI_CBHZ_MOD  mode    = CBHZ_MOD_NotPresent;
  T_ACI_CS        dcs     = CS_NotPresent;
  UBYTE           timeout = NOT_PRESENT_8BIT;
  T_ACI_RETURN    ret     = AT_FAIL;

  TRACE_FUNCTION("setatPercentCBHZ()");


  /*input functionality*/

  /*check first parameter */
  switch (*cl)
  {
    case '0':
    case '1':
      mode = *cl - 0x30;
      cl++;
      break;

    default:
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
  }

  /* check second parameter */
  if  ( *cl NEQ '\0' )
  {
    if ( *cl NEQ ',')
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
    cl++;

    if ( (*cl >= '0') AND (*cl <= '9') )
    {
      dcs = *cl -0x30;
      cl++;
    }

    /* check third parameter */
    if  ( *cl NEQ '\0' )
    {
      if ( *cl NEQ ',')
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
      cl++;

      cl = parse(cl,"d",&timeout);
      if  ( *cl NEQ '\0' )
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    }
  }

  /* parameters ok... process homezone request */
  ret = sAT_PercentCBHZ(srcId,mode,dcs,timeout);
  if (ret EQ AT_FAIL)
  {
    cmdCmeError(CME_ERR_Unknown);
    return (ATI_FAIL);
  }

  return (ATI_CMPL);
}


GLOBAL T_ATI_RSLT tesatPercentCBHZ (char *cl, UBYTE srcId)
{
  TRACE_FUNCTION("tesatPercentCBHZ()");

  sprintf( g_sa, "%s: (%d,%d),(%d-%d),(%d-%d)",
             "%CBHZ", CBHZ_MOD_NotActive, CBHZ_MOD_Active,
             CS_GsmDef, CS_Ascii, CBHZ_MIN_TIMEOUT, CBHZ_MAX_TIMEOUT);


  io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);

  return (ATI_CMPL);
}

GLOBAL T_ATI_RSLT queatPercentCBHZ (char *cl, UBYTE srcId)
{
  T_ACI_RETURN    ret;
  T_ACI_CBHZ_MOD  mode;
  T_ACI_CS        dcs;
  UBYTE           timeout;

  TRACE_FUNCTION("queatPercentCBSHZ()");

  ret = qAT_PercentCBHZ(srcId, &mode, &dcs, &timeout);

  if (ret EQ AT_FAIL)
  {
    cmdCmeError(CME_ERR_Unknown);
    return (ATI_FAIL);
  }

  /*
   *-----------------------------------------------------------
   * assemble the string for output
   *-----------------------------------------------------------
   */

  sprintf( g_sa, "%s: %d,%d,%d", "%CBHZ", mode, dcs, timeout);

  io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);

  return (ATI_CMPL);
}
#endif /* FF_HOMEZONE */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCSAS         |
+--------------------------------------------------------------------+

  PURPOSE : +CSAS command (Save SMS Profile)
*/

GLOBAL T_ATI_RSLT atPlusCSAS (char *cl, UBYTE srcId)
{
  SHORT        profile  = -1;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCSAS()");

  if ( *cl EQ '\0' )
  {
    profile = 1;
  }
  else
  {
    cl = parse ( cl, "r", &profile );
    if ( !cl )
    {
      cmdCmsError ( CMS_ERR_MemFail );
      return (ATI_FAIL);
    }
    profile++;
  }
#ifdef FF_ATI_BAT
  {
    T_BAT_cmd_send cmd;
    T_BAT_cmd_set_plus_csas csas;

    cmd.ctrl_params = BAT_CMD_SET_PLUS_CSAS;
    cmd.params.ptr_set_plus_csas = &csas;

    csas.profile = profile;

    TRACE_FUNCTION("atPlusCSAS() calls bat_send() <=== as APPLICATION");
    bat_send(ati_bat_get_client(srcId), &cmd);
    return (AT_EXCT);
  }
#else /* FF_ATI_BAT */
  switch (sAT_PlusCSAS (srcId, profile))
  {
    case AT_EXCT:
      src_params->curAtCmd    = AT_CMD_CSAS;
      return (ATI_EXCT);

    case AT_BUSY:
      return (ATI_BUSY);

    case AT_CMPL:
      return (ATI_CMPL_NO_OUTPUT);

    case AT_FAIL:           /* execution of command failed */
    default:
      cmdCmsError ( CMS_ERR_NotPresent);  /* use aciErrDesc */
      return (ATI_FAIL);
  }
#endif /* FF_ATI_BAT */
}

GLOBAL T_ATI_RSLT tesatPlusCSAS (char *cl, UBYTE srcId)
{
  SHORT        profile  = -1;

  if ((profile = cmhSMS_getPrfRge ()) < 1)
  {
    cmdCmsError ( CMS_ERR_MemFail );
    return (ATI_FAIL);
  }
  else
  {
    sprintf ( g_sa, "+CSAS: (0-%d)", profile - 1 );
    io_sendMessage ( srcId, g_sa, ATI_NORMAL_OUTPUT );
    return (ATI_CMPL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCRES         |
+--------------------------------------------------------------------+

  PURPOSE : +CRES command (Load SMS Profile)
*/

GLOBAL T_ATI_RSLT atPlusCRES (char *cl, UBYTE srcId)
{
  SHORT        profile  = -1;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCRES()");

  if ( *cl EQ '\0' )
  {
    profile = 1;
  }
  else
  {
    cl = parse ( cl, "r", &profile );

    if ( !cl )
    {
      cmdCmsError ( CMS_ERR_MemFail );
      return (ATI_FAIL);
    }
    profile++;
  }

  switch (sAT_PlusCRES (srcId, profile))
  {
    case AT_EXCT:
      src_params->curAtCmd    = AT_CMD_CRES;
      return (ATI_EXCT);

    case AT_BUSY:
      return (ATI_BUSY);

    case AT_CMPL:
      io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
      return (ATI_CMPL_NO_OUTPUT);

    case AT_FAIL:
    default:
      cmdCmsError ( CMS_ERR_NotPresent);  // use aciErrDesc
      return (ATI_FAIL);
  }
}

GLOBAL T_ATI_RSLT tesatPlusCRES (char *cl, UBYTE srcId)
{
  T_ACI_CRES    profile;
  T_ACI_RETURN  result;

  result = tAT_PlusCRES (srcId, &profile);
  switch (result)
  {
    case AT_FAIL:
      cmdCmsError ( CMS_ERR_MemFail );
      return (ATI_FAIL);

    case AT_CMPL:
      break;

    default:
      cmdCmsError ( CMS_ERR_MemFail );
      return (ATI_FAIL); 
  }

  sprintf ( g_sa, "+CRES: (%d-%d)", profile.min, profile.max);
  io_sendMessage ( srcId, g_sa, ATI_NORMAL_OUTPUT );
  return (ATI_CMPL);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGR         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGR command (Read Message)
*/

GLOBAL T_ATI_RSLT atPlusCMGR (char *cl, UBYTE srcId)
{
  char *me="+CMGR: ";
  T_ACI_RETURN ret = AT_FAIL;
  SHORT idx=-1;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCMGR()");

#ifndef WIN32
   cl = parse(cl,"r",&idx);
#else
   cl = parse(cl,"rd",&idx, &smsReadMode );
#endif
  if ( !cl OR idx > 255 OR idx < 0)
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return (ATI_FAIL);
  }

#ifdef FF_ATI_BAT

  {
    T_BAT_cmd_send cmd;
    T_BAT_cmd_set_plus_cmgr cmgr;

    cmd.ctrl_params=BAT_CMD_SET_PLUS_CMGR;
    cmd.params.ptr_set_plus_cmgr=&cmgr;

    cmgr.sms_index=(U16)idx;

    bat_send(ati_bat_get_client(srcId), &cmd);

    src_params->curAtCmd=AT_CMD_CMGR;
    return(ATI_EXCT);
  }

#else

#ifndef _CONC_TESTING_
#ifndef _SIMULATION_
  ret = sAT_PlusCMGR_Gl(srcId, (UBYTE)idx, SMS_READ_Normal, NULL);
#else
  ret = sAT_PlusCMGR_Gl(srcId, (UBYTE)idx, smsReadMode , NULL);
#endif
#else
#ifndef _SIMULATION_
  ret = sAT_PlusCMGR (srcId, (UBYTE)idx, SMS_READ_Normal);
#else
  ret = sAT_PlusCMGR (srcId, (UBYTE)idx, smsReadMode );
#endif
#endif
 if ( ret EQ AT_CMPL )
 {
   return (ATI_CMPL);
 }
 else if (ret EQ AT_EXCT)
 {
   src_params->curAtCmd    = AT_CMD_CMGR;
   return (ATI_EXCT);
 }
 else
 {
   cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
   return (ATI_FAIL);
 }

#endif /*FF_ATI_BAT*/
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGS         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGS command (SEND Message)
*/

GLOBAL T_ATI_RSLT tesatPlusCMGS (char *cl, UBYTE srcId)
{
  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  return ATI_CMPL_NO_OUTPUT;
}

GLOBAL T_ATI_RSLT queatPlusCMGS (char *cl, UBYTE srcId)
{
  cmdCmsError(CMS_ERR_OpNotAllowed); /* querying CMGS not specified in 07.05 */
  return (ATI_FAIL);
}


GLOBAL T_ATI_RSLT atPlusCMGS (char *cl, UBYTE srcId)
#if defined (SMS_PDU_SUPPORT)
{
  T_ACI_CMGF_MOD mode;
  
  TRACE_FUNCTION("atPlusCMGS()");
  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
  {
    /*
     * handle PDU mode
     */
    return (atPlusCMGSPdu (cl, srcId));
  }
  else
  {
    /*
     * handle Text mode
     */
    return (atPlusCMGSText (cl, srcId));
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_CMD              |
| STATE   : code                      ROUTINE : str_to_bcd           |
+--------------------------------------------------------------------+

  PURPOSE : A very specialised routine for converting a 2-byte string
            into one byte of BCD, intended to be used by atPlusCMGSText()
            only.
*/
LOCAL UBYTE str_to_bcd(
  CHAR *str)
{
  UBYTE bcd;
  UBYTE n;

  for (n=0;n<2;n++)
  {
    bcd>>=4;

    if ((str[n]<'0') || (str[n]>'9'))
      bcd+=0xF0;
    else
      bcd+=(str[n]-'0')<<4;
  }

  return(bcd);
}


LOCAL T_ATI_RSLT atPlusCMGSText(char *cl, UBYTE srcId)
#endif /* (SMS_PDU_SUPPORT) */
{
         T_ACI_VP_ABS  vpabs;
         SHORT         fo,
                       vprel,
                       pid,
                       dcs;
         CHAR*         me        = "+CMGS: ";
         T_ACI_RETURN  ret       = AT_FAIL;
         T_ACI_TOA     toda;
         T_ACI_TOA*    p_toda;
  GLOBAL SHORT         toda_val  = 0;
         T_ACI_SM_DATA msg;
         USHORT        lenMsg;
         CHAR*         da = daBuf;

  static T_ACI_TOA     tosca;
  static T_ACI_TOA    *p_tosca;
#ifdef _SIMULATION_
  CHAR         *sca =subBuf;
#endif /* _SIMULATION_ */
  SHORT         octet=0;
  static SHORT         isReply;

#ifdef _CONC_TESTING_
  T_SM_DATA_EXT msg_conc;
#endif

  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  if (src_params->text_mode EQ CMD_MODE)
  {
    TRACE_FUNCTION("atPlusCMGSText() CMD_MODE");
    memset (da, 0, MAX_SMS_NUM_LEN);
    /* input functionality */
    da[0]='\0';
#ifndef WIN32
    cl = parse (cl,"sr",(LONG)MAX_SMS_NUM_LEN,da,&toda_val);
    if ( !cl OR da[0] EQ '\0')
    {
      cmdCmsError (CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
#else
    *sca    ='\0';
    isReply = -1;
    cl = parse (cl,"srsrb",(LONG)MAX_SMS_NUM_LEN,da,&toda_val,
                           (LONG)MAX_SMS_NUM_LEN,sca,&octet,&isReply);
    if ( !cl OR da[0] EQ '\0')
    {
      cmdCmsError (CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
    if (octet EQ 0)
    {
      p_tosca=NULL;
    }
    else
    {
      tosca=toa_demerge(octet);
      if (tosca.ton < 0 OR tosca.npi < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    }
#endif
    if (toda_val)
    {
      toda=toa_demerge(toda_val);
      if (toda.ton < 0 OR toda.npi < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    }

    src_params->text_mode = TXT_MODE;
    return (ATI_EXCT);
  } /* end of if (src_params->text_mode EQ CMD_MODE) */
  else
  {
    TRACE_FUNCTION("atPlusCMGSText() TXT_MODE");

    src_params->text_mode = CMD_MODE;
    /* if the character sent is ESC, then abort command CLB 16.11.00 */
    if (*cl EQ 0x1B)
    {
      TRACE_EVENT("Send message command cancelled by user");

      return ATI_CMPL_NO_OUTPUT;
    }

    if ( toda_val EQ 0 )
    {
#ifndef _SIMULATION_
#endif /* ndef _SIMULATION_ */
      p_toda = NULL;
    }
    else
    {
      toda   = toa_demerge ( toda_val );
      p_toda = &toda;
    }

    qAT_PlusCSMP  ( srcId, &fo, &vprel, &vpabs, NULL, &pid, &dcs );

    srcId_cb = srcId;
    if (ati_user_output_cfg[srcId].cscsChset EQ CSCS_CHSET_Ucs2 )
    {
      utl_smDtaFromTe ((UBYTE*)cl,
                       (USHORT)MINIMUM(strlen(cl),sizeof(msg.data)*4),
                       msg.data,
                       &lenMsg,
                       (UBYTE)fo,
                       (UBYTE)dcs );
    }
    else if (ati_user_output_cfg[srcId].cscsChset EQ CSCS_CHSET_Hex )
    {
      utl_smDtaFromTe ((UBYTE*)cl,
                       (USHORT)MINIMUM(strlen(cl),sizeof(msg.data)*2),
                       msg.data,
                       &lenMsg,
                       (UBYTE)fo,
                       (UBYTE)dcs );
    }
    else
    {
      utl_smDtaFromTe ((UBYTE*)cl,
                       (USHORT)MINIMUM(strlen(cl),sizeof(msg.data)),
                       msg.data,
                       &lenMsg,
                       (UBYTE)fo,
                       (UBYTE)dcs );
    }
    msg.len = (UBYTE)lenMsg;

#if 0  /* #ifdef FF_ATI_BAT */

    {
      T_BAT_cmd_send cmd;
      T_BAT_cmd_set_plus_cmgs cmgs;
      UBYTE len;
      UBYTE i;
      U8 *p;
      CHAR clean_da[MAX_SMS_NUM_LEN+1];

      cmd.ctrl_params=BAT_CMD_SET_PLUS_CMGS;
      cmd.params.ptr_set_plus_cmgs=&cmgs;

      /*
      *   The BAT uses only PDU format, so we must convert the data.
      *   This code is sufficient to allow tests ACIPHB75-78 to pass - at
      *   the time of writing, these are the only tests we have available
      *   for +CMGS. When it comes to other tests, some enhancements will
      *   certainly be required.
      */

      p=cmgs.pdu;

      /*
      *   SCA - Service Centre Address
      */
      len=(UBYTE)strlen(sca);

      if (len==0)
      {
        /*
        *   No service centre address indicated. If we use a zero length
        *   to indicate the default SCA, we will have problems later in
        *   DecodeRPAddress(). The version below seems to be fine.
        */
        *p++=0x01;
        *p++=0x80;        
      }
      else
      {
        /*
        *   The length is the number of octets in the parameter, not
        *   the number of address digits.
        */
        *p++=(U8)((len+1)/2)+1;

        /*
        *   Type of number.
        */
        *p++=(tosca.ton==TON_International) ? 0x91:0x81;

        /*
        *   Convert the address from string format to BCD format.
        */
        for (i=0;i<len;i+=2)
          *p++=str_to_bcd(&sca[i]);
      }

      /*
      *   PDU type
      */
      *p++=0x01;

      /*
      *   MR - Message reference
      */
      *p++=0x00;

      /*
      *   DA - Destination Address
      *   The length is the number of address digits, not the number of
      *   octets in the parameter.
      */

      /*
      *   First, make a clean version of the string, getting rid of
      *   any unwanted characters.
      */
      {
        SHORT cctr,dctr;
        CHAR c;

        memset(clean_da,0,sizeof(clean_da));

        cctr=0;

        for (dctr=0;dctr<MAX_SMS_NUM_LEN;dctr++)
        {
          c=da[dctr];

          if ((c>='0') && (c<='9'))
            clean_da[cctr++]=c;
        }
      }
      
      len=(UBYTE)strlen(clean_da);

      *p++=(U8)len;

      /*
      *   Type of number.
      */
      *p++=(toda.ton==TON_International) ? 0x91:0x81;

      /*
      *   Convert the address from string format to BCD format.
      */
      for (i=0;i<len;i+=2)
        *p++=str_to_bcd(&clean_da[i]);

      /*
      *   PID - Protocol Identifier
      */
      *p++=(U8)pid;

      /*
      *   DCS - Data Coding Scheme
      */
      *p++=(U8)dcs;

      /*
      *   VP - Validity Period
      *   Not included here.
      */

      /*
      *   UDL - User Data Length
      */
      *p++=0x00;

      /*
      *   UD - User Data
      *   Not included here.
      */
      
      /*
      *   Length calculated by seeing how far the pointer has come
      *   from where it started.
      */
      cmgs.c_pdu=(U8)(p-cmgs.pdu);

      bat_send(ati_bat_get_client(srcId), &cmd);
    }

#else

#ifndef _CONC_TESTING_
#ifndef _SIMULATION_
    ret = sAT_PlusCMGS_Gl(srcId, da, p_toda, &msg, NULL, NULL, NULL, -1, NULL, NULL);
#else
    ret = sAT_PlusCMGS_Gl(srcId, da, p_toda, &msg, NULL, sca, p_tosca, isReply, NULL, NULL);
#endif
#else
    ACI_MALLOC(msg_conc.data, msg.len);
    memcpy ( msg_conc.data, msg.data, msg.len);
    msg_conc.len = msg.len;
#ifndef _SIMULATION_
    ret = sAT_PlusCMGS (srcId, da, p_toda, &msg_conc, NULL, NULL, -1);
#else
    ret = sAT_PlusCMGS (srcId, da, p_toda, &msg_conc, sca, p_tosca, isReply);
#endif
#endif

    if ( ret NEQ AT_EXCT )
    {
      cmdCmsError (CMS_ERR_NotPresent);  // use aciErrDesc
      return (ATI_FAIL);
    }
    /*
     *  rCI_OK will emitting +CMGS: <mr>[,<scts>]
     */
#endif

    return (ATI_EXCT);
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMSS         |
+--------------------------------------------------------------------+

  PURPOSE : +CMSS command (send message from storage)
*/

GLOBAL T_ATI_RSLT atPlusCMSS (char *cl, UBYTE srcId)
{
  CHAR         *me="+CMSS: ",
               *p_da;
  T_ACI_RETURN  ret = AT_FAIL;
  T_ACI_TOA     toda;
  T_ACI_TOA    *p_toda;
  SHORT         index=-1,
                toda_val=0;
  CHAR          da[MAX_SMS_NUM_LEN];
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCMSS()");

  p_toda=&toda;
  p_da=da;
  /*input functionality*/
  da[0]='\0';
  cl = parse(cl,"rsr",&index,(LONG)MAX_SMS_NUM_LEN,da,&toda_val);
  if ( !cl OR toda_val > 0xC9 OR index > 255 OR index < 0)
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return (ATI_FAIL);
  }
  p_toda=&toda;
  if(toda_val EQ 0)
  {
    p_toda=NULL;
  }
  else
  {
    toda=toa_demerge(toda_val);
    if (toda.ton < 0 OR toda.npi < 0)
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
  }
  if(!da[0])
    p_da=NULL;

#ifdef _CONC_TESTING_
  ret = sAT_PlusCMSS(srcId,(UBYTE)index,p_da,p_toda);
#else
  ret = sAT_PlusCMSS_Gl(srcId, (UBYTE)index, p_da, p_toda, NULL, NULL);
#endif
  if (ret EQ AT_EXCT)
  {
    src_params->curAtCmd    = AT_CMD_CMSS;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCNMA         |
+--------------------------------------------------------------------+

  PURPOSE : +CNMA command (new message acknowledgement)
*/
GLOBAL T_ATI_RSLT queatPlusCNMA (char *cl, UBYTE srcId)
{
  cmdCmsError(CMS_ERR_OpNotAllowed); /* querying CNMA not specified in 07.05 */
  return (ATI_FAIL);
}

GLOBAL T_ATI_RSLT tesatPlusCNMA (char *cl, UBYTE srcId)
{
  T_ACI_CMGF_MOD mode;

  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
  {
    /*
     * handle PDU mode: response is +CNMA: (list of supported <n>s)
     */
    io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
    return ATI_CMPL_NO_OUTPUT;
  }
  else
  {
    /*
     * handle Text mode: there is no response
     */
    io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
    return ATI_CMPL_NO_OUTPUT;
  }
}


GLOBAL T_ATI_RSLT atPlusCNMA (char *cl, UBYTE srcId)
#if defined (SMS_PDU_SUPPORT)
{
  T_ACI_CMGF_MOD         mode;
  T_CNMI_BUFFER_ELEMENT *psMsgInCnmiBuffer = NULL;

  if(srcId NEQ smsShrdPrm.smsSrcId)
  {
    cmdCmsError(CMS_ERR_NoCnmaAckExpect);
    return ( ATI_FAIL );
  }
  
  if( waitForCnmaFromBuffer_SrcId NEQ CMD_SRC_NONE )
  { /* incomming +CNMA acknowledges an +CMT from CNMI buffer 
       -> acknowledge has been sent to SMS entity */
    TIMERSTOP( ACI_CNMA_TIMER_HANDLE );
    cmd_clearFirstCnmiMessage(); /* The first message in CNMI buffer is cleared */
    waitForCnmaFromBuffer_SrcId = CMD_SRC_NONE;
    /* look for more messages in CNMI buffer for this srcId */
    cmd_flushCnmiBufOneByOne();
    return(ATI_CMPL);
  }
  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
    /*
     * handle PDU mode
     */
    return atPlusCNMAPdu (cl,srcId);
  else
    /*
     * handle Text mode
     */
    return atPlusCNMAText (cl,srcId);
}

LOCAL T_ATI_RSLT atPlusCNMAText (char *cl, UBYTE srcId)
#endif /* (SMS_PDU_SUPPORT) */
{
  TRACE_FUNCTION("atPlusCNMAText()");

  switch (*cl)
  {
    case(0x0):
      switch (sAT_PlusCNMA(srcId))
      {
        case( AT_CMPL ):
          cmdAtError ( atOk );
          return (ATI_CMPL);

        default:
          cmdCmsError (CMS_ERR_NotPresent);  // use aciErrDesc
          return (ATI_FAIL);
      }
    default:
      cmdCmeError(CME_ERR_Unknown);
      return (ATI_FAIL);
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGW         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGW command (Write message to memory)
*/

GLOBAL T_ATI_RSLT tesatPlusCMGW (char *cl, UBYTE srcId)
{
  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  return ATI_CMPL_NO_OUTPUT;
}

GLOBAL T_ATI_RSLT queatPlusCMGW (char *cl, UBYTE srcId)
{
  cmdCmsError(CMS_ERR_OpNotAllowed); /* querying CMGW not specified in 07.05 */
  return (ATI_FAIL);
}


GLOBAL T_ATI_RSLT atPlusCMGW (char *cl, UBYTE srcId)
#if defined (SMS_PDU_SUPPORT)
{
  T_ACI_CMGF_MOD mode;

  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
    /*
     * handle PDU mode
     */
    return atPlusCMGWPdu (cl, srcId);
  else
    /*
     * handle Text mode
     */
    return atPlusCMGWText (cl, srcId);
}
LOCAL T_ATI_RSLT atPlusCMGWText(char *cl, UBYTE srcId)
#endif /* (SMS_PDU_SUPPORT) */
{
  T_ACI_VP_ABS  vpabs;
  SHORT         fo,
                vprel,
                pid,
                dcs;
  CHAR*         me = "+CMGW: ";
  T_ACI_RETURN  ret;
  T_ACI_TOA     toa;
  T_ACI_TOA*    p_toa;
  CHAR          txtStat[15] = {0x00};
  USHORT        i;
  T_ACI_SM_DATA msg;
  USHORT        lenMsg;
  static T_ACI_SMS_STAT stat;

  static T_ACI_TOA     tosca;
  static T_ACI_TOA    *p_tosca;
#ifdef _SIMULATION_
  CHAR         *sca =subBuf;
#endif /* ndef _SIMULATION_ */
  SHORT         octet=0;
  static SHORT         isReply;
#ifdef _CONC_TESTING_
  T_SM_DATA_EXT msg_conc;
#endif
  CHAR         *da = daBuf;

  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCMGWText()");

  p_toa=&toa;
  toda_val=0;

  if (src_params->text_mode EQ CMD_MODE)
  {
    memset(da, 0, MAX_SMS_NUM_LEN);
    stat = SMS_STAT_NotPresent;
    /*input functionality*/
    *da='\0';                      /*sets global destination address to empty string*/
#ifndef WIN32
    cl = parse(cl,"srs",(LONG)MAX_SMS_NUM_LEN,
                        da,
                        &toda_val,
                        (LONG)sizeof(txtStat),
                        txtStat);
    if ( !cl )
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
#else
    *sca='\0';
    isReply = -1;
    cl = parse(cl,"srssrb",(LONG)MAX_SMS_NUM_LEN,
                       da,
                       &toda_val,
                       (LONG)sizeof(txtStat),
                       txtStat,
                       (LONG)MAX_SMS_NUM_LEN,sca,&octet,&isReply);
    if ( !cl )
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
    if(octet EQ 0)
      p_tosca = NULL;
    else
    {
      tosca=toa_demerge(octet);
      if (tosca.ton < 0 OR tosca.npi < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return 0;
      }
      p_tosca = &tosca;
    }
#endif
    if (toda_val)
    {
      toa = toa_demerge(toda_val);
      if (toa.ton < 0 OR toa.npi < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    }
    i = 0;
    while ( sms_stat[i].name                     NEQ NULL AND
            strcmp ( sms_stat[i].name, txtStat ) NEQ 0        )
    {
      i++;
    }
    stat = sms_stat[i].stat;

    src_params->text_mode = TXT_MODE;
    return (ATI_EXCT);
  } /* end of if (src_params->text_mode EQ CMD_MODE) */
  else
  {
    src_params->text_mode = CMD_MODE;
    /* if the character sent is ESC, then abort command CLB 16.11.00 */
    if (*cl EQ 0x1B)
    {
      TRACE_EVENT("Send message command cancelled by user");

      return ATI_CMPL_NO_OUTPUT;
    }

    if ( toda_val EQ 0 )
      p_toa = NULL;
    else
    {
      toa   = toa_demerge ( toda_val );
      p_toa = &toa;
    }

    qAT_PlusCSMP  ( srcId, &fo, &vprel, &vpabs, NULL, &pid, &dcs );

    srcId_cb = srcId;
    utl_smDtaFromTe ( (UBYTE*)cl,
                      (USHORT)strlen(cl),
                      (UBYTE*)msg.data,
                      &lenMsg,
                      (UBYTE)fo,
                      (UBYTE)dcs );

    msg.len = (UBYTE)lenMsg;

#ifndef _CONC_TESTING_
#ifndef _SIMULATION_
    ret = sAT_PlusCMGW_Gl( srcId,
                           CMGW_IDX_FREE_ENTRY,
                           da, p_toa, stat, NOT_PRESENT_8BIT,
                           &msg, NULL, NULL, NULL, -1,
                           NULL, NULL);
#else
    ret = sAT_PlusCMGW_Gl( srcId,
                           CMGW_IDX_FREE_ENTRY,
                           da, p_toa, stat, NOT_PRESENT_8BIT,
                           &msg, NULL, sca, p_tosca, isReply,
                           NULL, NULL);
#endif
#else
    ACI_MALLOC(msg_conc.data, msg.len);
    memcpy ( msg_conc.data, msg.data, msg.len);
    msg_conc.len = msg.len;
#ifndef _SIMULATION_
    ret = sAT_PlusCMGW ( srcId,
                         CMGW_IDX_FREE_ENTRY,
                         da, p_toa, stat, NOT_PRESENT_8BIT,
                         &msg_conc, NULL, NULL, -1 );
#else
    ret = sAT_PlusCMGW ( srcId,
                         CMGW_IDX_FREE_ENTRY,
                         da, p_toa, stat, NOT_PRESENT_8BIT,
                         &msg_conc, sca, p_tosca, isReply );
#endif
#endif

    if ( ret NEQ AT_EXCT )
    {
      cmdCmsError (CMS_ERR_NotPresent);  // use aciErrDesc
      return (ATI_FAIL);
    }
    /*
     *  rCI_OK will emitting +CMGW: <index>
     */
    return (ATI_EXCT);
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGD         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGD command (delete message from storage)
*/

GLOBAL T_ATI_RSLT setatPlusCMGD (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = ATI_FAIL;
  SHORT index=-1;
  UBYTE status = CMGD_DEL_INDEX;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  src_params->curAtCmd = AT_CMD_CMGD;

  /*input functionality*/
  if(!cl OR !*cl)
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return ret;
  }

  cl=parse(cl,"rr",&index,&status);
  if ( !cl OR (index > 255) OR (index < 0) OR
    ((status < CMGD_DEL_INDEX) OR (status > CMGD_DEL_ALL)))
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return ret;
  }

#ifdef FF_ATI_BAT
  {
  T_BAT_cmd_send cmd;
  T_BAT_cmd_set_plus_cmgd my_bat_set_plus_cmgd;

  TRACE_FUNCTION("setatPlusCMGD() calls bat_send() <=== as APPLICATION");

  memset(&my_bat_set_plus_cmgd, 0, sizeof(my_bat_set_plus_cmgd));
  cmd.ctrl_params = BAT_CMD_SET_PLUS_CMGD;
  cmd.params.ptr_set_plus_cmgd = &my_bat_set_plus_cmgd;

  my_bat_set_plus_cmgd.index = (U8)index;
  my_bat_set_plus_cmgd.status = status;

  bat_send(ati_bat_get_client(srcId), &cmd);

  return ATI_EXCT; /* executing, because response is passed by callback function */
  }
#else /* OLD FUNCTION BODY */

  TRACE_FUNCTION("setatPlusCMGD()");
  /*-----------------------------------------------------------------------
   *  Del flag is greater than zero, set index as Zero so that SMS module 
   *  starts searching for records satisfying the status from first record
   *-----------------------------------------------------------------------
   */
  if ( status > CMGD_DEL_INDEX )
  {
    index = 0;
  }
#ifdef _CONC_TESTING_
  ret = sAT_PlusCMGD(srcId,(UBYTE)index, status);
#else
  ret = sAT_PlusCMGD_Gl(srcId, (UBYTE)index, status, NULL, NULL);
#endif

  if (ret EQ AT_EXCT)
  {
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }

#endif /* no FF_ATI_BAT*/
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGC         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGC command (Send SMS command)
*/

GLOBAL T_ATI_RSLT tesatPlusCMGC (char *cl, UBYTE srcId)
{
  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  return ATI_CMPL_NO_OUTPUT;
}

GLOBAL T_ATI_RSLT queatPlusCMGC (char *cl, UBYTE srcId)
{
  cmdCmsError(CMS_ERR_OpNotAllowed); /* querying CMGC not specified in 07.05 */
  return (ATI_FAIL);
}

GLOBAL T_ATI_RSLT atPlusCMGC (char *cl, UBYTE srcId)
#if defined (SMS_PDU_SUPPORT)
{
  T_ACI_CMGF_MOD mode;

  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
    /*
     * handle PDU mode
     */
    return atPlusCMGCPdu (cl, srcId);
  else
    /*
     * handle Text mode
     */
    return atPlusCMGCText (cl, srcId);
}

LOCAL T_ATI_RSLT atPlusCMGCText(char *cl, UBYTE srcId)
#endif /* (SMS_PDU_SUPPORT) */
{
/*  char           buf[80]; */
  T_ACI_RETURN   ret = AT_FAIL;
  T_ACI_TOA      toa;
  T_ACI_TOA*     p_toa;
  T_ACI_CMD_DATA cmd;
  USHORT         lenCmd;
  CHAR*          da = daBuf;

  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("atPlusCMGCText()");
  p_toa=&toa;
  if (src_params->text_mode EQ CMD_MODE)
  {
    memset(da, 0, MAX_SMS_NUM_LEN);
    fo=-1;
    ct=-1;
    pid=-1;
    mn=-1;
    toda_val=0;
    /*input functionality*/
    da[0]='\0';
    cl = parse(cl,"rrrrsr",&fo,&ct,&pid,&mn,(LONG)MAX_SMS_NUM_LEN,da,&toda_val);

    if ( !cl OR  fo > 255 OR ct > 255 OR
          pid > 255 OR mn > 255 OR toda_val > 0xC9 OR da[0] EQ '\0')
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    if(toda_val)
    {
      toa = toa_demerge(toda_val);
      if (toa.ton < 0 OR toa.npi < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
    }

    src_params->text_mode = TXT_MODE;
    return (ATI_EXCT);
  } /* end of if (src_params->text_mode EQ CMD_MODE) */
  else
  {
    src_params->text_mode = CMD_MODE;
    p_toa=&toa;
    if(toda_val EQ 0)
    {
      p_toa = NULL;
    }
    else
    {
      toa = toa_demerge(toda_val);
    }
    if (!(check_str(cl,"0123456789ABCDEF")))
    {
      cmdCmsError(CMS_ERR_OpNotAllowed);
      return (ATI_FAIL);
    }
    utl_hexToGsm ( (UBYTE*)cl,
                   (USHORT)strlen(cl),
                   (UBYTE*)cmd.data,
                   &lenCmd,
                   GSM_ALPHA_Def,
                   CSCS_ALPHA_8_Bit);
    cmd.len = (UBYTE)lenCmd;

#ifndef _CONC_TESTING_
    ret = sAT_PlusCMGC_Gl (srcId,fo,ct,pid,mn,da,p_toa,&cmd,NULL);
#else
    ret= sAT_PlusCMGC(srcId,fo,ct,pid,mn,da,p_toa,&cmd);
#endif

    if ( ret NEQ AT_EXCT )
    {
      cmdCmsError (CMS_ERR_NotPresent);  // use aciErrDesc
      return (ATI_FAIL);
    }
    /*
     *  rCI_OK will emitting +CMGC: <mr>[,<scts>]
     */
    return (ATI_EXCT);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCMGL         |
+--------------------------------------------------------------------+

  PURPOSE : +CMGL command (List Messages)
*/

GLOBAL T_ATI_RSLT queatPlusCMGL (char *cl, UBYTE srcId)
{
  TRACE_FUNCTION("queatPlusCMGL()");
    cmdCmsError ( CMS_ERR_OpNotAllowed );
    return (ATI_FAIL);
}

GLOBAL T_ATI_RSLT tesatPlusCMGL (char *cl, UBYTE srcId)
{
#ifdef SMS_PDU_SUPPORT
  T_ACI_CMGF_MOD mode;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("tesatPlusCMGL()");
  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
  /*
   * handle PDU mode
   */
    io_sendMessage(srcId, "+CMGL: (0,1,2,3,4)", ATI_NORMAL_OUTPUT);
  else
  /*
   * handle Text mode
   */
#endif
   io_sendMessage(srcId, "+CMGL: (\"REC UNREAD\",\"REC READ\",\"STO UNSENT\",\"STO SENT\",\"ALL\")", ATI_NORMAL_OUTPUT);

  return (ATI_CMPL);
}

GLOBAL T_ATI_RSLT atPlusCMGL (char *cl, UBYTE srcId)
{
#ifndef FF_ATI_BAT
  T_ACI_RETURN   ret;
#endif

  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

#ifdef SMS_PDU_SUPPORT
  T_ACI_CMGF_MOD mode;
#endif
  CHAR           txtStat[15];
  USHORT         i;

  TRACE_FUNCTION("atPlusCMGL()");


  if (*cl EQ '\0')
  {
    cmglStat = SMS_STAT_NotPresent;
#ifdef WIN32
    smsReadMode  = SMS_READ_Normal;
#endif
  }
  else
  {
    /*
     * Request of a list of stored SMS messages
     * Parameter stat is optional
     */
#ifdef SMS_PDU_SUPPORT
    /*
     * request current mode
     */
    qAT_PlusCMGF(srcId, &mode);
    if (mode EQ 0)
    {
#ifndef WIN32
      /*
       * On the target is the definition according GSM 7.05 CMGL=[stat]
       */
      cmglStat = SMS_STAT_All;
      cl = parse (cl, "d", &cmglStat);
      if ( !cl OR cmglStat < SMS_STAT_RecUnread OR cmglStat > SMS_STAT_All)
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return NULL;
      }
#else
      /*
       * Under Windows the definition is CMGL=[stat],[preview]
       * to test the capabilities of the functional interface
       */
      cl = parse (cl, "dd", &cmglStat, &smsReadMode );
      if ( !cl OR ((cmglStat < SMS_STAT_RecUnread OR cmglStat > SMS_STAT_All)
           AND smsReadMode  EQ SMS_READ_NotPresent))
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
#endif
    }
    else
#endif
    {
#ifndef WIN32
      /*
       * On the target is the definition according GSM 7.05 CMGL=[stat]
       */
      cl = parse (cl, "s", (LONG)sizeof(txtStat), txtStat);
      if ( !cl OR txtStat[0] EQ '\0')
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
#else
      /*
       * Under Windows the definition is CMGL=[stat],[preview]
       * to test the capabilities of the functional interface
       */
      cl = parse (cl, "sd", (LONG)sizeof(txtStat), txtStat, &smsReadMode );
      if ( !cl OR (txtStat[0] EQ '\0' AND smsReadMode  EQ SMS_READ_NotPresent))
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
      if (txtStat[0] EQ '\0')
        strcpy (txtStat, sms_stat[4].name); /* ALL as default */
#endif
      i = 0;
      while ( sms_stat[i].name NEQ NULL            AND
              strcmp ( sms_stat[i].name, txtStat ) NEQ 0 )
        i++;

      if ( sms_stat[i].name EQ NULL )
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }

      cmglStat = sms_stat[i].stat;
    }
  }

#ifdef FF_ATI_BAT

  {
    T_BAT_cmd_send cmd;
    T_BAT_cmd_set_plus_cmgl cmgl;

    cmd.ctrl_params=BAT_CMD_SET_PLUS_CMGL;
    cmd.params.ptr_set_plus_cmgl=&cmgl;

    /*
    *   T_ACI_SMS_STAT and T_BAT_plus_cmgl_stat are not quite
    *   identical - the ACI version has the extra value
    *   SMS_STAT_Invalid.
    */
    if (cmglStat EQ SMS_STAT_Invalid)
      cmgl.stat=BAT_CMGL_STAT_NOT_PRESENT;
    else
      cmgl.stat=(T_BAT_plus_cmgl_stat)cmglStat;

    bat_send(ati_bat_get_client(srcId),&cmd);

    src_params->curAtCmd=AT_CMD_CMGL;
    return(ATI_EXCT);
  }

#else

  /*
   * Request the first five SMS messages
   */
#ifndef WIN32
  ret = sAT_PlusCMGL ( srcId, cmglStat, 0, SMS_READ_Normal );
#else
  ret = sAT_PlusCMGL ( srcId, cmglStat, 0, smsReadMode  );
#endif

  if ( ret EQ AT_EXCT )
  {
    src_params->curAtCmd = AT_CMD_CMGL;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError ( CMS_ERR_NotPresent );  // use aciErrDesc
    return (ATI_FAIL);
  }

#endif /*FF_ATI_BAT*/
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPlusCNMI         |
+--------------------------------------------------------------------+

  PURPOSE : +CNMI command (new messgae indication settings )
*/

GLOBAL T_ATI_RSLT  atPlusCNMI (char *cl, UBYTE srcId)
{
  T_ACI_CNMI_MT  mt   = CNMI_MT_NotPresent;
  T_ACI_CNMI_BM  bm   = CNMI_BM_NotPresent;
  T_ACI_CNMI_DS  ds   = CNMI_DS_NotPresent;
  T_ACI_CNMI_MOD mode = CNMI_MOD_NotPresent;
  T_ACI_CNMI_BFR bfr  = CNMI_BFR_NotPresent;
  T_ACI_RETURN   ret  = AT_FAIL;

  TRACE_FUNCTION("atPlusCNMI()");

  /* input functionality */
  cl = parse ( cl, "ddddd", &mode, &mt, &bm, &ds, &bfr );

  if ( !cl                              OR
        mode <  CNMI_MOD_NotPresent     OR
        mode >  CNMI_MOD_BufferAndFlush OR
        bfr  <  CNMI_BFR_NotPresent     OR
        bfr  >  CNMI_BFR_Clear          OR
      ( bfr  EQ CNMI_BFR_Flush          AND
        strlen ( cl ) > 0                   ) )
  {
      io_sendConfirm ( srcId, cmdCmsError ( CMS_ERR_OpNotAllowed ), ATI_ERROR_OUTPUT );
      cmdErrStr = NULL;
      return ATI_FAIL_NO_OUTPUT;
  }

  ret = sAT_PlusCNMI ( srcId, mt, bm, ds );
  if ( (ret EQ AT_FAIL) OR (ret EQ AT_BUSY) )
  {
    io_sendConfirm ( srcId, cmdCmsError ( CMS_ERR_NotPresent ), ATI_ERROR_OUTPUT );
    cmdErrStr = NULL;
    return ATI_FAIL_NO_OUTPUT;
  }

  /* 
   *----------------------Issue 25033--------------------------------
   * The source ID issuing the CNMI command is stored and henceforth 
   * all the unsolicited SMS indications are sent to this source 
   *-----------------------------------------------------------------
   */
  if(srcId NEQ CMD_SRC_LCL)
	  smsShrdPrm.smsSrcId = srcId;

  if ( bfr  NEQ CNMI_BFR_NotPresent )
    at.CNMI_bfr  = ( UBYTE ) bfr;

  if ( mode NEQ CNMI_MOD_NotPresent )
    at.CNMI_mode = ( UBYTE ) mode;

  if (mode EQ CNMI_MOD_DiscardOrForward OR  /* 07.05:3.4.1: check for <mode> 1...3  */
      mode EQ CNMI_MOD_BufferAndFlush)
  {
    if ( at.CNMI_bfr EQ CNMI_BFR_Flush )
    {
      io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
      cmdErrStr = NULL;

      if( smsShrdPrm.CSMSservice NEQ CSMS_SERV_GsmPh2Plus )
      {
        cmd_flushCnmiBuf();
      }
      else
      {
        cmd_flushCnmiBufOneByOne();
      }
      return ATI_CMPL_NO_OUTPUT;
    }
    else
    {
      cmd_clearCnmiBuf ();
    }
  }

  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  cmdErrStr = NULL;

  return ATI_CMPL_NO_OUTPUT;
}

GLOBAL T_ATI_RSLT  tesatPlusCNMI (char *cl, UBYTE srcId)
{
  /* query parameter ranges */
  io_sendMessage ( srcId, "+CNMI: (0-2),(0-3),(0,2),(0,1),(0,1)", ATI_NORMAL_OUTPUT );
  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  cmdErrStr = NULL;

  return ATI_CMPL_NO_OUTPUT;
}

GLOBAL T_ATI_RSLT  queatPlusCNMI (char *cl, UBYTE srcId)
{
  char*          me   = "+CNMI: ";
  T_ACI_CNMI_MT  mt   = CNMI_MT_NotPresent;
  T_ACI_CNMI_BM  bm   = CNMI_BM_NotPresent;
  T_ACI_CNMI_DS  ds   = CNMI_DS_NotPresent;
  T_ACI_CNMI_MOD mode = CNMI_MOD_NotPresent;
  T_ACI_CNMI_BFR bfr  = CNMI_BFR_NotPresent;

  if ( qAT_PlusCNMI ( srcId, &mt, &bm, &ds ) EQ AT_CMPL )
  {
    sprintf ( g_sa,"%s%d,%d,%d,%d,%d", me, at.CNMI_mode,
                                     mt, bm, ds, at.CNMI_bfr );
    io_sendMessage ( srcId, g_sa, ATI_NORMAL_OUTPUT );
  }
  else
  {
    io_sendConfirm ( srcId, cmdCmsError ( CMS_ERR_NotPresent ), ATI_ERROR_OUTPUT );
    cmdErrStr = NULL;
    return ATI_FAIL_NO_OUTPUT;
  }

  io_sendConfirm ( srcId, cmdAtError ( atOk ), ATI_NORMAL_OUTPUT );
  cmdErrStr = NULL;
  return ATI_CMPL_NO_OUTPUT;
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : setatPercentCPRSM  |
+--------------------------------------------------------------------+

  PURPOSE : %CPRSM set command 
            set the receiving of SMS to 
            1 -- Pause    or  
            2 -- Resume
           
*/

GLOBAL T_ATI_RSLT setatPercentCPRSM (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret     = AT_FAIL;
  T_ACI_CPRSM_MOD mode = CPRSM_MOD_NotPresent;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  src_params->curAtCmd = AT_CMD_CPRSM;
  
  /* parse command */
  cl = parse (cl, "d", &mode);

  /* check whether parsing has been successful */ 
  if (!cl)
  {
    /* undefined value for mode */
    TRACE_EVENT("+CPRSM ERROR: parse cmd failed!");
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return ATI_FAIL;    
  }

#ifdef FF_ATI_BAT
  {
  T_BAT_cmd_send cmd;
  T_BAT_cmd_set_percent_cprsm my_bat_set_percent_cprsm;

  TRACE_FUNCTION("setatPercentCPRSM() calls bat_send() <=== as APPLICATION");

  memset(&my_bat_set_percent_cprsm, 0, sizeof(my_bat_set_percent_cprsm));
  cmd.ctrl_params = BAT_CMD_SET_PERCENT_CPRSM;
  cmd.params.ptr_set_percent_cprsm = &my_bat_set_percent_cprsm;

  my_bat_set_percent_cprsm.mode = mode;

  bat_send(ati_bat_get_client(srcId), &cmd);

  return ATI_EXCT; /* executing, because response is passed by callback function */
  }
#else /* OLD FUNCTION BODY */

  TRACE_FUNCTION("setatPercentCPRSM()");

  switch (mode) /* check which mode has to be set and set it */ 
  {
    case(CPRSM_MOD_Resume):
    case(CPRSM_MOD_Pause):
    {     
      /* AT interface function called */
      ret = sAT_PercentCPRSM(srcId, mode);
      break;
    }
    default:
      /* undefined value for mode */
      TRACE_EVENT_P1("+CPRSM ERROR: undefined value for mode: %d", mode);
      cmdCmsError(CMS_ERR_OpNotSup);
      return ATI_FAIL;
  }

  /* check result */
  switch (ret)
  {
    case (AT_CMPL):
      /* operation successfully completed */
      break;
    case (AT_EXCT):
      /* operation still executing */
      src_params->curAtCmd = AT_CMD_COPS;
      break;
    default:
      /* unknown result type */
      TRACE_EVENT_P1("+CPRSM ERROR: undefined result: %d", ret);
      cmdCmsError(CMS_ERR_UnknownErr);  /*Command failed*/
      return ATI_FAIL;
  }

  /* map error to ATI type and return */ 
  return (map_aci_2_ati_rslt(ret)); 

#endif /* no FF_ATI_BAT*/
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : queatPercentCPRSM  |
+--------------------------------------------------------------------+

  PURPOSE : %CPRSM query command 
            request the current state of the pause flag for receiving SMS
*/

GLOBAL T_ATI_RSLT queatPercentCPRSM (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = ATI_FAIL;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("queatPercentCPRSM()");

  ret = qAT_PercentCPRSM( srcId );


  if (ret EQ AT_EXCT)
  {
    src_params->curAtCmd = AT_CMD_CPRSM;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
    return (ATI_FAIL);
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : cmd_clearCnmiBuf   |
+--------------------------------------------------------------------+

  PURPOSE : This function clears the buffer for storing new message
            indications while the serial interface is reserved for
            data transmission.
*/
GLOBAL void cmd_clearCnmiBuf (void)
{
  UBYTE i;

  for ( i = 0; i < CNMI_BUF_SIZE; i++ )
    cnmiBuf.sCnmiElement[i].type = CNMI_NONE;

  cnmiBuf.next = 0;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : cmd_flushCnmiBuf   |
+--------------------------------------------------------------------+

  PURPOSE : This function flushes the buffer for storing new message
            indications while the serial interface is released from
            data transmission.
*/
GLOBAL void cmd_flushCnmiBuf (void)
{
  UBYTE i            = cnmiBuf.next;
  UBYTE entries_read = 0;

  TRACE_FUNCTION("cmd_flushCnmiBuf");

  if ( cnmiBuf.sCnmiElement[0].type EQ CNMI_NONE )
  {
    entries_read = CNMI_BUF_SIZE; /* no need to read anything at all */
    //moreEntries = FALSE;
  }
  else if ( cnmiBuf.next                            EQ CNMI_BUF_SIZE OR
            cnmiBuf.sCnmiElement[cnmiBuf.next].type EQ CNMI_NONE )
  {
    i = 0;
  }

  cnmiFlushInProgress = TRUE;

  while ( entries_read < CNMI_BUF_SIZE /*moreEntries*/ )
  {
    if (smsShrdPrm.pDecMsg)
    { /* clear p_sm buffer */
      ACI_MFREE(smsShrdPrm.pDecMsg);
      smsShrdPrm.pDecMsg = NULL;
    }

    switch ( cnmiBuf.sCnmiElement[i].type )
    {
      
      case ( CNMI_CMT ):
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMT ( &cnmiBuf.sCnmiElement[i].indct.cmt );
        break;

      case ( CNMI_CMTI ):
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMTI ( cnmiBuf.sCnmiElement[i].indct.cmti.mem,
                       cnmiBuf.sCnmiElement[i].indct.cmti.index );
        break;

      case ( CNMI_CBM ):
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCBM (  &cnmiBuf.sCnmiElement[i].indct.cbm );
        break;

      case ( CNMI_CDS ):
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCDS (  &cnmiBuf.sCnmiElement[i].indct.cds );
        break;

      default:
//      moreEntries = FALSE;
        break;
    }

    cnmiBuf.sCnmiElement[i].type = CNMI_NONE;
    i++;
    entries_read++;

    if ( i EQ CNMI_BUF_SIZE )
      i = 0;
  }

  cnmiFlushInProgress = FALSE;
  cnmiBuf.next        = 0;
}

/*
+--------------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD                  |
| STATE   : code                        ROUTINE : cmd_flushCnmiBufOneByOne |
+--------------------------------------------------------------------------+

  PURPOSE : This function flushes the CNMI buffer in case of Phase2+ mode,
            while the serial interface is released from
            data transmission or an +CNMI <bfr>==Flush is requested.
*/

GLOBAL void cmd_flushCnmiBufOneByOne(void)
{ /* flushing +CMT one by one, because acknowledge is necessary */
  T_CNMI_BUFFER_ELEMENT* psMsgInCnmiBuffer = NULL;
  UINT16                 uiCnmiMsgCounter  = 0;
  BOOL                   bEndLoop          = FALSE;

  for( uiCnmiMsgCounter=0;
       (uiCnmiMsgCounter<cmd_getNumberOfCnmiEntrys()) && 
       (waitForCnmaFromBuffer_SrcId EQ CMD_SRC_NONE); 
       uiCnmiMsgCounter++ )
  { /* there are entrys in the CNMI buffer --> read it */
    psMsgInCnmiBuffer = cmd_getCnmiMessage(uiCnmiMsgCounter); /* FIFO */

    if( psMsgInCnmiBuffer EQ NULL )
    {
      TRACE_EVENT("ati_switch_mode() : Error at CNMI-buffer handling: NULL-pointer access!!");
      return;
    }
    
    cnmiFlushInProgress = TRUE; /* needed for the rCI_...commands */

    if (smsShrdPrm.pDecMsg)
    { /* clear p_sm buffer */
      ACI_MFREE(smsShrdPrm.pDecMsg);
      smsShrdPrm.pDecMsg = NULL;
    }

    switch ( psMsgInCnmiBuffer->type )
    {
      case ( CNMI_CMTI ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMTI ( psMsgInCnmiBuffer->indct.cmti.mem, psMsgInCnmiBuffer->indct.cmti.index );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CBM ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCBM (  &psMsgInCnmiBuffer->indct.cbm );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CDS ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCDS (  &psMsgInCnmiBuffer->indct.cds );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      /* special handling for +CMT --> acknowledge needed */
      case ( CNMI_CMT ) :
      {
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMT ( &psMsgInCnmiBuffer->indct.cmt );
        TIMERSTART(ACI_CNMA_TIMER_VALUE, ACI_CNMA_TIMER_HANDLE);
        waitForCnmaFromBuffer_SrcId = smsShrdPrm.smsSrcId;
        break;
      }
      default:
        TRACE_EVENT("ati_switch_mode() : wrong CNMI-buffer handling: wrong Msg. type");
    }
  }
  cnmiFlushInProgress = FALSE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : cmd_addCnmiNtry    |
+--------------------------------------------------------------------+

  PURPOSE : This function add a new entry to the buffer for storing
            new message indications while the serial interface is
            reserved for data transmission.
*/
GLOBAL void cmd_addCnmiNtry ( UBYTE type, T_CNMI_IND* newInd )
{
  TRACE_FUNCTION("cmd_addCnmiNtry");

  if ( type > CNMI_CDS OR type < CNMI_CMT )
    return;

  if ( cnmiBuf.next EQ CNMI_BUF_SIZE )
  {
    cnmiBuf.next = 0;
  }

  switch ( type )
  {
    case ( CNMI_CMT ):
      cnmiBuf.sCnmiElement[cnmiBuf.next].indct.cmt  = newInd -> cmt;
      break;

    case ( CNMI_CMTI ):
      cnmiBuf.sCnmiElement[cnmiBuf.next].indct.cmti = newInd -> cmti;
      break;


    case ( CNMI_CBM ):
      cnmiBuf.sCnmiElement[cnmiBuf.next].indct.cbm  = newInd -> cbm;
      break;

    case ( CNMI_CDS ):
      cnmiBuf.sCnmiElement[cnmiBuf.next].indct.cds  = newInd -> cds;
      break;
  }

  cnmiBuf.sCnmiElement[cnmiBuf.next].type  = type;
  cnmiBuf.next++;
}


/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : getNumberOfCnmiEntrys |
+-----------------------------------------------------------------------+

  PURPOSE : This function is the responsible to get the count 
            of CNMI entrys in the CNMI buffer.
*/
GLOBAL UINT16 cmd_getNumberOfCnmiEntrys(void)
{
  return cnmiBuf.next;
}


/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : getCnmiMessage        |
+-----------------------------------------------------------------------+

  PURPOSE : This function is the responsible to get an entire Msg.
            from the CNMI buffer. That means, this function only returns
            the pointer to the beginning of the CNMI buffer element.
            If the buffer is empty or if the uiIndex parameter is bigger
            than allowed, the return pointer will be NULL.
*/
GLOBAL T_CNMI_BUFFER_ELEMENT* cmd_getCnmiMessage(UINT16 uiIndex)
{
  T_CNMI_BUFFER_ELEMENT* psCnmiBufferElement = NULL;

  if( (cnmiBuf.next EQ 0) OR
      (cnmiBuf.sCnmiElement[0].type EQ CNMI_NONE) OR
      (uiIndex >= CNMI_BUF_SIZE ) )
  {
    return NULL;
  }

  psCnmiBufferElement = &cnmiBuf.sCnmiElement[uiIndex];
  return psCnmiBufferElement; /* returns the pointer to the element */
}


/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : clearFirstCnmiMessage |
+-----------------------------------------------------------------------+

  PURPOSE : This function is the responsible to clear an entire Msg.
            specified by uiIndex from the CNMI buffer.
            After succesful return, the message was delete from the CNMI
            buffer and the buffer has been resorted.
*/
GLOBAL BOOL cmd_clearCnmiMessage(UINT16 uiIndex)
{
  UINT16 uiBufCount;

  if( (cnmiBuf.next EQ 0) OR
      (cnmiBuf.sCnmiElement[0].type EQ CNMI_NONE))
  {
    return FALSE; /* CNMI buffer is empty or flushing is in progress */
  }

  /* delete first entry while resorting the buffer */
  for( uiBufCount = uiIndex; uiBufCount<(CNMI_BUF_SIZE-1); uiBufCount++ )
  {
    memcpy( &cnmiBuf.sCnmiElement[uiBufCount], &cnmiBuf.sCnmiElement[uiBufCount+1], sizeof(T_CNMI_BUFFER_ELEMENT) );
  }

  cnmiBuf.next--;

  return TRUE;
}

/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : getCnmiMessage        |
+-----------------------------------------------------------------------+

  PURPOSE : This function is the responsible to get the first entire Msg.
            from the CNMI buffer. That means, this function only returns
            the pointer to the beginning of the CNMI buffer.
            If the buffer is empty, the return pointer will be NULL.
*/
GLOBAL T_CNMI_BUFFER_ELEMENT* cmd_getFirstCnmiMessage(void)
{
  return cmd_getCnmiMessage(0);
}


/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : clearFirstCnmiMessage |
+-----------------------------------------------------------------------+

  PURPOSE : This function is the responsible to clear the first entire Msg.
            from the CNMI buffer. After succesful return, the 
            message was delete from the CNMI buffer.
*/
GLOBAL BOOL cmd_clearFirstCnmiMessage(void)
{
  return cmd_clearCnmiMessage(0);
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : rCI_IoMode         |
+--------------------------------------------------------------------+

  PURPOSE : This function will be called when IO mode of serial
            interface has changed.
*/
GLOBAL void rCI_IoMode ( void )
{
  TRACE_FUNCTION ( "rCI_IoMode (): actually not awaited !!" );

/*  if ( io_getIoMode () EQ IO_MODE_CMD AND
       at.CNMI_mode    EQ CNMI_MOD_Buffer )
    cmd_flushCnmiBuf (CMD_SRC_ATI);*/
}


/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : cmd_handleCnmaTimeout |
+-----------------------------------------------------------------------+

  PURPOSE : This function will be called when the +CNMA Timer has expired.
            Now all to be acknowledged +CMT messages whithin the CNMI
            buffer must be stored in the non-volatile buffer e.g. SIM...
            Note: all other Msgs. different from +CMT will be deliver
            to the source and remove from buffer. */

GLOBAL void cmd_handleCnmaTimeout( void )
{
  UINT16                 uiCnmiMsgCounter  = 0;
  T_CNMI_BUFFER_ELEMENT *psMsgInCnmiBuffer = NULL;

  TRACE_FUNCTION ( "cmd_handleCnmaTimeout()" );

  cmhSMS_resetMtDsCnmiParam();

  if( waitForCnmaFromBuffer_SrcId EQ CMD_SRC_NONE OR 
      waitForCnmaFromBuffer_SrcId NEQ smsShrdPrm.smsSrcId)
  {
    TRACE_EVENT("cmd_handleCnmaTimeout() : Error at CNMI-buffer handling: No +CNMA acknowledge expected!!");
    waitForCnmaFromBuffer_SrcId = CMD_SRC_NONE;
    return;
  }

  for( uiCnmiMsgCounter=0; uiCnmiMsgCounter<cmd_getNumberOfCnmiEntrys(); uiCnmiMsgCounter++ )
  { /* there are entrys in the CNMI buffer --> read it */
    psMsgInCnmiBuffer = cmd_getCnmiMessage(uiCnmiMsgCounter); /* FIFO */

    if( psMsgInCnmiBuffer EQ NULL )
    {
      TRACE_EVENT("cmd_handleCnmaTimeout() : Error at CNMI-buffer handling: NULL-pointer access!!");
      waitForCnmaFromBuffer_SrcId = CMD_SRC_NONE;
      return;
    }
    
    cnmiFlushInProgress = TRUE;

    switch ( psMsgInCnmiBuffer->type )
    {
      case ( CNMI_CMTI ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMTI ( psMsgInCnmiBuffer->indct.cmti.mem, psMsgInCnmiBuffer->indct.cmti.index );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CBM ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCBM (  &psMsgInCnmiBuffer->indct.cbm );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CDS ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCDS (  &psMsgInCnmiBuffer->indct.cds );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      /* special handling for +CMT --> acknowledge needed */
      case ( CNMI_CMT ) :
      {
        T_ACI_SM_DATA sPduData;

        waitForCnmaFromBuffer_SrcId = CMD_SRC_NONE; /* clear CNMA waiting flag */
        srcId_cb = smsShrdPrm.smsSrcId;
        sPduData.len = psMsgInCnmiBuffer->indct.cmt.sms_sdu.l_buf / 8; /* l_buf is in BIT !! */
        memcpy( &sPduData.data, &psMsgInCnmiBuffer->indct.cmt.sms_sdu.buf, SIM_PDU_LEN );
        cmhSMS_storePduToSim( smsShrdPrm.smsSrcId, SMS_RECORD_REC_UNREAD, &sPduData );
        cnmiFlushInProgress = FALSE;
        return; /* only one SMS can be stored at the SIM here */
      }

      default:
        TRACE_EVENT("cmd_handleCnmaTimeout() : wrong CNMI-buffer handling: wrong Msg. type");
    }
    cnmiFlushInProgress = FALSE;
  }
}

/*
+-----------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD               |
| STATE   : code                        ROUTINE : cmd_handleCnmaTimeout |
+-----------------------------------------------------------------------+

  PURPOSE : This function stores the next message - correxponding
            to a specified source - into the non volatile memory.
            Note: all other Msgs. different from +CMT will be deliver
            to the source and remove from buffer.
*/
GLOBAL BOOL cmd_storeNextCnmiBufMsgToSim( void )
{
  UINT16                 uiCnmiMsgCounter  = 0;
  T_CNMI_BUFFER_ELEMENT *psMsgInCnmiBuffer = NULL;

  TRACE_FUNCTION ( "cmd_storeNextCnmiBufMsgToSim()" );

  if( smsShrdPrm.uiInternalSmsStorage EQ CMD_SRC_NONE OR
      smsShrdPrm.uiInternalSmsStorage NEQ smsShrdPrm.smsSrcId)
  {
    TRACE_EVENT("cmd_storeNextCnmiBufMsgToSim() : no valid source -> abort !!");
    smsShrdPrm.uiInternalSmsStorage = CMD_SRC_NONE;
    return(FALSE);
  }

  for( uiCnmiMsgCounter=0; uiCnmiMsgCounter<cmd_getNumberOfCnmiEntrys(); uiCnmiMsgCounter++ )
  { /* there are entrys in the CNMI buffer --> read it */
    psMsgInCnmiBuffer = cmd_getCnmiMessage(uiCnmiMsgCounter); /* FIFO */

    if( psMsgInCnmiBuffer EQ NULL )
    {
      TRACE_EVENT("cmd_storeNextCnmiBufMsgToSim() : Error at CNMI-buffer handling: NULL-pointer access!!");
      smsShrdPrm.uiInternalSmsStorage = CMD_SRC_NONE;
      return(FALSE);
    }
    
    cnmiFlushInProgress = TRUE;

    switch ( psMsgInCnmiBuffer->type )
    {
      case ( CNMI_CMTI ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCMTI ( psMsgInCnmiBuffer->indct.cmti.mem, psMsgInCnmiBuffer->indct.cmti.index );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CBM ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCBM (  &psMsgInCnmiBuffer->indct.cbm );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      case ( CNMI_CDS ) :
        srcId_cb = smsShrdPrm.smsSrcId;
        rCI_PlusCDS (  &psMsgInCnmiBuffer->indct.cds );
        cmd_clearCnmiMessage(uiCnmiMsgCounter);
        uiCnmiMsgCounter--;
        break;

      /* special handling for +CMT --> acknowledge needed */
      case ( CNMI_CMT ) :
      {
        T_ACI_SM_DATA sPduData;

        srcId_cb = smsShrdPrm.smsSrcId;
        sPduData.len = psMsgInCnmiBuffer->indct.cmt.sms_sdu.l_buf / 8; /* l_buf is in BIT !! */
        memcpy( &sPduData.data, &psMsgInCnmiBuffer->indct.cmt.sms_sdu.buf, SIM_PDU_LEN );
        cmhSMS_storePduToSim( smsShrdPrm.smsSrcId, SMS_RECORD_REC_UNREAD, &sPduData );
        cnmiFlushInProgress = FALSE;
        return(TRUE); /* only one SMS can be stored at the SIM here */
      }

      default:
        TRACE_EVENT("cmd_handleCnmaTimeout() : wrong CNMI-buffer handling: wrong Msg. type");
    }
    cnmiFlushInProgress = FALSE;
  }
  smsShrdPrm.uiInternalSmsStorage = CMD_SRC_NONE; /* no more +CMT has to be store */
  return(FALSE);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : setatPlusCMMS      |
+--------------------------------------------------------------------+

  PURPOSE : +CMMS command (More Messages To Send)
*/

GLOBAL T_ATI_RSLT setatPlusCMMS (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = AT_FAIL;
  UBYTE        mode = 0;

  TRACE_FUNCTION("setatPlusCMMS()");

  cl = parse (cl,"r",&mode);

  /*
   * no mode values allowed other than 0-2
   */
  if ( !cl OR (mode < CMMS_MODE_DEF OR mode > CMMS_MODE_TWO))
  {
    cmdCmsError(CMS_ERR_OpNotAllowed);
    return (ATI_FAIL);
  }
  ret = sAT_PlusCMMS(srcId,mode);
  if (ret NEQ AT_CMPL)
  {
    cmdCmsError(CMS_ERR_UnknownErr);  
    return (ret);
  }
  return (map_aci_2_ati_rslt(ret));
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : queatPlusCMMS      |
+--------------------------------------------------------------------+

  PURPOSE : +CMMS query command 
*/
GLOBAL T_ATI_RSLT queatPlusCMMS (char *cl, UBYTE srcId)
{
  T_ACI_RETURN  ret = AT_FAIL;
  UBYTE         mode = CMMS_MODE_DEF;
  
  TRACE_FUNCTION("queatPlusCMMS()");

  ret = qAT_PlusCMMS (srcId,&mode);
  if (ret EQ AT_CMPL)
  {
    sprintf(g_sa, "+CMMS: %d",  mode);
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return (ATI_CMPL);
  }
  else
  {
    cmdCmsError(CMS_ERR_NotPresent);  
    return (ATI_FAIL);
  }
}

/*
+-------------------------------------------------------------------------+
| PROJECT : GSM-F&D                      MODULE  : ATI_SMS                |
| STATE   : finished                     ROUTINE : txt_rdmode_to_smsrdmode|
+-------------------------------------------------------------------------+

  PURPOSE : converts the text read mode to smsReadMode.

*/
GLOBAL T_ATI_RSLT txt_rdmode_to_smsrdmode(char *txt_rdmode)
{
  UBYTE i = 0;

   if (txt_rdmode[0] EQ '\0')
   {
     strcpy (txt_rdmode, sms_rdmode[0].name); /* NORMAL as default */
   }
   while ( sms_rdmode[i].name NEQ NULL      AND
              strcmp ( sms_rdmode[i].name, txt_rdmode ) NEQ 0 )
   {
      i++;
   }

   if ( sms_rdmode[i].name EQ NULL )
   {
      cmdCmsError ( CMS_ERR_OpNotAllowed );
      return (ATI_FAIL);
   }
   smsReadMode  = sms_rdmode[i].rdmode;
   return ATI_CMPL;
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPercentCMGL      |
+--------------------------------------------------------------------+

  PURPOSE : %CMGL command (List Message)
*/

GLOBAL T_ATI_RSLT atPercentCMGL (char *cl, UBYTE srcId)
{
  T_ACI_RETURN   ret;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

#ifdef SMS_PDU_SUPPORT
  T_ACI_CMGF_MOD mode;
#endif
  CHAR           txtStat[15]= {0};
  CHAR           txtRdMode[20] = {0};
  USHORT         i;

  TRACE_FUNCTION("atPercentCMGL()");

  cmglStat = SMS_STAT_NotPresent;
  smsReadMode  = SMS_READ_NotPresent;

  if (*cl EQ '\0')
  {
    smsReadMode  = SMS_READ_Normal;
  }
  else
  {
    /*
     * Request of a list of stored SMS messages
     * Parameter stat is optional
     */
#ifdef SMS_PDU_SUPPORT
    /*
     * request current mode
     */
    qAT_PlusCMGF(srcId, &mode);
    if (mode EQ 0)
    {

      /*
       * %CMGL=[stat],[preview]
       */
      cl = parse (cl, "dd", &cmglStat, &smsReadMode );
      if ( !cl 
            OR ((cmglStat < SMS_STAT_RecUnread OR cmglStat > SMS_STAT_All)
                  AND smsReadMode  EQ SMS_READ_NotPresent) 
            OR (cmglStat < SMS_STAT_RecUnread AND smsReadMode > SMS_READ_NotPresent) 
            OR (smsReadMode  > SMS_READ_StatusChange))
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
    }
    else
#endif
    {

      /*
       * %CMGL=[stat],[preview]
       */
      cl = parse (cl, "ss", (LONG)sizeof(txtStat), txtStat, 
                  (LONG)sizeof(txtRdMode), txtRdMode);
      if ( !cl OR (txtStat[0] EQ '\0' AND txtRdMode[0] NEQ '\0'))
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
      if (txtStat[0] EQ '\0')
        strcpy (txtStat, sms_stat[4].name); /* ALL as default */

      i = 0;
      while ( sms_stat[i].name NEQ NULL            AND
              strcmp ( sms_stat[i].name, txtStat ) NEQ 0 )
        i++;

      if ( sms_stat[i].name EQ NULL )
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
      cmglStat = sms_stat[i].stat;

      ret = txt_rdmode_to_smsrdmode(txtRdMode);
      if (ret EQ ATI_FAIL)
      {
        return (ret);
      }
    }
  }

#ifdef FF_ATI_BAT
  {
    T_BAT_cmd_send cmd;
    T_BAT_cmd_set_percent_cmgl cmgl;

    cmd.ctrl_params=BAT_CMD_SET_PERCENT_CMGL;
    cmd.params.ptr_set_percent_cmgl=&cmgl;

    /*
    *   T_ACI_SMS_STAT and T_BAT_percent_cmgl_stat are not quite
    *   identical - the ACI version has the extra value
    *   SMS_STAT_Invalid.
    */
    if (cmglStat EQ SMS_STAT_Invalid)
      cmgl.stat=BAT_CMGL_STAT_NOT_PRESENT;
    else
      cmgl.stat=(T_BAT_percent_cmgl_stat)cmglStat;

    cmgl.rdmode = smsReadMode ;

    bat_send(ati_bat_get_client(srcId),&cmd);

    src_params->curAtCmd=AT_CMD_P_CMGL;
    return(ATI_EXCT);
  }

#else

  ret = sAT_PercentCMGL ( srcId, cmglStat, smsReadMode  );

  if ( ret EQ AT_EXCT )
  {
    src_params->curAtCmd = AT_CMD_P_CMGL;
    return (ATI_EXCT);
  }
  else
  {
    cmdCmsError ( CMS_ERR_NotPresent );  
    return (ATI_FAIL);
  }
#endif
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)              MODULE  : ACI_CMD            |
| STATE   : code                        ROUTINE : atPercentCMGR         |
+--------------------------------------------------------------------+

  PURPOSE : %CMGR command (Read Message)
*/

GLOBAL T_ATI_RSLT atPercentCMGR (char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret = AT_FAIL;
  SHORT idx=-1;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);
#ifdef SMS_PDU_SUPPORT
  T_ACI_CMGF_MOD mode;
#endif
  CHAR           txtRdMode[20]={0};


  TRACE_FUNCTION("atPercentCMGR()");

  smsReadMode  = SMS_READ_Normal;

#ifdef SMS_PDU_SUPPORT
    /*
     * request current mode
     */
    qAT_PlusCMGF(srcId, &mode);
    if (mode EQ 0)
    {
      /*
       * %CMGR=[index],[preview]
       */
      cl = parse (cl, "rd", &idx, &smsReadMode );
      if ( !cl OR idx > 255 OR idx < 0 OR smsReadMode  > SMS_READ_StatusChange)
      {
        cmdCmsError ( CMS_ERR_OpNotAllowed );
        return (ATI_FAIL);
      }
    }
    else
#endif
    {
      /*
       * %CMGR=[index],[preview]
       */
      cl = parse (cl, "rs", &idx, 
                  (LONG)sizeof(txtRdMode), txtRdMode);
  
      if ( !cl OR idx > 255 OR idx < 0)
      {
        cmdCmsError(CMS_ERR_OpNotAllowed);
        return (ATI_FAIL);
      }
      ret = txt_rdmode_to_smsrdmode(txtRdMode);
      if (ret EQ ATI_FAIL)
      {
        return (ret);
      }
    }

#ifdef FF_ATI_BAT
  {
    T_BAT_cmd_send cmd;
    T_BAT_cmd_set_percent_cmgr cmgr;

    cmd.ctrl_params=BAT_CMD_SET_PERCENT_CMGR;
    cmd.params.ptr_set_percent_cmgr=&cmgr;

    cmgr.sms_index=(U16)idx;
    
    cmgr.rdmode = smsReadMode ;

    bat_send(ati_bat_get_client(srcId), &cmd);

    src_params->curAtCmd=AT_CMD_P_CMGR;
    return(ATI_EXCT);
  }

#else

#ifndef _CONC_TESTING_
  ret = sAT_PercentCMGR_Gl(srcId, (UBYTE)idx, smsReadMode , NULL);
#else
  ret = sAT_PercentCMGR (srcId, (UBYTE)idx, smsReadMode );
#endif
 if ( ret EQ AT_CMPL )
 {
   return (ATI_CMPL);
 }
 else if (ret EQ AT_EXCT)
 {
   src_params->curAtCmd    = AT_CMD_P_CMGR;
   return (ATI_EXCT);
 }
 else
 {
   cmdCmsError(CMS_ERR_NotPresent);  // use aciErrDesc
   return (ATI_FAIL);
 }

#endif /*FF_ATI_BAT*/
}

GLOBAL T_ATI_RSLT tesatPercentCMGL (char *cl, UBYTE srcId)
{
#ifdef SMS_PDU_SUPPORT
  T_ACI_CMGF_MOD mode;
  T_ATI_SRC_PARAMS *src_params = find_element (ati_src_list, srcId, search_ati_src_id);

  TRACE_FUNCTION("tesatPercentCMGL()");
  /*
   * request current mode
   */
  qAT_PlusCMGF(srcId, &mode);
  if (mode EQ 0)
  /*
   * handle PDU mode
   */
    io_sendMessage(srcId, "+CMGL: (0,1,2,3,4), (0,1,2)", ATI_NORMAL_OUTPUT);
  else
  /*
   * handle Text mode
   */
#endif
   io_sendMessage(srcId, "+CMGL: (\"REC UNREAD\",\"REC READ\",\"STO UNSENT\",\"STO SENT\",\"ALL\"), \
                                 (\"READ NORMAL\",\"READ PREVIEW\",\"STATUS CHANGE\")", ATI_NORMAL_OUTPUT);

  return (ATI_CMPL);
}

#endif /* ATI_SMS_C */