view src/aci2/aci/ati_err.c @ 600:8f50b202e81f

board preprocessor conditionals: prep for more FC hw in the future This change eliminates the CONFIG_TARGET_FCDEV3B preprocessor symbol and all preprocessor conditionals throughout the code base that tested for it, replacing them with CONFIG_TARGET_FCFAM or CONFIG_TARGET_FCMODEM. These new symbols are specified as follows: CONFIG_TARGET_FCFAM is intended to cover all hardware designs created by Mother Mychaela under the FreeCalypso trademark. This family will include modem products (repackagings of the FCDEV3B, possibly with RFFE or even RF transceiver changes), and also my desired FreeCalypso handset product. CONFIG_TARGET_FCMODEM is intended to cover all FreeCalypso modem products (which will be firmware-compatible with the FCDEV3B if they use TI Rita transceiver, or will require a different fw build if we switch to one of Silabs Aero transceivers), but not the handset product. Right now this CONFIG_TARGET_FCMODEM preprocessor symbol is used to conditionalize everything dealing with MCSI. At the present moment the future of FC hardware evolution is still unknown: it is not known whether we will ever have any beyond-FCDEV3B hardware at all (contingent on uncertain funding), and if we do produce further FC hardware designs, it is not known whether they will retain the same FIC modem core (triband), if we are going to have a quadband design that still retains the classic Rita transceiver, or if we are going to switch to Silabs Aero II or some other transceiver. If we produce a quadband modem that still uses Rita, it will run exactly the same fw as the FCDEV3B thanks to the way we define TSPACT signals for the RF_FAM=12 && CONFIG_TARGET_FCFAM combination, and the current fcdev3b build target will be renamed to fcmodem. OTOH, if that putative quadband modem will be Aero-based, then it will require a different fw build target, the fcdev3b target will stay as it is, and the two targets will both define CONFIG_TARGET_FCFAM and CONFIG_TARGET_FCMODEM, but will have different RF_FAM numbers. But no matter which way we are going to evolve, it is not right to have conditionals on CONFIG_TARGET_FCDEV3B in places like ACI, and the present change clears the way for future evolution.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 01 Apr 2019 01:05:24 +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: Error handling.
+-----------------------------------------------------------------------------
*/

/*********************************/
/* General Error Handling in ACI */
/*********************************/

#ifndef ATI_ERR_C
#define ATI_ERR_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.h"
#include "aci_mem.h"

#include "aci_lst.h"
#include "ati_int.h"

#ifdef FF_ATI_BAT

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

#include "ati_bat.h"

#endif /*FF_ATI_BAT*/

LOCAL CHAR *AT_Fail_Error(void);

EXTERN T_ACI_ERR_DESC aciErrDesc;

LOCAL CHAR ErrBuff[MAX_CMD_LEN];

typedef struct
{
  CHAR        *msg;
  CHAR    *nmb;
  AtErrCode   code;
} AtErrTable;

LOCAL const AtErrTable tabAtError[]=
{
  "OK",          "0",   atOk,
  "CONNECT",     "1",   atConnect,
  "RING",        "2",   atRing,
  "NO CARRIER",  "3",   atNoCarrier,
  "NO DIALTONE", "6",   atNoDialtone,
  "BUSY",        "7",   atBusy,
  "NO ANSWER",   "8",   atNoAnswer,
  "CONNECT 9600","15",  atConnect1,
  /* this has to be the last entry */
  "ERROR",       "4",   atError
};

GLOBAL CHAR *disable_or_numeric(const CHAR* key,LONG e) // e is actually enum...
{
  UBYTE srcId = srcId_cb;
  
  if(ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Disable)
  {
    cmdAtError(atError);
  }
  else if(ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Numeric)
  {
    sprintf(cmdErrStr,"%s ERROR: %d",key,e);
  }
  return cmdErrStr;
}


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

  PURPOSE : handle extended errors

*/

LOCAL const struct T_ATI_EXT_ERR /* error code - error message mapping */
{
  const CHAR*         msg;  /* error message */
  const T_ACI_EXT_ERR code; /* error code    */
  const ULONG displ_code;  /* error code to be display */
}

