diff options
author | Fulup Ar Foll <fulup@iot.bzh> | 2017-05-26 18:45:56 +0200 |
---|---|---|
committer | Fulup Ar Foll <fulup@iot.bzh> | 2017-05-26 18:45:56 +0200 |
commit | d2e42029ec04c3f224580f8007cdfbbfe0fc47a6 (patch) | |
tree | ad2ccf167cf7997c84191d41e6ba55cb2efd6bed /ucs2-lib/src/ucs_nsm.c | |
parent | 18e393e1443fd4c38b34979888fb55d30448cf31 (diff) |
Initial Commit
Diffstat (limited to 'ucs2-lib/src/ucs_nsm.c')
-rw-r--r-- | ucs2-lib/src/ucs_nsm.c | 725 |
1 files changed, 725 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_nsm.c b/ucs2-lib/src/ucs_nsm.c new file mode 100644 index 0000000..1e3a7e5 --- /dev/null +++ b/ucs2-lib/src/ucs_nsm.c @@ -0,0 +1,725 @@ +/*------------------------------------------------------------------------------------------------*/ +/* UNICENS V2.1.0-3491 */ +/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* */ +/* You may also obtain this software under a propriety license from Microchip. */ +/* Please contact Microchip for further information. */ +/*------------------------------------------------------------------------------------------------*/ + +/*! + * \file + * \brief Implementation of the Node Scripting Management. + * + * \cond UCS_INTERNAL_DOC + * \addtogroup G_NSM + * @{ + */ + +/*------------------------------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------------------------------*/ +#include "ucs_nsm.h" + +/*------------------------------------------------------------------------------------------------*/ +/* Service parameters */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief API locking Bitmask for Nsm_SendCurrScriptToTrcv() method. */ +#define NSM_RCMTX_API_LOCK 0x0001U + +/*! \brief Priority of the RSM service used by scheduler */ +static const uint8_t NSM_SRV_PRIO = 250U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ +/*! \brief Event for handling the next script */ +static const Srv_Event_t NSM_EVENT_HANDLE_NEXTSCRIPT = 0x01U; +/*! \brief Event for handling error in scripting */ +static const Srv_Event_t NSM_EVENT_HANDLE_ERROR = 0x02U; + +/*------------------------------------------------------------------------------------------------*/ +/* Internal prototypes */ +/*------------------------------------------------------------------------------------------------*/ +static void Nsm_Service(void *self); +static Ucs_Return_t Nsm_Start(CNodeScriptManagement * self); +static void Nsm_HandleApiTimeout(void *self, void *method_mask_ptr); +static void Nsm_UcsInitSucceededCb(void *self, void *event_ptr); +static void Nsm_UninitializeService(void *self, void *error_code_ptr); +static Ucs_Return_t Nsm_HandleNextScript(CNodeScriptManagement * self); +static Ucs_Return_t Nsm_DeviceSync(CNodeScriptManagement * self); +static Ucs_Return_t Nsm_SendCurrScriptToTrcv(CNodeScriptManagement * self); +static void Nsm_HandleError(CNodeScriptManagement * self); +static void Nsm_Finished(CNodeScriptManagement * self); +static bool Nsm_IsNextScriptAvailable(CNodeScriptManagement * self); +static void Nsm_IncrCurrScriptPtr (CNodeScriptManagement * self); +static void Nsm_MsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status); +static bool Nsm_IsCurrDeviceSynced(CNodeScriptManagement *self); +static void Nsm_RmtDevSyncResultCb(void *self, Rsm_Result_t result); +static Ucs_Return_t Nsm_PauseScript(CNodeScriptManagement * self); +static void Nsm_ResumeScriptHandling(void* self); +static void Nsm_ApiLocking(CNodeScriptManagement *self, bool status); +static bool Nsm_IsApiFree(CNodeScriptManagement *self); +static void Nsm_SendScriptResult(CNodeScriptManagement *self); + +/*------------------------------------------------------------------------------------------------*/ +/* Implementation of class CNodeScriptManagement */ +/*------------------------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------------------------*/ +/* Initialization Methods */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Constructor of the Node Script Manager class. + * \param self Instance pointer + * \param init_ptr init data_ptr + */ +void Nsm_Ctor(CNodeScriptManagement *self, Nsm_InitData_t *init_ptr) +{ + MISC_MEM_SET(self, 0, sizeof(CNodeScriptManagement)); + + /* Init all reference instances */ + self->base_ptr = init_ptr->base_ptr; + self->rcm_ptr = init_ptr->rcm_ptr; + self->rsm_ptr = init_ptr->rsm_ptr; + self->tm_ptr = &init_ptr->base_ptr->tm; + self->target_address = Inic_GetTargetAddress(self->rsm_ptr->inic_ptr); + + /* Initialize NSM service */ + Srv_Ctor(&self->nsm_srv, NSM_SRV_PRIO, self, &Nsm_Service); + + /* Initialize API locking mechanism */ + Sobs_Ctor(&self->lock.observer, self, &Nsm_HandleApiTimeout); + Al_Ctor(&self->lock.rcm_api, &self->lock.observer, self->base_ptr->ucs_user_ptr); + Alm_RegisterApi(&self->base_ptr->alm, &self->lock.rcm_api); + + /* Add NSM service to scheduler */ + (void)Scd_AddService(&self->base_ptr->scd, &self->nsm_srv); + + /* Inits observer for UCS termination */ + Mobs_Ctor(&self->ucstermination_observer, self, EH_M_TERMINATION_EVENTS, &Nsm_UninitializeService); + Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucstermination_observer); + + /* Inits observer for UCS initialization */ + Mobs_Ctor(&self->ucsinit_observer, self, EH_E_INIT_SUCCEEDED, &Nsm_UcsInitSucceededCb); + Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucsinit_observer); +} + +/*------------------------------------------------------------------------------------------------*/ +/* Service */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Executes the script(s) in the given Node. + * + * \param self Instance pointer of the CNodeScriptManagement + * \param node_ptr Reference to the node instance. + * \param pb_result_fptr Reference to the result function pointer + * \return Possible return values are: + * - \c UCS_RET_ERR_API_LOCKED the API is locked. + * - \c UCS_RET_SUCCESS if the execution was started successfully + * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available + * - \c UCS_RET_ERR_PARAM At least one parameter is NULL + * - \c UCS_RET_ERR_NOT_AVAILABLE Timer is not available for pausing the script process + */ +Ucs_Return_t Nsm_Run_Pb(CNodeScriptManagement * self, Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCb_t pb_result_fptr) +{ + Ucs_Return_t result = UCS_RET_ERR_API_LOCKED; + + if(Nsm_IsApiFree(self) != false) + { + result = UCS_RET_ERR_PARAM; + if ((node_ptr != NULL) && (node_ptr->script_list_ptr != NULL) && (node_ptr->script_list_size > 0U)) + { + /* Locked API */ + Nsm_ApiLocking(self, true); + + /* Private API is not used */ + self->is_private_api_used = false; + + /* Sets internal scripts references */ + self->curr_pb_result_fptr = pb_result_fptr; + self->curr_node_ptr = node_ptr; + self->curr_sript_ptr = self->curr_node_ptr->script_list_ptr; + self->curr_sript_size = self->curr_node_ptr->script_list_size; + self->curr_rxfilter_fptr = NULL; + + /* Runs script(s) */ + result = Nsm_Start(self); + } + + /* Release Locking if synchronous result is not successful */ + if (result != UCS_RET_SUCCESS) + { + Nsm_ApiLocking(self, false); + } + } + + return result; +} + +/*! \brief Executes the given script(s). + * + * \param self Instance pointer of the CNodeScriptManagement + * \param script Reference to the scripts table to be executed + * \param size Size of the scripts table + * \param user_ptr Reference to the caller instance + * \param rx_filter_fptr Reference to the optional RX filter callback function pointer + * \param result_fptr Reference to the optional result callback function pointer + * \return Possible return values are: + * - \c UCS_RET_ERR_API_LOCKED the API is locked. + * - \c UCS_RET_SUCCESS if the execution was started successfully + * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available + * - \c UCS_RET_ERR_PARAM At least one parameter is NULL + * - \c UCS_RET_ERR_NOT_AVAILABLE Timer is not available for pausing the script process + */ +Ucs_Return_t Nsm_Run_Pv(CNodeScriptManagement * self, Ucs_Ns_Script_t * script, uint8_t size, void * user_ptr, Nsm_RxFilterCb_t rx_filter_fptr, Nsm_ResultCb_t result_fptr) +{ + Ucs_Return_t result = UCS_RET_ERR_API_LOCKED; + + if(Nsm_IsApiFree(self) != false) + { + result = UCS_RET_ERR_PARAM; + if ((script != NULL) && (size > 0U)) + { + /* Locked API */ + Nsm_ApiLocking(self, true); + + /* Private API is not used */ + self->is_private_api_used = true; + + /* Sets internal scripts references */ + self->curr_sript_ptr = script; + self->curr_sript_size = size; + self->curr_user_ptr = user_ptr; + self->curr_rxfilter_fptr = rx_filter_fptr; + self->curr_pv_result_fptr = result_fptr; + + /* Runs script(s) */ + result = Nsm_Start(self); + } + + /* Release Locking if synchronous result is not successful */ + if (result != UCS_RET_SUCCESS) + { + Nsm_ApiLocking(self, false); + } + } + + return result; +} + +/*! \brief Filters RCM Rx messages allotted to NSM. + * \details The filter function shall not release the message object + * \param self Instance pointer of the CNodeScriptManagement + * \param tel_ptr Reference to the RCM Rx message object + * \return \c true if message is allotted to NSM, otherwise \c false. + */ +bool Nsm_OnRcmRxFilter(void *self, Msg_MostTel_t *tel_ptr) +{ + bool ret_val = false; + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + + if (self_ != NULL) + { + if (self_->curr_rxfilter_fptr != NULL) + { + ret_val = self_->curr_rxfilter_fptr(tel_ptr, self_->curr_user_ptr); + } + + if (!ret_val) + { + if ((self_->curr_sript_ptr != NULL) && (self_->curr_sript_ptr->exp_result != NULL)) + { + Ucs_Ns_ConfigMsg_t * tmp_exp_res = self_->curr_sript_ptr->exp_result; + if ((tmp_exp_res->FBlockId == tel_ptr->id.fblock_id) && + (tmp_exp_res->FunktId == tel_ptr->id.function_id) && + (tmp_exp_res->OpCode == tel_ptr->id.op_type) && + (tmp_exp_res->InstId == tel_ptr->id.instance_id) && + (tmp_exp_res->DataLen == tel_ptr->tel.tel_len)) + { + uint8_t k = 0U; + ret_val = true; + + if ((tmp_exp_res->DataPtr == NULL) && (tmp_exp_res->DataLen > 0U)) + { + ret_val = false; + } + + for (; ((k < tmp_exp_res->DataLen) && (ret_val == true)); k++) + { + if (tmp_exp_res->DataPtr[k] != tel_ptr->tel.tel_data_ptr[k]) + { + ret_val = false; + } + } + } + } + } + + if (ret_val) + { + TR_INFO((self_->base_ptr->ucs_user_ptr, "[NSM]", "Transfer of script [0x%X] completed", 1U, self_->curr_sript_ptr)); + Al_Release(&self_->lock.rcm_api, NSM_RCMTX_API_LOCK); + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_NEXTSCRIPT); + Nsm_IncrCurrScriptPtr(self_); + } + } + + return ret_val; +} + +/*! \brief Checks if the API is locked. + * \param self Instance pointer + * \return \c true if the API is locked, otherwise \c false. + */ +bool Nsm_IsLocked(CNodeScriptManagement * self) +{ + bool ret_val = false; + if (self != NULL) + { + ret_val = !Nsm_IsApiFree(self); + } + return ret_val; +} + +/*------------------------------------------------------------------------------------------------*/ +/* Private Methods */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Service function of the Node Scripting management. + * \param self Instance pointer + */ +static void Nsm_Service(void *self) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + Srv_Event_t event_mask; + Srv_GetEvent(&self_->nsm_srv, &event_mask); + + /* Event to process list of routes */ + if((event_mask & NSM_EVENT_HANDLE_NEXTSCRIPT) == NSM_EVENT_HANDLE_NEXTSCRIPT) + { + Srv_ClearEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_NEXTSCRIPT); + (void)Nsm_HandleNextScript(self_); + } + + /* Event to pause processing of routes list */ + if ((event_mask & NSM_EVENT_HANDLE_ERROR) == NSM_EVENT_HANDLE_ERROR) + { + Srv_ClearEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_ERROR); + Nsm_HandleError(self_); + } +} + +/*! \brief Executes the script(s). + * + * \param self Instance pointer of the CNodeScriptManagement + * \return Possible return values are: + * - \c UCS_RET_SUCCESS if the execution was started successfully + * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available + * - \c UCS_RET_ERR_NOT_AVAILABLE Timer is not available for pausing the script process + */ +static Ucs_Return_t Nsm_Start(CNodeScriptManagement * self) +{ + Ucs_Return_t result; + + /* Inits internal result */ + MISC_MEM_SET(&self->curr_internal_result, 0, sizeof(Nsm_Result_t)); + + /* Sets the pause for the current script */ + self->curr_pause = self->curr_sript_ptr->pause; + + if (Nsm_IsCurrDeviceSynced(self)) + { + result = Nsm_HandleNextScript(self); + } + else + { + result = Nsm_DeviceSync(self); + } + + return result; +} + +/*! \brief Handles, if available, the next script in the list. + * \param self Instance pointer + * \return UCS_RET_SUCCESS script was transmitted successfully + * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available + * \return UCS_RET_ERR_PARAM Script to be executed is NULL + * \return UCS_RET_ERR_NOT_AVAILABLE Timer is not available for pausing the script process + */ +static Ucs_Return_t Nsm_HandleNextScript(CNodeScriptManagement * self) +{ + Ucs_Return_t result = UCS_RET_SUCCESS; + + if (Nsm_IsNextScriptAvailable(self)) + { + if (self->curr_pause > 0U) + { + result = Nsm_PauseScript(self); + } + else + { + result = Nsm_SendCurrScriptToTrcv(self); + if (result != UCS_RET_SUCCESS) + { + Srv_SetEvent(&self->nsm_srv, NSM_EVENT_HANDLE_ERROR); + TR_ERROR((self->base_ptr->ucs_user_ptr, "[NSM]", "Synchronous error occurred while sending script to Transceiver. ErrorCode:0x%02.", 1U, result)); + } + else + { + TR_INFO((self->base_ptr->ucs_user_ptr, "[NSM]", "Start transfer of script [0x%X] to Trcvr", 1U, self->curr_sript_ptr)); + if ((self->curr_sript_ptr != NULL) && (self->curr_sript_ptr->exp_result == NULL) && + (!self->is_private_api_used)) + { + TR_ERROR((self->base_ptr->ucs_user_ptr, "[NSM]", "Expected_Result_Ptr is NULL. No expected result specified in the current script [0x%X].", 1U, self->curr_sript_ptr)); + } + } + } + } + else + { + Nsm_Finished(self); + } + + return result; +} + +/*! \brief Checks whether the next script is available. + * \param self Instance pointer + * \return \c true if script still available otherwise \c false. + */ +static bool Nsm_IsNextScriptAvailable(CNodeScriptManagement * self) +{ + return (self->curr_sript_size > 0U); +} + +/*! \brief Sets the current script_ptr to the next script if available and decrements the size of script table. + * \param self Instance pointer + */ +static void Nsm_IncrCurrScriptPtr(CNodeScriptManagement * self) +{ + if (self->curr_sript_size > 0U) + { + self->curr_sript_size--; + self->curr_sript_ptr++; + if (self->curr_sript_ptr != NULL) + { + self->curr_pause = self->curr_sript_ptr->pause; + } + else + { + TR_ERROR((self->base_ptr->ucs_user_ptr, "[NSM]", "Corrupted data: Next script is NULL although current script size is greater than 0.", 0U)); + } + } +} + +/*! \brief Synchronizes to the remote target device + * \param self Instance pointer + * \return Possible return values are shown in the table below. + * Value | Description + * ------------------------- | ------------------------------------ + * UCS_RET_SUCCESS | No error + * UCS_RET_ERR_BUFFER_OVERFLOW | no message buffer available + */ +static Ucs_Return_t Nsm_DeviceSync(CNodeScriptManagement * self) +{ + Ucs_Return_t result; + + result = Rsm_SyncDev(self->rsm_ptr, self, &Nsm_RmtDevSyncResultCb); + if(result == UCS_RET_SUCCESS) + { + TR_INFO((self->base_ptr->ucs_user_ptr, "[NSM]", "Start Synchronization of remote device", 0U)); + } + + return result; +} + +/*! \brief Transmits the current script_ptr to the RCM transceiver + * \param self Instance pointer + * \return UCS_RET_SUCCESS script was transmitted successfully + * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available + * \return UCS_RET_ERR_PARAM Script to be executed is NULL + * \return UCS_RET_ERR_API_LOCKED RCM Transceiver is currently locked + */ +static Ucs_Return_t Nsm_SendCurrScriptToTrcv(CNodeScriptManagement * self) +{ + Ucs_Return_t result = UCS_RET_ERR_API_LOCKED; + + if (Al_Lock(&self->lock.rcm_api, NSM_RCMTX_API_LOCK) != false) + { + result = UCS_RET_ERR_PARAM; + if ((self->curr_sript_ptr != NULL) && (self->curr_sript_ptr->send_cmd != NULL)) + { + Ucs_Ns_ConfigMsg_t * tmp_snd_cmd = self->curr_sript_ptr->send_cmd; + Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->rcm_ptr, tmp_snd_cmd->DataLen); + result = UCS_RET_ERR_BUFFER_OVERFLOW; + + if (msg_ptr != NULL) + { + uint8_t k = 0U; + result = UCS_RET_SUCCESS; + + msg_ptr->destination_addr = self->target_address; + msg_ptr->id.fblock_id = tmp_snd_cmd->FBlockId; + msg_ptr->id.instance_id = tmp_snd_cmd->InstId; + msg_ptr->id.function_id = tmp_snd_cmd->FunktId; + msg_ptr->id.op_type = (Ucs_OpType_t)tmp_snd_cmd->OpCode; + + if ((tmp_snd_cmd->DataLen > 0U) && (tmp_snd_cmd->DataPtr == NULL)) + { + result = UCS_RET_ERR_PARAM; + } + + for (; ((k < tmp_snd_cmd->DataLen) && (result == UCS_RET_SUCCESS)); k++) + { + msg_ptr->tel.tel_data_ptr[k] = tmp_snd_cmd->DataPtr[k]; + } + Trcv_TxSendMsgExt(self->rcm_ptr, msg_ptr, &Nsm_MsgTxStatusCb, self); + } + else + { + result = UCS_RET_ERR_BUFFER_OVERFLOW; + } + } + + if (result != UCS_RET_SUCCESS) + { + Al_Release(&self->lock.rcm_api, NSM_RCMTX_API_LOCK); + } + } + + return result; +} + +/*! \brief Check if the current device is already attached respectively sync'ed. + * \param self Instance pointer + * \return \c true if no error occurred, otherwise \c false. + */ +static bool Nsm_IsCurrDeviceSynced(CNodeScriptManagement *self) +{ + bool ret_val = true; + + if (Rsm_GetDevState(self->rsm_ptr) == RSM_DEV_UNSYNCED) + { + ret_val = false; + } + + return ret_val; +} + +/*! \brief Handles the error event + * \param self Instance pointer + */ +static void Nsm_HandleError(CNodeScriptManagement * self) +{ + self->curr_internal_result.code = UCS_NS_RES_ERROR; + Nsm_SendScriptResult(self); +} + +/*! \brief Informs user that the transfer of the current script is completed. + * \param self Instance pointer + */ +static void Nsm_Finished(CNodeScriptManagement * self) +{ + self->curr_internal_result.code = UCS_NS_RES_SUCCESS; + Nsm_SendScriptResult(self); +} + +/*! \brief Transmits the script result to the user callback. + * \param self Instance pointer + */ +static void Nsm_SendScriptResult(CNodeScriptManagement *self) +{ + Nsm_ApiLocking(self, false); + self->curr_rxfilter_fptr = NULL; + self->curr_sript_ptr = NULL; + if (self->is_private_api_used) + { + if (self->curr_pv_result_fptr != NULL) + { + self->curr_pv_result_fptr(self->curr_user_ptr, self->curr_internal_result); + } + } + else + { + if (self->curr_pb_result_fptr != NULL) + { + self->curr_pb_result_fptr(self->curr_node_ptr, self->curr_internal_result.code, self->base_ptr->ucs_user_ptr); + } + } +} + +/*! \brief Starts the timer for pausing the script. + * \param self Instance pointer + * \return UCS_RET_SUCCESS Timer was started successfully + * \return UCS_RET_ERR_NOT_AVAILABLE Timer is not available for pausing the script process + */ +static Ucs_Return_t Nsm_PauseScript(CNodeScriptManagement * self) +{ + Ucs_Return_t ret_val = UCS_RET_ERR_NOT_AVAILABLE; + + if(T_IsTimerInUse(&self->script_pause) == false) + { + ret_val = UCS_RET_SUCCESS; + + Tm_SetTimer(self->tm_ptr, + &self->script_pause, + &Nsm_ResumeScriptHandling, + self, + self->curr_pause, + 0U); + TR_INFO((self->base_ptr->ucs_user_ptr, "[NSM]", "Start pause for %d ms", 1U, self->curr_pause)); + } + + return ret_val; +} + +/*! \brief Locks/Unlocks the RTM API. + * \param self Instance pointer + * \param status Locking status. \c true = Lock, \c false = Unlock + */ +static void Nsm_ApiLocking(CNodeScriptManagement *self, bool status) +{ + self->lock.api = status; +} + +/*! \brief Checks if the API is locked. + * \param self Instance pointer + * \return \c true if the API is not locked, otherwise \c false. + */ +static bool Nsm_IsApiFree(CNodeScriptManagement *self) +{ + return (self->lock.api == false); +} + +/*------------------------------------------------------------------------------------------------*/ +/* Callback Functions */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Called if UCS initialization has been succeeded. + * \param self Instance pointer + * \param event_ptr Reference to reported event + */ +static void Nsm_UcsInitSucceededCb(void *self, void *event_ptr) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + MISC_UNUSED(event_ptr); + + /* Remove ucsinit_observer */ + Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucsinit_observer); +} + +/*! \brief Handles an API timeout + * \param self Instance pointer + * \param method_mask_ptr Bitmask to signal which API method has caused the timeout + */ +static void Nsm_HandleApiTimeout(void *self, void *method_mask_ptr) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + Alm_ModuleMask_t method_mask = *((Alm_ModuleMask_t *)method_mask_ptr); + + if ((method_mask & NSM_RCMTX_API_LOCK) == NSM_RCMTX_API_LOCK) + { + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_ERROR); + TR_ERROR((self_->base_ptr->ucs_user_ptr, "[NSM]", "API locking timeout occurred for Nsm_Start() method.", 0U)); + } +} + +/*! \brief Handle internal errors and un-initialize NSM service. + * \param self Instance pointer + * \param error_code_ptr Reference to internal error code + */ +static void Nsm_UninitializeService(void *self, void *error_code_ptr) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + MISC_UNUSED(error_code_ptr); + + /* Remove NSM service from schedulers list */ + (void)Scd_RemoveService(&self_->base_ptr->scd, &self_->nsm_srv); + /* Remove error/event observers */ + Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucstermination_observer); +} + +/*! \brief Handle message Tx status, Unlock the API and free the message objects + * \param self The instance + * \param tel_ptr Reference to transmitted message + * \param status Status of the transmitted message + */ +static void Nsm_MsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + + if (status != UCS_MSG_STAT_OK) + { + /* Set detailed result */ + self_->curr_internal_result.details.result_type = NS_RESULT_TYPE_TX; + self_->curr_internal_result.details.tx_result = status; + + Al_Release(&self_->lock.rcm_api, NSM_RCMTX_API_LOCK); + /* Set Handling error */ + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_ERROR); + TR_ERROR((self_->base_ptr->ucs_user_ptr, "[NSM]", "Transmission error occurred. ErrorCode:0x%02.", 1U, status)); + } + Trcv_TxReleaseMsg(tel_ptr); +} + +/*! \brief Handles the result of "device.sync" operations. + * \param self Instance pointer + * \param result RSM result + */ +static void Nsm_RmtDevSyncResultCb(void *self, Rsm_Result_t result) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + if (result.code == RSM_RES_SUCCESS) + { + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_NEXTSCRIPT); + TR_INFO((self_->base_ptr->ucs_user_ptr, "[NSM]", "Remote device has been successfully synchronized.", 0U)); + } + else + { + /* Set internal result for private use */ + self_->curr_internal_result.details.inic_result = result.details.inic_result; + self_->curr_internal_result.details.tx_result = result.details.tx_result; + if (result.details.tx_result != UCS_MSG_STAT_OK) + { + self_->curr_internal_result.details.result_type = NS_RESULT_TYPE_TX; + } + else + { + self_->curr_internal_result.details.result_type = NS_RESULT_TYPE_TGT_SYNC; + } + + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_ERROR); + if (result.details.inic_result.code == UCS_RES_ERR_TRANSMISSION) + { + TR_ERROR((self_->base_ptr->ucs_user_ptr, "[NSM]", "Synchronization to the remote device failed due to transmission error. ErrorCode: 0x%02X", 1U, result.details.inic_result.code)); + } + else + { + TR_ERROR((self_->base_ptr->ucs_user_ptr, "[NSM]", "Synchronization to the remote device failed due to error on target device. ErrorCode: 0x%02X", 1U, result.details.inic_result.code)); + } + } +} + +/*! \brief Resumes the handling of script. This method is the callback function of the NSM timer. + * \param self Instance pointer + */ +static void Nsm_ResumeScriptHandling(void* self) +{ + CNodeScriptManagement *self_ = (CNodeScriptManagement *)self; + self_->curr_pause = 0U; + Srv_SetEvent(&self_->nsm_srv, NSM_EVENT_HANDLE_NEXTSCRIPT); + TR_INFO((self_->base_ptr->ucs_user_ptr, "[NSM]", "Pause completed. Resume handling of scripts", 0U)); +} + +/*! + * @} + * \endcond + */ +/*------------------------------------------------------------------------------------------------*/ +/* End of file */ +/*------------------------------------------------------------------------------------------------*/ + |