/* -----------------------------------------------------------------------------
  Filename:    desc.c
  Description: Implementation of CANdesc.
                
                Manufacturer: Vector
                EcuDocFile:   C:\1_sangshulin\SVN\V2X\30_DevelopLibrary\03_SW\99_Others\CANbedded\Geny_For_CanMatrix5_1\Tbox4.00.cdd
                Variant:      Base_Variant

  Generated by CANdelaGen, Fri Oct 16 10:47:20 2020
 
 ----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
  C O P Y R I G H T
 -------------------------------------------------------------------------------
  Copyright (c) 2001-2013 by Vector Informatik GmbH. All rights reserved.
 
  This software is copyright protected and proprietary to Vector Informatik 
  GmbH.
  
  Vector Informatik GmbH grants to you only those rights as set out in the 
  license conditions.
  
  All other rights remain with Vector Informatik GmbH.
 -------------------------------------------------------------------------------
 ----------------------------------------------------------------------------- */

/* -----------------------------------------------------------------------------
    &&&~ Includes
 ----------------------------------------------------------------------------- */

/* Physical layer specific API */
#include "v_inc.h"
/* -- V_NULL Definition -- */
#if !defined(V_NULL)
# define V_NULL                                                      0
#endif

#include "desc.h"
#include "appdesc.h"

/*lint -function(exit,ApplDescFatalError)*/

#if defined (DESC_ENABLE_DOBT_SUPPORT)
/* include of DOBT (Diagnostic Onboard Tester) prototypes */
# include "dobt.h"
#endif



/* -----------------------------------------------------------------------------
    &&&~ Configuration switches
 ----------------------------------------------------------------------------- */

/* Default settings */
#if !defined(DESC_ENABLE_EXTERNAL_CHECK_TA) && \
    !defined(DESC_DISABLE_EXTERNAL_CHECK_TA)
# define DESC_DISABLE_EXTERNAL_CHECK_TA
#endif

#define DESC_DISABLE_MULTI_TP_CHANNEL_SUPPORT
/* By default there is need of this switch */
#if !(defined (DESC_ENABLE_OEM_MH_MULTI_CALL_PROTECTION) || \
    defined (DESC_DISABLE_OEM_MH_MULTI_CALL_PROTECTION))
# define DESC_ENABLE_OEM_MH_MULTI_CALL_PROTECTION
#endif

#if defined (DESC_ENABLE_PID_LIST_MODE) || \
    defined (DESC_ENABLE_SIM_PID_LIST_MODE) || \
    defined (DESC_ENABLE_PERIODIC_MODE) || \
    defined (DESC_ENABLE_ROUTINE_CONTROL_MODE) || \
    defined (DESC_ENABLE_MEMORY_BY_ADDRESS_MODE)
# define DESC_ENABLE_PROCESSING_DONE_REDIRECTOR
#else
# define DESC_DISABLE_PROCESSING_DONE_REDIRECTOR
#endif

#if (defined (DESC_ENABLE_SA_STATIC_SEED) && (kDescNumStateSecurityAccess > 2)) || \
    defined (DESC_ENABLE_MULTIPLE_SEED_LENGTH)
# define DESC_ENABLE_SA_MULTI_SEED_OBJ
#else
# define DESC_DISABLE_SA_MULTI_SEED_OBJ
#endif



/* -----------------------------------------------------------------------------
    &&&~ Preprocessor constants (defines)
 ----------------------------------------------------------------------------- */

#define DESC_MAIN_VERSION                                            0x06
#define DESC_SUB_VERSION                                             0x33
#define DESC_BUGFIX_VERSION                                          0x00
/* Compatibility for older versions */
#if !defined(VSTDLIB__COREHLL_VERSION)
# define VSTDLIB__COREHLL_VERSION                                    0x00
#endif

#if (VSTDLIB__COREHLL_VERSION >= 0x216) && \
    defined (VSTD_ENABLE_INTCTRL_HANDLING)
/* VStdLib will be used */
# define DescInterruptDisable()                                      VStdSuspendAllInterrupts()
# define DescInterruptRestore()                                      VStdResumeAllInterrupts()
#else
# define DescInterruptDisable()                                      (CanGlobalInterruptDisable())
# define DescInterruptRestore()                                      (CanGlobalInterruptRestore())
#endif

#define EVER                                                         (;;)
#ifndef V_BOOL_EXPR
# define V_BOOL_EXPR(exp)                                            ((DescBool)((exp)?kDescTrue:kDescFalse))
#endif

/* This magic number provides inter CANdesc generation process consistency check.All CANdesc files must have the same one. */
#define DESC_IMPLEMENTATION_MAGIC_NUMBER                             25928

#if defined (DESC_ENABLE_DEBUG_USER ) || defined (DESC_ENABLE_DEBUG_INTERNAL)
# define kDescDebugPatternLen                                        2
#else
# define kDescDebugPatternLen                                        0
#endif

/* patterns for owerwrite tests */
#define kDescAssertBufferLenPattern0                                 (vuint8)0xbe
#define kDescAssertBufferLenPattern1                                 (vuint8)0xda

/* Generation consitency check */
#if (DESC_PUBLIC_INTERFACE_MAGIC_NUMBER != DESC_IMPLEMENTATION_MAGIC_NUMBER)
# error "Desc.h doesn't match the Desc.c generation time!"
#endif

#if (DESC_APPLICATION_INTERFACE_MAGIC_NUMBER != DESC_IMPLEMENTATION_MAGIC_NUMBER)
# error "AppDesc.h doesn't match the Desc.c generation time!"
#endif

#if defined(VGEN_ENABLE_VSTDLIB) || defined(V_ENABLE_VSTDLIB)
/* VStdLib is available */
#else
# error "Error in File v_cfg.h: V_ENABLE_VSTDLIB (VGEN_ENABLE_VSTDLIB) must be defined!"
#endif

#if defined(DESC_ENABLE_PID_NRC_ALL_ON_WRONG_SESSION) && \
    !defined(DESC_ENABLE_SKIP_PID_ON_WRONG_SESSION)
# error "Required switch DESC_ENABLE_SKIP_PID_ON_WRONG_SESSION not set!"
#endif

#if defined (DESC_ENABLE_PARALLEL_OBD)
# define kDescTpNumContexts                                          2
#else
# define kDescTpNumContexts                                          1
#endif

#if defined (DESC_ENABLE_PARALLEL_OBD)
# define DESC_TPCONTEXT_PARAM_TYPE_ONLY                              vuint8
# define DESC_TPCONTEXT_PARAM_TYPE_FIRST                             vuint8,
# define DESC_TPCONTEXT_PARAM_VALUE                                  tpContext
# define DESC_TPCONTEXT_PARAM_ONLY                                   tpContext
# define DESC_TPCONTEXT_PARAM_FIRST                                  tpContext,
# define DESC_TPCONTEXT_FORMAL_PARAM_DEF_ONLY                        DESC_TPCONTEXT_PARAM_TYPE_ONLY DESC_TPCONTEXT_PARAM_ONLY
# define DESC_TPCONTEXT_PARAM_DEF_LOCAL                              DESC_TPCONTEXT_FORMAL_PARAM_DEF_ONLY;
# define DESC_TPCONTEXT_FORMAL_PARAM_DEF_FIRST                       DESC_TPCONTEXT_PARAM_TYPE_ONLY DESC_TPCONTEXT_PARAM_ONLY,
# define DESC_TPCONTEXT_PARAM_WRAPPER_ONLY(contextConst)             contextConst
# define DESC_TPCONTEXT_PARAM_WRAPPER_FIRST(contextConst)            contextConst,
# define DESC_TPCONTEXT_PARAM_WRAPPER_INDEX(contextConst)            contextConst
# define DESC_TPCONTEXT_PARAM_DUMMY_USE                              DESC_IGNORE_UNREF_PARAM(DESC_TPCONTEXT_PARAM_ONLY)
#else
# define DESC_TPCONTEXT_PARAM_TYPE_ONLY                              void
# define DESC_TPCONTEXT_PARAM_TYPE_FIRST
# define DESC_TPCONTEXT_PARAM_VALUE                                  ((vuint8)0)
# define DESC_TPCONTEXT_PARAM_ONLY
# define DESC_TPCONTEXT_PARAM_FIRST
# define DESC_TPCONTEXT_FORMAL_PARAM_DEF_ONLY                        void
# define DESC_TPCONTEXT_FORMAL_PARAM_DEF_FIRST
# define DESC_TPCONTEXT_PARAM_DEF_LOCAL
# define DESC_TPCONTEXT_PARAM_WRAPPER_ONLY(contextConst)
# define DESC_TPCONTEXT_PARAM_WRAPPER_FIRST(contextConst)
# define DESC_TPCONTEXT_PARAM_WRAPPER_INDEX(contextConst)            0
# define DESC_TPCONTEXT_PARAM_DUMMY_USE
#endif

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
# define kDescDebugNeedTpRxChannel_BusyRepReq                        1
# define kDescDebugNeedTpTxChannel_BusyRepReq                        1
#else
# define kDescDebugNeedTpRxChannel_BusyRepReq                        0
# define kDescDebugNeedTpTxChannel_BusyRepReq                        0
#endif

#if defined (DESC_ENABLE_PARALLEL_OBD)
# define kDescDebugNeedTpRxChannel_ParallelObd                       1
# define kDescDebugNeedTpTxChannel_ParallelObd                       1
#else
# define kDescDebugNeedTpRxChannel_ParallelObd                       0
# define kDescDebugNeedTpTxChannel_ParallelObd                       0
#endif

/* Check if TP has enough communication channels */
#define kDescNeededRxTpChannels                                      (kDescDebugNeedTpRxChannel_BusyRepReq + kDescDebugNeedTpRxChannel_ParallelObd + 1)
#define kDescNeededTxTpChannels                                      (kDescDebugNeedTpTxChannel_BusyRepReq + kDescDebugNeedTpTxChannel_ParallelObd + 1)

/* Use defaults */
/* CAN channel to TP-channel mapping */
#if !defined(kDescCan2TpChannel_0)
# define kDescCan2TpChannel_0                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_1)
# define kDescCan2TpChannel_1                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_2)
# define kDescCan2TpChannel_2                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_3)
# define kDescCan2TpChannel_3                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_4)
# define kDescCan2TpChannel_4                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_5)
# define kDescCan2TpChannel_5                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_6)
# define kDescCan2TpChannel_6                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_7)
# define kDescCan2TpChannel_7                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_8)
# define kDescCan2TpChannel_8                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_9)
# define kDescCan2TpChannel_9                                        kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_10)
# define kDescCan2TpChannel_10                                       kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_11)
# define kDescCan2TpChannel_11                                       kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_12)
# define kDescCan2TpChannel_12                                       kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_13)
# define kDescCan2TpChannel_13                                       kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_14)
# define kDescCan2TpChannel_14                                       kTpNoChannel
#endif
#if !defined(kDescCan2TpChannel_15)
# define kDescCan2TpChannel_15                                       kTpNoChannel
#endif


#if defined (TP_ECU_NUMBER)
# define kDescEcuNumber                                              TP_ECU_NUMBER /* Use the simple macro */
#else
# define kDescEcuNumber                                              (TP_RX_ECU_NR(0))
#endif

#if defined (DESC_ENABLE_PARALLEL_OBD)
# define kDescUsdtNetFuncInfPoolRef                                  (vuintx)(kTpRxChannelCount)
#else
# define kDescUsdtNetFuncInfPoolRef                                  kDescPrimContext
#endif
#define kDescUsdtNetSecInfoPool                                      (vuintx)(kDescNumContexts - 1)

#if defined (DESC_ENABLE_PARALLEL_OBD)
# define DescGetConnectionOfContext(tpContext)                       (g_descDescConnections[tpContext])
#else
# define DescGetConnectionOfContext(tpContext)                       kDescDiagConnection
#endif

#if defined (DESC_ENABLE_DOBT_SUPPORT)
# define DanisIsoTpTransmit(TP_CHANNEL_TX_PARAM_NAME, dataPtr, dataLen) (DOBTTransmit(TP_CHANNEL_TX_PARAM_FIRST (dataPtr), (dataLen)))
#else
# define DanisIsoTpTransmit(TP_CHANNEL_TX_PARAM_NAME, dataPtr, dataLen) (TpTransmit(TP_CHANNEL_TX_PARAM_FIRST (dataPtr), (dataLen)))
#endif

#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# define TP_CHANNEL_RX_PARAM_VALUE                                   TP_CHANNEL_RX_PARAM_NAME
# define TP_CHANNEL_RX_PARAM_ONLY                                    TP_CHANNEL_RX_PARAM_NAME
# define TP_CHANNEL_RX_PARAM_FIRST                                   TP_CHANNEL_RX_PARAM_NAME,

# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
#  define TP_CHANNEL_TX_PARAM_VALUE                                  TP_CHANNEL_TX_PARAM_NAME
#  define TP_CHANNEL_TX_PARAM_ONLY                                   TP_CHANNEL_TX_PARAM_NAME
#  define TP_CHANNEL_TX_PARAM_FIRST                                  TP_CHANNEL_TX_PARAM_NAME,
# else
#  if defined(DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND)
#   define TP_CHANNEL_TX_PARAM_VALUE                                 TP_CHANNEL_TX_PARAM_NAME
#  else
#   define TP_CHANNEL_TX_PARAM_VALUE                                 0
#  endif
#  define TP_CHANNEL_TX_PARAM_ONLY                                   TP_CHANNEL_TX_PARAM_VALUE
#  define TP_CHANNEL_TX_PARAM_FIRST                                  TP_CHANNEL_TX_PARAM_VALUE,
# endif
#else
# define TP_CHANNEL_RX_PARAM_VALUE                                   0
# define TP_CHANNEL_RX_PARAM_ONLY
# define TP_CHANNEL_RX_PARAM_FIRST
# define TP_CHANNEL_TX_PARAM_VALUE                                   0
# define TP_CHANNEL_TX_PARAM_ONLY
# define TP_CHANNEL_TX_PARAM_FIRST
# define tpTxChannel                                                 0
# define tpRxChannel                                                 0
#endif
/* check TPMC settings */
#if defined (VGEN_ENABLE_TP_ISO_MC)
# if (kTpRxChannelCount < kDescNeededRxTpChannels)
#  error "Not enough TP channels, please increase the number of Rx channels under TP Options!"
# endif

# if (kTpTxChannelCount < kDescNeededTxTpChannels)
#  error "Not enough TP channels, please increase the number of Tx channels under TP Options!"
# endif
#endif

#if defined (TP_ENABLE_EXTENDED_ADDRESSING) && !defined (TP_DISABLE_CHECKTA_COMPATIBILITY)
# error "Extended Addressing requires the a newer version of TPMC in combination with a newer GenTool"
#endif

#if defined( DESC_ENABLE_OVERRIDE_TP_MA_CHECK)
#else
# if defined(TP_ENABLE_MULTIPLE_ADDRESSING)
#  if(defined(TP_ENABLE_MIXED_11_ADDRESSING) && \
     defined(TP_ENABLE_NORMAL_ADDRESSING))  || \
     (defined(TP_ENABLE_EXTENDED_ADDRESSING) && \
     defined(TP_ENABLE_NORMAL_ADDRESSING))
/* OK */
#  else
#   error "Not supported yet!"
#  endif
# endif
#endif

#if defined(DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND) && defined (DESC_ENABLE_PARALLEL_OBD)
# error "Multi CAN workaround can not be used together with parallel OBD feature!"
#endif

#if defined(DESC_ENABLE_BUSY_REPEAT_RESPONDER)
# if (defined(TP_ENABLE_DYNAMIC_CHANNELS) && \
     defined(DESC_USDTNET_ENABLE_MULTI_TP) && \
     (defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING) || \
     defined (TP_ENABLE_NORMAL_ADDRESSING)))
/* OK */
# else
#  error "BusyRepeatRequest only allowed with Dynamic Normal Addressing Multi TP or Dynamic Normal Fixed Addressing Multi TP"
# endif
#endif

/* All functions are internal - generate the static declarator. */
#define DESCNET_USDT_STATIC                                          static
/* Used for additional information about each network */
#define kDescUsdtNetInvalidDescContext                               (t_descHandle)(0xFF)

/* Current diagnostic connection status */
#define kDescDescConnectionStateIdle                                 ((vuint8)0x00)
#define kDescDescConnectionStateActive                               ((vuint8)0x01)

#if !defined (kDescNrcResponsePending)
# define kDescNrcResponsePending                                     0x78
#endif

#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE)
# define kDescReadDynPidConnStateActive                              ((vuint8)(kDescDescConnectionStateActive<<kDescReadDynPidContext))
#else
# define kDescReadDynPidConnStateActive                              ((vuint8)(0))
#endif
#if defined (DESC_ENABLE_ROE_SUPPORT)
# define kDescRoeConnStateActive                                     ((vuint8)((kDescDescConnectionStateActive<<kDescRoeHelperContext) | \
                                                                     (kDescDescConnectionStateActive<<kDescRoeProcessorContext)))
#else
# define kDescRoeConnStateActive                                     ((vuint8)(0))
#endif

/* Default setting for "response on request" (phys - yes, func - no) */
#define kDescDefaultResOnReq                                         0x01
#define kDescResOnAllReq                                             0x03

/* TP wrapper states */
#define kDescMainReception                                           0x01
#define kDescMainTransmission                                        0x02
#define kDescAddReception                                            0x03
#define kDescAddTransmission                                         0x04


/* Current transfer mode */
#define kDescTxModeIdle                                              0x00
#define kDescTxModeRegularRes                                        0x01
#define kDescTxModeSpecialRes                                        0x02
#define kDescTxModeRcrRpRes                                          0x04
#define kDescTxModePeriodicRes                                       0x08
#define kDescTxModeRoeResponder                                      0x10

/* RCR-RP response descriptor */
#define kDescForcedRcrRpIdle                                         0x00
#define kDescForcedRcrRpCharged                                      0x01

/* Use the worst case for the first frame length (nromal addressing with 6Byte payload) */
#define kDescFirstFrameDataLength                                    6

/* Single frame length calculation (needed for the CopyToCan assertion check)*/
/* The FF has one byte for TP usage more, 
* so the data for SF are with one byte more */
#define kDescSingleFrameDataLength                                   ((vuint8)(kDescFirstFrameDataLength + 1))

#define kDescNumPhysReqParallel                                      1
#define kDescNumFuncReqContexts                                      0
#define kDescNumPhysReqContexts                                      1
/* Transport layer abstract transmission statuses */
#define kDescTxSuccess                                               ((vuint8)kDescUsdtNetworkOk)

/* Table offsets */
#define kDescTimingRefP2                                             0
#define kDescTimingRefP2Star                                         1

#define kDescNrcRejectStateSession                                   kDescNrcSubfunctionNotSupportedInActiveSession
#define kDescNrcRejectStateSecurityAccess                            kDescNrcAccessDenied
#define kDescStateGroupNumTransition                                  8
#define kDescStateNoTransition                                       ((DescSetStateIndex)kDescStateGroupNumTransition)

/* SecuredDataTransmission negative response code start number */
#define kDescNrcSecuredDataTransNrcOffset                            0x38

#define kDescNumSvcHeadConstGapBits                                  5
/* The biggest hexadecimal digit as a SID configured for this ECU. */
#define kDescMaxReqSid                                               0x85
/* The size of the index search table. */
#define kDescSvcIdMapSize                                            70
/* SvcHead table size. */
#define kDescSvcHeadNumItems                                         17
/* SvcInst table size. */
#define kDescSvcInstNumItems                                         46
/* SvcInstHeadEx table size. */
#define kDescSvcInstHeadExtNumItems                                  62
/* Context modes */
#define kDescContextModeNormal                                       0x00
#define kDescContextModePidList                                      0x01
#define kDescContextModePeriodic                                     0x02
#define kDescContextModeRoutineControl                               0x03
#define kDescContextModeMemByAddr                                    0x04


#define kDescInvalidSvcHandle                                        (DescSvcHeadIndex)kDescSvcHeadNumItems
#define kDescInvalidSvcInstHandle                                    (DescSvcInstIndex)kDescSvcInstNumItems

/*  Negative response service ID */
#define kDescNegResSId                                               0x7F

/* Default settings for the bit structure */
#if defined(kDescNumStateSession)
#else
# define kDescNumStateSession                                        0
#endif

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
# define DescExtractReqExtHeadLen(reqExtHeadLen)                     (reqExtHeadLen)
# define DescExtractResExtHeadLen(resExtHeadLen)                     (resExtHeadLen)
#else
# define DescExtractReqExtHeadLen(reqExtHeadLen)                     0
# define DescExtractResExtHeadLen(resExtHeadLen)                     0
#endif

#if !defined (kDescOemNrcParamIdNotSupportedInSession)
# define kDescOemNrcParamIdNotSupportedInSession                     kDescNrcRequestOutOfRange
#endif

#if !defined (kDescOemNrcParamIdNotSupportedInSecurityState)
# define kDescOemNrcParamIdNotSupportedInSecurityState               kDescNrcAccessDenied
#endif


/*  Length of negative response message */
#define kDescNegResLen                                               ((DescMsgLen)3)
/*  Positive response service ID offset */
#define kDescPosResIdOffset                                          ((vuint8)0x40)

#define kDescNumPreHandlers                                          5
#define kDescNumPostHandlers                                         7
/* Stores the reference of the SvcInstTable entry for the service which stops sessions (starts default session). */
#define kDescDefaultSessionSvcInstEntry                              0
/* No NRCs additionally suppressed */
#define DESC_ADD_SUPPRESSED_FUNC_NRC                                 case 0x7f: case 0x7e:

/* The first entry of the SessionControl service is to be found at this position (g_descSvcHead table). */
#define kDescSvcHeadOffsetSDS                                        0
/* The first entry of the SessionControl service is to be found at this position (g_descSvcInst table). */
#define kDescSvcInstOffsetSDS                                        0
/* No NRCs additionally suppressed */
#define DESC_OEM_SUPPRESSED_FUNC_NRC                                 /* Fall through */

/* Security access seed maximum length */
#define kDescSecurityAccessMaxSeedLength                             (vuint8) 64

/* Must not be greater 255 since a byte counter is used */
/* todo: check this setting in the generator!!!*/

#define kDescNumPids                                                 45
/* Invalid handle after PID lookup */
#define kDescInvalidPidHandle                                        ((DescMemPidInstIndex)kDescNumPids)

#define kDescNumRids                                                 7
#define kDescNumRidInst                                              7
#define kDescNumRidControlTypes                                      1
/* Invalid handle after RID lookup */
#define kDescInvalidRidHandle                                        ((DescMemRidLookUpIndex)kDescNumRids)
/* Invalid routine instance handle */
#define kDescInvalidRidInstHandle                                    ((DescMemRidInstIndex)kDescNumRidInst)

/* Multiple PIDs processing specific NRC on too long response. */
#define kDescOemNrcResponseTooLong                                   kDescNrcResponseTooLong
/* Multiple PIDs processing specific NRC on too many PID in single request. */
#define kDescOemNrcTooManyPIDs                                       kDescNrcInvalidFormat
/* Precalculated bit field length (in bytes)*/
#define kDescNumPostHdlrQueueBytes                                   (((kDescNumMaxPidList - 1)/ 8) + 1)
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
/* Do not hide the PID */
# define kDescReservedBytesForPid                                    0
#else
/* Do hide the PID */
# define kDescReservedBytesForPid                                    2
#endif



/* -----------------------------------------------------------------------------
    &&&~ Datatype definitions
 ----------------------------------------------------------------------------- */

/*-- TP information types  --*/
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
typedef struct
{
  vuint8 resBuffer[3];
  vuint8 tpRxChannel;
} DescAddResBuffer;

typedef union
{
  vuint8           reqBuffer[7];
  DescAddResBuffer res;
} DescAddBuffer;

typedef struct
{
  vuint8        status;
  DescAddBuffer buffers;
} DescAddChannel;

typedef struct
{
  vuint8         count;
  DescAddChannel channel[kDescNumAddRequestChannels];
} DescAddChannelCtrl;

#endif /* defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)*/

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
typedef struct
{
  DescBitType type:4;
  DescBitType info:4;
} DescTpMemberCtrl;

typedef struct
{
  DescTpMemberCtrl rxPath[kTpRxChannelCount];
  DescTpMemberCtrl txPath[kTpTxChannelCount];
} DescTpCtrl;
#endif /* defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER) */

/* forward declaration of t_descUsdtNetInfoPool */
typedef struct t_descUsdtNetInfoPoolTag t_descUsdtNetInfoPool;
typedef struct t_descUsdtNetInfoPoolTag* t_descUsdtNetInfoPoolPtr;
/* Network dependent data type */
struct t_descUsdtNetInfoPoolTag
{
  t_descUsdtNetBus        busInfo;
  t_descUsdtNetReqType    reqType;
  t_descUsdtNetResType    resType;
  t_descUsdtNetBusHandle  busHandle;
  t_descHandle            descHandle;
  vuint16                 dataLength;

  DescUsdtNetMsg          reqDataPtr;
  DescUsdtNetMsg          resDataPtr;
};

/* ---- Context management state machine ---- */
typedef struct
{
  t_descUsdtNetResult txState;/* Tp ErrorCode */
  DescBitType         contextMode                :3;/* 0x00 - Normal, 0x01 - PIDListProcess */
  DescBitType         isApplError                :1;/* 0x00 - CANdesc NR, 0x01 - APPL NR */
  DescBitType         isSupplPost                :1;/* 0x00 - CANdesc NR, 0x01 - SUPPL NR */
  DescBitType         isSPRMIBOverridden         :1;/* 0x00 - SPRMIB is not overridden, 0x01 - SPRMIB is orverridden*/
  DescBitType         dummy                      :2;
} DescContextCtrl;

/* ---- Interrupt context management state machine ---- */
typedef struct
{
  t_descUsdtNetInfoPoolPtr infoPoolPtr;
  vuint8             activity                 ;/* 0x00 - Idle, 0x01 - ActiveRx, 0x02 - ActiveProcess, 0x04 - ActiveTxSingleResponse ,0x08 - ActiveTxPeriodicRes, 0x10 - ActiveTxRoeResponder */
#if defined (DESC_ENABLE_FORCE_RCR_RP)
  DescBitType        forcedRcrRpState       :2;/* 0x00 - Idle, 0x01 - Charged, 0x02 - WaitConfirmation */
#endif
#if defined(DESC_ENABLE_ALL_RES_AFTER_RCRRP)
  DescBitType        rcrRpSent              :1;/* 0x00 - not sent, 0x01 - sent */
#endif
  DescBitType        isContextLocked        :1;
} DescInterruptContextCtrl;

/* ---  Timer definitions with 8 Bit CPU optimization  --- */
/* Time T2: */
/* if at least 16 bit CPU - use always 16 bit variables */
/* Time S1: */
typedef vuint16 DescS1Timer;
/* Time T2: */
typedef vuint16 DescT2Timer;

#if defined (DESC_ENABLE_RES_PENDING_TIME_LIMIT) || defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
/* type definition for Response pending limit timer */
typedef vuint16 DescRcrrpLimitTimer;
#endif

typedef struct DescStateInfoTag
{
  DescStateGroup stateSecurityAccess : 5;
  DescStateGroup stateSession : 3;
} DescStateInfo;
#if (kDescStateGroupNumTransition > 255)
  typedef vuint16    DescSetStateIndex;
#else
  typedef vuint8     DescSetStateIndex;
#endif

typedef vuint8 DescSvcHeadIndex; /* Typedef for the SvcHead table indexes- 8/16Bit depeding on its size. */
typedef vuint8_least DescSvcInstIndex; /* Type definition for the SvcInstTable indexes, depending on the SvcInstTable size. */
typedef vuint8 DescMemSvcInstIndex; /* Type definition for the DescMemSvcInstIndex indexes, depending on the SvcInstTable size. */
typedef vuint8 DescPreHandlerIndex; /* Type definition for the Pre-handler reference table, depending on its size. */
typedef vuint8 DescPostHandlerIndex; /* Type definition for the Post-handler reference table, depending on its size. */
typedef vuint8_least DescSvcInstHeadExtIndex; /* Type definition for the SvcInstHeadExtTable indexes, depending on the SvcInstTable size. */
typedef vuint8 DescMemSvcInstHeadExtIndex; /* Type definition for the DescMemSvcInstHeadExtIndex indexes, depending on the SvcInstTable size. */
/* Application callbacks (main handler is already defiend in  the desc.h (because of MSCall)) */
typedef void DESC_API_CALL_TYPE (*DescPreHandler)      (DESC_CONTEXT_PARAM_TYPE_ONLY);
typedef void DESC_API_CALL_TYPE (*DescPostHandler)     (DESC_CONTEXT_PARAM_TYPE_FIRST vuint8);

typedef struct
{
  DescBitType                reqHeadByteSpec   :8; /* Each bit represents sub-function/identifier - 0: identifier; 1: any subfunction */
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
  DescBitType                reqHeadExLen      :4; /* Request HeadEx length up to 7 Byte  */
  DescBitType                resHeadExLen      :4; /* Response HeadEx length up to 7 Byte */
#endif
#if defined (DESC_ENABLE_ADDR_METHOD_CHECK)
  DescBitType             reqType           :2; /* 0x01: Phys 0x02: Func */
  DescBitType             resOnReq          :2; /* 0x01: Phys 0x02: Func */
#endif
  DescBitType             suppPosRes        :1; /* 0x00: No   0x01: Yes  */
  DescBitType             isReqHeadExtEchoed:1; /* 0x00: No   0x01: Yes  */
  DescBitType             hasSubFunction    :1; /* 0x00: No   0x01: Yes  */
#if (kDescNumSvcHeadConstGapBits > 0)
  DescBitType             svcHeadPlaceHolder:kDescNumSvcHeadConstGapBits; /* Gap holder  */
#endif
#if defined (DESC_ENABLE_AUTO_STATES)
# if defined (DESC_ENABLE_ALL_STATEGROUPS_SID_CHECK)
  DescStateInfo           checkState;
# else
#  if (kDescNumStateSession > 0)
  DescStateGroup          checkSessionState :kDescNumStateSession;/* State group Session on SId level */
#   if (kDescNumSvcHeadSessionGapBits > 0)
  DescBitType             sessionPlaceHolder:kDescNumSvcHeadSessionGapBits; /* Gap holder  */
#   endif
#  endif
# endif
#endif
#if defined (DESC_ENABLE_MIN_REQ_LEN_CHECK) && \
    defined (DESC_ENABLE_SUB_SVC_USAGE)
  vuint8                  minReqLength;
#endif
#if defined (DESC_ENABLE_MULTI_VARIANT)
  DescVariantMask         variantMask;
#endif
/* First item in Service Instance table */
  DescMemSvcInstIndex        svcInstFirstItem;
  DescMemSvcInstHeadExtIndex svcInstHeadExtFirstItem;
} DescSvcHead;

typedef struct
{
  DescMsgLen             reqLen;
#if defined (DESC_ENABLE_ADDR_METHOD_CHECK)
  DescMsgAddInfo         msgAddInfo;
#endif
#if defined (DESC_ENABLE_AUTO_STATES)
  DescStateInfo          checkState;
# if (kDescStateGroupNumTransition > 0)
  DescSetStateIndex      setStateIndex;
# endif
#endif /* DESC_ENABLE_AUTO_STATES */
#if defined (DESC_ENABLE_MULTI_VARIANT)
  DescVariantMask        variantMask;
#endif
#if defined (DESC_ENABLE_PREHANDLER_USAGE)
  DescPreHandlerIndex    preHandlerRef;
#endif
#if defined (DESC_ENABLE_POSTHANDLER_USAGE)
  DescPostHandlerIndex   postHandlerRef;
#endif
  DescMainHandler        mainHandler;
} DescSvcInst;

typedef vuint8_least DescPidInstIndex;
typedef vuint8 DescMemPidInstIndex;
typedef enum
{
  pmAnalyseReasonNone = 0,
  pmAnalyseReasonSession,
  pmAnalyseReasonSecurityState,
  pmAnalyseReasonOther
}DescPidAnalyseFailureReason;

typedef enum
{
  pmClientReadOnce = 0,
  pmClientReadCycle,
  pmClientDynDefine
}DescPidClient;

typedef struct
{
#if defined (DESC_ENABLE_AUTO_STATES)
  DescStateInfo        checkState;
#endif /* DESC_ENABLE_AUTO_STATES */
#if defined (DESC_ENABLE_PID_PREHANDLER_USAGE)
  DescPreHandlerIndex  preHandlerRef;
#endif
  DescMsgAddInfo       msgAddInfo;
#if defined (DESC_ENABLE_MULTI_VARIANT)
  DescVariantMask      variantMask;
#endif
}DescPidTinyInfo;

typedef struct
{
  DescMemPidInstIndex  pidHandle;
  DescPidTinyInfo      tinyInfo;
}DescPidClientInfo;

typedef struct
{
  vuint16              reqPid;
#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE) || \
    defined(DESC_ENABLE_PID_LIST_MODE)        || \
    defined(DESC_ENABLE_DYN_DEFINED_DPID_MODE)
  DescMsgLen           resDataLen;
#endif
  DescPidTinyInfo      tinyInfo;
#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
  DescPostHandlerIndex postHandlerRef;
#endif
  DescMainHandler      mainHandler;
} DescPidInst;

typedef vuint8_least DescRidLookUpIndex;
typedef vuint8 DescMemRidLookUpIndex;
typedef vuint8_least DescRidInstIndex;
typedef vuint8 DescMemRidInstIndex;
typedef vuint8_least  DescRidControlType;
typedef struct
{
#if defined (DESC_ENABLE_AUTO_STATES)
  DescStateInfo        checkState;
#endif /* DESC_ENABLE_AUTO_STATES */
#if defined (DESC_ENABLE_RID_PREHANDLER_USAGE)
  DescPreHandlerIndex  preHandlerRef;
#endif
  DescMsgAddInfo       msgAddInfo;
#if defined (DESC_ENABLE_MULTI_VARIANT)
  DescVariantMask      variantMask;
#endif
}DescRidTinyInfo;

typedef struct
{
  DescMsgLen           reqDataLen; /* contains the RID and the request parameters' length only*/
  DescRidTinyInfo      tinyInfo;
#if defined (DESC_ENABLE_RID_POSTHANDLER_USAGE)
  DescPostHandlerIndex postHandlerRef;
#endif
  DescMainHandler      mainHandler;
} DescRidInst;

typedef struct
{
  DescBitType    pidCount            :8;
  DescBitType    curPid              :8;
  DescBitType    isPidReady          :1;
  DescBitType    isPidProcessed      :1;
  DescBitType    isSpaceRequired     :1;
  DescBitType    dummyGap            :5;
}DescPidProcessorState;



/* -----------------------------------------------------------------------------
    &&&~ Function prototypes
 ----------------------------------------------------------------------------- */

#if defined (DESC_ENABLE_DEBUG_INTERNAL )
static void CheckTableConsistency(void);
#endif
#if defined (DESC_ENABLE_DEBUG_USER ) || defined (DESC_ENABLE_DEBUG_INTERNAL)
static void DescDebugIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#endif

DESCNET_USDT_STATIC void DescUsdtNetIsoTpInitPowerOn(void);
DESCNET_USDT_STATIC void DescUsdtNetIsoTpInit(void);

DESCNET_USDT_STATIC void DescUsdtNetIsoTpStateTask(void);

DESCNET_USDT_STATIC void DescUsdtNetIsoTpPrepareResponse(t_descUsdtNetInfoPoolPtr infoPool);
DESCNET_USDT_STATIC void DescUsdtNetIsoTpTransmitResponse(t_descUsdtNetInfoPoolPtr infoPool);
DESCNET_USDT_STATIC void DescUsdtNetIsoTpReleaseInfoPool(t_descUsdtNetInfoPoolPtr infoPool);

#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
DESCNET_USDT_STATIC vuint16 DescUsdtNetIsoTpGetRingBuffTxMinLen(t_descUsdtNetInfoPoolPtr infoPool);
#endif

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
static void DescBusyResponseHandler(void);
#endif
#if defined (DESC_ENABLE_PARALLEL_OBD)
static vuint8 DescDispatchServiceContext(vuint8 sid);
#endif
static void DescUsdtNetIsoTpInitContext(DESC_TPCONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescUsdtNetIsoTpCopyToCan(TpCopyToCanInfoStructPtr infoStruct);

#if defined(DESC_USDTNET_ENABLE_LONGSERVICE_SUPPORT)
DESCNET_USDT_STATIC void                DescUsdtNetLSFinishReception         (t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status);
DESCNET_USDT_STATIC void                DescUsdtNetLSFinishTransmission      (t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status);
DESCNET_USDT_STATIC t_descUsdtNetResult DescUsdtNetLSStartReception          (t_descUsdtNetInfoPoolPtr infoPool);
/* Copy data from ringbuffer into network layer */
# if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
DESCNET_USDT_STATIC t_descUsdtNetResult DescUsdtNetLSRingBufferCopyRoutine   (t_descUsdtNetInfoPoolPtr infoPool, DescUsdtNetMsg pDestination, vuint8 dataLength);
# endif
#endif
/* Call backs */
DESCNET_USDT_STATIC void                DescUsdtNetAbsFinishReception         (t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status);
DESCNET_USDT_STATIC void                DescUsdtNetAbsFinishTransmission      (t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status);
DESCNET_USDT_STATIC t_descUsdtNetResult DescUsdtNetAbsStartReception          (t_descUsdtNetInfoPoolPtr infoPool);
/* Copy data from ringbuffer into network layer */
#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
DESCNET_USDT_STATIC t_descUsdtNetResult DescUsdtNetAbsRingBufferCopyRoutine   (t_descUsdtNetInfoPoolPtr infoPool, DescUsdtNetMsg pDestination, vuint8 dataLength);
#endif

static void DescNetworkIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

#if defined (DESC_ENABLE_POS_RES_ON_SET_SPRMIB)
# define DescIsTesterPresent(infoPool)                               kDescFalse
#else
static DescBool DescIsTesterPresent(t_descUsdtNetInfoPoolPtr infoPool);
#endif
#if (kDescNumContexts > 1)
static void DescResetConnectionActiveMultipleContext(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#endif

static void DescNetworkInitPowerOn(void);
static void DescNetworkInit(void);

static void DescTransmitRcrRp(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescReleaseContext(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

#if defined (DESC_ENABLE_RES_RINGBUFFER) && defined (DESC_ENABLE_PID_LIST_MODE)
static vuint8 DescGetMaxRestByteSize(DescMsgContext* pMsgContext);
#endif

static void DescTimingOnceInit(void);
static void DescTimingIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
static void DescOemNpmTimer(void);
# endif
static void DescNpmProcessQueue(void);
static void DescNpmSetSleepInd(void);
#endif

#if defined(DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
static vuint8_least DescGetSessionStateBitPosition(DescStateGroup sessionState);
#endif
/* Internal interface of session transition 
 * shall be before the generated code which defines the macro to nothing if
 * if it doesn't exist.
 */
#if defined(DESC_ENABLE_AUTO_STATES)
static void DescOnTransitionStateSession(DescStateGroup newState, DescStateGroup currentState);
#endif

static void DescStateOnceInit(void);

/* ---- Providing interface between subcomponents Dispatch and Network ---- */
static void DescDoPostProcessing(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST t_descUsdtNetResult status);
/* Internal API for INIT */
static void DescDispatcherIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
static DescSvcInstIndex DescFindSvcInst(DescConstPtr reqHeadPtr, V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, vuint8_least* failedByteMask);
#endif
static DescSvcHeadIndex DescFindSvc(DescMsgItem reqSvcId);

static void DescDispatcher(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
static vuint8_least DescGetSvcInstHeadExtEntrySize(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead);
# if defined(C_COMP_NEC_78K0_AFCAN)
static V_MEMROM1 V_MEMROM2 DescMsgItem V_MEMROM3 * DescGetSvcInstReqHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef);
static V_MEMROM1 V_MEMROM2 DescMsgItem V_MEMROM3 * DescGetSvcInstResHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef);
# else
static V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * DescGetSvcInstReqHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef);
static V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * DescGetSvcInstResHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef);
# endif
#endif

#if defined (DESC_ENABLE_PROCESSING_DONE_REDIRECTOR)
static void DescFinalProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#endif

static void DescContextStateTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescResponseTimeoutTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescHandleInternRcrRp(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

static void DESC_API_CALLBACK_TYPE DescOemStartSessionDefault(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemStartSessionProgramming(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemStartSessionExtended(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescReadDataByIdentifier(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_1_Request_Seed(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_1_sendKey_1(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_2_Request_Seed(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_2_sendKey(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_4_Request_Seed(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_4_send_Key(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_5_Request_Seed(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_5_sendKey(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemCommCtrlEnableRxEnableTx(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemCommCtrlEnableRxDisableTx(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescRoutineControlByIdentifier(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescOemProcessTesterPresent(DescMsgContext* pMsgContext);
static void DESC_API_CALLBACK_TYPE DescPostReadDataByIdentifier(vuint8 status);
static void DESC_API_CALLBACK_TYPE DescOemPostCommonCommCtrlProcess(vuint8 status);
#if defined (DESC_ENABLE_ANY_PREHANDLER_USAGE)
static void DESC_API_CALL_TYPE DescDummyPreHandler(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#endif
#if defined (DESC_ENABLE_ANY_POSTHANDLER_USAGE)
static void DESC_API_CALL_TYPE DescDummyPostHandler(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status);
#endif

static void DescOemCommonCommCtrlProcess(vuint8 reqInfo, DescMsgContext *pMsgContext);
static void DescCommCtrlManipulateCAN(DESC_COMM_CHANNEL_FORMAL_PARAM_DEF_ONLY);
#if defined (DESC_ENABLE_DYN_COM_CTRL_PARAM)
static DescBool DescOemCheckAndExtractCommTypeParam(DescOemCommControlInfo * pCommControlInfo, DescMsgItem comType);
#endif

/* Function prototypes */
static void DescOemPrepareSessionControl(DescMsgContext *pMsgContext, DescStateGroup targetSession);
#if defined (DESC_ENABLE_COMMON_OEM_POST_HANDLER)
static void DescOemCommonSessionPostProcessing(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status, DescStateGroup newSession);
#endif

/* Initialization of the sub-component and timing */
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
static void DescSecurityOnceInitPowerOn(void);
static void DescSecurityAccessTimer(void);
#endif

/* Initialization of the sub-component */
static void DescSecurityOnceInit(void);

/* Common seed/key processors */
static void DescOemSecuritySeed(DescMsgContext* pMsgContext, DescStateGroup requestedSecurityLevel);
static void DescOemSecurityKey(DescMsgContext* pMsgContext, DescStateGroup requestedSecurityLevel);

/* Utility */
#if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)  || \
    defined (DESC_ENABLE_MULTIPLE_KEY_LENGTH) || \
    defined (DESC_ENABLE_SA_MULTI_SEED_OBJ) || \
    defined (DESC_ENABLE_MULTI_CHALLENGE_SECURITY) || \
    defined (DESC_ENABLE_DELAY_TIME_LEVEL_SPECIFIC)
static vuint8_least DescGetLevelIdxOfState(DescStateGroup requestedSecurityLevel);
#endif

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
static void DescRepeaterSecurityAccessGetSeed(DescMsgContext* pMsgContext);
static void DescRepeaterSecurityAccessSendKey(DescMsgContext* pMsgContext);
#endif

static void DescOemOnInvalidReq_27(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

static DescPidInstIndex DescPmGetPidPoolHandle   (vuint16 pid);
static DescPidInstIndex DescPmGetAvailablePidHandle(vuint16 pid);
#if defined(DESC_ENABLE_PERIODIC_MODE)
static DescPidInstIndex DescPmGetSupportedPidClientHandle(vuint16 pid, V_MEMROM1 DescPidClientInfo V_MEMROM2 V_MEMROM3 * pClientInfoTbl, DescPidInstIndex topOfTable);
#endif
#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE) || defined(DESC_ENABLE_PERIODIC_MODE)
static DescPidInstIndex DescPmGetPidClientHandle (DescPidInstIndex pidInfoHandle, V_MEMROM1 DescPidClientInfo V_MEMROM2 V_MEMROM3 * pClientInfoTbl, DescPidInstIndex topOfTable);
#endif
static DescPidAnalyseFailureReason DescPmAnalysePid(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST V_MEMROM1 DescPidTinyInfo V_MEMROM2 V_MEMROM3 * pRefTinyInfo);
#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE) || \
    defined(DESC_ENABLE_PID_LIST_MODE)        || \
    defined(DESC_ENABLE_DYN_DEFINED_DPID_MODE)
static DescMsgLen       DescPmGetPidResponseLen  (DescPidInstIndex pidHandle);
#endif

static DescRidLookUpIndex DescRidFindRoutineId(vuint16 rid);
static DescRidInstIndex   DescRidFindSubFunction(vuint8 subFuncId, DescRidInstIndex ridRef);
static void DescRidAnalyseRoutine(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST V_MEMROM1 DescRidTinyInfo V_MEMROM2 V_MEMROM3 * pRefTinyInfo, DescBool isOnRid);
static void DescRidProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

static void DescIterInitPidListProcessor(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);

static void DescPidProcessorTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescPidProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
static void DescPidDispatcher(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY);
#if defined (DESC_ENABLE_RES_RINGBUFFER)
# if defined (DESC_ENABLE_PID_LIST_MODE)
static void DescPidPrepareNextPid(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint16 currWrittenDataLen);
# endif
#endif



/* -----------------------------------------------------------------------------
    &&&~ RAM definitions
 ----------------------------------------------------------------------------- */

#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
static vuint8 g_descUsdtNetTpTxChannel[kDescTpNumContexts];
# endif
#endif
static t_descUsdtNetInfoPool  g_descUsdtNetInfoPoolIsoTp[kDescNumContexts];
#if defined (DESC_ENABLE_PARALLEL_OBD)
static t_descUsdtNetInfoPoolPtr g_busInfoPoolRxRef[kTpRxChannelCount + 1]; /* rx channels + one functional */
#endif
static t_descUsdtNetInfoPoolPtr g_busInfoPoolTxRef[kTpTxChannelCount];

DESC_USDTNET_PRVT_DEF_VAR_FAR(vuint8) g_descBuffer[kDescTpNumContexts][kDescPrimBufferLen];

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
/* Tp state controller  */
static DescTpCtrl g_descTpCtrl;
#endif
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
/* Parallel request responder state controller
 use memory model specific define, since there are embedded Rx and Tx Buffers insider.
*/
DESC_USDTNET_PRVT_DEF_VAR_FAR(DescAddChannelCtrl) g_descAddChannelCtrl;
#endif

#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
# if defined(C_COMP_COSMIC_MCS12X_MSCAN12) && \
     defined(V_ENABLE_USED_GLOBAL_VAR)
DESC_USDTNET_PRVT_DEF_VAR_FAR(vuint8) g_descCopyToCanData[7];
# endif
#endif

#if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
static vuint8 g_descCanType;
#endif

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
/* In:
* - single channel system - flag for already activated DPM user.
* - multi  channel system - bit mapped register for already activated DPM users (channel specific).
*/
static DescComChannelBitMaskOptType  g_descCanChannelMap;
/* The same meaning of the above bit-map, but used for DPM manipulation at task level */
static DescComChannelBitMaskOptType  g_descCanChannelMapQueue;
#endif
/* Global storage of the user response information */
#if defined (DESC_ENABLE_SPONTANEOUS_RES)
static t_descUsdtNetInfoPool  g_descUsdtNetSpontanResInfoPool;
#endif
/* Extra buffer for the "response pending" negative response */
DESC_PRVT_DEF_VAR_FAR(DescMsgItem) g_descRcrrpBuffer[kDescNumContexts][3];

#if (kDescNumContexts > 1)
/* Each bit represents a diagnostic connection activity (maximum n parallel (n = 8)):
* Bit[  0]: Physical_0
* ..........
* Bit[n-2]: Physical_0
* Bit[n-1]: Functional
*/
static vuint8 g_descActiveRequestsMask;
#endif

DESC_PRVT_DEF_VAR_FAR(vuint8) g_descFblPosRes[6];

/* State machine of each received request */
static DescContextCtrl          g_descContextCtrl[kDescNumContexts];
static DescInterruptContextCtrl g_descInterruptContextCtrl[kDescNumContexts];
#if defined (DESC_ENABLE_ACCESS_TESTER_ADDRESS_API)
static vuint8                   g_descTesterAddress[kDescNumContexts];
#endif

#if defined (DESC_ENABLE_RES_PENDING_TIME_LIMIT) || defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
/* Limitation timer/counter for maximal time window for "response pending" 
* negative responses that will be sent. */
static DescRcrrpLimitTimer g_descRcrrpLimitCounter[kDescNumContexts];
#endif

/* T2 timer for response pending support */
static DescT2Timer  g_descT2Timer[kDescNumContexts];
/* "Tester present" timer */
static DescS1Timer  g_descS1Timer;

#if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
# define kDescP2InitValue                                            (g_descP2TicksTable[g_descCurrSessionNumber][kDescTimingRefP2])
# define kDescP2ReloadValue                                          (g_descP2TicksTable[g_descCurrSessionNumber][kDescTimingRefP2Star])
#else
# define kDescP2InitValue                                            kDescP2Ticks
# define kDescP2ReloadValue                                          kDescP2StarTicks
#endif

#if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
/* Global variable to store the converted session number value */
static vuint8 g_descCurrSessionNumber;
#endif

/* Timer reload event flag */
static DescBool g_descDoReloadS1Timer;

#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
static vuint16 g_descNpmTimer;
#endif

/* State machine of CANdesc described by CANdelaStudio */
static DescStateInfo g_descCurState;

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL) && \
    defined (DESC_ENABLE_OEM_MH_MULTI_CALL_PROTECTION)
static DescBool g_descIsOemMainHdlrAlreadyCalled;
#endif

/* Store the service entry index for the current request */
static DescSvcHeadIndex      g_descCurReqSvc[kDescNumContexts];

/* Store the instance entry index for the current request */
static DescMemSvcInstIndex   g_descCurReqSvcInst[kDescNumContexts];

/* Context information to accompany the complete request processing */
static DescMsgContext     g_descMsgContext[kDescNumContexts];

/* Store detected diagnostic error */
static DescNegResCode     g_descNegResCode[kDescNumContexts];

#if defined (DESC_ENABLE_MAINHANDLER_MULTICALL)
/* Pointer of main handlers */
static DescMainHandler    g_descRecallHandler[kDescNumContexts];
#endif

#if defined(DESC_ENABLE_GENERIC_USER_POST_HANDLER_SUPPORT)
/* Store the SID byte for the application if the post-handler is used */
static DescMsgItem        g_descUserSIdBackup[kDescNumContexts];
#endif


/* Shared communication control info */
static DescOemCommControlInfo  g_descCommControlInfo;


/* Security access sequence state */
static DescBool                   g_descIsKeyAwaited;
static DescSecurityAccessContext  g_descSecurityAccessContext;

#if defined (DESC_ENABLE_SECURITY_ACCESS_DATA)
  static vuint8                   g_securityAccessData[kDescSecurityAccessDataRecordMaxLength];
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
static vuint8                     g_descSecureNrOfAttempts[kDescNumStateSecurityAccess-1];
static vuint16                    g_descSecureTimer[kDescNumStateSecurityAccess-1];
#endif

#if defined (DESC_ENABLE_SA_STATIC_SEED)
static vuint8                     g_descSeedStored[kDescNumStateSecurityAccess-1];
#endif


#if defined (DESC_ENABLE_RID_POSTHANDLER_USAGE)
static DescMemRidInstIndex  g_descRidCurrInstRef;
#endif

/* Local context information storing (for each DID) */
static DescMsgContext        g_descPidMsgContext[kDescNumContexts];
static DescPidProcessorState g_descPidProcessorState[kDescNumContexts];
/* The current list of PID references */
static DescMemPidInstIndex   g_descPidList[kDescNumContexts][kDescNumMaxPidList];
#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
/* Bit-mapped post handler queue */
static vuint8                g_descPidPostHdlrQueue[kDescNumPostHdlrQueueBytes];
#endif



/* -----------------------------------------------------------------------------
    &&&~ ROM definitions
 ----------------------------------------------------------------------------- */

/* Version information */
V_MEMROM0 V_MEMROM1 vuint8 V_MEMROM2 g_descMainVersion     = (vuint8) DESC_MAIN_VERSION;
V_MEMROM0 V_MEMROM1 vuint8 V_MEMROM2 g_descSubVersion      = (vuint8) DESC_SUB_VERSION;
V_MEMROM0 V_MEMROM1 vuint8 V_MEMROM2 g_descBugFixVersion   = (vuint8) DESC_BUGFIX_VERSION;

#if defined(DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND)
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 g_descCan2TpChannelMap[kDescNumCommChannels] =
{
# if (kDescNumCommChannels >= 1)
  kDescCan2TpChannel_0
# endif
# if (kDescNumCommChannels >= 2)
  ,kDescCan2TpChannel_1
# endif
# if (kDescNumCommChannels >= 3)
  ,kDescCan2TpChannel_2
# endif
# if (kDescNumCommChannels >= 4)
  ,kDescCan2TpChannel_3
# endif
# if (kDescNumCommChannels >= 5)
  ,kDescCan2TpChannel_4
# endif
# if (kDescNumCommChannels >= 6)
  ,kDescCan2TpChannel_5
# endif
# if (kDescNumCommChannels >= 7)
  ,kDescCan2TpChannel_6
# endif
# if (kDescNumCommChannels >= 8)
  ,kDescCan2TpChannel_7
# endif
# if (kDescNumCommChannels >= 9)
  ,kDescCan2TpChannel_8
# endif
# if (kDescNumCommChannels >= 10)
  ,kDescCan2TpChannel_9
# endif
# if (kDescNumCommChannels >= 11)
  ,kDescCan2TpChannel_10
# endif
# if (kDescNumCommChannels >= 12)
  ,kDescCan2TpChannel_11
# endif
# if (kDescNumCommChannels >= 13)
  ,kDescCan2TpChannel_12
# endif
# if (kDescNumCommChannels >= 14)
  ,kDescCan2TpChannel_13
# endif
# if (kDescNumCommChannels >= 15)
  ,kDescCan2TpChannel_14
# endif
# if (kDescNumCommChannels == 16)
  ,kDescCan2TpChannel_15
# endif
# if (kDescNumCommChannels > 16)
#  error "Too many CAN-channels!!!"
# endif
};
#endif

#if defined(DESC_ENABLE_PARALLEL_OBD)
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 g_descDescConnections[kDescTpNumContexts] =
{
   kDescDiagConnection
  ,kDescDiagObdConnection
};
#endif

/* Table of all state transitions defined by CANdelaStudio. */
V_MEMROM0 static V_MEMROM1 DescStateInfo V_MEMROM2 g_descStateGroupTransition[kDescStateGroupNumTransition][2] = 
{
  { { 0x1E, 0x07 }, { 0x01, 0x01 } }, 
  { { 0x1E, 0x06 }, { 0x01, 0x02 } }, 
  { { 0x06, 0x05 }, { 0x01, 0x04 } }, 
  { { 0x1E, 0x06 }, { 0x01, 0x01 } }, 
  { { 0x05, 0x00 }, { 0x02, 0x00 } }, 
  { { 0x03, 0x00 }, { 0x04, 0x00 } }, 
  { { 0x01, 0x00 }, { 0x08, 0x00 } }, 
  { { 0x09, 0x00 }, { 0x10, 0x00 } }
};
/* &~MsgTables */
/* Table of reference indexes for fast SID look-up. */
V_MEMROM0 static V_MEMROM1 DescMsgItem V_MEMROM2 g_descSidMap[kDescSvcIdMapSize] = 
{
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0x00, 0x01, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x08, 
  0xFF, 0x09, 0xFF, 0xFF, 0x0A, 0xFF, 0x0B, 0x0C, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F
};
/* Table of service ID relevant information. */
V_MEMROM0 static V_MEMROM1 DescSvcHead V_MEMROM2 g_descSvcHead[kDescSvcHeadNumItems] = 
{
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x1F, 0x07 },  2,  0,  0 } /* $10 */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x1F, 0x06 },  2,  3,  3 } /* $11 */, 
  { 0x01, 0, 0, 0, 1, 0, 0x00, { 0x07, 0x05 },  4,  4,  4 } /* $14 */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x07, 0x05 },  2,  5,  4 } /* $19 */, 
  { 0x01, 0, 0, 0, 1, 0, 0x00, { 0x1F, 0x07 },  1,  9,  8 } /* $22 */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x1F, 0x06 },  2, 10,  8 } /* $27 */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x07, 0x04 },  2, 18, 16 } /* $28 */, 
  { 0x07, 2, 2, 0, 1, 0, 0x00, { 0x1E, 0x06 },  4, 20, 18 } /* $2E */, 

  { 0x0F, 3, 3, 0, 1, 0, 0x00, { 0x1F, 0x04 },  4, 34, 46 } /* $2F */, 
  { 0x01, 0, 0, 1, 1, 1, 0x00, { 0x1F, 0x06 },  1, 38, 58 } /* $31 */, 
  { 0x01, 0, 0, 0, 1, 0, 0x00, { 0x08, 0x02 },  5, 39, 58 } /* $34 */, 
  { 0x01, 0, 0, 0, 1, 0, 0x00, { 0x08, 0x02 },  2, 40, 58 } /* $36 */, 
  { 0x01, 0, 0, 0, 1, 0, 0x00, { 0x08, 0x02 },  1, 41, 58 } /* $37 */, 
  { 0x03, 1, 1, 0, 1, 0, 0x00, { 0x08, 0x02 },  2, 42, 58 } /* $38 */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x0F, 0x07 },  2, 43, 59 } /* $3E */, 
  { 0x01, 1, 1, 1, 1, 1, 0x00, { 0x07, 0x04 },  2, 44, 60 } /* $85 */, 

  { 0x00, 0, 0, 0, 1, 0, 0x00, { 0x00, 0x00 },  1, 46, 62 } /* $FF */
};
/* Table of all configured (effectively used) pre-handlers. */
V_MEMROM0 static V_MEMROM1 DescPreHandler V_MEMROM2 g_descPreHandlerTable[kDescNumPreHandlers] = 
{
  DescDummyPreHandler, 
  ApplDescPreGetLevel_1_Request_Seed, 
  ApplDescPreSendLevel_1_sendKey_1, 
  ApplDescPreGetLevel_4_Request_Seed, 
  ApplDescPreSendLevel_4_send_Key
};
/* Table of all configured (effectively used) post-handlers. */
V_MEMROM0 static V_MEMROM1 DescPostHandler V_MEMROM2 g_descPostHandlerTable[kDescNumPostHandlers] = 
{
  DescDummyPostHandler, 
  ApplDescPostGetLevel_1_Request_Seed, 
  ApplDescPostSendLevel_1_sendKey_1, 
  ApplDescPostGetLevel_4_Request_Seed, 
  ApplDescPostSendLevel_4_send_Key, 
  DescOemPostCommonCommCtrlProcess, 
  DescPostReadDataByIdentifier
};
/* Table of service (instance) relevant information. */
V_MEMROM0 static V_MEMROM1 DescSvcInst V_MEMROM2 g_descSvcInst[kDescSvcInstNumItems] = 
{
  {   2, { 0x1F, 0x07 },                      0,    0,    0, DescOemStartSessionDefault } /* $10 $1 */, 
  {   2, { 0x1F, 0x06 },                      1,    0,    0, DescOemStartSessionProgramming } /* $10 $2 */, 
  {   2, { 0x07, 0x05 },                      2,    0,    0, DescOemStartSessionExtended } /* $10 $3 */, 
  {   2, { 0x1F, 0x06 },                      3,    0,    0, ApplDescEcuResetHard } /* $11 $1 */, 
  {   0, { 0x07, 0x05 }, kDescStateNoTransition,    0,    0, ApplDescClearDiagInfo } /* $14 */, 
  {   3, { 0x07, 0x05 }, kDescStateNoTransition,    0,    0, ApplDescReadDtcRNODTCBSM } /* $19 $1 */, 
  {   3, { 0x07, 0x05 }, kDescStateNoTransition,    0,    0, ApplDescReadDtcRDTCBSM } /* $19 $2 */, 
  {   6, { 0x07, 0x05 }, kDescStateNoTransition,    0,    0, ApplDescReadDtcRDTCEDRBDN } /* $19 $6 */, 

  {   2, { 0x07, 0x05 }, kDescStateNoTransition,    0,    0, ApplDescReadDtcRSUPDTC } /* $19 $A */, 
  {   0, { 0x1F, 0x07 }, kDescStateNoTransition,    0,    6, DescReadDataByIdentifier } /* $22 */, 
  {   2, { 0x07, 0x04 }, kDescStateNoTransition,    1,    1, DescOemGetLevel_1_Request_Seed } /* $27 $1 */, 
  {   0, { 0x07, 0x04 },                      4,    2,    2, DescOemSendLevel_1_sendKey_1 } /* $27 $2 */, 
  {   2, { 0x07, 0x04 }, kDescStateNoTransition,    0,    0, DescOemGetLevel_2_Request_Seed } /* $27 $3 */, 
  {   0, { 0x07, 0x04 },                      5,    0,    0, DescOemSendLevel_2_sendKey } /* $27 $4 */, 
  {   2, { 0x09, 0x02 }, kDescStateNoTransition,    3,    3, DescOemGetLevel_4_Request_Seed } /* $27 $7 */, 
  {   0, { 0x09, 0x02 },                      6,    4,    4, DescOemSendLevel_4_send_Key } /* $27 $8 */, 

  {   2, { 0x19, 0x02 }, kDescStateNoTransition,    0,    0, DescOemGetLevel_5_Request_Seed } /* $27 $9 */, 
  {   0, { 0x19, 0x02 },                      7,    0,    0, DescOemSendLevel_5_sendKey } /* $27 $A */, 
  {   3, { 0x07, 0x04 }, kDescStateNoTransition,    0,    5, DescOemCommCtrlEnableRxEnableTx } /* $28 $0 */, 
  {   3, { 0x07, 0x04 }, kDescStateNoTransition,    0,    5, DescOemCommCtrlEnableRxDisableTx } /* $28 $1 */, 
  {  14, { 0x16, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDideCall_official_number } /* $2E $49 $A */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDideCall_enable_disable } /* $2E $49 $10 */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidautomatic_eCall_allowed } /* $2E $49 $11 */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidmanual_eCall_cancellation_allowed } /* $2E $49 $12 */, 

  {  17, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDideCall_test_number_1 } /* $2E $49 $13 */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDiddial_test_number_allowed } /* $2E $49 $14 */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidtest_mode_call_allowed } /* $2E $49 $15 */, 
  {   4, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDideCall_max_attempts } /* $2E $49 $16 */, 
  {  20, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidECU_Configuration } /* $2E $F1 $1 */, 
  {  15, { 0x08, 0x02 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidWrite_Programming_Fingerprint } /* $2E $F1 $5A */, 
  {  15, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidConfiguration_Fingerprint } /* $2E $F1 $5C */, 
  {  14, { 0x06, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidVehicle_Manufacturer_Spare_Part_Number } /* $2E $F1 $87 */, 

  {  43, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidECU_Serial_Number } /* $2E $F1 $8C */, 
  {  20, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescWriteDidVehicle_Identification_Number } /* $2E $F1 $90 */, 
  {   4, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescIoCtrlRetCtrlToEcueCall_control } /* $2F $49 $30 $0 */, 
  {   5, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescIoCtrlShortTermAdjeCall_control } /* $2F $49 $30 $3 */, 
  {   4, { 0x1F, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescIoCtrlRetCtrlToEcubackup_battery_boost_control } /* $2F $49 $31 $0 */, 
  {   5, { 0x04, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescIoCtrlShortTermAdjbackup_battery_boost_control } /* $2F $49 $31 $3 */, 
  {   0, { 0x1F, 0x06 }, kDescStateNoTransition,    0,    0, DescRoutineControlByIdentifier } /* $31 */, 
  {   0, { 0x08, 0x02 }, kDescStateNoTransition,    0,    0, ApplDescRequestDownload } /* $34 */, 

  {   0, { 0x08, 0x02 }, kDescStateNoTransition,    0,    0, ApplDescTransferData } /* $36 */, 
  {   1, { 0x08, 0x02 }, kDescStateNoTransition,    0,    0, ApplDescRequestTransferExit } /* $37 */, 
  {  23, { 0x08, 0x02 }, kDescStateNoTransition,    0,    0, ApplDescRequestFileTransferUpload_Download } /* $38 $1 */, 
  {   2, { 0x0F, 0x07 }, kDescStateNoTransition,    0,    0, DescOemProcessTesterPresent } /* $3E $0 */, 
  {   5, { 0x07, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescControlDtcSettingEnable } /* $85 $1 */, 
  {   5, { 0x07, 0x04 }, kDescStateNoTransition,    0,    0, ApplDescControlDtcSettingDisable } /* $85 $2 */
};
/* Table of sub-service protocol information. */
V_MEMROM0 static V_MEMROM1 DescMsgItem V_MEMROM2 g_descSvcInstHeadExt[kDescSvcInstHeadExtNumItems] = 
{
  0x01, 0x02, 0x03 /* $10 */, 
  0x01 /* $11 */, 
  0x01, 0x02, 0x06, 0x0A /* $19 */, 
  0x01, 0x02, 0x03, 0x04, 0x07, 0x08, 0x09, 0x0A /* $27 */, 
  0x00, 0x01 /* $28 */, 
  0x49, 0x0A, 0x49, 0x10, 0x49, 0x11, 0x49, 0x12, 0x49, 0x13, 0x49, 0x14, 0x49, 0x15, 0x49, 0x16 /* $2E */, 
  0xF1, 0x01, 0xF1, 0x5A, 0xF1, 0x5C, 0xF1, 0x87, 0xF1, 0x8C, 0xF1, 0x90 /* $2E */, 
  0x49, 0x30, 0x00, 0x49, 0x30, 0x03, 0x49, 0x31, 0x00, 0x49, 0x31, 0x03 /* $2F */, 

  0x01 /* $38 */, 
  0x00 /* $3E */, 
  0x01, 0x02 /* $85 */
};

#if defined ( C_ENABLE_MULTI_ECU_CONFIG )
# if (C_VERSION_REF_IMPLEMENTATION >= 0x150)
V_MEMROM0 extern V_MEMROM1 tVIdentityMsk V_MEMROM2 CanChannelIdentityAssignment[kCanNumberOfChannels];
# endif
#endif

/* Each entry represents a reference to a challenge set. */
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 g_descSeedLength[kDescNumStateSecurityAccess - 1] = 
{
  4, 
  4, 
  4, 
  64
};
/* Each entry represents a reference to a challenge set. */
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 g_descKeyLength[kDescNumStateSecurityAccess - 1] = 
{
  4, 
  4, 
  4, 
  64
};
/* Table of all PIDs' instances which can be read using SIMD procedure. */
V_MEMROM0 static V_MEMROM1 DescPidInst V_MEMROM2 g_descPIDInfo[kDescNumPids] = 
{
  { 0x4900,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidbackup_battery_healthy_status }, 
  { 0x4901,    9, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidvehicle_location_information }, 
  { 0x4902,   17, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidIMEI }, 
  { 0x4903,   20, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidICCID }, 
  { 0x4904,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSIM_card_status }, 
  { 0x4905,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSIM_card_airplane_mode }, 
  { 0x4906,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidcellular_network_signal_strength }, 
  { 0x4907,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidcellular_network_signal_level }, 

  { 0x4908,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidcellular_network_type }, 
  { 0x4909,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidbackup_battery_temp }, 
  { 0x490A,   11, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_official_number }, 
  { 0x490C,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidreprogramming_result }, 
  { 0x490F,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidIMU_calibration_confidence_percent }, 
  { 0x4910,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_enable_disable }, 
  { 0x4911,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidautomatic_eCall_allowed }, 
  { 0x4912,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidmanual_eCall_cancellation_allowed }, 

  { 0x4913,   14, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_test_number_1 }, 
  { 0x4914,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDiddial_test_number_allowed }, 
  { 0x4915,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidtest_mode_call_allowed }, 
  { 0x4916,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_max_attempts }, 
  { 0x4917,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_already_attempted_times }, 
  { 0x4919,   11, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidBLE_MAC_address }, 
  { 0x4930,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDideCall_control_state }, 
  { 0x4931,    1, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidbackup_battery_boost_control }, 

  { 0xF010,    0, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidReprogramming_Attempt_Counter }, 
  { 0xF101,   17, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECU_Configuration }, 
  { 0xF110,   11, { { 0x0F, 0x07 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Manufacture_Hardware_Part_Number }, 
  { 0xF111,    2, { { 0x0F, 0x07 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Manufacture_Hardware_Baseline }, 
  { 0xF118,   11, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Manufacturer_Software_Part_Number }, 
  { 0xF119,    2, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Manufacture_Software_Baseline }, 
  { 0xF11A,   11, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECALL_Software_Part_Number }, 
  { 0xF150,    3, { { 0x0F, 0x07 }, { 0x03, 0x03, 0 } }, ApplDescReadDidBootloader_Version_Number }, 

  { 0xF15B,   12, { { 0x0E, 0x06 }, { 0x03, 0x03, 0 } }, ApplDescReadDidRead_Programming_Fingerprint }, 
  { 0xF15C,   12, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidConfiguration_Fingerprint }, 
  { 0xF186,    1, { { 0x1F, 0x07 }, { 0x03, 0x03, 0 } }, ApplDescReadDidRead_Active_Diagnostic_Session }, 
  { 0xF187,   11, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Manufacturer_Spare_Part_Number }, 
  { 0xF18A,    8, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSystem_Supplier_Identifier }, 
  { 0xF18B,    3, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECU_Manufacturing_Date }, 
  { 0xF18C,   40, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECU_Serial_Number }, 
  { 0xF190,   17, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidVehicle_Identification_Number }, 

  { 0xF193,   10, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSystem_Supplier_Hardware_Version_Number }, 
  { 0xF195,   10, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSystem_Supplier_Software_Version_Number }, 
  { 0xF197,    8, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidSystem_Name }, 
  { 0xF199,    3, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECU_Programming_Date }, 
  { 0xF19E,    3, { { 0x07, 0x05 }, { 0x03, 0x03, 0 } }, ApplDescReadDidECU_Diagnostic_Database_Version }
};
/* Table of all RIDs' */
V_MEMROM0 static V_MEMROM1 vuint16 V_MEMROM2 g_descRidLookUpTable[kDescNumRids] = 
{
  0x0203, 0x3387, 0x33BB, 0x33BC, 0x33BE, 0xFF00, 0xFF01
};
/* Table of RIDs' sub-function to control type mapping. */
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 g_descRidSubFuncToCtrlTypeMap[4] = 
{
  7, 
  0, 
  7, 
  7
};
/* Table of all RIDs' properties. */
V_MEMROM0 static V_MEMROM1 DescRidTinyInfo V_MEMROM2 g_descRIDInfo[kDescNumRids] = 
{
  { { 0x0F, 0x06 }, { 0x03, 0x03, 0 } } /* $0203 */, 
  { { 0x10, 0x02 }, { 0x03, 0x03, 0 } } /* $3387 */, 
  { { 0x10, 0x02 }, { 0x03, 0x03, 0 } } /* $33bb */, 
  { { 0x10, 0x02 }, { 0x03, 0x03, 0 } } /* $33bc */, 
  { { 0x10, 0x02 }, { 0x03, 0x03, 0 } } /* $33be */, 
  { { 0x08, 0x02 }, { 0x03, 0x03, 0 } } /* $ff00 */, 
  { { 0x08, 0x02 }, { 0x03, 0x03, 0 } } /* $ff01 */
};
/* Table of all RIDs' instances. */
V_MEMROM0 static V_MEMROM1 DescRidInst V_MEMROM2 g_descRIDInstInfo[kDescNumRidInst] = 
{
  {   3, { { 0x0F, 0x06 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartCheck_Programming_Preconditions } /* $31 $1 $2 $3 */, 
  {   5, { { 0x10, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartSSH_control_in_production_env } /* $31 $1 $33 $87 */, 
  {  12, { { 0x10, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartinstall_cert } /* $31 $1 $33 $BB */, 
  {   0, { { 0x10, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStarttest_cert_installation } /* $31 $1 $33 $BC */, 
  {  17, { { 0x10, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartstart_sideloading } /* $31 $1 $33 $BE */, 
  {  12, { { 0x08, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartErase_Memory } /* $31 $1 $FF $0 */, 
  {   3, { { 0x08, 0x02 }, { 0x03, 0x03, 0 } }, ApplDescRtnCtrlStartCheck_Programming_Dependence } /* $31 $1 $FF $1 */
};


/* -----------------------------------------------------------------------------
    &&&~ Macro definitions
 ----------------------------------------------------------------------------- */

#define DescGetTicksOfMs(timeMs)                                     (vuint16)((timeMs)/(kDescCallCycleUs/1000))
#define DescUtiGetBitFromIndex(bitsetBaseType, bitIdx)               ((bitsetBaseType)(((bitsetBaseType)0x01u)<<(bitIdx)))

#define _DescMisraOpValue(tgt, tgtType, value, op)                   ((tgt) = (tgtType)((tgt) op (value)))
#define DescMisraAddValue(tgt, tgtType, value)                       (_DescMisraOpValue(tgt, tgtType, value, +))
#define DescMisraSubValue(tgt, tgtType, value)                       (_DescMisraOpValue(tgt, tgtType, value, -))
#define DescMisraMulValue(tgt, tgtType, value)                       (_DescMisraOpValue(tgt, tgtType, value, *))
#define DescMisraDivValue(tgt, tgtType, value)                       (_DescMisraOpValue(tgt, tgtType, value, /))
#define DescMisraMoveOnPtr(ptr, step)                                ((ptr)=&(ptr)[step])

#define DescUtiMathFastMul2(a)                                       ((a) << 1u)
#define DescUtiMathFastMul3(a)                                       (DescUtiMathFastMul2(a) + (a))
#define DescUtiMathFastMul4(a)                                       ((a) << 2u)
#define DescUtiMathFastMul5(a)                                       (DescUtiMathFastMul4(a) + (a))
#define DescUtiMathFastMul6(a)                                       (DescUtiMathFastMul4(a) + DescUtiMathFastMul2(a))
#define DescUtiMathFastMul7(a)                                       (DescUtiMathFastMul6(a) + (a))
#define DescUtiMathFastMul8(a)                                       ((a) << 3u)
#define DescUtiMathFastMul9(a)                                       (DescUtiMathFastMul8(a) + (a))
#define DescUtiMathFastMul10(a)                                      (DescUtiMathFastMul8(a) + DescUtiMathFastMul2(a))

#define DescDiagUpdateResLength(msgContextPtr, step)                 (DescMisraAddValue((msgContextPtr)->resDataLen, DescMsgLen, (step)))
#define DescDiagUpdateResLengthAll(msgContextPtr, step)              (DescDiagUpdateResLength(msgContextPtr, step))

#define DescDiagMoveOnRes(msgContextPtr, step)                       (DescMisraMoveOnPtr((msgContextPtr)->resData, (step)))

#define DescDiagMoveOnResWithLength(msgContextPtr, step)             for EVER { \
                                                                     DescDiagMoveOnRes((msgContextPtr), (step)); \
                                                                     DescDiagUpdateResLength((msgContextPtr), (step)); \
                                                                     break; \
                                                                     }
#define DescDiagMoveOnResWithLengthAll(msgContextPtr, step)          for EVER { \
                                                                     DescDiagMoveOnRes((msgContextPtr), (step)); \
                                                                     DescDiagUpdateResLengthAll((msgContextPtr), (step)); \
                                                                     break; \
                                                                     }

#define DescUtiMemSetUintX(tgtPtr, uintType, uintValue, elements)    {vuint16_least memIter = (vuint16_least)(elements);while(memIter != 0u){--memIter; (tgtPtr)[memIter] = (uintType)(uintValue);}}

#if (kDescNumContexts > 1)
# if defined (DESC_ENABLE_DEBUG_USER )
#  define DescAssertContext(p,e)                                     if (!(p)) {ApplDescFatalError(e, (vuint16)__LINE__);}
# else
#  define DescAssertContext(p,e)
# endif
#else
# define DescAssertContext(p,e)
#endif

#if defined (DESC_ENABLE_DEBUG_USER ) || defined (DESC_ENABLE_DEBUG_INTERNAL)
# define DescAssertCommon(p,e)                                       if (!(p)) {ApplDescFatalError(e, (vuint16)__LINE__);}
# define DescAssertCommonAlways(e)                                   (ApplDescFatalError((e), (vuint16)__LINE__))
#else
# define DescAssertCommon(p,e)
# define DescAssertCommonAlways(e)
#endif

#if defined (DESC_ENABLE_DEBUG_INTERNAL )
# define DescAssertInternal(p,e)                                     if (!(p)) {ApplDescFatalError((e), (vuint16)__LINE__);}
# define DescAssertInternalAlways(e)                                 (ApplDescFatalError((e), (vuint16)__LINE__))
#else
# define DescAssertInternal(p,e)
# define DescAssertInternalAlways(e)
#endif

#if defined (DESC_ENABLE_DEBUG_USER )
# define DescAssertUser(p,e)                                         if (!(p)) {ApplDescFatalError((e), (vuint16)__LINE__);}
# define DescAssertUserAlways(e)                                     (ApplDescFatalError((e), (vuint16)__LINE__))
#else
# define DescAssertUser(p,e)
# define DescAssertUserAlways(e)
#endif

#if defined (DESC_ENABLE_DEBUG_INTERNAL )
# define DescSubcompOnceInitPowerOnDebug()                           (CheckTableConsistency())
#endif

  /* Save too many else cases :) */
#if !defined (DescSubcompOnceInitPowerOnDebug)
# define DescSubcompOnceInitPowerOnDebug()                           /* Not used */
#endif

#if defined (DESC_ENABLE_DEBUG_USER ) || defined (DESC_ENABLE_DEBUG_INTERNAL)
# define DescSubcompOnceInitDebug()                                  /* Not used */
# define DescSubcompIterInitDebug(iContext)                          (DescDebugIterInit(DESC_CONTEXT_PARAM_ONLY))
#else
# define DescSubcompOnceInitDebug()                                  /* Not used */
# define DescSubcompIterInitDebug(iContext)                          /* Not used */
#endif

#if defined (DESC_ENABLE_DEBUG_USER )
# define DescUsdtNetIsoTpAssertUser(p,e)                             if (!(p)) {ApplDescFatalError((e), (vuint16)__LINE__);}
# define DescUsdtNetIsoTpAssertUserAlways(e)                         do {ApplDescFatalError((e), (vuint16)__LINE__);}while(0)
#else
# define DescUsdtNetIsoTpAssertUser(p,e)                             /* Not used */
# define DescUsdtNetIsoTpAssertUserAlways(e)                         /* Not used */
#endif

#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# define DescUsdtNetIsoTpAssertChannel(p,e)                          DescUsdtNetIsoTpAssertUser((p), (e))
#else
# define DescUsdtNetIsoTpAssertChannel(p,e)                          /* Not used */
#endif

#if (kDescNumCommChannels > 1)
# define DescUsdtNetIsoTpInterruptDisable()                          DescInterruptDisable()
# define DescUsdtNetIsoTpInterruptRestore()                          DescInterruptRestore()
#else
# define DescUsdtNetIsoTpInterruptDisable()                          /* Not used */
# define DescUsdtNetIsoTpInterruptRestore()                          /* Not used */
#endif

#define DescUsdtNetInitPowerOn()                                     (DescUsdtNetIsoTpInitPowerOn())
#define DescUsdtNetInit()                                            (DescUsdtNetIsoTpInit())
#define DescUsdtNetStateTask()                                       (DescUsdtNetIsoTpStateTask())
#define DescUsdtNetTimerTask()
#define DescUsdtNetPrepareResponse(infoPool)                         (DescUsdtNetIsoTpPrepareResponse(infoPool))
#define DescUsdtNetTransmitResponse(infoPool)                        (DescUsdtNetIsoTpTransmitResponse(infoPool))
#define DescUsdtNetReleaseInfoPool(infoPool)                         (DescUsdtNetIsoTpReleaseInfoPool(infoPool))
#if defined(DESC_USDTNET_ENABLE_LONGSERVICE_SUPPORT)
# define DescUsdtNetFinishReception(infoPool, status)                (DescUsdtNetLSFinishReception((infoPool),(status)))
# define DescUsdtNetFinishTransmission(infoPool, status)             (DescUsdtNetLSFinishTransmission((infoPool),(status)))
# define DescUsdtNetStartReception(infoPool)                         (DescUsdtNetLSStartReception((infoPool)))
# define DescUsdtNetRingBufferCopyRoutine(infoPool, pDestination, dataLength) (DescUsdtNetLSRingBufferCopyRoutine((infoPool),(pDestination),(dataLength)))
#else
# define DescUsdtNetFinishReception(infoPool, status)                (DescUsdtNetAbsFinishReception((infoPool),(status)))
# define DescUsdtNetFinishTransmission(infoPool, status)             (DescUsdtNetAbsFinishTransmission((infoPool),(status)))
# define DescUsdtNetStartReception(infoPool)                         (DescUsdtNetAbsStartReception((infoPool)))
# define DescUsdtNetRingBufferCopyRoutine(infoPool, pDestination, dataLength) (DescUsdtNetAbsRingBufferCopyRoutine((infoPool),(pDestination),(dataLength)))
#endif

#define DescUudtNetInitPowerOn()                                     /* Not used */
#define DescUudtNetInit()                                            /* Not used */
#define DescUudtNetTimerTask()                                       /* Not used */
#define DescUudtNetStateTask()                                       /* Not used */

/* Internal API for INIT */
#define DescSubcompOnceInitPowerOnNetwork()                          (DescNetworkInitPowerOn())

#if defined(DESC_ENABLE_NODE_POWER_CONTROL) || (kDescNumContexts > 1)|| defined(DESC_ENABLE_SPONTANEOUS_RES)
static void DescNetworkOnceInit(void);
# define DescSubcompOnceInitNetwork()                                (DescNetworkOnceInit())
#else
# define DescSubcompOnceInitNetwork()                                (DescNetworkInit())
#endif
#define DescSubcompIterInitNetwork(iContext)                         (DescNetworkIterInit(DESC_CONTEXT_PARAM_ONLY))

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
# if defined (DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
#  define DescNpmSetSleepReady(channel)                              (__DescNpmSetSleepReady(channel))
#  define DescNpmSetKeepAwake(channel)                               (__DescNpmSetKeepAwake(channel))
#  define DescIsNpmOnCanChannelActive(canChannel, canMap)            ((DescComChannelBitMaskMemType)(DescUtiGetBitFromIndex(DescComChannelBitMaskOptType, canChannel) & (canMap)) != kDescFalse)
#  define DescSetNpmOnCanChannelActive(canChannel, canMap)           ((canMap) |= DescUtiGetBitFromIndex(DescComChannelBitMaskOptType, canChannel))
#  define DescResetNpmOnCanChannelActive(canChannel, canMap)         ((canMap) &= (vuintx)(~DescUtiGetBitFromIndex(DescComChannelBitMaskOptType, canChannel)))
# else
#  define DescNpmSetSleepReady(channel)                              (__DescNpmSetSleepReady(0))
#  define DescNpmSetKeepAwake(channel)                               (__DescNpmSetKeepAwake(0))
#  define DescIsNpmOnCanChannelActive(canChannel, canMap)            ((canMap) != 0)
#  define DescSetNpmOnCanChannelActive(canChannel, canMap)           ((canMap) =  1)
#  define DescResetNpmOnCanChannelActive(canChannel, canMap)         ((canMap) =  0)
# endif
#endif

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
#  define DescGetMirroredQueue(canMap, canMapMirror)                 (canMapMirror)
# else
#  define DescGetMirroredQueue(canMap, canMapMirror)                 (canMap)
# endif
#endif
/* S1 timer decrementation mask */
#if (kDescNumContexts > 1)
# define DescSetConnectionActive(iContext)                           (g_descActiveRequestsMask |= ((vuint8)(kDescDescConnectionStateActive<<iContext)))
/* No interrutp lock, because it is already used (see DescDoPostProcessing) */
# define DescResetConnectionActive(iContext)                         (DescResetConnectionActiveMultipleContext(iContext))
# define DescIsNoExtConnectionActive()                               ((g_descActiveRequestsMask & (vuint8)(~(vuint8)(kDescReadDynPidConnStateActive | kDescRoeConnStateActive))) == 0)
# define DescIsNoConnectionActive()                                  (g_descActiveRequestsMask == 0)
#else
# define DescSetConnectionActive(iContext)                           /* not used */
# define DescResetConnectionActive(iContext)                         /* not used */
# define DescIsNoExtConnectionActive()                               /* not used */
/* Check if the diagnostic layer is in Idle Mode (ignore the periodic responses - they must not avoid S1 timer decrementation) */
# define DescIsNoConnectionActive()                                  (g_descInterruptContextCtrl[kDescPrimContext].isContextLocked == 0)
#endif

#if defined(DESC_USDTNET_ENABLE_LONGSERVICE_SUPPORT)
# define DescUsdtNetAbsReleaseInfoPool(infoPool)                     (DescUsdtNetLSReleaseInfoPool((infoPool)))
# define DescUsdtNetAbsInitPowerOn()                                 (DescUsdtNetLSInitPowerOn())
# define DescUsdtNetAbsInit()                                        (DescUsdtNetLSInit())
# define DescUsdtNetAbsStateTask()                                   (DescUsdtNetLSStateTask())
# define DescUsdtNetAbsTimerTask()                                   (DescUsdtNetLSTimerTask())
# define DescUsdtNetAbsTransmitResponse(infoPool)                    (DescUsdtNetLSTransmitResponse((infoPool)))
# define DescUsdtNetAbsPrepareResponse(infoPool)                     (DescUsdtNetLSPrepareResponse((infoPool)))
#else
# define DescUsdtNetAbsReleaseInfoPool(infoPool)                     (DescUsdtNetReleaseInfoPool((infoPool)))
# define DescUsdtNetAbsInitPowerOn()                                 (DescUsdtNetInitPowerOn())
# define DescUsdtNetAbsInit()                                        (DescUsdtNetInit())
/* This is an optional API - may be an empty macro!!! Do not enclose in paranthesis */
# define DescUsdtNetAbsStateTask()                                   DescUsdtNetStateTask()
/* This is an optional API - may be an empty macro!!! Do not enclose in paranthesis */
# define DescUsdtNetAbsTimerTask()                                   DescUsdtNetTimerTask()
# define DescUsdtNetAbsTransmitResponse(infoPool)                    (DescUsdtNetTransmitResponse((infoPool)))
/* This is an optional API - may be an empty macro!!! Do not enclose in paranthesis */
# define DescUsdtNetAbsPrepareResponse(infoPool)                     DescUsdtNetPrepareResponse((infoPool))
#endif

#if defined(ApplDescOnBeginOfProcExt)
/* ok - some one needs it */
#else
# define ApplDescOnBeginOfProcExt()                                  /* Not used */
#endif

#if defined(ApplDescOnEndOfProcExt)
/* ok - some one needs it */
#else
# define ApplDescOnEndOfProcExt()                                    /* Not used */
#endif
#if defined (DESC_USDTNET_ENABLE_DYNAMIC_BUFFER_LENGTH)
# define DescGetAvailBufferLenByMsgContext(pMsgContext)              ((pMsgContext)->busInfo.availBufferLength)
# define DescGetAvailBufferLenByInfoPool(infoPool)                   ((infoPool)->busInfo.availBufferLength)
#else
# define DescGetAvailBufferLenByMsgContext(iContext)                 kDescPrimBufferLen
# define DescGetAvailBufferLenByInfoPool(infoPool)                   kDescPrimBufferLen
#endif
#define DescNetGetAvailBufferLenByIContext(iContext)                 (DescGetAvailBufferLenByInfoPool(g_descInterruptContextCtrl[(iContext)].infoPoolPtr))

#define DescOemOnTxFrame()                                           /* Not used */
#define DescOemOnRxErrorInd(status)                                  /* Not used */
#define DescOemOnTxErrorInd(status)                                  /* Not used */
#define DescOemOnRxStart(infoPool)                                   /* Not used */
#define DescOemOnReqInd(iContext)                                    /* Not used */
/* Activate the S1 timer if necessary (Not in default session) */
#define DescOemOnConfirmation(iContext,status)                       /* Not used */

/* T2 timer macros */
#if defined (DESC_ENABLE_RES_PENDING_TIME_LIMIT) || defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
# define DescActivateLimiter(iContext)                               (g_descRcrrpLimitCounter[iContext] = kDescRcrrpMaxTicks)
# define DescDeactivateLimiter(iContext)                             (g_descRcrrpLimitCounter[iContext] = 0)
#else
# define DescActivateLimiter(iContext)                               /* Not used */
# define DescDeactivateLimiter(iContext)                             /* Not used */
#endif

#define DescActivateT2Timer(iContext)                                (g_descT2Timer[iContext] = kDescP2InitValue)
#define DescReloadT2TimerWithP3maxTime(iContext)                     (g_descT2Timer[iContext] = kDescP2ReloadValue)
#define DescDeactivateT2Timer(iContext)                              (g_descT2Timer[iContext] = 0)

/* Internal API for INIT */
#define DescSubcompOnceInitPowerOnTiming()                           /* Not used */

#define DescSubcompOnceInitTiming()                                  (DescTimingOnceInit())
#define DescSubcompIterInitTiming(iContext)                          (DescTimingIterInit(DESC_CONTEXT_PARAM_ONLY))

/* S1 timer macros */
#define DescActivateS1Timer()                                        (g_descS1Timer = kDescS1TimerTicks)
#define DescReloadS1Timer()                                          (g_descS1Timer = kDescS1TimerTicks)
#define DescDeactivateS1Timer()                                      (g_descS1Timer = 0)

/* Oem specific timers during service execution */
#define DescOemPreActiveTimer(iContext)                              /* Not used */
#define DescOemPostActiveTimer(iContext)                             /* Not used */

/* Generic OEM specific timer */
#define DescOemTaskTimer()                                           /* Not used */
/* Oem specific timers desc idle mode */
#define DescOemDescIdleTimer()                                       /* Not used */

/* Do the same as in case of StartDiagnosticSession_default */
#define DescOemOnS1Timeout()                                         /* not used */
#define DescOemOnT2Timeout(iContext)                                 /* not used */
#define DescOemOnResPendingOvertime(iContext)                        /* not used */
#define DescOemOnResPendingOverrun(iContext)                         /* not used */

/* Protocol specific initialization */
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL) && \
    defined (DESC_ENABLE_OEM_MH_MULTI_CALL_PROTECTION)
# define DescStateCompInitOnceGroup()                                (g_descIsOemMainHdlrAlreadyCalled = 0)
#endif
#if defined(DESC_ENABLE_AUTO_STATES)
# define DescOemOnTransitionSession(newState,currentState)           (DescOnTransitionStateSession((newState), (currentState)))
#endif

/* Internal API for INIT */
#if !defined(DescStateCompInitOnceOem)
# define DescStateCompInitOnceOem()                                  /* Not used */
#endif

#if !defined(DescStateCompInitOnceGroup)
# define DescStateCompInitOnceGroup()                                /* Not used */
#endif

#if defined(DESC_ENABLE_AUTO_STATES)
# define DescStateCompInitOnceCore()                                 (DescStateOnceInit())
#else
# define DescStateCompInitOnceCore()                                 /* Not used */
#endif


#define DescSubcompOnceInitPowerOnState()                            /* Not used */
#define DescSubcompOnceInitState()                                   {DescStateCompInitOnceCore(); DescStateCompInitOnceGroup(); DescStateCompInitOnceOem()}
#define DescSubcompIterInitState(iContext)                           /* Not used */

#if defined (DESC_ENABLE_AUTO_STATES)
# if (kDescStateGroupNumTransition > 0)
static void DescSetState(DescSvcInstIndex svcInstHandle);
# else
#  define DescSetState(svcInstHandle)                                /* Not used */
# endif
static DescNegResCode DescCheckState (V_MEMROM1 DescStateInfo V_MEMROM2 V_MEMROM3 * refState);
#else
# define DescCheckState(a)                                           /* Not used */
# define DescSetState(svcInstHandle)                                 /* Not used */
#endif

#if defined(DescOemOnTransitionSession)
#else
  #define DescOemOnTransitionSession(newState, formerState)
#endif

#if defined(DescOemOnTransitionSecurityAccess)
#else
  #define DescOemOnTransitionSecurityAccess(newState, formerState)
#endif

#define DescSvcIsSupportedInStateSession(refState)                   (((refState)->stateSession & g_descCurState.stateSession) != 0)
#define DescSvcIsSupportedInStateSecurityAccess(refState)            (((refState)->stateSecurityAccess & g_descCurState.stateSecurityAccess) != 0)
/* Enable communication */
#if defined (DESC_ENABLE_COMM_CTRL)
# define DESC_COMM_CTRL_REENABLE                                     (DescEnableCommunication())
#else
# define DESC_COMM_CTRL_REENABLE
#endif
#if defined (DESC_ENABLE_DELETE_DEF_DYN_ID_DEFAULT)
# define DESC_DELETE_ALL_DYN_DIDS                                    (DescDynDidDeleteAllDynDid())
#else
# define DESC_DELETE_ALL_DYN_DIDS                                    /* not used */
#endif
#if defined (DESC_ENABLE_CONTROL_DTC_SETTING_SUPPORT)
# define DESC_DTC_SETTING_REENABLE                                   (DescOemOnEnableDtcSetting())
#else
# define DESC_DTC_SETTING_REENABLE
#endif

#define DescOemOnTransitionToDefaultSession()                        {                            \
                                                                     DESC_COMM_CTRL_REENABLE;   \
                                                                     DESC_DTC_SETTING_REENABLE; \
                                                                     DESC_DELETE_ALL_DYN_DIDS; \
                                                                     }

#define DescOemOnTransitionToNonDefaultSession()                     /* not used */
/* Session Transition notification */
#define DescOemOnSessionTransition()                                 /* not used */

#if defined (DESC_ENABLE_MAINHANDLER_MULTICALL)
/* Prototype exists in desc.h */
# if (kDescNumContexts > 1)
#  define _DescStartRepeatedServiceCall(iContext,mainHandler)        (DescStartRepeatedServiceCall(iContext, mainHandler))
# else
#  define _DescStartRepeatedServiceCall(iContext,mainHandler)        (DescStartRepeatedServiceCall(mainHandler))
# endif
#else
  /* Preprocessor workaround */
# define _DescStartRepeatedServiceCall(iContext,mainHandler)         /* Not active */
#endif
#define DescSubcompOnceInitPowerOnDispatcher()                       /* Not used */

#define DescSubcompOnceInitDispatcher()                              /* Not used */
#define DescSubcompIterInitDispatcher(iContext)                      (DescDispatcherIterInit(DESC_CONTEXT_PARAM_ONLY))

/* Extract the bit position from the handle and shift with one position more 
 * (start from 0x02 instead of 0x01) since the Bit0 is for the SId.
 */
#define DescGetSvcInstFailurePosMask(svcInstHandle)                  ((vuint8)(0x02<<((vuint8)((svcInstHandle)>>13))))

#define DescOemOnProcessingDone(iContext)                            /* Not used */
#define DescOemOnSvcNotFound(iContext)                               /* Not used */
#define DescOemOnSvcInstNotFound(iContext)                           /* Not used */
#define DescOemOnReqLengthNotMatched(iContext)                       /* Not used */
#define DescOemOnReqLengthTooSmall(iContext)                         /* Not used */
#define DescOemOnInvalidSidSession(iContext)                         /* Not used */
#define DescOemOnInvalidAddrMethod(iContext)                         /* Not used */
#define DescOemOnInvalidEcuState(iContext)                           /* Not used */
#define DescOemOnValidService(iContext)                              /* Not used */

/* API for inter sub-component initialization */
#define DescSubcompOnceInitPowerOnController()                       /* Not used */
#define DescSubcompOnceInitController()                              /* Not used */
#define DescSubcompIterInitController(iContext)                      /* Not used */

#define DescOemOnInit(initParam)                                     /* Not used */
#define DescOemOnPowerOnInit(initParam)                              /* Not used */

#if !defined (DescOemDemCancelOperationOnOvertime)
# define DescOemDemCancelOperationOnOvertime(iContext)               /* Not used */
#else
  /* Already defined, do nothing */
#endif

#if !defined (DescOemDemCancelOperationOnOverrun)
# define DescOemDemCancelOperationOnOverrun(iContext)                /* Not used */
#else
  /* Already defined, do nothing */
#endif

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnProcessor()                        /* Not used */
#define DescSubcompOnceInitProcessor()                               /* Not used */
#define DescSubcompIterInitProcessor(iContext)                       /* Not used */

#define ApplDescGenericServiceConfirmation(status)
#define DescOemCustomizeComTypeParam(pCommCtrlInfo)                  /* Not used */

/* -- Communication layer adapter -- */
/* Part offline function handler prototype */
#if defined (C_MULTIPLE_RECEIVE_CHANNEL)
# if defined (DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
#  if defined ( C_ENABLE_MULTI_ECU_CONFIG )
#   define DescCommSetTxOnline(channel, msgGroup)                    do { if ( (CanChannelIdentityAssignment[channel] & V_ACTIVE_IDENTITY_MSK) != (tVIdentityMsk)0 ) {CanPartOnline((channel), (msgGroup));} } while (0)
#   define DescCommSetTxOffline(channel, msgGroup)                   do { if ( (CanChannelIdentityAssignment[channel] & V_ACTIVE_IDENTITY_MSK) != (tVIdentityMsk)0 ) {CanPartOffline((channel), (msgGroup));} } while (0)
#  else
/* Code-doubled systems are excluded up to now */
#   define DescCommSetTxOnline(channel, msgGroup)                    CanPartOnline((CanChannelHandle)(channel), (vuint8)(msgGroup))
#   define DescCommSetTxOffline(channel, msgGroup)                   CanPartOffline((CanChannelHandle)(channel), (vuint8)(msgGroup))
#  endif
# else
#  define DescCommSetTxOnline(channel, msgGroup)                     CanPartOnline(0, (vuint8)(msgGroup))
#  define DescCommSetTxOffline(channel, msgGroup)                    CanPartOffline(0, (vuint8)(msgGroup))
# endif
#else
# define DescCommSetTxOnline(channel, msgGroup)                      CanPartOnline((vuint8)(msgGroup))
# define DescCommSetTxOffline(channel, msgGroup)                     CanPartOffline((vuint8)(msgGroup))
#endif
#if defined (DESC_ENABLE_RX_COMM_CONTROL)
# define DescMakeCommCtrlParam(txState,rxState)                      ((vuint8)(((rxState) << 2)|(txState)))
#else
# define DescMakeCommCtrlParam(txState,rxState)                      ((vuint8)(txState))
#endif

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnFaultMemory()                      /* Not used */
#define DescSubcompOnceInitFaultMemory()                             /* Not used */
#define DescSubcompIterInitFaultMemory(iContext)                     /* Not used */

/* Internal API for INIT */
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
# define DescSubcompOnceInitPowerOnSecurityAccess()                  (DescSecurityOnceInitPowerOn())
#else
# define DescSubcompOnceInitPowerOnSecurityAccess()                  /* Not used */
#endif
#define DescSubcompOnceInitSecurityAccess()                          (DescSecurityOnceInit())
#define DescSubcompIterInitSecurityAccess(iContext)                  /* Not used */


/* Optimized seed length access */
#if defined (DESC_ENABLE_MULTIPLE_SEED_LENGTH)
# define DescGetSeedLength(levelIndex)                               (g_descSeedLength[levelIndex])
#else
# define DescGetSeedLength(levelIndex)                               (kDescSecurityAccessSeedLength)
#endif

#if defined (DESC_ENABLE_MULTIPLE_KEY_LENGTH)
# define DescGetKeyLength(levelIndex)                                (g_descKeyLength[levelIndex])
#else
# define DescGetKeyLength(levelIndex)                                (kDescSecurityAccessKeyLength)
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
# if defined (DESC_ENABLE_ATTEMPT_COUNTER_LEVEL_SPECIFIC)
#  define DescGetSACounterValue(index)                               (g_descAttemptCounterValue[index])
# else
#  define DescGetSACounterValue(index)                               (kDescMaxNumberOfAttempts)
# endif

# if defined (DESC_ENABLE_POWERON_TIME_LEVEL_SPECIFIC)
#  define DescGetSAPwrOnTimeValue(index)                             (g_descPwrOnTimeValue[index])
# else
#  define DescGetSAPwrOnTimeValue(index)                             (kDescPowerOnSecureTimer)
# endif

# if defined (DESC_ENABLE_DELAY_TIME_LEVEL_SPECIFIC)
#  define DescGetSADelayTimeValue(index)                             (g_descDelayTimerValue[index])
# else
#  define DescGetSADelayTimeValue(index)                             (kDescSecureTimer)
# endif
#endif

#if defined (DESC_ENABLE_SA_STATIC_SEED)
# define DescGetSASeedBuffer(index)                                  (g_descSASeedBufferTable[index])
#else
/* shall not be used */
#endif


#if defined (DESC_ENABLE_SA_STATIC_SEED)
# define DescIsSAStoredSeed(index)                                   (g_descSeedStored[index] != kDescFalse)
# define DescSetSAStoredSeed(index, value)                           (g_descSeedStored[index] = (value))
#endif

#if defined (DESC_ENABLE_SA_MULTI_SEED_OBJ)
# define DescGetSeedObjIdxOfLevel(securityLevel)                     (DescGetLevelIdxOfState(securityLevel))
#else
# define DescGetSeedObjIdxOfLevel(securityLevel)                     ((vuint8_least)0)
#endif

#if defined (DESC_ENABLE_MULTIPLE_KEY_LENGTH)
# define DescGetKeyObjIdxOfLevel(securityLevel)                      (DescGetLevelIdxOfState(securityLevel))
#else
# define DescGetKeyObjIdxOfLevel(securityLevel)                      ((vuint8_least)0)
#endif

#if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
# define DescGetInstanceIdxOfLevel(securityLevel)                    (DescGetLevelIdxOfState(securityLevel))
#else
# define DescGetInstanceIdxOfLevel(securityLevel)                    ((vuint8_least)0)
#endif

#if defined (DESC_ENABLE_DELAY_TIME_LEVEL_SPECIFIC)
# define DescGetDelayTimeIdxOfLevel(securityLevel)                   (DescGetLevelIdxOfState(securityLevel))
#else
# define DescGetDelayTimeIdxOfLevel(securityLevel)                   ((vuint8_least)0)
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
# define DescSetSADelayTimer(index, value)                           (g_descSecureTimer[index] = (value))
# define DescGetSADelayTimer(index)                                  (g_descSecureTimer[index])
# define DescDecrementSADelayTimer(index)                            (g_descSecureTimer[index]--)
# define DescIncrementSAAttemptCounter(index)                        (g_descSecureNrOfAttempts[index]++)
# define DescSetSAAttemptCounter(index, value)                       (g_descSecureNrOfAttempts[index] = (value))
# define DescGetSAAttemptCounter(index)                              (g_descSecureNrOfAttempts[index])
#endif

#if !defined(DescOemOnInvalidRequest)
# define DescOemOnInvalidRequest(iContext)                           (DescOemOnInvalidReq_27(DESC_CONTEXT_PARAM_WRAPPER_ONLY(iContext)))
#endif

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnPidManager()                       /* Not used */
#define DescSubcompOnceInitPidManager()                              /* Not used */
#define DescSubcompIterInitPidManager(iContext)                      /* Not used */

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnRidManager()                       /* Not used */
#define DescSubcompOnceInitRidManager()                              /* Not used */
#define DescSubcompIterInitRidManager(iContext)                      /* Not used */

#if defined (DESC_ENABLE_RID_OPTIMIZED_USAGE)
#endif

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnScheduled()                        /* Not used */
#define DescSubcompOnceInitScheduled()                               /* Not used */
#define DescSubcompIterInitScheduled(iContext)                       /* Not used */

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnPidListProcessor()                 /* Not used */
#define DescSubcompOnceInitPidListProcessor()                        /* Not used */
#define DescSubcompIterInitPidListProcessor(iContext)                (DescIterInitPidListProcessor(DESC_CONTEXT_PARAM_ONLY))

#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
# define DescPidMod8(value)                                          ((vuint8_least)((value) & (8-1)))
# if (kDescNumPostHdlrQueueBytes > 1)
#  define DescPidDiv8(value)                                         ((vuint8_least)((value) >> 3))
# else
#  define DescPidDiv8(value)                                         0
# endif
/* Queue the current reference of PID */
# define DescPidDoQueuePostHandlerAt(pidRef)                         (g_descPidPostHdlrQueue[DescPidDiv8(pidRef)] |= (vuint8)(0x01 << DescPidMod8(pidRef)))
# define DescPidIsPostHandlerQueuedAt(pidRef)                        ((g_descPidPostHdlrQueue[DescPidDiv8(pidRef)] & (0x01 << DescPidMod8(pidRef))) != 0)
#endif

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnDynDefinePid()                     /* Not used */
#define DescSubcompOnceInitDynDefinePid()                            /* Not used */
#define DescSubcompIterInitDynDefinePid(iContext)                    /* Not used */

/* Hook functions for PID manager */
#define DescPmClientCheckPid(result, pid)                            (result)
#define DescPmClientGetResLength(pidHandle)                          ((vuint8)0)


/* Internal API for INIT */
#define DescSubcompOnceInitPowerOnDynDefineDpid()                    /* Not used */
#define DescSubcompOnceInitDynDefineDpid()                           /* Not used */
#define DescSubcompIterInitDynDefineDpid(iContext)                   /* Not used */

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnRoeProcessor()                     /* Not used */
#define DescSubcompOnceInitRoeProcessor()                            /* Not used */
#define DescSubcompIterInitRoeProcessor(iContext)                    /* Not used */

/* Default internal API for INIT - not used */
#define DescSubcompOnceInitPowerOnVariantManager()                   /* Not used */
#define DescSubcompOnceInitVariantManager()                          /* Not used */
#define DescSubcompIterInitVariantManager(iContext)                  /* Not used */



/* -----------------------------------------------------------------------------
    &&&~ Implementation
 ----------------------------------------------------------------------------- */

/* Check if this feature is enabled */
#if defined (GEN_MAGIC_NUMBER_V_CFG) && \
    defined (kDescIntegrationMagicNumber)
/* begin Fileversion check */
# if (GEN_MAGIC_NUMBER_V_CFG != kDescIntegrationMagicNumber)
#  error "The magic number of the generated header v_cfg.h is different! Check time and date of generated files!"
# endif
#endif

/******************************************************************************
* All necessary preprocessor directives existence checks
******************************************************************************/
#if !defined(DESC_ENABLE_RES_PENDING_TIME_LIMIT) && \
    !defined(DESC_DISABLE_RES_PENDING_TIME_LIMIT)
# error "Missing switch DESC_XXXABLE_RES_PENDING_TIME_LIMIT!"
#endif

#if !defined(DESC_ENABLE_RES_PENDING_COUNT_LIMIT) && \
    !defined(DESC_DISABLE_RES_PENDING_COUNT_LIMIT)
# error "Missing switch DESC_XXXABLE_RES_PENDING_COUNT_LIMIT!"
#endif

#if defined (kDescNumContexts)
# if (kDescNumContexts == 0)
#  error "No diagnostic connection will be available!"
# endif
#else
# error "Missing kDescNumContexts define!"
#endif
/******************************************************************************
*  Conditional checks
******************************************************************************/
#if defined(DESC_ENABLE_MULTI_TP)
# if defined(DESC_ENABLE_SINGLE_TP_OPTIMIZED)
#  error "Could not be used both transport layers types!"
# endif
#elif defined(DESC_DISABLE_MULTI_TP)
# if defined(DESC_DISABLE_SINGLE_TP_OPTIMIZED)
#  error "At least one transport layer type must be selected!"
# endif
#else
# error "Missing switch DESC_XXXABLE_MULTI_TP!"
#endif

#if !defined(DESC_ENABLE_SINGLE_TP_OPTIMIZED) && \
    !defined(DESC_DISABLE_SINGLE_TP_OPTIMIZED)
# error "Missing switch DESC_XXXABLE_SINGLE_TP_OPTIMIZED!"
#endif

#if defined(DESC_ENABLE_RES_PENDING_TIME_LIMIT) && \
    defined(DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
# error "Both type of response pending limitations are not possible at the same time!"
#endif

#if defined (C_MULTIPLE_RECEIVE_CHANNEL) || defined (C_SINGLE_RECEIVE_CHANNEL)
/* config ok */
#else
/* code doubled system */
# if (kDescNumCommChannels > 1)
#  if defined (kDescCanChannel)
/* config ok */
#  else
#   error "Missing kDescCanChannel define!"
#  endif
# endif
#endif


#if defined (DESC_ENABLE_DEBUG_INTERNAL)
/*******************************************************************************
* NAME:              CheckIndexTableConsistency
*
* CALLED BY:         DescInitPowerOn
* PRECONDITIONS:     
*
* DESCRIPTION:       Performs check if the table relations are consistent, and 
*                    if all main handler functions are not V_NULL.
*
*******************************************************************************/
static void CheckTableConsistency(void)
{
# if defined( C_COMP_IAR_M16C )
#  if defined ( _NEAR_ )
  static vuint8  sidCnt;
  static DescSvcInstIndex i;
#  else
  vuint8  sidCnt;
  DescSvcInstIndex i;
#  endif
# else
  vuint8  sidCnt;
  DescSvcInstIndex i;
# endif
  /*--------------------------*/
  /*   Check SID references   */
  /*--------------------------*/
  sidCnt = 0;
  for (i = 0; i < kDescSvcIdMapSize; i++)
  {
    if (g_descSidMap[i] != 0xff)
    {
       /* Will be used for checking if all sid are referenced */
       sidCnt++;
        /* unexisting reference (-1 due to the dummy entry */
       DescAssertInternal((g_descSidMap[i] < (kDescSvcHeadNumItems - 1)),
                         kDescAssertIndexTableInvalidReference
                       );
    }
  }
  DescAssertInternal((sidCnt == (kDescSvcHeadNumItems - 1)),
                    kDescAssertSvcTableUnreachableItem
                  );
  /*--------------------------------*/
  /*  Check SID To SINST references */
  /*--------------------------------*/
  for (i = 0; i < (kDescSvcHeadNumItems - 1); i++)
  {
    DescAssertInternal((g_descSvcHead[i].svcInstFirstItem < kDescSvcInstNumItems),
                      kDescAssertSvcTableInvalidReference
                    );
  }
# if defined(DESC_ENABLE_GENERIC_USER_SERVICE_SUPPORT)
  /* Check the last line content (must be exactly the last line number of the svcInst table) */
  DescAssertInternal((g_descSvcHead[i].svcInstFirstItem == (kDescSvcInstNumItems - 1)),
                    kDescAssertSvcTableInvalidReference
                  );
# else
  /* Check the dummy line content */
  DescAssertInternal((g_descSvcHead[i].svcInstFirstItem == kDescSvcInstNumItems),
                    kDescAssertSvcTableInvalidReference
                  );
# endif
  /*--------------------------------*/
  /*  Check Main handler existence  */
  /*--------------------------------*/
  for (i = 0; i < kDescSvcInstNumItems; i++)
  {
    DescAssertInternal((g_descSvcInst[i].mainHandler != V_NULL), kDescAssertMissingMainHandler);
  }
}
#endif

#if defined (DESC_ENABLE_DEBUG_INTERNAL) || \
    defined (DESC_ENABLE_DEBUG_USER)
/*******************************************************************************
* NAME:              DescDebugIterInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:     
*
* DESCRIPTION:       Initilizes the debug subcomponent context specific data.
*
*******************************************************************************/
static void DescDebugIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Avoid warnings */
  DESC_CONTEXT_PARAM_DUMMY_USE;
}
#endif

/******************************************************************************
* All necessary preprocessor directives existence checks
******************************************************************************/
/* Node power management configuration validation*/
#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && \
    !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION) && \
    !defined (DESC_ENABLE_COMMON_OEM_POST_HANDLER)
# error "Enable OEM-post-handler support on service $10"
#endif

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpInitPowerOn
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       Power on initialization
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpInitPowerOn(void)
{
  DescUsdtNetIsoTpInit();
}

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpInitContext
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       Re-initialization
*
*
*******************************************************************************/
static void DescUsdtNetIsoTpInitContext(DESC_TPCONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
  vuint8  descTmpTxChannel;

  /* Find a channel for TP */
  descTmpTxChannel = TpTxGetConnectionStatus(DescGetConnectionOfContext(DESC_TPCONTEXT_PARAM_VALUE));
  if(descTmpTxChannel == kTpNoChannel)
  {
    if( (g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE] = TpTxGetFreeChannel(DescGetConnectionOfContext(DESC_TPCONTEXT_PARAM_VALUE))) != kTpNoChannel )
    {
      TpTxLockChannel(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
#  if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
      /* Initialize the transmission type */
      g_descTpCtrl.txPath[g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]].type = kDescMainTransmission;
#  endif
    }
  }
#  if defined (DESC_ENABLE_DEBUG_INTERNAL)
  else
  { /* The TX channel is still locked but is it the same as before? */
    DescUsdtNetIsoTpAssertChannel(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE] == descTmpTxChannel, kDescAssertWrongTpTxChannel);
  }
#  endif
  DescUsdtNetIsoTpAssertChannel(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE] != kTpNoChannel, kDescAssertWrongTpTxChannel);
# endif
#endif

#if defined(DESC_USDTNET_ENABLE_DYNAMIC_BUFFER_LENGTH)
  g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.availBufferLength = kDescPrimBufferLen;
#endif
  g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle = kDescUsdtNetInvalidDescContext;
  g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqDataPtr = g_descBuffer[DESC_TPCONTEXT_PARAM_VALUE];
  g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].resDataPtr = g_descBuffer[DESC_TPCONTEXT_PARAM_VALUE];
  g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].resType = kDescUsdtResponseNone;
}

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpInit
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       Re-initialization
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpInit(void)
{
  { /* Init tx resources */
    vuint8_least resIter = kTpTxChannelCount;
    while(resIter != 0)
    {
      resIter--;
      g_busInfoPoolTxRef[resIter] = V_NULL;
    }
  }

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  {
    vuint8_least addIter = kDescNumAddRequestChannels;

    g_descAddChannelCtrl.count = 0;
    while(addIter != 0)
    {
      --addIter;
      g_descAddChannelCtrl.channel[addIter].status = kDescContextIdle;
    }
  }
#endif

  DescUsdtNetIsoTpInitContext(DESC_TPCONTEXT_PARAM_WRAPPER_ONLY(kDescPrimContext));
#if defined (DESC_ENABLE_PARALLEL_OBD)
  DescUsdtNetIsoTpInitContext(DESC_TPCONTEXT_PARAM_WRAPPER_ONLY(kDescObdContext));
#endif

#if defined(TP_FUNC_ENABLE_RECEPTION) && \
    (kDescNumFuncReqContexts > 0)
  g_descUsdtNetInfoPoolIsoTp[kDescUsdtNetSecInfoPool].descHandle = kDescUsdtNetInvalidDescContext;
  g_descUsdtNetInfoPoolIsoTp[kDescUsdtNetSecInfoPool].reqDataPtr = g_descSecBuffer;
  g_descUsdtNetInfoPoolIsoTp[kDescUsdtNetSecInfoPool].resDataPtr = g_descSecBuffer;
  g_descUsdtNetInfoPoolIsoTp[kDescUsdtNetSecInfoPool].resType = kDescUsdtResponseNone;
# if defined(DESC_USDTNET_ENABLE_DYNAMIC_BUFFER_LENGTH)
  g_descUsdtNetInfoPoolIsoTp[kDescUsdtNetSecInfoPool].busInfo.availBufferLength = kDescSecBufferLen;
# endif
#endif
}

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpStateTask
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       State Task of the IsoTp driver
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpStateTask(void)
{
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  /* Process additional requests */
  DescBusyResponseHandler();
#endif
}

#if defined (TP_ENABLE_EXTENDED_ADDRESSING)
# if defined (TP_DISABLE_CHECKTA_COMPATIBILITY) && \
     defined (DESC_DISABLE_EXTERNAL_CHECK_TA)
/*******************************************************************************
* NAME:              DescCheckTA
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Target address evaluation.
*
*******************************************************************************/
t_ta_type DescCheckTA (vuint8 targetAddress)
{
  t_ta_type returnValue = kTpNone;

  if (targetAddress == TP_ECU_NUMBER)
  {
    returnValue = kTpPhysical;
  }
  else
  {
    if (targetAddress == kDescOemExtAddrFuncTargetAddr)
    {
      returnValue = kTpFunctional;
    }
  }
  return returnValue;
}
# endif
#endif

#if defined (DESC_ENABLE_PARALLEL_OBD)
/*******************************************************************************
* NAME:              DescDispatchServiceContext
*
* CALLED BY:         Desc start reception event
* PRECONDITIONS:
*
* DESCRIPTION:       this function dispatches the parallel request reception target context
*******************************************************************************/
static vuint8 DescDispatchServiceContext(vuint8 sid)
{
  vuint8 result = kDescPrimContext; /* Main connection */

  /* OBD predispatching for request routing */
  if((sid > 0x00) && (sid < 0x10))
  {
    result = kDescObdContext;
  }
  return result;
}
#endif

/*******************************************************************************
* NAME:              DescGetBuffer
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       StartOfFrame reception function
*
*******************************************************************************/
TP_MEMORY_MODEL_DATA vuint8* DescGetBuffer(TP_CHANNEL_RX_FORMAL_PARAM_DEF_FIRST vuint32 dataLength)
{
  DescUsdtNetMsg returnValue = V_NULL;
  TpRxSetTransmitID(0,0x6DF);/*SANGSHULIN*/

#if (defined (DESC_ENABLE_PHYSREQ_TA_CHECK) || defined (DESC_ENABLE_PHYSREQ_SA_CHECK))
  DescBool addressCheckResult;

# if defined (DESC_ENABLE_PHYSREQ_TA_CHECK)
  addressCheckResult = DescOemCheckPhysTargetAddress(TpGetTargetAddress(TP_CHANNEL_RX_PARAM_ONLY));
  if(addressCheckResult == kDescTrue)
# endif
  {
# if defined (DESC_ENABLE_PHYSREQ_SA_CHECK)
    addressCheckResult = DescOemCheckPhysSourceAddress(TpRxGetSourceAddress(TP_CHANNEL_RX_PARAM_ONLY));
# endif
  }

  if(addressCheckResult == kDescTrue)
#endif
  {
#if defined (DESC_ENABLE_PARALLEL_OBD)
    DESC_TPCONTEXT_PARAM_DEF_LOCAL /* For OBD */
    DESC_TPCONTEXT_PARAM_VALUE = DescDispatchServiceContext(TpRxGetCanBuffer(tpRxChannel)[0]);
#endif

    /* Check if CANdesc is free and protect it from interrupting request from different channel */
    DescUsdtNetIsoTpInterruptDisable();
    if (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle == kDescUsdtNetInvalidDescContext)
    {
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle = DESC_TPCONTEXT_PARAM_VALUE; /* Write used context */
      DescUsdtNetIsoTpInterruptRestore();

      if(dataLength > kDescPrimBufferLen)
#if defined (DESC_ENABLE_NEGRES_ON_MSG_TOO_LONG)
      {
        /* Force only one frame copy, length validation should fail later on causing NRC message */
        TpRxSetBufferOverrun(TP_CHANNEL_RX_PARAM_ONLY);
      } /* no else required in that case - a valid reception has to be simulated */
#else
      {
# if ((TP_ISO15765_VERSION >= 0x0273) && defined (TP_ENABLE_ISO_15765_2_2))
#  if (TP_ISO15765_VERSION >= 0x0277)
        TpRxSetFCStatus(TP_CHANNEL_RX_PARAM_FIRST kTpFCStatusOverflow);
#  else
#   error "Incompatible TPMC Version - please use version 2.77+"
#  endif
# else
        /* returnValue = V_NULL; it is already default */
# endif
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle = kDescUsdtNetInvalidDescContext; /* Free already locked context */
      } /* discard reception */
      else
#endif
      {
        t_descUsdtNetResult result;
#if defined (TP_ENABLE_EXTENDED_ADDRESSING)
# if defined (TP_DISABLE_CHECKTA_COMPATIBILITY)
        t_ta_type ta_type;
# endif
#endif
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.busType   = kDescUsdtNetBusTypeIsoTp;
#if (TP_USE_EXTENDED_ADDRESSING           == kTpOn)      || \
    defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING)  || \
    defined (TP_ENABLE_MIXED_29_ADDRESSING)
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.SourceAddress = TpRxGetSourceAddress(TP_CHANNEL_RX_PARAM_ONLY);
        /* Make the tester ID visible to the above layer */
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.testerId = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.SourceAddress;

    /* g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = TpRxGetReceivedTargetAddress (TP_CHANNEL_RX_PARAM_VALUE); */
#endif

#if ( kCanNumberOfChannels > 1 ) /* more than one canChannel ? */
# if defined (DESC_USDTNET_ENABLE_MULTI_TP)
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.CanChannel = TpRxGetCanChannel(TP_CHANNEL_RX_PARAM_ONLY);
# else
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.CanChannel = TpRxGetCanChannel();
# endif
        /* Make the communication channel ID visible to the above layer */
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.comChannel = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.CanChannel;
#endif
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle         = TP_CHANNEL_RX_PARAM_VALUE;
#endif

#if defined (TP_ENABLE_EXTENDED_ADDRESSING)
# if defined (TP_ENABLE_MULTIPLE_ADDRESSING)
          /* This check should be used for all Multi Addressing Tps*/
        if(TpRxGetAddressingFormat(TP_CHANNEL_RX_PARAM_ONLY) == kTpExtendedAddressing)
# endif
        {
# if defined (TP_DISABLE_CHECKTA_COMPATIBILITY) /*It has to be actviated for Extended Addressing */
          ta_type = TpRxGetTaType(TP_CHANNEL_RX_PARAM_ONLY);
          if (ta_type == kTpPhysical)
# endif
#endif
          {
            g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqType         = kDescUsdtNetReqTypePhysical;
          }
#if defined (TP_ENABLE_EXTENDED_ADDRESSING)
# if defined (TP_DISABLE_CHECKTA_COMPATIBILITY)
          else
          {
            g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqType         = kDescUsdtNetReqTypeFunctional;
          }
# endif

        }
# if defined (TP_ENABLE_MULTIPLE_ADDRESSING)
        else
        {
          g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqType   = (t_descUsdtNetReqType)((TpRxGetAssignedDestination(TP_CHANNEL_RX_PARAM_ONLY) == kTpRequestDiagPhysical) ? kDescUsdtNetReqTypePhysical: kDescUsdtNetReqTypeFunctional);
        }
# endif
#endif

        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].dataLength        = dataLength;

        /* Check if Desc itself is free */
        result = DescUsdtNetStartReception(&g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE]);
        if(result == kDescUsdtNetworkOk)
        { /* it is */
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
          /* store the connection type */
          g_descTpCtrl.rxPath[tpRxChannel].type = kDescMainReception;
#endif
#if defined (DESC_ENABLE_PARALLEL_OBD)
          /* store the working context type */
          g_busInfoPoolRxRef[tpRxChannel] = &g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE];
#endif
          returnValue = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqDataPtr;
        }
        else
        {
          g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle = kDescUsdtNetInvalidDescContext; /* Write used context */
        }
      }
    }
    else
    {
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
# if (TP_USE_EXTENDED_ADDRESSING           == kTpOn)      || \
     defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING)  || \
     defined (TP_ENABLE_MIXED_29_ADDRESSING)

if ((g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.testerId != TpRxGetSourceAddress(TP_CHANNEL_RX_PARAM_ONLY))
#  if ( kCanNumberOfChannels > 1 ) /* more than one canChannel ? */
#   if defined (DESC_USDTNET_ENABLE_MULTI_TP)
        || (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.comChannel != TpRxGetCanChannel(TP_CHANNEL_RX_PARAM_ONLY))
#   else
        || (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.comChannel != TpRxGetCanChannel())
#   endif
#  endif
                                                                                                                              )
# endif
      {
        /* check if an additional request channel is free */
        vuint8_least iter;
        iter = kDescNumAddRequestChannels;
        while( iter != 0 )
        {
          --iter;
          if(g_descAddChannelCtrl.channel[iter].status == kDescContextIdle)
          {
            g_descAddChannelCtrl.channel[iter].status = kDescContextActiveRx;
            /* Force only one frame copy */
            TpRxSetBufferOverrun(TP_CHANNEL_RX_PARAM_ONLY);
            g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_ONLY].type = kDescAddReception;
            g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_ONLY].info = (vuint8)iter;
            returnValue = g_descAddChannelCtrl.channel[iter].buffers.reqBuffer;
            /* Break */
            iter = 0;
          }
        }
      }
#endif
      /* CANdesc is not free -> release interrupts again */
      DescUsdtNetIsoTpInterruptRestore();
    }
  }
  return returnValue;
}

/*******************************************************************************
* NAME:              DescPhysReqInd
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Rx path for physical requests.
*                    Function name must be entered to the CANgen OSEK-TP Options
*                    dialog in the fields "RxIndication".
*******************************************************************************/
void TP_API_CALLBACK_TYPE DescPhysReqInd(TP_CHANNEL_RX_FORMAL_PARAM_DEF_FIRST vuint32 dataLen)
{
  DESC_IGNORE_UNREF_PARAM(dataLen);

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  switch (g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].type)
  {
  case kDescMainReception:
#endif
    {
#if defined (DESC_ENABLE_PARALLEL_OBD)
      DESC_TPCONTEXT_PARAM_DEF_LOCAL /* For OBD */
      DESC_TPCONTEXT_PARAM_VALUE = g_busInfoPoolRxRef[TP_CHANNEL_RX_PARAM_VALUE]->descHandle;
#endif
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
      DescUsdtNetIsoTpAssertChannel(g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle == TP_CHANNEL_RX_PARAM_VALUE, kDescNetAssertWrongIsoTpRxChannel);
#endif
      /*-----------------------------*/
      /*Transport protocol management*/
      /*-----------------------------*/
#if defined (TP_ENABLE_DYNAMIC_CHANNELS)
# if defined (TP_ENABLE_NORMAL_ADDRESSING)       || \
     defined (TP_ENABLE_MIXED_11_ADDRESSING)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.ReceiveID = TpRxGetChannelID(TP_CHANNEL_RX_PARAM_ONLY);
#  if defined (TP_FUNC_ENABLE_RECEPTION)
      if (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqType == kDescUsdtNetReqTypeFunctional)
      {
        TpFuncSetResponse(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
      }
      else
#  endif
      {
        TpTxSetResponse(g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle, g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
      }
# endif
# if defined(TP_ENABLE_CANFD)
#  if defined (TP_ENABLE_SINGLE_CHANNEL_TP)
      g_descCanType = TpTxGetCanType();
#  else
      g_descCanType = TpTxGetCanType(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
#  endif
# endif
#endif
#if (TP_USE_MULTIPLE_ECU_NR == kTpOn)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = TpRxGetEcuNumber(TP_CHANNEL_RX_PARAM_ONLY);
#else
# if (TP_USE_EXTENDED_ADDRESSING == kTpOn) || \
     defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING) || \
     defined (TP_ENABLE_MIXED_29_ADDRESSING)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = kDescEcuNumber;
# endif
#endif
#if (TP_USE_EXTENDED_ADDRESSING == kTpOn)
# if (TP_USE_MULTIPLE_BASEADDRESS == kTpOn)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.BaseAddress = TpRxGetBaseAddress(TP_CHANNEL_RX_PARAM_ONLY);
# endif
#endif
      /* Reception has finished */
      DescUsdtNetFinishReception(&g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE], kDescUsdtNetworkOk);
      /* Reset the channel */
      TpRxResetChannel(TP_CHANNEL_RX_PARAM_ONLY);
    }
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
    break;
  case kDescAddReception:
    /* Increase succesfully received additionally requests */
    DescUsdtNetIsoTpAssertUser((g_descAddChannelCtrl.count < kDescNumAddRequestChannels), kDescAssertIllegalAddRequestCount);

# if defined(DESC_ENABLE_NEG_RES_ON_SID_WITH_SET_BIT6)
    /* Process any SID */
# else
    /* Check for invalid SID (if bit6 set -> SID from the response ID page received. */
    if((g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.reqBuffer[0] & 0x40) == 0)
# endif
    {
      if(g_descAddChannelCtrl.count < kDescNumAddRequestChannels)
      {
        g_descAddChannelCtrl.count++;
      }
      /* Store tpRxChannel in buffer*/
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.res.tpRxChannel = TP_CHANNEL_RX_PARAM_VALUE;
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].status = kDescContextActiveProcess;
      /* write the negative response code */
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.res.resBuffer[2] = 0x21;
      /* copy SID onto the right place */
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.res.resBuffer[1] = g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.reqBuffer[0];
      /* write the negative response identifier */
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].buffers.res.resBuffer[0] = 0x7f;
    }
# if defined(DESC_ENABLE_NEG_RES_ON_SID_WITH_SET_BIT6)
    /* nothing to do */
# else
    else
    {
      /* Reset the additional channel state */
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].status = kDescContextIdle;
      TpRxResetChannel(TP_CHANNEL_RX_PARAM_VALUE);
    }
# endif
    break;
  default:
    /* Unknown type */
    DescUsdtNetIsoTpAssertUserAlways(kDescAssertUnknownTpTransmissionType);
    break;
  }
#endif
}


/*******************************************************************************
* NAME:              DescRxErrorIndication
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Release the lock mechanism for Rx on error by receiving.
*                    Function name must be entered to the CANgen TP setup
*                    dialog in the fields "TpXXXErrorIndication".
*******************************************************************************/
void TP_API_CALLBACK_TYPE DescRxErrorIndication(TP_CHANNEL_RX_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  /* Avoid warnings*/
  DESC_IGNORE_UNREF_PARAM(status);
  TP_CHANNEL_RX_PARAM_IGNORE_UNREF;

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  switch (g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].type)
  {
    case kDescMainReception:
#endif
      {
#if defined (DESC_ENABLE_PARALLEL_OBD)
        DESC_TPCONTEXT_PARAM_DEF_LOCAL /* For OBD */
        DESC_TPCONTEXT_PARAM_VALUE = g_busInfoPoolRxRef[TP_CHANNEL_RX_PARAM_VALUE]->descHandle;
#endif
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
        DescUsdtNetIsoTpAssertChannel(g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle == TP_CHANNEL_RX_PARAM_VALUE, kDescNetAssertWrongIsoTpRxChannel);
#endif
        /* reception error - notify CANdesc */
        DescUsdtNetFinishReception(&g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE], kDescUsdtNetworkAbort);
      }
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
      break;
    case kDescAddReception:
      /* reset the additional cahnnel status */
      g_descAddChannelCtrl.channel[g_descTpCtrl.rxPath[TP_CHANNEL_RX_PARAM_VALUE].info].status = kDescContextIdle;
      break;
    default:
      /* Unknown type */
      DescUsdtNetIsoTpAssertUserAlways(kDescAssertUnknownTpTransmissionType);
      break;
  }
#endif
}

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpPrepareResponse
*
* CALLED BY:         CANdesc (Dispatcher)
* PRECONDITIONS:
*
* DESCRIPTION:       Prepare address info for response message
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpPrepareResponse(t_descUsdtNetInfoPoolPtr infoPool)
{
#if (TP_USE_EXTENDED_ADDRESSING           == kTpOn)      || \
    defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING)  || \
    defined (TP_ENABLE_MIXED_29_ADDRESSING)
  vuint8 sourceAddress;

  DescUsdtNetIsoTpAssertUser(infoPool->busInfo.busType == kDescUsdtNetBusTypeIsoTp, kDescNetAssertWrongBusType);

  /* Swap Source- and TargetAddress */
  sourceAddress = infoPool->busInfo.addressingInfo.isoTp.SourceAddress;
  infoPool->busInfo.addressingInfo.isoTp.SourceAddress  = infoPool->busInfo.addressingInfo.isoTp.TargetAddress;
  infoPool->busInfo.addressingInfo.isoTp.TargetAddress = sourceAddress;
#else
  /* Avoid warnings*/
  DESC_IGNORE_UNREF_PARAM(infoPool);
#endif
}

/*******************************************************************************
* NAME:              DescTransmitResponse
*
* CALLED BY:         CANdesc (Dispatcher)
* PRECONDITIONS:
*
* DESCRIPTION:       Response transmission function
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpTransmitResponse(t_descUsdtNetInfoPoolPtr infoPool)
{
  vuint8 result;
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# if ( defined (TP_ENABLE_DYNAMIC_CHANNELS) || defined (DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND) )
  vuint8 tpTxChannel;
# endif
#endif
#if defined (DESC_ENABLE_PARALLEL_OBD)
  DESC_TPCONTEXT_PARAM_DEF_LOCAL /* For OBD */
#endif
  volatile t_descUsdtNetInfoPoolPtr* lBusInfoPoolTxRef;

  DescUsdtNetIsoTpAssertUser(infoPool->busInfo.busType == kDescUsdtNetBusTypeIsoTp, kDescNetAssertWrongBusType);

#if defined (DESC_ENABLE_PARALLEL_OBD)
  DESC_TPCONTEXT_PARAM_VALUE = infoPool->descHandle;
#endif

#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
  tpTxChannel = g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE];
  infoPool->busHandle = tpTxChannel;
# else
#  if defined (DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND)
  tpTxChannel = g_descCan2TpChannelMap[DESC_COMM_CHANNEL_PARAM_WRAP_INDEX(infoPool->busInfo.comChannel)];
#  endif
# endif
#endif
  /* Avoid compiler optimization */
  lBusInfoPoolTxRef = &g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE];

  /* Busy ? */
  if(*lBusInfoPoolTxRef != V_NULL)
  {
    DescInterruptDisable();
    /* Still busy ? */
    if(*lBusInfoPoolTxRef != V_NULL)
    {
      t_descUsdtNetInfoPoolPtr lBusInfoPoolTxRefBackup;
      /* Push old content */
      lBusInfoPoolTxRefBackup = g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE];
      /* assign temporarly the new resource to be finalized */
      g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE] = infoPool;
      /* Cancel the transmission */
      DescConfirmation(TP_CHANNEL_TX_PARAM_FIRST kTpBusy);
      /* Pop old content */
      g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE] = lBusInfoPoolTxRefBackup;
      DescInterruptRestore();
      return;
    }
    DescInterruptRestore();
  }

  g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE] = infoPool;

#if defined (TP_ENABLE_EXTENDED_ADDRESSING)     || \
    defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING) || \
    defined (TP_ENABLE_MIXED_29_ADDRESSING)
  TpTxSetTargetAddress (TP_CHANNEL_TX_PARAM_FIRST infoPool->busInfo.testerId); /* use the abstract info for spontaneus responses */
#endif
#if ( kTpNumberOfCanChannels > 1 ) /* more than one canChannel ? */
# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
  TpTxSetCanChannel(TP_CHANNEL_TX_PARAM_FIRST infoPool->busInfo.comChannel);/* use the abstract info for spontaneus responses */
# endif
#endif
#if (TP_USE_EXTENDED_ADDRESSING           == kTpOn)      || \
    defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING)  || \
    defined (TP_ENABLE_MIXED_29_ADDRESSING)
# if (TP_USE_MULTIPLE_ECU_NR == kTpOn)
  TpTxSetEcuNumber(TP_CHANNEL_TX_PARAM_FIRST infoPool->busInfo.addressingInfo.isoTp.SourceAddress);
# endif
#endif
#if defined (TP_ENABLE_EXTENDED_ADDRESSING)
# if (TP_USE_MULTIPLE_BASEADDRESS == kTpOn)
  TpTxSetBaseAddress(TP_CHANNEL_TX_PARAM_FIRST infoPool->busInfo.addressingInfo.isoTp.BaseAddress);
# endif
#endif

#if (!defined (TP_ENABLE_DYNAMIC_CHANNELS) && !defined (TP_ENABLE_SINGLE_CHANNEL_TP))
# if defined (DESC_ENABLE_DESC_ON_MULTI_CAN) && \
     !defined (DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND)
/* In order to use CANdesc on multiple CANchannels, define DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND
 * in your user config file and define the CAN to TPconnection association e.g.:
  #define kDescCan2TpChannel_0    1 - if CAN 0 corresponds to TPconnection 1 */
#  error "CANdesc on multiple CANchannels needs DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND!"
# endif
#endif

#if (!defined (TP_ENABLE_DYNAMIC_CHANNELS) && !defined (TP_ENABLE_SINGLE_CHANNEL_TP))
  /* Overwrite the 0xFE value to avoid assertions to be miscalled. */
  infoPool->busHandle = TP_CHANNEL_TX_PARAM_VALUE;
  /* CAN-channel to TP-channel */
  DescUsdtNetIsoTpAssertUser((TP_CHANNEL_TX_PARAM_VALUE != kTpNoChannel), kDescNetAssertWrongIsoTpTxChannel);

# if defined (DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND)
  result = DanisIsoTpTransmit(TP_CHANNEL_TX_PARAM_VALUE, infoPool->resDataPtr, infoPool->dataLength);
# else
#  if defined(DESC_ENABLE_DOBT_SUPPORT)
#   error "DOBT on static multi TPMC is not supported!"
#  endif
  result = TpTransmitDiag(infoPool->resDataPtr, infoPool->dataLength);
# endif
#else
  result = DanisIsoTpTransmit(TP_CHANNEL_TX_PARAM_VALUE, infoPool->resDataPtr, infoPool->dataLength);
#endif
  if (result != kTpSuccess)
  { /* Cancel the transmission */
    DescConfirmation(TP_CHANNEL_TX_PARAM_FIRST result);
  }
}

#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
/*******************************************************************************
* NAME:              DescUsdtNetIsoTpGetRingBuffTxMinLen
*
* CALLED BY:         CANdesc (Dispatcher)
* PRECONDITIONS:
*
* DESCRIPTION:       Get Minimum Length
*
*
*******************************************************************************/
DESCNET_USDT_STATIC vuint16 DescUsdtNetIsoTpGetRingBuffTxMinLen(t_descUsdtNetInfoPoolPtr infoPool)
{
# if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
  vuint8  canType;
# endif
  DESC_IGNORE_UNREF_PARAM(infoPool);
# if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
  canType = DescGetCanType();
  if (canType==kTpCANFD2)
  {
    return (vuint16) kDescFirstFrameSize;
  }
  else
  {
    return 6;
  }
# else
  return (vuint16) kDescFirstFrameSize;
# endif
}
#endif

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpCopyToCan
*
* CALLED BY:         DescCopyToCAN
* PRECONDITIONS:
*
* DESCRIPTION:       Provides abstract copy functionality between CANdriver and DANIS.
*******************************************************************************/
static void DescUsdtNetIsoTpCopyToCan(TpCopyToCanInfoStructPtr infoStruct)
{
  vuint16_least i = infoStruct->Length;
  while(i != 0)
  {
    i--;
    infoStruct->pDestination[i] = infoStruct->pSource[i];
  }
}

/*******************************************************************************
* NAME:              DescCopyToCAN
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Callback for filling the data into the Tx buffer.
*                    Function name must be entered to the CANgen TP setup
*                    dialog in the fields "TpCopyToCan".
*******************************************************************************/
vuint8 TP_API_CALLBACK_TYPE DescCopyToCAN(TpCopyToCanInfoStructPtr infoStruct)
{
#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
  vuint8 returnValue = kTpFailed;
# if defined (DESC_USDTNET_ENABLE_MULTI_TP)
#  if ( defined (TP_ENABLE_DYNAMIC_CHANNELS) || defined (DESC_ENABLE_MULTI_TP_MULTI_CAN_WORKAROUND) )
  vuint8 TP_CHANNEL_TX_PARAM_ONLY = infoStruct->Channel;
#  endif
# endif
#endif

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  switch (g_descTpCtrl.txPath[infoStruct->Channel].type)
  {
    case kDescMainTransmission:
#endif
#if defined (DESC_USDTNET_ENABLE_RING_BUFFER)
# if defined (DESC_USDTNET_ENABLE_MULTI_TP)
      DescUsdtNetIsoTpAssertChannel(g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE]->busHandle == TP_CHANNEL_TX_PARAM_VALUE, kDescNetAssertWrongIsoTpTxChannel);
# endif
      if (g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE]->resType == kDescUsdtResponseRingBuffer)
      {
        t_descUsdtNetResult result;
# if defined(C_COMP_COSMIC_MCS12X_MSCAN12) && \
     defined(V_ENABLE_USED_GLOBAL_VAR)
        result = DescUsdtNetRingBufferCopyRoutine(g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE], &g_descCopyToCanData[0], (vuint8)infoStruct->Length);
# else
        result = DescUsdtNetRingBufferCopyRoutine(g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE], (DescUsdtNetMsg)infoStruct->pDestination, (vuint8)infoStruct->Length);
# endif
        if (result == kDescUsdtNetworkOk)
        {
# if defined(C_COMP_COSMIC_MCS12X_MSCAN12) && \
     defined(V_ENABLE_USED_GLOBAL_VAR)
          infoStruct->pSource = &g_descCopyToCanData[0];
          DescUsdtNetIsoTpCopyToCan(infoStruct);
# endif
          returnValue = kTpSuccess;
        }
      }
      else
      {
        DescUsdtNetIsoTpCopyToCan(infoStruct);
        returnValue = kTpSuccess;
      }
      return returnValue;
#else
      {
        DescUsdtNetIsoTpCopyToCan(infoStruct);
        return kTpSuccess;
      }
#endif

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
    case kDescAddTransmission:
      DescUsdtNetIsoTpCopyToCan(infoStruct);
      return kTpSuccess;   /*Everything's ok now*/
    default:
      /* Unknown type */
      break;
    }
    DescUsdtNetIsoTpAssertUserAlways(kDescAssertUnknownTpTransmissionType);
    return kTpSuccess;   /*Everything's ok now*/
#endif
}

/*******************************************************************************
* NAME:              DescConfirmation
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Provides the post transmission processing.
*                    Function name must be entered to the CANgen TP setup
*                    dialog in the fields "TpConfirmation".
*******************************************************************************/
void TP_API_CALLBACK_TYPE DescConfirmation(TP_CHANNEL_TX_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  t_descUsdtNetResult result;
  TP_CHANNEL_TX_PARAM_IGNORE_UNREF;

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  switch (g_descTpCtrl.txPath[tpTxChannel].type)
  {
    case kDescMainTransmission:
#endif
      {
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
        DescUsdtNetIsoTpAssertChannel(g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE]->busHandle == TP_CHANNEL_TX_PARAM_VALUE, kDescNetAssertWrongIsoTpTxChannel);
#endif
        /* Translate the TP parameter to the DESC_NET type */
        result = (t_descUsdtNetResult)((status != kTpSuccess) ? kDescUsdtNetworkAbort:kDescUsdtNetworkOk);

        DescUsdtNetFinishTransmission(g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE], result);
      /* No response any more is reset by CANdesc (DescUsdtNetFinishTransmission) */
      /* g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE]->resType = kDescUsdtResponseNone;*/
      }
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
      break;
    case kDescAddTransmission:
      /* Decrease pending count of additionally requests */
      DescUsdtNetIsoTpAssertUser((g_descAddChannelCtrl.count != 0), kDescAssertIllegalAddRequestCount);
      if(g_descAddChannelCtrl.count != 0)
      {
        g_descAddChannelCtrl.count--;
      }

      g_descAddChannelCtrl.channel[g_descTpCtrl.txPath[tpTxChannel].info].status = kDescContextIdle;
      break;
    default:
      /* Unknown type */
      DescUsdtNetIsoTpAssertUserAlways(kDescAssertUnknownTpTransmissionType);
      break;
  }
#endif

  g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE] = V_NULL;
}

/*******************************************************************************
* NAME:              DescTxErrorIndication
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Release the lock mechanism for Tx on error by sending.
*                    Function name must be entered to the CANgen TP setup
*                    dialog in the fields "TpXXXErrorIndication".
*******************************************************************************/
vuint8 TP_API_CALLBACK_TYPE DescTxErrorIndication(TP_CHANNEL_TX_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  vuint8 rc = kTpHoldChannel;

  /* Avoid warnings*/
  DESC_IGNORE_UNREF_PARAM(status);
  TP_CHANNEL_TX_PARAM_IGNORE_UNREF;

#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
  switch (g_descTpCtrl.txPath[tpTxChannel].type)
  {
    case kDescMainTransmission:
#endif
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
      if (g_busInfoPoolTxRef[TP_CHANNEL_TX_PARAM_VALUE]->busHandle == TP_CHANNEL_TX_PARAM_VALUE)
#endif
      {
        /* do nothing, rc already set */
      }
#if defined (DESC_USDTNET_ENABLE_MULTI_TP)
      else
      {
        rc = kTpFreeChannel;
      }
#endif
#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
      break;
    case kDescAddTransmission:
      rc = kTpFreeChannel;
      break;
    default:
      /* Unknown type */
      DescUsdtNetIsoTpAssertUserAlways(kDescAssertUnknownTpTransmissionType);
      rc = kTpFreeChannel;
      break;
  }
#endif
  /* Flush the response */
  DescConfirmation(TP_CHANNEL_TX_PARAM_FIRST status);
  return rc;
}

/*******************************************************************************
* NAME:              DescUsdtNetIsoTpReleaseInfoPool
*
* CALLED BY:         CANdesc (Dispatcher)
* PRECONDITIONS:
*
* DESCRIPTION:       Release of infopool
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetIsoTpReleaseInfoPool(t_descUsdtNetInfoPoolPtr infoPool)
{
  DescUsdtNetIsoTpAssertUser(infoPool->busInfo.busType == kDescUsdtNetBusTypeIsoTp, kDescNetAssertWrongBusType);
  infoPool->descHandle = kDescUsdtNetInvalidDescContext;
}


#if defined (DESC_ENABLE_BUSY_REPEAT_RESPONDER)
/******************************************************************************
* NAME:              DescBusyResponseHandler
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Busy response handler for additional received requests
*
*******************************************************************************/
static void DescBusyResponseHandler(void)
{
  vuint8_least addIter;
  vuint8       tpTxChannel;

  /* */
  if (g_descAddChannelCtrl.count != 0)
  {
    addIter = kDescNumAddRequestChannels;
    while(addIter != 0)
    {
      --addIter;
      if(g_descAddChannelCtrl.channel[addIter].status == kDescContextActiveProcess)
      {
        tpTxChannel = TpTxGetFreeChannel(kDescDiagAddConnection);
        if (tpTxChannel != kTpNoChannel)
        {
          g_descTpCtrl.txPath[tpTxChannel].type = kDescAddTransmission;
          /* store additional request channel number */
          g_descTpCtrl.txPath[tpTxChannel].info = (vuint8)addIter;
          /* copy the TP addressinformations from rx channel to tx channel */
          /* tpRxChannel is stored in 6.th byte of dummy buffer */
          TpTxSetResponse(g_descAddChannelCtrl.channel[addIter].buffers.res.tpRxChannel, tpTxChannel);

          g_descAddChannelCtrl.channel[addIter].status = kDescContextActiveTx;

          if (DanisIsoTpTransmit(tpTxChannel, g_descAddChannelCtrl.channel[addIter].buffers.res.resBuffer, 3) == kTpSuccess)
          {
            TpRxResetChannel(g_descAddChannelCtrl.channel[addIter].buffers.res.tpRxChannel);
          }
          else
          { /* If we can not send the data, we have to terminate this channel and try it at next cycle */
            g_descAddChannelCtrl.channel[addIter].status = kDescContextActiveProcess;
            TpTxResetChannel(tpTxChannel);
          }
        }
      }
    }
  }
}
#endif

#if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
/******************************************************************************
* NAME:              DescGetCanType
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Request for CAN type
*
*******************************************************************************/
vuint8  DescGetCanType()
{
  return g_descCanType;
}
#endif

#if defined(TP_FUNC_ENABLE_RECEPTION) && \
    !defined (TP_ENABLE_EXTENDED_ADDRESSING)
/*******************************************************************************
* NAME:              DescGetFuncBuffer
*
* CALLED BY:         Transport layer
* PRECONDITIONS: 
*
* DESCRIPTION:       StartOfFrame reception function
*                    
*******************************************************************************/
TP_MEMORY_MODEL_DATA vuint8* TP_API_CALLBACK_TYPE DescGetFuncBuffer(vuint16 dataLength)
{
  DescUsdtNetMsg returnValue = V_NULL;

# if (defined (DESC_ENABLE_FUNCREQ_TA_CHECK) || defined (DESC_ENABLE_FUNCREQ_SA_CHECK))
  DescBool addressCheckResult;

#  if defined (DESC_ENABLE_FUNCREQ_TA_CHECK)
  addressCheckResult = DescOemCheckFuncTargetAddress(TpFuncGetTargetAddress());
  if(addressCheckResult == kDescTrue)
#  endif
  {
#  if defined (DESC_ENABLE_FUNCREQ_SA_CHECK)
    addressCheckResult = DescOemCheckFuncSourceAddress(TpFuncGetSourceAddress());
#  endif
  }

  if(addressCheckResult == kDescTrue)
# endif
  {
# if defined (DESC_ENABLE_PARALLEL_OBD)
    DESC_TPCONTEXT_PARAM_DEF_LOCAL /* For OBD */
    DESC_TPCONTEXT_PARAM_VALUE = DescDispatchServiceContext(TpFuncGetCanBuffer()[0]);
# endif
    if (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle == kDescUsdtNetInvalidDescContext)
    {
      t_descUsdtNetResult result;

      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.busType   = kDescUsdtNetBusTypeIsoTp;
# if ( kCanNumberOfChannels > 1 ) /* more than one canChannel ? */
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.CanChannel = TpFuncGetCanChannel();
      /* Make the communication channel ID visible to the above layer */
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.comChannel = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.CanChannel;
# endif
# if defined (TP_ENABLE_EXTENDED_ADDRESSING)      || \
     defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING)  || \
     defined (TP_ENABLE_MIXED_29_ADDRESSING)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.SourceAddress = TpFuncGetSourceAddress();
      /* Make the tester ID visible to the above layer */
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.testerId = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.SourceAddress;

    /* g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = TpRxGetReceivedTargetAddress (TP_CHANNEL_RX_PARAM_VALUE); */
# endif
# if defined (DESC_USDTNET_ENABLE_MULTI_TP)
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle         = 0xfe;
# endif
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqType           = kDescUsdtNetReqTypeFunctional;
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].resType           = kDescUsdtResponseNone;
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqDataPtr        = g_descBuffer[DESC_TPCONTEXT_PARAM_VALUE];
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].resDataPtr        = g_descBuffer[DESC_TPCONTEXT_PARAM_VALUE];
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].dataLength        = dataLength;
      g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle        = DESC_TPCONTEXT_PARAM_VALUE; /* Write used context */
      /* Check if Desc itself is free */
      result = DescUsdtNetStartReception(&g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE]);
      if(result == kDescUsdtNetworkOk)
      { /* it is */
        returnValue = g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].reqDataPtr;
# if defined (DESC_ENABLE_PARALLEL_OBD)
       /* store the working context type */
       g_busInfoPoolRxRef[kDescUsdtNetFuncInfPoolRef] = &g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE];
# endif
      }
      else
      {
        g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].descHandle = kDescUsdtNetInvalidDescContext;
      }
    }
  }
  /* discard reception */
  return returnValue;
}

/*******************************************************************************
* NAME:              DescFuncReqInd
*
* CALLED BY:         Transport layer
* PRECONDITIONS: 
*
* DESCRIPTION:       Rx path for physical requests.
*                    Function name must be entered to the CANgen OSEK-TP Options 
*                    dialog in the fields "RxIndication".
*******************************************************************************/
void TP_API_CALLBACK_TYPE DescFuncReqInd(vuint16 dataLen)
{
# if defined (DESC_ENABLE_PARALLEL_OBD)
  DESC_TPCONTEXT_PARAM_DEF_LOCAL
# endif

  /* Avoid warnings*/
  DESC_IGNORE_UNREF_PARAM(dataLen);

# if defined (DESC_ENABLE_PARALLEL_OBD)
   /* store the working context type */
  DESC_TPCONTEXT_PARAM_VALUE = g_busInfoPoolRxRef[kDescUsdtNetFuncInfPoolRef]->descHandle;
# endif

# if defined (DESC_USDTNET_ENABLE_MULTI_TP)
  if (g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busHandle == 0xfe)
# endif
  {
    /*-----------------------------*/
    /*Transport protocol management*/
    /*-----------------------------*/
# if defined (TP_ENABLE_DYNAMIC_CHANNELS)
#  if defined (TP_ENABLE_NORMAL_ADDRESSING)       || \
      defined (TP_ENABLE_MIXED_11_ADDRESSING)
    g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.ReceiveID = TpFuncGetReceiveCanID();
    TpFuncSetResponse(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
#  endif
#  if defined(TP_ENABLE_CANFD)
#   if defined (TP_ENABLE_SINGLE_CHANNEL_TP)
    g_descCanType = TpTxGetCanType();
#   else
    g_descCanType = TpTxGetCanType(g_descUsdtNetTpTxChannel[DESC_TPCONTEXT_PARAM_VALUE]);
#   endif
#  endif
# endif
# if (TP_USE_MULTIPLE_ECU_NR == kTpOn)
    g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = TpFuncGetTargetAddress();
# else
#  if (TP_USE_EXTENDED_ADDRESSING == kTpOn) || \
      defined (TP_ENABLE_NORMAL_FIXED_ADDRESSING) || \
      defined(TP_FUNC_ENABLE_EXTENDED_ADDRESSING) || \
      defined (TP_ENABLE_MIXED_29_ADDRESSING)
    g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.TargetAddress = kDescEcuNumber;
#  endif
# endif
# if (TP_USE_EXTENDED_ADDRESSING == kTpOn)
#  if (TP_USE_MULTIPLE_BASEADDRESS == kTpOn)
    g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE].busInfo.addressingInfo.isoTp.BaseAddress = TpFuncGetBaseAddress();
#  endif
# endif
    /* Reception has finished */
    DescUsdtNetFinishReception(&g_descUsdtNetInfoPoolIsoTp[DESC_TPCONTEXT_PARAM_VALUE], kDescUsdtNetworkOk);
    /* Reset the channel */
    TpFuncResetChannel();
  }
}
#endif

#if defined(DESC_ENABLE_NODE_POWER_CONTROL) || (kDescNumContexts > 1) || defined(DESC_ENABLE_SPONTANEOUS_RES)
/*******************************************************************************
* NAME:              DescNetworkOnceInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:
*
* DESCRIPTION:       Initilizes the network subcomponent specific data.
*
*******************************************************************************/
static void DescNetworkOnceInit(void)
{
# if (kDescNumContexts > 1)
  g_descActiveRequestsMask = 0;
# endif

# if defined(DESC_ENABLE_NODE_POWER_CONTROL)
#  if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  g_descNpmTimer = 0;
#  endif

  /* Not necessary since the timer is not running
   * g_descDoReloadNpmTimer = 0;
   */

  /* Reset channel map and queue */
  g_descCanChannelMap = 0;
  g_descCanChannelMapQueue = 0;
# endif
# if defined (DESC_ENABLE_SPONTANEOUS_RES)
  /* Initialization of the spontaneous pool */
  g_descUsdtNetSpontanResInfoPool.resType = kDescUsdtResponseNone;
  /* will be done at transmission time:
  g_descUsdtNetSpontanResInfoPool.descHandle = kDescPrimContext;
  g_descUsdtNetSpontanResInfoPool.reqDataPtr = V_NULL;
  g_descUsdtNetSpontanResInfoPool.busInfo.busType = kDescUsdtNetBusTypeIsoTp;
  */
# endif
  /* Don't forget the USDT NET */
  DescNetworkInit();
}
#endif

/*******************************************************************************
* NAME:              DescNetworkIterInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:
*
* DESCRIPTION:       Initilizes the network subcomponent context specific data.
*
*******************************************************************************/
static void DescNetworkIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Init the buffer state mashine */
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].txState = kDescUsdtNetworkOk;
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isApplError = 0;
#if defined (DESC_ENABLE_SUPPLIER_CALLBACKS)
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSupplPost = 0;
#endif
#if defined (DESC_ENABLE_SPRMIB_OVERRIDE)
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSPRMIBOverridden = 0;
#endif
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModeNormal;

  /* Interrupt context controller */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextIdle;
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].isContextLocked = 0;
#if defined (DESC_ENABLE_FORCE_RCR_RP)
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState = kDescForcedRcrRpIdle;
#endif

  /* Prepare for RCR-RP negative response - the SID will be filled
  when the T2 timer expires */
  g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE][0] = kDescNegResSId;
  g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE][2] = kDescNrcResponsePending;

#if defined (DESC_ENABLE_RES_RINGBUFFER)
  DescRingBufferIterInit(DESC_CONTEXT_PARAM_ONLY);
#endif

}

#if (kDescNumContexts > 1)
/*******************************************************************************
* NAME:              DescResetConnectionActiveMultipleContext
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       Deactivates the connection
*******************************************************************************/
static void DescResetConnectionActiveMultipleContext(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
   DescInterruptDisable();
   g_descActiveRequestsMask&= (vuint8)~(vuint8)(kDescDescConnectionStateActive<<DESC_CONTEXT_PARAM_VALUE);
   DescInterruptRestore();
}
#endif

/*******************************************************************************
* NAME:              DescReleaseContext
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       releases the RX path and manages the S1 timer
*******************************************************************************/
static void DescReleaseContext(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_ENABLE_DESCICN_SUPPORT)
  /* Check if this instance is a internal request */
  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqType != kDescUsdtNetReqTypeInternal)
#endif
  {
    /* Force reloading the S1 timer (will affect only if timer active) */
    g_descDoReloadS1Timer = kDescTrue;
    /* Notify the application */
    ApplDescOnEndOfProcExt();
  }
  /* Deactivate the connection */
  DescResetConnectionActive(DESC_CONTEXT_PARAM_VALUE);
  /* Release context */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].isContextLocked = 0;
  /* Release the network resource */
  DescUsdtNetAbsReleaseInfoPool(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr );
}

#if defined (DESC_ENABLE_SPONTANEOUS_RES)
/*******************************************************************************
* NAME:              DescSendSpontaneousResponse
*
* CALLED BY:         Desc internal
* PRECONDITIONS:
*
* DESCRIPTION:       Any time can make the application a single frame response.
*******************************************************************************/
DescBool DescSendSpontaneousResponse(DescMsg resData, DescMsgLen resLen, t_descUsdtNetBus* pBusInfo, t_descUsdtNetResType resType)
{
# if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
#  if !defined (TP_ENABLE_SINGLE_CHANNEL_TP)
  vuint8 tpTxChannel;
#  endif
# endif

  if(g_descUsdtNetSpontanResInfoPool.resType == kDescUsdtResponseNone)
  {
    DescInterruptDisable();
    if(g_descInterruptContextCtrl[kDescPrimContext].activity == kDescContextIdle)
    {
      /* Lock the component for RX */
      g_descInterruptContextCtrl[kDescPrimContext].isContextLocked = 1;
      DescInterruptRestore();

      /* Store into the global variables */
      g_descUsdtNetSpontanResInfoPool.descHandle = kDescPrimContext;
      g_descUsdtNetSpontanResInfoPool.reqDataPtr = V_NULL;
      g_descUsdtNetSpontanResInfoPool.resDataPtr = resData;
      g_descUsdtNetSpontanResInfoPool.busInfo = *pBusInfo;
      g_descUsdtNetSpontanResInfoPool.dataLength = resLen;
      g_descUsdtNetSpontanResInfoPool.resType = resType;

# if defined(TP_ENABLE_DYNAMIC_CHANNELS) && defined(TP_ENABLE_CANFD)
      if (resType == kDescUsdtResponseSpontaneous)
      {
#  if defined (TP_ENABLE_SINGLE_CHANNEL_TP)
        TpTxSetCanType(pBusInfo->canType);
#  else
        tpTxChannel = g_descUsdtNetTpTxChannel[kDescPrimContext];
        TpTxSetCanType(tpTxChannel, pBusInfo->canType);
#  endif
      }
      else
      {
#  if defined (TP_ENABLE_SINGLE_CHANNEL_TP)
        TpTxSetCanType(kTpCAN20);
#  else
        tpTxChannel = g_descUsdtNetTpTxChannel[kDescPrimContext];
        TpTxSetCanType(tpTxChannel, kTpCAN20);
#  endif
      }
# endif

      DescUsdtNetAbsTransmitResponse(&g_descUsdtNetSpontanResInfoPool);
      return kDescTrue;
    }
    /* Ignore */
    DescInterruptRestore();
  }
  return kDescFalse;
}
#endif


#if defined (DESC_ENABLE_POS_RES_ON_SET_SPRMIB)
/* Not needed */
#else
/*******************************************************************************
* NAME:              DescIsTesterPresent
*
* CALLED BY:         Desc
* PRECONDITIONS:
*
* DESCRIPTION:
*
*******************************************************************************/
static DescBool DescIsTesterPresent(t_descUsdtNetInfoPoolPtr infoPool)
{
  DescBool returnValue = kDescFalse;

  if ((infoPool->reqType == kDescUsdtNetReqTypeFunctional) && /* Only for functional request */
      (infoPool->reqDataPtr[0] == 0x3e) &&                /* Is it a TesterPresent? */
      (infoPool->reqDataPtr[1] == 0x80) &&                /* Is the SPRIMB set?*/
      (infoPool->dataLength == 0x02))                     /* Do little format check */
  {
    /* Reloading the S1 timer (will affect only if timer active) will be performed at DescReleaseContect call */
    returnValue = kDescTrue;
  }
  return returnValue;
}
#endif

#if defined(DESC_ENABLE_PERIODIC_MODE) && defined (DESC_ENABLE_SCHEDULER_UUDT_TRANSMITTER)
/*******************************************************************************
* NAME:              DescUudtNetFinishTransmission
*
* CALLED BY:         Transport layer
* PRECONDITIONS:
*
* DESCRIPTION:       Provides the post transmission processing.
*                    The used resources should be freed
*
*******************************************************************************/
DESCNET_UUDT_STATIC void DescUudtNetFinishTransmission(t_descUudtNetInfoPoolPtr infoPool, t_descUudtNetResult status)
{
  DESC_IGNORE_UNREF_PARAM(infoPool);
  DESC_IGNORE_UNREF_PARAM(status);
  DescDoSchedulePostProcessing();
}
#endif

/*******************************************************************************
* NAME:              DescSendPosRespFBL
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Enforces a transmission of a specific pos response.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescSendPosRespFBL(t_descFblPosRespType posRespSId)
{
  t_descUsdtNetBus busInfo;
  vuintx result;

  result = ApplDescInitPosResFblBusInfo(&busInfo);
  if(kDescOk == result)
  {
    switch(posRespSId)
    {
      /*-------------------------------------*/
      case kDescSendFblPosRespEcuHardReset:
      /*-------------------------------------*/
        g_descFblPosRes[0] = 0x51;
        g_descFblPosRes[1] = 0x01;
        (void)DescSendSpontaneousResponse(g_descFblPosRes, 2, &busInfo, kDescUsdtResponseSpontaneous);
        break;
      /*-------------------------------------*/
      case kDescSendFblPosRespDscDefault:
      /*-------------------------------------*/
        {
#if defined (DESC_ENABLE_P2_TIME_REPORT)
          vuint16   p2Time, p2ExTime;
          DescGetSessionTimings(kDescStateSessionDefault, &p2Time, &p2ExTime);

          g_descFblPosRes[0] = 0x50;
          g_descFblPosRes[1] = 0x01;
          g_descFblPosRes[2] = DescGetHiByte(p2Time);
          g_descFblPosRes[3] = DescGetLoByte(p2Time);
          g_descFblPosRes[4] = DescGetHiByte(p2ExTime);
          g_descFblPosRes[5] = DescGetLoByte(p2ExTime);
          (void)DescSendSpontaneousResponse(g_descFblPosRes, 6, &busInfo, kDescUsdtResponseSpontaneous);
#else
          g_descFblPosRes[0] = 0x50;
          g_descFblPosRes[1] = 0x01;
          (void)DescSendSpontaneousResponse(g_descFblPosRes, 2, &busInfo, kDescUsdtResponseSpontaneous);
#endif
        }
        break;
      default:
        /* Invalid value */
        DescAssertUserAlways(kDescAssertWrongFblPosResParameterValue);
        break;
    }
  }
}

/*******************************************************************************
* NAME:              DescNetworkInitPowerOn
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Reports the current state of the CANdesc component
*
*******************************************************************************/
static void DescNetworkInitPowerOn(void)
{
  DescUsdtNetAbsInitPowerOn();
  DescUudtNetInitPowerOn();
}


/*******************************************************************************
* NAME:              DescNetworkInit
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Reports the current state of the CANdesc component
*
*******************************************************************************/
static void DescNetworkInit(void)
{
  DescUsdtNetAbsInit();
  DescUudtNetInit();
}

/*******************************************************************************
* NAME:              DescGetActivityState
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Reports the current state of the CANdesc component
*
*******************************************************************************/
vuint8 DESC_API_CALL_TYPE DescGetActivityState(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  return g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity;
}

#if defined(DESC_ENABLE_DESCICN_SUPPORT)
/*******************************************************************************
* NAME:              DescICNRxMsgInd
*
* CALLED BY:         Desc Network Layer
* PRECONDITIONS:
*
* DESCRIPTION:
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescICNRxMsgInd(t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status)
{
  switch(infoPool->busInfo.addressingInfo.descICN.Client)
  {
# if defined(DESC_ENABLE_DYN_DEFINED_DID_CLIENT)
    case kDescIcnClientDynDefDid:
      DescDynDefinedDidRxMsgInd(infoPool, status);
      break;
# endif
# if defined(DESC_ENABLE_DYN_DEFINED_DPID_CLIENT)
    case kDescIcnClientDynDefDpid:
      DescDynDefinedDpidRxMsgInd(infoPool, status);
      break;
# endif
# if defined(DESC_ENABLE_ROE_CLIENT)
    case kDescIcnClientRoe:
      DescRoeRxMsgInd(infoPool, status);
      break;
# endif
    default:
      DescAssertInternalAlways(kDescAssertInvalidDescICNClient);
      break;
  }
}
#endif


/*******************************************************************************
* NAME:              DescUsdtNetAbsStartReception
*
* CALLED BY:         Desc Network Layer
* PRECONDITIONS:
*
* DESCRIPTION:       StartOfFrame reception function
*
*
*******************************************************************************/
DESCNET_USDT_STATIC t_descUsdtNetResult DescUsdtNetAbsStartReception(t_descUsdtNetInfoPoolPtr infoPool)
{
  t_descUsdtNetResult returnValue = kDescUsdtNetworkFailed;

  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].isContextLocked == 0)
  {
#if defined (DESC_ENABLE_CHECK_MSG_RX_ACCEPTANCE)
    if(DescOemCheckAcceptance(infoPool) != kDescFalse)
#endif
    {
      /* Lock the buffer */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].isContextLocked = 1;
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].activity |= kDescContextActiveRxBegin;

      /* Store infoPool reference */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].infoPoolPtr = infoPool;

      /* Set connection active for S1 timer check */
      DescSetConnectionActive(infoPool->descHandle);

#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
      DescSetNpmOnCanChannelActive(infoPool->busInfo.comChannel, g_descCanChannelMapQueue);
#endif
#if defined (DESC_ENABLE_ACCESS_TESTER_ADDRESS_API)
      /* Store the ISO TP Source Address */
      g_descTesterAddress[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)] = infoPool->busInfo.testerId;
#endif
      /* Notify the application */
#if defined (DESC_ENABLE_DESCICN_SUPPORT)
      /* Check if this instance is a internal request */
      if(infoPool->reqType != kDescUsdtNetReqTypeInternal)
#endif
      {
        ApplDescOnBeginOfProcExt();
      }
      /* Notify the implementation */
      DescOemOnRxStart(infoPool);
      returnValue = kDescUsdtNetworkOk;
    }
  }
  return returnValue;
}


/*******************************************************************************
* NAME:              DescUsdtNetAbsFinishReception
*
* CALLED BY:         Desc Network Layer
* PRECONDITIONS:
*
* DESCRIPTION:       reception has finished
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetAbsFinishReception(t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status)
{
  /* Clear this state always!!! (in error case lefts ContextIdle then) */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].activity &= (DescContextActivity)(~kDescContextActiveRxBegin);
  if ((status == kDescUsdtNetworkOk) &&
      (g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].infoPoolPtr == infoPool))
  {
    /* Check if a TesterPresent is requested with SuppresPosBit set to not lock Desc */
    DescBool result = DescIsTesterPresent(infoPool);
    if (result == kDescFalse)
    {
      /* On physical requested message actions (for S1 timer normally)*/
      DescOemOnReqInd(infoPool->descHandle);

      g_descMsgContext[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].busInfo = infoPool->busInfo;

      DescUsdtNetAbsPrepareResponse(infoPool);

      /* Sets indication flag for cyclic task */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(infoPool->descHandle)].activity |= kDescContextActiveRxEnd;
      /*TBD: DescSetEvent(DescDSDTask, descRequestReceived)*/
      return;
    }
  }
  else
  { /* Reception error had happened */
    DescOemOnRxErrorInd(status);
  }
  DescReleaseContext(DESC_CONTEXT_PARAM_WRAPPER_ONLY(infoPool->descHandle));
}

/*******************************************************************************
* NAME:              DescUsdtNetAbsFinishTransmission
*
* CALLED BY:         Desc Network Layer
* PRECONDITIONS:
*
* DESCRIPTION:       transmission has finished
*
*
*******************************************************************************/
DESCNET_USDT_STATIC void DescUsdtNetAbsFinishTransmission(t_descUsdtNetInfoPoolPtr infoPool, t_descUsdtNetResult status)
{
  DESC_CONTEXT_PARAM_DEF_LOCAL

#if(kDescNumContexts > 1)
  DESC_CONTEXT_PARAM_ONLY = infoPool->descHandle;
#endif

  if (status == kDescUsdtNetworkOk)
  {
    /* nothing to do */
  }
  else
  {
    DescOemOnTxErrorInd(status);
  }

  switch (infoPool->resType)
  {
  case kDescUsdtResponsePositive:
    /* fall through */
  case kDescUsdtResponseNegative:
    /* fall through */
  case kDescUsdtResponseRingBuffer:
    /* Make post processing not always success (if called from the error indication)*/
    DescDoPostProcessing(DESC_CONTEXT_PARAM_FIRST status);
#if defined(DESC_ENABLE_SPONTANEOUS_RES)
    /* fall through */
  case kDescUsdtResponseRoe:
    /* fall through */
  case kDescUsdtResponseSpontaneous:
    /* fall through */
  case kDescUsdtResponseSpontaneousAppl:
# if defined (DESC_ENABLE_PROTOCOL_UDS) || defined (DESC_ENABLE_PROTOCOL_UDS2012)
    if(infoPool->resType == kDescUsdtResponseSpontaneousAppl)
    {
       vuint8 result;
      /* Interpret the status */
      result = (vuint8)((status == kDescUsdtNetworkOk)?kDescOk:kDescFailed);
      /* Confirm the forced RCR-RP response transmission */
      ApplDescSpontaneousResponseConfirmation(DESC_CONTEXT_PARAM_FIRST result);
      /* no break - fall through */

    }
#  if defined (DESC_ENABLE_ROE_SUPPORT)
    else
    {
      if(infoPool->resType == kDescUsdtResponseRoe)
      {
        /* Notify the ROE handler */
        DescRoeResponseConfirmation();
      }
    }
#  endif
    /* Release context here */
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].isContextLocked = 0;
# endif
#endif
#if defined (DESC_USDTNET_ENABLE_VECTOR_ISO_TP)
  /* Save code */
#else
    if (infoPool->resDataPtr != infoPool->reqDataPtr )
    {
      DescUsdtNetReleaseTransmissionObj(infoPool);
    }
#endif
    break;
#if defined (DESC_ENABLE_FORCE_RCR_RP)
  case kDescUsdtResponseNegativeApplRCR_RP:
    {
      vuint8 result;
      /* Interpret the status */
      result = (vuint8)((status == kDescUsdtNetworkOk)?kDescOk:kDescFailed);
      /* Confirm the forced RCR-RP resposne transmission */
      ApplDescRcrRpConfirmation(DESC_CONTEXT_PARAM_FIRST result);
      /* no break - fall through */
    }
#endif
    /* fall through */
  case kDescUsdtResponseNegativeRCR_RP:
#if defined (DESC_USDTNET_ENABLE_VECTOR_ISO_TP)
  /* Save code */
#else
    if (infoPool->resDataPtr != g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE])
    {
      infoPool->resDataPtr = V_NULL;
      DescUsdtNetReleaseTransmissionObj(infoPool);
    }
#endif
    break;
#if defined (DESC_ENABLE_SCHEDULER_USDT_TRANSMITTER)
  case kDescUsdtResponsePeriodic:
    DescDoSchedulePostProcessing();
    break;
#endif
  default:
    break;
  }
  /* Reset response type */
  infoPool->resType = kDescUsdtResponseNone;
}

/*******************************************************************************
* NAME:              DescTransmitRcrRp
*
* CALLED BY:         Desc
* PRECONDITIONS:
*
* DESCRIPTION:       Transmission of RCR-RP
*
*******************************************************************************/
static void DescTransmitRcrRp(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_USDTNET_ENABLE_VECTOR_ISO_TP)
  /* Save code */
#else
  /* The response message is already filled with the necessary information */
  if (g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr == V_NULL)
  {
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr = DescUsdtNetGetTransmissionPtr(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr);
    memcpy(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr,g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE],3);
  }
  else
#endif
  {
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr = g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE];
  }
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->dataLength = kDescNegResLen;

  DescUsdtNetAbsTransmitResponse(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr);
  DescReloadT2TimerWithP3maxTime(DESC_CONTEXT_PARAM_VALUE);
  /* Custom management in case of timeout of T2 */
  DescOemOnT2Timeout(DESC_CONTEXT_PARAM_VALUE);
#if defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
  g_descRcrrpLimitCounter[DESC_CONTEXT_PARAM_VALUE]--;
#endif
#if defined (DESC_ENABLE_ALL_RES_AFTER_RCRRP)
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].rcrRpSent = 1;
#endif
}

#if defined (DESC_ENABLE_ACCESS_TESTER_ADDRESS_API)
/*******************************************************************************
* NAME:              DescGetTesterAddress
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Returns the tester address of the last request.
*******************************************************************************/
vuint8 DESC_API_CALL_TYPE DescGetTesterAddress(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  return g_descTesterAddress[DESC_CONTEXT_PARAM_VALUE];
}
#endif

/*******************************************************************************
* NAME:              DescGetCurrentBusInfo
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Returns the current communication parameters.
*******************************************************************************/
t_descUsdtNetBus* DESC_API_CALL_TYPE DescGetCurrentBusInfo (DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  return &(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].busInfo);
}

#if defined (DESC_ENABLE_RES_RINGBUFFER) && defined (DESC_ENABLE_PID_LIST_MODE)
/*******************************************************************************
* NAME:              DescGetMaxRestByteSize
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Returns the maimum possible rest bytes in case of multiple PID and ring buffer.
*******************************************************************************/
static vuint8 DescGetMaxRestByteSize(DescMsgContext* pMsgContext)
{
    DESC_IGNORE_UNREF_PARAM(pMsgContext);
    return (kDescConsecutiveFrameSize-1);
}
#endif

/*******************************************************************************
* NAME:              DescTimingIterInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:     
*
* DESCRIPTION:       Initilizes the timing subcomponent context data.
*
*******************************************************************************/
static void DescTimingIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  DescDeactivateT2Timer(DESC_CONTEXT_PARAM_VALUE);
  DescDeactivateLimiter(DESC_CONTEXT_PARAM_VALUE);
}

#if defined (DESC_ENABLE_FORCE_RCR_RP)
/*******************************************************************************
* NAME:              DescForceRcrRpResponse
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Forces the CANdesc to send immediately a RCR-RP response.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescForceRcrRpResponse(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Check for correct context */
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);
  /* Check if allowed such force RCR-RP to be used) 
   * To be able to send RCR-RP teh requested service must be a service which will send a response. */
  DescAssertUser(((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq & g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType) != 0), kDescAssertInvalidUsageOfForceRcrRpApi);
  /* Mark that a RCR-RP shall be sent immediately */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState = kDescForcedRcrRpCharged;
}
#endif

/* Functions */
/*******************************************************************************
* NAME:              DescTimingOnceInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:     
*
* DESCRIPTION:       Initilizes the network subcomponent common data.
*
*******************************************************************************/
static void DescTimingOnceInit(void)
{
#if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
  /* Set the default session reference timings */
  g_descCurrSessionNumber = 0;
#endif

  /* Clear the flag to avoid one DescTask callcycle time S1 timeout jitter */
  g_descDoReloadS1Timer = kDescFalse;
  /* Deactivate the timers */
  DescDeactivateS1Timer();
}

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
/*******************************************************************************
* NAME:              DescNpmSetSleepInd
*
* CALLED BY:         DescTask
* PRECONDITIONS:     
*
* DESCRIPTION:       Timer which will be running only when DESC not idle mode
*
*******************************************************************************/
static void DescNpmSetSleepInd(void)
{
# if defined(DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
  vuint8_least channel = kDescNumCommChannels;
  while(channel > 0)
  {
    channel--;
# endif
    if(DescIsNpmOnCanChannelActive(channel, g_descCanChannelMap))
    {
      DescNpmSetSleepReady(channel);
    }
# if defined(DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
  }
# endif
  /* Reset channel map */
  g_descCanChannelMap = 0;
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  /* Stop always here (even in dpmTimeout) */
  g_descNpmTimer = 0;
# endif
}
#endif

#if defined (DESC_ENABLE_NODE_POWER_CONTROL)
/*******************************************************************************
* NAME:              DescNpmProcessQueue
*
* CALLED BY:         DescTask
* PRECONDITIONS:     
*
* DESCRIPTION:       Timer which will be running only when DESC not idle mode
*
*******************************************************************************/
static void DescNpmProcessQueue(void)
{
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  DescComChannelBitMaskOptType canChannelMapMirror;
  /* Something in the queue */
  if(g_descCanChannelMapQueue != 0)
  {
    /* Activate / reload the DPM timer (it is not running during reception and service processing) */
    g_descNpmTimer = kDescNpmTimerTicks;

    /* Make a safe copy of the queue */
    DescInterruptDisable();
    canChannelMapMirror = g_descCanChannelMapQueue;
    DescInterruptRestore();
# endif
    /* Merge queued and already active channels => leave only the new CAN channels */
    DescGetMirroredQueue(g_descCanChannelMapQueue, canChannelMapMirror) &= (DescComChannelBitMaskOptType)(~g_descCanChannelMap);
# if defined(DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
    {
      vuint8_least channel = kDescNumCommChannels;
      while(channel != 0)
      {
        channel--;
# endif
        if(DescIsNpmOnCanChannelActive(channel, DescGetMirroredQueue(g_descCanChannelMapQueue, canChannelMapMirror)))
        {
          DescNpmSetKeepAwake(channel);
        }
# if defined(DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
      }
    }
# endif
    /* Merge the queued channel to the activity map */
    g_descCanChannelMap |= DescGetMirroredQueue(g_descCanChannelMapQueue, canChannelMapMirror);
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
    DescInterruptDisable();
# endif
    /* Clear already processed flags */
    g_descCanChannelMapQueue &= (DescComChannelBitMaskOptType)(~g_descCanChannelMap);
# if defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
    DescInterruptRestore();
  }
# endif
}
#endif

#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
/*******************************************************************************
* NAME:              DescOemNpmTimer
*
* CALLED BY:         DescTask
* PRECONDITIONS:     
*
* DESCRIPTION:       Timer which will be running only in DESC idle mode and default session active
*
*******************************************************************************/
static void DescOemNpmTimer(void)
{
  /* ----------------*/
  /* Activity Timeout*/
  /* ----------------*/
  if(g_descNpmTimer != 0)
  {
    /* Decrement timer */
    g_descNpmTimer--;
    /* Check for timeout */
    if(g_descNpmTimer == 0)
    {
      /* The same behavior as in a non-default session timeout */
      DescNpmSetSleepInd();
    }
  }
}
#endif

/*******************************************************************************
* NAME:              DescStateOnceInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:     
*
* DESCRIPTION:       Initilizes the state subcomponent common data.
*
*******************************************************************************/
static void DescStateOnceInit(void)
{
  DescStateInit();
}

void DESC_API_CALL_TYPE DescStateInit(void)
{
  g_descCurState.stateSession = kDescStateSessionDefault;
  g_descCurState.stateSecurityAccess = kDescStateSecurityAccessLocked;
}


DescStateGroup DESC_API_CALL_TYPE DescGetStateSession(void)
{
  return g_descCurState.stateSession;
}


void DESC_API_CALL_TYPE DescSetStateSession(DescStateGroup descState)
{
  /* The new state shall not be zero */
  DescAssertCommon((descState != 0), kDescAssertZeroStateValue);
  DescOemOnTransitionSession(descState, g_descCurState.stateSession);
  ApplDescOnTransitionSession(descState, g_descCurState.stateSession);
  g_descCurState.stateSession = CANBITTYPE_CAST descState;
}


DescStateGroup DESC_API_CALL_TYPE DescGetStateSecurityAccess(void)
{
  return g_descCurState.stateSecurityAccess;
}


void DESC_API_CALL_TYPE DescSetStateSecurityAccess(DescStateGroup descState)
{
  /* The new state shall not be zero */
  DescAssertCommon((descState != 0), kDescAssertZeroStateValue);
  DescOemOnTransitionSecurityAccess(descState, g_descCurState.stateSecurityAccess);
  ApplDescOnTransitionSecurityAccess(descState, g_descCurState.stateSecurityAccess);
  g_descCurState.stateSecurityAccess = CANBITTYPE_CAST descState;
}


static DescNegResCode DescCheckState(V_MEMROM1 DescStateInfo V_MEMROM2 V_MEMROM3* refState)
{
  if((refState->stateSession & g_descCurState.stateSession) == 0)
  {
    return kDescNrcRejectStateSession;
  }
  if((refState->stateSecurityAccess & g_descCurState.stateSecurityAccess) == 0)
  {
    return kDescNrcRejectStateSecurityAccess;
  }
  return kDescNrcNone;
}


static void DescSetState(DescSvcInstIndex svcInstHandle)
{
  V_MEMROM1 DescStateInfo V_MEMROM2 V_MEMROM3* curRefState;
  if(g_descSvcInst[svcInstHandle].setStateIndex != kDescStateNoTransition)
  {
    curRefState = &g_descStateGroupTransition[g_descSvcInst[svcInstHandle].setStateIndex][0];
    DescInterruptDisable();
    if((g_descCurState.stateSession & curRefState->stateSession) != 0)
    {
      DescSetStateSession((curRefState+1)->stateSession);
    }
    if((g_descCurState.stateSecurityAccess & curRefState->stateSecurityAccess) != 0)
    {
      DescSetStateSecurityAccess((curRefState+1)->stateSecurityAccess);
    }
    DescInterruptRestore();
  }
}


#if defined(DESC_ENABLE_AUTO_STATES)
/*******************************************************************************
* NAME:              DescGetSessionStateOfSessionId
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Converts Session ID to its state.
*
*******************************************************************************/
DescStateGroup DESC_API_CALL_TYPE DescGetSessionStateOfSessionId(DescMsgItem sessionId)
{
  vuint8_least iter;
  vuint8_least scanner;
  vuint8_least step;
  V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * pReqHeadExt;
  DescStateGroup returnValue;
  step = DescGetSvcInstHeadExtEntrySize(&g_descSvcHead[kDescSvcHeadOffsetSDS]);

  /* First entry */
  pReqHeadExt = DescGetSvcInstReqHeadExt(&g_descSvcHead[kDescSvcHeadOffsetSDS], kDescSvcInstOffsetSDS);

  iter = 0;
  scanner = 0;
  while(iter < kDescNumStateSession)
  {
    if(pReqHeadExt[scanner] == sessionId)
    {
      break;
    }
    scanner+=step;
    iter++;
  }

  /* Check if found */
  DescAssertCommon((iter < kDescNumStateSession), kDescAssertInvalidStateParameterValue);

  /* Convert to bit mask */
  if(g_descSvcInst[iter + kDescSvcInstOffsetSDS].setStateIndex != kDescStateNoTransition)
  {
    returnValue = g_descStateGroupTransition[g_descSvcInst[iter + kDescSvcInstOffsetSDS].setStateIndex][1].stateSession;
  }
  else
  {
    /* Would mean illegal state was found */
    DescAssertCommonAlways(kDescAssertInvalidStateParameterValue);
    /*lint --e(527) */
    returnValue = kDescStateValueInvalid;
  }
  return returnValue;
}
#endif

#if defined(DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
/*******************************************************************************
* NAME:              DescGetSessionStateBitPosition
*
* CALLED BY:         SetState
* PRECONDITIONS:     
*
* DESCRIPTION:       Gathers the set bit number (0,1,...).
*
*******************************************************************************/
static vuint8_least DescGetSessionStateBitPosition(DescStateGroup sessionState)
{
  vuint8_least stateNumber = 1;

  /* Must be non-zero value */
  DescAssertCommon((sessionState != 0), kDescAssertZeroStateValue);
  while((sessionState>>stateNumber)!= 0)
  {
    stateNumber++;
  }
  /* correct the zero offset */
  stateNumber--;

  /* Must be one of the legal state values */
  DescAssertCommon((stateNumber < kDescNumStateSession), kDescAssertInvalidStateParameterValue);
  return stateNumber;
}
#endif

#if defined(DESC_ENABLE_AUTO_STATES)
/*******************************************************************************
* NAME:              DescGetSessionIdOfSessionState
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Converts given session state into its corresponding sub-function Id.
*
*******************************************************************************/
DescMsgItem DESC_API_CALL_TYPE DescGetSessionIdOfSessionState(DescStateGroup sessionState)
{
  vuint8_least iter;

  iter = kDescSvcInstOffsetSDS;
  while (iter < (kDescSvcInstOffsetSDS + kDescNumStateSession))
  {
    if(g_descSvcInst[iter].setStateIndex != kDescStateNoTransition)
    {
      if((DescStateGroup) (g_descStateGroupTransition[g_descSvcInst[iter].setStateIndex][1].stateSession) == sessionState)
      {
        return *DescGetSvcInstReqHeadExt(&g_descSvcHead[kDescSvcHeadOffsetSDS], iter);
      }
    }
    iter++;
  }

  /* Check if not found */
  DescAssertCommonAlways( kDescAssertInvalidStateParameterValue);

  return (DescMsgItem)0xFF;
}
#endif

#if defined(DESC_ENABLE_AUTO_STATES)
/*******************************************************************************
* NAME:              DescGetSessionTimings
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Returns the session specific P2/P2* timings
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescGetSessionTimings(DescStateGroup sessionState, vuint16* p2Time_1ms, vuint16* p2ExTime_10ms)
{
# if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
  vuint8_least    bitPos;
# endif

# if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
  bitPos = DescGetSessionStateBitPosition(sessionState);
  /* Set P2 Time for the response */
  *p2Time_1ms = g_descP2TimingsTable[bitPos][kDescTimingRefP2];
  /* Set P2* Time for the response */
  *p2ExTime_10ms = g_descP2TimingsTable[bitPos][kDescTimingRefP2Star];
# else
  DESC_IGNORE_UNREF_PARAM(sessionState);
  /* Set P2 Time for the response */
  *p2Time_1ms = kDescTimeValueP2;
  /* Set P2* Time for the response */
  *p2ExTime_10ms = kDescTimeValueP2Star;
# endif
}
#endif

#if defined(DESC_ENABLE_AUTO_STATES)
/*******************************************************************************
* NAME:              DescOnTransitionStateSession
*
* CALLED BY:         SetState
* PRECONDITIONS:     
*
* DESCRIPTION:       Special processing for the state group session.
*
*******************************************************************************/
static void DescOnTransitionStateSession(DescStateGroup newState, DescStateGroup currentState)
{
  /* On any transition */
  DescOemOnSessionTransition();

# if defined (DESC_ENABLE_SECURITY_ACCESS)
  /* Restore the security sequence */
  DescSecurityOnceInit();
# endif

# if defined (DESC_ENABLE_ROE_SUPPORT)
  DescClearRoeEvents();
# endif
  /* S1 Timer managment */
  if(currentState == kDescStateSessionDefault)
  {
    if(newState != kDescStateSessionDefault)
    {
      DescActivateS1Timer();
# if defined (DESC_ENABLE_NODE_POWER_CONTROL) && !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
      DescNpmProcessQueue();
# endif
      DescOemOnTransitionToNonDefaultSession();
    }
  }
  else
  {
    if(newState == kDescStateSessionDefault)
    {
      DescDeactivateS1Timer();
# if defined (DESC_ENABLE_PERIODIC_MODE)
      /* Clear the Scheduler */
      DescSchedulerInit();
# endif
# if defined (DESC_ENABLE_NODE_POWER_CONTROL) && !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
      DescNpmSetSleepInd();
# endif
      /* OEM implementation for this transition */
      DescOemOnTransitionToDefaultSession();
    }
  }
# if defined (DESC_ENABLE_DYNAMICAL_P2_TIMINGS)
  /* In case of dynamical P2 timings - set the new session reference */
  g_descCurrSessionNumber = (vuint8)DescGetSessionStateBitPosition(newState);
# endif
}
#endif


#if defined (DESC_ENABLE_MAINHANDLER_MULTICALL)
/*******************************************************************************
* NAME:              DescStartRepeatedServiceCall
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Enables the multicall feature for the current service.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescStartRepeatedServiceCall(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST DescMainHandler mainHandler)
{
  /* Initialize the required function handler */
  g_descRecallHandler[DESC_CONTEXT_PARAM_VALUE] = mainHandler;
}
#endif

/*******************************************************************************
* NAME:              DescSetNegResponse
*
* CALLED BY:         any application function
* PRECONDITIONS:     
*
* DESCRIPTION:       Sets the error.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescSetNegResponse(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST DescNegResCode errorCode)
{
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);
  /* Ignore setting an error if already set */
  if (g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
  {
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = errorCode;
  }
}

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
/******************************************************************************
* NAME:              DescGetSvcInstHeadExtEntrySize
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Binary search for service instance.
*
*******************************************************************************/
static vuint8_least DescGetSvcInstHeadExtEntrySize(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead)
{
  return (vuint8_least)((pSvcHead->isReqHeadExtEchoed != 0)?
                  (pSvcHead->reqHeadExLen):(pSvcHead->reqHeadExLen + pSvcHead->resHeadExLen));
}
#endif

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
/******************************************************************************
* NAME:              DescGetSvcInstResHeadExt
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Binary search for service instance.
*
*******************************************************************************/
# if defined(C_COMP_NEC_78K0_AFCAN)
static V_MEMROM1 V_MEMROM2 DescMsgItem V_MEMROM3 * DescGetSvcInstResHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef)
# else
static V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * DescGetSvcInstResHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef)
# endif
{
  vuint8_least offset = 0;
  if(pSvcHead->isReqHeadExtEchoed == 0)
  {
    offset = pSvcHead->reqHeadExLen;
  }
  return (DescGetSvcInstReqHeadExt(pSvcHead, svcInstAbsRef) + offset);
}
#endif

#if defined (DESC_ENABLE_SUB_SVC_USAGE)
/******************************************************************************
* NAME:              DescGetSvcInstReqHeadExt
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Binary search for service instance.
*
*******************************************************************************/
# if defined(C_COMP_NEC_78K0_AFCAN)
static V_MEMROM1 V_MEMROM2 DescMsgItem V_MEMROM3 * DescGetSvcInstReqHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef)
# else
static V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * DescGetSvcInstReqHeadExt(V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, DescSvcInstIndex svcInstAbsRef)
# endif
{
  vuint16_least offset = DescGetSvcInstHeadExtEntrySize(pSvcHead);
  offset *= (vuint16)(svcInstAbsRef - pSvcHead->svcInstFirstItem);

  return &g_descSvcInstHeadExt[pSvcHead->svcInstHeadExtFirstItem + offset];
}
#endif

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
# if defined(DESC_ENABLE_BINARY_SVCINST_SEARCH)
/******************************************************************************
* NAME:              DescFindSvcInst
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Binary search for service instance.
*
*******************************************************************************/
static DescSvcInstIndex DescFindSvcInst(DescConstPtr reqHeadPtr, V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, vuint8_least* failedByteMask)
{
  V_MEMROM1 DescMsgItem V_MEMROM2 V_MEMROM3 * headEx;
  DescSvcInstIndex        loIdx;
  DescSvcInstIndex        hiIdx;
  DescSvcInstIndex        idx;
  DescSvcInstIndex        reqSvcInstHandle;
  vuint8_least            currColFound;
  DescBool                isEqual;

  loIdx = pSvcHead->svcInstFirstItem;
  /* Calculate search elements */
  hiIdx = (DescSvcInstIndex)((pSvcHead + 1)->svcInstFirstItem - 1);

  /* Mark subserviceInstance handle as invalid */
  reqSvcInstHandle = kDescInvalidSvcInstHandle;

  /* No error still found */
  *failedByteMask = 0;
  do
  {
    /* Examine one concrete serviceInstanceHeader */
    /* ------------------------------------------ */
    idx = (DescSvcInstIndex)(((vuint16)((vuint16)hiIdx + (vuint16)loIdx)) >> 1);

    headEx = DescGetSvcInstReqHeadExt(pSvcHead, idx);
    currColFound = 0;

    do
    {
      isEqual = V_BOOL_EXPR(reqHeadPtr[currColFound] == headEx[currColFound]);
      currColFound++;
    }
    while((currColFound < pSvcHead->reqHeadExLen)&&(isEqual != kDescFalse));

    if(isEqual != kDescFalse)
    {
#  if defined (DESC_ENABLE_MULTI_VARIANT)
      /*Check if it is allowed in the actual configuration*/
      if(DescPermittedInConfig(g_descSvcInst[idx].variantMask) != 0)
#  endif
      {
        reqSvcInstHandle = idx;
      }
      break;
    }
    else
    {
      /* Compensate post increment */
      currColFound--;
      /* Check for deepest error column */
      if(currColFound > *failedByteMask)
      {
        *failedByteMask = currColFound;
      }
      /* Determine which half shall be taken */
      if (reqHeadPtr[currColFound] < headEx[currColFound])
      {
        /* Avoid signed types */
        if(idx == 0)
        {
          break;
        }
        hiIdx = (DescSvcInstIndex)(idx - 1);
      }
      else
      {
        /* Message 'greater' than service instance: Use upper half of interval... */
        loIdx = (DescSvcInstIndex)(idx + 1);
      }
    }
  }
  while (loIdx <= hiIdx);
  /* Use 0x02, to skip the SID bit */
  *failedByteMask = (vuint8)(0x02 << *failedByteMask);
  /* return the search result 
   * place the error column number in the last 3 bits */
  return reqSvcInstHandle;
}
# endif
#endif

#if defined(DESC_ENABLE_SUB_SVC_USAGE)
# if defined(DESC_ENABLE_LINEAR_SVCINST_SEARCH)
/******************************************************************************
* NAME:              DescFindSvcInst
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Linear search for service instance.
*
*******************************************************************************/
static DescSvcInstIndex DescFindSvcInst(DescConstPtr reqHeadPtr, V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * pSvcHead, vuint8_least* failedByteMask)
{
  DescSvcInstHeadExtIndex iter;
  DescSvcInstIndex        reqSvcInstHandle;
  DescSvcInstIndex        offset;
  vuint8_least            currColFound;
  vuint8_least            incStep;
  DescBool                isEqual;


  incStep = DescGetSvcInstHeadExtEntrySize(pSvcHead);

  /* Mark subserviceInstance handle as invalid */
  reqSvcInstHandle = kDescInvalidSvcInstHandle;
  /* No error still found */
  *failedByteMask = 0;
  offset = 0;

  for(iter = pSvcHead->svcInstHeadExtFirstItem;
      iter < (pSvcHead + 1)->svcInstHeadExtFirstItem;
      iter+= incStep)
  {
    currColFound = 0;
    do
    {
      isEqual = V_BOOL_EXPR(reqHeadPtr[currColFound] == g_descSvcInstHeadExt[iter + currColFound]);
      currColFound++;
    }
    while ((currColFound < pSvcHead->reqHeadExLen)&&(isEqual != kDescFalse));


    if(isEqual != kDescFalse)
    {
      reqSvcInstHandle = (DescSvcInstIndex)(offset + pSvcHead->svcInstFirstItem);
#  if defined (DESC_ENABLE_MULTI_VARIANT)
       /*Check if it is allowed in the actual configuration*/
      if(DescPermittedInConfig(g_descSvcInst[reqSvcInstHandle].variantMask) == 0)
      {
        reqSvcInstHandle = kDescInvalidSvcInstHandle;
      }
#  endif
      break;
    }
    else
    {
      /* Compensate post increment */
      currColFound--;
      /* Check for deepest error column */
      if(currColFound > *failedByteMask)
      {
        /* Use 0x02, to skip the SID bit */
        *failedByteMask = currColFound;
      }
      /* Check if it makes sense to continue the search */
      if(reqHeadPtr[currColFound] < g_descSvcInstHeadExt[iter + currColFound])
      {
        /* That was it */
        break;
      }
    }
    /* Increment the reference */
    offset++;
  }

  /* Use 0x02, to skip the SID bit */
  *failedByteMask = (vuint8)(0x02 << *failedByteMask);
  return reqSvcInstHandle;
}
# endif
#endif

/******************************************************************************
* NAME:              DescFindSvc
*
* CALLED BY:         Dispatcher,FuncReception
* PRECONDITIONS:     
*
* DESCRIPTION:       Search a service ID.
*
*******************************************************************************/
static DescSvcHeadIndex DescFindSvc(DescMsgItem reqSvcId)
{
  DescSvcHeadIndex result  = kDescInvalidSvcHandle;
  vuint8_least     byteVar = 0;

  /* check if it is in the correct range (0x00-0x3f or 0x80-bf => bit2 must be 0) */
  /* check if it is not bigger that the maximum defined SID */
  if (((reqSvcId & kDescPosResIdOffset) == 0)&&
       (reqSvcId <= kDescMaxReqSid))
  {
    /* find in which response range is the request. */
    if ((reqSvcId & 0x80) != 0)
    {
      byteVar = kDescPosResIdOffset;
    }
    result = g_descSidMap[reqSvcId - byteVar];
  }


#if defined (DESC_ENABLE_MULTI_VARIANT) || \
    defined(DESC_ENABLE_GENERIC_USER_SERVICE_SUPPORT)
  if(result < kDescInvalidSvcHandle)
  {
# if defined (DESC_ENABLE_MULTI_VARIANT)
    /*Check if it is allowed in the actual configuration*/
    if(DescPermittedInConfig(g_descSvcHead[result].variantMask) == 0)
    {
      result = kDescInvalidSvcHandle;
    }
# endif
  }
  else
  {
# if defined(DESC_ENABLE_GENERIC_USER_SERVICE_SUPPORT)
    /* Check if the application can recognize the SID */
    if(ApplDescCheckUserService(reqSvcId) == kDescOk)
    {
      /* The last service is the generic user one */
      result = (DescSvcHeadIndex)(kDescSvcHeadNumItems - 1);
    }
# endif
  }
#endif
  return result;
}

#if defined(DESC_ENABLE_GENERIC_USER_SERVICE_SUPPORT)
/******************************************************************************
* NAME:              DescGetServiceId
*
* CALLED BY:         Application user service
* PRECONDITIONS:     
*
* DESCRIPTION:       Returns the current request's SId.
*
*******************************************************************************/
DescMsgItem DESC_API_CALL_TYPE DescGetServiceId(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Check for correct context */
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);
# if defined(DESC_ENABLE_GENERIC_USER_POST_HANDLER_SUPPORT)
  /* Service Id can be reported only if not receive was active (post-handler are called in Idle mode) 
   * Removed since the condition is incomplete - if between the call of DescProcessingDOne and the PosHandler excution a new service will be requested,
   * it is still possible to evaluate the SID but the activity is set to ActiveRx.
   */
  /* DescAssertUser((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity != kDescContextActiveRx), kDescAssertNoSidCanBeReportedInIdleMode);*/
  /* Take from the backup */
  return g_descUserSIdBackup[DESC_CONTEXT_PARAM_VALUE];
# else
  /* Service Id can be reported only during request processing */
  DescAssertUser((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity == kDescContextActiveProcess), kDescAssertNoSidCanBeReportedInIdleMode);
  /* Take from the current buffer */
  return g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr[0];
# endif
}
#endif

/*******************************************************************************
* NAME:              DescDispatcherIterInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:     
*
* DESCRIPTION:       Initilizes the dispatcher subcomponent context specific data.
*
*******************************************************************************/
static void DescDispatcherIterInit(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_ENABLE_MAINHANDLER_MULTICALL)
  /* Clear the multicall function pointer */
  g_descRecallHandler[DESC_CONTEXT_PARAM_VALUE] = V_NULL;
#endif
#if (kDescNumContexts > 1)
  /* Init the context reference */
  g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].iContext = DESC_CONTEXT_PARAM_VALUE;
#endif

  /* Delete the error registers */
  /* Done before the dispatcher will be called.
   * g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcNone;
   */
}

/*******************************************************************************
* NAME:              DescDispatcher
*
* CALLED BY:         DescTask
* PRECONDITIONS:     If there is at least one received request.
*
* DESCRIPTION:       Provides the kernel of the diagnostic
*
*******************************************************************************/
static void DescDispatcher(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Code optimization */
  DescMsg msg;

  msg = g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr;

#if defined(DESC_ENABLE_GENERIC_USER_POST_HANDLER_SUPPORT)
  /* Store the SId for the case it is user SId */
  g_descUserSIdBackup[DESC_CONTEXT_PARAM_VALUE] = msg[0];
#endif
  /* Encapsulate the error handling for distinguishing if the PostHAndler has to
   * be called in error cases, handled by CANdesc 
   */
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isApplError = 0;

#if defined (DESC_ENABLE_SUPPLIER_CALLBACKS)
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSupplPost = 0;
#endif

#if defined (DESC_ENABLE_SPRMIB_OVERRIDE)
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSPRMIBOverridden = 0;
#endif

  /* Set default response on request type (phys - yes, func - yes) */
  g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = kDescResOnAllReq;

  /* Update the context phase */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveProcess;

#if defined (DESC_ENABLE_MANUFACTURER_CALLBACKS)
  ApplDescManufacturerIndication(DESC_CONTEXT_PARAM_FIRST msg[0], &msg[1], (DescMsgLen)(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen - 1) ,(vuint8) g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType, &g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].busInfo);
  if (g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
  {
    /*---------------------------------------------*/
    /*              Search service ID              */
    /*---------------------------------------------*/
    /* If service not supported */
    /* -------------------------*/
    g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE] = DescFindSvc(msg[0]);
    if(g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE] < kDescInvalidSvcHandle)
    {
      V_MEMROM1 DescSvcHead V_MEMROM2 V_MEMROM3 * refDescSvcHead;

      refDescSvcHead = &g_descSvcHead[g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE]];

      /*------------------------------------*/
      /*     Service ID session check       */
      /*------------------------------------*/
#if defined (DESC_ENABLE_AUTO_STATES)
      /* Generated state checks */
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = DescCheckState(&(refDescSvcHead->checkState));

      /* If any error was detected - go out */
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
      {
#if defined (DESC_ENABLE_SUPPLIER_CALLBACKS)
        ApplDescSupplierIndication(DESC_CONTEXT_PARAM_FIRST  msg[0],  &msg[1], (g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen-1) ,(vuint8) g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType, &g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].busInfo);
        g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSupplPost = 1;
        /*register confirmation*/
        if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
        {
        /*---------------------------------------------*/
        /*      The length of the request must be at   */
        /*    least the length of the requests header  */
        /*---------------------------------------------*/
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
          if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen >= refDescSvcHead->minReqLength)
#endif
          {
            vuint8_least supPosResBit;
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
            vuint8_least svcInstFailedBytePosMask = 0;
#endif

            /* SID is no more of relevance - position to the first sub-service byte */
            msg++;
            /*---------------------------------------------*/
            /*   Suppress positive response bit calc       */
            /*---------------------------------------------*/
            supPosResBit = refDescSvcHead->suppPosRes;
            /* compose 0x80 or 0x00 depending on the CDD info */
            supPosResBit <<= 7;
            /* Extract the information to the application */
            g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.suppPosRes = (DescBitType) (((supPosResBit & *msg)!= 0)?0x01:0x00);
            /* Mask out the SPRMB */
            *msg &= (DescMsgItem)(~supPosResBit);/* compose 0x80 or 0x00 depending on the CDD info */

            /*---------------------------------------------*/
            /*              Search service instance        */
            /*---------------------------------------------*/
            /* if at least one instance is defined - check if it is valid */
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
            if(refDescSvcHead->reqHeadExLen > 0)
            { /*lint -e{644}*/
              g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE] = (DescMemSvcInstIndex)DescFindSvcInst(msg, refDescSvcHead, &svcInstFailedBytePosMask);
            }
            else
#endif
            {
              g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE] = refDescSvcHead->svcInstFirstItem;
            }
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
            if((g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE]) < kDescInvalidSvcInstHandle)
#endif
            {
              V_MEMROM1 DescSvcInst V_MEMROM2 V_MEMROM3 * refDescSvcInst;

              refDescSvcInst = &g_descSvcInst[g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE]];

              /* -----------------------------------------------*/
              /*      Set the default state for the response    */
              /* -----------------------------------------------*/

                /*---------------------------------------------*/
                /*      Service instance related checks        */
                /*---------------------------------------------*/
                /* Request length (top limit) check */

                /*---------------------------------------------*/
                /*      Service instance related checks        */
                /*---------------------------------------------*/
                /* Generated session check */
#if defined (DESC_ENABLE_SESSION_FORMAT_STATE_CHECK)
                if ((refDescSvcInst->checkState.stateSession & g_descCurState.stateSession) != 0)
#endif
                {
                  /* Request length (top limit) check */
                  /* If the table stored length is not zero - 
                  check it for matching with the request length */
                  if((refDescSvcInst->reqLen == 0) ||
                    (refDescSvcInst->reqLen == g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen))
                  {
#if defined (DESC_ENABLE_AUTO_STATES)
                    /* Generated state checks */
                    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = DescCheckState(&(refDescSvcInst->checkState));

                    /* If any error was detected - go out */
                    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
                    {
                      /* Release the PostHandler call feature */
                      g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isApplError = 1;


                      /* OEM specific hook for pre-service execution */
                      DescOemOnValidService(DESC_CONTEXT_PARAM_VALUE);

                      /* If any error was detected - go out */
                      /* Do not use pre-processor encapsulation - since good compilers would optimize this check. */
                      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
                      {
#if defined (DESC_ENABLE_PREHANDLER_USAGE)
                        /*---------------------------------------------*/
                        /*    Application specific condition check     */
                        /*---------------------------------------------*/
                        /* Call the pre handler */
                        g_descPreHandlerTable[refDescSvcInst->preHandlerRef](DESC_CONTEXT_PARAM_ONLY);
                        /* If any error was detected - go out */
                        if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
                        {
                          /* Prepare the application information */
                          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData    = (DescMsg)(msg + DescExtractReqExtHeadLen(refDescSvcHead->reqHeadExLen));
                          /* This is the extension of the response header (the header without the resposne SID), so for the complete length - add 1 */
                          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resData    = (DescMsg)(msg + DescExtractResExtHeadLen(refDescSvcHead->resHeadExLen));
                          /* The length contains up to now the whole request length, so just substract the header length */
                          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen -= (DescMsgLen)(DescExtractReqExtHeadLen(refDescSvcHead->reqHeadExLen) + 1);
                          /* Zero the response length - optimization for no data responses */
                          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = 0;

                          /*---------------------------------------------*/
                          /*      Call the main handler function         */
                          /*---------------------------------------------*/
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
                          /* If each service needs it - start always here to save ROM for the application */
                          _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, refDescSvcInst->mainHandler);
#endif
                          refDescSvcInst->mainHandler(&g_descMsgContext[DESC_CONTEXT_PARAM_VALUE]);

                          DescAssertContext((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].iContext == DESC_CONTEXT_PARAM_VALUE), kDescAssertContextIdWasModified);
                          DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts), kDescAssertInvalidContextId);
                          /* Skip the processing done call - let the application decide when */
                          return;
                        }
                      }/* else: error code already set - skip further processing */
                    }
#if defined (DESC_ENABLE_AUTO_STATES)
                    else
                    {
                      /* Correct the negative response code dependent on the sub-function instantiation */
                      if((g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcSubfunctionNotSupportedInActiveSession)
                        &&(refDescSvcHead->hasSubFunction == 0))
                      {
                        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcParamIdNotSupportedInSession;
                      }

                      /* EXAMPLE: Additional activities may be necessary */
                      DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
                      DescOemOnInvalidEcuState(DESC_CONTEXT_PARAM_VALUE);
                    }
#endif
                  }
                  else
                  {
                    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidFormat;
                    /* EXAMPLE: Additional activities may be necessary */
                    DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
                    DescOemOnReqLengthNotMatched(DESC_CONTEXT_PARAM_VALUE);
                  }
                }
#if defined (DESC_ENABLE_SESSION_FORMAT_STATE_CHECK)
                else
                {
                  /* Correct the negative response code dependent on the sub-function instantiation */
                  if(refDescSvcHead->hasSubFunction == 0)
                  {
                    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcParamIdNotSupportedInSession;
                  }
                  else
                  {
                    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcSubfunctionNotSupportedInActiveSession;
                  }
                  /* EXAMPLE: Additional activities may be necessary */
                  DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
                  DescOemOnInvalidEcuState(DESC_CONTEXT_PARAM_VALUE);
                }
#endif
            }
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
            else
            {
# if defined (DESC_ENABLE_SAME_NRC_ON_SUB_FUNC_AND_PARAM_ID)
              /* Send always NRC kDescNrcSubfunctionNotSupported */
# else
              /* Check which negative response shall be send (UnexpectedId/UnexpectedSubFunction)*/
              /*lint -e{644} (PClint can not know that this code will be reached only if the service is not found, and the variable is always initialized with 0)*/
              if((vuintx)(refDescSvcHead->reqHeadByteSpec & svcInstFailedBytePosMask) != (vuintx)0)
              {
                g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcRequestOutOfRange;
              }
              else
# endif
              {
                g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcSubfunctionNotSupported;
              }
              /* Could be used in case when the instance is not found special init to be done*/
              DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
              DescOemOnSvcInstNotFound(DESC_CONTEXT_PARAM_VALUE);
            }
#endif
          }
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
          else
          {
            g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidFormat;
            /* EXAMPLE: Additional activities may be necessary */
            DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
            DescOemOnReqLengthTooSmall(DESC_CONTEXT_PARAM_VALUE);
          }
#endif
        }/*SuppleirIndication check, NRC already set*/
      } /*check state on SID level*/
      else
      {
        /* EXAMPLE: Additional activities may be necessary */
        if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] ==  kDescNrcSubfunctionNotSupportedInActiveSession)
        {
          g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] =  kDescNrcServiceNotSupportedInActiveSession;
        }

        DescOemOnInvalidRequest(DESC_CONTEXT_PARAM_VALUE);
        DescOemOnInvalidSidSession(DESC_CONTEXT_PARAM_VALUE);
      }
    }
    else
    {
      /* Could be used in case when the service is not found special init to be done*/
      DescOemOnSvcNotFound(DESC_CONTEXT_PARAM_VALUE);
#if defined(DESC_ENABLE_NEG_RES_ON_SID_WITH_SET_BIT6)
      /* Let always a response transmission */
#else
      if((msg[0] & 0x40) != 0)
      {
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = 0;
      }
#endif
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcServiceNotSupported;
    }
  }/*ManufacturerIndication check, NRC already set*/
  DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}

#if defined (DESC_ENABLE_PROCESSING_DONE_REDIRECTOR)
/*******************************************************************************
* NAME:              DescProcessingDone
*
* CALLED BY:         Dispatch,  any application function
* PRECONDITIONS: 
*
* DESCRIPTION:       Depending on the current situation, provides the right 
*                    action. 
*******************************************************************************/
void DESC_API_CALL_TYPE DescProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);

  switch(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode)
  {
    case kDescContextModeNormal:
      /* Finalize the request processing */
      DescFinalProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      break;
# if defined (DESC_ENABLE_PID_LIST_MODE) || \
     defined (DESC_ENABLE_SIM_PID_LIST_MODE)
    case kDescContextModePidList:
      /* Current Pid list process finalization */
      DescPidProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      break;
# endif
# if defined (DESC_ENABLE_PERIODIC_MODE)
    case kDescContextModePeriodic:
      /* Current P-Pid list process finalization */
      DescSchedulerProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      break;
# endif
# if defined (DESC_ENABLE_ROUTINE_CONTROL_MODE)
    case kDescContextModeRoutineControl:
      /* The routine control service is ready - finalize it */
      DescRidProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      break;
# endif
# if defined (DESC_ENABLE_MEMORY_BY_ADDRESS_MODE)
    case kDescContextModeMemByAddr:
      /* The memory by address service is ready - finalize it */
      DescMemByAddrProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      break;
# endif
    default:
      /* Unknown context mode */
      DescAssertCommonAlways(kDescAssertInvalidContextMode);
      break;
  }
}
#endif

/*******************************************************************************
* NAME:              DescFinalProcessingDone/DescProcessingDone
*
* CALLED BY:         DescProcessingDone/Appl(CANdesc)
* PRECONDITIONS: 
*
* DESCRIPTION:       Depending on the current situation, provides the right 
*                    action. 
*******************************************************************************/
#if defined (DESC_ENABLE_PROCESSING_DONE_REDIRECTOR)
static void DescFinalProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
#else
void DESC_API_CALL_TYPE DescProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
#endif
{
  DescMsg       msg;
  /* temporary variable to avoid multiple calculations */
  vuint8_least  resHeadLen;

  /* check for correct context */
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);
  /* check for correct time point of function call */
  DescAssertCommon((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity == kDescContextActiveProcess),
                   kDescAssertProcessingDoneCallAfterResFlushing);
  /* Is ProcessingDone awaited */
  if((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity & kDescContextActiveProcess) != 0)
  {
#if defined (DESC_ENABLE_PROCESSING_DONE_REDIRECTOR)
    /* Set the CANdesc in a normal mode */
    g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModeNormal;
#endif

    /* Specific actions which will be performed each time processing done with real response is called (timer management) */
    DescOemOnProcessingDone(DESC_CONTEXT_PARAM_VALUE);

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL) && \
    defined (DESC_ENABLE_RES_RINGBUFFER)
    /* If no ring buffer currently in use - stop multiple calls */
    if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive == 0)
#endif
    {
      /* Deactivate the multicall mechanism */
      _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, V_NULL);
    }

    /* Check if there will be a real response onto the bus */
    if ((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq &
         g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType) !=0 )
    {
      /* Init with the current buffer location */
      msg = g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr;
      /* if there was an error detection - make negative response */
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
      {
        /*---------------------------------------------*/
        /*          Negative response section          */
        /*---------------------------------------------*/
        if((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType & kDescFuncReq) != 0)
        {
#if defined (DESC_ENABLE_ALL_RES_AFTER_RCRRP)
          if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].rcrRpSent == 0)
#endif
          {
            /* In case of secured transmission - it is not possible to enter here!!! */
            switch(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE])
            {
              case 0x11:/* fall through */
              case 0x12:/* fall through */
              case 0x31:/* fall through */
              DESC_OEM_SUPPRESSED_FUNC_NRC
              DESC_ADD_SUPPRESSED_FUNC_NRC
                /* fall through */
                /* Simulate success confirmation */
                DescDoPostProcessing(DESC_CONTEXT_PARAM_FIRST kDescUsdtNetworkOk);
                return;/* Leave the function */
              default:break;/* Send negative response onto the comm bus */
            }
          }

#if defined (DESC_ENABLE_OBDII_NR_CONFORMANCE)
          /* Functional OBD requests (Sid =[0x00,...,0x0F]) */
          if(msg[0] < 0x10)
          {
            /* ...may support only NRCs: $21, $22 and $78 */
            switch(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE])
            {
              case 0x21:/* Fall through */
              case 0x22:/* Fall through */
              case 0x78:/* Fall through */
                /* These are allowed - continue processing */
                break;
              default:
                /* Simulate success confirmation */
                DescDoPostProcessing(DESC_CONTEXT_PARAM_FIRST kDescUsdtNetworkOk);
                return;
            }
          }
#endif
        }

        /* Format and send negative response */
        msg[1] = msg[0]; /* Copy the SID */
        msg[0] = kDescNegResSId;/* Place 0x7F ...*/
        msg[2] = g_descNegResCode[DESC_CONTEXT_PARAM_VALUE];/*... and the current error code*/
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = kDescNegResLen;
      }
      else
      {
        /*---------------------------------------------*/
        /*          Positive response section          */
        /*---------------------------------------------*/
#if defined (DESC_ENABLE_POS_RES_ON_SET_SPRMIB)
        /* Do not consider the bit information - send always positive response */
#else
        /* Check if positive response shall be sent */
        if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.suppPosRes == 0)
#endif
        {
          /* Create response SID */
          msg[0] += kDescPosResIdOffset;
          msg++;
          /* Fill header of response */
          DescAssertCommon((g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE] < kDescSvcHeadNumItems),kDescAssertSvcTableIndexOutOfRange);
          /* optimize the loop - casting because it is sure that the header length is far below 254 bytes */
          /* This is the extension of the response header (the header without the resposne SID), so for the complete length - add 1 */
          resHeadLen = DescExtractResExtHeadLen((vuintx)(g_descSvcHead[g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE]].resHeadExLen));
#if defined(DESC_ENABLE_SUB_SVC_USAGE)
          DescMsgCopyRomToFarRam(msg,
                                 DescGetSvcInstResHeadExt(&g_descSvcHead[g_descCurReqSvc[DESC_CONTEXT_PARAM_VALUE]],
                                                           g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE]),
                                 (vuint16)resHeadLen);
#endif
#if defined (DESC_ENABLE_SPRMIB_OVERRIDE)
          if (g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSPRMIBOverridden == 1)
          {
            msg[0] |= 0x80;    /*To restore the SPRMIB in the sub-function ID*/
          }
#endif
          /* Now consider the SID too */
          resHeadLen++;
          /* Making the total length of the response message 
          * (header + data) This macro is an optimization for adding a value: (X+=Y)*/
          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += (DescMsgLen)resHeadLen;
#if defined (DESC_ENABLE_RES_RINGBUFFER)
          /*Set the write pointer for the ring buffer manager (resHeadLen + SIdByte) */
          g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txWriteIndex =    (DescMsgLen)resHeadLen;
          /* Protocol data are the response head data */
          g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].protocolDataLen = (DescBitType)resHeadLen;
#endif
        }
#if defined (DESC_ENABLE_POS_RES_ON_SET_SPRMIB)
        /* Do not consider the bit information - send always positive response */
#else
        else
        {
          /* Simulate success confirmation */
          DescDoPostProcessing(DESC_CONTEXT_PARAM_FIRST kDescUsdtNetworkOk);
          return;
        }
#endif
      }

#if defined (DESC_ENABLE_RES_RINGBUFFER)
      /* Mark that from now on a single response will be sent */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveProcessEnd;
      /* Set it for the copyToCan function */
      g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txReadIndex = 0;
      /* Init RingBuffer controller */
      g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].bytesWritten = 0;

      /* Set the write pointer in case of RingBuffer usage and leave this function */
      if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive == 0)
#endif
      {
        /* Set ready for transmit */
        g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveTxReady;
      }
    }
    else
    {
      /* Simulate success confirmation */
      DescDoPostProcessing(DESC_CONTEXT_PARAM_FIRST kDescUsdtNetworkOk);
    }
  }
}

/*******************************************************************************
* NAME:              DescDoPostProcessing
*
* CALLED BY:         DescConfirmation, DescProcessingDone
* PRECONDITIONS: 
*
* DESCRIPTION:       Provides finalizing actions
*                    In case of secured Transmission
*******************************************************************************/
static void DescDoPostProcessing(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST t_descUsdtNetResult status)
{
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);

  /* Copy the state for task processing */
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].txState = status;

  /* Deactivate the RCR-RP timer here for those services without response */
  DescDeactivateT2Timer(DESC_CONTEXT_PARAM_VALUE);
  DescDeactivateLimiter(DESC_CONTEXT_PARAM_VALUE);
  /* Activate the post processing */
  g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActivePostProcess;

  /* Predefined function */
  DescOemOnConfirmation(DESC_CONTEXT_PARAM_VALUE, status);

  /* Stop calling the application if set */
  _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, V_NULL);
  /* Release context for next requests */
  DescReleaseContext(DESC_CONTEXT_PARAM_ONLY);
}

/*******************************************************************************
* NAME:              DescInitPowerOn
*
* CALLED BY:         Application
* PRECONDITIONS:     On system boot.
*
* DESCRIPTION:       Performs time consuming init/checks of the diag module.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescInitPowerOn(DescInitParam initParam)
{
  /******************************
  Subcomponent once InitPowerOn
  *******************************/
  DescSubcompOnceInitPowerOnDebug();
  DescSubcompOnceInitPowerOnNetwork();
  DescSubcompOnceInitPowerOnTiming();
  DescSubcompOnceInitPowerOnState();
  DescSubcompOnceInitPowerOnDispatcher();
  DescSubcompOnceInitPowerOnController();
  DescSubcompOnceInitPowerOnProcessor();
  DescSubcompOnceInitPowerOnFaultMemory();
  DescSubcompOnceInitPowerOnScheduled();
  DescSubcompOnceInitPowerOnSecurityAccess();
  DescSubcompOnceInitPowerOnPidManager();
  DescSubcompOnceInitPowerOnRidManager();
  DescSubcompOnceInitPowerOnPidListProcessor();
  DescSubcompOnceInitPowerOnDynDefinePid();
  DescSubcompOnceInitPowerOnDynDefineDpid();
  DescSubcompOnceInitPowerOnRoeProcessor();
  DescSubcompOnceInitPowerOnVariantManager();


  /* Generated function - DescInit must be here called because of init parameters */
  DescOemOnPowerOnInit(initParam);
  DescInit(initParam);
}

/*******************************************************************************
* NAME:              DescInit
*
* CALLED BY:         any application function, DescInitPowerOn
* PRECONDITIONS:
*
* DESCRIPTION:       Performs init of the diag module.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescInit(DescInitParam initParam)
{

  DESC_CONTEXT_PARAM_DEF_LOCAL

  /* Parameter may not be used - use dummy assignemt if necessary */
  DESC_IGNORE_UNREF_PARAM(initParam);

  /************************
  Subcomponent once init
  ************************/
  DescSubcompOnceInitDebug();
  DescSubcompOnceInitNetwork();
  DescSubcompOnceInitTiming();
  DescSubcompOnceInitState();
  DescSubcompOnceInitDispatcher();
  DescSubcompOnceInitController();
  DescSubcompOnceInitProcessor();
  DescSubcompOnceInitFaultMemory();
  DescSubcompOnceInitScheduled();
  DescSubcompOnceInitSecurityAccess();
  DescSubcompOnceInitPidManager();
  DescSubcompOnceInitRidManager();
  DescSubcompOnceInitPidListProcessor();
  DescSubcompOnceInitDynDefinePid();
  DescSubcompOnceInitDynDefineDpid();
  DescSubcompOnceInitRoeProcessor();
  DescSubcompOnceInitVariantManager();

#if(kDescNumContexts > 1)
  DESC_CONTEXT_PARAM_VALUE = kDescNumContexts;
  while(DESC_CONTEXT_PARAM_VALUE != 0)
  {
    DESC_CONTEXT_PARAM_ONLY--;
#endif
    /************************
    Subcomponent context init
    ************************/
    DescSubcompIterInitDebug(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitNetwork(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitTiming(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitState(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitDispatcher(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitController(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitProcessor(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitFaultMemory(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitScheduled(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitSecurityAccess(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitPidManager(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitRidManager(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitPidListProcessor(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitDynDefinePid(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitDynDefineDpid(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitRoeProcessor(DESC_CONTEXT_PARAM_VALUE);
    DescSubcompIterInitVariantManager(DESC_CONTEXT_PARAM_VALUE);
#if(kDescNumContexts > 1)
  }
#endif
  /* Customized function */
  DescOemOnInit(initParam);
}

/*******************************************************************************
* NAME:              DescTimerTask
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescTimerTask(void)
{
  DESC_CONTEXT_PARAM_DEF_LOCAL

  /* Check if desc is globally in idle mode */
#if(kDescNumContexts > 1)
  DESC_CONTEXT_PARAM_VALUE = kDescNumContexts;
  while(DESC_CONTEXT_PARAM_VALUE != 0)
  {
    DESC_CONTEXT_PARAM_ONLY--;
#endif
    /* RCR-RP only during processing (pprocessingEnd but not during transmission) */
    if((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity & (kDescContextActiveProcess|kDescContextActiveProcessEnd)) != 0)
    {
      DescResponseTimeoutTask(DESC_CONTEXT_PARAM_ONLY);
    }
#if(kDescNumContexts > 1)
  }
#endif

#if defined (DESC_ENABLE_DESCICN_SUPPORT)
  if(DescIsNoExtConnectionActive())
#else
  if(DescIsNoConnectionActive())
#endif
  {
#if defined (DESC_ENABLE_AUTO_STATES)
    /* ----------------*/
    /* Tester Timeout  */
    /* ----------------*/
    if(g_descS1Timer != 0)
    {
      if(g_descDoReloadS1Timer == kDescTrue)
      {
        /* This will clear the flag. No data loss possible, since the flag can be only set
         * in interrupt, and only here will be cleared.
         */
        g_descDoReloadS1Timer = kDescFalse;
        DescReloadS1Timer();
      }
      /* Decrement timer */
      g_descS1Timer--;
      /* Check for timeout */
      if(g_descS1Timer == 0)
      {
        /* Simulate the same behavior as it would be done by requesting
         * default session
         */
# if (kDescStateGroupNumTransition > 0)
        /* Patch the setstate function to simulate real request */
        DescSetState(kDescDefaultSessionSvcInstEntry);
# endif
# if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
        DescNpmSetSleepInd();
# endif
        /* Special handling in case of S1 timeout */
        DescOemOnS1Timeout();
      }
    }
    else
#endif
    {
#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
      DescOemNpmTimer();
#endif
      /* OEM specific timer during diag idle & default session) */
      DescOemDescIdleTimer();
    }
  }

#if defined (DESC_ENABLE_SECURITY_ACCESS)
# if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
  DescSecurityAccessTimer();
# else
#  if defined (kDescSecureTimer)
#   if (kDescSecureTimer != 0)
  DescSecurityAccessTimer();
#   endif
#  endif
# endif
#endif

  /* Custom timers */
  DescOemTaskTimer();
#if defined(DESC_ENABLE_PERIODIC_MODE)
  /* In case of periodic PIDs process them here */
  DescSchedulerTimerTask();
#endif
  /* Call the DescNet  tasks */
  DescUudtNetTimerTask();
  DescUsdtNetAbsTimerTask();
}

/*******************************************************************************
* NAME:              DescResponseTimeoutTask
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
static void DescResponseTimeoutTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_ENABLE_RES_PENDING_TIME_LIMIT)
  /* --------------------------------------------------------*/
  /* Response pending time limitation -----------------      */
  /* --------------------------------------------------------*/
  /* Attention: Reenable interrupt after comparision against zero to avoid test-and-set problem. */
  if(g_descRcrrpLimitCounter[DESC_CONTEXT_PARAM_VALUE] != 0)
  {
    g_descRcrrpLimitCounter[DESC_CONTEXT_PARAM_VALUE]--;
    if(g_descRcrrpLimitCounter[DESC_CONTEXT_PARAM_VALUE] == 0)
    {
# if defined (DESC_ENABLE_FORCE_RCR_RP)
      /* Reset this flag if set */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState = kDescForcedRcrRpIdle;
# endif
      /* Cancel interaction with Dem */
      DescOemDemCancelOperationOnOvertime(DESC_CONTEXT_PARAM_VALUE);

# if defined(DESC_ENABLE_RES_RINGBUFFER)
      if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive != 0)
      {
        DescRingBufferCancel(DESC_CONTEXT_PARAM_ONLY);
      }
      else
# endif
      {
        /* Stop sending of further $78 error codes */
        DescDeactivateT2Timer(DESC_CONTEXT_PARAM_VALUE);
        /* further call of processing done is illegal */

# if defined(DESC_ENABLE_OEM_HANDLING_ON_RCRRP_LIMIT_EXPIRATION)
        /* Custom action */
        DescOemOnResPendingOvertime(DESC_CONTEXT_PARAM_VALUE);
# else
        DescInterruptDisable();
        /* Set no response - just finalize the request */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = 0;
        /* Set an error so no complicatet checks to be performed and no PostHandler to be called */
        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = (DescNegResCode)(~kDescNrcNone);

        /* Close the case :) */
        DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
        DescInterruptRestore();
# endif
      }
      /* Notify the application about timeout */
      ApplDescResponsePendingOvertimed(DESC_CONTEXT_PARAM_ONLY);
      return;
    }
  }
#endif
  /* --------------------------------------------------------*/
  /* Response Timeout ---------------------------------------*/
  /* --------------------------------------------------------*/
  if(g_descT2Timer[DESC_CONTEXT_PARAM_VALUE] != 0)
  {
#if defined (DESC_ENABLE_FORCE_RCR_RP)
    /* Check if the application needs RCR-RP right now */
    if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState == kDescForcedRcrRpCharged)
    {
      /* Check if the TX channel is free */
      if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType == kDescUsdtResponseNone)
      {
# if defined (DESC_ENABLE_SCHEDULER_USDT_TRANSMITTER)
        /* Catch situation: ongoing USDT periodic response and parallel main response
         * check if other context wants to send or scheduler is not on sending */
        if((DESC_CONTEXT_PARAM_VALUE != kDescPrimContext)
            ||((g_descInterruptContextCtrl[kDescSchedulerContext].activity & kDescContextActiveTx) == 0))
# endif
        {
          /* reserve the TX channel for single frame */
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType = kDescUsdtResponseNegativeApplRCR_RP;
          /* reset RCR-RP state */
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState = kDescForcedRcrRpIdle;

          /* Ignore the SPRMB value and send always positive response if at least one RCR-RP has been sent */
          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.suppPosRes = 0;

          DescTransmitRcrRp(DESC_CONTEXT_PARAM_ONLY);
        }
      }
      else
      { /* Force timeout */
        g_descT2Timer[DESC_CONTEXT_PARAM_VALUE] = 1;
      }
    }
    else
#endif
    {
      /* TimeoutT2 unequal to 0 means running */
      g_descT2Timer[DESC_CONTEXT_PARAM_VALUE]--;
      /*Timeout reached?*/
      if(g_descT2Timer[DESC_CONTEXT_PARAM_VALUE] == 0)
      {
        DescHandleInternRcrRp(DESC_CONTEXT_PARAM_ONLY);
      }/* T2 timeout case */
    }/* T2 timer running check */
  }
}


/*******************************************************************************
* NAME:              DescTask
*
* CALLED BY:         any application function
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescTask(void)
{
#if defined(DESC_ENABLE_HIPERFORMANCE_DYNDID_MODE)
  /* Do not call the state task again to avoid CPU overload - the do-while loop will do this job */
#else
  DescStateTask();
#endif
  DescTimerTask();
}


/*******************************************************************************
* NAME:              DescStateTask
*
* CALLED BY:         any application function
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescStateTask(void)
{
  DESC_CONTEXT_PARAM_DEF_LOCAL

  /*Postprocess UUDT confirmation*/
  DescUudtNetStateTask();

  /*-------------------------*/
  /* Global tasks processing */
  /*-------------------------*/
#if defined(DESC_ENABLE_PERIODIC_MODE)
  DescSchedulerTask();
#endif
#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE)
  DescDynDidTask();
#endif
#if defined (DESC_ENABLE_ROE_SUPPORT)
  DescRoeStateTask();
#endif
  /*--------------------------*/
  /* Context tasks processing */
  /*--------------------------*/
#if(kDescNumContexts > 1)
  DESC_CONTEXT_PARAM_VALUE = kDescNumContexts;
  while(DESC_CONTEXT_PARAM_VALUE != 0)
  {
    DESC_CONTEXT_PARAM_ONLY--;
#endif
    /* Check pending post-processing */
    if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity != kDescContextIdle)
    {
      DescContextStateTask(DESC_CONTEXT_PARAM_ONLY);
    }
#if(kDescNumContexts > 1)
  }
#endif

  /*-------------------------*/
  /* Global tasks processing */
  /*-------------------------*/

#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  DescNpmProcessQueue();
#endif
  /* Call the DescNet  tasks */
  DescUudtNetStateTask();
  DescUsdtNetAbsStateTask();
}

/*******************************************************************************
* NAME:              DescContextStateTask
*
* CALLED BY:         any application function
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
static void DescContextStateTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /*------------------------*/
  /*  Post processing task  */
  /*------------------------*/
  if((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity & kDescContextActivePostProcess) != 0)
  {
    vuint8  postProcessState;

    DescInterruptDisable();
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity &= (DescContextActivity)(~kDescContextActivePostProcess);
    DescInterruptRestore();

    /* By default - ok */
    postProcessState = kDescPostHandlerStateOk;

    /* Check the status of the response */
    if(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].txState != kDescUsdtNetworkOk)
    {
      /* Clear ok, set error type */
      postProcessState = kDescPostHandlerStateTxFailed;
    }

    /* Add type of the response */
    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
    {
      /* Clear ok, set error type */
      postProcessState &= (vuint8)(~kDescPostHandlerStateOk);
      postProcessState |= kDescPostHandlerStateNegResSent;
    }

#if defined (DESC_ENABLE_RES_RINGBUFFER)
    /**********************
    * RingBuffer handling
    **********************/
    /* Ring buffer relevant states reset */
    DescRingBufferStateReset(DESC_CONTEXT_PARAM_ONLY);
#endif

    ApplDescGenericServiceConfirmation(postProcessState);
#if defined (DESC_ENABLE_POSTHANDLER_USAGE)
    /* Call the post handler only if application error was active */
    if(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isApplError != 0)
    {
      /* Call the post handler */
      g_descPostHandlerTable[g_descSvcInst[g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE]].postHandlerRef](DESC_CONTEXT_PARAM_FIRST postProcessState);
    }
#endif

#if defined (DESC_ENABLE_SUPPLIER_CALLBACKS)
    /* Call the post handler only if application error was active */
    if(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].isSupplPost != 0)
    {
      ApplDescSupplierConfirmation(DESC_CONTEXT_PARAM_FIRST postProcessState);
    }
#endif


#if defined (DESC_ENABLE_MANUFACTURER_CALLBACKS)
    ApplDescManufacturerConfirmation(DESC_CONTEXT_PARAM_FIRST postProcessState);
#endif


#if defined (DESC_ENABLE_AUTO_STATES) && (kDescStateGroupNumTransition > 0)
    /*----------------------------*/
    /*        Modify state        */
    /*----------------------------*/
    /* Called only in successfully finished
     * request processing */
    if((postProcessState & kDescPostHandlerStateOk) != 0)
    {
      DescSetState(g_descCurReqSvcInst[DESC_CONTEXT_PARAM_VALUE]);
    }
#endif
  }

  /*-------------------------*/
  /*    Rx processing task   */
  /*-------------------------*/
  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity == kDescContextActiveRxEnd)
  {
    /* Switch to process state */
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveProcess;

#if defined (DESC_ENABLE_DESCICN_SUPPORT)
    /* Check if this instance is a internal request */
    if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqType != kDescUsdtNetReqTypeInternal)
#endif
    {
      /* transfer addressing information from infoPool into MsgContext */
      if (g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqType == kDescUsdtNetReqTypeFunctional)
      {
        /* Specify that the current request was actually a functional one */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType = kDescFuncReq;
      }
      else
      {
        /* Set request addressing method */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType = kDescPhysReq;
      }
      /* Copy the SID for RCR-RP response.
       * necessary for multi session diag to know which one will be sent
       */
      g_descRcrrpBuffer[DESC_CONTEXT_PARAM_VALUE][1] = *g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr;

      /* Activate always the T2 timer. Once the timeout occurs,
       * there will be decision about sending a response or not.
       */
      DescActivateT2Timer(DESC_CONTEXT_PARAM_VALUE);
      DescActivateLimiter(DESC_CONTEXT_PARAM_VALUE);

#if defined(DESC_ENABLE_ALL_RES_AFTER_RCRRP)
      /*Reset Rcr-Rp Flag*/
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].rcrRpSent = 0;
#endif
    }
#if defined (DESC_ENABLE_DESCICN_SUPPORT)
    else
    {
      /* Set request addressing method always to simulate physical reception */
      g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType = kDescPhysReq;
    }
#endif
    /* Stores the length */
    g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen = g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->dataLength;

    /* Clear the error code */
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcNone;
    /* Process the dispatcher */
    DescDispatcher(DESC_CONTEXT_PARAM_ONLY);
  }

  /*------------------------------*/
  /*    Process processing task   */
  /*------------------------------*/
#if defined (DESC_ENABLE_MAINHANDLER_MULTICALL) || defined (DESC_ENABLE_PID_LIST_MODE)
  /*--------------------------------------*/
  /*    Repeated Main-Handler Call task   */
  /*--------------------------------------*/
  if((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity & (kDescContextActiveProcess |
                                                                       kDescContextActiveTxReady |
                                                                       kDescContextActiveTx |
                                                                       kDescContextActiveProcessEnd)) != 0)
  {
    /*--------------------------------------*/
    /*    Repeated Main-Handler Call task   */
    /*--------------------------------------*/
# if defined (DESC_ENABLE_MAINHANDLER_MULTICALL)
    if(g_descRecallHandler[DESC_CONTEXT_PARAM_VALUE] != V_NULL)
    {
#  if defined(DESC_ENABLE_PID_LIST_MODE)
      /* If list mode service - process using its context */
      if(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode == kDescContextModePidList)
      {
        g_descRecallHandler[DESC_CONTEXT_PARAM_VALUE](&g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE]);
      }
      else
#  endif
      {
        g_descRecallHandler[DESC_CONTEXT_PARAM_VALUE](&g_descMsgContext[DESC_CONTEXT_PARAM_VALUE]);
      }
    }
# endif
# if defined (DESC_ENABLE_PID_LIST_MODE)
    DescPidProcessorTask(DESC_CONTEXT_PARAM_ONLY);
# endif
  }
#endif

  /*-------------------------*/
  /*    Tx processing task   */
  /*-------------------------*/
  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity == kDescContextActiveTxReady)
  {
    /* Check if the TX channel is free */
#if defined (DESC_ENABLE_SCHEDULER_USDT_TRANSMITTER)
    /* Catch situation: ongoing USDT periodic response and parallel main response
     * check if other context wants to send or scheduler is not on sending */
    if((DESC_CONTEXT_PARAM_VALUE != kDescPrimContext)
        ||((g_descInterruptContextCtrl[kDescSchedulerContext].activity & kDescContextActiveTx) == 0))
#endif
    {
      if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType == kDescUsdtResponseNone)
      {
        /* Deactivate the RCR-RP timer here:
         * - equivalent to stopping it into ProcessingDone
         * - reduces code complexity to distinguish the different use cases
         */
        DescDeactivateT2Timer(DESC_CONTEXT_PARAM_VALUE);
        DescDeactivateLimiter(DESC_CONTEXT_PARAM_VALUE);

        /* Set the new state of CANdesc */
        g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveTx;

        /* reserve the TX channel and set the confirmation type to be expected */
        g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->dataLength = g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen;
#if defined (DESC_ENABLE_RES_RINGBUFFER)
        if (g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive != 0)
        {
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType    = kDescUsdtResponseRingBuffer;
        }
        else
#endif
        {
          /* Check if the negative response code is set */
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType    = (t_descUsdtNetResType)((g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)?kDescUsdtResponsePositive:kDescUsdtResponseNegative);
        }
#if defined (DESC_USDTNET_ENABLE_VECTOR_ISO_TP)
    /* Save code */
#else
        if (g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr == V_NULL)
        {
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr = DescUsdtNetGetTransmissionPtr(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr);
          memcpy(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr,g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr,g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->dataLength);
        }
        else
#endif
        {
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resDataPtr = g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr;
        }
        DescUsdtNetAbsTransmitResponse(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr);
      }
    }
  }
}

/*******************************************************************************
* NAME:              DescHandleInternRcrRp
*
* CALLED BY:         any application function
* PRECONDITIONS:
*
* DESCRIPTION:       Performs cyclic tasking for diagnostic purpouse.
*
*******************************************************************************/
static void DescHandleInternRcrRp(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{

 /*Send timeout*/
#if defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
  if(g_descRcrrpLimitCounter[DESC_CONTEXT_PARAM_VALUE] != 0)
#endif
  {
    /* Check for request with response required */
    if((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq &
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType) != 0)
    {
      /* Ignore the SPRMB value and send always positive response if P2 time has expired */
      g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.suppPosRes = 0;
      /* Check if the TX channel is free */
      if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType == kDescUsdtResponseNone)
      {
#if defined (DESC_ENABLE_SCHEDULER_USDT_TRANSMITTER)
        /* Catch situation: ongoing USDT periodic response and parallel main response
         * check if other context wants to send or scheduler is not on sending */
        if((DESC_CONTEXT_PARAM_VALUE != kDescPrimContext)
            ||((g_descInterruptContextCtrl[kDescSchedulerContext].activity & kDescContextActiveTx) == 0))
#endif
        {
          /* reserve the TX channel for single frame */
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->resType = kDescUsdtResponseNegativeRCR_RP;

          DescTransmitRcrRp(DESC_CONTEXT_PARAM_ONLY);
        }
      }
      else
      {
        /* Retry again */
        g_descT2Timer[DESC_CONTEXT_PARAM_VALUE]++;
      }
    }
    else
    {
      /* Run into assertion to show during development that the application can not fulfill
       * the timing requirements for the tester.
       */
      DescAssertUserAlways(kDescAssertApplLackOfConfirmation);
    }
  }
#if defined (DESC_ENABLE_RES_PENDING_COUNT_LIMIT)
  else
  {
# if defined (DESC_ENABLE_FORCE_RCR_RP)
    /* Reset this flag if set */
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].forcedRcrRpState = kDescForcedRcrRpIdle;
# endif
    /* Cancel interaction with Dem */
    DescOemDemCancelOperationOnOverrun(DESC_CONTEXT_PARAM_VALUE);
# if defined(DESC_ENABLE_RES_RINGBUFFER)
    if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive != 0)
    {
      DescRingBufferCancel(DESC_CONTEXT_PARAM_ONLY);
    }
    else
# endif
    {
# if defined(DESC_ENABLE_OEM_HANDLING_ON_RCRRP_LIMIT_EXPIRATION)
      /* Custom action */
      DescOemOnResPendingOverrun(DESC_CONTEXT_PARAM_VALUE);
# else
      DescInterruptDisable();
      /* Set no response - just finalize the request */
      g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = 0;
      /* Set an error so no complicatet checks to be performed and no PostHandler to be called */
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = (DescNegResCode)(~kDescNrcNone);

      /* Close the case :) */
      DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
      DescInterruptRestore();
# endif
    }
    /* Notify the application about timeout */
    ApplDescResponsePendingOverrun(DESC_CONTEXT_PARAM_ONLY);
  }
#endif
}

/*  ********************************************************************************
 * Function name:DescOemStartSessionDefault
 * Description:Processes the session change request, parametrizing the common processing
 * function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemStartSessionDefault(DescMsgContext* pMsgContext)
{
  DescOemPrepareSessionControl(pMsgContext, kDescStateSessionDefault);
}


/*  ********************************************************************************
 * Function name:DescOemStartSessionProgramming
 * Description:Processes the session change request, parametrizing the common processing
 * function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemStartSessionProgramming(DescMsgContext* pMsgContext)
{
  DescOemPrepareSessionControl(pMsgContext, kDescStateSessionProgramming);
}


/*  ********************************************************************************
 * Function name:DescOemStartSessionExtended
 * Description:Processes the session change request, parametrizing the common processing
 * function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemStartSessionExtended(DescMsgContext* pMsgContext)
{
  DescOemPrepareSessionControl(pMsgContext, kDescStateSessionExtended);
}


/*  ********************************************************************************
 * Function name:DescOemGetLevel_1_Request_Seed
 * Description:Manages the security get seed function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_1_Request_Seed(DescMsgContext* pMsgContext)
{
  DescOemSecuritySeed(pMsgContext, kDescStateSecurityAccessUnlockedL1);
}


/*  ********************************************************************************
 * Function name:DescOemSendLevel_1_sendKey_1
 * Description:Manages the security send key function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_1_sendKey_1(DescMsgContext* pMsgContext)
{
  DescOemSecurityKey(pMsgContext, kDescStateSecurityAccessUnlockedL1);
}


/*  ********************************************************************************
 * Function name:DescOemGetLevel_2_Request_Seed
 * Description:Manages the security get seed function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_2_Request_Seed(DescMsgContext* pMsgContext)
{
  DescOemSecuritySeed(pMsgContext, kDescStateSecurityAccessUnlocked_L2);
}


/*  ********************************************************************************
 * Function name:DescOemSendLevel_2_sendKey
 * Description:Manages the security send key function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_2_sendKey(DescMsgContext* pMsgContext)
{
  DescOemSecurityKey(pMsgContext, kDescStateSecurityAccessUnlocked_L2);
}


/*  ********************************************************************************
 * Function name:DescOemGetLevel_4_Request_Seed
 * Description:Manages the security get seed function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_4_Request_Seed(DescMsgContext* pMsgContext)
{
  DescOemSecuritySeed(pMsgContext, kDescStateSecurityAccessUnlocked_L4);
}


/*  ********************************************************************************
 * Function name:DescOemSendLevel_4_send_Key
 * Description:Manages the security send key function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_4_send_Key(DescMsgContext* pMsgContext)
{
  DescOemSecurityKey(pMsgContext, kDescStateSecurityAccessUnlocked_L4);
}


/*  ********************************************************************************
 * Function name:DescOemGetLevel_5_Request_Seed
 * Description:Manages the security get seed function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemGetLevel_5_Request_Seed(DescMsgContext* pMsgContext)
{
  DescOemSecuritySeed(pMsgContext, kDescStateSecurityAccessUnlocked_L5);
}


/*  ********************************************************************************
 * Function name:DescOemSendLevel_5_sendKey
 * Description:Manages the security send key function.
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemSendLevel_5_sendKey(DescMsgContext* pMsgContext)
{
  DescOemSecurityKey(pMsgContext, kDescStateSecurityAccessUnlocked_L5);
}


/*  ********************************************************************************
 * Function name:DescOemCommCtrlEnableRxEnableTx
 * Description: not available 
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemCommCtrlEnableRxEnableTx(DescMsgContext* pMsgContext)
{
  DescOemCommonCommCtrlProcess(DescMakeCommCtrlParam(kDescCommControlStateEnable, kDescCommControlStateEnable), pMsgContext);
}


/*  ********************************************************************************
 * Function name:DescOemCommCtrlEnableRxDisableTx
 * Description: not available 
 * Returns:  nothing
 * Parameter(s):
 *   - pMsgContext:
 *       - Contains all request properties.
 *       - Access type: read/write
 * Particularitie(s) and limitation(s): none
 ********************************************************************************  */
static void DESC_API_CALLBACK_TYPE DescOemCommCtrlEnableRxDisableTx(DescMsgContext* pMsgContext)
{
  DescOemCommonCommCtrlProcess(DescMakeCommCtrlParam(kDescCommControlStateDisable, kDescCommControlStateEnable), pMsgContext);
}


#if defined (DESC_ENABLE_ANY_PREHANDLER_USAGE)
/*******************************************************************************
* NAME:              DescDummyPreHandler
*
* CALLED BY:         DESCDispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Used instead of V_NULL pointer
*
*******************************************************************************/
static void DESC_API_CALL_TYPE DescDummyPreHandler(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Avoid warnings */
  DESC_CONTEXT_PARAM_DUMMY_USE;
}
#endif

#if defined (DESC_ENABLE_ANY_POSTHANDLER_USAGE)
/*******************************************************************************
* NAME:              DescDummyPostHandler
*
* CALLED BY:         DESCDispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Used instead of V_NULL pointer
*
*******************************************************************************/
static void DESC_API_CALL_TYPE DescDummyPostHandler(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  /* Avoid warnings */
  DESC_CONTEXT_PARAM_DUMMY_USE;
  DESC_IGNORE_UNREF_PARAM(status);
}
#endif

/*******************************************************************************
* NAME:              DescSessionGetSuppressPosBit
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Will return the current value of the SPRMIB.
*
*******************************************************************************/
DescBool DESC_API_CALL_TYPE DescIsSuppressPosResBitSet(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  return V_BOOL_EXPR(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.suppPosRes != 0);
}



/************************************************/
/* $3E Tester Present */
/************************************************/
/*******************************************************************************
* NAME:              DescOemProcessTesterPresent
*
* CALLED BY:         DescDispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       
*
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescOemProcessTesterPresent(DescMsgContext *pMsgContext)
{
#if (kDescNumContexts == 1)
  /* Avoid warnings */
  DESC_IGNORE_UNREF_PARAM(pMsgContext);
#endif
  DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
}

#if defined (DESC_ENABLE_DYN_COM_CTRL_PARAM)
/*******************************************************************************
* NAME:              DescOemCheckAndExtractCommTypeParam
*
* CALLED BY:         Default/CommunicationControl is activated
* PRECONDITIONS:     
*
* DESCRIPTION:       Checks if the msg type is APPL or NM.
*
*******************************************************************************/
static DescBool DescOemCheckAndExtractCommTypeParam(DescOemCommControlInfo * pCommControlInfo, DescMsgItem comType)
{
  DescBool returnValue = kDescFalse;

  if(((comType & 0x0F) <= kDescCommControlMsgTypeAll) &&
     ((comType & 0x0F) != 0))
  {
    /* Extract ComType parameter values */
    pCommControlInfo->msgTypes = (DescBitType)(comType & 0x03);
    pCommControlInfo->subNetNumber = (DescBitType)((comType & 0xF0) >> 4);

    returnValue = kDescTrue;
  }
  return returnValue;
}
#endif

/*******************************************************************************
* NAME:              DescEnableCommunication
*
* CALLED BY:         Application/DescInit/Session fall
* PRECONDITIONS:     
*
* DESCRIPTION:       Enables the communciation for all messages on all channels.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescEnableCommunication(void)
{
  /* Prepare for "TxEnable on ALL channels" */
  g_descCommControlInfo.subNetNumber   = kDescCommControlSubNetNumAll;
  g_descCommControlInfo.txPathState    = kDescCommControlStateEnable;
#if defined (DESC_ENABLE_RX_COMM_CONTROL)
  g_descCommControlInfo.rxPathState    = kDescCommControlStateEnable;
#endif
  g_descCommControlInfo.msgTypes       = kDescCommControlMsgTypeAll;

  /* Context parameter doesn't mean anything - use zero.*/
  DescOemPostCommonCommCtrlProcess(DESC_CONTEXT_PARAM_WRAPPER_FIRST(0) kDescPostHandlerStateOk);
}

/*******************************************************************************
* NAME:              DescOemCommonCommCtrlProcess
*
* CALLED BY:         DescOemCommCtrl_XXXableRxAndXXXableTx
* PRECONDITIONS:     
*
* DESCRIPTION:       Central communciation control processing.
*
*******************************************************************************/
static void DescOemCommonCommCtrlProcess(vuint8 reqInfo, DescMsgContext *pMsgContext)
{
  DescNegResCode errorCode = kDescNrcNone;

#if defined (DESC_ENABLE_DYN_COM_CTRL_PARAM)
  DescBool result;
#endif

  DESC_IGNORE_UNREF_PARAM(pMsgContext);

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
  if(g_descIsOemMainHdlrAlreadyCalled == kDescFalse)
#endif
  {
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
    g_descIsOemMainHdlrAlreadyCalled = kDescTrue;
#endif
    /* Optimize the pointer operation (only the first 4 bits are relevant)*/
#if defined (DESC_ENABLE_DYN_COM_CTRL_PARAM)
    /* Check control parameter type */
    result = DescOemCheckAndExtractCommTypeParam(&g_descCommControlInfo, pMsgContext->reqData[0]);
    if(kDescFalse == result)
    {
      errorCode = kDescNrcRequestOutOfRange;
    }
#else /*No Dynamic Communication Control Parameter*/
# if defined(DESC_ENABLE_COM_CTRL_PARAM_CHECK)
    if(pMsgContext->reqData[0] != (vuint8)kDescComParam)
    {
      errorCode = kDescNrcRequestOutOfRange;
    }
    else
# endif
    {
      g_descCommControlInfo.msgTypes = (DescBitType)((kDescComParam)& 0x03);
      g_descCommControlInfo.subNetNumber = (DescBitType)(((kDescComParam) & 0xF0) >> 4);
    }
#endif
    if(kDescNrcNone == errorCode)
    {
      /* Set the TX communication state */
      g_descCommControlInfo.txPathState = reqInfo;
#if defined (DESC_ENABLE_RX_COMM_CONTROL)
      /* Set the TX communication state */
      g_descCommControlInfo.rxPathState = (DescBitType)(reqInfo >> 2);
#endif
#if defined(DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
      g_descCommControlInfo.reqCommChannel = g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_WRAPPER_INDEX(pMsgContext->iContext)].infoPoolPtr->busInfo.comChannel;
#endif

      /* make customized parameter interpretation */
      DescOemCustomizeComTypeParam(&g_descCommControlInfo);

#if defined (DESC_ENABLE_COMM_CTRL_SUBNET_SUPPORT)
      /* Let the application decide which sub-network to which CAN channel is mapped */
#else
      if((g_descCommControlInfo.subNetNumber == kDescCommControlSubNetNumAll) ||
        (g_descCommControlInfo.subNetNumber == kDescCommControlSubNetNumRx))
      {
        /* Legal parameter values both for single and multi channel systems */
      }
      else
      {
# if defined (DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
        /* Assume 1:1 mapping subNetNumber:CAN (on multi channel system) */
        g_descCommControlInfo.commCtrlChannel = g_descCommControlInfo.subNetNumber;
        /* Convert subnetNum1 -> CAN0, etc.*/
        g_descCommControlInfo.commCtrlChannel--;
        /* If an invalid subnetwork (CAN channel) is requested - reject */
        if(g_descCommControlInfo.commCtrlChannel > (kDescNumCommChannels - 1))
        {
          errorCode = kDescNrcRequestOutOfRange;
        }
# else
        /* No sub-networks => no subnetwork number can be requested */
        errorCode = kDescNrcRequestOutOfRange;
# endif
      }
#endif

      /* Prepare the response length for positive response 
      * done by Dispatcher  (set to zero)
      */
    }
  }

  if(errorCode == kDescNrcNone)
  {
    /* Call the application for request data evaluation */
    ApplDescCheckCommCtrl(DESC_CONTEXT_PARAM_WRAPPER_FIRST(pMsgContext->iContext) &g_descCommControlInfo);
  }
  else
  {
    /* Only out of range is used - use the constant */
    DescSetNegResponse(DESC_CONTEXT_PARAM_WRAPPER_FIRST(pMsgContext->iContext) kDescNrcRequestOutOfRange);
    DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
  }
}

/*******************************************************************************
* NAME:              DescOemPostCommonCommCtrlProcess
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Processes the request after the positive response was sent.
*
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescOemPostCommonCommCtrlProcess(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  DESC_COMM_CHANNEL_LOCAL_PARAM_DEF

  /* If you intend to use the context parameter don't forget the DescEnableCommunication API!!! */
  DESC_CONTEXT_PARAM_DUMMY_USE;

  if((status & kDescPostHandlerStateOk) != 0)
  {
    switch(g_descCommControlInfo.subNetNumber)
    {
      case kDescCommControlSubNetNumAll:/* Disable all comm channels (CAN, LIN, etc.)*/
        DESC_COMM_CHANNEL_PARAM_VALUE_INIT;
        DESC_COMM_CHANNEL_LOOP
        {
          DESC_COMM_CHANNEL_PARAM_VALUE_DEC;
          DescCommCtrlManipulateCAN(DESC_COMM_CHANNEL_PARAM_ONLY);
        }
#if defined (DESC_ENABLE_COMM_CTRL_SUBNET_SUPPORT)
        /* Manipulate application channels */
        ApplDescSetCommMode(&g_descCommControlInfo);
#endif
        break;
      case kDescCommControlSubNetNumRx:/* Disable only the request RX comm channel (CAN)*/
        DescCommCtrlManipulateCAN(DESC_COMM_CHANNEL_PARAM_WRAP_ONLY(g_descCommControlInfo.reqCommChannel));
        break;
      default:
        if(g_descCommControlInfo.commCtrlChannel != kDescCommControlCanChNone)
        {
          DescCommCtrlManipulateCAN(DESC_COMM_CHANNEL_PARAM_WRAP_ONLY(g_descCommControlInfo.commCtrlChannel));
        }
#if defined (DESC_ENABLE_COMM_CTRL_SUBNET_SUPPORT)
        else
        {
          /* Only application specific communication busses (no CAN) */
          ApplDescSetCommMode(&g_descCommControlInfo);
        }
#endif
    }

    if((g_descCommControlInfo.txPathState & kDescCommControlStateEnable) != 0)
    {
      /* Notify the application about the enabling communication */
      ApplDescOnCommunicationEnable();
    }
    else
    {
      /* Notify the application about the disabling communication */
      ApplDescOnCommunicationDisable();
    }
  }
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
  /* Always clear the flag */
  g_descIsOemMainHdlrAlreadyCalled = kDescFalse;
#endif
}

/*******************************************************************************
* NAME:              DescCommCtrlManipulateCAN
*
* CALLED BY:         DescOemPostCommonCommCtrlProcess
* PRECONDITIONS:     
*
* DESCRIPTION:       Processes requested action.
*
*******************************************************************************/
static void DescCommCtrlManipulateCAN(DESC_COMM_CHANNEL_FORMAL_PARAM_DEF_ONLY)
{
  if((g_descCommControlInfo.txPathState & kDescCommControlStateEnable) != 0)
  {
    DescCommSetTxOnline(DESC_COMM_CHANNEL_PARAM_VALUE, g_descCommControlInfo.msgTypes);
  }
  else
  {
    DescCommSetTxOffline(DESC_COMM_CHANNEL_PARAM_VALUE, g_descCommControlInfo.msgTypes);
  }

#if defined (DESC_ENABLE_RX_COMM_CONTROL)
# if defined (DESC_ENABLE_MULTI_CHANNEL_SUPPORT)
  /* Reinit the comm channel in case of multi CAN */
  g_descCommControlInfo.commCtrlChannel = DESC_COMM_CHANNEL_PARAM_VALUE;
# endif
  /* let the application to manipulate the RX path */
  ApplDescSetCommModeOnRxPath(&g_descCommControlInfo);
#endif
}

/*******************************************************************************
* NAME:              DescOemPrepareSessionControl
*
* CALLED BY:         CANdesc
* PRECONDITIONS:     
*
* DESCRIPTION:       Prepares the response for DiagnosticSessionControl.
*
*******************************************************************************/
static void DescOemPrepareSessionControl(DescMsgContext *pMsgContext, DescStateGroup targetSession)
{
#if defined (DESC_ENABLE_P2_TIME_REPORT)
  DescMsg   resData;
  vuint16   p2Time, p2ExTime;
#endif

  DESC_IGNORE_UNREF_PARAM(pMsgContext);/* Not always used - ignore per default! */

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
  if(g_descIsOemMainHdlrAlreadyCalled == kDescFalse)
#endif
  {
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
    g_descIsOemMainHdlrAlreadyCalled = kDescTrue;
#endif
#if defined (DESC_ENABLE_P2_TIME_REPORT)
    resData = pMsgContext->resData;
    /* Set the new response length */
    pMsgContext->resDataLen = 4;

    DescGetSessionTimings(targetSession, &p2Time, &p2ExTime);
    /* Set P2 Time for the response */
    resData[0] = DescGetHiByte(p2Time);
    resData[1] = DescGetLoByte(p2Time);
    /* Set P2* Time for the response */
    resData[2] = DescGetHiByte(p2ExTime);
    resData[3] = DescGetLoByte(p2ExTime);
#endif
#if defined (DESC_ENABLE_NODE_POWER_CONTROL) && !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
    /* Store the CAN channel here, since there during the session transition there can be another request */
    DescSetNpmOnCanChannelActive(pMsgContext->busInfo.comChannel, g_descCanChannelMapQueue);
#endif
  }

  /* Ask the application for permission to accept the session transition */
  ApplDescCheckSessionTransition(DESC_CONTEXT_PARAM_WRAPPER_FIRST(pMsgContext->iContext) targetSession, g_descCurState.stateSession);
}

#if defined (DESC_ENABLE_COMMON_OEM_POST_HANDLER)
/*******************************************************************************
* NAME:              DescOemCommonSessionPostProcessing
*
* CALLED BY:         Dispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Common DiagnosticSessionControl session post handler.
*                    Workaround for session self-transitioning.
*
*******************************************************************************/
static void DescOemCommonSessionPostProcessing(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status, DescStateGroup newSession)
{
  /* Avoid warnings */
  DESC_CONTEXT_PARAM_DUMMY_USE;

  DESC_IGNORE_UNREF_PARAM(status);
  DESC_IGNORE_UNREF_PARAM(newSession);
# if defined (DESC_ENABLE_SESSION_SELFTRANSITION_SIM) || \
     defined (DESC_ENABLE_NODE_POWER_CONTROL) && !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  /* If ok ( no negative response, no transmission failure) */
  if((status & kDescPostHandlerStateOk) != 0)
  {
#  if defined (DESC_ENABLE_SESSION_SELFTRANSITION_SIM)
    /* Simulate session self-transition into default one */
    if((((DescStateGroup)g_descCurState.stateSession) & newSession) != 0)
    {
      DescSetStateSession(newSession);
    }
#  endif
  }
#  if defined (DESC_ENABLE_NODE_POWER_CONTROL) && !defined (DESC_ENABLE_DEFAULT_SESSION_SLEEP_PREVENTION)
  else
  {
    /* Reset the queue if error */
    g_descCanChannelMapQueue = 0;
  }
#  endif
# endif
}
#endif

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
/*******************************************************************************
* NAME:              DescSessionTransitionChecked
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Session transition check finished.
*
*******************************************************************************/
void DESC_API_CALL_TYPE DescSessionTransitionChecked(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Clear always the flag */
  g_descIsOemMainHdlrAlreadyCalled = kDescFalse;
  DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}
#endif

#if defined(DESC_ENABLE_TOTAL_ATTEMPT_COUNTER) && \
    defined(DESC_ENABLE_USE_ERR_CNTR_PROTECTION)
# error "Both options cannot be enabled. Switch Off One."
#endif


/*******************************************************************************
* Function name:  DescOemOnInvalidReq_27
* Description:    Special security state handling on invalid request
* Returns:        -
* Parameters:     iContext - Context parameter value of the active context
* Called by:         DescDispatcher
* Particularitie(s) and limitation(s): The function is called in case a general
*       format check has failed. The state should not be reset in case the SID
*       is not supported in active session/security state. The function will be also
*       called in that case, but because the SID is not supported in the active state
*       the "awaitKey" state will never be true during that active state (because
*       all requests to change that state are forbidden in that state).
*
*******************************************************************************/
static void DescOemOnInvalidReq_27(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Take only service $27 into account */
  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr[0] == 0x27)
  {
    g_descIsKeyAwaited = kDescFalse;
  }
}

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name:ApplDescSecurityAccessInitPowerOn
 * Description: Shall be called at ECU power on event.
 * Returns:  -
 * Parameter(s):none
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
static void DescSecurityOnceInitPowerOn(void)
{
# if defined (DESC_ENABLE_SA_STATIC_SEED)|| defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
  vuint8_least i = 0;
  for( ; i < (kDescNumStateSecurityAccess-1); i++)

  {
#  if defined (DESC_ENABLE_SA_STATIC_SEED)
    DescSetSAStoredSeed(i, kDescFalse);
#  endif
#  if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
    DescSetSADelayTimer(i, DescGetSAPwrOnTimeValue(i));
    DescSetSAAttemptCounter(i, 0);
#  endif
  }
# endif /*(DESC_ENABLE_SA_STATIC_SEED)|| defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)*/

# if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
/* already initialized */
# else
  DescSetSADelayTimer(0, DescGetSAPwrOnTimeValue(0));
  DescSetSAAttemptCounter(0, 0);
# endif

/*Set PowerOn timer values*/

/*Attempt counter*/
}
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name: DescSecurityAccessTimer
 * Description: Shall be called periodically by the application.
 * Returns:  -
 * Parameter(s):none
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
static void DescSecurityAccessTimer(void)
{
  vuint8_least i = 0;
  /*iterate over all timer for all levels*/
# if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
  for(; i < (kDescNumStateSecurityAccess-1); i++)
# endif
  {
   /*timer active?*/
    if(DescGetSADelayTimer(i) != 0)
    {
      DescDecrementSADelayTimer(i);

# if defined (DESC_ENABLE_ATT_CNTR_RESET_ON_TIME_EXPIRE)
      if(DescGetSADelayTimer(i) == 0)
      {
#  if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
#   if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
        DescStateGroup securityLevel = 2<<i;
#   endif
        ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnTimeExpire, 0);
#  endif
        DescSetSAAttemptCounter(i, 0);
      }
# endif
    }
  }
}
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name:DescGetAttemptCounterValue
 * Description: Reports the current value of the attempt counter
 * Returns:  The current value of the attempt counter
 * Parameter(s): - securityLevel: when level specific counters are used
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
vuint8 DescGetAttemptCounterValue(DESC_LEVEL_FORMAL_PARAM_DEF_ONLY)
{
  return DescGetSAAttemptCounter(DescGetInstanceIdxOfLevel(DESC_LEVEL_CONTEXT_PARAM_VALUE));
}
#endif

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name:DescSetAttemptCounterValue
 * Description: Sets a new value of the attempt counter
 * Returns:  -
 * Parameter(s): - securityLevel: when level specific counters are used
 *               - value: value of the attempt counter
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
void DescSetAttemptCounterValue(DESC_LEVEL_FORMAL_PARAM_DEF_FIRST vuint8 value)
{
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
  ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnApplRequest, value);
# endif
  DescSetSAAttemptCounter(DescGetInstanceIdxOfLevel(DESC_LEVEL_CONTEXT_PARAM_VALUE), value);
}
#endif

#if defined (DESC_ENABLE_START_SA_TIMER_EXTERN) &&  defined(DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name:DescStartSecureTimer
 * Description: Activate brute-force inhibition
 * Returns:  -
 * Parameter(s): - securityLevel: when level specific timers are used
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
void  DescStartSecureTimer(DESC_LEVEL_FORMAL_PARAM_DEF_ONLY)
{
  vuint8_least index = DescGetInstanceIdxOfLevel(DESC_LEVEL_CONTEXT_PARAM_VALUE);
  DescSetSADelayTimer(index, DescGetSADelayTimeValue(index));
}
#endif

#if defined (DESC_ENABLE_START_SA_TIMER_EXTERN) &&  defined(DESC_ENABLE_SA_TIMER_AND_COUNTER)
/* ********************************************************************************
 * Function name:DescStartSecureTimer
 * Description: Activate brute-force inhibition
 * Returns:  -
 * Parameter(s): - securityLevel: when level specific timers are used
 *               - value: value of the timer in ms
 * Particularitie(s) and limitation(s):
 ******************************************************************************** */
void  DescStartSecureTimerValue(DESC_LEVEL_FORMAL_PARAM_DEF_FIRST vuint16 value)
{
  DescSetSADelayTimer(DescGetInstanceIdxOfLevel(DESC_LEVEL_CONTEXT_PARAM_VALUE), DescGetTicksOfMs(value));
}
#endif

/*******************************************************************************
* NAME:              DescSecurityOnceInit
*
* CALLED BY:         DescInit
* PRECONDITIONS:
*
* DESCRIPTION:       Initilizes the network subcomponent common data.
*
*******************************************************************************/
static void DescSecurityOnceInit(void)
{
  g_descIsKeyAwaited = kDescFalse;
  /* Use invalid state */
  g_descSecurityAccessContext.securityLevel = 0;
}

#if defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)  || \
    defined (DESC_ENABLE_MULTIPLE_KEY_LENGTH) || \
    defined (DESC_ENABLE_SA_MULTI_SEED_OBJ) || \
    defined (DESC_ENABLE_MULTI_CHALLENGE_SECURITY) || \
    defined (DESC_ENABLE_DELAY_TIME_LEVEL_SPECIFIC)
/******************************************************************************
* Name         :  DescGetLevelIdxOfState
* Called by    :  SA component
* Preconditions:  None
* Parameters   :  StateLevel
* Description  :  Converts bit map into bit position
******************************************************************************/
static vuint8_least DescGetLevelIdxOfState(DescStateGroup securityLevel)
{
  vuint8_least levelIdx = 0;
  /* Must be non-zero value since this function shall not be called for the locked state!!! */
  DescAssertCommon((securityLevel > 0x01), kDescAssertZeroStateValue);

  /* Skip locked state and one iteration */
  securityLevel>>=2;

  while(securityLevel != 0)
  {
    securityLevel>>=1;
    levelIdx++;
  }
  return levelIdx;
}
#endif

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
/******************************************************************************
* Name         :  DescRepeaterSecurityAccessGetSeed
* Called by    :  DescOemSecuritySeed
* Preconditions:  None
* Parameters   :  Read in global Diag buffer
* Description  :  This function is called after key bytes have been received
*                 This is provided as example, has to be implemented by the user.
******************************************************************************/
static void DescRepeaterSecurityAccessGetSeed(DescMsgContext* pMsgContext)
{
  DESC_IGNORE_UNREF_PARAM(pMsgContext);
  ApplDescSecurityAccessGetSeed(&g_descSecurityAccessContext);
}
#endif

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
/******************************************************************************
* Name         :  DescRepeaterSecurityAccessSendKey
* Called by    :  DescOemSecurityKey
* Preconditions:  None
* Parameters   :  Read in global Diag buffer
* Description  :  This function is called after key bytes have been received
*                 This is provided as example, has to be implemented by the user.
******************************************************************************/
static void DescRepeaterSecurityAccessSendKey(DescMsgContext* pMsgContext)
{
  DESC_IGNORE_UNREF_PARAM(pMsgContext);
  ApplDescSecurityAccessCheckKey(&g_descSecurityAccessContext);
}
#endif

/******************************************************************************
* Name         :  DescOemSecuritySeed
* Called by    :  Dispatcher
* Preconditions:  None
* Parameters   :  Read in global Diag buffer
* Description  :  This function is called after seed bytes have been requested
*                 This is provided as example, has to be implemented by the user.
******************************************************************************/
static void DescOemSecuritySeed(DescMsgContext* pMsgContext, DescStateGroup requestedSecurityLevel)
{
#if defined (DESC_ENABLE_SECURITY_ACCESS_DATA)
  vuint16 length;
#endif
  /* Init application context here */
#if defined (DESC_ENABLE_SA_STATIC_SEED) || defined ( DESC_ENABLE_MULTIPLE_SEED_LENGTH)
  vuint8_least securitySeedObjIndex = DescGetSeedObjIdxOfLevel(requestedSecurityLevel);
#endif
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
  vuint8_least securityInstanceIndex = DescGetInstanceIdxOfLevel(requestedSecurityLevel);
#endif

  g_descSecurityAccessContext.dataLen       = DescGetSeedLength(securitySeedObjIndex);
  /* store seed in correct buffer if needed => GetBuffer*/
#if defined (DESC_ENABLE_SA_STATIC_SEED)
  g_descSecurityAccessContext.dataPtr       = (DescMsg)((DescGetSASeedBuffer(securitySeedObjIndex) == V_NULL)? pMsgContext->resData : DescGetSASeedBuffer(securitySeedObjIndex));
#else
  g_descSecurityAccessContext.dataPtr       = pMsgContext->resData;
#endif

#if defined (DESC_ENABLE_SECURITY_ACCESS_DATA)
  /* Copy the securityAccessDataRecord */
  length = pMsgContext->reqDataLen;
  if (length != 0)
  {
    DescMsgCopyRamToFarRam(g_securityAccessData, pMsgContext->reqData, length);
  }
  g_descSecurityAccessContext.securityAccessDataRecordLength       = length;
  g_descSecurityAccessContext.dataPtrSecurityAccessData            = g_securityAccessData;
#endif

#if (kDescNumContexts > 1)
  g_descSecurityAccessContext.iContext      = pMsgContext->iContext;
#endif

  /* Init now the currently processed seed level id */
  g_descSecurityAccessContext.securityLevel = requestedSecurityLevel;

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
  /*check timer*/
  if(DescGetSADelayTimer(securityInstanceIndex) != 0)
  {
    g_descNegResCode[DESC_CONTEXT_PARAM_WRAPPER_INDEX(pMsgContext->iContext)] = kDescNrcTimeDelayNotExpired;
    DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
  }
  else
#endif
  {
    /* secLevel==0 is prohibited and checked by CANdesc      */
    /* Thus, if secLevel == requested level, ECU is unlocked */
    if ( requestedSecurityLevel == DescGetStateSecurityAccess())
    {
      /* MemSet with zero. */
#if defined(DESC_ENABLE_FAR_BUFFER)
      VStdMemFarClr(g_descSecurityAccessContext.dataPtr, g_descSecurityAccessContext.dataLen );
#else
      VStdMemClr(g_descSecurityAccessContext.dataPtr, g_descSecurityAccessContext.dataLen );
#endif
      /* Finalize the request */
      DescSecurityAccessSeedReady(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
    }
    else
    {
      g_descIsKeyAwaited = kDescTrue;
#if defined (DESC_ENABLE_SA_STATIC_SEED)
      /* Call application if Seed needed */
      if(DescIsSAStoredSeed(securitySeedObjIndex))
      {
        /* Finalize the request */
        DescSecurityAccessSeedReady(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
      }
      else
#endif
      {
#if defined (DESC_ENABLE_SA_STATIC_SEED)
        if(DescGetSASeedBuffer(securitySeedObjIndex) != V_NULL)
        {
          DescSetSAStoredSeed(securitySeedObjIndex, kDescTrue);
        }
#endif
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
        DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_WRAPPER_FIRST(pMsgContext->iContext) DescRepeaterSecurityAccessGetSeed);
#endif
        ApplDescSecurityAccessGetSeed(&g_descSecurityAccessContext);
        /* wait for the application */
      }
    }
  }
}

/******************************************************************************
* Name         :  DescSecurityAccessSeedReady
* Called by    :  Application
* Preconditions:  None
* Parameters   :  iContext
* Description  :  This function is called after seed bytes have been written
******************************************************************************/
void DescSecurityAccessSeedReady(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
  {
    g_descIsKeyAwaited = kDescFalse;
  }
  else
  {
    /* Set the seed length */
    g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = g_descSecurityAccessContext.dataLen;
#if defined(DESC_ENABLE_SA_STATIC_SEED)
    if(DescGetSASeedBuffer(DescGetSeedObjIdxOfLevel(g_descSecurityAccessContext.securityLevel)) != V_NULL)
    {
      /* Copy the SEED (either the stored, newly generated or zero seed)  */
      DescMsgCopyRamToFarRam(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resData, g_descSecurityAccessContext.dataPtr, g_descSecurityAccessContext.dataLen);
    }
#endif
  }
  DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}

/******************************************************************************
* Name         :  DescOemSecurityKey
* Called by    :  Dispatcher
* Preconditions:  None
* Parameters   :  Read in global Diag buffer
* Description  :  This function is called after key bytes have been received
*                 This is provided as example, has to be implemented by the user.
******************************************************************************/
static void DescOemSecurityKey(DescMsgContext* pMsgContext, DescStateGroup requestedSecurityLevel)
{
#if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE) && defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
  DescStateGroup securityLevel = requestedSecurityLevel;
#endif
  if(g_descIsKeyAwaited != kDescFalse)
  {
#if defined (DESC_ENABLE_MULTIPLE_KEY_LENGTH)
    vuint8_least securityKeyObjIndex = DescGetKeyObjIdxOfLevel(requestedSecurityLevel);
#endif
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
    vuint8_least securityInstanceIndex = DescGetInstanceIdxOfLevel(requestedSecurityLevel);
#endif

    g_descIsKeyAwaited = kDescFalse;
    /*correct level*/
    if(g_descSecurityAccessContext.securityLevel == requestedSecurityLevel)
    {
      if(pMsgContext->reqDataLen == DescGetKeyLength(securityKeyObjIndex))
      {
        /*But first develop a new dispatcher concept*/
        g_descSecurityAccessContext.dataPtr        = pMsgContext->reqData;
        g_descSecurityAccessContext.dataLen        = (vuint8)pMsgContext->reqDataLen;
#if (kDescNumContexts > 1)
        g_descSecurityAccessContext.iContext       = pMsgContext->iContext;
#endif
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
        DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_WRAPPER_FIRST(pMsgContext->iContext) DescRepeaterSecurityAccessSendKey);
#endif
        ApplDescSecurityAccessCheckKey(&g_descSecurityAccessContext);
        /* wait for the application */
      }
      else
      {
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
        ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnKeyLengthInvalid, DescGetSAAttemptCounter(securityInstanceIndex)+1);
# endif
        DescIncrementSAAttemptCounter(securityInstanceIndex);
#endif
        /*raise false attempt counter*/
        g_descNegResCode[DESC_CONTEXT_PARAM_WRAPPER_INDEX(pMsgContext->iContext)] = kDescNrcInvalidFormat;
        /*finish processing*/
        DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
      }
    }
    else /*key for wrong level received*/
    {
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
      ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnKeyWrongLevel, DescGetSAAttemptCounter(securityInstanceIndex)+1);
# endif
      DescIncrementSAAttemptCounter(securityInstanceIndex);
#endif
      /*raise false attempt counter*/
      g_descNegResCode[DESC_CONTEXT_PARAM_WRAPPER_INDEX(pMsgContext->iContext)] = kDescNrcRequestSequenceError;
      /*finish processing*/
      DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
    }
  }
  else /*key not awaited*/
  {
    g_descNegResCode[DESC_CONTEXT_PARAM_WRAPPER_INDEX(pMsgContext->iContext)] = kDescNrcRequestSequenceError;
    /*finish processing*/
    DescProcessingDone(DESC_CONTEXT_PARAM_WRAPPER_ONLY(pMsgContext->iContext));
  }
}

/******************************************************************************
* Name         :  DescSecurityAccessKeyChecked
* Called by    :  Application
* Preconditions:  None
* Parameters   :  iContext
* Description  :  This function is called after key bytes have been validates
******************************************************************************/
void DescSecurityAccessKeyChecked(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
#if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE) && defined (DESC_ENABLE_SA_LEVEL_SPECIFIC)
  DescStateGroup securityLevel = g_descSecurityAccessContext.securityLevel;
#endif
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
  vuint8_least securityInstanceIndex = DescGetInstanceIdxOfLevel(g_descSecurityAccessContext.securityLevel);
#endif

  if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
  {
    /* do nothing */
  }
  else
  {
    /*Key not OK?*/
    if(g_descSecurityAccessContext.status != kDescSaStatusOk)
    {
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidKey;

#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
  /*increment counter*/
# if defined (DESC_ENABLE_ATTEMPT_COUNTER_LEVEL_SPECIFIC)
      /*counter supported for current level?*/
      if(DescGetSACounterValue(securityInstanceIndex) != 0)
# endif
      {
        if(DescGetSAAttemptCounter(securityInstanceIndex) >=  DescGetSACounterValue(securityInstanceIndex)-1)
        {
          g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcExceedNumOfAttempts;
          /*Start Timer*/
          DescSetSADelayTimer( securityInstanceIndex, DescGetSADelayTimeValue(DescGetDelayTimeIdxOfLevel(g_descSecurityAccessContext.securityLevel)) );
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
          ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnTooManyInvalidKeys, DescGetSAAttemptCounter(securityInstanceIndex)+1);
# endif
        }
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
        else
        {
          ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnInvalidKey, DescGetSAAttemptCounter(securityInstanceIndex)+1);
        }
# endif
        DescIncrementSAAttemptCounter(securityInstanceIndex);
      }
#endif
    }
    else /*Key OK*/
    {
#if defined (DESC_ENABLE_SA_TIMER_AND_COUNTER)
      /*Clear Counter*/
# if defined (DESC_ENABLE_REPORT_ATT_CNTR_STATE)
      ApplDescSecurityAccessOnAttCntrChanged(DESC_LEVEL_CONTEXT_PARAM_VALUE_SET_FIRST kDescSecAccAttCtrChgOnValidKey, 0);
# endif
      DescSetSAAttemptCounter(securityInstanceIndex, 0);
#endif
      /*Clear seed*/

#if defined (DESC_ENABLE_SA_STATIC_SEED)
      {
        vuint8_least securityIndex = DescGetSeedObjIdxOfLevel(g_descSecurityAccessContext.securityLevel);

        if(DescGetSASeedBuffer(securityIndex) != V_NULL)
        {
          DescSetSAStoredSeed(securityIndex, kDescFalse);
        }
      }
#endif
      /*transition is done via statemachine*/
    }
  }
  /*finish processing*/
  DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}

#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE) || \
    defined(DESC_ENABLE_PID_LIST_MODE)        || \
    defined(DESC_ENABLE_DYN_DEFINED_DPID_MODE)
/*******************************************************************************
* NAME:              DescPmGetPidResponseLen
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
* 
*******************************************************************************/
static DescMsgLen DescPmGetPidResponseLen(DescPidInstIndex pidHandle)
{
  DescMsgLen result;

  result = DescPmClientGetResLength(pidHandle);

  /* If client didn't recognize it as own DID */
  if(result == 0)
  {
    result = g_descPIDInfo[pidHandle].resDataLen;
  }

  return result;
}
#endif

/*******************************************************************************
* NAME:              DescAnalysePid
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
* 
*******************************************************************************/
static DescPidAnalyseFailureReason DescPmAnalysePid(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST V_MEMROM1 DescPidTinyInfo V_MEMROM2 V_MEMROM3 * pRefTinyInfo)
{
  DescPidAnalyseFailureReason reason = pmAnalyseReasonOther;
  /*---------------------------------------------*/
  /*     Service ID addressing method check      */
  /*---------------------------------------------*/
#if defined (DESC_ENABLE_ADDR_METHOD_CHECK)
  if ((pRefTinyInfo->msgAddInfo.reqType &
       g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType) == 0)
  {
    /* EXAMPLE: Additional activities may be necessary */
    /*DescOemOnInvalidAddrMethod(DESC_CONTEXT_PARAM_ONLY);*/
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcInvalidAddrMethod;
  }
  else
#endif
  {
#if defined (DESC_ENABLE_AUTO_STATES)
    /* Generated state checks */
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = DescCheckState(&(pRefTinyInfo->checkState));
    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
    {
#if defined (DESC_ENABLE_PID_PREHANDLER_USAGE)
      /*---------------------------------------------*/
      /*    Application specific condition check     */
      /*---------------------------------------------*/
      /* Call the pre handler */
      g_descPreHandlerTable[pRefTinyInfo->preHandlerRef](DESC_CONTEXT_PARAM_ONLY);
#endif
    }
#if defined (DESC_ENABLE_AUTO_STATES)
    else
    {
      /* Correct the negative response code dependent on the sub-function availability */
# if defined (DESC_ENABLE_PROTOCOL_KWP)
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcServiceNotSupportedInActiveMode)
# else
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcSubfunctionNotSupportedInActiveSession)
# endif
      {
        reason = pmAnalyseReasonSession;
        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcParamIdNotSupportedInSession;
      }

      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] ==  kDescOemNrcParamIdNotSupportedInSecurityState)
      {
        reason = pmAnalyseReasonSecurityState;
      }
    }
#endif
  }

  return reason;
}

#if defined(DESC_ENABLE_DYN_DEFINED_DID_MODE) || defined(DESC_ENABLE_PERIODIC_MODE)
/******************************************************************************
* NAME:              DescPmGetPidClientHandle
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
*
*******************************************************************************/
static DescPidInstIndex DescPmGetPidClientHandle(DescPidInstIndex pidInfoHandle, V_MEMROM1 DescPidClientInfo V_MEMROM2 V_MEMROM3 * pClientInfoTbl, DescPidInstIndex topOfTable)
{
  DescPidInstIndex result;
  DescPidInstIndex iter;

  result = kDescInvalidPidHandle;
  iter = topOfTable;
  while(iter != 0)
  {
    iter--;
    if(pClientInfoTbl[iter].pidHandle == pidInfoHandle)
    {
# if defined (DESC_ENABLE_MULTI_VARIANT)
      /*Check if it is allowed in the actual configuration*/
      if(DescPermittedInConfig(pClientInfoTbl[iter].tinyInfo.variantMask) != 0)
# endif
      {
        result = iter;
      }
      /* Break */
      iter = 0;
    }
  }
  return result;
}
#endif

/******************************************************************************
* NAME:              DescPmGetAvailablePidHandle
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
*
*******************************************************************************/
static DescPidInstIndex DescPmGetAvailablePidHandle(vuint16 pid)
{
  DescPidInstIndex result;

  result = DescPmGetPidPoolHandle(pid);
  result = DescPmClientCheckPid(result, pid);

  return result;
}

#if defined(DESC_ENABLE_PERIODIC_MODE)
/******************************************************************************
* NAME:              DescPmGetSupportedPidClientHandle
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:    Returns a reference of the DID in the client specific info table
*
*******************************************************************************/
static DescPidInstIndex DescPmGetSupportedPidClientHandle(vuint16 pid, V_MEMROM1 DescPidClientInfo V_MEMROM2 V_MEMROM3 * pClientInfoTbl, DescPidInstIndex topOfTable)
{
  DescPidInstIndex result;
  result = DescPmGetAvailablePidHandle(pid);
  /* No check needed for invalidity since all the functions are protected by such checks */
  result = DescPmGetPidClientHandle(result, pClientInfoTbl, topOfTable);
  return result;
}
#endif

/******************************************************************************
* NAME:              DescPmGetPidPoolHandle
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
*
*******************************************************************************/
static DescPidInstIndex DescPmGetPidPoolHandle(vuint16 pid)
{
  DescPidInstIndex  loIdx;
  DescPidInstIndex  hiIdx;
  DescPidInstIndex  idx;

  /* Init look-up */
  loIdx= 0;
  hiIdx= (DescPidInstIndex)(kDescNumPids - 1);

  do
  {
    /* Examine one concrete serviceInstanceHeader */
    /* ------------------------------------------ */
    idx = (DescPidInstIndex)(((vuint16)((vuint16)hiIdx + (vuint16)loIdx)) >> 1);

    /* Check for matching element */
    if(g_descPIDInfo[idx].reqPid == pid)
    {
#if defined (DESC_ENABLE_MULTI_CFG_SUPPORT)
      DescBool isSupported = ApplDescIsDataIdSupported(pid);
      if(isSupported == kDescFalse)
      {
        /* Nothing more to look for */
        break;
      }
      else
#endif
      {
#if defined (DESC_ENABLE_PID_SECURITY_FILTER)
        DescBool isAllowed = DescPmCheckPidSecurityAccess(&(g_descPIDInfo[idx].tinyInfo.checkState));
        if(isAllowed == kDescFalse)
        {
          /* Nothing more to look for */
          break;
        }
        else
#endif
        {
          /* Bingoooo :) */
#if defined (DESC_ENABLE_MULTI_VARIANT)
          /*Check if it is allowed in the actual configuration*/
          if(DescPermittedInConfig(g_descPIDInfo[idx].tinyInfo.variantMask) == 0)
          {
            return kDescInvalidPidHandle;
          }
          else
#endif
          {
            return idx;
          }
        }
      }
    }
    /* Determine which half shall be taken */
    if (pid < g_descPIDInfo[idx].reqPid)
    {
      /* Avoid use of signed types */
      if(idx == 0)
      {
        break;
      }
      hiIdx = (DescPidInstIndex)(idx - 1);
    }
    else
    {
      /* Message 'greater' than service instance: Use upper half of interval... */
      loIdx = (DescPidInstIndex)(idx + 1);
    }
  }
  while (loIdx <= hiIdx);
  /* return the search result */
  return kDescInvalidPidHandle;
}

/*******************************************************************************
* NAME:              DescRidAnalyseRoutine
*
* CALLED BY:         
* PRECONDITIONS:     
*
* DESCRIPTION:       
* 
*******************************************************************************/
static void DescRidAnalyseRoutine(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST V_MEMROM1 DescRidTinyInfo V_MEMROM2 V_MEMROM3 * pRefTinyInfo, DescBool isOnRid)
{
  /*---------------------------------------------*/
  /*     Service ID addressing method check      */
  /*---------------------------------------------*/
#if defined (DESC_ENABLE_ADDR_METHOD_CHECK)
  if ((pRefTinyInfo->msgAddInfo.reqType &
       g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType) == 0)
  {
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcInvalidAddrMethod;
  }
  else
#endif
  {
#if defined (DESC_ENABLE_AUTO_STATES)
    /* Generated state checks */
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = DescCheckState(&(pRefTinyInfo->checkState));
    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
#endif
    {
#if defined (DESC_ENABLE_RID_PREHANDLER_USAGE)
      /*---------------------------------------------*/
      /*    Application specific condition check     */
      /*---------------------------------------------*/
      /* Call the pre handler */
      g_descPreHandlerTable[pRefTinyInfo->preHandlerRef](DESC_CONTEXT_PARAM_ONLY);
#endif
    }
    else
    {
      /* Correct the negative response code dependent on the sub-function availability */
      if((g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcSubfunctionNotSupportedInActiveSession) &&
         (isOnRid == kDescTrue))
      {
        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcRequestOutOfRange;
      }
    }
  }
}

/*******************************************************************************
* NAME:              DescRidFindSubFunction
*
* CALLED BY:         DescRoutineControlByIdentifier
* PRECONDITIONS:     
*
* DESCRIPTION:       Check if sub-function supported
* 
*******************************************************************************/
static DescRidInstIndex DescRidFindSubFunction(vuint8 subFuncId, DescRidInstIndex ridRef)
{
  /* Assume failed */
  DescRidInstIndex result = kDescInvalidRidInstHandle;
  /* Valid sub-function at all (top limit)? ($1, $2 or $3 only)*/
  if(subFuncId < 4)
  {
    /* Is supported at all? */
    result = g_descRidSubFuncToCtrlTypeMap[subFuncId];

    if(result < kDescInvalidRidInstHandle)
    {
#if defined (DESC_ENABLE_RID_CTRL_OPER_CHECK)
      result = g_descRidControlTypeInfo[ridRef][result];
#else
# if (kDescNumRidControlTypes > 1)
      ridRef *= kDescNumRidControlTypes;
      ridRef += result;
# else
      /* Since 1:1 relation - the value is already assigned! */
# endif
      result = ridRef;
#endif
    }
  }
  return result;
}

/*******************************************************************************
* NAME:              DescRoutineControlByIdentifier
*
* CALLED BY:         DescDispatcher
* PRECONDITIONS:     
*
* DESCRIPTION:       Main handler for RID handling.
* 
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescRoutineControlByIdentifier(DescMsgContext* pMsgContext)
{
  DescRidInstIndex   ridInstRef;
  /* Use iContext when necessary */
  DESC_CONTEXT_PARAM_DEF_LOCAL
#if (kDescNumContexts > 1)
  /* Use iContext as name to be able to use the DESC_CONTEXT_PARAM_VALUE macro */
  DESC_CONTEXT_PARAM_VALUE = pMsgContext->iContext;
#endif

#if defined (DESC_ENABLE_RID_POSTHANDLER_USAGE)
  /* Set reference to invalid (skip application post-handler call) */
  g_descRidCurrInstRef = kDescInvalidRidInstHandle;
#endif
  /* Check minimum length (SubFunction and RID must be inside) */
  if(pMsgContext->reqDataLen > 2)
  {
    ridInstRef = DescRidFindRoutineId(DescMake16Bit(pMsgContext->reqData[1], pMsgContext->reqData[2]));

    /* Is the RID supported? */
    if(ridInstRef < kDescInvalidRidHandle)
    {
      /* analyze the RID specific information */
      DescRidAnalyseRoutine(DESC_CONTEXT_PARAM_FIRST &(g_descRIDInfo[ridInstRef]), kDescTrue);
      /* Dispatching successful?*/
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
      {
        /* Check if sub-function valid (at all and for RID) */
        ridInstRef = DescRidFindSubFunction(pMsgContext->reqData[0], ridInstRef);

#if defined (DESC_ENABLE_RID_POSTHANDLER_USAGE)
        /* Store the RID reference for later */
        g_descRidCurrInstRef = (DescMemRidInstIndex)ridInstRef;
#endif

        /* Does the RID support the control type? */
        if(ridInstRef < kDescInvalidRidInstHandle)
        {
          /* If dynamic request length OR valid one - process the service */
          if((g_descRIDInstInfo[ridInstRef].reqDataLen == 0) ||
             (pMsgContext->reqDataLen == g_descRIDInstInfo[ridInstRef].reqDataLen))
          {
            /* analyze the sub-function specific information */
            DescRidAnalyseRoutine(DESC_CONTEXT_PARAM_FIRST &(g_descRIDInstInfo[ridInstRef].tinyInfo), kDescFalse);

            /* Dispatching successful?*/
            if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
            {
#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
              /* Redirect main-handler call */
              _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, g_descRIDInstInfo[ridInstRef].mainHandler);
#endif
              /* Skip the routine Id and sub-function */
              pMsgContext->reqData+=3;
              pMsgContext->resData+=3;
              pMsgContext->reqDataLen-=3;
              /* Set the context mode */
              g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModeRoutineControl;
              /* Call the main-handler */
              g_descRIDInstInfo[ridInstRef].mainHandler(pMsgContext);
              /* Let the application to take care about the service */
              return;
            }
            /*else - NRC is already registered */
          }
          else
          {
            /* Invalid service length */
            g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidFormat;
          }
        }
        else
        {
          /* the RID is available but the sub-function not */
          g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcSubfunctionNotSupported;
        }
      }
      /*else - NRC is already registered */
    }
    else
    {
      /* the RID is not available but the sub-function not */
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcRequestOutOfRange;
    }
  }
  else
  {
    /* Too short service length */
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidFormat;
  }

  /* Error Case */
  DescProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}

/*******************************************************************************
* NAME:              DescRidProcessingDone
*
* CALLED BY:         Application
* PRECONDITIONS:     
*
* DESCRIPTION:       Subcomponent processing done for a RID 
* iContext for the main response is also the same for the RID 
*******************************************************************************/
static void DescRidProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* Add the sub-function and RID length */
  g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += 3;
  /* Go on with the response */
  DescFinalProcessingDone(DESC_CONTEXT_PARAM_ONLY);
#if defined (DESC_ENABLE_RES_RINGBUFFER)
  /* Modify the write pointer for the ring buffer manager (+ sub-function and RID length) */
  g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txWriteIndex += 3;
  /* Those bytes are protocol data */
  g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].protocolDataLen += 3;
#endif
}

#if defined (DESC_ENABLE_RID_POSTHANDLER_USAGE)
/*******************************************************************************
* NAME:              DescPostRoutineControlByIdentifier
*
* CALLED BY:         DescTask
* PRECONDITIONS:     
*
* DESCRIPTION:       Post handler for RID handling.
* 
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescPostRoutineControlByIdentifier(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
  if(g_descRidCurrInstRef < kDescInvalidRidInstHandle)
  {
    /* Call the post handler */
    g_descPostHandlerTable[g_descRIDInstInfo[g_descRidCurrInstRef].postHandlerRef](DESC_CONTEXT_PARAM_FIRST status);
  }
}
#endif

/*******************************************************************************
* NAME:              DescRidFindRoutineId
*
* CALLED BY:         Rid Processor
* PRECONDITIONS:     
*
* DESCRIPTION:       Linear look-up for RID (there are not so many RIDs expected).
* 
*******************************************************************************/
static DescRidLookUpIndex DescRidFindRoutineId(vuint16 rid)
{
  DescRidLookUpIndex  result = kDescInvalidRidHandle;
  DescRidLookUpIndex  iter   = kDescInvalidRidHandle;

  while(iter != 0)
  {
    iter--;
    if(g_descRidLookUpTable[iter] == rid)
    {
#if defined (DESC_ENABLE_MULTI_VARIANT)
      /*Check if it is allowed in the actual configuration*/
      if(DescPermittedInConfig(g_descRIDInfo[iter].variantMask) != 0)
#endif
      {
        result = iter;
      }
      iter = 0;
    }
  }
  return result;
}

/*******************************************************************************
* NAME:              DescIterInitPidListProcessor
*
* CALLED BY:         CANdesc
* PRECONDITIONS:
*
* DESCRIPTION:       Subcomponent initialization
*******************************************************************************/
static void DescIterInitPidListProcessor(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* These are initilized each time a request has been received */
  /*g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount = 0;
   *g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid = 0;
    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidProcessed = 0;*/
  /* No PID to be processed */
  g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady = 0;

}

/*******************************************************************************
* NAME:              DescPidProcessingDone
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Subcomponent processing done for a single PID
* iContext for the main response is also the same for the DID
*******************************************************************************/
static void DescPidProcessingDone(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  /* check for correct context */
  DescAssertContext((DESC_CONTEXT_PARAM_VALUE < kDescNumContexts),kDescAssertInvalidContextId);

#if defined (DESC_ENABLE_RES_RINGBUFFER)
  /********************************************************/
  /*        Mixed mode (Ring buffer || Linear)            */
  /********************************************************/
  /* The length will be composed in the PidDispatcher */
# if defined (DESC_ENABLE_DEBUG_USER )
  {
    DescMsgLen expectedPidLen;
#  if defined(DESC_ENABLE_UNIFIED_PID_MGR)
    /* Check for dynamic response length and multiple PID request */
    expectedPidLen = ApplDescGetPidDataLength(pidTypeReadOnce, g_descPidList[DESC_CONTEXT_PARAM_VALUE][g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid]);
    /* Add the PID itself */
    expectedPidLen+=2;
#  else
    expectedPidLen = DescPmGetPidResponseLen(g_descPidList[DESC_CONTEXT_PARAM_VALUE][g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid]);
#  endif

#  if defined (DESC_ENABLE_DYN_DID_RES_LENGTH)
    /* Check for non-dynamic length */
    if(expectedPidLen != 0)
#  endif
    {
      DescAssertUser(((g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen == expectedPidLen)||
                      (g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)), kDescAssertPidResLenToCddDefNotMatched);
    }/* else: for dynamic length - no validation */
  }
# endif
  /* PID processing finished */
  g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidProcessed = 1;

# if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
  /* If no ring buffer currently in use
   * OR
   * the transmission has been started AND current PID does not support ring-buffer
   * -> stop multiple calls
   */
  if((g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive == 0) ||
    ((g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferTxActive != 0) &&
     (g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferReactivated == 0)))
# endif
  {
    /* Deactivate the multicall mechanism */
    _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, V_NULL);
  }

  /* Check if a response transmission has been started */
  if(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity == kDescContextActiveProcess)
  {
    /* if there was an error detection - make negative response */
    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
    {
      /* Go on with the response */
      DescFinalProcessingDone(DESC_CONTEXT_PARAM_ONLY);
    }
    else
    {
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr[0] += kDescPosResIdOffset;
# if defined (DESC_ENABLE_DYN_DID_RES_LENGTH)
      /* Handling of DID with dynamic data length */
      if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen == 2)
      {
        /* If no response length set - the only PID is with dynamic length - use the application length */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen;
      }
# endif
      /* Set response length (add the Sid byte length) */
      g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += 1;
      /* No transmission started yet and RingBuffer active means: first RingBuffer PID */
      if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive == 0)
      {
        DescLinearResponseProcessing(DESC_CONTEXT_PARAM_ONLY);
      }
      /* Set ring buffer is under transmission */
      g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferTxActive = 1;
      g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive = 1;

# if defined (DESC_ENABLE_PID_LIST_MODE)
      /* Only for PID LIst mode */
      /* Check whether from now on a  response will be sent */
      if ((g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity != kDescContextActiveTxReady) &&
          (g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferReactivated == 0))

      {
        vuint16 currWrittenDataLen;
        vuint16 txMinLen;

        /* Speed up the process (add the response header length (sid + sub-service id bytes)) */
        currWrittenDataLen = (vuint16)((DescGetAvailBufferLenByInfoPool(infoPool) - 1) - DescRingBufferGetFreeSpace(DESC_CONTEXT_PARAM_ONLY));
        txMinLen = DescUsdtNetGetRingBuffTxMinLen(g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr);

        /* Shall we start the transmission ? (either full length or FF length is achieved)*/
        if(currWrittenDataLen >= txMinLen)
        {
          /* Update ringbuffer manager state */
          /* Set ready for transmit */
          g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveTxReady;
        }
        else
        {
          DescPidPrepareNextPid(DESC_CONTEXT_PARAM_FIRST currWrittenDataLen);
        }
      }
# else
      /* Mark that from now on a single response will be sent */
      g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveTxReady;
# endif
    }
  }
  else
  {
    /* Check if there is still a positive response */
    if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] != kDescNrcNone)
    {
      /* Force buffer underrun in the RingBufferCopy function */
      g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModeNormal;
    }
    else
    {
      /* Check if this is a linear response */
      if(g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferReactivated == 0)
      {
        /* -- Linear -- */
        DescLinearResponseProcessing(DESC_CONTEXT_PARAM_ONLY);
      }
    }
  }
#else
  /********************************************************/
  /*                  Pure linear mode                    */
  /********************************************************/
    /* Stop always the current main-handler cyclic call */
  _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, V_NULL);

  /* Check positive or negative responses */
  if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
  {
    /* Calculate the common length up to now (including the PID previosely placed) */
    g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen + kDescReservedBytesForPid;

    /* Check BUS's buffer overflow */
    if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen > (DescMsgLen)(4095 - 1))
    {
      /* Accept only bus specific length */
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcResponseTooLong;
    }
    else
    {
      g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData += g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen;
      /* Process next PID */
      g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid++;

      if(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid <
         g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount)
      {
        /* No transmission up to now initiated, no ring buffer used - only linear buffer usage - take immediatelly the next PID */
        g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady = 1;
        /* Skip the final response activation */
        return;
      }
    }
  }
  /* Go on with the response */
  DescFinalProcessingDone(DESC_CONTEXT_PARAM_ONLY);
#endif
}

#if defined (DESC_ENABLE_RES_RINGBUFFER)
# if defined (DESC_ENABLE_PID_LIST_MODE)
/*******************************************************************************
* NAME:              DescPidPrepareNextPid
*
* CALLED BY:         Application
* PRECONDITIONS:
*
* DESCRIPTION:       Prepare the handling of the next PID in case of multiple PIDs and ring buffer
*
*******************************************************************************/
static void DescPidPrepareNextPid(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint16 currWrittenDataLen)
{
  if ((g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid +1) >= g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount)
  {
    /* Update ringbuffer manager state */
    /* Set ready for transmit */
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].activity = kDescContextActiveTxReady;
  }
  else
  {
    /* Reset the written byte counter - this will avoid this code execution even if the next MainHandler is not so fast with the data suppliment. */
    g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].bytesWritten = 0;
    /* Set back to zero the protocol length */
    g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].protocolDataLen = 0;
    /* Prepare where to write the data if linear writing used (offset 2 will be added in the PIDTask after copy of PID )*/
    g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData = &g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr[currWrittenDataLen];
    /* Process next PID */
    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid++;

    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidProcessed = 0;
    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isSpaceRequired = 0;
    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady = 1;

    /* offset will be set again in next PID handling */
    g_descInterruptContextCtrl[DESC_CONTEXT_PARAM_VALUE].infoPoolPtr->reqDataPtr[0] -= kDescPosResIdOffset;
    /* Set response length will be added again in next PID */
    g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen -= 1;

    /* reset ringbuffer activity */
    g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferActive = 0;
  }
}
# endif
#endif

/*******************************************************************************
* NAME:              DescPidProcessorTask
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Subcomponent task functionality. Polling mode.
*
*******************************************************************************/
static void DescPidProcessorTask(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  DescPidInstIndex pidHandle;

  /* Active task only if PID list mode active */
  if(g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode == kDescContextModePidList)
  {
    /* Process next PID? */
    if(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady !=0)
    {
      g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady = 0;
#if defined (DESC_ENABLE_RES_RINGBUFFER)
      /* Reset the temporary state (may be the next PID will use linear buffer who knows :o) ) */
      g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].isRingBufferReactivated = 0;
#endif
#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
      /* Set post handler to be called */
      DescPidDoQueuePostHandlerAt(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid);
#endif
      /*---------------------*/
      /* Execute main handler*/
      /*---------------------*/
      /* Cache the reference */
      pidHandle = g_descPidList[DESC_CONTEXT_PARAM_VALUE][g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid];
      {
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
        /* Use the global service id $22 preferences */

        /* Copy the PID again */
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData = g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData;
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData[0] = DescGetHiByte(pidHandle);
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData[1] = DescGetLoByte(pidHandle);
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen = 2;
#else
        /* Copy the response information */
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = g_descPIDInfo[pidHandle].tinyInfo.msgAddInfo.resOnReq;
        /* Put the PID inside */
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData[0] = DescGetHiByte(g_descPIDInfo[pidHandle].reqPid);
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData[1] = DescGetLoByte(g_descPIDInfo[pidHandle].reqPid);
#endif
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData += kDescReservedBytesForPid;

        /* Copy this location into the original context to be able to use the free linear space calculation function */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resData = g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resData;

        /* Zero the response length */
        g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = 0;
#if defined (DESC_ENABLE_RES_RINGBUFFER)
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txWriteIndex += kDescReservedBytesForPid;
        /* Once started transmission - there are no data rather than the PID inside */
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].bytesWritten = 0;
        /* Initiate the none application data length - PID is 2 Byte or the first time 3Byte*/
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].protocolDataLen += kDescReservedBytesForPid;
#endif

#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
# if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
        /* If each service needs it - start always here to save ROM for the application */
        _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, ApplDescReadDataByIdentifier);
# endif
        /* Call the only available main-handler for PID read: Sid $22's one.*/
        ApplDescReadDataByIdentifier(&g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE]);
#else
# if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
        /* If each service needs it - start always here to save ROM for the application */
        _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, g_descPIDInfo[pidHandle].mainHandler);
# endif
        /* Give the control to the application */
        g_descPIDInfo[pidHandle].mainHandler(&g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE]);
#endif
      }
    }
  }
}

/*******************************************************************************
* NAME:              DescPidDispatcher
*
* CALLED BY:         PidTask
* PRECONDITIONS:
*
* DESCRIPTION:       Processes a single PID with dispatcher functionality.
*
*******************************************************************************/
static void DescPidDispatcher(DESC_CONTEXT_FORMAL_PARAM_DEF_ONLY)
{
  vuint8_least     iter;
  DescPidInstIndex pidHandle;

#if defined(DESC_ENABLE_PID_NRC_ALL_ON_WRONG_SESSION)
  vuint8_least     numPidsNotSuppInSession = 0;
#endif

  /* No data to be send to the application */
  g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen = 0;
  /* Init the counter */
  g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen >>= 1; /* (length div 2), since the PID are 2 Byte */
  /* Already initialized in DescDispatcher */
  /* g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = 0; */

#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
  /* Clear the post-handler queue */
  iter = (vuint8_least)kDescNumPostHdlrQueueBytes;
  while(iter > 0)
  {
    iter--;
    g_descPidPostHdlrQueue[iter] = 0;
  }
#endif
  g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount = 0;
  /* Initialize the current PID ref to be processed */
  g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].curPid = 0;

  /* Req data len contains still the count of the PIDs */
  /* Process all PIDs until an error has been detected */
  iter = (vuint8_least)(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen);
  while((iter != 0)&&
        (g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone))
  {
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
    DescBool isSupported;
    pidHandle = DescMake16Bit(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData[0],
                              g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData[1]);
    isSupported = ApplDescIsPidSupported(pidTypeReadOnce, pidHandle);
#else
    /* Find PID (use main pool since each read-able PID is accessible by $22)*/
    pidHandle = DescPmGetAvailablePidHandle(DescMake16Bit(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData[0],
                                                          g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData[1]));
#endif
    /* Decrement counter (already divided by 2) */
    iter--;
    /* Next PID prepare */
    g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqData +=2;

    /* If found */
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
    if(isSupported != kDescFalse)
#else
    if(pidHandle < kDescInvalidPidHandle)
#endif
    {
      /* Found - Jepiiii */
      DescMsgLen pidResLen;
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
      /* Check for dynamic response length and multiple PID request */
      pidResLen = ApplDescGetPidDataLength(pidTypeReadOnce, pidHandle);
#else
      /* Check for dynamic response length and multiple PID request */
      pidResLen = DescPmGetPidResponseLen(pidHandle);
#endif

#if defined (DESC_ENABLE_DYN_DID_RES_LENGTH)
      /* Only in single PID mode and if last PID in the list, a PID with dynamic length will be accepted */
      if((pidResLen != 0)||
# if defined (DESC_ENABLE_RES_RINGBUFFER)
        /* Ringbuffer: with dynamic length may be only single PID request */
        (g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen == 1)
# else
        /* Linear: with dynamic length may be only the last PID or single PID request */
        (iter == 0)
# endif
        )/* end if expr */
#endif
      {
#if !defined(DESC_ENABLE_UNIFIED_PID_MGR) &&  defined(DESC_ENABLE_SKIP_PID)
        DescPidAnalyseFailureReason analyseReason;
#endif
        g_descPidList[DESC_CONTEXT_PARAM_VALUE][g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount] = (DescMemPidInstIndex)pidHandle;
        /* Do dispatch the PID */
#if defined(DESC_ENABLE_UNIFIED_PID_MGR)
        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = ApplDescVerifyPidAccessConditions(pidTypeReadOnce, pidHandle);
#else
# if defined(DESC_ENABLE_SKIP_PID)
        analyseReason = DescPmAnalysePid(DESC_CONTEXT_PARAM_FIRST &g_descPIDInfo[pidHandle].tinyInfo);
# else
        (void)DescPmAnalysePid(DESC_CONTEXT_PARAM_FIRST &g_descPIDInfo[pidHandle].tinyInfo);
# endif
#endif
        {
          /* if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone) -> PostHandler has to be called in any case */
#if defined(DESC_ENABLE_SKIP_PID)
# if defined(DESC_ENABLE_UNIFIED_PID_MGR)
          switch(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE])
# else
          switch(analyseReason)
# endif
#endif
          {
#if defined(DESC_ENABLE_SKIP_PID)
# if defined(DESC_ENABLE_UNIFIED_PID_MGR)
#  if defined(DESC_ENABLE_SKIP_PID_ON_WRONG_SESSION)
          case kDescOemNrcParamIdNotSupportedInSession:
          /*Fall Through*/
#  endif
#  if defined(DESC_ENABLE_SKIP_PID_ON_WRONG_SECURITY_STATE)
          case kDescOemNrcParamIdNotSupportedInSecurityState:
          /*Fall Through*/
#  endif
# else
#  if defined(DESC_ENABLE_SKIP_PID_ON_WRONG_SESSION)
          case pmAnalyseReasonSession:
          /*Fall Through*/
#  endif
#  if defined(DESC_ENABLE_SKIP_PID_ON_WRONG_SECURITY_STATE)
          case pmAnalyseReasonSecurityState:
#  endif
# endif
              /* Just treat it as "not supported" - undo the registered NRC */
            g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcNone;
# if defined(DESC_ENABLE_PID_NRC_ALL_ON_WRONG_SESSION)
            ++numPidsNotSuppInSession;
# endif
            break;
         default:
#endif /*DESC_ENABLE_SKIP_PID*/
#if defined (DESC_ENABLE_PID_PREHANDLER_USAGE) && \
    defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
            /* Check for non-dummy pre-handler */
            if(g_descPIDInfo[pidHandle].tinyInfo.preHandlerRef != 0)
            {
              /* Set post handler to be called */
              DescPidDoQueuePostHandlerAt(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount);
            }
#endif
            /* One PID found - set it here because it will be used also for the post handler call */
            g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount++;
            /* Add the current PID response dataLen to the total response */
            g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen += (DescMsgLen)(pidResLen + 2);

          } /*switch*/
        }
      }
#if defined (DESC_ENABLE_DYN_DID_RES_LENGTH)
      else
      {
        /* A PID with non constant length is illegally used */
        g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcRequestOutOfRange;
      }
#endif
    }
  }
  /* If not found - no more elements */
  if(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount == 0)
  {
#if defined(DESC_ENABLE_PID_NRC_ALL_ON_WRONG_SESSION)
    if(numPidsNotSuppInSession != 0)
    {
      /* Set the session NRC only if the supported PIDs were not supported in the session */
      DescSetNegResponse(DESC_CONTEXT_PARAM_FIRST kDescOemNrcParamIdNotSupportedInSession);
    }
    else
#endif
    {
      /* May be no PID found - negative response */
      /* Important : use the function call to avoid overwriting of the NRC if previously set */
      DescSetNegResponse(DESC_CONTEXT_PARAM_FIRST kDescNrcRequestOutOfRange);
    }
  }

  /* Check bus's buffer overflow */
  if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen > (DescMsgLen)(4095 - 1)
#if !defined (DESC_ENABLE_RES_RINGBUFFER)
    /* If linear buffer - check for overflow */
     || g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen > (DescMsgLen)(DescGetAvailBufferLenByMsgContext(&g_descMsgContext[DESC_CONTEXT_PARAM_VALUE]) - 1)
#endif
    )
  {
    /* Accept only bus specific length */
    /* Important : use the function call to avoid overwriting of the NRC if previously set */
    DescSetNegResponse(DESC_CONTEXT_PARAM_FIRST kDescOemNrcResponseTooLong);
  }
#if !defined (DESC_ENABLE_RES_RINGBUFFER)
  /* If linear buffer - build the total length iteractively (assume dynamic length signals) */
  g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].resDataLen = 0;
#endif
}

/*******************************************************************************
* NAME:              DescPostReadDataByIdentifier
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Post handler for PID list handling.
*
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescPostReadDataByIdentifier(DESC_CONTEXT_FORMAL_PARAM_DEF_FIRST vuint8 status)
{
#if defined (DESC_ENABLE_PID_POSTHANDLER_USAGE)
  DescPidInstIndex localPidInfoRef;


  localPidInfoRef = 0;
  /* Merge the main response status with the applications */
  while(g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount != 0)
  {
    /* Check if the post handler may be called */
    if(DescPidIsPostHandlerQueuedAt(localPidInfoRef))
    {
      /* Call the post handler */
      g_descPostHandlerTable[g_descPIDInfo[g_descPidList[DESC_CONTEXT_PARAM_VALUE][localPidInfoRef]].postHandlerRef](DESC_CONTEXT_PARAM_FIRST status);
    }
    /* Decrement queued count */
    g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].pidCount--;
    /* Take the next post handler */
    localPidInfoRef++;
  }
#endif
#if defined (DESC_ENABLE_RES_RINGBUFFER)
  /* If no ring buffer active -> the transmission will start through DescFinalProcessingDone() which sets the context back to normal */
  /* Set the CANdesc in a normal mode */
  g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModeNormal;
#endif
  DESC_IGNORE_UNREF_PARAM(status);
#if (kDescNumContexts > 1)
  DESC_IGNORE_UNREF_PARAM(DESC_CONTEXT_PARAM_VALUE);
#endif
}

/*******************************************************************************
* NAME:              DescReadDataByIdentifier
*
* CALLED BY:         DescTask
* PRECONDITIONS:
*
* DESCRIPTION:       Main handler for PID list handling.
*
*******************************************************************************/
static void DESC_API_CALLBACK_TYPE DescReadDataByIdentifier(DescMsgContext *pMsgContext)
{
  /* Use iContext when necessary */
  DESC_CONTEXT_PARAM_DEF_LOCAL

#if (kDescNumContexts > 1)
  /* Use iContext as name to be able to use the DESC_CONTEXT_PARAM_VALUE macro */
  DESC_CONTEXT_PARAM_VALUE = pMsgContext->iContext;
#endif

#if defined (DESC_ENABLE_PERMANENT_MAINHANDLER_MULTICALL)
  /* Disable this multiple service call */
  _DescStartRepeatedServiceCall(DESC_CONTEXT_PARAM_VALUE, V_NULL);
#endif
  /* The length for this service shall be ZERO to allow the application (CANdesc)
   * to check it */
  /* Check if at least one PID is available (at least 2 Byte) */
  /* Check if the length is multiple of 2, since each PID is 2 Byte.*/
  if((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen > 1)&&
    ((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen & 0x01) == 0))
  {
    /* Also the capacity of the ECU shall not be exceeded */
    if((g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].reqDataLen >> 1) <= kDescNumMaxPidList)
    {
      /* Set the CANdesc in a PID List mode */
      g_descContextCtrl[DESC_CONTEXT_PARAM_VALUE].contextMode = kDescContextModePidList;
      /* Copy the original structure */
      g_descPidMsgContext[DESC_CONTEXT_PARAM_VALUE] = *pMsgContext;
      /* Dispatch all PID */
      DescPidDispatcher(DESC_CONTEXT_PARAM_ONLY);
      /* Check if any error was found */
      if(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] == kDescNrcNone)
      {
        /* Prepare for datat processing */
#if defined (DESC_ENABLE_RES_RINGBUFFER)
        /* Start from the begining */
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txReadIndex = 0;
        /* Write after the SID */
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].txWriteIndex = 1;
        /* Once started transmission - there are no data rather than the PID inside (will be written later) */
        /* g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].bytesWritten = 0;*/
        /* Initiate the none application data length - 1Byte SID*/
        g_descRingBufferCtrl[DESC_CONTEXT_PARAM_VALUE].protocolDataLen = 1;
        g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidProcessed = 0;
        g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isSpaceRequired = 0;
#endif
        /* Process the first PID
        * stack utilization optimization */
        g_descPidProcessorState[DESC_CONTEXT_PARAM_VALUE].isPidReady = 1;
        return;
      }
    }
    else
    {
      /* Too many PIDs */
      g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescOemNrcTooManyPIDs;
    }
  }
  else
  {
    /* Invalid length */
    g_descNegResCode[DESC_CONTEXT_PARAM_VALUE] = kDescNrcInvalidFormat;
  }
#if defined (DESC_ENABLE_PROTOCOL_KWP)
  /* KWP shall not respond on failed functionally requested service $22 with NR $31 ($33 is mapped to $31)*/
  if(g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.reqType == kDescFuncReq)
  {
    switch(g_descNegResCode[DESC_CONTEXT_PARAM_VALUE])
    {
      case kDescNrcRequestOutOfRange:
        /* Fall through */
      case kDescNrcAccessDenied:
        /* Suppress response */
        g_descMsgContext[DESC_CONTEXT_PARAM_VALUE].msgAddInfo.resOnReq = 0;
        break;
      default:/* Normal processing */ break;
    }
  }
#endif
  /* Reaching this point means diagnostic error was found */
  DescFinalProcessingDone(DESC_CONTEXT_PARAM_ONLY);
}