err[] =
{
"parameter not allowed",                  EXT_ERR_Parameter,       EXT_ERR_Parameter,
"data corrupted",                         EXT_ERR_DataCorrupt,     EXT_ERR_DataCorrupt,
"internal error",                         EXT_ERR_Internal,        EXT_ERR_Internal,
"call table full",                        EXT_ERR_CallTabFull,     EXT_ERR_CallTabFull,
"service table full",                     EXT_ERR_SrvTabFull,      EXT_ERR_SrvTabFull,
"call not found",                         EXT_ERR_CallNotFound,    EXT_ERR_CallNotFound,
"no data-call supported",                 EXT_ERR_NoDataCallSup,   EXT_ERR_NoDataCallSup,
"one call on hold",                       EXT_ERR_OneCallOnHold,   EXT_ERR_OneCallOnHold,
"hold call not supported for this type",  EXT_ERR_CallTypeNoHold,  EXT_ERR_CallTypeNoHold,
"number not allowed by FDN",              EXT_ERR_FdnCheck,        EXT_ERR_FdnCheck,
"number not allowed by BDN",              EXT_ERR_BdnCheck,        EXT_ERR_BdnCheck,
"parallel USSD not supported",            EXT_ERR_ParallelUSSD,    EXT_ERR_ParallelUSSD,
"fax minimum speed condition",            EXT_ERR_FaxMinSpeedCond, EXT_ERR_FaxMinSpeedCond,
"conflict with command details",          EXT_ERR_CmdDetailsSAT,   EXT_ERR_CmdDetailsSAT,
"IMEI illegal",                           EXT_ERR_IMEICheck,       EXT_ERR_IMEICheck,
"not allowed by ALS-Lock",                EXT_ERR_AlsLock,         EXT_ERR_AlsLock,
#if defined FF_EOTD
"Command not supported",                                        EXT_ERR_LCS_CmdNotSup,          0,
"Command not recognised/out of range",                          EXT_ERR_LCS_CmdNotRec,          1,
"LCS Client ID not recognised/out of range",                    EXT_ERR_LCS_CLPSClientNotRec,   2,
"Interval attribute out of range",                              EXT_ERR_LCS_IntervalNotSup,     3,
"Repeat attribute not supported/ out of range",                 EXT_ERR_LCS_RepeatNotSup,       4,
"Send request type not recognised / out of range",              EXT_ERR_LCS_SendReqTyNotRec,    2,
"User confirmation request type not recognised / out of range", EXT_ERR_LCS_UsConfReqTyNotRec,  3,
"LCS Client ID not recognised/out of range",                    EXT_ERR_LCS_CLSRClientIdNotRec, 4,
"Circuit switched call number out of range",                    EXT_ERR_LCS_CSCallNumNotSup,    5,
#endif /* FF_EOTD */
"error unknown",                          EXT_ERR_Unknown,         EXT_ERR_Unknown,
/* this has to be the last entry */
"other error",                            EXT_ERR_NotPresent,      EXT_ERR_NotPresent
};

GLOBAL CHAR *cmdExtError (T_ACI_EXT_ERR e)
{
  SHORT idx=0;
  T_ACI_ERR_DESC aed;
  UBYTE srcId = srcId_cb;


  if ( e EQ EXT_ERR_NotPresent )
  {
    if (((aed = qAT_ErrDesc()) >> 16) EQ ACI_ERR_CLASS_Ext)
    {
      e = (T_ACI_EXT_ERR)(aed & 0xFFFF);
    }
    else
    {
      e = EXT_ERR_Unknown;
    }
  }

  *ErrBuff = '\0';
  cmdErrStr = ErrBuff;

  if (ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Verbose OR
      ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Numeric)
  {
    /* search the array for the index of the notified failure */
    while ( err[idx].code NEQ EXT_ERR_NotPresent AND
            err[idx].code NEQ e )
    {
       idx++;
    }
  }
  else /* Catch some Extended Error Codes and map them to more suitable codes */
  {
    switch (e)
    {
      case EXT_ERR_CallTabFull:
      case EXT_ERR_FdnCheck:
      case EXT_ERR_BdnCheck:
        return(cmdAtError(atNoCarrier));
    }
  }
  if (ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Verbose)
  {
    strcat(cmdErrStr,"+EXT ERROR: ");
    strcat( cmdErrStr, err[idx].msg );
  }
  return(disable_or_numeric("+EXT", err[idx].displ_code));
}

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

  PURPOSE : handle Mobile Equipment Errors

*/
#ifdef GPRS
#define GPRS_ERR(a,b) a,b,
#else
#define GPRS_ERR(a,b)
#endif  /* GPRS */

