aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/epl/EplApiGeneric.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/epl/EplApiGeneric.c')
-rw-r--r--drivers/staging/epl/EplApiGeneric.c2060
1 files changed, 2060 insertions, 0 deletions
diff --git a/drivers/staging/epl/EplApiGeneric.c b/drivers/staging/epl/EplApiGeneric.c
new file mode 100644
index 000000000000..ae19e34cd7b3
--- /dev/null
+++ b/drivers/staging/epl/EplApiGeneric.c
@@ -0,0 +1,2060 @@
+/****************************************************************************
+
+ (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