| /**************************************************************************** |
| |
| (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 |
| www.systec-electronic.com |
| |
| Project: openPOWERLINK |
| |
| Description: source file for generic EPL API module |
| |
| License: |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| 3. Neither the name of SYSTEC electronic GmbH nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without prior written permission. For written |
| permission, please contact info@systec-electronic.com. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGE. |
| |
| Severability Clause: |
| |
| If a provision of this License is or becomes illegal, invalid or |
| unenforceable in any jurisdiction, that shall not affect: |
| 1. the validity or enforceability in that jurisdiction of any other |
| provision of this License; or |
| 2. the validity or enforceability in other jurisdictions of that or |
| any other provision of this License. |
| |
| ------------------------------------------------------------------------- |
| |
| $RCSfile: EplApiGeneric.c,v $ |
| |
| $Author: D.Krueger $ |
| |
| $Revision: 1.21 $ $Date: 2008/11/21 09:00:38 $ |
| |
| $State: Exp $ |
| |
| Build Environment: |
| GCC V3.4 |
| |
| ------------------------------------------------------------------------- |
| |
| Revision History: |
| |
| 2006/09/05 d.k.: start of the implementation, version 1.00 |
| |
| ****************************************************************************/ |
| |
| #include "Epl.h" |
| #include "kernel/EplDllk.h" |
| #include "kernel/EplErrorHandlerk.h" |
| #include "kernel/EplEventk.h" |
| #include "kernel/EplNmtk.h" |
| #include "kernel/EplObdk.h" |
| #include "kernel/EplTimerk.h" |
| #include "kernel/EplDllkCal.h" |
| #include "kernel/EplPdokCal.h" |
| #include "user/EplDlluCal.h" |
| #include "user/EplLedu.h" |
| #include "user/EplNmtCnu.h" |
| #include "user/EplNmtMnu.h" |
| #include "user/EplSdoComu.h" |
| #include "user/EplIdentu.h" |
| #include "user/EplStatusu.h" |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) |
| #include "kernel/EplPdok.h" |
| #endif |
| |
| #include "SharedBuff.h" |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0) |
| #error "EPL API layer needs EPL module OBDK!" |
| #endif |
| |
| /***************************************************************************/ |
| /* */ |
| /* */ |
| /* G L O B A L D E F I N I T I O N S */ |
| /* */ |
| /* */ |
| /***************************************************************************/ |
| |
| //--------------------------------------------------------------------------- |
| // const defines |
| //--------------------------------------------------------------------------- |
| |
| //--------------------------------------------------------------------------- |
| // local types |
| //--------------------------------------------------------------------------- |
| |
| //--------------------------------------------------------------------------- |
| // modul globale vars |
| //--------------------------------------------------------------------------- |
| |
| //--------------------------------------------------------------------------- |
| // local function prototypes |
| //--------------------------------------------------------------------------- |
| |
| /***************************************************************************/ |
| /* */ |
| /* */ |
| /* C L A S S EplApi */ |
| /* */ |
| /* */ |
| /***************************************************************************/ |
| // |
| // Description: |
| // |
| // |
| /***************************************************************************/ |
| |
| //=========================================================================// |
| // // |
| // P R I V A T E D E F I N I T I O N S // |
| // // |
| //=========================================================================// |
| |
| //--------------------------------------------------------------------------- |
| // const defines |
| //--------------------------------------------------------------------------- |
| |
| //--------------------------------------------------------------------------- |
| // local types |
| //--------------------------------------------------------------------------- |
| |
| typedef struct { |
| tEplApiInitParam m_InitParam; |
| |
| } tEplApiInstance; |
| |
| //--------------------------------------------------------------------------- |
| // local vars |
| //--------------------------------------------------------------------------- |
| |
| static tEplApiInstance EplApiInstance_g; |
| |
| //--------------------------------------------------------------------------- |
| // local function prototypes |
| //--------------------------------------------------------------------------- |
| |
| // NMT state change event callback function |
| static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange |
| NmtStateChange_p); |
| |
| // update DLL configuration from OD |
| static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p); |
| |
| // update OD from init param |
| static tEplKernel PUBLIC EplApiUpdateObd(void); |
| |
| // process events from user event queue |
| static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p); |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| // callback function of SDO module |
| static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p); |
| #endif |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // callback functions of NmtMnu module |
| static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, |
| tEplNmtNodeEvent NodeEvent_p, |
| tEplNmtState NmtState_p, |
| WORD wErrorCode_p, |
| BOOL fMandatory_p); |
| |
| static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, |
| tEplNmtState NmtState_p, |
| WORD wErrorCode_p); |
| #endif |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) |
| // callback function of Ledu module |
| static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, |
| BOOL fOn_p); |
| #endif |
| |
| // OD initialization function (implemented in Objdict.c) |
| tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p); |
| |
| //=========================================================================// |
| // // |
| // P U B L I C F U N C T I O N S // |
| // // |
| //=========================================================================// |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiInitialize() |
| // |
| // Description: add and initialize new instance of EPL stack. |
| // After return from this function the application must start |
| // the NMT state machine via |
| // EplApiExecNmtCommand(kEplNmtEventSwReset) |
| // and thereby the whole EPL stack :-) |
| // |
| // Parameters: pInitParam_p = initialisation parameters |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| tEplObdInitParam ObdInitParam; |
| tEplDllkInitParam DllkInitParam; |
| #ifndef EPL_NO_FIFO |
| tShbError ShbError; |
| #endif |
| |
| // reset instance structure |
| EPL_MEMSET(&EplApiInstance_g, 0, sizeof(EplApiInstance_g)); |
| |
| EPL_MEMCPY(&EplApiInstance_g.m_InitParam, pInitParam_p, |
| min(sizeof(tEplApiInitParam), |
| pInitParam_p->m_uiSizeOfStruct)); |
| |
| // check event callback function pointer |
| if (EplApiInstance_g.m_InitParam.m_pfnCbEvent == NULL) { // application must always have an event callback function |
| Ret = kEplApiInvalidParam; |
| goto Exit; |
| } |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) |
| // init OD |
| // FIXME |
| // Ret = EplObdInitRam(&ObdInitParam); |
| // if (Ret != kEplSuccessful) |
| // { |
| // goto Exit; |
| // } |
| |
| // initialize EplObd module |
| Ret = EplObdInit(&ObdInitParam); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| #ifndef EPL_NO_FIFO |
| ShbError = ShbInit(); |
| if (ShbError != kShbOk) { |
| Ret = kEplNoResource; |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplEventk module |
| Ret = EplEventkInit(EplApiInstance_g.m_InitParam.m_pfnCbSync); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplEventu module |
| Ret = EplEventuInit(EplApiProcessEvent); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // init EplTimerk module |
| Ret = EplTimerkInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplNmtk module before DLL |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) |
| Ret = EplNmtkInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplDllk module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) |
| EPL_MEMCPY(DllkInitParam.m_be_abSrcMac, |
| EplApiInstance_g.m_InitParam.m_abMacAddress, 6); |
| Ret = EplDllkAddInstance(&DllkInitParam); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplErrorHandlerk module |
| Ret = EplErrorHandlerkInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplDllkCal module |
| Ret = EplDllkCalAddInstance(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplDlluCal module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) |
| Ret = EplDlluCalAddInstance(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplPdok module |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) |
| Ret = EplPdokAddInstance(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| Ret = EplPdokCalAddInstance(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplNmtCnu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) |
| Ret = EplNmtCnuAddInstance(EplApiInstance_g.m_InitParam.m_uiNodeId); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplNmtu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = EplNmtuInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // register NMT event callback function |
| Ret = EplNmtuRegisterStateChangeCb(EplApiCbNmtStateChange); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // initialize EplNmtMnu module |
| Ret = EplNmtMnuInit(EplApiCbNodeEvent, EplApiCbBootEvent); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplIdentu module |
| Ret = EplIdentuInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // initialize EplStatusu module |
| Ret = EplStatusuInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // initialize EplLedu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) |
| Ret = EplLeduInit(EplApiCbLedStateChange); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // init SDO module |
| #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \ |
| (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)) |
| // init sdo command layer |
| Ret = EplSdoComInit(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // the application must start NMT state machine |
| // via EplApiExecNmtCommand(kEplNmtEventSwReset) |
| // and thereby the whole EPL stack |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiShutdown() |
| // |
| // Description: deletes an instance of EPL stack |
| // |
| // Parameters: (none) |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiShutdown(void) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| // $$$ d.k.: check if NMT state is NMT_GS_OFF |
| |
| // $$$ d.k.: maybe delete event queues at first, but this implies that |
| // no other module must not use the event queues for communication |
| // during shutdown. |
| |
| // delete instance for all modules |
| |
| // deinitialize EplSdoCom module |
| #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \ |
| (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)) |
| Ret = EplSdoComDelInstance(); |
| // PRINTF1("EplSdoComDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplLedu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) |
| Ret = EplLeduDelInstance(); |
| // PRINTF1("EplLeduDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // deinitialize EplNmtMnu module |
| Ret = EplNmtMnuDelInstance(); |
| // PRINTF1("EplNmtMnuDelInstance(): 0x%X\n", Ret); |
| |
| // deinitialize EplIdentu module |
| Ret = EplIdentuDelInstance(); |
| // PRINTF1("EplIdentuDelInstance(): 0x%X\n", Ret); |
| |
| // deinitialize EplStatusu module |
| Ret = EplStatusuDelInstance(); |
| // PRINTF1("EplStatusuDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplNmtCnu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) |
| Ret = EplNmtCnuDelInstance(); |
| // PRINTF1("EplNmtCnuDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplNmtu module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = EplNmtuDelInstance(); |
| // PRINTF1("EplNmtuDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplDlluCal module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) |
| Ret = EplDlluCalDelInstance(); |
| // PRINTF1("EplDlluCalDelInstance(): 0x%X\n", Ret); |
| |
| #endif |
| |
| // deinitialize EplEventu module |
| Ret = EplEventuDelInstance(); |
| // PRINTF1("EplEventuDelInstance(): 0x%X\n", Ret); |
| |
| // deinitialize EplNmtk module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) |
| Ret = EplNmtkDelInstance(); |
| // PRINTF1("EplNmtkDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplDllk module |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) |
| Ret = EplDllkDelInstance(); |
| // PRINTF1("EplDllkDelInstance(): 0x%X\n", Ret); |
| |
| // deinitialize EplDllkCal module |
| Ret = EplDllkCalDelInstance(); |
| // PRINTF1("EplDllkCalDelInstance(): 0x%X\n", Ret); |
| #endif |
| |
| // deinitialize EplEventk module |
| Ret = EplEventkDelInstance(); |
| // PRINTF1("EplEventkDelInstance(): 0x%X\n", Ret); |
| |
| // deinitialize EplTimerk module |
| Ret = EplTimerkDelInstance(); |
| // PRINTF1("EplTimerkDelInstance(): 0x%X\n", Ret); |
| |
| #ifndef EPL_NO_FIFO |
| ShbExit(); |
| #endif |
| |
| return Ret; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // Function: EplApiExecNmtCommand() |
| // |
| // Description: executes a NMT command, i.e. post the NMT command/event to the |
| // NMTk module. NMT commands which are not appropriate in the current |
| // NMT state are silently ignored. Please keep in mind that the |
| // NMT state may change until the NMT command is actually executed. |
| // |
| // Parameters: NmtEvent_p = NMT command/event |
| // |
| // Returns: tEplKernel = error code |
| // |
| // State: |
| //---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = EplNmtuNmtEvent(NmtEvent_p); |
| #endif |
| |
| return Ret; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // Function: EplApiLinkObject() |
| // |
| // Description: Function maps array of application variables onto specified object in OD |
| // |
| // Parameters: uiObjIndex_p = Function maps variables for this object index |
| // pVar_p = Pointer to data memory area for the specified object |
| // puiVarEntries_p = IN: pointer to number of entries to map |
| // OUT: pointer to number of actually used entries |
| // pEntrySize_p = IN: pointer to size of one entry; |
| // if size is zero, the actual size will be read from OD |
| // OUT: pointer to entire size of all entries mapped |
| // uiFirstSubindex_p = This is the first subindex to be mapped. |
| // |
| // Returns: tEplKernel = error code |
| // |
| // State: |
| //---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, |
| void *pVar_p, |
| unsigned int *puiVarEntries_p, |
| tEplObdSize * pEntrySize_p, |
| unsigned int uiFirstSubindex_p) |
| { |
| BYTE bVarEntries; |
| BYTE bIndexEntries; |
| BYTE MEM *pbData; |
| unsigned int uiSubindex; |
| tEplVarParam VarParam; |
| tEplObdSize EntrySize; |
| tEplObdSize UsedSize; |
| |
| tEplKernel RetCode = kEplSuccessful; |
| |
| if ((pVar_p == NULL) |
| || (puiVarEntries_p == NULL) |
| || (*puiVarEntries_p == 0) |
| || (pEntrySize_p == NULL)) { |
| RetCode = kEplApiInvalidParam; |
| goto Exit; |
| } |
| |
| pbData = (BYTE MEM *) pVar_p; |
| bVarEntries = (BYTE) * puiVarEntries_p; |
| UsedSize = 0; |
| |
| // init VarParam structure with default values |
| VarParam.m_uiIndex = uiObjIndex_p; |
| VarParam.m_ValidFlag = kVarValidAll; |
| |
| if (uiFirstSubindex_p != 0) { // check if object exists by reading subindex 0x00, |
| // because user wants to link a variable to a subindex unequal 0x00 |
| // read number of entries |
| EntrySize = (tEplObdSize) sizeof(bIndexEntries); |
| RetCode = EplObdReadEntry(uiObjIndex_p, |
| 0x00, |
| (void GENERIC *)&bIndexEntries, |
| &EntrySize); |
| |
| if ((RetCode != kEplSuccessful) || (bIndexEntries == 0x00)) { |
| // Object doesn't exist or invalid entry number |
| RetCode = kEplObdIndexNotExist; |
| goto Exit; |
| } |
| } else { // user wants to link a variable to subindex 0x00 |
| // that's OK |
| bIndexEntries = 0; |
| } |
| |
| // Correct number of entries if number read from OD is greater |
| // than the specified number. |
| // This is done, so that we do not set more entries than subindexes the |
| // object actually has. |
| if ((bIndexEntries > (bVarEntries + uiFirstSubindex_p - 1)) && |
| (bVarEntries != 0x00)) { |
| bIndexEntries = (BYTE) (bVarEntries + uiFirstSubindex_p - 1); |
| } |
| // map entries |
| for (uiSubindex = uiFirstSubindex_p; uiSubindex <= bIndexEntries; |
| uiSubindex++) { |
| // if passed entry size is 0, then get size from OD |
| if (*pEntrySize_p == 0x00) { |
| // read entry size |
| EntrySize = EplObdGetDataSize(uiObjIndex_p, uiSubindex); |
| |
| if (EntrySize == 0x00) { |
| // invalid entry size (maybe object doesn't exist or entry of type DOMAIN is empty) |
| RetCode = kEplObdSubindexNotExist; |
| break; |
| } |
| } else { // use passed entry size |
| EntrySize = *pEntrySize_p; |
| } |
| |
| VarParam.m_uiSubindex = uiSubindex; |
| |
| // set pointer to user var |
| VarParam.m_Size = EntrySize; |
| VarParam.m_pData = pbData; |
| |
| UsedSize += EntrySize; |
| pbData += EntrySize; |
| |
| RetCode = EplObdDefineVar(&VarParam); |
| if (RetCode != kEplSuccessful) { |
| break; |
| } |
| } |
| |
| // set number of mapped entries and entry size |
| *puiVarEntries_p = ((bIndexEntries - uiFirstSubindex_p) + 1); |
| *pEntrySize_p = UsedSize; |
| |
| Exit: |
| |
| return (RetCode); |
| |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiReadObject() |
| // |
| // Description: reads the specified entry from the OD of the specified node. |
| // If this node is a remote node, it performs a SDO transfer, which |
| // means this function returns kEplApiTaskDeferred and the application |
| // is informed via the event callback function when the task is completed. |
| // |
| // Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access) |
| // uiNodeId_p = IN: node ID (0 = itself) |
| // uiIndex_p = IN: index of object in OD |
| // uiSubindex_p = IN: sub-index of object in OD |
| // pDstData_le_p = OUT: pointer to data in little endian |
| // puiSize_p = INOUT: pointer to size of data |
| // SdoType_p = IN: type of SDO transfer |
| // pUserArg_p = IN: user-definable argument pointer, |
| // which will be passed to the event callback function |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p, |
| unsigned int uiNodeId_p, |
| unsigned int uiIndex_p, |
| unsigned int uiSubindex_p, |
| void *pDstData_le_p, |
| unsigned int *puiSize_p, |
| tEplSdoType SdoType_p, void *pUserArg_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| if ((uiIndex_p == 0) || (pDstData_le_p == NULL) || (puiSize_p == NULL) |
| || (*puiSize_p == 0)) { |
| Ret = kEplApiInvalidParam; |
| goto Exit; |
| } |
| |
| if (uiNodeId_p == 0 || uiNodeId_p == EplObdGetNodeId()) { // local OD access can be performed |
| tEplObdSize ObdSize; |
| |
| ObdSize = (tEplObdSize) * puiSize_p; |
| Ret = |
| EplObdReadEntryToLe(uiIndex_p, uiSubindex_p, pDstData_le_p, |
| &ObdSize); |
| *puiSize_p = (unsigned int)ObdSize; |
| } else { // perform SDO transfer |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplSdoComTransParamByIndex TransParamByIndex; |
| // tEplSdoComConHdl SdoComConHdl; |
| |
| // check if application provides space for handle |
| if (pSdoComConHdl_p == NULL) { |
| Ret = kEplApiInvalidParam; |
| goto Exit; |
| // pSdoComConHdl_p = &SdoComConHdl; |
| } |
| // init command layer connection |
| Ret = EplSdoComDefineCon(pSdoComConHdl_p, uiNodeId_p, // target node id |
| SdoType_p); // SDO type |
| if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) { |
| goto Exit; |
| } |
| TransParamByIndex.m_pData = pDstData_le_p; |
| TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeRead; |
| TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p; |
| TransParamByIndex.m_uiDataSize = *puiSize_p; |
| TransParamByIndex.m_uiIndex = uiIndex_p; |
| TransParamByIndex.m_uiSubindex = uiSubindex_p; |
| TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon; |
| TransParamByIndex.m_pUserArg = pUserArg_p; |
| |
| Ret = EplSdoComInitTransferByIndex(&TransParamByIndex); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| Ret = kEplApiTaskDeferred; |
| |
| #else |
| Ret = kEplApiInvalidParam; |
| #endif |
| } |
| |
| Exit: |
| return Ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiWriteObject() |
| // |
| // Description: writes the specified entry to the OD of the specified node. |
| // If this node is a remote node, it performs a SDO transfer, which |
| // means this function returns kEplApiTaskDeferred and the application |
| // is informed via the event callback function when the task is completed. |
| // |
| // Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access) |
| // uiNodeId_p = IN: node ID (0 = itself) |
| // uiIndex_p = IN: index of object in OD |
| // uiSubindex_p = IN: sub-index of object in OD |
| // pSrcData_le_p = IN: pointer to data in little endian |
| // uiSize_p = IN: size of data in bytes |
| // SdoType_p = IN: type of SDO transfer |
| // pUserArg_p = IN: user-definable argument pointer, |
| // which will be passed to the event callback function |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p, |
| unsigned int uiNodeId_p, |
| unsigned int uiIndex_p, |
| unsigned int uiSubindex_p, |
| void *pSrcData_le_p, |
| unsigned int uiSize_p, |
| tEplSdoType SdoType_p, void *pUserArg_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| if ((uiIndex_p == 0) || (pSrcData_le_p == NULL) || (uiSize_p == 0)) { |
| Ret = kEplApiInvalidParam; |
| goto Exit; |
| } |
| |
| if (uiNodeId_p == 0 || uiNodeId_p == EplObdGetNodeId()) { // local OD access can be performed |
| |
| Ret = |
| EplObdWriteEntryFromLe(uiIndex_p, uiSubindex_p, |
| pSrcData_le_p, uiSize_p); |
| } else { // perform SDO transfer |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplSdoComTransParamByIndex TransParamByIndex; |
| // tEplSdoComConHdl SdoComConHdl; |
| |
| // check if application provides space for handle |
| if (pSdoComConHdl_p == NULL) { |
| Ret = kEplApiInvalidParam; |
| goto Exit; |
| // pSdoComConHdl_p = &SdoComConHdl; |
| } |
| // d.k.: How to recycle command layer connection? |
| // Try to redefine it, which will return kEplSdoComHandleExists |
| // and the existing command layer handle. |
| // If the returned handle is busy, EplSdoComInitTransferByIndex() |
| // will return with error. |
| // $$$ d.k.: Collisions may occur with Configuration Manager, if both the application and |
| // Configuration Manager, are trying to communicate with the very same node. |
| // possible solution: disallow communication by application if Configuration Manager is busy |
| |
| // init command layer connection |
| Ret = EplSdoComDefineCon(pSdoComConHdl_p, uiNodeId_p, // target node id |
| SdoType_p); // SDO type |
| if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) { |
| goto Exit; |
| } |
| TransParamByIndex.m_pData = pSrcData_le_p; |
| TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeWrite; |
| TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p; |
| TransParamByIndex.m_uiDataSize = uiSize_p; |
| TransParamByIndex.m_uiIndex = uiIndex_p; |
| TransParamByIndex.m_uiSubindex = uiSubindex_p; |
| TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon; |
| TransParamByIndex.m_pUserArg = pUserArg_p; |
| |
| Ret = EplSdoComInitTransferByIndex(&TransParamByIndex); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| Ret = kEplApiTaskDeferred; |
| |
| #else |
| Ret = kEplApiInvalidParam; |
| #endif |
| } |
| |
| Exit: |
| return Ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiFreeSdoChannel() |
| // |
| // Description: frees the specified SDO channel. |
| // This function must be called after each call to EplApiReadObject()/EplApiWriteObject() |
| // which returns kEplApiTaskDeferred and the application |
| // is informed via the event callback function when the task is completed. |
| // |
| // Parameters: SdoComConHdl_p = IN: SDO connection handle |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| |
| // init command layer connection |
| Ret = EplSdoComUndefineCon(SdoComConHdl_p); |
| |
| #else |
| Ret = kEplApiInvalidParam; |
| #endif |
| |
| return Ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiReadLocalObject() |
| // |
| // Description: reads the specified entry from the local OD. |
| // |
| // Parameters: uiIndex_p = IN: index of object in OD |
| // uiSubindex_p = IN: sub-index of object in OD |
| // pDstData_p = OUT: pointer to data in platform byte order |
| // puiSize_p = INOUT: pointer to size of data |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p, |
| unsigned int uiSubindex_p, |
| void *pDstData_p, |
| unsigned int *puiSize_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| tEplObdSize ObdSize; |
| |
| ObdSize = (tEplObdSize) * puiSize_p; |
| Ret = EplObdReadEntry(uiIndex_p, uiSubindex_p, pDstData_p, &ObdSize); |
| *puiSize_p = (unsigned int)ObdSize; |
| |
| return Ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiWriteLocalObject() |
| // |
| // Description: writes the specified entry to the local OD. |
| // |
| // Parameters: uiIndex_p = IN: index of object in OD |
| // uiSubindex_p = IN: sub-index of object in OD |
| // pSrcData_p = IN: pointer to data in platform byte order |
| // uiSize_p = IN: size of data in bytes |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p, |
| unsigned int uiSubindex_p, |
| void *pSrcData_p, |
| unsigned int uiSize_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| Ret = |
| EplObdWriteEntry(uiIndex_p, uiSubindex_p, pSrcData_p, |
| (tEplObdSize) uiSize_p); |
| |
| return Ret; |
| } |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // ---------------------------------------------------------------------------- |
| // |
| // Function: EplApiMnTriggerStateChange() |
| // |
| // Description: triggers the specified node command for the specified node. |
| // |
| // Parameters: uiNodeId_p = node ID for which the node command will be executed |
| // NodeCommand_p = node command |
| // |
| // Return: tEplKernel = error code |
| // |
| // ---------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, |
| tEplNmtNodeCommand NodeCommand_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| Ret = EplNmtMnuTriggerStateChange(uiNodeId_p, NodeCommand_p); |
| |
| return Ret; |
| } |
| |
| #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbObdAccess |
| // |
| // Description: callback function for OD accesses |
| // |
| // Parameters: pParam_p = OBD parameter |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| |
| #if (EPL_API_OBD_FORWARD_EVENT != FALSE) |
| tEplApiEventArg EventArg; |
| |
| // call user callback |
| // must be disabled for EplApiLinuxKernel.c, because of reentrancy problem |
| // for local OD access. This is not so bad as user callback function in |
| // application does not use OD callbacks at the moment. |
| EventArg.m_ObdCbParam = *pParam_p; |
| Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventObdAccess, |
| &EventArg, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| #endif |
| |
| switch (pParam_p->m_uiIndex) { |
| //case 0x1006: // NMT_CycleLen_U32 (valid on reset) |
| case 0x1C14: // DLL_LossOfFrameTolerance_U32 |
| //case 0x1F98: // NMT_CycleTiming_REC (valid on reset) |
| { |
| if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) { |
| // update DLL configuration |
| Ret = EplApiUpdateDllConfig(FALSE); |
| } |
| break; |
| } |
| |
| case 0x1020: // CFM_VerifyConfiguration_REC.ConfId_U32 != 0 |
| { |
| if ((pParam_p->m_ObdEvent == kEplObdEvPostWrite) |
| && (pParam_p->m_uiSubIndex == 3) |
| && (*((DWORD *) pParam_p->m_pArg) != 0)) { |
| DWORD dwVerifyConfInvalid = 0; |
| // set CFM_VerifyConfiguration_REC.VerifyConfInvalid_U32 to 0 |
| Ret = |
| EplObdWriteEntry(0x1020, 4, |
| &dwVerifyConfInvalid, 4); |
| // ignore any error because this objekt is optional |
| Ret = kEplSuccessful; |
| } |
| break; |
| } |
| |
| case 0x1F9E: // NMT_ResetCmd_U8 |
| { |
| if (pParam_p->m_ObdEvent == kEplObdEvPreWrite) { |
| BYTE bNmtCommand; |
| |
| bNmtCommand = *((BYTE *) pParam_p->m_pArg); |
| // check value range |
| switch ((tEplNmtCommand) bNmtCommand) { |
| case kEplNmtCmdResetNode: |
| case kEplNmtCmdResetCommunication: |
| case kEplNmtCmdResetConfiguration: |
| case kEplNmtCmdSwReset: |
| case kEplNmtCmdInvalidService: |
| // valid command identifier specified |
| break; |
| |
| default: |
| pParam_p->m_dwAbortCode = |
| EPL_SDOAC_VALUE_RANGE_EXCEEDED; |
| Ret = kEplObdAccessViolation; |
| break; |
| } |
| } else if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) { |
| BYTE bNmtCommand; |
| |
| bNmtCommand = *((BYTE *) pParam_p->m_pArg); |
| // check value range |
| switch ((tEplNmtCommand) bNmtCommand) { |
| case kEplNmtCmdResetNode: |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = |
| EplNmtuNmtEvent |
| (kEplNmtEventResetNode); |
| #endif |
| break; |
| |
| case kEplNmtCmdResetCommunication: |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = |
| EplNmtuNmtEvent |
| (kEplNmtEventResetCom); |
| #endif |
| break; |
| |
| case kEplNmtCmdResetConfiguration: |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = |
| EplNmtuNmtEvent |
| (kEplNmtEventResetConfig); |
| #endif |
| break; |
| |
| case kEplNmtCmdSwReset: |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) |
| Ret = |
| EplNmtuNmtEvent |
| (kEplNmtEventSwReset); |
| #endif |
| break; |
| |
| case kEplNmtCmdInvalidService: |
| break; |
| |
| default: |
| pParam_p->m_dwAbortCode = |
| EPL_SDOAC_VALUE_RANGE_EXCEEDED; |
| Ret = kEplObdAccessViolation; |
| break; |
| } |
| } |
| break; |
| } |
| |
| default: |
| break; |
| } |
| |
| //Exit: |
| return Ret; |
| } |
| |
| //=========================================================================// |
| // // |
| // P R I V A T E F U N C T I O N S // |
| // // |
| //=========================================================================// |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiProcessEvent |
| // |
| // Description: processes events from event queue and forwards these to |
| // the application's event callback function |
| // |
| // Parameters: pEplEvent_p = pointer to event |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p) |
| { |
| tEplKernel Ret; |
| tEplEventError *pEventError; |
| tEplApiEventType EventType; |
| |
| Ret = kEplSuccessful; |
| |
| // process event |
| switch (pEplEvent_p->m_EventType) { |
| // error event |
| case kEplEventTypeError: |
| { |
| pEventError = (tEplEventError *) pEplEvent_p->m_pArg; |
| switch (pEventError->m_EventSource) { |
| // treat the errors from the following sources as critical |
| case kEplEventSourceEventk: |
| case kEplEventSourceEventu: |
| case kEplEventSourceDllk: |
| { |
| EventType = kEplApiEventCriticalError; |
| // halt the stack by entering NMT state Off |
| Ret = |
| EplNmtuNmtEvent |
| (kEplNmtEventCriticalError); |
| break; |
| } |
| |
| // the other errors are just warnings |
| default: |
| { |
| EventType = kEplApiEventWarning; |
| break; |
| } |
| } |
| |
| // call user callback |
| Ret = |
| EplApiInstance_g.m_InitParam.m_pfnCbEvent(EventType, |
| (tEplApiEventArg |
| *) |
| pEventError, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| // discard error from callback function, because this could generate an endless loop |
| Ret = kEplSuccessful; |
| break; |
| } |
| |
| // at present, there are no other events for this module |
| default: |
| break; |
| } |
| |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbNmtStateChange |
| // |
| // Description: callback function for NMT state changes |
| // |
| // Parameters: NmtStateChange_p = NMT state change event |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange |
| NmtStateChange_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| BYTE bNmtState; |
| tEplApiEventArg EventArg; |
| |
| // save NMT state in OD |
| bNmtState = (BYTE) NmtStateChange_p.m_NewNmtState; |
| Ret = EplObdWriteEntry(0x1F8C, 0, &bNmtState, 1); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // do work which must be done in that state |
| switch (NmtStateChange_p.m_NewNmtState) { |
| // EPL stack is not running |
| case kEplNmtGsOff: |
| break; |
| |
| // first init of the hardware |
| case kEplNmtGsInitialising: |
| #if 0 |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) |
| // configure SDO via UDP (i.e. bind it to the EPL ethernet interface) |
| Ret = |
| EplSdoUdpuConfig(EplApiInstance_g.m_InitParam.m_dwIpAddress, |
| EPL_C_SDO_EPL_PORT); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| #endif |
| |
| break; |
| |
| // init of the manufacturer-specific profile area and the |
| // standardised device profile area |
| case kEplNmtGsResetApplication: |
| { |
| // reset application part of OD |
| Ret = EplObdAccessOdPart(kEplObdPartApp, |
| kEplObdDirLoad); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| break; |
| } |
| |
| // init of the communication profile area |
| case kEplNmtGsResetCommunication: |
| { |
| // reset communication part of OD |
| Ret = EplObdAccessOdPart(kEplObdPartGen, |
| kEplObdDirLoad); |
| |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // $$$ d.k.: update OD only if OD was not loaded from non-volatile memory |
| Ret = EplApiUpdateObd(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| break; |
| } |
| |
| // build the configuration with infos from OD |
| case kEplNmtGsResetConfiguration: |
| { |
| |
| Ret = EplApiUpdateDllConfig(TRUE); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| break; |
| } |
| |
| //----------------------------------------------------------- |
| // CN part of the state machine |
| |
| // node liste for EPL-Frames and check timeout |
| case kEplNmtCsNotActive: |
| { |
| // indicate completion of reset in NMT_ResetCmd_U8 |
| bNmtState = (BYTE) kEplNmtCmdInvalidService; |
| Ret = EplObdWriteEntry(0x1F9E, 0, &bNmtState, 1); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| break; |
| } |
| |
| // node process only async frames |
| case kEplNmtCsPreOperational1: |
| { |
| break; |
| } |
| |
| // node process isochronus and asynchronus frames |
| case kEplNmtCsPreOperational2: |
| { |
| break; |
| } |
| |
| // node should be configured und application is ready |
| case kEplNmtCsReadyToOperate: |
| { |
| break; |
| } |
| |
| // normal work state |
| case kEplNmtCsOperational: |
| { |
| break; |
| } |
| |
| // node stopped by MN |
| // -> only process asynchronus frames |
| case kEplNmtCsStopped: |
| { |
| break; |
| } |
| |
| // no EPL cycle |
| // -> normal ethernet communication |
| case kEplNmtCsBasicEthernet: |
| { |
| break; |
| } |
| |
| //----------------------------------------------------------- |
| // MN part of the state machine |
| |
| // node listens for EPL-Frames and check timeout |
| case kEplNmtMsNotActive: |
| { |
| break; |
| } |
| |
| // node processes only async frames |
| case kEplNmtMsPreOperational1: |
| { |
| break; |
| } |
| |
| // node processes isochronous and asynchronous frames |
| case kEplNmtMsPreOperational2: |
| { |
| break; |
| } |
| |
| // node should be configured und application is ready |
| case kEplNmtMsReadyToOperate: |
| { |
| break; |
| } |
| |
| // normal work state |
| case kEplNmtMsOperational: |
| { |
| break; |
| } |
| |
| // no EPL cycle |
| // -> normal ethernet communication |
| case kEplNmtMsBasicEthernet: |
| { |
| break; |
| } |
| |
| default: |
| { |
| TRACE0 |
| ("EplApiCbNmtStateChange(): unhandled NMT state\n"); |
| } |
| } |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) |
| // forward event to Led module |
| Ret = EplLeduCbNmtStateChange(NmtStateChange_p); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // forward event to NmtMn module |
| Ret = EplNmtMnuCbNmtStateChange(NmtStateChange_p); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #endif |
| |
| // call user callback |
| EventArg.m_NmtStateChange = NmtStateChange_p; |
| Ret = |
| EplApiInstance_g.m_InitParam. |
| m_pfnCbEvent(kEplApiEventNmtStateChange, &EventArg, |
| EplApiInstance_g.m_InitParam.m_pEventUserArg); |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiUpdateDllConfig |
| // |
| // Description: update configuration of DLL |
| // |
| // Parameters: fUpdateIdentity_p = TRUE, if identity must be updated |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| tEplDllConfigParam DllConfigParam; |
| tEplDllIdentParam DllIdentParam; |
| tEplObdSize ObdSize; |
| WORD wTemp; |
| BYTE bTemp; |
| |
| // configure Dll |
| EPL_MEMSET(&DllConfigParam, 0, sizeof(DllConfigParam)); |
| DllConfigParam.m_uiNodeId = EplObdGetNodeId(); |
| |
| // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1006, 0, &DllConfigParam.m_dwCycleLen, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // 0x1F82: NMT_FeatureFlags_U32 |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1F82, 0, &DllConfigParam.m_dwFeatureFlags, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // d.k. There is no dependance between FeatureFlags and async-only CN |
| DllConfigParam.m_fAsyncOnly = EplApiInstance_g.m_InitParam.m_fAsyncOnly; |
| |
| // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1C14, 0, &DllConfigParam.m_dwLossOfFrameTolerance, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // 0x1F98: NMT_CycleTiming_REC |
| // 0x1F98.1: IsochrTxMaxPayload_U16 |
| ObdSize = 2; |
| Ret = EplObdReadEntry(0x1F98, 1, &wTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiIsochrTxMaxPayload = wTemp; |
| |
| // 0x1F98.2: IsochrRxMaxPayload_U16 |
| ObdSize = 2; |
| Ret = EplObdReadEntry(0x1F98, 2, &wTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiIsochrRxMaxPayload = wTemp; |
| |
| // 0x1F98.3: PResMaxLatency_U32 |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1F98, 3, &DllConfigParam.m_dwPresMaxLatency, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // 0x1F98.4: PReqActPayloadLimit_U16 |
| ObdSize = 2; |
| Ret = EplObdReadEntry(0x1F98, 4, &wTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiPreqActPayloadLimit = wTemp; |
| |
| // 0x1F98.5: PResActPayloadLimit_U16 |
| ObdSize = 2; |
| Ret = EplObdReadEntry(0x1F98, 5, &wTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiPresActPayloadLimit = wTemp; |
| |
| // 0x1F98.6: ASndMaxLatency_U32 |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1F98, 6, &DllConfigParam.m_dwAsndMaxLatency, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // 0x1F98.7: MultiplCycleCnt_U8 |
| ObdSize = 1; |
| Ret = EplObdReadEntry(0x1F98, 7, &bTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiMultiplCycleCnt = bTemp; |
| |
| // 0x1F98.8: AsyncMTU_U16 |
| ObdSize = 2; |
| Ret = EplObdReadEntry(0x1F98, 8, &wTemp, &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| DllConfigParam.m_uiAsyncMtu = wTemp; |
| |
| // $$$ Prescaler |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| // 0x1F8A.1: WaitSoCPReq_U32 in [ns] |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1F8A, 1, &DllConfigParam.m_dwWaitSocPreq, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] (optional) |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1F8A, 2, &DllConfigParam.m_dwAsyncSlotTimeout, |
| &ObdSize); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| #endif |
| |
| DllConfigParam.m_uiSizeOfStruct = sizeof(DllConfigParam); |
| Ret = EplDllkConfig(&DllConfigParam); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| if (fUpdateIdentity_p != FALSE) { |
| // configure Identity |
| EPL_MEMSET(&DllIdentParam, 0, sizeof(DllIdentParam)); |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1000, 0, &DllIdentParam.m_dwDeviceType, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1018, 1, &DllIdentParam.m_dwVendorId, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1018, 2, &DllIdentParam.m_dwProductCode, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1018, 3, |
| &DllIdentParam.m_dwRevisionNumber, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1018, 4, &DllIdentParam.m_dwSerialNumber, |
| &ObdSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| DllIdentParam.m_dwIpAddress = |
| EplApiInstance_g.m_InitParam.m_dwIpAddress; |
| DllIdentParam.m_dwSubnetMask = |
| EplApiInstance_g.m_InitParam.m_dwSubnetMask; |
| EPL_MEMCPY(DllIdentParam.m_sHostname, |
| EplApiInstance_g.m_InitParam.m_sHostname, |
| sizeof(DllIdentParam.m_sHostname)); |
| |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1020, 1, |
| &DllIdentParam.m_dwVerifyConfigurationDate, |
| &ObdSize); |
| // ignore any error, because this object is optional |
| |
| ObdSize = 4; |
| Ret = |
| EplObdReadEntry(0x1020, 2, |
| &DllIdentParam.m_dwVerifyConfigurationTime, |
| &ObdSize); |
| // ignore any error, because this object is optional |
| |
| // $$$ d.k.: fill rest of ident structure |
| |
| DllIdentParam.m_uiSizeOfStruct = sizeof(DllIdentParam); |
| Ret = EplDllkSetIdentity(&DllIdentParam); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| } |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiUpdateObd |
| // |
| // Description: update OD from init param |
| // |
| // Parameters: (none) |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiUpdateObd(void) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| WORD wTemp; |
| BYTE bTemp; |
| |
| // set node id in OD |
| Ret = EplObdSetNodeId(EplApiInstance_g.m_InitParam.m_uiNodeId, // node id |
| kEplObdNodeIdHardware); // set by hardware |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwCycleLen != -1) { |
| Ret = |
| EplObdWriteEntry(0x1006, 0, |
| &EplApiInstance_g.m_InitParam.m_dwCycleLen, |
| 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwLossOfFrameTolerance != -1) { |
| Ret = |
| EplObdWriteEntry(0x1C14, 0, |
| &EplApiInstance_g.m_InitParam. |
| m_dwLossOfFrameTolerance, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| } */ |
| } |
| // d.k. There is no dependance between FeatureFlags and async-only CN. |
| if (EplApiInstance_g.m_InitParam.m_dwFeatureFlags != -1) { |
| Ret = |
| EplObdWriteEntry(0x1F82, 0, |
| &EplApiInstance_g.m_InitParam. |
| m_dwFeatureFlags, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| } */ |
| } |
| |
| wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrTxMaxPayload; |
| Ret = EplObdWriteEntry(0x1F98, 1, &wTemp, 2); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| |
| wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrRxMaxPayload; |
| Ret = EplObdWriteEntry(0x1F98, 2, &wTemp, 2); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| |
| Ret = |
| EplObdWriteEntry(0x1F98, 3, |
| &EplApiInstance_g.m_InitParam.m_dwPresMaxLatency, |
| 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| |
| if (EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit <= |
| EPL_C_DLL_ISOCHR_MAX_PAYL) { |
| wTemp = |
| (WORD) EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit; |
| Ret = EplObdWriteEntry(0x1F98, 4, &wTemp, 2); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit <= |
| EPL_C_DLL_ISOCHR_MAX_PAYL) { |
| wTemp = |
| (WORD) EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit; |
| Ret = EplObdWriteEntry(0x1F98, 5, &wTemp, 2); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| Ret = |
| EplObdWriteEntry(0x1F98, 6, |
| &EplApiInstance_g.m_InitParam.m_dwAsndMaxLatency, |
| 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| |
| if (EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt <= 0xFF) { |
| bTemp = (BYTE) EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt; |
| Ret = EplObdWriteEntry(0x1F98, 7, &bTemp, 1); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_uiAsyncMtu <= |
| EPL_C_DLL_MAX_ASYNC_MTU) { |
| wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiAsyncMtu; |
| Ret = EplObdWriteEntry(0x1F98, 8, &wTemp, 2); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_uiPrescaler <= 1000) { |
| wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPrescaler; |
| Ret = EplObdWriteEntry(0x1F98, 9, &wTemp, 2); |
| // ignore return code |
| Ret = kEplSuccessful; |
| } |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| if (EplApiInstance_g.m_InitParam.m_dwWaitSocPreq != -1) { |
| Ret = |
| EplObdWriteEntry(0x1F8A, 1, |
| &EplApiInstance_g.m_InitParam. |
| m_dwWaitSocPreq, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| } */ |
| } |
| |
| if ((EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != 0) |
| && (EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != -1)) { |
| Ret = |
| EplObdWriteEntry(0x1F8A, 2, |
| &EplApiInstance_g.m_InitParam. |
| m_dwAsyncSlotTimeout, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| } */ |
| } |
| #endif |
| |
| // configure Identity |
| if (EplApiInstance_g.m_InitParam.m_dwDeviceType != -1) { |
| Ret = |
| EplObdWriteEntry(0x1000, 0, |
| &EplApiInstance_g.m_InitParam. |
| m_dwDeviceType, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwVendorId != -1) { |
| Ret = |
| EplObdWriteEntry(0x1018, 1, |
| &EplApiInstance_g.m_InitParam.m_dwVendorId, |
| 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwProductCode != -1) { |
| Ret = |
| EplObdWriteEntry(0x1018, 2, |
| &EplApiInstance_g.m_InitParam. |
| m_dwProductCode, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwRevisionNumber != -1) { |
| Ret = |
| EplObdWriteEntry(0x1018, 3, |
| &EplApiInstance_g.m_InitParam. |
| m_dwRevisionNumber, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_dwSerialNumber != -1) { |
| Ret = |
| EplObdWriteEntry(0x1018, 4, |
| &EplApiInstance_g.m_InitParam. |
| m_dwSerialNumber, 4); |
| /* if(Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_pszDevName != NULL) { |
| // write Device Name (0x1008) |
| Ret = |
| EplObdWriteEntry(0x1008, 0, |
| (void GENERIC *)EplApiInstance_g. |
| m_InitParam.m_pszDevName, |
| (tEplObdSize) strlen(EplApiInstance_g. |
| m_InitParam. |
| m_pszDevName)); |
| /* if (Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_pszHwVersion != NULL) { |
| // write Hardware version (0x1009) |
| Ret = |
| EplObdWriteEntry(0x1009, 0, |
| (void GENERIC *)EplApiInstance_g. |
| m_InitParam.m_pszHwVersion, |
| (tEplObdSize) strlen(EplApiInstance_g. |
| m_InitParam. |
| m_pszHwVersion)); |
| /* if (Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| if (EplApiInstance_g.m_InitParam.m_pszSwVersion != NULL) { |
| // write Software version (0x100A) |
| Ret = |
| EplObdWriteEntry(0x100A, 0, |
| (void GENERIC *)EplApiInstance_g. |
| m_InitParam.m_pszSwVersion, |
| (tEplObdSize) strlen(EplApiInstance_g. |
| m_InitParam. |
| m_pszSwVersion)); |
| /* if (Ret != kEplSuccessful) |
| { |
| goto Exit; |
| }*/ |
| } |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbSdoCon |
| // |
| // Description: callback function for SDO transfers |
| // |
| // Parameters: pSdoComFinished_p = SDO parameter |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p) |
| { |
| tEplKernel Ret; |
| tEplApiEventArg EventArg; |
| |
| Ret = kEplSuccessful; |
| |
| // call user callback |
| EventArg.m_Sdo = *pSdoComFinished_p; |
| Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventSdo, |
| &EventArg, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| |
| return Ret; |
| |
| } |
| #endif |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbNodeEvent |
| // |
| // Description: callback function for node events |
| // |
| // Parameters: uiNodeId_p = node ID of the CN |
| // NodeEvent_p = event from the specified CN |
| // NmtState_p = current NMT state of the CN |
| // wErrorCode_p = EPL error code if NodeEvent_p==kEplNmtNodeEventError |
| // fMandatory_p = flag if CN is mandatory |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, |
| tEplNmtNodeEvent NodeEvent_p, |
| tEplNmtState NmtState_p, |
| WORD wErrorCode_p, BOOL fMandatory_p) |
| { |
| tEplKernel Ret; |
| tEplApiEventArg EventArg; |
| |
| Ret = kEplSuccessful; |
| |
| // call user callback |
| EventArg.m_Node.m_uiNodeId = uiNodeId_p; |
| EventArg.m_Node.m_NodeEvent = NodeEvent_p; |
| EventArg.m_Node.m_NmtState = NmtState_p; |
| EventArg.m_Node.m_wErrorCode = wErrorCode_p; |
| EventArg.m_Node.m_fMandatory = fMandatory_p; |
| |
| Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventNode, |
| &EventArg, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| |
| return Ret; |
| |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbBootEvent |
| // |
| // Description: callback function for boot events |
| // |
| // Parameters: BootEvent_p = event from the boot-up process |
| // NmtState_p = current local NMT state |
| // wErrorCode_p = EPL error code if BootEvent_p==kEplNmtBootEventError |
| // |
| // Returns: tEplKernel = error code |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, |
| tEplNmtState NmtState_p, |
| WORD wErrorCode_p) |
| { |
| tEplKernel Ret; |
| tEplApiEventArg EventArg; |
| |
| Ret = kEplSuccessful; |
| |
| // call user callback |
| EventArg.m_Boot.m_BootEvent = BootEvent_p; |
| EventArg.m_Boot.m_NmtState = NmtState_p; |
| EventArg.m_Boot.m_wErrorCode = wErrorCode_p; |
| |
| Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventBoot, |
| &EventArg, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| |
| return Ret; |
| |
| } |
| |
| #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplApiCbLedStateChange |
| // |
| // Description: callback function for LED change events. |
| // |
| // Parameters: LedType_p = type of LED |
| // fOn_p = state of LED |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| |
| static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, |
| BOOL fOn_p) |
| { |
| tEplKernel Ret; |
| tEplApiEventArg EventArg; |
| |
| Ret = kEplSuccessful; |
| |
| // call user callback |
| EventArg.m_Led.m_LedType = LedType_p; |
| EventArg.m_Led.m_fOn = fOn_p; |
| |
| Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventLed, |
| &EventArg, |
| EplApiInstance_g. |
| m_InitParam. |
| m_pEventUserArg); |
| |
| return Ret; |
| |
| } |
| |
| #endif |
| |
| // EOF |