LOCAL const struct T_ATI_CME_ERR /* error code - error message mapping */
{
  const CHAR*         msg;  /* error message */
  const T_ACI_CME_ERR code; /* error code    */
}
  error[] =
{
"phone failure",                        CME_ERR_PhoneFail,
"no connection to phone",               CME_ERR_NoConnect,
"phone-adaptor link reserved",          CME_ERR_LinkRes,
"operation not allowed",                CME_ERR_OpNotAllow,
"operation not supported",              CME_ERR_OpNotSupp,
"PH-SIM PIN required",                  CME_ERR_PhSimPinReq,
"SIM not inserted",                     CME_ERR_SimNotIns,
"SIM PIN required",                     CME_ERR_SimPinReq,
"SIM PUK required",                     CME_ERR_SimPukReq,
"SIM failure",                          CME_ERR_SimFail,
"SIM busy",                             CME_ERR_SimBusy,
"SIM wrong",                            CME_ERR_SimWrong,
"incorrect password",                   CME_ERR_WrongPasswd,
"SIM PIN2 required",                    CME_ERR_SimPin2Req,
"SIM PUK2 required",                    CME_ERR_SimPuk2Req,
"memory full",                          CME_ERR_MemFull,
"invalid index",                        CME_ERR_InvIdx,
"not found",                            CME_ERR_NotFound,
"memory failure",                       CME_ERR_MemFail,
"text string too long",                 CME_ERR_TxtToLong,
"invalid characters in text string",    CME_ERR_InvalidTxtChar,
"dial string too long",                 CME_ERR_DialToLong,
"invalid characters in dial string",    CME_ERR_InvDialChar,
"no network service",                   CME_ERR_NoServ,
"network timeout",                      CME_ERR_Timeout,
"network not allowed - emergency calls only", CME_ERR_LimServ,
"Network lock - PIN required",  CME_ERR_NetworkPersPinReq,                      /* PIN to change network personalisation required */
"Network lock - PUK required",  CME_ERR_NetworkPersPukReq,                    /* network personalisation PUK is required */
"Subnetwork lock - PIN required",  CME_ERR_NetworkSubsetPersPinReq,       /* keycode to change nw subset personalisation required */
"Subnetwork lock - PUK required",  CME_ERR_NetworkSubsetPersPukReq,     /* network subset  personalisation PUK is required */
"Provider lock - PIN required",  CME_ERR_ProviderPersPinReq,                     /* keycode to change service provider personal. required */
"Provider lock - PUK required",  CME_ERR_ProviderPersPukReq,                   /* service provider personalisation PUK is required */
"Corporate lock - PIN required",  CME_ERR_CorporatePersPinReq,                /* keycode to change corporate personalisation required */
"Corporate lock - PUK required",  CME_ERR_CorporatePersPukReq,              /* corporate personalisation PUK is required */
"unknown",                              CME_ERR_Unknown,                                    /* ATTENTION! If you insert new entries before CME_ERR_Unknown, remember to increase NBR_CME_NORM_ERR */
GPRS_ERR("illegal MS",                  CME_ERR_GPRSBadMs)
GPRS_ERR("illegal ME",                  CME_ERR_GPRSBadMe)
GPRS_ERR("GPRS service not allowed",    CME_ERR_GPRSNoService)
GPRS_ERR("PLMN not allowed",            CME_ERR_GPRSBadPlmn)
GPRS_ERR("Location not allowed",        CME_ERR_GPRSBadLoc)
GPRS_ERR("Roaming not allowed in Location Area",   CME_ERR_GPRSNoRoam)
GPRS_ERR("GPRS service option not supported",      CME_ERR_GPRSSerOptNsup)
GPRS_ERR("requested service option not subscribed",CME_ERR_GPRSSerOptNsub)
GPRS_ERR("service option temporarily out of order",CME_ERR_GPRSSerOptOOO)
GPRS_ERR("unspecified GPRS error",      CME_ERR_GPRSUnspec)
GPRS_ERR("PDP authorisation error",     CME_ERR_GPRSPdpAuth)
GPRS_ERR("invalid module class",        CME_ERR_GPRSBadModClass)
"failed to abort",                      CME_ERR_FailedToAbort,
"ACM reset needed",                     CME_ERR_AcmResetNeeded,
/* this has to be the last entry */
"other error",                          CME_ERR_NotPresent
};

GLOBAL CHAR *cmdCmeError (T_ACI_CME_ERR e)
{
  SHORT idx=0;
  T_ACI_ERR_DESC aed;
  UBYTE srcId = srcId_cb;

  *ErrBuff = '\0';     /* initialization */
  cmdErrStr = ErrBuff;

  if ( e EQ CME_ERR_NotPresent )
  {
    if (((aed = qAT_ErrDesc()) >> 16) EQ ACI_ERR_CLASS_Cme)
    {
      e = (T_ACI_CME_ERR)(aed & 0xFFFF);
    }
    else
    {
      e = CME_ERR_Unknown;
    }
  }
  else if( e EQ CME_ERR_Unknown )
  {
    return(AT_Fail_Error());
  }

  if (ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Verbose)
  {
    strcat(cmdErrStr,"+CME ERROR: ");

    /* search for the description of the notified error */
    while ( error[idx].code NEQ CME_ERR_NotPresent AND
            error[idx].code NEQ e )
    {
      idx++;
    }
    strcat( cmdErrStr, error[idx].msg );
  }
  return(disable_or_numeric("+CME",e));
}


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

  PURPOSE : handle Short Message Errors

*/

