tEplKernel PUBLIC AppCbEvent ( tEplApiEventType EventType_p, // IN: event type (enum) tEplApiEventArg* pEventArg_p, // IN: event argument (union) void GENERIC* pUserArg_p //__attribute((unused)) ) { tEplKernel EplRet = kEplSuccessful; UINT uiVarLen; UNUSED_PARAMETER(pUserArg_p); // check if NMT_GS_OFF is reached switch (EventType_p) { case kEplApiEventNmtStateChange: { switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) { case kEplNmtGsOff: { // NMT state machine was shut down, // because of user signal (CTRL-C) or critical EPL stack error // -> also shut down EplApiProcess() and main() EplRet = kEplShutdown; printlog("Event:kEplNmtGsOff originating event = 0x%X (%s)\n", pEventArg_p->m_NmtStateChange.m_NmtEvent, EplGetNmtEventStr(pEventArg_p->m_NmtStateChange.m_NmtEvent)); break; } case kEplNmtGsResetCommunication: { // continue } case kEplNmtGsResetConfiguration: { if (uiCycleLen_g != 0) { EplRet = EplApiWriteLocalObject(0x1006, 0x00, &uiCycleLen_g, sizeof (uiCycleLen_g)); uiCurCycleLen_g = uiCycleLen_g; } else { uiVarLen = sizeof(uiCurCycleLen_g); EplApiReadLocalObject(0x1006, 0x00, &uiCurCycleLen_g, &uiVarLen); } // continue } case kEplNmtMsPreOperational1: { printlog("AppCbEvent(0x%X) originating event = 0x%X (%s)\n", pEventArg_p->m_NmtStateChange.m_NewNmtState, pEventArg_p->m_NmtStateChange.m_NmtEvent, EplGetNmtEventStr(pEventArg_p->m_NmtStateChange.m_NmtEvent)); // continue } case kEplNmtGsInitialising: case kEplNmtGsResetApplication: case kEplNmtMsNotActive: case kEplNmtCsNotActive: case kEplNmtCsPreOperational1: { break; } case kEplNmtCsOperational: case kEplNmtMsOperational: { break; } default: { break; } } break; } case kEplApiEventCriticalError: case kEplApiEventWarning: { // error or warning occurred within the stack or the application // on error the API layer stops the NMT state machine printlog( "%s(Err/Warn): Source = %s (%02X) EplError = %s (0x%03X)\n", __func__, EplGetEventSourceStr(pEventArg_p->m_InternalError.m_EventSource), pEventArg_p->m_InternalError.m_EventSource, EplGetEplKernelStr(pEventArg_p->m_InternalError.m_EplError), pEventArg_p->m_InternalError.m_EplError ); FTRACE_MARKER("%s(Err/Warn): Source = %s (%02X) EplError = %s (0x%03X)\n", __func__, EplGetEventSourceStr(pEventArg_p->m_InternalError.m_EventSource), pEventArg_p->m_InternalError.m_EventSource, EplGetEplKernelStr(pEventArg_p->m_InternalError.m_EplError), pEventArg_p->m_InternalError.m_EplError ); // check additional argument switch (pEventArg_p->m_InternalError.m_EventSource) { case kEplEventSourceEventk: case kEplEventSourceEventu: { // error occurred within event processing // either in kernel or in user part printlog(" OrgSource = %s %02X\n", EplGetEventSourceStr(pEventArg_p->m_InternalError.m_Arg.m_EventSource), pEventArg_p->m_InternalError.m_Arg.m_EventSource); FTRACE_MARKER(" OrgSource = %s %02X\n", EplGetEventSourceStr(pEventArg_p->m_InternalError.m_Arg.m_EventSource), pEventArg_p->m_InternalError.m_Arg.m_EventSource); break; } case kEplEventSourceDllk: { // error occurred within the data link layer (e.g. interrupt processing) // the DWORD argument contains the DLL state and the NMT event printlog(" val = %X\n", pEventArg_p->m_InternalError.m_Arg.m_dwArg); FTRACE_MARKER(" val = %X\n", pEventArg_p->m_InternalError.m_Arg.m_dwArg); break; } default: { printlog("\n"); break; } } break; } case kEplApiEventHistoryEntry: { // new history entry printlog("%s(HistoryEntry): Type=0x%04X Code=0x%04X (0x%02X %02X %02X %02X %02X %02X %02X %02X)\n", __func__, pEventArg_p->m_ErrHistoryEntry.m_wEntryType, pEventArg_p->m_ErrHistoryEntry.m_wErrorCode, (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[0], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[1], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[2], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[3], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[4], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[5], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[6], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[7]); FTRACE_MARKER("%s(HistoryEntry): Type=0x%04X Code=0x%04X (0x%02X %02X %02X %02X %02X %02X %02X %02X)\n", __func__, pEventArg_p->m_ErrHistoryEntry.m_wEntryType, pEventArg_p->m_ErrHistoryEntry.m_wErrorCode, (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[0], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[1], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[2], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[3], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[4], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[5], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[6], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[7]); break; } case kEplApiEventPdoChange: { unsigned int uiSubIndex; QWORD qwMappObject; printlog("%s(%sPDO=0x%X to node 0x%X with %d objects %s)\n", __func__, (pEventArg_p->m_PdoChange.m_fTx ? "T" : "R"), pEventArg_p->m_PdoChange.m_uiPdoMappIndex, pEventArg_p->m_PdoChange.m_uiNodeId, pEventArg_p->m_PdoChange.m_uiMappObjectCount, (pEventArg_p->m_PdoChange.m_fActivated ? "activated" : "deleted")); for (uiSubIndex = 1; uiSubIndex <= pEventArg_p->m_PdoChange.m_uiMappObjectCount; uiSubIndex++) { uiVarLen = sizeof(qwMappObject); EplRet = EplApiReadLocalObject( pEventArg_p->m_PdoChange.m_uiPdoMappIndex, uiSubIndex, &qwMappObject, &uiVarLen); if (EplRet != kEplSuccessful) { printlog(" Reading 0x%X/%d failed with 0x%X\n", pEventArg_p->m_PdoChange.m_uiPdoMappIndex, uiSubIndex, EplRet); continue; } printlog(" %d. mapped object 0x%X/%d\n", uiSubIndex, qwMappObject & 0x00FFFFULL, (qwMappObject & 0xFF0000ULL) >> 16); } break; } #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) case kEplApiEventNode: { // check additional argument switch (pEventArg_p->m_Node.m_NodeEvent) { case kEplNmtNodeEventCheckConf: { printlog("%s(Node=0x%X, CheckConf)\n", __func__, pEventArg_p->m_Node.m_uiNodeId); break; } case kEplNmtNodeEventUpdateConf: { printlog("%s(Node=0x%X, UpdateConf)\n", __func__, pEventArg_p->m_Node.m_uiNodeId); break; } case kEplNmtNodeEventNmtState: { printlog("%s(Node=0x%X, NmtState=%s)\n", __func__, pEventArg_p->m_Node.m_uiNodeId, EplGetNmtStateStr(pEventArg_p->m_Node.m_NmtState)); break; } case kEplNmtNodeEventError: { printlog("%s (Node=0x%X): Error = %s (0x%.4X)\n", __func__, pEventArg_p->m_Node.m_uiNodeId, EplGetEmergErrCodeStr(pEventArg_p->m_Node.m_wErrorCode), pEventArg_p->m_Node.m_wErrorCode); break; } case kEplNmtNodeEventFound: { printlog("%s(Node=0x%X, Found)\n", __func__, pEventArg_p->m_Node.m_uiNodeId); break; } default: { break; } } break; } #endif #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFM)) != 0) case kEplApiEventCfmProgress: { printlog("%s(Node=0x%X, CFM-Progress: Object 0x%X/%u, ", __func__, pEventArg_p->m_CfmProgress.m_uiNodeId, pEventArg_p->m_CfmProgress.m_uiObjectIndex, pEventArg_p->m_CfmProgress.m_uiObjectSubIndex); printlog("%lu/%lu Bytes", (ULONG) pEventArg_p->m_CfmProgress.m_dwBytesDownloaded, (ULONG) pEventArg_p->m_CfmProgress.m_dwTotalNumberOfBytes); if ((pEventArg_p->m_CfmProgress.m_dwSdoAbortCode != 0) || (pEventArg_p->m_CfmProgress.m_EplError != kEplSuccessful)) { printlog(" -> SDO Abort=0x%lX, Error=0x%X)\n", (unsigned long) pEventArg_p->m_CfmProgress.m_dwSdoAbortCode, pEventArg_p->m_CfmProgress.m_EplError); } else { printlog(")\n"); } break; } case kEplApiEventCfmResult: { switch (pEventArg_p->m_CfmResult.m_NodeCommand) { case kEplNmtNodeCommandConfOk: { printlog("%s(Node=0x%X, ConfOk)\n", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfErr: { printlog("%s(Node=0x%X, ConfErr)\n", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfReset: { printlog("%s(Node=0x%X, ConfReset)\n", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfRestored: { printlog("%s(Node=0x%X, ConfRestored)\n", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } default: { printlog("%s(Node=0x%X, CfmResult=0x%X)\n", __func__, pEventArg_p->m_CfmResult.m_uiNodeId, pEventArg_p->m_CfmResult.m_NodeCommand); break; } } break; } #endif default: break; } return EplRet; }
static int EplLinIoctl(struct inode *pDeviceFile_p, // information about the device to open struct file *pInstance_p, // information about driver instance unsigned int uiIoctlCmd_p, // Ioctl command to execute unsigned long ulArg_p) // Ioctl command specific argument/parameter { tEplKernel EplRet; int iErr; int iRet; // TRACE1("EPL: + EplLinIoctl (uiIoctlCmd_p=%d)...\n", uiIoctlCmd_p); iRet = -EINVAL; switch (uiIoctlCmd_p) { // ---------------------------------------------------------- case EPLLIN_CMD_INITIALIZE: { tEplApiInitParam EplApiInitParam; iErr = copy_from_user(&EplApiInitParam, (const void *)ulArg_p, sizeof(EplApiInitParam)); if (iErr != 0) { iRet = -EIO; goto Exit; } EplApiInitParam.m_pfnCbEvent = EplLinCbEvent; EplApiInitParam.m_pfnCbSync = EplLinCbSync; EplRet = EplApiInitialize(&EplApiInitParam); uiEplState_g = EPL_STATE_RUNNING; iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_SHUTDOWN: { // shutdown the threads // pass control to sync kernel thread, but signal termination atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbSync_g); wake_up_interruptible(&WaitQueuePI_In_g); // pass control to event queue kernel thread atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbEvent_g); if (uiEplState_g == EPL_STATE_RUNNING) { // post NmtEventSwitchOff EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff); } iRet = 0; break; } // ---------------------------------------------------------- case EPLLIN_CMD_READ_LOCAL_OBJECT: { tEplLinLocalObject LocalObject; void *pData; iErr = copy_from_user(&LocalObject, (const void *)ulArg_p, sizeof(LocalObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0)) { iRet = (int)kEplApiInvalidParam; goto Exit; } pData = vmalloc(LocalObject.m_uiSize); if (pData == NULL) { // no memory available iRet = -ENOMEM; goto Exit; } EplRet = EplApiReadLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, &LocalObject.m_uiSize); if (EplRet == kEplSuccessful) { iErr = copy_to_user(LocalObject.m_pData, pData, LocalObject.m_uiSize); vfree(pData); if (iErr != 0) { iRet = -EIO; goto Exit; } // return actual size (LocalObject.m_uiSize) iErr = put_user(LocalObject.m_uiSize, (unsigned int *)(ulArg_p + (unsigned long) &LocalObject. m_uiSize - (unsigned long) &LocalObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } } else { vfree(pData); } iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_WRITE_LOCAL_OBJECT: { tEplLinLocalObject LocalObject; void *pData; iErr = copy_from_user(&LocalObject, (const void *)ulArg_p, sizeof(LocalObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0)) { iRet = (int)kEplApiInvalidParam; goto Exit; } pData = vmalloc(LocalObject.m_uiSize); if (pData == NULL) { // no memory available iRet = -ENOMEM; goto Exit; } iErr = copy_from_user(pData, LocalObject.m_pData, LocalObject.m_uiSize); if (iErr != 0) { iRet = -EIO; goto Exit; } EplRet = EplApiWriteLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, LocalObject.m_uiSize); vfree(pData); iRet = (int)EplRet; break; } case EPLLIN_CMD_READ_OBJECT: { tEplLinSdoObject SdoObject; void *pData; tEplLinSdoBufHeader *pBufHeader; tEplSdoComConHdl *pSdoComConHdl; iErr = copy_from_user(&SdoObject, (const void *)ulArg_p, sizeof(SdoObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0)) { iRet = (int)kEplApiInvalidParam; goto Exit; } pBufHeader = (tEplLinSdoBufHeader *) vmalloc(sizeof(tEplLinSdoBufHeader) + SdoObject.m_uiSize); if (pBufHeader == NULL) { // no memory available iRet = -ENOMEM; goto Exit; } // initiate temporary buffer pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app pData = pBufHeader + sizeof(tEplLinSdoBufHeader); if (SdoObject.m_fValidSdoComConHdl != FALSE) { pSdoComConHdl = &SdoObject.m_SdoComConHdl; } else { pSdoComConHdl = NULL; } EplRet = EplApiReadObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex, SdoObject.m_uiSubindex, pData, &SdoObject.m_uiSize, SdoObject.m_SdoType, pBufHeader); // return actual SDO handle (SdoObject.m_SdoComConHdl) iErr = put_user(SdoObject.m_SdoComConHdl, (unsigned int *)(ulArg_p + (unsigned long) &SdoObject. m_SdoComConHdl - (unsigned long) &SdoObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if (EplRet == kEplSuccessful) { iErr = copy_to_user(SdoObject.m_le_pData, pData, SdoObject.m_uiSize); vfree(pBufHeader); if (iErr != 0) { iRet = -EIO; goto Exit; } // return actual size (SdoObject.m_uiSize) iErr = put_user(SdoObject.m_uiSize, (unsigned int *)(ulArg_p + (unsigned long) &SdoObject. m_uiSize - (unsigned long) &SdoObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } } else if (EplRet != kEplApiTaskDeferred) { // error ocurred vfree(pBufHeader); if (iErr != 0) { iRet = -EIO; goto Exit; } } iRet = (int)EplRet; break; } case EPLLIN_CMD_WRITE_OBJECT: { tEplLinSdoObject SdoObject; void *pData; tEplLinSdoBufHeader *pBufHeader; tEplSdoComConHdl *pSdoComConHdl; iErr = copy_from_user(&SdoObject, (const void *)ulArg_p, sizeof(SdoObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0)) { iRet = (int)kEplApiInvalidParam; goto Exit; } pBufHeader = (tEplLinSdoBufHeader *) vmalloc(sizeof(tEplLinSdoBufHeader) + SdoObject.m_uiSize); if (pBufHeader == NULL) { // no memory available iRet = -ENOMEM; goto Exit; } // initiate temporary buffer pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app pData = pBufHeader + sizeof(tEplLinSdoBufHeader); iErr = copy_from_user(pData, SdoObject.m_le_pData, SdoObject.m_uiSize); if (iErr != 0) { iRet = -EIO; goto Exit; } if (SdoObject.m_fValidSdoComConHdl != FALSE) { pSdoComConHdl = &SdoObject.m_SdoComConHdl; } else { pSdoComConHdl = NULL; } EplRet = EplApiWriteObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex, SdoObject.m_uiSubindex, pData, SdoObject.m_uiSize, SdoObject.m_SdoType, pBufHeader); // return actual SDO handle (SdoObject.m_SdoComConHdl) iErr = put_user(SdoObject.m_SdoComConHdl, (unsigned int *)(ulArg_p + (unsigned long) &SdoObject. m_SdoComConHdl - (unsigned long) &SdoObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } if (EplRet != kEplApiTaskDeferred) { // succeeded or error ocurred, but task not deferred vfree(pBufHeader); } iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_FREE_SDO_CHANNEL: { // forward SDO handle to EPL stack EplRet = EplApiFreeSdoChannel((tEplSdoComConHdl) ulArg_p); iRet = (int)EplRet; break; } #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) // ---------------------------------------------------------- case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE: { tEplLinNodeCmdObject NodeCmdObject; iErr = copy_from_user(&NodeCmdObject, (const void *)ulArg_p, sizeof(NodeCmdObject)); if (iErr != 0) { iRet = -EIO; goto Exit; } EplRet = EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId, NodeCmdObject. m_NodeCommand); iRet = (int)EplRet; break; } #endif // ---------------------------------------------------------- case EPLLIN_CMD_GET_EVENT: { tEplLinEvent Event; // save event structure iErr = copy_from_user(&Event, (const void *)ulArg_p, sizeof(Event)); if (iErr != 0) { iRet = -EIO; goto Exit; } // save return code from application's event callback function RetCbEvent_g = Event.m_RetCbEvent; if (RetCbEvent_g == kEplShutdown) { // pass control to event queue kernel thread, but signal termination atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbEvent_g); // exit with error -> EplApiProcess() will leave the infinite loop iRet = 1; goto Exit; } // pass control to event queue kernel thread atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL); wake_up_interruptible(&WaitQueueCbEvent_g); // fall asleep itself in own wait queue iErr = wait_event_interruptible(WaitQueueProcess_g, (atomic_read (&AtomicEventState_g) == EVENT_STATE_READY) || (atomic_read (&AtomicEventState_g) == EVENT_STATE_TERM)); if (iErr != 0) { // waiting was interrupted by signal // pass control to event queue kernel thread, but signal termination atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbEvent_g); // exit with this error -> EplApiProcess() will leave the infinite loop iRet = iErr; goto Exit; } else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM) { // termination in progress // pass control to event queue kernel thread, but signal termination wake_up_interruptible(&WaitQueueCbEvent_g); // exit with this error -> EplApiProcess() will leave the infinite loop iRet = 1; goto Exit; } // copy event to user space iErr = copy_to_user(Event.m_pEventType, &EventType_g, sizeof(EventType_g)); if (iErr != 0) { // not all data could be copied iRet = -EIO; goto Exit; } // $$$ d.k. perform SDO event processing if (EventType_g == kEplApiEventSdo) { void *pData; tEplLinSdoBufHeader *pBufHeader; pBufHeader = (tEplLinSdoBufHeader *) pEventArg_g->m_Sdo. m_pUserArg; pData = pBufHeader + sizeof(tEplLinSdoBufHeader); if (pEventArg_g->m_Sdo.m_SdoAccessType == kEplSdoAccessTypeRead) { // copy read data to user space iErr = copy_to_user(pBufHeader->m_pData, pData, pEventArg_g->m_Sdo. m_uiTransferredByte); if (iErr != 0) { // not all data could be copied iRet = -EIO; goto Exit; } } pEventArg_g->m_Sdo.m_pUserArg = pBufHeader->m_pUserArg; vfree(pBufHeader); } iErr = copy_to_user(Event.m_pEventArg, pEventArg_g, min(sizeof(tEplApiEventArg), Event.m_uiEventArgSize)); if (iErr != 0) { // not all data could be copied iRet = -EIO; goto Exit; } // return to EplApiProcess(), which will call the application's event callback function iRet = 0; break; } // ---------------------------------------------------------- case EPLLIN_CMD_PI_SETUP: { EplRet = EplApiProcessImageSetup(); iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_PI_IN: { tEplApiProcessImage ProcessImageIn; // save process image structure iErr = copy_from_user(&ProcessImageIn, (const void *)ulArg_p, sizeof(ProcessImageIn)); if (iErr != 0) { iRet = -EIO; goto Exit; } // pass control to event queue kernel thread atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL); // fall asleep itself in own wait queue iErr = wait_event_interruptible(WaitQueuePI_In_g, (atomic_read (&AtomicSyncState_g) == EVENT_STATE_READY) || (atomic_read (&AtomicSyncState_g) == EVENT_STATE_TERM)); if (iErr != 0) { // waiting was interrupted by signal // pass control to sync kernel thread, but signal termination atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbSync_g); // exit with this error -> application will leave the infinite loop iRet = iErr; goto Exit; } else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM) { // termination in progress // pass control to sync kernel thread, but signal termination wake_up_interruptible(&WaitQueueCbSync_g); // exit with this error -> application will leave the infinite loop iRet = 1; goto Exit; } // exchange process image EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn); // return to EplApiProcessImageExchangeIn() iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_PI_OUT: { tEplApiProcessImage ProcessImageOut; // save process image structure iErr = copy_from_user(&ProcessImageOut, (const void *)ulArg_p, sizeof(ProcessImageOut)); if (iErr != 0) { iRet = -EIO; goto Exit; } if (atomic_read(&AtomicSyncState_g) != EVENT_STATE_READY) { iRet = (int)kEplInvalidOperation; goto Exit; } // exchange process image EplRet = EplApiProcessImageExchangeOut(&ProcessImageOut); // pass control to sync kernel thread atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); wake_up_interruptible(&WaitQueueCbSync_g); // return to EplApiProcessImageExchangeout() iRet = (int)EplRet; break; } // ---------------------------------------------------------- case EPLLIN_CMD_NMT_COMMAND: { // forward NMT command to EPL stack EplRet = EplApiExecNmtCommand((tEplNmtEvent) ulArg_p); iRet = (int)EplRet; break; } // ---------------------------------------------------------- default: { break; } } Exit: // TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet); return (iRet); }
//--------------------------------------------------------------------------- // // Function: AppCbEvent // // Description: event callback function called by EPL API layer within // user part (low priority). // // Parameters: EventType_p = event type // pEventArg_p = pointer to union, which describes // the event in detail // pUserArg_p = user specific argument // // Returns: tEplKernel = error code, // kEplSuccessful = no error // kEplReject = reject further processing // otherwise = post error event to API layer // // State: // //--------------------------------------------------------------------------- tEplKernel PUBLIC AppCbEvent ( tEplApiEventType EventType_p, // IN: event type (enum) tEplApiEventArg* pEventArg_p, // IN: event argument (union) io_sAgent* pUserArg_p ) { UINT uiVarLen; tEplKernel EplRet = kEplSuccessful; pwr_sClass_Epl_MN *op = (pwr_sClass_Epl_MN *)pUserArg_p->op; io_sRack *rp; // check if NMT_GS_OFF is reached switch (EventType_p) { case kEplApiEventNmtStateChange: { op->NmtState = pEventArg_p->m_NmtStateChange.m_NewNmtState; op->Status = op->NmtState == pwr_eEplNmtState_EplNmtMsOperational ? IOM__EPL_OPER : IOM__EPL_NOOPER; switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) { case kEplNmtGsOff: { // NMT state machine was shut down, // because of user signal (CTRL-C) or critical EPL stack error // -> also shut down EplApiProcess() and main() EplRet = kEplShutdown; errh_Fatal("Event:kEplNmtGsOff originating event = 0x%X (%s)", pEventArg_p->m_NmtStateChange.m_NmtEvent, EplGetNmtEventStr(pEventArg_p->m_NmtStateChange.m_NmtEvent)); break; } case kEplNmtGsResetCommunication: { break; } case kEplNmtGsResetConfiguration: { if (uiCycleLen_g != 0) { EplRet = EplApiWriteLocalObject(0x1006, 0x00, &uiCycleLen_g, sizeof (uiCycleLen_g)); uiCurCycleLen_g = uiCycleLen_g; } else { uiVarLen = sizeof(uiCurCycleLen_g); EplApiReadLocalObject(0x1006, 0x00, &uiCurCycleLen_g, &uiVarLen); } break; } case kEplNmtCsPreOperational1: case kEplNmtMsPreOperational1: { errh_Info("AppCbEvent(0x%X) originating event = 0x%X (%s)", pEventArg_p->m_NmtStateChange.m_NewNmtState, pEventArg_p->m_NmtStateChange.m_NmtEvent, EplGetNmtEventStr(pEventArg_p->m_NmtStateChange.m_NmtEvent)); break; } case kEplNmtCsPreOperational2: case kEplNmtMsPreOperational2: { break; } case kEplNmtCsReadyToOperate: case kEplNmtMsReadyToOperate: { break; } case kEplNmtGsInitialising: { break; } case kEplNmtGsResetApplication: { break; } case kEplNmtMsNotActive: case kEplNmtCsNotActive: { break; } case kEplNmtCsOperational: case kEplNmtMsOperational: { break; } case kEplNmtCsBasicEthernet: case kEplNmtMsBasicEthernet: { break; } default: { } } break; } case kEplApiEventCriticalError: case kEplApiEventWarning: { // error or warning occurred within the stack or the application // on error the API layer stops the NMT state machine errh_Error( "%s(Err/Warn): Source = %s (%02X) EplError = %s (0x%03X)", __func__, EplGetEventSourceStr(pEventArg_p->m_InternalError.m_EventSource), pEventArg_p->m_InternalError.m_EventSource, EplGetEplKernelStr(pEventArg_p->m_InternalError.m_EplError), pEventArg_p->m_InternalError.m_EplError); // check additional argument switch (pEventArg_p->m_InternalError.m_EventSource) { case kEplEventSourceEventk: case kEplEventSourceEventu: { // error occurred within event processing // either in kernel or in user part errh_Error(" OrgSource = %s %02X", EplGetEventSourceStr(pEventArg_p->m_InternalError.m_Arg.m_EventSource), pEventArg_p->m_InternalError.m_Arg.m_EventSource); break; } case kEplEventSourceDllk: { // error occurred within the data link layer (e.g. interrupt processing) // the DWORD argument contains the DLL state and the NMT event errh_Error(" val = %X", pEventArg_p->m_InternalError.m_Arg.m_dwArg); break; } default: { break; } } break; } case kEplApiEventHistoryEntry: { // new history entry errh_Info("%s(HistoryEntry): Type=0x%04X Code=0x%04X (0x%02X %02X %02X %02X %02X %02X %02X %02X)", __func__, pEventArg_p->m_ErrHistoryEntry.m_wEntryType, pEventArg_p->m_ErrHistoryEntry.m_wErrorCode, (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[0], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[1], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[2], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[3], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[4], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[5], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[6], (WORD) pEventArg_p->m_ErrHistoryEntry.m_abAddInfo[7]); break; } case kEplApiEventNode: { switch (pEventArg_p->m_Node.m_NodeEvent) { case kEplNmtNodeEventCheckConf: { errh_Info("%s(Node=0x%X, CheckConf)", __func__, pEventArg_p->m_Node.m_uiNodeId); break; } case kEplNmtNodeEventUpdateConf: { errh_Info("%s(Node=0x%X, UpdateConf)", __func__, pEventArg_p->m_Node.m_uiNodeId); break; } case kEplNmtNodeEventFound: { break; } case kEplNmtNodeEventNmtState: { for ( rp = pUserArg_p->racklist; rp; rp = rp->next) if(((pwr_sClass_Epl_CN *)rp->op)->NodeId == pEventArg_p->m_Node.m_uiNodeId) { ((pwr_sClass_Epl_CN *)rp->op)->NmtState = pEventArg_p->m_Node.m_NmtState; } switch (pEventArg_p->m_Node.m_NmtState) { case kEplNmtGsOff: case kEplNmtGsInitialising: case kEplNmtGsResetApplication: case kEplNmtGsResetCommunication: case kEplNmtGsResetConfiguration: case kEplNmtCsNotActive: { break; } case kEplNmtCsPreOperational1: case kEplNmtCsPreOperational2: case kEplNmtCsReadyToOperate: { break; } case kEplNmtCsOperational: { break; } case kEplNmtCsBasicEthernet: case kEplNmtCsStopped: default: { break; } } break; } case kEplNmtNodeEventError: { errh_Error("AppCbEvent (Node=0x%X): Error = %s (0x%.4X)", pEventArg_p->m_Node.m_uiNodeId, EplGetEmergErrCodeStr(pEventArg_p->m_Node.m_wErrorCode), pEventArg_p->m_Node.m_wErrorCode); break; } default: { break; } } break; } case kEplApiEventCfmProgress: { errh_Info("%s(Node=0x%X, CFM-Progress: Object 0x%X/%u, %lu/%lu Bytes", __func__, pEventArg_p->m_CfmProgress.m_uiNodeId, pEventArg_p->m_CfmProgress.m_uiObjectIndex, pEventArg_p->m_CfmProgress.m_uiObjectSubIndex, (ULONG) pEventArg_p->m_CfmProgress.m_dwBytesDownloaded, (ULONG) pEventArg_p->m_CfmProgress.m_dwTotalNumberOfBytes); if ((pEventArg_p->m_CfmProgress.m_dwSdoAbortCode != 0) || (pEventArg_p->m_CfmProgress.m_EplError != kEplSuccessful)) { errh_Error(" -> SDO Abort=0x%lX, Error=0x%X)", (unsigned long) pEventArg_p->m_CfmProgress.m_dwSdoAbortCode, pEventArg_p->m_CfmProgress.m_EplError); } else { } break; } case kEplApiEventCfmResult: { switch (pEventArg_p->m_CfmResult.m_NodeCommand) { case kEplNmtNodeCommandConfOk: { errh_Info("%s(Node=0x%X, ConfOk)", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfErr: { errh_Info("%s(Node=0x%X, ConfErr)", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfReset: { errh_Info("%s(Node=0x%X, ConfReset)", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } case kEplNmtNodeCommandConfRestored: { errh_Info("%s(Node=0x%X, ConfRestored)", __func__, pEventArg_p->m_CfmResult.m_uiNodeId); break; } default: { errh_Info("%s(Node=0x%X, CfmResult=0x%X)", __func__, pEventArg_p->m_CfmResult.m_uiNodeId, pEventArg_p->m_CfmResult.m_NodeCommand); break; } } break; } default: break; } return EplRet; }