//------------------------------------------------------------------------------
void SdoDialog::userDefEvent(void* pUserArg_p)
{
    tSdoComConHdl SdoComConHdl;
    tObdSize obdSize;
    tOplkError ret;

    obdSize = data.size();

    if (pUserArg_p == readButton)
    {
        ret = oplk_readObject(&SdoComConHdl, targetNodeId,
                               targetIndex, targetSubindex,
                               data.data(), &obdSize,
                               (tSdoType) sdoType, NULL);
        if (ret == kErrorApiTaskDeferred)
        {   // SDO transfer started
            return;
        }
        else if (ret == kErrorOk)
        {   // local OD access
            data.resize(obdSize);

            emit sigUpdateData("Successfully read from local OD");
        }
        else
        {
            data.resize(0);

            emit sigUpdateData(QString("Error 0x%1: %2")
                                .arg(ret, 0, 16)
                                .arg(debugstr_getRetValStr(ret)));
        }
    }
    else if (pUserArg_p == writeButton)
    {
        ret = oplk_writeObject(&SdoComConHdl, targetNodeId,
                               targetIndex, targetSubindex,
                               data.data(), obdSize,
                               (tSdoType) sdoType, NULL);
        if (ret == kErrorApiTaskDeferred)
        {   // SDO transfer started
            return;
        }
        else if (ret == kErrorOk)
        {   // local OD access
            data.resize(obdSize);

            emit sigUpdateData("Successfully written to local OD");
        }
        else
        {
            data.resize(0);

            emit sigUpdateData(QString("Error 0x%1: %2")
                                .arg(ret, 0, 16)
                                .arg(debugstr_getRetValStr(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;
}
//------------------------------------------------------------------------------
static tFirmwareRet transmitFirmware(tFirmwareUpdateTransmissionInfo* pInfo_p)
{
    tFirmwareRet    ret = kFwReturnOk;
    tOplkError      oplkRet;

    if (pInfo_p->fTranmissionActive)
    {
        goto EXIT;
    }

    if (!isTransmissionAllowed(pInfo_p))
    {
        FWM_TRACE("Postpone update for node: %u index: 0x%x subindex: 0x%x\n",
                  pInfo_p->pUpdateList->nodeId, pInfo_p->pUpdateList->index,
                  pInfo_p->pUpdateList->subindex);

        goto EXIT;
    }

    FWM_TRACE("Start update for node: %u index: 0x%x subindex: 0x%x\n",
              pInfo_p->pUpdateList->nodeId, pInfo_p->pUpdateList->index,
              pInfo_p->pUpdateList->subindex);

    ret = firmwarestore_loadData(pInfo_p->pUpdateList->pStoreHandle);
    if (ret != kFwReturnOk)
    {
        FWM_ERROR("Loading image for transmission failed with %d and errno %d\n",
                  ret, errno);
        goto EXIT;
    }

    ret = firmwarestore_getData(pInfo_p->pUpdateList->pStoreHandle,
                                &pInfo_p->pFirmwareImage,
                                &pInfo_p->firmwareSize);
    if (ret != kFwReturnOk)
    {
        FWM_ERROR("Getting the image for transmission failed with %d and errno %d\n",
                  ret, errno);
        goto EXIT;
    }

    oplkRet = oplk_writeObject(&pInfo_p->sdoComCon,
                               pInfo_p->pUpdateList->nodeId,
                               pInfo_p->pUpdateList->index,
                               pInfo_p->pUpdateList->subindex,
                               pInfo_p->pFirmwareImage,
                               (UINT)pInfo_p->firmwareSize,
                               FIRMWARE_UPDATE_SDO_TYPE,
                               &instance_l);

    if ((oplkRet != kErrorApiTaskDeferred) && (pInfo_p->sdoComCon != FIRMWARE_UPDATE_INVALID_SDO))
    {
        FWM_ERROR("Writing the firmware object failed with 0x%X\n", oplkRet);
        ret = kFwReturnSdoWriteFailed;
        goto EXIT;
    }

    instance_l.numberOfStartedTransmissions++;
    pInfo_p->fTranmissionActive = TRUE;

EXIT:
    if (ret != kFwReturnOk)
    {
        firmwarestore_flushData(pInfo_p->pUpdateList->pStoreHandle);
    }
    return ret;
}