LOCAL const struct T_ATI_CMS_ERR /* error code - error message mapping */
{
  const CHAR*         msg;  /* error message */
  const T_ACI_CMS_ERR code; /* error code    */
}
  cms_err[] =
{
  "unassigned (unallocated) number",               CMS_ERR_UnAllocNum,
  "operator determined barring",                   CMS_ERR_OpDetermBarr,
  "call barred",                                   CMS_ERR_CallBarr,
  "short message transfer rejected",               CMS_ERR_TransReject,
  "destination out of service",                    CMS_ERR_DestOutOfServ,
  "unidentified subscriber",                       CMS_ERR_UnidentSubsc,
  "facility rejected",                             CMS_ERR_FacReject,
  "unknown subscriber",                            CMS_ERR_UnKnownSubsc,
  "network out of order",                          CMS_ERR_NetOutOfOrder,
  "temporary failure",                             CMS_ERR_TempFail,
  "congestion",                                    CMS_ERR_Congestion,
  "resources unavailable, unspecified",            CMS_ERR_ResUnAvail,
  "requested facility not subscribed",             CMS_ERR_FacNotSubscr,
  "requested facility not implemented",            CMS_ERR_FacNotImpl,
  "invalid short message transfer ref. value",     CMS_ERR_TransRefInval,
  "semantically incorrect message",                CMS_ERR_InValSM,
  "invalid mandatory information",                 CMS_ERR_InValManInfo,
  "message type non-existent or not implemented",  CMS_ERR_MsgTypNotExist,
  "message not compatible with SM protocol state", CMS_ERR_MsgNotCompatible,
  "information element non-existent or not impl.", CMS_ERR_InfoElemNotImpl,
  "protocol error, unspecified",                   CMS_ERR_ProtErr,
  "interworking, unspecified",                     CMS_ERR_InterWrkUnSpec,
  "telematic interworking not supported",          CMS_ERR_TlmtkNotSup,
  "short message type 0 not supported",            CMS_ERR_SM0NotSup,
  "cannot replace short message",                  CMS_ERR_CantReplceSM,
  "unspecified TP-PID error",                      CMS_ERR_UnSpecPIDErr,
  "data coding scheme (alphabet) not supported",   CMS_ERR_DcsNotSup,
  "message class not supported",                   CMS_ERR_MsgClassNotSup,
  "unspecified TP-DCS error",                      CMS_ERR_UnSpecTpDcs,
  "command cannot be actioned",                    CMS_ERR_CmdNotAct,
  "command unsupported",                           CMS_ERR_CmdUnSup,
  "unspecified TP-Command error",                  CMS_ERR_UnSpecTpCmd,
  "TPDU not supported",                            CMS_ERR_TpduUnSup,
  "SC busy",                                       CMS_ERR_ScBsy,
  "no SC subscription",                            CMS_ERR_NoScSubsc,
  "SC system failure",                             CMS_ERR_ScSysFail,
  "invalid SME address",                           CMS_ERR_InValSme,
  "destination SME barred",                        CMS_ERR_DestSmeBarr,
  "SM rejected-duplicate SM",                      CMS_ERR_SmRejctDuplSm,
  "TP-VPF not supported",                          CMS_ERR_SmTPVPFNotSup,
  "TP-VP not supported",                           CMS_ERR_SmTPVPNotSup,
  "SIM SMS storage full",                          CMS_ERR_SimSmsStorFull,
  "no SMS storage capability in SIM",              CMS_ERR_NoStorInSim,
  "error in MS",                                   CMS_ERR_ErrInMs,
  "memory capacity exceeded",                      CMS_ERR_MemCabExcee,
  "unspecified error cause",                       CMS_ERR_UnSpecErr,
  "ME failure",                                    CMS_ERR_MeFail,
  "SMS service of ME reserved",                    CMS_ERR_ServRes,
  "operation not allowed",                         CMS_ERR_OpNotAllowed,
  "operation not supported",                       CMS_ERR_OpNotSup,
  "invalid PDU mode parameter",                    CMS_ERR_InValPduMod,
  "invalid text mode parameter",                   CMS_ERR_InValTxtMod,
  "SIM not inserted",                              CMS_ERR_SimNotIns,
  "SIM PIN required",                              CMS_ERR_SimPinReq,
  "PH-SIM PIN required",                           CMS_ERR_PhSimPinReq,
  "SIM failure",                                   CMS_ERR_SimFail,
  "SIM busy",                                      CMS_ERR_SimBsy,
  "SIM wrong",                                     CMS_ERR_SimWrong,
  "SIM PUK required",                              CMS_ERR_SimPukReq,
  "SIM PIN2 required",                             CMS_ERR_SimPin2Req,
  "SIM PUK2 required",                             CMS_ERR_SimPuk2Req,
  "memory failure",                                CMS_ERR_MemFail,
  "invalid memory index",                          CMS_ERR_InValMemIdx,
  "memory full",                                   CMS_ERR_MemFull,
  "SMSC address unknown",                          CMS_ERR_SmscAdrUnKnown,
  "no network service",                            CMS_ERR_NoNetServ,
  "network timeout",                               CMS_ERR_NetTimeOut,
  "no +CNMA acknowledegment expected",             CMS_ERR_NoCnmaAckExpect,
  "unknown error",                                 CMS_ERR_UnknownErr,
  "failed to abort",                               CMS_ERR_FailedToAbort,
  /* this must be the last entry */
  "other error",                                   CMS_ERR_NotPresent
};

