//------------------------------------------------------------------------------
static tOplkError processSdoEvent(tOplkApiEventType EventType_p,
                                  tOplkApiEventArg* pEventArg_p,
                                  void* pUserArg_p)
{
    tSdoComFinished*    pSdo = &pEventArg_p->sdoInfo;
    tOplkError          ret = kErrorOk;

    UNUSED_PARAMETER(EventType_p);
    UNUSED_PARAMETER(pUserArg_p);

    // SDO transfer finished
    if ((ret = oplk_freeSdoChannel(pSdo->sdoAccessType)) != kErrorOk)
    {
        return ret;
    }

    if (pSdo->sdoComConState == kSdoComTransferFinished)
    {   // continue boot-up of CN with NMT command Reset Configuration
        ret = oplk_triggerMnStateChange(pSdo->nodeId, kNmtNodeCommandConfReset);
    }
    else
    {   // indicate configuration error CN
        ret = oplk_triggerMnStateChange(pSdo->nodeId, kNmtNodeCommandConfErr);
    }
    return ret;
}
//------------------------------------------------------------------------------
tOplkError ProcessThread::processNodeEvent(tOplkApiEventType eventType_p,
                                           tOplkApiEventArg* pEventArg_p,
                                           void* pUserArg_p)
{
    tOplkApiEventNode*   pNode = &pEventArg_p->nodeEvent;
    tOplkError           ret = kErrorOk;

    UNUSED_PARAMETER(eventType_p);
    UNUSED_PARAMETER(pUserArg_p);
    // printf("AppCbEvent(Node): NodeId=%u Event=0x%02X\n",
    //        pEventArg_p->nodeEvent.nodeId, pEventArg_p->nodeEvent.nodeEvent);
    // check additional argument
    switch (pEventArg_p->nodeEvent.nodeEvent)
    {
        case kNmtNodeEventCheckConf:
#if !defined(CONFIG_INCLUDE_CFM)
            // Configuration Manager is not available,
            // so configure CycleLen (object 0x1006) on CN
            tSdoComConHdl SdoComConHdl;

            // update object 0x1006 on CN
            ret = oplk_writeObject(&SdoComConHdl, pEventArg_p->nodeEvent.nodeId,
                                   0x1006, 0x00, &cycleLen_g, 4,
                                   kSdoTypeAsnd, NULL);
            if (ret == kErrorApiTaskDeferred)
            {   // SDO transfer started
                ret = kErrorReject;
            }
            else if (ret == kErrorOk)
            {   // local OD access (should not occur)
                printf("AppCbEvent(Node) write to local OD\n");
            }
            else
            {   // error occured

                ret = oplk_freeSdoChannel(SdoComConHdl);
                SdoComConHdl = 0;

                ret = oplk_writeObject(&SdoComConHdl, pEventArg_p->nodeEvent.nodeId,
                                       0x1006, 0x00, &cycleLen_g, 4,
                                       kSdoTypeAsnd, NULL);
                if (ret == kErrorApiTaskDeferred)
                {   // SDO transfer started
                    ret = kErrorReject;
                }
                else
                {
                    printf("AppCbEvent(Node): oplk_writeObject() returned 0x%03X", ret);
                }
            }
#endif

            sigPrintLog(QString("Node Event: (Node=%2, CheckConf)")
                                .arg(pEventArg_p->nodeEvent.nodeId, 0, 10));
            break;

        case kNmtNodeEventUpdateConf:
            sigPrintLog(QString("Node Event: (Node=%1, UpdateConf)")
                                .arg(pEventArg_p->nodeEvent.nodeId, 0, 10));
            break;

        case kNmtNodeEventFound:
            pProcessThread_g->sigNodeAppeared(pEventArg_p->nodeEvent.nodeId);
            break;

        case kNmtNodeEventNmtState:
            switch (pEventArg_p->nodeEvent.nmtState)
            {
                case kNmtGsOff:
                case kNmtGsInitialising:
                case kNmtGsResetApplication:
                case kNmtGsResetCommunication:
                case kNmtGsResetConfiguration:
                case kNmtCsNotActive:
                    pProcessThread_g->sigNodeDisappeared(pEventArg_p->nodeEvent.nodeId);
                    break;

                case kNmtCsPreOperational1:
                case kNmtCsPreOperational2:
                case kNmtCsReadyToOperate:
                    pProcessThread_g->sigNodeAppeared(pEventArg_p->nodeEvent.nodeId);
                    pProcessThread_g->sigNodeStatus(pEventArg_p->nodeEvent.nodeId, 1);
                    break;

                case kNmtCsOperational:
                    pProcessThread_g->sigNodeAppeared(pEventArg_p->nodeEvent.nodeId);
                    pProcessThread_g->sigNodeStatus(pEventArg_p->nodeEvent.nodeId, 2);
                    break;

                case kNmtCsBasicEthernet:
                case kNmtCsStopped:
                default:
                    pProcessThread_g->sigNodeStatus(pEventArg_p->nodeEvent.nodeId, -1);
                    break;
            }
            break;

        case kNmtNodeEventError:
            pProcessThread_g->sigNodeStatus(pEventArg_p->nodeEvent.nodeId, -1);
            sigPrintLog(QString("AppCbEvent (Node=%1): Error = %2 (0x%3)")
                                .arg(pEventArg_p->nodeEvent.nodeId, 0, 10)
                                .arg(debugstr_getEmergErrCodeStr(pEventArg_p->nodeEvent.errorCode))
                                .arg(pEventArg_p->nodeEvent.errorCode, 4, 16, QLatin1Char('0')));
            break;

        case kNmtNodeEventAmniReceived:
            sigPrintLog(QString("AppCbEvent (Node=%1): received ActiveManagingNodeIndication")
                                .arg(pEventArg_p->nodeEvent.nodeId, 0, 10));
            break;

        default:
            break;
    }
    return kErrorOk;
}