static int EplLinProcWrite(struct file *file, const char __user *buffer, unsigned long count, void *data) { char abBuffer[count + 1]; int iErr; int iVal = 0; tEplNmtEvent NmtEvent; if (count > 0) { iErr = copy_from_user(abBuffer, buffer, count); if (iErr != 0) { return count; } abBuffer[count] = '\0'; iErr = sscanf(abBuffer, "%i", &iVal); } if ((iVal <= 0) || (iVal > 0x2F)) { NmtEvent = kEplNmtEventSwReset; } else { NmtEvent = (tEplNmtEvent) iVal; } // execute specified NMT command on write access of /proc/epl #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) EplNmtuNmtEvent(NmtEvent); #endif return count; }
//--------------------------------------------------------------------------- // // Function: EplNmtuProcessEvent // // Description: processes events from event queue // // // // Parameters: pEplEvent_p = pointer to event // // // Returns: tEplKernel = errorcode // // // State: // //--------------------------------------------------------------------------- EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) { tEplKernel Ret; Ret = kEplSuccessful; // process event switch (pEplEvent_p->m_EventType) { // state change of NMT-Module case kEplEventTypeNmtStateChange: { tEplEventNmtStateChange *pNmtStateChange; // delete timer Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl); pNmtStateChange = (tEplEventNmtStateChange *) pEplEvent_p->m_pArg; // call cb-functions to inform higher layer if (EplNmtuInstance_g.m_pfnNmtChangeCb != NULL) { Ret = EplNmtuInstance_g. m_pfnNmtChangeCb(*pNmtStateChange); } if (Ret == kEplSuccessful) { // everything is OK, so switch to next state if necessary switch (pNmtStateChange->m_NewNmtState) { // EPL stack is not running case kEplNmtGsOff: break; // first init of the hardware case kEplNmtGsInitialising: { Ret = EplNmtuNmtEvent (kEplNmtEventEnterResetApp); break; } // init of the manufacturer-specific profile area and the // standardised device profile area case kEplNmtGsResetApplication: { Ret = EplNmtuNmtEvent (kEplNmtEventEnterResetCom); break; } // init of the communication profile area case kEplNmtGsResetCommunication: { Ret = EplNmtuNmtEvent (kEplNmtEventEnterResetConfig); break; } // build the configuration with infos from OD case kEplNmtGsResetConfiguration: { unsigned int uiNodeId; // get node ID from OD #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) uiNodeId = EplObduGetNodeId (EPL_MCO_PTR_INSTANCE_PTR); #else uiNodeId = 0; #endif //check node ID if not should be master or slave if (uiNodeId == EPL_C_ADR_MN_DEF_NODE_ID) { // node shall be MN #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) Ret = EplNmtuNmtEvent (kEplNmtEventEnterMsNotActive); #else TRACE0 ("EplNmtuProcess(): no MN functionality implemented\n"); #endif } else { // node shall be CN Ret = EplNmtuNmtEvent (kEplNmtEventEnterCsNotActive); } break; } //----------------------------------------------------------- // CN part of the state machine // node listens for EPL-Frames and check timeout case kEplNmtCsNotActive: { DWORD dwBuffer; tEplObdSize ObdSize; tEplTimerArg TimerArg; // create timer to switch automatically to BasicEthernet if no MN available in network // read NMT_CNBasicEthernetTimerout_U32 from OD ObdSize = sizeof(dwBuffer); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) Ret = EplObduReadEntry (EPL_MCO_PTR_INSTANCE_PTR_ 0x1F99, 0x00, &dwBuffer, &ObdSize); #else Ret = kEplObdIndexNotExist; #endif if (Ret != kEplSuccessful) { break; } if (dwBuffer != 0) { // BasicEthernet is enabled // convert us into ms dwBuffer = dwBuffer / 1000; if (dwBuffer == 0) { // timer was below one ms // set one ms dwBuffer = 1; } TimerArg.m_EventSink = kEplEventSinkNmtk; TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerBasicEthernet; Ret = EplTimeruModifyTimerMs (&EplNmtuInstance_g. m_TimerHdl, (unsigned long) dwBuffer, TimerArg); // potential error is forwarded to event queue which generates error event } break; } // node processes only async frames case kEplNmtCsPreOperational1: { break; } // node processes isochronous and asynchronous frames case kEplNmtCsPreOperational2: { Ret = EplNmtuNmtEvent (kEplNmtEventEnterReadyToOperate); break; } // node should be configured und application is ready case kEplNmtCsReadyToOperate: { break; } // normal work state case kEplNmtCsOperational: { break; } // node stopped by MN // -> only process asynchronous frames case kEplNmtCsStopped: { break; } // no EPL cycle // -> normal ethernet communication case kEplNmtCsBasicEthernet: { break; } //----------------------------------------------------------- // MN part of the state machine #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) // node listens for EPL-Frames and check timeout case kEplNmtMsNotActive: { DWORD dwBuffer; tEplObdSize ObdSize; tEplTimerArg TimerArg; // create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network // check NMT_StartUp_U32.Bit13 // read NMT_StartUp_U32 from OD ObdSize = sizeof(dwBuffer); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) Ret = EplObduReadEntry (EPL_MCO_PTR_INSTANCE_PTR_ 0x1F80, 0x00, &dwBuffer, &ObdSize); #else Ret = kEplObdIndexNotExist; #endif if (Ret != kEplSuccessful) { break; } if ((dwBuffer & EPL_NMTST_BASICETHERNET) == 0) { // NMT_StartUp_U32.Bit13 == 0 // new state PreOperational1 TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerMsPreOp1; } else { // NMT_StartUp_U32.Bit13 == 1 // new state BasicEthernet TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerBasicEthernet; } // read NMT_BootTime_REC.MNWaitNotAct_U32 from OD ObdSize = sizeof(dwBuffer); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) Ret = EplObduReadEntry (EPL_MCO_PTR_INSTANCE_PTR_ 0x1F89, 0x01, &dwBuffer, &ObdSize); #else Ret = kEplObdIndexNotExist; #endif if (Ret != kEplSuccessful) { break; } // convert us into ms dwBuffer = dwBuffer / 1000; if (dwBuffer == 0) { // timer was below one ms // set one ms dwBuffer = 1; } TimerArg.m_EventSink = kEplEventSinkNmtk; Ret = EplTimeruModifyTimerMs (&EplNmtuInstance_g. m_TimerHdl, (unsigned long)dwBuffer, TimerArg); // potential error is forwarded to event queue which generates error event break; } // node processes only async frames case kEplNmtMsPreOperational1: { DWORD dwBuffer = 0; tEplObdSize ObdSize; tEplTimerArg TimerArg; // create timer to switch automatically to PreOp2 if MN identified all mandatory CNs // read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD ObdSize = sizeof(dwBuffer); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) Ret = EplObduReadEntry (EPL_MCO_PTR_INSTANCE_PTR_ 0x1F89, 0x03, &dwBuffer, &ObdSize); if (Ret != kEplSuccessful) { // ignore error, because this timeout is optional dwBuffer = 0; } #endif if (dwBuffer == 0) { // delay is deactivated // immediately post timer event Ret = EplNmtuNmtEvent (kEplNmtEventTimerMsPreOp2); break; } // convert us into ms dwBuffer = dwBuffer / 1000; if (dwBuffer == 0) { // timer was below one ms // set one ms dwBuffer = 1; } TimerArg.m_EventSink = kEplEventSinkNmtk; TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerMsPreOp2; Ret = EplTimeruModifyTimerMs (&EplNmtuInstance_g. m_TimerHdl, (unsigned long)dwBuffer, TimerArg); // potential error is forwarded to event queue which generates error event 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; } #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) default: { TRACE1 ("EplNmtuProcess(): unhandled NMT state 0x%X\n", pNmtStateChange-> m_NewNmtState); } } } else if (Ret == kEplReject) { // application wants to change NMT state itself // it's OK Ret = kEplSuccessful; } EPL_DBGLVL_NMTU_TRACE0 ("EplNmtuProcessEvent(): NMT-State-Maschine announce change of NMT State\n"); break; } default: { Ret = kEplNmtInvalidEvent; } } //Exit: return Ret; }