#define NBR_CMS_ERR 69
#define MAX_CMS_LTH 60

GLOBAL char* cmdCmsError ( T_ACI_CMS_ERR e )
{
  int i = 0;
  T_ACI_ERR_DESC aed;
  UBYTE srcId = srcId_cb;  

  if ( e EQ CMS_ERR_NotPresent )
  {
    if (((aed = qAT_ErrDesc()) >> 16) EQ ACI_ERR_CLASS_Cms)
    {
      e = (T_ACI_CMS_ERR)(aed & 0xFFFF);
    }
    else                        /* no SMS error code */
    {
      e = CMS_ERR_UnknownErr;
    }
  }

  {
    *ErrBuff = '\0';        /* build message */
    cmdErrStr = ErrBuff;

    if ( ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Verbose )
    {
      strcat( cmdErrStr, "+CMS ERROR: " );

      while ( cms_err[i].code NEQ CMS_ERR_NotPresent AND
              cms_err[i].code NEQ e )
      {
        i++;
      }
      strcat( cmdErrStr, cms_err[i].msg );
    }
    else if ( ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Disable )
    {
      strcat ( cmdErrStr, "ERROR" );
    }
    else if ( ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Numeric )
    {
      sprintf ( cmdErrStr, "+CMS ERROR: %d", e );
    }
  }

  return cmdErrStr;
}


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

  PURPOSE : Extented error report
*/

typedef struct
  {
    char        * desc;
    T_ACI_CEER    rpt;
  } CEER_TABLE;

/* Defined by standards CEER cause description table */
const CEER_TABLE StdCEERDesc[]=
{
   {"unassigned number",                  CEER_Unassign },
   {"no route to destination",            CEER_NoRoute },
   {"channel unacceptable",               CEER_ChanUnaccept },
   {"operator determined barring",        CEER_Barred },
   {"normal call clearing",               CEER_CallClear },
   {"user busy",                          CEER_UserBusy },
   {"no user responding",                 CEER_NoResponse },
   {"user alerting, no answer",           CEER_AlertNoAnswer },
   {"call rejected",                      CEER_CallReject },
   {"number changed",                     CEER_NumChanged },
   {"non selected user clearing",         CEER_UserClear },
   {"destination out of order",           CEER_DestOutOfOrder },
   {"invalid number format",              CEER_NumFormat },
   {"facility rejected",                  CEER_FacilityReject },
   {"response to status enquiry",         CEER_StatusEnquiry },
   {"normal, unspecified",                CEER_Unspecified },
   {"no channel available",               CEER_NoChanAvail },
   {"network out of order",               CEER_NetworkOutOfOrder },
   {"temporary failure",                  CEER_TempFailure },
   {"switching equipment congestion",     CEER_SwitchCongest },
   {"access information discarded",       CEER_InfoDiscard },
   {"requested channel unavailable",      CEER_ReqChanUnavail },
   {"recources unavailable",              CEER_ResourceUnavail },
   {"quality of service unavailable",     CEER_QOS_Unavail },
   {"requested facility unsubscribed",    CEER_FAC_Unsubscr },
   {"incoming calls barred within CUG",   CEER_BarredInCUG },
   {"bearer capability not authorized",   CEER_BearerCapNotAuth },
   {"bearer capability not available",    CEER_BearerCapUnavail },
   {"service not available",              CEER_ServUnavail },
   {"bearer service not implemented",     CEER_BearerNotImpl },
   {"ACM reached ACM maximum",            CEER_ACM_Max },
   {"facility not implemented",           CEER_FAC_NotImpl },
   {"only restricted bearer cap. avail.", CEER_RestrictBearerCap },
   {"service not implemented",            CEER_ServNotImpl },
   {"invalid TI",                         CEER_InvalidTI },
   {"no member of CUG",                   CEER_UserNotInCUG },
   {"incompatible destination",           CEER_IncompatDest },
   {"invalid transit network selection",  CEER_InvalidTransNet },
   {"incorrect message",                  CEER_IncorrMsg },
   {"invalid mandatory information",      CEER_InvalidMandInfo },
   {"message type not implemented",       CEER_MsgTypeNotImpl },
   {"message type incompatible",          CEER_MsgTypeIncomp },
   {"info element not implemented",       CEER_InfoElemNotImpl },
   {"conditional info element error",     CEER_CondInfoElem },
   {"message incompatible",               CEER_MsgIncomp },
   {"recovery on time expiry",            CEER_Timer },
   {"protocol error",                     CEER_Protocol },
   {"interworking error",                 CEER_Interworking },
   {"bearer service not available",       CEER_ReqBearerServNotAvail },
   {"no TI available",                    CEER_NoTransIdAvail },
   {"timer 303 expiry",                   CEER_Timer303 },
   {"establishment failure",              CEER_EstabFail },
   {"no error",                           CEER_NoError },
   {"operation failed",                   CEER_Failed },
   {"timeout",                            CEER_Timeout },
   {"bearer service not compatible",      CEER_BearerServNotCompat },
#ifdef GPRS
   {"unsuccessful GPRS attach",           CEER_FailedGPRSAttach },
   {"unsuccessful PDP context activation",CEER_FailedGPRSContextAct },
   {"GPRS detach",                        CEER_GPRSDetach },
   {"GPRS PDP context deactivation",      CEER_GPRSDeactivation },
#endif /* GPRS */
   /* these have  to be the last entries */
   {"no error",                           CEER_NotPresent },
   /* last entry for at+ceer */
   { NULL,                                0}
};

/* Proprietary ACI CEER cause description table */
const CEER_TABLE pACI_CEERDesc[]=
{
   {"ACM reached ACM maximum", P_CEER_ACMMaxReachedOrExceeded, },
   {"number not in FDN list",              P_CEER_InvalidFDN },
   /* these have  to be the last entries */
   {"no error",                            P_CEER_NotPresent },
   /* last entry for at+ceer */
   { NULL,                                 0}
};

/* Proprietary MM CEER cause description table */
const CEER_TABLE pMM_CEERDesc[]=
{
  {"IMSI not present in HLR", P_MM_CEER_IMSINotInHLR},
  {"no service",              P_MM_CEER_NoService },
  /* these have  to be the last entries */
  {"no error",                            P_MM_CEER_NotPresent },
  /* last entry for at+ceer */
  { NULL,                                 0}
};

/* Proprietary SS CEER cause description table */
const CEER_TABLE pSS_CEERDesc[]=
{
  {"Unknown Subscriber",                           P_SS_CEER_UnknownSubscriber },
  {"Illegal Subscriber",                           P_SS_CEER_IllegalSubscriber },
  {"Bearer service not provisioned",               P_SS_CEER_BearerSvcNotProv },
  {"Teleservice not provisioned",                  P_SS_CEER_TeleSvcNotProv },
  {"Illegal Equipment",                            P_SS_CEER_IllegalEquipment },
  {"Call barred",                                  P_SS_CEER_CallBarred },
  {"Illegal supplementary service operation",      P_SS_CEER_IllegalSSOperation },
  {"SS error status",                              P_SS_CEER_SSerrStatus },
  {"SS not available",                             P_SS_CEER_SSNotAvail },
  {"SS subscript violation",                       P_SS_CEER_SSSubsViolation },
  {"SS incompatible",                              P_SS_CEER_SSIncomp },
  {"Facility not supported",                       P_SS_CEER_FacNotSupported },
  {"Absent subscriber",                            P_SS_CEER_AbsentSubs },
  {"System failure",                               P_SS_CEER_SystenFail },
  {"Data Missing",                                 P_SS_CEER_DataMissing },
  {"Unexpected Data Value",                        P_SS_CEER_UnexpectData },
  {"Password registration failure",                P_SS_CEER_PwdRegFail },
  {"Negative password check",                      P_SS_CEER_NegPwdCheck},
  {"Number of password attempts violation",        P_SS_CEER_NumPwdViolation },
  {"Unknown alphabet",                             P_SS_CEER_UnknownAlpha },
  {"Unstructured supplementary service data busy", P_SS_CEER_UssdBusy },
  {"Number of multiparty participants exceeded",   P_SS_CEER_MaxNumMptyExceed },
  {"Resource not available",                       P_SS_CEER_ResourceNotAvail },

  /* these have  to be the last entries */
  {"no error",                            P_SS_CEER_NotPresent },
  /* last entry for at+ceer */
  { NULL,                                 0}
};
#define MAX_CEER_DESC_LTH (50)
#define MAX_CEER_VAL_LTH (11)

GLOBAL void getCeerDesc(USHORT cause, char *desc)
{
  SHORT  idx;
  int    val;

  TRACE_FUNCTION("getCeerDesc()");

  memset(desc,0,MAX_CEER_DESC_LTH);

  if ( GET_CAUSE_DEFBY(cause) EQ DEFBY_STD )
  {
    TRACE_EVENT_P1("Cause: %d, defined by standard", cause);
    val = GET_CAUSE_VALUE(cause);

    if ( val EQ NOT_PRESENT_8BIT )
    {
      val = CEER_NotPresent;
    }
    TRACE_EVENT("Get desc from Standard CEER desc table");
    for( idx = 0; StdCEERDesc[idx].desc NEQ NULL; idx++ )
    {
      if ( StdCEERDesc[idx].rpt EQ val )
      {
        memcpy(desc, StdCEERDesc[idx].desc, strlen(StdCEERDesc[idx].desc) );
        return;
      }
    }
  }

  if ( GET_CAUSE_DEFBY(cause) EQ DEFBY_CONDAT )
  {
    if ( GET_CAUSE_ORIGIN_ENTITY(cause) EQ ACI_ORIGINATING_ENTITY )
    {
      TRACE_EVENT_P1("Cause: %d, is ACI proprietary", cause);
      val = GET_CAUSE_VALUE(cause);

      if ( val EQ NOT_PRESENT_8BIT )
      {
        val = P_CEER_NotPresent;
      }
      TRACE_EVENT("Get desc from proprietary ACI CEER desc table");
      for( idx = 0; pACI_CEERDesc[idx].desc NEQ NULL; idx++ )
      {
        if ( pACI_CEERDesc[idx].rpt EQ val )
        {
          memcpy(desc, pACI_CEERDesc[idx].desc, strlen(pACI_CEERDesc[idx].desc) );
          return;
        }
      }
    }
    else if ( GET_CAUSE_ORIGIN_ENTITY(cause) EQ MM_ORIGINATING_ENTITY )
    {
      TRACE_EVENT_P1("Cause: %d, is MM proprietary", cause);
      val = GET_CAUSE_VALUE(cause);

      if ( val EQ NOT_PRESENT_8BIT )
      {
        val = P_MM_CEER_NotPresent;
      }
      TRACE_EVENT("Get desc from proprietary MM CEER desc table");
      for( idx = 0; pMM_CEERDesc[idx].desc NEQ NULL; idx++ )
      {
        if ( pMM_CEERDesc[idx].rpt EQ val )
        {
          memcpy(desc, pMM_CEERDesc[idx].desc, strlen(pMM_CEERDesc[idx].desc) );
          return;
        }
      }
    }
    else if ( GET_CAUSE_ORIGIN_ENTITY(cause) EQ SS_ORIGINATING_ENTITY )
    {
      TRACE_EVENT_P1("Cause: %d, is SS proprietary", cause);
      val = GET_CAUSE_VALUE(cause);

      if ( val EQ NOT_PRESENT_8BIT )
      {
        val = P_SS_CEER_NotPresent;
      }
      TRACE_EVENT("Get desc from proprietary SS CEER desc table");
      for( idx = 0; pSS_CEERDesc[idx].desc NEQ NULL; idx++ )
      {
        if ( pSS_CEERDesc[idx].rpt EQ val )
        {
          memcpy(desc, pSS_CEERDesc[idx].desc, strlen(pSS_CEERDesc[idx].desc) );
          return;
        }
      }
    }
  }
}


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

#ifdef FF_ATI_BAT
  {
    T_BAT_cmd_send cmd;
    T_BAT_no_parameter dummy;

    cmd.ctrl_params=BAT_CMD_SET_PLUS_CEER;
    dummy.bat_dummy = 0xFF;
    cmd.params.ptr_set_plus_ceer = &dummy;
    bat_send(ati_bat_get_client(srcId), &cmd);
    return(ATI_EXCT);
  }
#else /* no FF_ATI_BAT */
  {
    char   desc[MAX_CEER_DESC_LTH];
    T_ACI_RETURN ret;
    USHORT cause;

    ret=qAT_PlusCEER( srcId, &cause );
    if (ret EQ AT_CMPL)
    {
      /* check if description text is available*/
      getCeerDesc(cause, desc);

      if ( desc[0] EQ 0 )
      {
        /* no description text is available */
        sprintf( g_sa, "+CEER: %d,%d,%d,%d",
                 GET_CAUSE_DEFBY(cause), GET_CAUSE_ORIGSIDE(cause),
                 GET_CAUSE_ORIGIN_ENTITY(cause), GET_CAUSE_VALUE(cause));
      }
      else
      {
        /* description text is available */
        sprintf( g_sa, "+CEER: %d,%d,%d,%d,%s",
                 GET_CAUSE_DEFBY(cause), GET_CAUSE_ORIGSIDE(cause),
                 GET_CAUSE_ORIGIN_ENTITY(cause), GET_CAUSE_VALUE(cause),
                 desc );
      }
      io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
      return ATI_CMPL;
    }
    else
    {
      cmdAtError(atError);
      return ATI_FAIL;
    }
  }
#endif /* no FF_ATI_BAT */
}

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

  PURPOSE : Supplementary Service Diagnostic 
*/

GLOBAL T_ATI_RSLT atPercentCSSD(char *cl, UBYTE srcId)
{
  T_ACI_RETURN ret;
  UBYTE ss_diag;
  CHAR *me  =  "%CSSD: ";

  TRACE_FUNCTION("atPercentCSSD()");

  ret = qAT_PercentCSSD( srcId, &ss_diag);

  if (ret EQ AT_CMPL)
  {
    sprintf( g_sa, "%s%d", me, ss_diag );
    io_sendMessage(srcId, g_sa, ATI_NORMAL_OUTPUT);
    return ATI_CMPL;
  }
  else
  {
    cmdAtError(atError);
    return ATI_FAIL;
  }

}

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

  PURPOSE : handle CEER Errors

*/

GLOBAL CHAR *cmdCeerError(USHORT cause)
{
  T_ACI_ERR_DESC aed;
  char desc[MAX_CEER_DESC_LTH];
  UBYTE srcId = srcId_cb;
  
  *ErrBuff = '\0';        /* build message */
  cmdErrStr = ErrBuff;

  if ( GET_CAUSE_VALUE(cause) EQ NOT_PRESENT_8BIT )
  {
    if (((aed = qAT_ErrDesc()) >> 16) EQ ACI_ERR_CLASS_Ceer)
      cause = (T_ACI_CEER)(aed & 0xFFFF);
    else
      cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, ACI_ORIGINATING_ENTITY,
                       CEER_NoError);
  }
  if (ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Verbose)
  {
    sprintf(cmdErrStr, "+CEER ERROR: %d,%d,%d,%d",
            GET_CAUSE_DEFBY(cause), GET_CAUSE_ORIGSIDE(cause),
            GET_CAUSE_ORIGIN_ENTITY(cause), GET_CAUSE_DEFBY(cause));

    getCeerDesc(cause, desc);

    if ( desc[0] NEQ 0 )
    {
      strcat( cmdErrStr, desc);
    }

  }
  return(disable_or_numeric("+CEER",cause));
}

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

  PURPOSE : handle standard AT Errors

*/

GLOBAL CHAR *cmdAtError (AtErrCode e)
{
  SHORT idx=0;

  *ErrBuff = '\0';
  cmdErrStr = ErrBuff;

  /* search for the description of the notified error */
  while ( tabAtError[idx].code NEQ atError AND
          tabAtError[idx].code NEQ e )
  {
    idx++;
  }
  sprintf(cmdErrStr,(at.s1415.atV) ? tabAtError[idx].msg : tabAtError[idx].nmb);
  return cmdErrStr;
}

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

  PURPOSE : General handling of errors (either CME CMS CEER or EXT errors)
            when function returns AT_FAIL

*/
#define ACI_GET_ERR_CLASS() ((aciErrDesc & 0xFFFF0000) >> 16)
#define ACI_GET_ERR_VALUE()  (aciErrDesc & 0x0000FFFF)
#define ACI_RESET_ERR_DESC() (aciErrDesc = 0xFFFFFFFF)
#define ACI_VALID_ERR_DESC() (aciErrDesc NEQ 0xFFFFFFFF)

LOCAL CHAR *AT_Fail_Error(void)
{
  T_ACI_ERR_CLASS err_class;

  if ( ACI_VALID_ERR_DESC() )
  {
    err_class = ACI_GET_ERR_CLASS();
    switch(err_class)
    {
      case(ACI_ERR_CLASS_NotPresent):
        break;
      case(ACI_ERR_CLASS_Cme):
        {
          T_ACI_CME_ERR l_err;

          l_err = ACI_GET_ERR_VALUE();
          ACI_RESET_ERR_DESC();      // needs to be reinitialized
          return(cmdCmeError (l_err));
        }
      case(ACI_ERR_CLASS_Cms):
        {
          T_ACI_CMS_ERR l_err;

          l_err = ACI_GET_ERR_VALUE();
          ACI_RESET_ERR_DESC();      // needs to be reinitialized
          return(cmdCmsError (l_err));
        }
      case(ACI_ERR_CLASS_Ceer):
        {
          T_ACI_CEER l_err;

          l_err = ACI_GET_ERR_VALUE();
          ACI_RESET_ERR_DESC();      // needs to be reinitialized
          /* return(cmdCeerError((USHORT)err)); */
          return(cmdCeerError(l_err));
        }
      case(ACI_ERR_CLASS_Ext):
        {
          T_ACI_EXT_ERR l_err;

          l_err = ACI_GET_ERR_VALUE();
          ACI_RESET_ERR_DESC();      // needs to be reinitialized
          return(cmdExtError (l_err));
        }
      default:
        break;
    }
  }
  *ErrBuff = '\0';
  cmdErrStr = ErrBuff;

  return (cmdCmeError(CME_ERR_NotPresent));
}

#endif /* ATI_ERR_C */