diff options
Diffstat (limited to 'ucs2-lib/src')
54 files changed, 0 insertions, 33150 deletions
diff --git a/ucs2-lib/src/CMakeLists.txt b/ucs2-lib/src/CMakeLists.txt deleted file mode 100644 index 1aedb22..0000000 --- a/ucs2-lib/src/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -########################################################################### -# Copyright 2015, 2016, 2017 IoT.bzh -# -# author: Fulup Ar Foll <fulup@iot.bzh> -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -########################################################################### - -# Add target to project dependency list -PROJECT_TARGET_ADD(ucs2-lib) - -# Define targets source files -ADD_LIBRARY(ucs2-lib STATIC ucs_alm.c ucs_amd.c ucs_ams.c ucs_amsmessage.c ucs_amspool.c ucs_amtp.c ucs_attach.c ucs_base.c ucs_bc_diag.c ucs_class.c ucs_cmd.c ucs_dec.c ucs_dl.c ucs_eh.c ucs_encoder.c ucs_epm.c ucs_exc.c ucs_factory.c ucs_fsm.c ucs_gpio.c ucs_i2c.c ucs_inic.c ucs_inic_res.c ucs_jobs.c ucs_lldpool.c ucs_message.c ucs_mgr.c ucs_misc.c ucs_net.c ucs_nodedis.c ucs_nodeobserver.c ucs_nsm.c ucs_obs.c ucs_pmchannel.c ucs_pmcmd.c ucs_pmevent.c ucs_pmfifo.c ucs_pmfifos.c ucs_pmp.c ucs_pool.c ucs_prog.c ucs_rsm.c ucs_rtm.c ucs_scheduler.c ucs_segmentation.c ucs_smm.c ucs_sys_diag.c ucs_telqueue.c ucs_timer.c ucs_transceiver.c ucs_xrm.c ucs_xrmpool.c ucs_xrm_res.c) - - # Expose Library Properties - SET_TARGET_PROPERTIES(ucs2-lib PROPERTIES OUTPUT_NAME ucs2net) - - # Library dependencies from PKG_REQUIRED_LIST - TARGET_LINK_LIBRARIES(ucs2-lib ${link_libraries}) - - # Define properties to expose when others use this target - TARGET_INCLUDE_DIRECTORIES(ucs2-lib - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/../inc - ${CMAKE_CURRENT_SOURCE_DIR}/../cfg - ${CMAKE_CURRENT_SOURCE_DIR}/ucs-xml - ) - diff --git a/ucs2-lib/src/ucs_alm.c b/ucs2-lib/src/ucs_alm.c deleted file mode 100644 index 972402d..0000000 --- a/ucs2-lib/src/ucs_alm.c +++ /dev/null @@ -1,275 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 API locking manager. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_ALM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_alm.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constant */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Interval for garbage collection */ -static const uint16_t ALM_GARBAGE_COLLECTOR_INTERVAL = 2600U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Alm_HandleInternalErrors(void *self, void *error_code_ptr); -static void Alm_GarbageCollector(void *self); -static bool Alm_CheckRegisteredApi(void *current_alm_ptr, void *alm_inst_ptr); -static void Alm_StartTimeout(CApiLockingManager *self); -static void Alm_ClearTimeout(CApiLockingManager *self); -static bool Alm_SearchLockedApi(void *current_alm_ptr, void *alm_inst_ptr); -static void Alm_ResetRegisteredApis(CApiLockingManager *self); -static bool Alm_ResetApi(void *current_alm_ptr, void *alm_inst_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CApiLockingManager */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the API locking manager class. - * \param self Instance pointer - * \param tm_ptr Reference to timer management instance - * \param eh_ptr Reference to event handler instance - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Alm_Ctor(CApiLockingManager *self, - CTimerManagement *tm_ptr, - CEventHandler *eh_ptr, - void * ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - T_Ctor(&self->garbage_collector); - self->tm_ptr = tm_ptr; - self->eh_ptr = eh_ptr; - self->ucs_user_ptr = ucs_user_ptr; - - /* Observe internal errors and events */ - Mobs_Ctor(&self->internal_error_obs, self, EH_M_TERMINATION_EVENTS, &Alm_HandleInternalErrors); - Eh_AddObsrvInternalEvent(self->eh_ptr, &self->internal_error_obs); -} - -/*! \brief Handles internal errors and events - * \param self Instance pointer - * \param error_code_ptr Reference to reported error code - */ -static void Alm_HandleInternalErrors(void *self, void *error_code_ptr) -{ - CApiLockingManager *self_ = (CApiLockingManager *)self; - MISC_UNUSED(error_code_ptr); - - Tm_ClearTimer(self_->tm_ptr, &self_->garbage_collector); /* Clear timeout */ - Alm_ResetRegisteredApis(self_); /* Reset all registered APIs */ -} - -/*! \brief Checks for API locking timeouts. This method is the callback function of timer - * \c garbage_collector. - * \param self Instance pointer - */ -static void Alm_GarbageCollector(void *self) -{ - CApiLockingManager *self_ = (CApiLockingManager *)self; - (void)Dl_Foreach(&self_->api_list, &Alm_CheckRegisteredApi, self_); -} - -/*! \brief This method is used by Alm_GarbageCollector() to process each registered API. - * \param current_alm_ptr Reference to the current API - * \param alm_inst_ptr Instance of the API locking manager - * \return \c false to process all registered APIs - */ -static bool Alm_CheckRegisteredApi(void *current_alm_ptr, void *alm_inst_ptr) -{ - CApiLockingManager *self = (CApiLockingManager *)alm_inst_ptr; - CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr; - MISC_UNUSED(self); - - if(alm_ptr_->timeout_mask != 0U) - { - Alm_ModuleMask_t tmp_mask = 1U; - while(alm_ptr_->timeout_mask != 0U) - { - if(tmp_mask == (tmp_mask & alm_ptr_->timeout_mask)) - { - Ssub_Notify(&alm_ptr_->subject, &tmp_mask, false); - alm_ptr_->method_mask &= ~tmp_mask; - alm_ptr_->timeout_mask &= ~tmp_mask; - } - tmp_mask <<= 1; - } - Alm_ClearTimeout(self); - } - if(alm_ptr_->method_mask != 0U) - { - alm_ptr_->timeout_mask = alm_ptr_->method_mask; - } - return false; -} - -/*! \brief Registers a new API locking object. - * \param self Instance pointer - * \param al_ptr Reference to the API to register - */ -void Alm_RegisterApi(CApiLockingManager *self, CApiLocking *al_ptr) -{ - Dl_InsertTail(&self->api_list, &al_ptr->node); - Dln_SetData(&al_ptr->node, al_ptr); - al_ptr->alm_ptr = self; -} - -/*! \brief Starts the garbage collecting timer. - * \param self Instance pointer - */ -static void Alm_StartTimeout(CApiLockingManager *self) -{ - if(T_IsTimerInUse(&self->garbage_collector) == false) - { - Tm_SetTimer(self->tm_ptr, - &self->garbage_collector, - &Alm_GarbageCollector, - self, - ALM_GARBAGE_COLLECTOR_INTERVAL, - ALM_GARBAGE_COLLECTOR_INTERVAL); - } -} - -/*! \brief Clears the garbage collecting timer. The timer is clear if no API locking flag is - * currently pending. - * \param self Instance pointer - */ -static void Alm_ClearTimeout(CApiLockingManager *self) -{ - if(Dl_Foreach(&self->api_list, &Alm_SearchLockedApi, self) == NULL) - { - Tm_ClearTimer(self->tm_ptr, &self->garbage_collector); - } -} - -/*! \brief Used by Alm_ClearTimeout() to check if at least one registered API is locked. - * \param current_alm_ptr Reference to the current API locking object - * \param alm_inst_ptr Instance of the API locking manager - * \return \c true if a locked API was found, otherwise \c false - */ -static bool Alm_SearchLockedApi(void *current_alm_ptr, void *alm_inst_ptr) -{ - CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr; - bool ret_val = false; - MISC_UNUSED(alm_inst_ptr); - - if(alm_ptr_->method_mask != 0U) - { - ret_val = true; - } - return ret_val; -} - -/*! \brief Resets all registered APIs. Called if an internal error has been occurred. - * \param self Instance pointer - */ -static void Alm_ResetRegisteredApis(CApiLockingManager *self) -{ - (void)Dl_Foreach(&self->api_list, &Alm_ResetApi, self); -} - -/*! \brief Used by Alm_ResetRegisteredApis() to reset all registered APIs. - * \param current_alm_ptr Reference to the current API locking object - * \param alm_inst_ptr Instance of the API locking manager - * \return \c false (process all registered APIs) - */ -static bool Alm_ResetApi(void *current_alm_ptr, void *alm_inst_ptr) -{ - CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr; - MISC_UNUSED(alm_inst_ptr); - - alm_ptr_->method_mask = 0U; - alm_ptr_->timeout_mask = 0U; - - return false; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CApiLocking */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the API locking class. - * \param self Instance pointer - * \param obs_ptr Observer to signal locked API methods - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Al_Ctor(CApiLocking *self, CSingleObserver *obs_ptr, void * ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->ucs_user_ptr = ucs_user_ptr; - Dln_Ctor(&self->node, NULL); - if(obs_ptr != NULL) - { - Ssub_Ctor(&self->subject, self->ucs_user_ptr); - (void)Ssub_AddObserver(&self->subject, obs_ptr); - } -} - -/*! \brief Locks the given API method. - * \param self Instance pointer - * \param method Bitmask of method to lock - * \return \c true if the API has been locked successfully - * \return \c false if the API was already locked - */ -bool Al_Lock(CApiLocking *self, Alm_ModuleMask_t method) -{ - bool ret_val = false; - if((self->method_mask & method) == 0U) - { - ret_val = true; - self->method_mask |= method; - self->timeout_mask &= ~method; - Alm_StartTimeout(self->alm_ptr); - } - return ret_val; -} - -/*! \brief Releases the lock of the given API method. - * \param self Instance pointer - * \param method Bitmask of method to lock - */ -void Al_Release(CApiLocking *self, Alm_ModuleMask_t method) -{ - self->method_mask &= ~method; - self->timeout_mask &= ~method; - Alm_ClearTimeout(self->alm_ptr); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_amd.c b/ucs2-lib/src/ucs_amd.c deleted file mode 100644 index c4d3456..0000000 --- a/ucs2-lib/src/ucs_amd.c +++ /dev/null @@ -1,570 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Application Message Distributor - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMD - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_amd.h" -#include "ucs_misc.h" - -/*! \brief Priority of the Application Message Distribution */ -static const uint8_t AMD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ -/*! \brief Event which starts the Rx message distribution */ -static const Srv_Event_t AMD_EV_NOTIFY_RX = 1U; -/*! \brief Event triggers notification of messages in tx_notify_queue */ -static const Srv_Event_t AMD_EV_NOTIFY_TX = 2U; -/*! \brief FBlockID of FBlock NetBlock */ -static const uint8_t AMD_FB_NETBLOCK = 1U; -/*! \brief FBlockID of FBlock NetworkMaster */ -static const uint8_t AMD_FB_NETWORKMASTER = 2U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Amd_Service(void *self); -static void Amd_OnAmsComplete(void* self, Ucs_AmsRx_Msg_t* msg_ptr); -static void Amd_OnEvent(void *self, void *error_code_ptr); -static void Amd_OnTerminateEvent(void *self, void *error_code_ptr); -static void Amd_RxFlush(CAmd *self, CDlList *list_ptr); -#ifdef AMD_TX_DISTRIB -static bool Amd_TxIsRcmMsg(Ucs_AmsTx_Msg_t *msg_ptr); -static bool Amd_TxReceiveInternal(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr); -static void Amd_TxProcessNotifyQueue(CAmd *self); -#endif - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CAmd - * \param self The instance - * \param base_ptr Reference to base services - * \param ams_ptr Reference to the AMS - */ -void Amd_Ctor(CAmd *self, CBase *base_ptr, CAms *ams_ptr) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */ - - self->base_ptr = base_ptr; - self->ams_ptr = ams_ptr; - - self->started = false; - Srv_Ctor(&self->service, AMD_SRV_PRIO, self, &Amd_Service); /* register service */ - (void)Scd_AddService(&self->base_ptr->scd, &self->service); - - Dl_Ctor(&self->pre_queue, self->base_ptr->ucs_user_ptr); /* init preprocessor queue */ - Dl_Ctor(&self->rx_queue, self->base_ptr->ucs_user_ptr); /* init Rx queue */ - /* register event observer */ - Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Amd_OnEvent); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer); - /* register termination events */ - Mobs_Ctor(&self->terminate_observer, self, EH_M_TERMINATION_EVENTS, &Amd_OnTerminateEvent); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->terminate_observer); - - Ams_RxAssignReceiver(self->ams_ptr, &Amd_OnAmsComplete, self); -} - - -#ifdef AMD_TX_DISTRIB -/*! \brief Constructor of class CAmd - * \param self The instance - * \param base_ptr Reference to base services - * \param ams_ptr Reference to the AMS - * \param pool_ptr Reference to the AMS message pool - * \param inic_ptr Reference to the INIC - * \param net_ptr Reference to the network management - */ -void Amd_Ctor(CAmd *self, CBase *base_ptr, CAms *ams_ptr, CAmsMsgPool *pool_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */ - - self->base_ptr = base_ptr; - self->ams_ptr = ams_ptr; - self->pool_ptr = pool_ptr; - self->inic_ptr = inic_ptr; - self->net_ptr = net_ptr; - - self->started = false; - Srv_Ctor(&self->service, AMD_SRV_PRIO, self, &Amd_Service); /* register service */ - (void)Scd_AddService(&self->base_ptr->scd, &self->service); - - Dl_Ctor(&self->tx_notify_queue, self->base_ptr->ucs_inst_id); /* init queues */ - Dl_Ctor(&self->pre_queue, self->base_ptr->ucs_inst_id); /* init preprocessor queue */ - Dl_Ctor(&self->rx_queue, self->base_ptr->ucs_inst_id); /* init Rx queue */ - /* register event observer */ - Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Amd_OnEvent); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer); - /* register termination events */ - Mobs_Ctor(&self->terminate_observer, self, EH_M_TERMINATION_EVENTS, &Amd_OnTerminateEvent); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->terminate_observer); - - Ams_RxAssignReceiver(self->ams_ptr, &Amd_OnAmsComplete, self); - Ams_TxAssignTrcvSelector(self->ams_ptr, &Amd_TxIsRcmMsg); -} -#endif - -/*! \brief Assigns a pre-processor callback function for Rx messages - * \details This function must be called during initialization time. - * The AMS shall not already run. - * \param self The instance - * \param callback_fptr Reference to the callback function - * \param inst_ptr Reference to the pre-processor - */ -void Amd_AssignPreprocessor(CAmd *self, Amd_RxMsgCompleteCb_t callback_fptr, void *inst_ptr) -{ - if (callback_fptr != NULL) - { - self->preprocess_fptr = callback_fptr; - self->preprocess_inst_ptr = inst_ptr; - - self->first_receive_fptr = callback_fptr; - self->first_receive_inst_ptr = inst_ptr; - self->first_q_ptr = &self->pre_queue; - } -} - -/*! \brief Assigns a receiver callback function for Rx messages - * \details This function must be called during initialization time. - * The AMS shall not already run. - * \param self The instance - * \param callback_fptr Reference to the callback function - * \param inst_ptr Reference to the receiver - */ -void Amd_AssignReceiver(CAmd *self, Amd_RxMsgCompleteCb_t callback_fptr, void *inst_ptr) -{ - if (callback_fptr != NULL) - { - self->receive_fptr = callback_fptr; - self->receive_inst_ptr = inst_ptr; - - if (self->first_receive_fptr == NULL) - { - self->first_receive_fptr = callback_fptr; - self->first_receive_inst_ptr = inst_ptr; - self->first_q_ptr = &self->rx_queue; - } - } -} - -/*! \brief Assigns as callback function which is able to read and modify the Rx message - * \param self The instance - * \param callback_fptr Reference to the callback function - * \param inst_ptr Reference to the instance (owner of the callback function) - */ -void Amd_RxAssignModificator(CAmd *self, Amd_RxModificationCb_t callback_fptr, void *inst_ptr) -{ - if (callback_fptr != NULL) - { - self->rx_modification_fptr = callback_fptr; - self->rx_modification_inst_ptr = inst_ptr; - } -} - -/*! \brief Service function of CAmd - * \details The processing of the Rx queues shall be started asynchronously - * after the initialization has succeeded. - * \param self The instance - */ -static void Amd_Service(void *self) -{ - CAmd *self_ = (CAmd*)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->service, &event_mask); - - if((event_mask & AMD_EV_NOTIFY_RX) == AMD_EV_NOTIFY_RX) /* triggered on internal transmission */ - { - Srv_ClearEvent(&self_->service, AMD_EV_NOTIFY_RX); - if ((self_->started != false) && (self_->first_receive_fptr != NULL)) - { - uint16_t size = Dl_GetSize(self_->first_q_ptr); - if (size > 0U) - { - self_->first_receive_fptr(self_->first_receive_inst_ptr); - } - } - } - -#ifdef AMD_TX_DISTRIB - if((event_mask & AMD_EV_NOTIFY_TX) == AMD_EV_NOTIFY_TX) /* notify Tx distribution failure asynchronously */ - { - Srv_ClearEvent(&self_->service, AMD_EV_NOTIFY_TX); - Amd_TxProcessNotifyQueue(self_); - } -#endif -} - -/*------------------------------------------------------------------------------------------------*/ -/* Events */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Callback function which is invoked on completed application message reception - * \param self The instance - * \param msg_ptr Reference to the completed application message - */ -static void Amd_OnAmsComplete(void *self, Ucs_AmsRx_Msg_t *msg_ptr) -{ - CAmd *self_ = (CAmd*)self; - - if (self_->rx_modification_fptr != NULL) - { - self_->rx_modification_fptr(self_->rx_modification_inst_ptr, msg_ptr); - } - - if (self_->first_receive_fptr != NULL) - { - Amsg_RxEnqueue(msg_ptr, self_->first_q_ptr); - - if (self_->started != false) - { - self_->first_receive_fptr(self_->first_receive_inst_ptr); - } - } - else - { - Ams_RxFreeMsg(self_->ams_ptr, msg_ptr); - } -} - -/*! \brief Callback function if an events leads to the termination of the MNS - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Amd_OnTerminateEvent(void *self, void *error_code_ptr) -{ - CAmd *self_ = (CAmd*)self; - MISC_UNUSED(error_code_ptr); - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Starting AMD Cleanup", 0U)); - Amd_RxFlush(self_, &self_->pre_queue); - Amd_RxFlush(self_, &self_->rx_queue); -#ifdef AMD_TX_DISTRIB - Amd_TxProcessNotifyQueue(self_); -#endif - TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Finished AMD Cleanup", 0U)); -} - -/*! \brief Callback function which is invoked if the initialization is complete - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Amd_OnEvent(void *self, void *error_code_ptr) -{ - CAmd *self_ = (CAmd*)self; - MISC_UNUSED(error_code_ptr); - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Received init complete event", 0U)); - self_->started = true; - Srv_SetEvent(&self_->service, AMD_EV_NOTIFY_RX); -} - -/*! \brief Flushes a given application Rx message queue - * \param self The instance - * \param list_ptr Reference to a list containing application Rx message objects - */ -static void Amd_RxFlush(CAmd *self, CDlList *list_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr; - - for (msg_ptr = Amsg_RxDequeue(list_ptr); msg_ptr != NULL; msg_ptr = Amsg_RxDequeue(list_ptr)) - { - Ams_RxFreeMsg(self->ams_ptr, msg_ptr); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Pre-processor methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Peeks the front-most application message from the preprocessing queue - * \param self The instance - * \return Returns a reference to the front-most application message or \c NULL if the queue - * is empty. - */ -Ucs_AmsRx_Msg_t* Amd_PrePeekMsg(CAmd *self) -{ - return (Ucs_AmsRx_Msg_t*)(void*)Amsg_RxPeek(&self->pre_queue); -} - -/*! \brief Removes the front-most application message from the preprocessing queue and frees it - * \param self The instance - */ -void Amd_PreReleaseMsg(CAmd *self) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->pre_queue); - - if (msg_ptr != NULL) - { - Ams_RxFreeMsg(self->ams_ptr, msg_ptr); - } -} - -/*! \brief Forwards the front-most application message from the preprocessing queue to the Rx queue - * \param self The instance - */ -void Amd_PreForwardMsg(CAmd *self) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->pre_queue); - - if (msg_ptr != NULL) - { - if (self->receive_fptr != NULL) - { - Amsg_RxEnqueue(msg_ptr, &self->rx_queue); - self->receive_fptr(self->receive_inst_ptr); - } - else - { - Ams_RxFreeMsg(self->ams_ptr, msg_ptr); - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Receiver methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Peeks the front-most application message from the Rx queue - * \param self The instance - * \return Returns a reference to the front-most application message or \c NULL if the queue - * is empty. - */ -Ucs_AmsRx_Msg_t* Amd_RxPeekMsg(CAmd *self) -{ - return (Ucs_AmsRx_Msg_t*)(void*)Amsg_RxPeek(&self->rx_queue); -} - -/*! \brief Removes the front-most application message from the Rx queue and frees it - * \param self The instance - */ -void Amd_RxReleaseMsg(CAmd *self) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->rx_queue); - - if (msg_ptr != NULL) - { - Ams_RxFreeMsg(self->ams_ptr, msg_ptr); - } -} - -/*! \brief Retrieves the number of messages which are appended to the Rx queue - * \param self The instance - * \return Returns the number of messages. - */ -uint16_t Amd_RxGetMsgCnt(CAmd *self) -{ - return Dl_GetSize(&self->rx_queue); -} - -#ifdef AMD_TX_DISTRIB -/*------------------------------------------------------------------------------------------------*/ -/* Transmitter methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Distributes a Tx message internally as Rx message - * \param self The instance - * \param msg_ptr The Tx message - * \param tx_complete_sia_fptr Single instance API callback function which is invoked as soon as - * the transmission was finished. - * \param tx_complete_fptr Multi instance callback function which is invoked as soon as - * the transmission was finished. - * \param tx_complete_inst_ptr Instance pointer which is referred when tx_complete_fptr is invoked. - * \return Returns \c UCS_RET_SUCCESS if the message accepted for transmission. - * Returns \c UCS_RET_ERR_PARAM if the message is refused due to invalid message attributes. - */ -Ucs_Return_t Amd_TxSendMsg(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr, Amsg_TxCompleteSiaCb_t tx_complete_sia_fptr, - Amsg_TxCompleteCb_t tx_complete_fptr, void* tx_complete_inst_ptr) -{ - Ucs_Return_t ret = UCS_RET_SUCCESS; - bool tx_internal = false; - bool tx_network = false; - bool tx_ignore_nw_failure = false; - bool tx_check_ni = true; /* if false, transmit to INIC even during NET_OFF */ - - if (Ams_TxIsValidMessage(msg_ptr) != false) - { - Net_IsOwnAddrResult_t addr_type = Net_IsOwnAddress(self->net_ptr, msg_ptr->destination_address); - - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (((tx_complete_sia_fptr != NULL) && (tx_complete_fptr != NULL)) == false)); - Amsg_TxSetCompleteCallback(msg_ptr, tx_complete_sia_fptr, tx_complete_fptr, tx_complete_inst_ptr); - - if (msg_ptr->destination_address == UCS_ADDR_INTERNAL) - { - tx_internal = true; /* do not forward internal messages to INIC */ - } - else if ((msg_ptr->fblock_id == AMD_FB_NETBLOCK) || (msg_ptr->fblock_id == AMD_FB_NETWORKMASTER)) - { - if (addr_type == NET_IS_OWN_ADDR_NODE) /* replace own node address by "1" to force INIC internal routing */ - { /* do not replace multicast addresses (these are static and handled by INIC) */ - Amsg_TxReplaceDestinationAddr(msg_ptr, MSG_ADDR_INIC); - } - else if ((addr_type == NET_IS_OWN_ADDR_GROUP) || - (msg_ptr->destination_address == UCS_ADDR_BROADCAST_BLOCKING) || - (msg_ptr->destination_address == UCS_ADDR_BROADCAST_UNBLOCKING)) - { - tx_ignore_nw_failure = true; - } - - tx_network = true; /* route FBlocks NB and NWM to INIC */ - tx_check_ni = false; /* INIC performs checks independent from NI state */ - } - else if ((msg_ptr->destination_address == UCS_ADDR_BROADCAST_BLOCKING) || - (msg_ptr->destination_address == UCS_ADDR_BROADCAST_UNBLOCKING)) - { - tx_internal = true; /* forward broadcast messages to INIC and distribute internally */ - tx_network = true; - } - else - { - switch (addr_type) - { - case NET_IS_OWN_ADDR_NODE: - tx_internal = true; - break; - case NET_IS_OWN_ADDR_GROUP: - tx_internal = true; - tx_network = true; - break; - case NET_IS_OWN_ADDR_NONE: - default: - tx_network = true; - break; - } - } - - if ((Inic_GetAvailability(self->inic_ptr) == UCS_NW_NOT_AVAILABLE) && (tx_check_ni == true)) - { - tx_network = false; /* abort network transmission */ - Amsg_TxUpdateResult(msg_ptr, UCS_MSG_STAT_ERROR_NA_OFF); - } - - if (tx_internal != false) - { - if (Amd_TxReceiveInternal(self, msg_ptr) == false) - { /* internal transmission failed */ - Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_ERRBUF); - } - else - { /* internal transmission succeeded */ - Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_SUCCESS); - } - } - else if (tx_ignore_nw_failure != false) - { /* INIC routing will succeed while NW transmission fails */ - Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_SUCCESS); - } - - if (tx_network == false) - { /* enqueue message to notification queue and set event */ - Amsg_TxEnqueue(msg_ptr, &self->tx_notify_queue); - Srv_SetEvent(&self->service, AMD_EV_NOTIFY_TX); - } - else - { - Ams_TxSendMsgDirect(self->ams_ptr, msg_ptr); - } - } - else - { - ret = UCS_RET_ERR_PARAM; /* invalid message parameters */ - } - - return ret; -} - -/*! \brief Decides whether to root a message to MCM or RCM FIFO - * \param msg_ptr The Tx message object - * \return Returns \c true if a Tx message shall be routed to RCM FIFO, otherwise returns \c false. - */ -static bool Amd_TxIsRcmMsg(Ucs_AmsTx_Msg_t *msg_ptr) -{ - bool ret = false; - if (((msg_ptr->fblock_id == AMD_FB_NETBLOCK) && (msg_ptr->op_type <= UCS_OP_STARTACK)) /* is NB.Command */ - || ((msg_ptr->fblock_id == AMD_FB_NETWORKMASTER) && (msg_ptr->op_type > UCS_OP_STARTACK))) /* or NWM.Report?*/ - { - ret = true; - } - - return ret; -} - -/*! \brief Distributes a Tx message internally as Rx message - * \param self The instance - * \param msg_ptr The Tx message - * \return Returns \c true if the message distributed successfully. - * Returns \c false if the allocation of the Rx message has failed. - */ -static bool Amd_TxReceiveInternal(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr) -{ - bool ret = false; - Ucs_AmsRx_Msg_t *rx_ptr = Amsp_AllocRxObj(self->pool_ptr, msg_ptr->data_size); - - if (rx_ptr != NULL) - { - uint16_t src_addr = UCS_ADDR_INTERNAL; - if (msg_ptr->destination_address != UCS_ADDR_INTERNAL) - { - src_addr = Inic_GetNodeAddress(self->inic_ptr); - } - Amsg_RxBuildFromTx(rx_ptr, msg_ptr, src_addr); - if (self->first_q_ptr != NULL) - { - Amsg_RxEnqueue(rx_ptr, self->first_q_ptr); - Srv_SetEvent(&self->service, AMD_EV_NOTIFY_RX); - ret = true; - } - else - { - Amsp_FreeRxObj(self->pool_ptr, rx_ptr); - TR_FAILED_ASSERT(self->base_ptr->ucs_user_ptr, "[AMD]"); - } - } - - return ret; -} - -/*! \brief Notifies the transmission result for all messages in the tx_notify_queue - * \param self The instance - */ -static void Amd_TxProcessNotifyQueue(CAmd *self) -{ - Ucs_AmsTx_Msg_t *tx_ptr = NULL; - - for (tx_ptr = Amsg_TxDequeue(&self->tx_notify_queue); tx_ptr != NULL; tx_ptr = Amsg_TxDequeue(&self->tx_notify_queue)) - { - /* just just notify completion, the object is automatically freed to the pool */ - Amsg_TxNotifyComplete(tx_ptr, Amsg_TxGetResultCode(tx_ptr), Amsg_TxGetResultInfo(tx_ptr)); - } -} -#endif - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_ams.c b/ucs2-lib/src/ucs_ams.c deleted file mode 100644 index 2df7129..0000000 --- a/ucs2-lib/src/ucs_ams.c +++ /dev/null @@ -1,669 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Application Message Service - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMSC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_ams.h" -#include "ucs_amsmessage.h" -#include "ucs_dl.h" -#include "ucs_misc.h" -#include "ucs_pmp.h" -#include "ucs_encoder.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Priority of the Application Message Service */ -static const uint8_t AMS_SRV_PRIO = 253U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ -/*! \brief Event which triggers the Rx service */ -static const Srv_Event_t AMS_EV_RX_SERVICE = 1U; -/*! \brief Event which triggers the Tx service */ -static const Srv_Event_t AMS_EV_TX_SERVICE = 2U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Ams_Cleanup(CAms *self); -static void Ams_Service(void *self); -static void Ams_OnEhEvent(void *self, void *error_code_ptr); - -static void Ams_TxService(CAms *self); -static void Ams_TxOnStatus(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status); -static uint8_t Ams_TxGetNextFollowerId(CAms *self); - -static void Ams_RxOnTelComplete(CAms *self, Msg_MostTel_t *tel_ptr); -static void Ams_RxReleaseTel(CAms *self, Msg_MostTel_t *tel_ptr); -static void Ams_RxProcessWaitingQ(CAms *self); -static void Ams_RxOnSegError(void *self, Msg_MostTel_t *tel_ptr, Segm_Error_t error); -static void Ams_RxOnFreedMsg(void *self, void *data_ptr); -static void Ams_RxFlush(CAms *self); - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CAms - * \param self The instance - * \param base_ptr Reference to base services - * \param mcm_trcv_ptr Reference to the MCM transceiver - * \param rcm_trcv_ptr Reference to the RCM transceiver - * \param pool_ptr Reference to the pool for application message handles - * \param rx_def_payload_sz Default memory size that is allocated when receiving segmented messages - * without size prefix - */ -void Ams_Ctor(CAms *self, CBase *base_ptr, CTransceiver *mcm_trcv_ptr, CTransceiver *rcm_trcv_ptr, - CAmsMsgPool *pool_ptr, uint16_t rx_def_payload_sz) -{ - MISC_UNUSED(rcm_trcv_ptr); - MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */ - self->trcv_mcm_ptr = mcm_trcv_ptr; - self->trcv_rcm_ptr = rcm_trcv_ptr; - self->base_ptr = base_ptr; - self->pool_ptr = pool_ptr; - - self->tx.default_llrbc = AMS_LLRBC_DEFAULT; /* set initial retries */ - self->tx.next_follower_id = 1U; /* set initial follower id */ - /* init pools */ - Obs_Ctor(&self->rx.message_freed_observer, self, &Ams_RxOnFreedMsg); - Amsp_AssignRxFreedObs(self->pool_ptr, &self->rx.message_freed_observer); - Telq_Ctor(&self->rx.waiting_queue, self->base_ptr->ucs_user_ptr); /* init Rx waiting queue */ - - Dl_Ctor(&self->tx.queue, self->base_ptr->ucs_user_ptr); - - Srv_Ctor(&self->service, AMS_SRV_PRIO, self, &Ams_Service); /* register service */ - (void)Scd_AddService(&self->base_ptr->scd, &self->service); - - Segm_Ctor(&self->segmentation, self->base_ptr, self->pool_ptr, rx_def_payload_sz); - Segm_AssignRxErrorHandler(&self->segmentation, &Ams_RxOnSegError, self); - - if (self->trcv_mcm_ptr != NULL) - { - Trcv_RxAssignReceiver(self->trcv_mcm_ptr, &Ams_RxOnMcmTelComplete, self); - } - if (self->trcv_rcm_ptr != NULL) - { - Trcv_RxAssignReceiver(self->trcv_rcm_ptr, &Ams_RxOnRcmTelComplete, self); - } - - Mobs_Ctor(&self->unsync_result_observer, self, EH_M_TERMINATION_EVENTS, &Ams_OnEhEvent); /* register error observer */ - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->unsync_result_observer); -} - -/*! \brief Sets the default retry values used for Application Messages - * \param self The instance - * \param llrbc The default low level retry block count - */ -void Ams_TxSetDefaultRetries(CAms* self, uint8_t llrbc) -{ - self->tx.default_llrbc = llrbc; -} - -/*! \brief Assigns a function of another class to receive application messages - * \param self The instance - * \param cb_fptr Callback function - * \param inst_ptr The instance of the receiver class - */ -void Ams_RxAssignReceiver(CAms *self, Amsg_RxCompleteCb_t cb_fptr, void *inst_ptr) -{ - self->rx.complete_fptr = cb_fptr; - self->rx.complete_inst_ptr = inst_ptr; -} - -/*! \brief Assigns an observer which is invoked if a Tx application message is freed. - * \details The observer is only notified a previous allocation of a Tx object has failed. - * The data_ptr of the update callback function is not used (always \c NULL). - * See \ref Obs_UpdateCb_t. - * \param self The instance - * \param observer_ptr The observer - */ -void Ams_TxAssignMsgFreedObs(CAms *self, CObserver *observer_ptr) -{ - Amsp_AssignTxFreedObs(self->pool_ptr, observer_ptr); -} - -/*! \brief Assigns a callback function that selects FIFO routing for a Tx message. - * \details If no callback function is assigned, then all Tx messages are routed to RCM FIFO. - * \param self The instance - * \param cb_fptr The callback function - */ -void Ams_TxAssignTrcvSelector(CAms *self, Ams_TxIsRcmMsgCb_t cb_fptr) -{ - self->tx.is_rcm_fptr = cb_fptr; -} - -/*! \brief Performs a cleanup of the Tx message queue and notifies - * the transmission error UCS_AMSTX_RES_NOT_AVAILABLE. - * \param self The instance - */ -static void Ams_Cleanup(CAms *self) -{ - Ucs_AmsTx_Msg_t *tx_ptr = NULL; - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Starting AMS Cleanup", 0U)); - /* cleanup Tx queue */ - for (tx_ptr = Amsg_TxDequeue(&self->tx.queue); tx_ptr != NULL; tx_ptr = Amsg_TxDequeue(&self->tx.queue)) - { - /* just just notify completion, the object is automatically freed to the pool */ - Amsg_TxNotifyComplete(tx_ptr, UCS_AMSTX_RES_ERR_NOT_AVAILABLE, UCS_AMSTX_I_ERR_UNSYNCED); - } - - Segm_Cleanup(&self->segmentation); /* cleanup Rx */ - Ams_RxFlush(self); - Amsp_Cleanup(self->pool_ptr); /* final cleanup of pool */ - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Finished AMS Cleanup", 0U)); -} - -/*! \brief Callback function which is invoked by the event handler - * on any termination event. - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Ams_OnEhEvent(void *self, void *error_code_ptr) -{ - CAms *self_ = (CAms*)self; - MISC_UNUSED(error_code_ptr); - Ams_Cleanup(self_); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief The AMS service function - * \param self The instance - */ -static void Ams_Service(void *self) -{ - CAms *self_ = (CAms*)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->service, &event_mask); - - if ((event_mask & AMS_EV_TX_SERVICE) == AMS_EV_TX_SERVICE) /* Is event pending? */ - { - Srv_ClearEvent(&self_->service, AMS_EV_TX_SERVICE); - Ams_TxService(self_); - } - - if ((event_mask & AMS_EV_RX_SERVICE) == AMS_EV_RX_SERVICE) /* Is event pending? */ - { - Srv_ClearEvent(&self_->service, AMS_EV_RX_SERVICE); - Ams_RxProcessWaitingQ(self_); - } -} - -/*! \brief Allocates and transmits MCMs for the dedicated Application Messages - * \param self The instance - */ -static void Ams_TxService(CAms *self) -{ - CDlNode *node1_ptr; - /* run as long as messages are available in Tx queue */ - for (node1_ptr = Dl_PeekHead(&self->tx.queue); node1_ptr != NULL; node1_ptr = Dl_PeekHead(&self->tx.queue)) - { - Msg_MostTel_t *tel_ptr = NULL; - CTransceiver *trcv_ptr = self->trcv_mcm_ptr; - Ucs_AmsTx_Msg_t *tx_ptr = (Ucs_AmsTx_Msg_t*)Dln_GetData(node1_ptr); - - if (self->tx.is_rcm_fptr != NULL) - { - if (self->tx.is_rcm_fptr(tx_ptr) != false) - { - trcv_ptr = self->trcv_rcm_ptr; - } - } - /* allocate telegram object with 2 bytes for TelId 4 */ - tel_ptr = Trcv_TxAllocateMsg(trcv_ptr, 2U); /* remaining message payload is attached as external memory */ - - if (tel_ptr != NULL) /* transmit message if telegram object is available */ - { - CDlNode *node2_ptr = Dl_PopHead(&self->tx.queue); /* now retrieve application message from queue, previously checked by peek operation */ - - if (node2_ptr != NULL) - { - bool done; - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (node1_ptr == node2_ptr)); - tx_ptr = (Ucs_AmsTx_Msg_t*)Dln_GetData(node2_ptr); - done = Segm_TxBuildSegment(&self->segmentation, tx_ptr, tel_ptr); /* run segmentation */ - Trcv_TxSendMsgExt(trcv_ptr, tel_ptr, &Ams_TxOnStatus, self); /* transmit telegram */ - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Ams_TxService(tel_ptr=0x%p)", 1U, tel_ptr)); - - if (done == false) - { - Dl_InsertHead(&self->tx.queue, node2_ptr); - } - } - else - { - TR_FAILED_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]"); /* inconsistency between peek and pop operation */ - } - } - else - { - break; - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* AMS Tx handles */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Retrieves a message Tx handle - * \details The payload provided is limited the supported size of the memory management. - * The application may also attach own payload to a message object. Therefore, - * Ams_TxGetMsg() shall be called with size "0". - * \param self The instance - * \param size Payload size in bytes or "0" to use application provided payload. - * The payload provided by MNS is limited to a size of 45 bytes. - * Valid values: 0..45. - * \return A Tx message object or \c NULL if no message object is available. - */ -Ucs_AmsTx_Msg_t * Ams_TxGetMsg(CAms *self, uint16_t size) -{ - Ucs_AmsTx_Msg_t * msg_ptr = Amsp_AllocTxObj(self->pool_ptr, size); - - if (msg_ptr != NULL) - { - msg_ptr->destination_address = AMS_ADDR_RSVD_RANGE; /* set invalid address to prevent internal transmission*/ - msg_ptr->llrbc = self->tx.default_llrbc; - } - - return msg_ptr; -} - -/*! \brief Frees an unused or completed Tx message to the pool - * \param self The instance - * \param msg_ptr Reference to the related message object - */ -void Ams_TxFreeUnusedMsg(CAms *self, Ucs_AmsTx_Msg_t *msg_ptr) -{ - MISC_UNUSED(self); - Amsg_TxFreeUnused(msg_ptr); /* the object is automatically freed to the pool */ -} - -/*------------------------------------------------------------------------------------------------*/ -/* AMS Transmission */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Transmits a MOST Application Message - * \details After the transmission completed the function will call one callback function. Therefore - * the caller is able to assign one of two different callback function. The difference between - * the callback function is that tx_complete_sia_fptr does no provide a self pointer whether - * tx_complete_fptr and tx_complete_inst_ptr allow to invoke a class method. - * \param self The instance - * \param msg_ptr Reference to the related message object - * \param tx_complete_sia_fptr Single instance API callback function which is invoked as soon as - * the transmission was finished. - * \param tx_complete_fptr Multi instance callback function which is invoked as soon as - * the transmission was finished. - * \param tx_complete_inst_ptr Instance pointer which is referred when tx_complete_fptr is invoked. - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_PARAM if the transmission was refused due to an invalid parameter - */ -Ucs_Return_t Ams_TxSendMsg(CAms *self, Ucs_AmsTx_Msg_t *msg_ptr, Amsg_TxCompleteSiaCb_t tx_complete_sia_fptr, - Amsg_TxCompleteCb_t tx_complete_fptr, void* tx_complete_inst_ptr) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Called Ams_TxSendMsg(0x%p)", 1U, msg_ptr)); - - if (Ams_TxIsValidMessage(msg_ptr)) /* prevent application messages to loc. INIC */ - { /* do not set both callback pointers */ - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (((tx_complete_sia_fptr != NULL) && (tx_complete_fptr != NULL)) == false)) - Amsg_TxSetCompleteCallback(msg_ptr, tx_complete_sia_fptr, tx_complete_fptr, tx_complete_inst_ptr); - Ams_TxSendMsgDirect(self, msg_ptr); - ret_val = UCS_RET_SUCCESS; - } - - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (ret_val == UCS_RET_SUCCESS)); - - return ret_val; -} - -/*! \brief Transmits a MOST Application Message without attributes check - * \details This method shall be only be used by AMD and AMS internally - * \param self The instance - * \param msg_ptr Reference to the related message object - */ -void Ams_TxSendMsgDirect(CAms *self, Ucs_AmsTx_Msg_t *msg_ptr) -{ - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Called Ams_TxSendMsg(0x%p)", 1U, msg_ptr)); - - if (msg_ptr->data_size > SEGM_MAX_SIZE_TEL) /* set follower id to be used for all segments */ - { - Amsg_TxSetFollowerId(msg_ptr, Ams_TxGetNextFollowerId(self)); - } - - Amsg_TxEnqueue(msg_ptr, &self->tx.queue); /* schedule transmission */ - Srv_SetEvent(&self->service, AMS_EV_TX_SERVICE); -} - -/*! \brief Callback function which is invoked as soon as MCM transmission - * was finished in PMS. - * \param self The instance - * \param tel_ptr Reference to the telegram - * \param status Transmission status - */ -static void Ams_TxOnStatus(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status) -{ - CAms *self_ = (CAms*)self; - Ucs_AmsTx_Msg_t* msg_ptr = (Ucs_AmsTx_Msg_t*)tel_ptr->info_ptr; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMS]", "Ams_TxOnStatus(tel_ptr=0x%p, %d)", 2U, tel_ptr, status)); - - if (msg_ptr != NULL) /* MOST Telegram has AMS parent? */ - { - Amsg_TxUpdateResult(msg_ptr, status); - - if ((tel_ptr->tel.tel_id == 0U) || (tel_ptr->tel.tel_id == 3U)) /* is finished? */ - { /* just just notify completion, the object is */ - Amsg_TxNotifyComplete(msg_ptr, Amsg_TxGetResultCode(msg_ptr), Amsg_TxGetResultInfo(msg_ptr)); /* automatically freed to the pool */ - } - else if (status != UCS_MSG_STAT_OK) /* check transmission needs termination before transmission end */ - { - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[AMS]", (Amsg_TxGetFollowerId(msg_ptr) != 0U)); - - if (((uint8_t)Amsg_TxGetNextSegmCnt(msg_ptr) == (uint8_t)(tel_ptr->tel.tel_cnt + 1U)) /* is last transmitted segment */ - || ((Amsg_TxGetNextSegmCnt(msg_ptr) == 0U) && (tel_ptr->tel.tel_id == 4U))) /* or TelId 4 and the first segment is pending */ - { - Amsg_TxRemoveFromQueue(msg_ptr, &self_->tx.queue); - Amsg_TxNotifyComplete(msg_ptr, Amsg_TxGetResultCode(msg_ptr), Amsg_TxGetResultInfo(msg_ptr)); /* just just notify completion, the object is */ - } /* automatically freed to the pool */ - } - } - Trcv_TxReleaseMsg(tel_ptr); /* release message object to pool */ - - if ((Dl_GetSize(&self_->tx.queue) > 0U) && (status != UCS_MSG_STAT_ERROR_SYNC)) /* Application Messages are available for Tx */ - { - Srv_SetEvent(&self_->service, AMS_EV_TX_SERVICE); - } -} - -/*! \brief Checks if the destination address of the Tx message is valid and payload is consistent - * \param msg_ptr Reference to the Tx message object - * \return Returns \c true if the destination is correct, otherwise \c false. - */ -bool Ams_TxIsValidMessage(Ucs_AmsTx_Msg_t *msg_ptr) -{ - bool ret = false; - - if (msg_ptr != NULL) - { - if (msg_ptr->destination_address > AMS_ADDR_RSVD_RANGE) /* is not reserved address? */ - { - if (((msg_ptr->destination_address & 0xFF00U) != 0x0300U)/* is single-cast? */ - || (msg_ptr->data_size <= SEGM_MAX_SIZE_TEL)) /* or not segmented */ - { - if (!((msg_ptr->data_size > 0U) && (msg_ptr->data_ptr == NULL))) - { - ret = true; - } - } - } - } - - return ret; -} - -/*! \brief Retrieves the next follower id to use for segmented transfer - * \param self The instance - * \return The follower id - */ -static uint8_t Ams_TxGetNextFollowerId(CAms *self) -{ - uint8_t ret; - ret = self->tx.next_follower_id; - self->tx.next_follower_id++; - - if (self->tx.next_follower_id == 0U) /* skip zero since it means */ - { /* "no follower" */ - self->tx.next_follower_id = 1U; - } - - return ret; -} - -/*! \brief Retrieves the number of messages that are queued for transmission - * \param self The instance - * \return The number of messages in the Tx queue - */ -uint16_t Ams_TxGetMsgCnt(CAms *self) -{ - return Dl_GetSize(&self->tx.queue); -} - -/*------------------------------------------------------------------------------------------------*/ -/* AMS Reception */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Rx callback function that can be assigned to the MCM transceiver - * \details The associated transceiver reference will be stored in the telegrams \c info_ptr. - * Later on the telegram must be released via Ams_RxReleaseTel(). - * \param self The instance - * \param tel_ptr Reference to the Rx telegram object - */ -void Ams_RxOnMcmTelComplete(void *self, Msg_MostTel_t *tel_ptr) -{ - CAms *self_ = (CAms*)self; - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[AMS]", (tel_ptr->info_ptr == NULL)); - tel_ptr->info_ptr = self_->trcv_mcm_ptr; - Ams_RxOnTelComplete(self_, tel_ptr); -} - -/*! \brief Rx callback function that can be assigned to the RCM transceiver - * \details The associated transceiver reference will be stored in the telegrams \c info_ptr. - * Later on the telegram must be released via Ams_RxReleaseTel(). - * \param self The instance - * \param tel_ptr Reference to the Rx telegram object - */ -void Ams_RxOnRcmTelComplete(void *self, Msg_MostTel_t *tel_ptr) -{ - CAms *self_ = (CAms*)self; - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[AMS]", (tel_ptr->info_ptr == NULL)); - tel_ptr->info_ptr = self_->trcv_rcm_ptr; - Ams_RxOnTelComplete(self_, tel_ptr); -} - -/*! \brief Releases an Rx telegram to the associated transceiver - * \details The associated transceiver reference is stored in the telegrams \c info_ptr - * \param self The instance - * \param tel_ptr Reference to the Rx telegram object - */ -static void Ams_RxReleaseTel(CAms *self, Msg_MostTel_t *tel_ptr) -{ - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", ((tel_ptr != NULL) && (tel_ptr->info_ptr != NULL))); - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", ((tel_ptr->info_ptr == self->trcv_mcm_ptr)||(tel_ptr->info_ptr == self->trcv_rcm_ptr))); - - if (tel_ptr->info_ptr != NULL) - { - Trcv_RxReleaseMsg((CTransceiver*)tel_ptr->info_ptr, tel_ptr); - } - - MISC_UNUSED(self); -} - -/*! \brief Internal callback function which is invoked as soon as the transceiver - * reference is stored to the telegrams info_ptr. - * \param self The instance - * \param tel_ptr Reference to the Rx telegram object - */ -static void Ams_RxOnTelComplete(CAms *self, Msg_MostTel_t *tel_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Ams_RxOnComplete(0x%p)", 1U, tel_ptr)); - - if (self->rx.complete_fptr == NULL) - { - /* no processing required, tel_ptr shall be freed */ - msg_ptr = NULL; - } - else if (Telq_GetSize(&self->rx.waiting_queue) > 0U) /* asynchronous Rx is running */ - { /* queue Rx telegram for later processing */ - Telq_Enqueue(&self->rx.waiting_queue, tel_ptr); - tel_ptr = NULL; /* do not free Rx telegram */ - msg_ptr = NULL; - } - else - { - Segm_Result_t result; /* synchronous processing is possible now */ - msg_ptr = Segm_RxExecuteSegmentation(&self->segmentation, tel_ptr, &result); - - if (result == SEGM_RES_RETRY) - { - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (msg_ptr == NULL)); - Telq_Enqueue(&self->rx.waiting_queue, tel_ptr); - tel_ptr = NULL; /* do not free Rx telegram */ - } - } - - if (msg_ptr != NULL) - { - self->rx.complete_fptr(self->rx.complete_inst_ptr, (Ucs_AmsRx_Msg_t*)(void*)msg_ptr); - } - - if (tel_ptr != NULL) - { - Ams_RxReleaseTel(self, tel_ptr); /* free Rx telegram */ - } -} - -/*! \brief Processes all telegrams in waiting queue - * \details Stops if allocation of Rx messages fails - * \param self The instance - */ -static void Ams_RxProcessWaitingQ(CAms *self) -{ - Msg_MostTel_t *tel_ptr; - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - - for (tel_ptr = Telq_Peek(&self->rx.waiting_queue); tel_ptr != NULL; tel_ptr = Telq_Peek(&self->rx.waiting_queue)) - { - Segm_Result_t result; - msg_ptr = Segm_RxExecuteSegmentation(&self->segmentation, tel_ptr, &result); - - if (result == SEGM_RES_OK) /* segmentation process succeeded */ - { - (void)Telq_Dequeue(&self->rx.waiting_queue); /* remove telegram from waitingQ */ - Ams_RxReleaseTel(self, tel_ptr); /* free telegram */ - tel_ptr = NULL; /* parasoft-suppress MISRA2004-13_6 "variable is not used as a counter" */ - - if (msg_ptr != NULL) - { - self->rx.complete_fptr(self->rx.complete_inst_ptr, (Ucs_AmsRx_Msg_t*)(void*)msg_ptr); - } - } - else - { - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (msg_ptr == NULL)); - break; /* wait until further Rx messages can be allocated - abort loop */ - } - } -} - -/*! \brief Callback function which is invoked by segmentation process to notify a segmentation error - * \param self The instance - * \param tel_ptr The related Rx telegram which caused the segmentation error - * \param error The segmentation error number - */ -static void Ams_RxOnSegError(void *self, Msg_MostTel_t *tel_ptr, Segm_Error_t error) -{ - const uint8_t ERR_SZ = 2U; - CAms *self_ = (CAms*)self; - Msg_MostTel_t* error_tel_ptr = NULL; - - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[AMS]", "Ams_RxOnComplete(0x%p, %d)", 2U, tel_ptr, error)); - - if (tel_ptr->source_addr != MSG_ADDR_INIC) - { /* only generate segmentation errors */ - error_tel_ptr = Trcv_TxAllocateMsg(self_->trcv_mcm_ptr, ERR_SZ); /* for messages which are NOT locally routed by the INIC */ - } - - if (error_tel_ptr != NULL) - { - error_tel_ptr->destination_addr = tel_ptr->source_addr; - error_tel_ptr->id = tel_ptr->id; - error_tel_ptr->id.op_type = UCS_OP_ERROR; - error_tel_ptr->tel.tel_data_ptr[0] = 0x0CU; - error_tel_ptr->tel.tel_data_ptr[1] = (uint8_t)error; - error_tel_ptr->opts.llrbc = 0U; - - Trcv_TxSendMsg(self_->trcv_mcm_ptr, error_tel_ptr); /* just fire the message */ - } -} - -/*! \brief Callback function that is invoked if application Rx messages are available again - * \param self The instance - * \param data_ptr Unused parameter of observer callback - */ -static void Ams_RxOnFreedMsg(void *self, void *data_ptr) -{ - CAms *self_ = (CAms*) self; - Srv_SetEvent(&self_->service, AMS_EV_RX_SERVICE); - MISC_UNUSED(data_ptr); -} - -/*! \brief Removes and frees a message from the Rx queue - * \details The application must not access the passed - * message any more. - * \param self The instance - * \param msg_ptr Reference to the message, or \c NULL for the front-most - * message in the Rx queue. - */ -void Ams_RxFreeMsg(CAms *self, Ucs_AmsRx_Msg_t *msg_ptr) -{ - TR_INFO((self->base_ptr->ucs_user_ptr, "[AMS]", "Ams_RxFreeMsg(msg_ptr=0x%p)", 1U, msg_ptr)); - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (msg_ptr != NULL)); - - if (msg_ptr != NULL) - { - Amsp_FreeRxPayload(self->pool_ptr, msg_ptr); /* free external payload */ - Amsp_FreeRxObj(self->pool_ptr, msg_ptr); /* return message to Rx pool */ - } -} - -/*! \brief Removes all messages located in Rx queues - * \param self The instance - */ -static void Ams_RxFlush(CAms *self) -{ - Msg_MostTel_t *tel_ptr; - - for (tel_ptr = Telq_Dequeue(&self->rx.waiting_queue); tel_ptr != NULL; tel_ptr = Telq_Dequeue(&self->rx.waiting_queue)) - { - Ams_RxReleaseTel(self, tel_ptr); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_amsmessage.c b/ucs2-lib/src/ucs_amsmessage.c deleted file mode 100644 index c3d4757..0000000 --- a/ucs2-lib/src/ucs_amsmessage.c +++ /dev/null @@ -1,639 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Application Message Classes - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMSMSG - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_amsmessage.h" -#include "ucs_dl.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -#define SELF_RX ((Amsg_IntMsgRx_t*)(void*)(self)) -#define SELF_TX ((Amsg_IntMsgTx_t*)(void*)(self)) - -#define AMSG_TX_BACKUP_ADDR_NONE 0U - -/*------------------------------------------------------------------------------------------------*/ -/* Prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static Ucs_AmsRx_ReceiveType_t Amsg_RxGetReceiveType(uint16_t destination_address); -static void Amsg_TxRestoreDestinationAddr(Ucs_AmsTx_Msg_t *self); - -/*------------------------------------------------------------------------------------------------*/ -/* Tx Message */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initializes aggregated objects - * \details Needs to be called once before first usage. Call Amsg_TxHandleSetup() before - * repeated usage. - * \param self Reference to an internal Application Message Tx handle - * \param info_ptr Memory information required to free the object - * \param free_fptr Callback function which is invoked when the object is freed - * \param free_inst_ptr The instance which is passed to free_fptr - */ -void Amsg_TxCtor(Ucs_AmsTx_Msg_t *self, void *info_ptr, Amsg_TxFreedCb_t free_fptr, void *free_inst_ptr) -{ - /* cleanup complete object */ - MISC_MEM_SET((void*)self, 0, sizeof(Amsg_IntMsgTx_t)); - - /* reset default references - SELF_TX->memory_ptr = NULL; - SELF_TX->memory_sz = NULL; - SELF_TX->memory_info_ptr = NULL; - - SELF_TX->complete_fptr = NULL; - SELF_TX->complete_inst_ptr = NULL; - SELF_TX->complete_sia_fptr = NULL; - - SELF_TX->backup_dest_address = AMSG_TX_BACKUP_ADDR_NONE;*/ - - SELF_TX->info_ptr = info_ptr; - SELF_TX->free_fptr = free_fptr; - SELF_TX->free_inst_ptr = free_inst_ptr; - SELF_TX->next_segment_cnt = 0xFFFFU; /* start with TelId "4" */ - SELF_TX->temp_result = UCS_MSG_STAT_OK; - SELF_TX->internal_status = AMSG_TX_INTRES_NONE; - SELF_TX->ignore_wrong_target = false; - - Dln_Ctor(&SELF_TX->node, self); /* initialize node */ -} - -/*! \brief Sets payload memory provided by memory management and updates data pointer and size - * \param self The instance - * \param mem_ptr Reference to the provided memory chunk - * \param mem_size Size of the provided memory chunk - * \param mem_info_ptr Optional reference for memory management - */ -void Amsg_TxSetInternalPayload(Ucs_AmsTx_Msg_t *self, uint8_t *mem_ptr, uint16_t mem_size, void *mem_info_ptr) -{ - SELF_TX->memory_ptr = mem_ptr; - SELF_TX->memory_sz = mem_size; - SELF_TX->memory_info_ptr = mem_info_ptr; - - SELF_TX->pb_msg.data_ptr = mem_ptr; - SELF_TX->pb_msg.data_size = mem_size; -} - -/*! \brief Prepares the message object for re-usage - * \details The public message structure is re-initialized. The internal payload - * is assigned to the public data reference. - * \param self The instance - */ -void Amsg_TxReuse(Ucs_AmsTx_Msg_t *self) -{ - MISC_MEM_SET((void *)&SELF_TX->pb_msg, 0, sizeof(SELF_TX->pb_msg)); /* cleanup public object */ - /* SELF_TX->backup_dest_address = AMSG_TX_BACKUP_ADDR_NONE; */ - - SELF_TX->pb_msg.data_ptr = SELF_TX->memory_ptr; /* reset public payload */ - SELF_TX->pb_msg.data_size = SELF_TX->memory_sz; - - SELF_TX->next_segment_cnt = 0xFFFFU; /* start with TelId "4" */ - SELF_TX->temp_result = UCS_MSG_STAT_OK; - SELF_TX->internal_status = AMSG_TX_INTRES_NONE; -} - -/*! \brief Assigns a Tx complete callback function - * \details It is not possible to assign the single and multiple instance callback - * at the same time. This function shall be called before message transmission. - * \param self The instance - * \param compl_sia_fptr Reference to the single instance callback function - * \param compl_fptr Reference to a multiple instance callback function - * \param compl_inst_ptr Instance which is invoked by compl_fptr() - */ -void Amsg_TxSetCompleteCallback(Ucs_AmsTx_Msg_t *self, Amsg_TxCompleteSiaCb_t compl_sia_fptr, - Amsg_TxCompleteCb_t compl_fptr, void* compl_inst_ptr) -{ - SELF_TX->complete_sia_fptr = compl_sia_fptr; - SELF_TX->complete_fptr = compl_fptr; - SELF_TX->complete_inst_ptr = compl_inst_ptr; -} - -/*! \brief Invokes the correct callback function to notify the transmission result - * and frees the memory - * \param self Reference to the related message object - * \param result The transmission result - * \param info The INIC transmission result - */ -void Amsg_TxNotifyComplete(Ucs_AmsTx_Msg_t *self, Ucs_AmsTx_Result_t result, Ucs_AmsTx_Info_t info) -{ - Amsg_TxRestoreDestinationAddr(self); - - if (SELF_TX->complete_sia_fptr != NULL) /* invoke single instance API callback */ - { - SELF_TX->complete_sia_fptr(self, result, info); - } - else if (SELF_TX->complete_fptr != NULL) - { - SELF_TX->complete_fptr(self, result, info, SELF_TX->complete_inst_ptr); - } - - TR_ASSERT(NULL, "[AMSG_TX]", (SELF_TX->free_fptr != NULL)); - if (SELF_TX->free_fptr != NULL) - { - SELF_TX->free_fptr(SELF_TX->free_inst_ptr, self); - } -} - -/*! \brief Frees an unused message object to the owning pool - * \param self Reference to the message object - */ -void Amsg_TxFreeUnused(Ucs_AmsTx_Msg_t *self) -{ - TR_ASSERT(NULL, "[AMSG_TX]", (SELF_TX->free_fptr != NULL)); - if (SELF_TX->free_fptr != NULL) - { - SELF_TX->free_fptr(SELF_TX->free_inst_ptr, self); - } -} - -/*! \brief Updates the transmission result - * \param self Reference to the related message object - * \param result The latest MCM transmission result - * \details Since the transmission result of an application message may - * consist of multiple telegram transmission results, it is - * important to store the final transmission error. An error cannot - * be overwritten by a success. - */ -void Amsg_TxUpdateResult(Ucs_AmsTx_Msg_t *self, Ucs_MsgTxStatus_t result) -{ - if (result != UCS_MSG_STAT_OK) /* store the latest error and do not overwrite with success */ - { - SELF_TX->temp_result = result; - } -} - -/*! \brief Updates the internal transmission result - * \param self Reference to the related message object - * \param result The internal transmission result - * \details The internal transmission result must be updated if the - * the message is transmitted to the internal Rx queue. - */ -void Amsg_TxUpdateInternalResult(Ucs_AmsTx_Msg_t *self, Amsg_TxIntStatus_t result) -{ - SELF_TX->internal_status = result; -} - -/*! \brief Returns the latest AMS transmission result code - * \param self Reference to the related message object - * \return Returns the transmission result which shall be notified to the application - */ -Ucs_AmsTx_Result_t Amsg_TxGetResultCode(Ucs_AmsTx_Msg_t *self) -{ - Ucs_AmsTx_Result_t res = UCS_AMSTX_RES_SUCCESS; /* success is the expected result */ - - switch (SELF_TX->temp_result) - { - case UCS_MSG_STAT_OK: - if (SELF_TX->internal_status == AMSG_TX_INTRES_ERRBUF) - { - res = UCS_AMSTX_RES_ERR_BUF_INTERNAL; /* internal transmission error overrules network success */ - } - break; - case UCS_MSG_STAT_ERROR_BF: - case UCS_MSG_STAT_ERROR_CRC: - case UCS_MSG_STAT_ERROR_ID: - case UCS_MSG_STAT_ERROR_ACK: - case UCS_MSG_STAT_ERROR_TIMEOUT: - res = UCS_AMSTX_RES_ERR_RETRIES_EXP; /* transmission failed, retries are possible */ - break; - case UCS_MSG_STAT_ERROR_FATAL_WT: - case UCS_MSG_STAT_ERROR_FATAL_OA: - if (SELF_TX->internal_status == AMSG_TX_INTRES_ERRBUF) - { - res = UCS_AMSTX_RES_ERR_BUF_INTERNAL; /* internal transmission error and network node not found */ - } - else if (SELF_TX->internal_status == AMSG_TX_INTRES_NONE) - { - res = UCS_AMSTX_RES_ERR_INVALID_TGT; /* not transmitted internally and no network node found */ - } - /* else -> internal success -> target node was found locally */ - break; - case UCS_MSG_STAT_ERROR_NA_TRANS: - case UCS_MSG_STAT_ERROR_NA_OFF: - if (SELF_TX->internal_status != AMSG_TX_INTRES_SUCCESS) - { - res = UCS_AMSTX_RES_ERR_NOT_AVAILABLE; /* successful if internal transmission succeeded, otherwise "not available" */ - } - break; - case UCS_MSG_STAT_ERROR_SYNC: - res = UCS_AMSTX_RES_ERR_NOT_AVAILABLE; - break; - default: - res = UCS_AMSTX_RES_ERR_UNEXPECTED; /* unexpected network transmission state */ - break; - } - - return res; -} - -/*! \brief Returns the latest MCM transmission error - * \param self Reference to the related message object - * \return Returns the INIC transmission result which is provided as additional info - */ -Ucs_AmsTx_Info_t Amsg_TxGetResultInfo(Ucs_AmsTx_Msg_t *self) -{ - Ucs_AmsTx_Info_t res = (Ucs_AmsTx_Info_t)SELF_TX->temp_result; - - if ((SELF_TX->temp_result == UCS_MSG_STAT_ERROR_FATAL_WT) && (SELF_TX->ignore_wrong_target != false)) - { - res = UCS_AMSTX_I_SUCCESS; - } - - return res; -} - -/*! \brief Queues a Tx message at the tail of a list - * \param self The instance - * \param list_ptr Reference to the list - */ -void Amsg_TxEnqueue(Ucs_AmsTx_Msg_t* self, CDlList* list_ptr) -{ - Dl_InsertTail(list_ptr, &SELF_TX->node); -} - -/*! \brief Retrieves the next segment count - * \param self The instance - * \return The next segment count as uint16_t - */ -uint16_t Amsg_TxGetNextSegmCnt(Ucs_AmsTx_Msg_t *self) -{ - return SELF_TX->next_segment_cnt; -} - -/*! \brief Increments the next segment count - * \param self The instance - */ -void Amsg_TxIncrementNextSegmCnt(Ucs_AmsTx_Msg_t *self) -{ - SELF_TX->next_segment_cnt++; -} - -/*! \brief Retrieves the follower id which labels all telegrams of a segmented message - * \param self The instance - * \return The follower id - */ -uint8_t Amsg_TxGetFollowerId(Ucs_AmsTx_Msg_t *self) -{ - return SELF_TX->follower_id; -} - -/*! \brief Sets the follower id which labels all telegrams of a segmented message - * \param self The instance - * \param id The follower id - */ -void Amsg_TxSetFollowerId(Ucs_AmsTx_Msg_t *self, uint8_t id) -{ - SELF_TX->follower_id = id; -} - -/*! \brief Replaces the current destination address by a new one. - * \details The current destination address can be restore by Amsg_TxRestoreDestinationAddr(). - * \param self The instance - * \param new_destination The new destination address - */ -void Amsg_TxReplaceDestinationAddr(Ucs_AmsTx_Msg_t *self, uint16_t new_destination) -{ - SELF_TX->backup_dest_address = self->destination_address; /* internal backup of current destination address */ - self->destination_address = new_destination; /* replace public destination address */ -} - -/*! \brief Restores the destination address which was saved by calling Amsg_TxReplaceDestinationAddr(). - * \param self The instance - */ -static void Amsg_TxRestoreDestinationAddr(Ucs_AmsTx_Msg_t *self) -{ - if (SELF_TX->backup_dest_address != AMSG_TX_BACKUP_ADDR_NONE) - { - self->destination_address = SELF_TX->backup_dest_address;/* restore public destination address */ - } -} - -/*! \brief Removes a message from a given queue - * \param self The instance - * \param list_ptr The queue that contains the message - */ -void Amsg_TxRemoveFromQueue(Ucs_AmsTx_Msg_t *self, CDlList *list_ptr) -{ - (void)Dl_Remove(list_ptr, &SELF_TX->node); -} - -/*! \brief Peeks a Tx message from the head of a list - * \param list_ptr Reference to the list - * \return Reference to the Tx message - */ -Ucs_AmsTx_Msg_t* Amsg_TxPeek(CDlList* list_ptr) -{ - Ucs_AmsTx_Msg_t *msg_ptr = NULL; - CDlNode *node_ptr = Dl_PeekHead(list_ptr); - - if (node_ptr != NULL) - { - msg_ptr = (Ucs_AmsTx_Msg_t*)Dln_GetData(node_ptr); - } - - return msg_ptr; -} - -/*! \brief Removes a Tx message from the head of a list - * \param list_ptr Reference to the list - * \return Reference to the Tx message - */ -Ucs_AmsTx_Msg_t* Amsg_TxDequeue(CDlList* list_ptr) -{ - Ucs_AmsTx_Msg_t *msg_ptr = NULL; - CDlNode *node_ptr = Dl_PopHead(list_ptr); - - if (node_ptr != NULL) - { - msg_ptr = (Ucs_AmsTx_Msg_t*)Dln_GetData(node_ptr); - } - - return msg_ptr; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Rx Message */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initializes aggregated objects - * \details Needs to be called once before first usage. Call Amsg_RxHandleSetup() before - * repeated usage. - * \param self Reference to an internal Application Message Rx handle - * \param info_ptr Memory information required to free the object - */ -void Amsg_RxCtor(Ucs_AmsRx_Msg_t *self, void *info_ptr) -{ - Dln_Ctor(&SELF_RX->node, SELF_RX); - SELF_RX->info_ptr = info_ptr; /* reset memory information */ - SELF_RX->memory_sz = 0U; - SELF_RX->memory_ptr = NULL; - SELF_RX->memory_info_ptr = NULL; -} - -/*! \brief Copies all attributes and payload from a Tx message to the Rx message - * \details The caller has to ensure that the payload size of the Rx message is equal - * or greater than the payload size of the Tx message. - * \param self Reference to an Rx message object - * \param tx_ptr Reference to an Tx message object - * \param source_address The source address that shall be set in the Rx message - */ -void Amsg_RxBuildFromTx(Ucs_AmsRx_Msg_t *self, Ucs_AmsTx_Msg_t *tx_ptr, uint16_t source_address) -{ - TR_ASSERT(NULL,"[AMSG]", (SELF_RX->memory_sz >= tx_ptr->data_size)); - - self->receive_type = Amsg_RxGetReceiveType(tx_ptr->destination_address); - self->source_address = source_address; - self->msg_id = tx_ptr->msg_id; - self->data_size = tx_ptr->data_size; - - Misc_MemCpy(self->data_ptr, tx_ptr->data_ptr, (size_t)self->data_size); -} - -/*! \brief Sets all attributes of an internal Rx message to valid values - * \param self Reference to an internal Rx message object - * \details Assigned payload memory has to be freed before calling this function - */ -void Amsg_RxHandleSetup(Ucs_AmsRx_Msg_t *self) -{ - MISC_MEM_SET((void *)&SELF_RX->pb_msg, 0, sizeof(SELF_RX->pb_msg)); /* cleanup public message object */ - SELF_RX->pb_msg.data_ptr = SELF_RX->memory_ptr; /* set data to valid memory */ - SELF_RX->gc_marker = false; /* reset garbage collector flag */ - SELF_RX->exp_tel_cnt = 0U; /* reset TelCnt */ -} - -/*! \brief Evaluates if an Application Message has the same functional address - * as a MOST telegram - * \param self Reference to an internal Application Message Rx handle - * \param tel_ptr Reference to a MOST message object - * \return Returns \c true if both message objects have the same functional address, - * otherwise \c false. - */ -bool Amsg_RxHandleIsIdentical(Ucs_AmsRx_Msg_t *self, Msg_MostTel_t *tel_ptr) -{ - bool result = false; - uint16_t msg_id = Msg_GetAltMsgId((CMessage*)(void*)tel_ptr); - - if ((self->source_address == tel_ptr->source_addr) - && (self->msg_id == msg_id)) - { - result = true; - } - - return result; -} - -/*! \brief Copies the Rx message signature from a MOST message object to an - * internal Application message object - * \param self Reference to an internal Application Message Rx handle - * \param src_ptr Reference to a MOST message object - */ -void Amsg_RxCopySignatureFromTel(Ucs_AmsRx_Msg_t *self, Msg_MostTel_t* src_ptr) -{ - self->source_address = src_ptr->source_addr; - self->receive_type = Amsg_RxGetReceiveType(src_ptr->destination_addr); - self->msg_id = Msg_GetAltMsgId((CMessage*)(void*)src_ptr); -} - -/*! \brief Copies the Rx message signature from an internal Application - * message object to a MOST message object - * \param self Reference to an internal Application Message Rx handle - * \param target_ptr Reference to a MOST message object - */ -void Amsg_RxCopySignatureToTel(Ucs_AmsRx_Msg_t *self, Msg_MostTel_t* target_ptr) -{ - target_ptr->source_addr = self->source_address; - target_ptr->destination_addr = UCS_ADDR_DEBUG; - Msg_SetAltMsgId((CMessage*)(void*)target_ptr, self->msg_id); -} - -/*! \brief Retrieves the addressing type related to a destination_address of an Rx message - * \param destination_address The destination address of an Rx message - * \return The receive type related to the destination address - */ -static Ucs_AmsRx_ReceiveType_t Amsg_RxGetReceiveType(uint16_t destination_address) -{ - Ucs_AmsRx_ReceiveType_t ret = UCS_AMSRX_RCT_SINGLECAST; - - if ((destination_address == UCS_ADDR_BROADCAST_BLOCKING) || - (destination_address == UCS_ADDR_BROADCAST_UNBLOCKING)) - { - ret = UCS_AMSRX_RCT_BROADCAST; - } - else if ((destination_address >= 0x0300U) && /* 0x300..0x3FF is reserved for group cast */ - (destination_address < 0x0400U)) - { - ret = UCS_AMSRX_RCT_GROUPCAST; - } - - return ret; -} - -/*! \brief Appends payload of an Rx MOST message object to internal Application - * message object - * \param self Reference to an internal Application Message Rx handle - * \param src_ptr Reference to a MOST message object - * \return Returns \c true if the payload was appended successfully, - * otherwise \c false. - */ -bool Amsg_RxAppendPayload(Ucs_AmsRx_Msg_t *self, Msg_MostTel_t* src_ptr) -{ - uint8_t cnt; - bool ret = false; - const uint16_t curr_size = SELF_RX->pb_msg.data_size; /* get current message size */ - - if ((SELF_RX->memory_sz - src_ptr->tel.tel_len) >= SELF_RX->pb_msg.data_size) /* is size sufficient */ - { - for (cnt = 0U; cnt < src_ptr->tel.tel_len; cnt++) - { - SELF_RX->pb_msg.data_ptr[curr_size + (uint16_t)cnt] = src_ptr->tel.tel_data_ptr[cnt]; - } - - SELF_RX->pb_msg.data_size = curr_size + src_ptr->tel.tel_len; /* update message size */ - SELF_RX->exp_tel_cnt++; - ret = true; - } - - return ret; -} - -/*! \brief Copies data to allocated payload buffer - * \param self The instance - * \param data Reference to external payload data - * \param data_sz Size of external payload data - */ -void Amsg_RxCopyToPayload(Ucs_AmsRx_Msg_t *self, uint8_t data[], uint8_t data_sz) -{ - MISC_MEM_CPY(&self->data_ptr[0], &data[0], (size_t)data_sz); /* parasoft-suppress MISRA2004-20_3 "data_sz is limited and checked via Msg_VerifyContent()" */ - self->data_size = data_sz; /* remember payload size */ -} - -/*! \brief Checks if the message has externally allocated payload memory - * \param self The instance - * \return Returns \c true if external payload is assigned to the message, otherwise \c false. - */ -bool Amsg_RxHasExternalPayload(Ucs_AmsRx_Msg_t *self) -{ - return (SELF_RX->memory_sz > 0U); -} - -/*! \brief Sets payload memory provided by memory management and updates data pointer and size - * \param self The instance - * \param mem_ptr Reference to the provided memory chunk - * \param mem_size Size of the provided memory chunk - * \param info_ptr Optional reference for memory management - */ -void Amsg_RxHandleSetMemory(Ucs_AmsRx_Msg_t *self, uint8_t *mem_ptr, uint16_t mem_size, void *info_ptr) -{ - SELF_RX->memory_ptr = mem_ptr; - SELF_RX->memory_info_ptr = info_ptr; - SELF_RX->memory_sz = mem_size; - - SELF_RX->pb_msg.data_ptr = mem_ptr; - SELF_RX->pb_msg.data_size = 0U; -} - -/*! \brief Queues an Rx message at the tail of a list - * \param self The instance - * \param list_ptr Reference to the list - */ -void Amsg_RxEnqueue(Ucs_AmsRx_Msg_t* self, CDlList* list_ptr) -{ - Dl_InsertTail(list_ptr, &SELF_RX->node); -} - -/*! \brief Sets or resets the garbage collector flag - * \param self The instance - * \param value New value of the flag - */ -void Amsg_RxSetGcMarker(Ucs_AmsRx_Msg_t* self, bool value) -{ - SELF_RX->gc_marker = value; -} - -/*! \brief Retrieves the value of the garbage collector flag - * \param self The instance - * \return The current value of the flag - */ -bool Amsg_RxGetGcMarker(Ucs_AmsRx_Msg_t* self) -{ - return SELF_RX->gc_marker; -} - -/*! \brief Retrieves the next expected telegram count - * \param self The instance - * \return The next expected telegram count as uint8_t - */ -uint8_t Amsg_RxGetExpTelCnt(Ucs_AmsRx_Msg_t* self) -{ - return SELF_RX->exp_tel_cnt; -} - -/*! \brief Peeks an Rx message from the head of a list - * \param list_ptr Reference to the list - * \return Reference to the Rx message - */ -Ucs_AmsRx_Msg_t* Amsg_RxPeek(CDlList* list_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - CDlNode *node_ptr = Dl_PeekHead(list_ptr); - - if (node_ptr != NULL) - { - msg_ptr = (Ucs_AmsRx_Msg_t*)Dln_GetData(node_ptr); - } - - return msg_ptr; -} - -/*! \brief Removes an Rx message from the head of a list - * \param list_ptr Reference to the list - * \return Reference to the Rx message - */ -Ucs_AmsRx_Msg_t* Amsg_RxDequeue(CDlList* list_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - CDlNode *node_ptr = Dl_PopHead(list_ptr); - - if (node_ptr != NULL) - { - msg_ptr = (Ucs_AmsRx_Msg_t*)Dln_GetData(node_ptr); - } - - return msg_ptr; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_amspool.c b/ucs2-lib/src/ucs_amspool.c deleted file mode 100644 index 5c20d22..0000000 --- a/ucs2-lib/src/ucs_amspool.c +++ /dev/null @@ -1,335 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Application Message Pool - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMSPOOL - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_amspool.h" -#include "ucs_amsmessage.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal macros */ -/*------------------------------------------------------------------------------------------------*/ -#define INT_RX(ptr) ((Amsg_IntMsgRx_t*)(void*)(ptr)) /* parasoft-suppress MISRA2004-19_7 "common definition of type cast improves code" */ -#define INT_TX(ptr) ((Amsg_IntMsgTx_t*)(void*)(ptr)) /* parasoft-suppress MISRA2004-19_7 "common definition of type cast improves code" */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Amsp_FreeTxObj(void *self, Ucs_AmsTx_Msg_t* msg_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of application message pool class - * \param self The instance - * \param mem_allocator_ptr Reference to memory allocator - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Amsp_Ctor(CAmsMsgPool *self, Ams_MemAllocator_t *mem_allocator_ptr, void *ucs_user_ptr) -{ - self->ucs_user_ptr = ucs_user_ptr; - self->allocator_ptr = mem_allocator_ptr; - self->rx_rsvd_msg_ptr = Amsp_AllocRxObj(self, 45U); - self->rx_rsvd_msg_ref = self->rx_rsvd_msg_ptr; - self->terminated = false; - self->tx_notify_freed = false; - self->rx_notify_freed = false; - Sub_Ctor(&self->tx_freed_subject, self->ucs_user_ptr); - Sub_Ctor(&self->rx_freed_subject, self->ucs_user_ptr); - - TR_ASSERT(self->ucs_user_ptr, "[AMSP]", (self->rx_rsvd_msg_ptr != NULL)); -} - -/*! \brief Frees pre-allocated message memory - * \param self The instance - */ -void Amsp_Cleanup(CAmsMsgPool *self) -{ - Amsg_IntMsgRx_t *msg_ptr = INT_RX(self->rx_rsvd_msg_ptr); - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Amsp_Cleanup: rx_rsvd_msg_ptr=0x%p", 1U, self->rx_rsvd_msg_ptr)); - - self->terminated = true; - self->tx_notify_freed = false; - self->rx_notify_freed = false; - - if (msg_ptr != NULL) - { - self->allocator_ptr->free_fptr(self->allocator_ptr->inst_ptr, msg_ptr->memory_ptr, AMS_MU_RX_PAYLOAD, msg_ptr->memory_info_ptr); - self->allocator_ptr->free_fptr(self->allocator_ptr->inst_ptr, msg_ptr, AMS_MU_RX_OBJECT, msg_ptr->info_ptr); - self->rx_rsvd_msg_ref = NULL; - self->rx_rsvd_msg_ptr = NULL; - } -} - -/*! \brief Assigns an observer which is invoked as soon as memory dedicated to a Tx message is - * freed.The data_ptr of the update callback function is not used (always \c NULL). - * See \ref Obs_UpdateCb_t. - * \param self The instance - * \param observer_ptr The observer - */ -void Amsp_AssignTxFreedObs(CAmsMsgPool *self, CObserver *observer_ptr) -{ - (void)Sub_AddObserver(&self->tx_freed_subject, observer_ptr); -} - -/*! \brief Assigns an observer which is invoked as soon as memory dedicated to a Tx message is - * freed.The data_ptr of the update callback function is not used (always \c NULL). - * See \ref Obs_UpdateCb_t. - * \param self The instance - * \param observer_ptr The observer - */ -void Amsp_AssignRxFreedObs(CAmsMsgPool *self, CObserver *observer_ptr) -{ - (void)Sub_AddObserver(&self->rx_freed_subject, observer_ptr); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Tx allocations */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Allocates an internal Tx message object (without payload) - * \param self The instance - * \param payload_sz The required payload size in bytes - * \return Reference to the Tx message object if the allocation succeeds. Otherwise \c NULL. - */ -Ucs_AmsTx_Msg_t* Amsp_AllocTxObj(CAmsMsgPool *self, uint16_t payload_sz) -{ - void *payload_info_ptr = NULL; - void *payload_ptr = NULL; - void *obj_info_ptr = NULL; - Ucs_AmsTx_Msg_t *msg_ptr = (Ucs_AmsTx_Msg_t*)self->allocator_ptr->alloc_fptr(self->allocator_ptr->inst_ptr, AMSG_TX_OBJECT_SZ, AMS_MU_TX_OBJECT, &obj_info_ptr); - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Allocating TxObject: msg_ptr=0x%p, size=%d, info_ptr=0x%p", 3U, msg_ptr, AMSG_TX_OBJECT_SZ, obj_info_ptr)); - - if (msg_ptr != NULL) - { - if (payload_sz > 0U) - { - payload_ptr = self->allocator_ptr->alloc_fptr(self->allocator_ptr->inst_ptr, payload_sz, AMS_MU_TX_PAYLOAD, &payload_info_ptr); - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Allocating TxPayload: msg_ptr=0x%p, mem_ptr=0x%p, size=%d, info_ptr=0x%p", 4U, msg_ptr, payload_ptr, payload_sz, payload_info_ptr)); - - if (payload_ptr == NULL) - { - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Freeing TxObject: msg_ptr=0x%p, info_ptr=0x%p", 2U, msg_ptr, obj_info_ptr)); - self->allocator_ptr->free_fptr(self->allocator_ptr->inst_ptr, msg_ptr, AMS_MU_TX_OBJECT, obj_info_ptr); - msg_ptr = NULL; - } - } - } - - if (msg_ptr != NULL) - { - Amsg_TxCtor(msg_ptr, obj_info_ptr, &Amsp_FreeTxObj, self); - - if (payload_ptr != NULL) - { - Amsg_TxSetInternalPayload(msg_ptr, (uint8_t*)payload_ptr, payload_sz, payload_info_ptr); - } - } - else - { - self->tx_notify_freed = true; - } - - return msg_ptr; -} - -/*! \brief Frees an internal Tx message object including its payload - * \param self The instance - * \param msg_ptr Reference to the internal Tx message object - */ -static void Amsp_FreeTxObj(void *self, Ucs_AmsTx_Msg_t* msg_ptr) -{ - CAmsMsgPool *self_ = (CAmsMsgPool*)self; - Amsg_IntMsgTx_t *obj_ptr = INT_TX(msg_ptr); - - if (obj_ptr->memory_ptr != NULL) - { - TR_INFO((self_->ucs_user_ptr, "[AMSP]", "Freeing TxPayload: msg_ptr=0x%p, mem_ptr=0x%p, info_ptr=0x%p", 3U, msg_ptr, obj_ptr->memory_ptr, obj_ptr->memory_info_ptr)); - self_->allocator_ptr->free_fptr(self_->allocator_ptr->inst_ptr, obj_ptr->memory_ptr, AMS_MU_TX_PAYLOAD, obj_ptr->memory_info_ptr); - Amsg_TxSetInternalPayload(msg_ptr, NULL, 0U, NULL); - } - - TR_INFO((self_->ucs_user_ptr, "[AMSP]", "Freeing TxObject: msg_ptr=0x%p, info_ptr=0x%p", 2U, msg_ptr, obj_ptr->info_ptr)); - self_->allocator_ptr->free_fptr(self_->allocator_ptr->inst_ptr, msg_ptr, AMS_MU_TX_OBJECT, obj_ptr->info_ptr); - - if (self_->tx_notify_freed) - { - Sub_Notify(&self_->tx_freed_subject, NULL); - self_->tx_notify_freed = false; - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Rx allocations */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Allocates an internal Rx message object (optionally with payload) - * \param self The instance - * \param payload_sz The required payload size that shall be allocated and assigned to the object. - * Value "0" means that no payload memory shall be allocated in the same turn. - * \return Reference to the Rx message object if the allocation succeeds. Otherwise \c NULL. - */ -Ucs_AmsRx_Msg_t* Amsp_AllocRxObj(CAmsMsgPool *self, uint16_t payload_sz) -{ - void *info_ptr = NULL; - Ucs_AmsRx_Msg_t *msg_ptr = (Ucs_AmsRx_Msg_t*)self->allocator_ptr->alloc_fptr(self->allocator_ptr->inst_ptr, AMSG_RX_OBJECT_SZ, AMS_MU_RX_OBJECT, &info_ptr); - - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Allocating RxObject: msg_ptr=0x%p, size=%d, info_ptr=0x%p", 3U, msg_ptr, AMSG_RX_OBJECT_SZ, info_ptr)); - - if (msg_ptr != NULL) - { - Amsg_RxCtor(msg_ptr, info_ptr); - Amsg_RxHandleSetup(msg_ptr); - - if (payload_sz != 0U) - { - if (!Amsp_AllocRxPayload(self, payload_sz, msg_ptr)) - { - Amsp_FreeRxObj(self, msg_ptr); /* payload allocation has failed - release message object */ - msg_ptr = NULL; - } - } - } - - return msg_ptr; -} - -/*! \brief Allocates a reserved Rx message object with payload up to 45 bytes payload - * \param self The instance - * \return Reference to the Rx message object if the allocation succeeds. Otherwise \c NULL. - */ -Ucs_AmsRx_Msg_t* Amsp_AllocRxRsvd(CAmsMsgPool *self) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - - if (self->rx_rsvd_msg_ptr != NULL) - { - msg_ptr = self->rx_rsvd_msg_ptr; - self->rx_rsvd_msg_ptr = NULL; - Amsg_RxHandleSetup(msg_ptr); - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Retrieving reserved RxObject: msg_ptr=0x%p", 1U, msg_ptr)); - } - else - { - self->rx_notify_freed = true; - } - - return msg_ptr; -} - -/*! \brief Allocates payload for an internal Rx message object - * \param self The instance - * \param payload_sz Payload size in bytes - * \param msg_ptr Reference to the internal Rx message object - * \return Returns \c true if the allocation succeeds. Otherwise \c NULL. - */ -bool Amsp_AllocRxPayload(CAmsMsgPool *self, uint16_t payload_sz, Ucs_AmsRx_Msg_t* msg_ptr) -{ - bool success = false; - void *info_ptr = NULL; - void *mem_ptr = self->allocator_ptr->alloc_fptr(self->allocator_ptr->inst_ptr, payload_sz, AMS_MU_RX_PAYLOAD, &info_ptr); - - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Allocating RxPayload: msg_ptr=0x%p, mem_ptr=0x%p, size=%d, info_ptr=0x%p", 4U, msg_ptr, mem_ptr, payload_sz, info_ptr)); - TR_ASSERT(self->ucs_user_ptr, "[AMSP]", (msg_ptr != NULL)); /* message reference is required */ - TR_ASSERT(self->ucs_user_ptr, "[AMSP]", (msg_ptr != self->rx_rsvd_msg_ref)); /* forbidden overwrite of pre-allocated message payload */ - - if (mem_ptr != NULL) - { - Amsg_RxHandleSetMemory(msg_ptr, (uint8_t*)mem_ptr, payload_sz, info_ptr); - success = true; - } - - return success; -} - -/*! \brief Frees an internal Rx message object - * \param self The instance - * \param msg_ptr Reference to the internal Rx message object - * \details Payload that is assigned to the message object has to be freed - * separately by using Amsp_FreeRxPayload(). - */ -void Amsp_FreeRxObj(CAmsMsgPool *self, Ucs_AmsRx_Msg_t* msg_ptr) -{ - if (msg_ptr == self->rx_rsvd_msg_ref) - { - TR_ASSERT(self->ucs_user_ptr, "[AMSP]", (self->rx_rsvd_msg_ptr == NULL)); /* before freeing, message shall be reserved */ - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Restoring reserved RxObject: msg_ptr=0x%p", 1U, msg_ptr)); - self->rx_rsvd_msg_ptr = self->rx_rsvd_msg_ref; /* restore reserved message */ - - if (self->terminated != false) - { /* also free reserved message if it is freed */ - Amsp_Cleanup(self); /* from any queue after Amsp_Cleanup() */ - } - } - else - { - Amsg_IntMsgRx_t *obj_ptr = INT_RX(msg_ptr); - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Freeing RxObject: msg_ptr=0x%p, info_ptr=0x%p", 2U, msg_ptr, obj_ptr->info_ptr)); - self->allocator_ptr->free_fptr(self->allocator_ptr->inst_ptr, msg_ptr, AMS_MU_RX_OBJECT, obj_ptr->info_ptr); - } - - if (self->rx_notify_freed) - { - Sub_Notify(&self->rx_freed_subject, NULL); - self->rx_notify_freed = false; - } -} - -/*! \brief Frees payload that is associated with an internal Rx message object - * \param self The instance - * \param msg_ptr Reference to the internal Rx message object - */ -void Amsp_FreeRxPayload(CAmsMsgPool *self, Ucs_AmsRx_Msg_t* msg_ptr) -{ - Amsg_IntMsgRx_t *obj_ptr = INT_RX(msg_ptr); - - if (msg_ptr == self->rx_rsvd_msg_ref) - { - TR_ASSERT(self->ucs_user_ptr, "[AMSP]", (self->rx_rsvd_msg_ptr == NULL)); /* release payload before object */ - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Restoring reserved RxPayload: msg_ptr=0x%p", 1U, msg_ptr)); - } - else if (obj_ptr->memory_ptr != NULL) - { - TR_INFO((self->ucs_user_ptr, "[AMSP]", "Freeing RxPayload: msg_ptr=0x%p, mem_ptr=0x%p, info_ptr=0x%p", 3U, msg_ptr, obj_ptr->memory_ptr, obj_ptr->memory_info_ptr)); - self->allocator_ptr->free_fptr(self->allocator_ptr->inst_ptr, obj_ptr->memory_ptr, AMS_MU_RX_PAYLOAD, obj_ptr->memory_info_ptr); - Amsg_RxHandleSetMemory(msg_ptr, NULL, 0U, NULL); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_amtp.c b/ucs2-lib/src/ucs_amtp.c deleted file mode 100644 index e4550d6..0000000 --- a/ucs2-lib/src/ucs_amtp.c +++ /dev/null @@ -1,114 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Application Message Tx Pool - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMTP - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_amtp.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Amtp_OnMsgFreed(void *self, Ucs_AmsTx_Msg_t* msg_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CAmtp - * \param self The instance - * \param msg_ptr Reference to an array of Amsg_IntMsgTx_t objects - * \param data_ptr Reference to payload data which is required for the payload of all messages. - * The data size must be the product of message_cnt and payload_cnt. - * \param msg_cnt The number of message objects in the array - * \param payload_sz The payload size for each message. The size must be a multiple of "4". - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Amtp_Ctor(CAmtp *self, Amsg_IntMsgTx_t msg_ptr[], uint8_t data_ptr[], uint8_t msg_cnt, uint16_t payload_sz, void *ucs_user_ptr) -{ - uint8_t i = 0U; - uint32_t mem_idx = 0U; - Ucs_AmsTx_Msg_t *tx_ptr; - - self->ucs_user_ptr = ucs_user_ptr; - TR_ASSERT(self->ucs_user_ptr, "[AMTP]", ((payload_sz % 4U) == 0U)); /* payload_sz shall be rounded to full quadlet */ - TR_ASSERT(self->ucs_user_ptr, "[AMTP]", ((payload_sz * msg_cnt) <= 65535U)); /* total data shall be referenced by uint32_t index */ - - Dl_Ctor(&self->msg_queue, self->ucs_user_ptr); - - for (i = 0U; i < msg_cnt; i++) - { - tx_ptr = (Ucs_AmsTx_Msg_t*)(void*)&(msg_ptr[i]); - Amsg_TxCtor(tx_ptr, NULL, &Amtp_OnMsgFreed, self); - - if (payload_sz > 0U) - { - Amsg_TxSetInternalPayload(tx_ptr, &data_ptr[mem_idx], payload_sz, NULL); - mem_idx += payload_sz; - } - - Amsg_TxEnqueue(tx_ptr, &self->msg_queue); - } - -} - -/*! \brief Retrieves a Tx application message object - * \param self The instance - * \return Retrieves the reference to a Tx application message object if the allocation - * succeeded, otherwise \c NULL. - */ -Ucs_AmsTx_Msg_t* Amtp_AllocMsg(CAmtp *self) -{ - return Amsg_TxDequeue(&self->msg_queue); -} - -/*! \brief Callback function which is invoked if the message object is freed - * by the AMS - * \param self The instance - * \param msg_ptr Reference to the freed application Tx message object - */ -static void Amtp_OnMsgFreed(void *self, Ucs_AmsTx_Msg_t* msg_ptr) -{ - CAmtp *self_ = (CAmtp*)self; - - Amsg_TxReuse(msg_ptr); - Amsg_TxEnqueue(msg_ptr, &self_->msg_queue); -} - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_attach.c b/ucs2-lib/src/ucs_attach.c deleted file mode 100644 index 33604ef..0000000 --- a/ucs2-lib/src/ucs_attach.c +++ /dev/null @@ -1,607 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 CAttachService class - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_ATS - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_attach.h" -#include "ucs_pmevent.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the ATS service used by scheduler */ -static const uint8_t ATS_SRV_PRIO = 254U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the ATS service */ -static const Srv_Event_t ATS_EVENT_SERVICE = 1U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initialization timeout in milliseconds (t = 3s) */ -static const uint16_t ATS_INIT_TIMEOUT = 3000U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal definitions */ -/*------------------------------------------------------------------------------------------------*/ -#define ATS_NUM_STATES 11U /*!< \brief Number of state machine states */ -#define ATS_NUM_EVENTS 5U /*!< \brief Number of state machine events */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal enumerators */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Possible events of the attach state machine */ -typedef enum Ats_Events_ -{ - ATS_E_NIL = 0, /*!< \brief NIL Event */ - ATS_E_NEXT = 1, /*!< \brief Go to next state */ - ATS_E_RETRY = 2, /*!< \brief Retry current action */ - ATS_E_ERROR = 3, /*!< \brief An error has been occurred */ - ATS_E_TIMEOUT = 4 /*!< \brief An timeout has been occurred */ - -} Ats_Events_t; - -/*! \brief States of the attach state machine */ -typedef enum Ats_State_ -{ - ATS_S_START = 0, /*!< \brief Start state */ - ATS_S_PMS_UNSYNC = 1, /*!< \brief Initially un-synchronizes all FIFOs */ - ATS_S_PMS_INIT = 2, /*!< \brief PMS initialization state */ - ATS_S_VERS_CHK = 3, /*!< \brief Version check state */ - ATS_S_INIC_OVHL = 4, /*!< \brief INIC overhaul state */ - ATS_S_DEV_ATT_STAGE_1 = 5, /*!< \brief Device attach state 1 (wait for first condition) */ - ATS_S_DEV_ATT_STAGE_2 = 6, /*!< \brief Device attach state 2 (wait for second condition) */ - ATS_S_DEV_ATT_STAGE_3 = 7, /*!< \brief Device attach state 3 (wait for third condition) */ - ATS_S_NW_CONFIG = 8, /*!< \brief Retrieve network configuration */ - ATS_S_INIT_CPL = 9, /*!< \brief Initialization complete state */ - ATS_S_ERROR = 10 /*!< \brief Error state */ - -} Ats_State_t; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Ats_TimeoutCb(void *self); -static void Ats_Service(void *self); -static void Ats_ResetObservers(CAttachService *self); -static void Ats_StartPmsUnsync(void *self); -static void Ats_StartPmsInit(void *self); -static void Ats_StartVersChk(void *self); -static void Ats_StartInicOvhl(void *self); -static void Ats_StartDevAtt(void *self); -static void Ats_StartNwConfig(void *self); -static void Ats_InitCpl(void *self); -static void Ats_HandleInternalErrors(void *self, void *error_code_ptr); -static void Ats_HandleError(void *self); -static void Ats_HandleTimeout(void *self); -static void Ats_InvalidTransition(void *self); -static void Ats_CheckPmsUnsyncResult(void *self, void *result_ptr); -static void Ats_CheckPmsInitResult(void *self, void *result_ptr); -static void Ats_CheckVersChkResult(void *self, void *result_ptr); -static void Ats_CheckNetworkStatusReceived(void *self, void *result_ptr); -static void Ats_CheckDeviceStatusReceived(void *self, void *data_ptr); -static void Ats_CheckDevAttResult(void *self, void *result_ptr); -static void Ats_CheckNwConfigStatus(void *self, void *result_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* State transition table (used by finite state machine) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief State transition table */ -static const Fsm_StateElem_t ats_trans_tab[ATS_NUM_STATES][ATS_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ -/* |--------------------------------|------------------------------------------------|------------------------------------------------|--------------------------------------|----------------------------------------| - * | ATS_E_NIL | ATS_E_NEXT | ATS_E_RETRY | ATS_E_ERROR | ATS_E_TIMEOUT | - * |--------------------------------|------------------------------------------------|------------------------------------------------|--------------------------------------|----------------------------------------| - */ - { {NULL, ATS_S_START }, {&Ats_StartPmsUnsync, ATS_S_PMS_UNSYNC }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_PMS_UNSYNC }, {&Ats_StartPmsInit, ATS_S_PMS_INIT }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_PMS_INIT }, {&Ats_StartVersChk, ATS_S_VERS_CHK }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_VERS_CHK }, {&Ats_StartInicOvhl, ATS_S_INIC_OVHL }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_INIC_OVHL }, {&Ats_StartDevAtt, ATS_S_DEV_ATT_STAGE_1}, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_DEV_ATT_STAGE_1}, {NULL, ATS_S_DEV_ATT_STAGE_2}, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_DEV_ATT_STAGE_2}, {NULL, ATS_S_DEV_ATT_STAGE_3}, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_DEV_ATT_STAGE_3}, {&Ats_StartNwConfig, ATS_S_NW_CONFIG }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_NW_CONFIG }, {&Ats_InitCpl, ATS_S_INIT_CPL }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_HandleError, ATS_S_ERROR}, {&Ats_HandleTimeout, ATS_S_ERROR} }, - { {NULL, ATS_S_INIT_CPL }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR}, {&Ats_InvalidTransition, ATS_S_ERROR} }, - { {NULL, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR }, {&Ats_InvalidTransition, ATS_S_ERROR}, {&Ats_InvalidTransition, ATS_S_ERROR} } -}; - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CAttachService */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the attach service class - * \param self Instance pointer - * \param init_ptr Reference to the initialization data - */ -void Ats_Ctor(CAttachService *self, Ats_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - T_Ctor(&self->timer); - self->report_result = UCS_INIT_RES_SUCCESS; - self->init_data = *init_ptr; - Ssub_Ctor(&self->ats_result_subject, self->init_data.base_ptr->ucs_user_ptr); - Fsm_Ctor(&self->fsm, self, &(ats_trans_tab[0][0]), ATS_NUM_EVENTS, ATS_S_START); - /* Initialize ATS service */ - Srv_Ctor(&self->ats_srv, ATS_SRV_PRIO, self, &Ats_Service); - /* Add ATS service to scheduler */ - (void)Scd_AddService(&self->init_data.base_ptr->scd, &self->ats_srv); -} - -/*! \brief Starts the attach process and the initialization timeout. - * \param self Instance pointer - * \param obs_ptr Reference to result observer - */ -void Ats_Start(void *self, CSingleObserver *obs_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - /* Observe internal errors during the attach process */ - Mobs_Ctor(&self_->internal_error_obs, self_, (EH_E_BIST_FAILED | EH_E_SYNC_LOST), &Ats_HandleInternalErrors); - Eh_AddObsrvInternalEvent(&self_->init_data.base_ptr->eh, &self_->internal_error_obs); - /* Set first event of attach state machine */ - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - /* Start timeout timer used for attach process */ - Tm_SetTimer(&self_->init_data.base_ptr->tm, - &self_->timer, - &Ats_TimeoutCb, - self_, - ATS_INIT_TIMEOUT, - 0U); - (void)Ssub_AddObserver(&self_->ats_result_subject, obs_ptr); -} - -/*! \brief Timer callback used for initialization timeout. - * \param self Instance pointer - */ -static void Ats_TimeoutCb(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - Fsm_SetEvent(&self_->fsm, ATS_E_TIMEOUT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); -} - -/*! \brief Service function of the attach service. - * \param self Instance pointer - */ -static void Ats_Service(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->ats_srv, &event_mask); - if (ATS_EVENT_SERVICE == (event_mask & ATS_EVENT_SERVICE)) /* Is event pending? */ - { - Fsm_State_t result; - Srv_ClearEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - result = Fsm_Service(&self_->fsm); - TR_ASSERT(self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", (result != FSM_STATE_ERROR)); - MISC_UNUSED(result); - } -} - -/*! \brief Resets all module internal observers. - * \param self Instance pointer - */ -static void Ats_ResetObservers(CAttachService *self) -{ - Eh_DelObsrvInternalEvent(&self->init_data.base_ptr->eh, &self->internal_error_obs); - Sobs_Ctor(&self->sobs, NULL, NULL); - Obs_Ctor(&self->obs, NULL, NULL); - Obs_Ctor(&self->obs2, NULL, NULL); -} - -/*------------------------------------------------------------------------------------------------*/ -/* State machine actions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief un-synchronizes PMS and observes PM events - * \param self Instance pointer - */ -static void Ats_StartPmsUnsync(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - Obs_Ctor(&self_->obs, self_, &Ats_CheckPmsUnsyncResult); - Fifos_ConfigureSyncParams(self_->init_data.fifos_ptr, FIFOS_SYNC_RETRIES, FIFOS_SYNC_TIMEOUT); - Fifos_Unsynchronize(self_->init_data.fifos_ptr, true, true); - Fifos_AddEventObserver(self_->init_data.fifos_ptr, &self_->obs); -} - -/*! \brief Synchronizes PMS and observes PM events - * \param self Instance pointer - */ -static void Ats_StartPmsInit(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - Obs_Ctor(&self_->obs, self_, &Ats_CheckPmsInitResult); - Pmev_Start(self_->init_data.pme_ptr); /* enables failure reporting to all modules */ - Fifos_Synchronize(self_->init_data.fifos_ptr, false, true); /* now synchronizes, counter is not reset to "0" */ - Fifos_AddEventObserver(self_->init_data.fifos_ptr, &self_->obs); -} - -/*! \brief Starts the request of the INIC firmware and hardware revisions. - * \param self Instance pointer - */ -static void Ats_StartVersChk(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - Sobs_Ctor(&self_->sobs, self_, &Ats_CheckVersChkResult); - if (Inic_DeviceVersion_Get(self_->init_data.inic_ptr, - &self_->sobs) != UCS_RET_SUCCESS) - { - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "INIC device version check failed!", 0U)); - self_->report_result = UCS_INIT_RES_ERR_BUF_OVERFLOW; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - } -} - -/*! \brief Starts the overhaul process of the INIC. - * \param self Instance pointer - */ -static void Ats_StartInicOvhl(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); -} - -/*! \brief Starts the attach process between EHC and INIC. - * \param self Instance pointer - */ -static void Ats_StartDevAtt(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_StartDevAtt() called", 0U)); - /* Assign observer to monitor the initial receipt of INIC message INIC.MOSTNetworkStatus */ - Obs_Ctor(&self_->obs, self_, &Ats_CheckNetworkStatusReceived); - Inic_AddObsrvNwStatus(self_->init_data.inic_ptr, &self_->obs); - /* Assign observer to monitor the initial receipt of INIC message INIC.DeviceStatus */ - Obs_Ctor(&self_->obs2, self_, &Ats_CheckDeviceStatusReceived); - Inic_AddObsvrDeviceStatus(self_->init_data.inic_ptr, &self_->obs2); - - /* Start device attach process */ - Sobs_Ctor(&self_->sobs, self_, &Ats_CheckDevAttResult); - if (Inic_DeviceAttach(self_->init_data.inic_ptr, &self_->sobs) != UCS_RET_SUCCESS) - { - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "INIC device attach failed!", 0U)); - self_->report_result = UCS_INIT_RES_ERR_BUF_OVERFLOW; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - } -} - -/*! \brief Starts request of network configuration property required - * to retrieve the own group address. - * \param self Instance pointer - */ -static void Ats_StartNwConfig(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - - /* Assign observer to monitor the initial receipt of INIC message INIC.MOSTNetworkConfigurarion */ - Sobs_Ctor(&self_->sobs, self_, &Ats_CheckNwConfigStatus); - - if (Inic_NwConfig_Get(self_->init_data.inic_ptr, &self_->sobs) != UCS_RET_SUCCESS) - { - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "INIC network configuration failed!", 0U)); - self_->report_result = UCS_INIT_RES_ERR_BUF_OVERFLOW; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - } -} - -/*! \brief This method is called when the initialization has been completed. - * \param self Instance pointer - */ -static void Ats_InitCpl(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - self_->report_result = UCS_INIT_RES_SUCCESS; - /* Attach process finished -> Reset observers and terminate state machine */ - Ats_ResetObservers(self_); - Tm_ClearTimer(&self_->init_data.base_ptr->tm, &self_->timer); - Fsm_End(&self_->fsm); - Eh_ReportEvent(&self_->init_data.base_ptr->eh, EH_E_INIT_SUCCEEDED); - Ssub_Notify(&self_->ats_result_subject, &self_->report_result, true); - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_InitCpl() called", 0U)); -} - -/*! \brief Handles internal errors during the attach process. - * \param self Instance pointer - * \param error_code_ptr Reference to reported error code - */ -static void Ats_HandleInternalErrors(void *self, void *error_code_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - uint32_t error_code = *((uint32_t *)error_code_ptr); - switch (error_code) - { - case EH_E_SYNC_LOST: - self_->report_result = UCS_INIT_RES_ERR_INIC_SYNC; - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "A control FiFo synchronization lost!", 0U)); - break; - case EH_E_BIST_FAILED: - self_->report_result = UCS_INIT_RES_ERR_INIC_SYSTEM; - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "INIC Build-In-Self-Test failed!", 0U)); - break; - default: - self_->report_result = UCS_INIT_RES_ERR_INTERNAL; - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Unknown internal error occurred! Error code: 0x%04X", 1U, error_code)); - break; - } - /* Error occurred -> Reset observers and terminate state machine */ - Ats_ResetObservers(self_); - Tm_ClearTimer(&self_->init_data.base_ptr->tm, &self_->timer); - Fsm_End(&self_->fsm); - Eh_ReportEvent(&self_->init_data.base_ptr->eh, EH_E_INIT_FAILED); - Ssub_Notify(&self_->ats_result_subject, &self_->report_result, true); -} - -/*! \brief Handles general errors during the attach process. - * \param self Instance pointer - */ -static void Ats_HandleError(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - /* Error occurred -> Reset observers and terminate state machine */ - Ats_ResetObservers(self_); - Tm_ClearTimer(&self_->init_data.base_ptr->tm, &self_->timer); - Fsm_End(&self_->fsm); - Eh_ReportEvent(&self_->init_data.base_ptr->eh, EH_E_INIT_FAILED); - Ssub_Notify(&self_->ats_result_subject, &self_->report_result, true); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Error occurred during initialization!", 0U)); -} - -/*! \brief Handles timeouts during the attach process. - * \param self Instance pointer - */ -static void Ats_HandleTimeout(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - self_->report_result = UCS_INIT_RES_ERR_TIMEOUT; - /* Error occurred -> Reset observers and terminate state machine */ - Ats_ResetObservers(self_); - Fsm_End(&self_->fsm); - Eh_ReportEvent(&self_->init_data.base_ptr->eh, EH_E_INIT_FAILED); - Ssub_Notify(&self_->ats_result_subject, &self_->report_result, true); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Initialization timeout occurred!", 0U)); -} - -/*! \brief This method is invoked if an invalid state machine transition is executed. - * \param self Instance pointer - */ -static void Ats_InvalidTransition(void *self) -{ - CAttachService *self_ = (CAttachService *)self; - self_->report_result = UCS_INIT_RES_ERR_INTERNAL; - /* Invalid Transition -> Reset observers and terminate state machine */ - Ats_ResetObservers(self_); - Tm_ClearTimer(&self_->init_data.base_ptr->tm, &self_->timer); - Fsm_End(&self_->fsm); - Eh_ReportEvent(&self_->init_data.base_ptr->eh, EH_E_INIT_FAILED); - Ssub_Notify(&self_->ats_result_subject, &self_->report_result, true); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Invalid transition within ATS state machine!", 0U)); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of the observer results */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Result callback for action "PMS Initialization". This function is part of an - * observer object and is invoked by Sub_Notify(). - * \param self Instance pointer - * \param result_ptr Reference to the received PMS event. The pointer must be casted into - * data type Fifos_Event_t. - */ -static void Ats_CheckPmsUnsyncResult(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Fifos_Event_t pms_event = *((Fifos_Event_t *)result_ptr); - - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckPmsUnsyncResult() called", 0U)); - - if (pms_event == FIFOS_EV_UNSYNC_COMPLETE) - { - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - } - else - { - self_->report_result = UCS_INIT_RES_ERR_INIC_SYNC; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckPmsUnsyncResult(): un-sync failed, event=0x%02X", 1U, pms_event)); - } - Fifos_RemoveEventObserver(self_->init_data.fifos_ptr, &self_->obs); -} - -/*! \brief Result callback for action "PMS Initialization". This function is part of an - * observer object and is invoked by Sub_Notify(). - * \param self Instance pointer - * \param result_ptr Reference to the received PMS event. The pointer must be casted into - * data type Fifos_Event_t. - */ -static void Ats_CheckPmsInitResult(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Fifos_Event_t pms_event = *((Fifos_Event_t *)result_ptr); - - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckPmsInitResult() called", 0U)); - - if (pms_event == FIFOS_EV_SYNC_ESTABLISHED) - { - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - } - else - { - self_->report_result = UCS_INIT_RES_ERR_INIC_SYNC; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckPmsInitResult(): sync failed, event=0x%02X", 1U, pms_event)); - } - Fifos_RemoveEventObserver(self_->init_data.fifos_ptr, &self_->obs); -} - -/*! \brief Result callback for action "Version Check". This function is part of a single - * observer object and is invoked by Ssub_Notify(). - * \param self Instance pointer - * \param result_ptr Reference to the received version check result. The pointer must be casted - * into data type Inic_StdResult_t. - */ -static void Ats_CheckVersChkResult(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - } - else - { - self_->report_result = UCS_INIT_RES_ERR_INIC_VERSION; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "INIC version check failed!", 0U)); - } - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckVersChkResult() called", 0U)); -} - -/*! \brief Result callback which handles one of three conditions for action "Device Attach". The - * function is called if INIC message INIC.MOSTNetworkStatus was received. The function is - * part of an observer object and is invoked by Sub_Notify(). The property - * INIC.MOSTNetworkStatus.Status() is notified. Thus, there is no error condition available. - * \param self Instance pointer - * \param result_ptr Reference to the MOST Network Status. The pointer must be casted into data - * type Inic_StdResult_t. - */ -static void Ats_CheckNetworkStatusReceived(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Inic_DelObsrvNwStatus(self_->init_data.inic_ptr, &self_->obs); - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - MISC_UNUSED(result_ptr); - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckNetworkStatusReceived() called", 0U)); -} - -/*! \brief Observer callback that is notified on received INIC.DeviceStatus - * \param self Instance pointer - * \param data_ptr The pointer to the current INIC.DeviceStatus structure - */ -static void Ats_CheckDeviceStatusReceived(void *self, void *data_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Inic_DelObsvrDeviceStatus(self_->init_data.inic_ptr, &self_->obs2); - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - MISC_UNUSED(data_ptr); - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckDeviceStatusReceived() called", 0U)); -} - -/*! \brief Result callback which handles one of two conditions for action "Device Attach". The - * function handles the result of the INIC method INIC.DeviceAttach. This function is part - * of a single-observer object and is invoked by Ssub_Notify(). - * \param self Instance pointer - * \param result_ptr Reference to the received device attach result. The pointer must be casted - * into data type Inic_StdResult_t. - */ -static void Ats_CheckDevAttResult(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Inic_StdResult_t error_data = *((Inic_StdResult_t *)result_ptr); - switch (error_data.result.code) - { - case UCS_RES_SUCCESS: - /* Operation succeeded */ - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - break; - case UCS_RES_ERR_CONFIGURATION: - /* Configuration error occurred -> attach process failed! */ - self_->report_result = UCS_INIT_RES_ERR_DEV_ATT_CFG; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Device attach failed due to an configuration error!", 0U)); - TR_ERROR_INIC_RESULT(self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", error_data.result.info_ptr, error_data.result.info_size); - break; - case UCS_RES_ERR_SYSTEM: - /* INIC is still attached -> attach process failed! */ - self_->report_result = UCS_INIT_RES_ERR_DEV_ATT_PROC; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "EHC is already attached to the INIC!", 0U)); - break; - default: - /* INIC reports an unexpected error -> attach process failed! */ - self_->report_result = UCS_INIT_RES_ERR_DEV_ATT_PROC; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Device attach failed! Unexpected error code = 0x%02X", 1U, error_data.result.code)); - TR_ERROR_INIC_RESULT(self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", error_data.result.info_ptr, error_data.result.info_size); - break; - } - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckDevAttResult() called", 0U)); -} - -/*! \brief Result callback for INIC network configuration - * \param self Instance pointer - * \param result_ptr Reference to the received network configuration status event. - * The pointer must be casted into data type Inic_StdResult_t. - */ -static void Ats_CheckNwConfigStatus(void *self, void *result_ptr) -{ - CAttachService *self_ = (CAttachService *)self; - Inic_StdResult_t error_data = *((Inic_StdResult_t *)result_ptr); - - if (error_data.result.code == UCS_RES_SUCCESS) - { - /* Operation succeeded */ - Fsm_SetEvent(&self_->fsm, ATS_E_NEXT); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - } - else - { - /* INIC reports an unexpected error -> attach process failed! */ - self_->report_result = UCS_INIT_RES_ERR_NET_CFG; - Fsm_SetEvent(&self_->fsm, ATS_E_ERROR); - Srv_SetEvent(&self_->ats_srv, ATS_EVENT_SERVICE); - TR_ERROR((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Network configuration failed! Unexpected error code = 0x%02X", 1U, error_data.result.code)); - TR_ERROR_INIC_RESULT(self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", error_data.result.info_ptr, error_data.result.info_size); - } - TR_INFO((self_->init_data.base_ptr->ucs_user_ptr, "[ATS]", "Ats_CheckNwConfigStatus() called", 0U)); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_base.c b/ucs2-lib/src/ucs_base.c deleted file mode 100644 index 583dd80..0000000 --- a/ucs2-lib/src/ucs_base.c +++ /dev/null @@ -1,69 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Base class. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_BASE - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_base.h" -#include "ucs_misc.h" -#include "ucs_message.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CBase */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Base class. - * \param self Instance pointer - * \param init_ptr Reference to the initialization data - */ -void Base_Ctor(CBase *self, Base_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - /* Save instance ID and user pointer */ - self->ucs_inst_id = init_ptr->ucs_inst_id; - self->ucs_user_ptr = init_ptr->ucs_user_ptr; - /* Create the scheduler instance */ - Scd_Ctor(&self->scd, &init_ptr->scd, init_ptr->ucs_user_ptr); - /* Create the timer management instance */ - Tm_Ctor(&self->tm, &self->scd, &init_ptr->tm, init_ptr->ucs_user_ptr); - /* Create the event handler instance */ - Eh_Ctor(&self->eh, init_ptr->ucs_user_ptr); - /* Create the API locking manager instance */ - Alm_Ctor(&self->alm, &self->tm, &self->eh, init_ptr->ucs_user_ptr); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_bc_diag.c b/ucs2-lib/src/ucs_bc_diag.c deleted file mode 100644 index c932c90..0000000 --- a/ucs2-lib/src/ucs_bc_diag.c +++ /dev/null @@ -1,784 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 BackChannel Diagnosis. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_BACKCHANNEL_DIAG - * @{ - - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_inic_pb.h" -#include "ucs_bc_diag.h" -#include "ucs_misc.h" - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -#define BCD_NUM_STATES 7U /*!< \brief Number of state machine states */ -#define BCD_NUM_EVENTS 12U /*!< \brief Number of state machine events */ - -#define BCD_TIMEOUT_COMMAND 100U /*!< \brief supervise EXC commands */ - -#define BCD_SIGNATURE_VERSION 1U /*!< \brief signature version used for BackChannel Diagnosis */ - -#define BCD_T_SEND 0x0100U -#define BCD_T_WAIT4DUT 0x1000U -#define BCD_T_SWITCH 0x0100U -#define BCD_T_BACK 0x2000U -#define BCD_TIMEOUT2 0x3000U -#define BCD_T_SIGNAL_ON 100U -#define BCD_T_LOCK 100U -#define BCD_T_LIGHT_PROGRESS 20U -#define BCD_AUTOBACK (true) -#define ADMIN_BASE_ADDR 0x0F00U - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the BackChannel Diagnosis used by scheduler */ -static const uint8_t BCD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the BackChannel Diagnosis */ -static const Srv_Event_t BCD_EVENT_SERVICE = 1U; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal enumerators */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Possible events of the BackChannel Diagnosis state machine */ -typedef enum Bcd_Events_ -{ - BCD_E_NIL = 0U, /*!< \brief NIL Event */ - BCD_E_START = 1U, /*!< \brief API start command was called. */ - BCD_E_DIAGMODE_END = 2U, /*!< \brief INIC.BCDiagEnd.Result successful. */ - BCD_E_DIAG_MODE_STARTED = 3U, /*!< \brief INIC.BCDiag.Result successful. */ - BCD_E_DIAG_MODE_FAILED = 4U, /*!< \brief INIC.BCDiag.Error received. */ - BCD_E_TX_ENABLE_SUCCESS = 5U, /*!< \brief EXC.BCEnableTx successful */ - BCD_E_TX_ENABLE_FAILED = 6U, /*!< \brief EXC.BCEnableTx failed. */ - BCD_E_DIAG_RESULT_OK = 7U, /*!< \brief EXC.BCDIAG.Result Ok received. */ - BCD_E_DIAG_RESULT_NOTOK = 8U, /*!< \brief EXC.BCDIAG.Result NotOk received. */ - BCD_E_NET_OFF = 9U, /*!< \brief NetOff occurred. */ - BCD_E_TIMEOUT = 10U, /*!< \brief Timeout occurred. */ - BCD_E_ERROR = 11U /*!< \brief An unexpected error occurred. */ - -} Bcd_Events_t; - - -/*! \brief States of the BackChannel Diagnosis state machine */ -typedef enum Bcd_State_ -{ - BCD_S_IDLE = 0U, /*!< \brief Idle state */ - BCD_S_STARTED = 1U, /*!< \brief BackChannel Diagnosis started */ - BCD_S_WAIT_ENABLED = 2U, /*!< \brief Wait for BCEnableTx.Result */ - BCD_S_WAIT_SIG_PROP = 3U, /*!< \brief Wait for signal propagating through the following nodes */ - BCD_S_WAIT_SIGNAL_ON = 4U, /*!< \brief Wait for t_SignalOn to expire. */ - BCD_S_WAIT_RESULT = 5U, /*!< \brief Wait for ENC.BCDiag.Result */ - BCD_S_END = 6U /*!< \brief BackChannel Diagnosis ends. */ -} Bcd_State_t; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Bcd_Service(void *self); - -static void Bcd_InicBcdStartCb(void *self, void *result_ptr); -static void Bcd_EnableTxResultCb(void *self, void *result_ptr); -static void Bcd_DiagnosisResultCb(void *self, void *result_ptr); -static void Bcd_InicBcdEndCb(void *self, void *result_ptr); - -static void Bcd_OnTerminateEventCb(void *self, void *result_ptr); -static void Bcd_NetworkStatusCb(void *self, void *result_ptr); - -static void Bcd_A_Start(void *self); -static void Bcd_A_EnableTx(void *self); -static void Bcd_A_DiagStart(void *self); -static void Bcd_A_NextSeg(void *self); -static void Bcd_A_StopDiag(void *self); -static void Bcd_A_Error(void *self); -static void Bcd_A_EndDiag(void *self); -static void Bcd_A_Timeout2(void *self); -static void Bcd_A_WaitLight(void *self); - - -static Ucs_Return_t Bcd_EnableTx(void *self, uint8_t port); - -static void Bcd_TimerCb(void *self); - -/*------------------------------------------------------------------------------------------------*/ -/* State transition table (used by finite state machine) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief State transition table */ -static const Fsm_StateElem_t bcd_trans_tab[BCD_NUM_STATES][BCD_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - { /* State BCD_S_IDLE */ - /* BCD_E_NIL */ {NULL, BCD_S_IDLE }, - /* BCD_E_START */ {Bcd_A_Start, BCD_S_STARTED }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_IDLE }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_IDLE }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_IDLE }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_IDLE }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_IDLE }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_IDLE }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_IDLE }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_IDLE }, - /* BCD_E_TIMEOUT */ {NULL, BCD_S_IDLE }, - /* BCD_E_ERROR */ {NULL, BCD_S_IDLE } - }, - { /* State BCD_S_STARTED */ - /* BCD_E_NIL */ {NULL, BCD_S_STARTED }, - /* BCD_E_START */ {NULL, BCD_S_STARTED }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_STARTED }, - /* BCD_E_DIAG_MODE_STARTED */ {Bcd_A_EnableTx, BCD_S_WAIT_ENABLED }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_STARTED }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_STARTED }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_STARTED }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_STARTED }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_STARTED }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_STARTED }, - /* BCD_E_TIMEOUT */ {Bcd_A_Timeout2, BCD_S_IDLE }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - }, - { /* State BCD_S_WAIT_ENABLED */ - /* BCD_E_NIL */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_START */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_TX_ENABLE_SUCCESS */ {Bcd_A_WaitLight, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_TX_ENABLE_FAILED */ {Bcd_A_Error, BCD_S_IDLE }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_WAIT_ENABLED }, - /* BCD_E_TIMEOUT */ {Bcd_A_Timeout2, BCD_S_IDLE }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - }, - { /* State BCD_S_WAIT_SIG_PROP */ - /* BCD_E_NIL */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_START */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_WAIT_SIG_PROP }, - /* BCD_E_TIMEOUT */ {Bcd_A_DiagStart, BCD_S_WAIT_RESULT }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - }, - { /* State BCD_S_WAIT_SIGNAL_ON */ - /* BCD_E_NIL */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_START */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_TIMEOUT */ {Bcd_A_EnableTx, BCD_S_WAIT_ENABLED }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - }, - { /* State BCD_S_WAIT_RESULT */ - /* BCD_E_NIL */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_START */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_DIAGMODE_END */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_DIAG_RESULT_OK */ {Bcd_A_NextSeg, BCD_S_WAIT_SIGNAL_ON }, - /* BCD_E_DIAG_RESULT_NOTOK */ {Bcd_A_StopDiag, BCD_S_END }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_WAIT_RESULT }, - /* BCD_E_TIMEOUT */ {Bcd_A_Timeout2, BCD_S_IDLE }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - }, - { /* State BCD_S_END */ - /* BCD_E_NIL */ {NULL, BCD_S_END }, - /* BCD_E_START */ {NULL, BCD_S_END }, - /* BCD_E_DIAGMODE_END */ {Bcd_A_EndDiag, BCD_S_IDLE }, - /* BCD_E_DIAG_MODE_STARTED */ {NULL, BCD_S_END }, - /* BCD_E_DIAG_MODE_FAILED */ {NULL, BCD_S_END }, - /* BCD_E_TX_ENABLE_SUCCESS */ {NULL, BCD_S_END }, - /* BCD_E_TX_ENABLE_FAILED */ {NULL, BCD_S_END }, - /* BCD_E_DIAG_RESULT_OK */ {NULL, BCD_S_END }, - /* BCD_E_DIAG_RESULT_NOTOK */ {NULL, BCD_S_END }, - /* BCD_E_NET_OFF */ {NULL, BCD_S_END }, - /* BCD_E_TIMEOUT */ {Bcd_A_Timeout2, BCD_S_IDLE }, - /* BCD_E_ERROR */ {Bcd_A_Error, BCD_S_IDLE } - } -}; - - -/*! \brief Constructor of class CBackChannelDiag. - * \param self Reference to CBackChannelDiag instance - * \param inic Reference to CInic instance - * \param base Reference to CBase instance - * \param exc Reference to CExc instance - */ - /* \param init_ptr Report callback function*/ -void Bcd_Ctor(CBackChannelDiag *self, CInic *inic, CBase *base, CExc *exc) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->inic = inic; - self->exc = exc; - self->base = base; - - Fsm_Ctor(&self->fsm, self, &(bcd_trans_tab[0][0]), BCD_NUM_EVENTS, BCD_E_NIL); - - - Sobs_Ctor(&self->bcd_inic_bcd_start, self, &Bcd_InicBcdStartCb); - Sobs_Ctor(&self->bcd_inic_bcd_end, self, &Bcd_InicBcdEndCb); - Sobs_Ctor(&self->bcd_enabletx, self, &Bcd_EnableTxResultCb); - Sobs_Ctor(&self->bcd_diagnosis, self, &Bcd_DiagnosisResultCb); - - - /* register termination events */ - Mobs_Ctor(&self->bcd_terminate, self, EH_M_TERMINATION_EVENTS, &Bcd_OnTerminateEventCb); - Eh_AddObsrvInternalEvent(&self->base->eh, &self->bcd_terminate); - - /* Register NetOn and MPR events */ - Obs_Ctor(&self->bcd_nwstatus, self, &Bcd_NetworkStatusCb); - Inic_AddObsrvNwStatus(self->inic, &self->bcd_nwstatus); - self->neton = false; - - /* Initialize Node Discovery service */ - Srv_Ctor(&self->service, BCD_SRV_PRIO, self, &Bcd_Service); - /* Add Node Discovery service to scheduler */ - (void)Scd_AddService(&self->base->scd, &self->service); - -} - - -/*! \brief Service function of the Node Discovery service. - * \param self Reference to Node Discovery object - */ -static void Bcd_Service(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->service, &event_mask); - if(BCD_EVENT_SERVICE == (event_mask & BCD_EVENT_SERVICE)) /* Is event pending? */ - { - Fsm_State_t result; - Srv_ClearEvent(&self_->service, BCD_EVENT_SERVICE); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); - result = Fsm_Service(&self_->fsm); - TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", (result != FSM_STATE_ERROR)); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "FSM -> %d", 1U, self_->fsm.current_state)); - MISC_UNUSED(result); - } -} - - -/**************************************************************************************************/ -/* API functions */ -/**************************************************************************************************/ -/*! \brief Program a node - * - * \param *self Reference to BackChannel Diagnosis object - * \param *report_fptr Reference to result callback used by BackChannel Diagnosis -*/ -void Bcd_Start(CBackChannelDiag *self, Ucs_Bcd_ReportCb_t report_fptr) -{ - self->report_fptr = report_fptr; - - Fsm_SetEvent(&self->fsm, BCD_E_START); - Srv_SetEvent(&self->service, BCD_EVENT_SERVICE); - - TR_INFO((self->base->ucs_user_ptr, "[BCD]", "Bcd_Start", 0U)); - -} - - - -/**************************************************************************************************/ -/* FSM Actions */ -/**************************************************************************************************/ -static void Bcd_A_Start(void *self) -{ - Ucs_Return_t ret_val; - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - /* send INIC.BCDiag.StartResult */ - ret_val = Inic_BCDiagnosis(self_->inic, &self_->bcd_inic_bcd_start); - - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_TIMEOUT_COMMAND, - 0U); - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); - } - - self_->current_segment = 0U; - - TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - -static void Bcd_A_EnableTx(void *self) -{ - Ucs_Return_t ret_val; - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - /* send ENC.EnableTx */ - ret_val = Bcd_EnableTx(self, 0U); - - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_TIMEOUT_COMMAND, - 0U); - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); - } - - TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - -/*! Starts the diagnosis command for one certain segment. - * - * \param *self The instance - */ -static void Bcd_A_DiagStart(void *self) -{ - Ucs_Return_t ret_val; - uint16_t t_send = BCD_T_SEND; - uint16_t t_wait4dut = BCD_T_WAIT4DUT; - uint16_t t_switch = BCD_T_SWITCH; - uint16_t t_back = BCD_T_BACK; - bool autoback = BCD_AUTOBACK; - - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - ret_val = Exc_BCDiag_Start(self_->exc, - self_->current_segment, - ADMIN_BASE_ADDR + self_->current_segment, - t_send, - t_wait4dut, - t_switch, - t_back, - autoback, - &self_->bcd_diagnosis); - - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_TIMEOUT2, - 0U); - - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); - } - - - MISC_UNUSED(ret_val); -} - - -static void Bcd_A_NextSeg(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - self_->report_fptr(UCS_BCD_RES_SUCCESS, - (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), - self_->base->ucs_user_ptr); - self_->current_segment += 1U; /* switch to next segment. */ - - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_T_SIGNAL_ON, - 0U); -} - -static void Bcd_A_StopDiag(void *self) -{ - Ucs_Return_t ret_val; - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - switch(self_->bcd_result.diag_result) - { - case DUT_MASTER: - self_->report_fptr(UCS_BCD_RES_NO_RING_BREAK, - (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), - self_->base->ucs_user_ptr); - break; - - case DUT_NO_ANSWER: - self_->report_fptr(UCS_BCD_RES_RING_BREAK, - (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), - self_->base->ucs_user_ptr); - break; - - case DUT_TIMEOUT: - self_->report_fptr(UCS_BCD_RES_TIMEOUT1, - (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), - self_->base->ucs_user_ptr); - break; - - default: - break; - } - - /* finish Back Channel Diagnosis Mode: send INIC.BCDiagEnd.StartResult */ - ret_val = Inic_BCDiagEnd(self_->inic, &self_->bcd_inic_bcd_end); - - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_TIMEOUT_COMMAND, - 0U); - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); - } - - MISC_UNUSED(ret_val); -} - - -static void Bcd_A_EndDiag(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_BCD_RES_END, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr); - } -} - -static void Bcd_A_Timeout2(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_BCD_RES_TIMEOUT2, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr); - } -} - -static void Bcd_A_WaitLight(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Bcd_TimerCb, - self_, - BCD_T_LOCK + (BCD_T_LIGHT_PROGRESS * (self_->current_segment + 1U)), - 0U); -} - - - - -/*! \brief An unecpected error occurred - * - * \param *self Reference to BackChannelDiagnosis object - */ -static void Bcd_A_Error(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_BCD_RES_ERROR, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr); - } - -} - - -/**************************************************************************************************/ -/* Callback functions */ -/**************************************************************************************************/ - -/*! \brief Function is called on reception of the Welcome.Result messsage - * \param self Reference to BackChannelDiagnosis object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Bcd_InicBcdStartCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_MODE_STARTED); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb BCD_E_DIAG_MODE_STARTED", 0U)); - } - else - { - uint8_t i; - - Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_MODE_FAILED); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb Error (code) 0x%x", 1U, result_ptr_->result.code)); - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i])); - } - } - - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); -} - - - -/*! \brief Function is called on reception of the BCEnableTx.Result messsage - * \param self Reference to BackChannelDiagnosis object - * \param result_ptr Pointer to the result of the BCEnableTx message - */ -static void Bcd_EnableTxResultCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - /* self_->signature_status = *(Exc_SignatureStatus_t *)(result_ptr_->data_info);*/ - Fsm_SetEvent(&self_->fsm, BCD_E_TX_ENABLE_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_EnableTxResultCb BCD_E_TX_ENABLE_SUCCESS", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_TX_ENABLE_FAILED); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_EnableTxResultCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); -} - - -/*! \brief Function is called on reception of the ENC.BCDiag.Result messsage - * \param self Reference to BackChannelDiagnosis object - * \param result_ptr Pointer to the result of the BCDiag message - */ -static void Bcd_DiagnosisResultCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - self_->bcd_result = *((Exc_BCDiagResult *)(result_ptr_->data_info)); - switch (self_->bcd_result.diag_result) - { - case DUT_SLAVE: - /* node reported working segment */ - Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_RESULT_OK); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_DiagnosisResultCb DUT_SLAVE", 0U)); - break; - - case DUT_MASTER: /* all segments are ok */ - case DUT_NO_ANSWER: /* ring break found */ - case DUT_TIMEOUT: /* no communication on back channel */ - Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_RESULT_NOTOK); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_DiagnosisResultCb others", 0U)); - break; - - default: - /* report error */ - break; - } - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_DiagnosisResultCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); -} - - -/*! \brief Function is called on reception of the INIC.BCDiagEnd.Result messsage - * \param self Reference to BackChannel Diagnosis object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Bcd_InicBcdEndCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, BCD_E_DIAGMODE_END); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdEndCb BCD_E_DIAGMODE_END", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, BCD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_InicBcdEndCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); -} - - -/*! Function is called on severe internal errors - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Reference to data - */ -static void Bcd_OnTerminateEventCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - MISC_UNUSED(result_ptr); - - if (self_->fsm.current_state != BCD_S_IDLE) - { - Tm_ClearTimer(&self_->base->tm, &self_->timer); - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_BCD_RES_ERROR, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr); - } - } -} - - -/*! \brief Callback function for the INIC.NetworkStatus status and error messages - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Pointer to the result of the INIC.NetworkStatus message - */ -static void Bcd_NetworkStatusCb(void *self, void *result_ptr) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_NetworkStatusCb 0x%x", 1U, result_ptr_->result.code)); - /* check for NetOn/NetOff events */ - if ( (self_->neton == true) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) ) - { - self_->neton = false; - Fsm_SetEvent(&self_->fsm, BCD_E_NET_OFF); - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); - } - /* check for NetOn/NetOff events */ - else if ( (self_->neton == false) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) ) - { -/* self_->neton = true; - self_->hello_neton_request = true; - Fsm_SetEvent(&self_->fsm, BCD_E_CHECK);*/ - } - /* check for MPR event */ - else if ( (((Inic_NetworkStatus_t *)(result_ptr_->data_info))->events & UCS_NETWORK_EVENT_NCE) - == UCS_NETWORK_EVENT_NCE) - { -/* self_->hello_mpr_request = true; - Fsm_SetEvent(&self_->fsm, BCD_E_CHECK);*/ - } - } - -} - - -/*! \brief Timer callback used for supervising INIC command timeouts. - * \param self Reference to Node Discovery object - */ -static void Bcd_TimerCb(void *self) -{ - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - Fsm_SetEvent(&self_->fsm, BCD_E_TIMEOUT); - TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_TimerCb BCD_E_TIMEOUT", 0U)); - - Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE); -} - - -/**************************************************************************************************/ -/* Helper functions */ -/**************************************************************************************************/ -static Ucs_Return_t Bcd_EnableTx(void *self, uint8_t port) -{ - Ucs_Return_t ret_val; - CBackChannelDiag *self_ = (CBackChannelDiag *)self; - - /* send INIC.BCDiag.StartResult */ - ret_val = Exc_BCEnableTx_StartResult(self_->exc, port, &self_->bcd_enabletx); - - TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS); - return ret_val; -} - - - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_class.c b/ucs2-lib/src/ucs_class.c deleted file mode 100644 index f999d43..0000000 --- a/ucs2-lib/src/ucs_class.c +++ /dev/null @@ -1,1790 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 UNICENS API. - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_class.h" -#include "ucs_misc.h" -#include "ucs_trace.h" -#include "ucs_ams.h" -#include "ucs_cmd.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Macros */ -/*------------------------------------------------------------------------------------------------*/ -/*! \def UCS_NUM_INSTANCES - * \brief Number of API instances which can be created by function Ucs_CreateInstance(). - * \details One API instance is used to communicate with one local INIC. In this case the application - * is connected to one network. - * It is possible access multiple networks by having multiple API instances. Each API instance - * requires communication with an exclusive INIC. - * Valid values: 1..10. Default Value: 1. - * \ingroup G_UCS_INIT_AND_SRV - */ -#ifndef UCS_NUM_INSTANCES -# define UCS_NUM_INSTANCES 1 -# define UCS_API_INSTANCES 1U /* default value */ -#elif (UCS_NUM_INSTANCES > 10) -# define UCS_API_INSTANCES 10U -#elif (UCS_NUM_INSTANCES < 1) -# define UCS_API_INSTANCES 1U -#else -# define UCS_API_INSTANCES ((uint8_t)UCS_NUM_INSTANCES) -#endif - -/*! \cond UCS_INTERNAL_DOC - * \addtogroup G_UCS_CLASS - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static bool Ucs_CheckInitData(const Ucs_InitData_t *init_ptr); -static void Ucs_Ctor(CUcs* self, uint8_t ucs_inst_id, void *api_user_ptr); -static void Ucs_InitComponents(CUcs* self); -static void Ucs_InitFactoryComponent(CUcs *self); -static void Ucs_InitBaseComponent(CUcs *self); -static void Ucs_InitPmsComponentConfig(CUcs *self); -static void Ucs_InitNetComponent(CUcs *self); -static void Ucs_InitLocalInicComponent(CUcs *self); -static void Ucs_InitRoutingComponent(CUcs *self); -static void Ucs_InitAtsClass(CUcs *self); -static void Ucs_InitExcComponent(CUcs *self); -static void Ucs_InitSysDiagComponent(CUcs *self); -static void Ucs_InitNodeDiscovery(CUcs *self); -static void Ucs_InitBackChannelDiagnosis(CUcs *self); -static void Ucs_InitProgramming(CUcs *self); -static void Ucs_InitManager(CUcs *self); -static void Ucs_InitResultCb(void *self, void *result_ptr); -static void Ucs_UninitResultCb(void *self, void *error_code_ptr); -static void Ucs_OnRxRcm(void *self, Msg_MostTel_t *tel_ptr); -static bool Ucs_OnRxMsgFilter(void *self, Msg_MostTel_t *tel_ptr); -static void Ucs_OnGetTickCount(void *self, void *tick_count_value_ptr); -static void Ucs_OnSetApplicationTimer(void *self, void *new_time_value_ptr); -static void Ucs_OnServiceRequest(void *self, void *result_ptr); -static void Ucs_OnGeneralError(void *self, void *result_ptr); -static void Ucs_Most_PortStatusCb(void *self, void *result_ptr); -static void Ucs_StartAppNotification(CUcs *self); -static void Ucs_StopAppNotification(CUcs *self); -static void Ucs_Inic_OnDeviceStatus(void *self, void *data_ptr); -static void Ucs_NetworkStartupResult(void *self, void *result_ptr); -static void Ucs_NetworkShutdownResult(void *self, void *result_ptr); -static void Ucs_NetworkForceNAResult(void *self, void *result_ptr); -static void Ucs_NetworkFrameCounterResult(void *self, void *result_ptr); -static void Ucs_NetworkStatus(void *self, void *result_ptr); -static void Ucs_InitPmsComponent(CUcs *self); -static void Ucs_InitPmsComponentApp(CUcs *self); -static void Ucs_InitAmsComponent(CUcs *self); -static void Ucs_AmsRx_Callback(void *self); -static void Ucs_AmsTx_FreedCallback(void *self, void *data_ptr); -static bool Ucs_McmRx_FilterCallback(void *self, Msg_MostTel_t *tel_ptr); -static Ucs_Nd_CheckResult_t Ucs_OnNdEvaluate(void *self, Ucs_Signature_t *signature_ptr); -static void Ucs_OnNdReport(void *self, Ucs_Nd_ResCode_t code, Ucs_Signature_t *signature_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Public Methods */ -/*------------------------------------------------------------------------------------------------*/ -extern Ucs_Inst_t* Ucs_CreateInstance(void) -{ - static CUcs api_instances[UCS_API_INSTANCES]; - static uint8_t next_index = 0U; - Ucs_Inst_t *inst_ptr = NULL; - - if (next_index < UCS_API_INSTANCES) - { - CUcs *ucs_ptr = &api_instances[next_index]; - ucs_ptr->ucs_inst_id = next_index + 1U; /* start with instance id "1" */ - TR_INFO((ucs_ptr->ucs_user_ptr, "[API]", "Ucs_CreateInstance(): returns 0x%p", 1U, ucs_ptr)); - inst_ptr = (Ucs_Inst_t*)(void*)ucs_ptr; /* convert API pointer to abstract data type */ - next_index++; - } - else - { - TR_INFO((0U, "[API]", "Ucs_CreateInstance(): failed!", 0U)); - } - - return inst_ptr; -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization structure */ -/*------------------------------------------------------------------------------------------------*/ -extern Ucs_Return_t Ucs_SetDefaultConfig(Ucs_InitData_t *init_ptr) -{ - Ucs_Return_t ret = UCS_RET_ERR_PARAM; - - if (init_ptr != NULL) - { - MISC_MEM_SET(init_ptr, 0, sizeof(*init_ptr)); - /* -- add default values here -- */ - init_ptr->general.inic_watchdog_enabled = true; - init_ptr->ams.enabled = true; - init_ptr->network.status.notification_mask = 0xFFFFU; /* Initialize notification masks for NET callbacks */ - init_ptr->mgr.packet_bw = MGR_PACKET_BW_DEFAULT; - init_ptr->mgr.enabled = false; - ret = UCS_RET_SUCCESS; - } - - TR_INFO((0U, "[API]", "Ucs_SetDefaultConfig(init_ptr: 0x%p): called", 1U, init_ptr)); - return ret; -} - -/*! \brief Checks if the given initialization data is valid - * \param init_ptr Reference to initialization data - * \return Returns \c true if the given initialization data is valid, otherwise \c false. - */ -static bool Ucs_CheckInitData(const Ucs_InitData_t *init_ptr) -{ - bool ret_val = true; - - if ((init_ptr == NULL) || /* General NULL pointer checks */ - (init_ptr->general.get_tick_count_fptr == NULL) || - (init_ptr->lld.start_fptr == NULL) || - (init_ptr->lld.stop_fptr == NULL) || - (init_ptr->lld.tx_transmit_fptr == NULL) - ) - { - TR_ERROR((0U, "[API]", "Initialization failed. Required initialization data contains a NULL pointer.", 0U)); - ret_val = false; - } - else if (((init_ptr->general.set_application_timer_fptr == NULL) && (init_ptr->general.request_service_fptr != NULL)) || - ((init_ptr->general.set_application_timer_fptr != NULL) && (init_ptr->general.request_service_fptr == NULL))) - { - TR_ERROR((0U, "[API]", "Initialization failed. To run UCS in event driven service mode, both callback functions must be assigned.", 0U)); - ret_val = false; - } - else if ((init_ptr->mgr.enabled != false) && ((init_ptr->nd.eval_fptr != NULL) || (init_ptr->nd.report_fptr != NULL))) - { - TR_INFO((0U, "[API]", "Ambiguous initialization structure. NodeDiscovery callback functions are not effective if 'mgr.enabled' is 'true'.", 0U)); - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Class initialization */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of API. Values are reset, initialization must be triggered via Ucs_Init(). - * \param self The instance - * \param ucs_inst_id The ID of the instance - * \param api_user_ptr The user reference for API callback functions - */ -static void Ucs_Ctor(CUcs* self, uint8_t ucs_inst_id, void *api_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); /* reset memory and backup/restore instance id */ - self->ucs_inst_id = ucs_inst_id; - self->ucs_user_ptr = api_user_ptr; -} - -extern Ucs_Return_t Ucs_Init(Ucs_Inst_t* self, const Ucs_InitData_t *init_ptr, Ucs_InitResultCb_t init_result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret = UCS_RET_ERR_PARAM; - - /* Note: "self_->ucs_inst_id" is already set to the correct value in Ucs_CreateInstance(), do not overwrite it */ - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Init(init_ptr: 0x%p): called", 1U, init_ptr)); - - if (Ucs_CheckInitData(init_ptr)) - { - Ucs_Ctor(self_, self_->ucs_inst_id, init_ptr->user_ptr);/* initialize object */ - self_->init_result_fptr = init_result_fptr; /* backup result callback function */ - - self_->init_data = *init_ptr; /* backup init data */ - Ucs_InitComponents(self_); /* call constructors and link all components */ - /* create init-complete observer */ - Sobs_Ctor(&self_->init_result_obs, self, &Ucs_InitResultCb); - Ats_Start(&self_->inic.attach, &self_->init_result_obs);/* Start attach process */ - ret = UCS_RET_SUCCESS; - } - /* register observer related to Ucs_Stop() */ - Mobs_Ctor(&self_->uninit_result_obs, self, (EH_E_UNSYNC_COMPLETE | EH_E_UNSYNC_FAILED), &Ucs_UninitResultCb); - return ret; -} - -extern void Ucs_Service(Ucs_Inst_t* self) -{ - CUcs *self_ = (CUcs*)(void*)self; - bool pending_events = false; - - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Service(): called", 0U)); - Scd_Service(&self_->general.base.scd); /* Run the scheduler */ - pending_events = Scd_AreEventsPending(&self_->general.base.scd); /* Check if events are still pending? */ - - if (pending_events != false) /* At least one event is pending? */ - { - if (self_->general.request_service_fptr != NULL) - { - self_->general.request_service_fptr(self_->ucs_user_ptr); /* Trigger UCS service call immediately */ - } - } - - Tm_CheckForNextService(&self_->general.base.tm); /* If UCS timers are running: What is the next time that - * the timer management must be serviced again? */ -} - -extern void Ucs_ReportTimeout(Ucs_Inst_t* self) -{ - CUcs *self_ = (CUcs*)(void*)self; - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_ReportTimeout(): called", 0U)); - Tm_TriggerService(&self_->general.base.tm); /* Trigger TM service call */ -} - -extern Ucs_Return_t Ucs_Stop(Ucs_Inst_t* self, Ucs_StdResultCb_t stopped_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Stop() called", 0U)); - - if ((self_->uninit_result_fptr == NULL) && (self_->init_complete != false)) - { - if (stopped_fptr != NULL) - { - self_->uninit_result_fptr = stopped_fptr; - Eh_DelObsrvPublicError(&self_->general.base.eh); - Eh_AddObsrvInternalEvent(&self_->general.base.eh, &self_->uninit_result_obs); - ret_val = UCS_RET_SUCCESS; - Fifos_ConfigureSyncParams(&self_->fifos, FIFOS_UNSYNC_RETRIES, FIFOS_UNSYNC_TIMEOUT); - Fifos_Unsynchronize(&self_->fifos, true, false); - } - } - else - { - ret_val = UCS_RET_ERR_API_LOCKED; /* termination is already running */ - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Connection Routing Management */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Rm_Start(Ucs_Inst_t *self, Ucs_Rm_Route_t *routes_list, uint16_t list_size) -{ - CUcs *self_ = (CUcs*)(void*)self; - - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (self_->init_complete != false) - { - ret_val = Rtm_StartProcess (&self_->rtm, routes_list, list_size); - } - - return ret_val; -} - -Ucs_Return_t Ucs_Rm_SetRouteActive (Ucs_Inst_t *self, Ucs_Rm_Route_t *route_ptr, bool active) -{ - CUcs *self_ = (CUcs*)(void*)self; - - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if ((self_ != NULL) && (route_ptr != NULL)) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - if (!active) - { - ret_val = Rtm_DeactivateRoute(&self_->rtm, route_ptr); - } - else - { - ret_val = Rtm_ActivateRoute(&self_->rtm, route_ptr); - } - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Xrm_Stream_SetPortConfig(Ucs_Inst_t *self, - uint16_t destination_address, - uint8_t index, - Ucs_Stream_PortOpMode_t op_mode, - Ucs_Stream_PortOption_t port_option, - Ucs_Stream_PortClockMode_t clock_mode, - Ucs_Stream_PortClockDataDelay_t clock_data_delay, - Ucs_Xrm_Stream_PortCfgResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Xrm_Stream_SetPortConfig(Fac_GetXrmLegacy(&self_->factory, destination_address, self_->init_data.rm.xrm.check_unmute_fptr), - index, - op_mode, - port_option, - clock_mode, - clock_data_delay, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Xrm_Stream_GetPortConfig(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index, - Ucs_Xrm_Stream_PortCfgResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Xrm_Stream_GetPortConfig(Fac_GetXrmLegacy(&self_->factory, destination_address, self_->init_data.rm.xrm.check_unmute_fptr), - index, result_fptr); - } - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Node Management */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Rm_SetNodeAvailable(Ucs_Inst_t *self, Ucs_Rm_Node_t *node_ptr, bool available) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if ((self_ != NULL) && (node_ptr != NULL)) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Rtm_SetNodeAvailable(&self_->rtm, node_ptr, available); - } - } - - return ret_val; -} - -bool Ucs_Rm_GetNodeAvailable (Ucs_Inst_t *self, Ucs_Rm_Node_t *node_ptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - bool ret_val = false; - - if ((self_ != NULL) && (node_ptr != NULL)) - { - ret_val = Rtm_GetNodeAvailable(&self_->rtm, node_ptr); - } - - return ret_val; -} - -Ucs_Return_t Ucs_Rm_GetAttachedRoutes (Ucs_Inst_t *self, Ucs_Rm_EndPoint_t * ep_inst, - Ucs_Rm_Route_t * ls_found_routes[], uint16_t ls_size) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Rtm_GetAttachedRoutes(&self_->rtm, ep_inst, ls_found_routes, ls_size); - } - } - - return ret_val; -} - -uint16_t Ucs_Rm_GetConnectionLabel(Ucs_Inst_t *self, Ucs_Rm_Route_t *route_ptr) -{ - uint16_t ret_value = 0U; - CUcs *self_ = (CUcs*)(void*)self; - - if ((self_ != NULL) && (self_->init_complete != false) && (route_ptr != NULL)) - { - ret_value = Rtm_GetConnectionLabel(&self_->rtm, route_ptr); - } - - return ret_value; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Node Scripting Management */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Ns_Run (Ucs_Inst_t *self, Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if ((self_ != NULL) && (node_ptr != NULL) && (node_ptr->signature_ptr != NULL)) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - CNodeScriptManagement * nsm_inst = Fac_GetNsm(&self_->factory, node_ptr->signature_ptr->node_address); - - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - if (nsm_inst != NULL) - { - ret_val = Nsm_Run_Pb(nsm_inst, node_ptr, result_fptr); - } - } - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* GPIO and I2C Peripheral Bus Interfaces */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Gpio_CreatePort(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index, uint16_t debounce_time, Ucs_Gpio_CreatePortResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Gpio_CreatePort(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr), - index, - debounce_time, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Gpio_SetPinMode(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, - uint8_t pin, Ucs_Gpio_PinMode_t mode, Ucs_Gpio_ConfigPinModeResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Gpio_SetPinModeConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr), - gpio_port_handle, - pin, - mode, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Gpio_GetPinMode(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, Ucs_Gpio_ConfigPinModeResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Gpio_GetPinModeConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr), - gpio_port_handle, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Gpio_WritePort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, - uint16_t mask, uint16_t data, Ucs_Gpio_PinStateResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Gpio_SetPinStateConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr), - gpio_port_handle, - mask, - data, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_Gpio_ReadPort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, Ucs_Gpio_PinStateResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Gpio_GetPinStateConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr), - gpio_port_handle, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_I2c_CreatePort(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index, Ucs_I2c_Speed_t speed, - uint8_t i2c_int_mask, Ucs_I2c_CreatePortResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = I2c_CreatePort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr), - index, - speed, - i2c_int_mask, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_I2c_WritePort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t port_handle, Ucs_I2c_TrMode_t mode, uint8_t block_count, - uint8_t slave_address, uint16_t timeout, uint8_t data_len, uint8_t * data_ptr, - Ucs_I2c_WritePortResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = I2c_WritePort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr), - port_handle, - mode, - block_count, - slave_address, - timeout, - data_len, - data_ptr, - result_fptr); - } - } - - return ret_val; -} - -Ucs_Return_t Ucs_I2c_ReadPort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t port_handle, uint8_t slave_address, uint8_t data_len, - uint16_t timeout, Ucs_I2c_ReadPortResCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if (self_ != NULL) - { - ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = I2c_ReadPort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr), - port_handle, - slave_address, - data_len, - timeout, - result_fptr); - } - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Components */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initializes all UCS core components - * \param self The instance - */ -static void Ucs_InitComponents(CUcs* self) -{ - Ucs_InitBaseComponent(self); - Ucs_InitFactoryComponent(self); - Ucs_InitLocalInicComponent(self); - Ucs_InitNetComponent(self); - Ucs_InitPmsComponent(self); - Ucs_InitAmsComponent(self); - Ucs_InitRoutingComponent(self); - Ucs_InitAtsClass(self); - - Ucs_InitExcComponent(self); - Ucs_InitSysDiagComponent(self); - Ucs_InitNodeDiscovery(self); - Ucs_InitBackChannelDiagnosis(self); - Ucs_InitProgramming(self); - Ucs_InitManager(self); /* shall be called as last one due to re-configuration work */ -} - -/*! \brief Initializes the factory component - * \param self The instance - */ -static void Ucs_InitFactoryComponent(CUcs *self) -{ - Fac_InitData_t fac_init_data; - fac_init_data.base_ptr = &self->general.base; - fac_init_data.net_ptr = &self->net.inst; - fac_init_data.xrmp_ptr = &self->xrmp; - fac_init_data.icm_transceiver = &self->icm_transceiver; - fac_init_data.rcm_transceiver = &self->rcm_transceiver; - Fac_Ctor(&self->factory, &fac_init_data); -} - -/*! \brief Initializes the the base component - * \param self The instance - */ -static void Ucs_InitBaseComponent(CUcs *self) -{ - Base_InitData_t base_init_data; - - if (self->init_data.general.request_service_fptr != NULL) /* pointer may be NULL for termination */ - { - self->general.request_service_fptr = self->init_data.general.request_service_fptr; - Sobs_Ctor(&self->general.service_request_obs, self, &Ucs_OnServiceRequest); - base_init_data.scd.service_request_obs_ptr = &self->general.service_request_obs; - } - else - { - base_init_data.scd.service_request_obs_ptr = NULL; - } - - self->general.get_tick_count_fptr = self->init_data.general.get_tick_count_fptr; - Sobs_Ctor(&self->general.get_tick_count_obs, self, &Ucs_OnGetTickCount); - base_init_data.tm.get_tick_count_obs_ptr = &self->general.get_tick_count_obs; - if (self->init_data.general.set_application_timer_fptr != NULL) - { - self->general.set_application_timer_fptr = self->init_data.general.set_application_timer_fptr; - Sobs_Ctor(&self->general.set_application_timer_obs, self, &Ucs_OnSetApplicationTimer); - base_init_data.tm.set_application_timer_obs_ptr = &self->general.set_application_timer_obs; - } - else - { - base_init_data.tm.set_application_timer_obs_ptr = NULL; - } - base_init_data.ucs_inst_id = self->ucs_inst_id; - base_init_data.ucs_user_ptr = self->ucs_user_ptr; - Base_Ctor(&self->general.base, &base_init_data); -} - -/*! \brief Initializes the port message service - * \param self The instance - */ -static void Ucs_InitPmsComponent(CUcs *self) -{ - CPmFifo * mcm_fifo_ptr = NULL; - - if (self->init_data.ams.enabled == true) - { - mcm_fifo_ptr = &self->msg.mcm_fifo; - } - - Ucs_InitPmsComponentConfig(self); - Ucs_InitPmsComponentApp(self); - - Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, &self->icm_fifo, mcm_fifo_ptr, &self->rcm_fifo); - Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */ -} - -/*! \brief Initializes the port message service - * \param self The instance - */ -static void Ucs_InitPmsComponentConfig(CUcs *self) -{ - Pmch_InitData_t pmch_init_data; - Fifo_InitData_t icm_init; - Fifo_Config_t icm_config; - Fifo_InitData_t rcm_init; - Fifo_Config_t rcm_config; - - /* Initialize port message service */ - pmch_init_data.ucs_user_ptr = self->ucs_user_ptr; - pmch_init_data.tx_release_fptr = &Fifo_TxOnRelease; - pmch_init_data.lld_iface = self->init_data.lld; - Pmch_Ctor(&self->pmch, &pmch_init_data); - - /* Initialize the ICM channel */ - icm_init.base_ptr = &self->general.base; - icm_init.channel_ptr = &self->pmch; - icm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete; - icm_init.rx_cb_inst = &self->icm_transceiver; - icm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - icm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - icm_config.fifo_id = PMP_FIFO_ID_ICM; - icm_config.tx_wd_timeout = 0U; - icm_config.tx_wd_timer_value = 0U; - icm_config.rx_ack_timeout = 10U; - icm_config.rx_busy_allowed = 0xFU; - icm_config.rx_credits = PMCH_FIFO_CREDITS; - icm_config.rx_threshold = PMCH_FIFO_THRESHOLD; - if (self->init_data.general.inic_watchdog_enabled == false) - { - icm_config.rx_ack_timeout = 0U; - } - Fifo_Ctor(&self->icm_fifo, &icm_init, &icm_config); - - /* Initialize the RCM channel */ - rcm_init.base_ptr = &self->general.base; - rcm_init.channel_ptr = &self->pmch; - rcm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete; - rcm_init.rx_cb_inst = &self->rcm_transceiver; - rcm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - rcm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - rcm_config.fifo_id = PMP_FIFO_ID_RCM; - rcm_config.tx_wd_timeout = 10U; /* Watchdog timeout: 1s */ - rcm_config.tx_wd_timer_value = 600U; /* Watchdog trigger every 600 ms */ - rcm_config.rx_ack_timeout = 10U; /* Acknowledge timeout: 10 ms */ - rcm_config.rx_busy_allowed = 0xFU; - rcm_config.rx_credits = PMCH_FIFO_CREDITS; - rcm_config.rx_threshold = PMCH_FIFO_THRESHOLD; - if (self->init_data.general.inic_watchdog_enabled == false) - { - /* Disable INIC watchdog */ - rcm_config.tx_wd_timeout = 0U; /* Watchdog timeout: 0 -> infinite */ - rcm_config.tx_wd_timer_value = 0U; /* Watchdog timer: 0 -> no timer */ - rcm_config.rx_ack_timeout = 0U; /* Acknowledge timeout: 0 -> infinite */ - } - Fifo_Ctor(&self->rcm_fifo, &rcm_init, &rcm_config); -#if 0 - Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, &self->icm_fifo, NULL/*MCM*/, &self->rcm_fifo); - Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */ -#endif - - /* initialize transceivers and set reference to FIFO instance */ - Trcv_Ctor(&self->icm_transceiver, &self->icm_fifo, MSG_ADDR_EHC_CFG, self->ucs_user_ptr, PMP_FIFO_ID_ICM); - Trcv_RxAssignFilter(&self->icm_transceiver, &Ucs_OnRxMsgFilter, self); - Trcv_RxAssignReceiver(&self->icm_transceiver, &Inic_OnIcmRx, self->inic.local_inic); - Trcv_Ctor(&self->rcm_transceiver, &self->rcm_fifo, MSG_ADDR_EHC_CFG, self->ucs_user_ptr, PMP_FIFO_ID_RCM); - /* Assign RX filter and receiver function to the RCM transceiver */ - Trcv_RxAssignFilter(&self->rcm_transceiver, &Ucs_OnRxMsgFilter, self); - Trcv_RxAssignReceiver(&self->rcm_transceiver, &Ucs_OnRxRcm, self); -} - -/*! \brief Initializes the network management component - * \param self The instance - */ -static void Ucs_InitNetComponent(CUcs *self) -{ - Net_InitData_t net_init_data; - - Sobs_Ctor(&self->net.startup_obs, self, &Ucs_NetworkStartupResult); - Sobs_Ctor(&self->net.shutdown_obs, self, &Ucs_NetworkShutdownResult); - Sobs_Ctor(&self->net.force_na_obs, self, &Ucs_NetworkForceNAResult); - Sobs_Ctor(&self->net.frame_counter_obs, self, &Ucs_NetworkFrameCounterResult); - net_init_data.base_ptr = &self->general.base; - net_init_data.inic_ptr = self->inic.local_inic; - Net_Ctor(&self->net.inst, &net_init_data); -} - -/*! \brief Initializes the FBlock INIC - * \param self The instance - */ -static void Ucs_InitLocalInicComponent(CUcs *self) -{ - self->inic.local_inic = Fac_GetInic(&self->factory, UCS_ADDR_LOCAL_INIC); - Obs_Ctor(&self->inic.device_status_obs, self, &Ucs_Inic_OnDeviceStatus); -} - -/*! \brief Initializes the Routing components - * \param self The instance - */ -static void Ucs_InitRoutingComponent(CUcs *self) -{ - Epm_InitData_t epm_init; - Rtm_InitData_t rtm_init; - - /* Initialize the unique XRM Pool Instance */ - Xrmp_Ctor(&self->xrmp); - - /* Initialize the EndPoint Management Instance */ - epm_init.base_ptr = &self->general.base; - epm_init.fac_ptr = &self->factory; - epm_init.res_debugging_fptr = self->init_data.rm.debug_resource_status_fptr; - epm_init.check_unmute_fptr = self->init_data.rm.xrm.check_unmute_fptr; - Epm_Ctor (&self->epm, &epm_init); - - /* Initialize the Routes Management Instance */ - rtm_init.base_ptr = &self->general.base; - rtm_init.epm_ptr = &self->epm; - rtm_init.net_ptr = &self->net.inst; - rtm_init.report_fptr = self->init_data.rm.report_fptr; - Rtm_Ctor(&self->rtm, &rtm_init); -} - -/*! \brief Initializes the attach service - * \param self The instance - */ -static void Ucs_InitAtsClass(CUcs *self) -{ - Ats_InitData_t ats_init_data; - ats_init_data.base_ptr = &self->general.base; - ats_init_data.fifos_ptr = &self->fifos; - ats_init_data.inic_ptr = self->inic.local_inic; - ats_init_data.pme_ptr = &self->pme; - Ats_Ctor(&self->inic.attach, &ats_init_data); -} - -/*! \brief Initializes the FBlock ExtendedNetworkControl API - * \param self The instance - */ -static void Ucs_InitExcComponent(CUcs *self) -{ - /* Create the FBlock ExtendedNetworkControl instance */ - Exc_Ctor(&self->exc, &self->general.base, &self->rcm_transceiver); -} - -/*! \brief Initializes the SystemDiagnosis component - * \param self The instance - */ -static void Ucs_InitSysDiagComponent(CUcs *self) -{ - /* Create the System Diagnosis instance */ - SysDiag_Ctor(&self->sys_diag, self->inic.local_inic, &self->general.base, &self->exc); -} - - -static void Ucs_InitNodeDiscovery(CUcs *self) -{ - Nd_InitData_t nd_init_data; - - if (self->init_data.mgr.enabled == false) - { - nd_init_data.inst_ptr = self; - nd_init_data.report_fptr = &Ucs_OnNdReport; - nd_init_data.eval_fptr = &Ucs_OnNdEvaluate; - } - else - { - nd_init_data.inst_ptr = &self->nobs; - nd_init_data.report_fptr = &Nobs_OnNdReport; - nd_init_data.eval_fptr = &Nobs_OnNdEvaluate; - } - - Nd_Ctor(&self->nd, self->inic.local_inic, &self->general.base, &self->exc, &nd_init_data); - -} - -static void Ucs_InitBackChannelDiagnosis(CUcs *self) -{ - Bcd_Ctor(&self->bcd, self->inic.local_inic, &self->general.base, &self->exc); -} - -static void Ucs_InitProgramming(CUcs *self) -{ - Prg_Ctor(&self->prg, self->inic.local_inic, &self->general.base, &self->exc); -} - - -/*! \brief Initializes the Manager class - * \details This function shall be called as the latest initialization function since - * it may disable some of the conventional API. - * \param self The instance - */ -static void Ucs_InitManager(CUcs *self) -{ - if (self->init_data.mgr.enabled == true) - { - Mgr_Ctor(&self->mgr, &self->general.base, self->inic.local_inic, &self->net.inst, &self->nd, self->init_data.mgr.packet_bw); - Nobs_Ctor(&self->nobs, &self->general.base, &self->nd, &self->rtm, &self->init_data.mgr); - } -} - - -/*! \brief Callback function which announces the result of the attach process - * \param self The instance - * \param result_ptr Result of the initialization process. Result must be casted into data type - * Ucs_InitResult_t. Possible return values are shown in the table below. - * Result Code | Description - * ----------------------------- | ---------------------------------------------------- - * UCS_INIT_RES_SUCCESS | Initialization succeeded - * UCS_INIT_RES_ERR_BUF_OVERFLOW | No message buffer available - * UCS_INIT_RES_ERR_PMS_INIT | PMS Initialization failed - * UCS_INIT_RES_ERR_INIC_VERSION | INIC device version check failed - * UCS_INIT_RES_ERR_DEV_ATT_CFG | Device attach failed due to an configuration error - * UCS_INIT_RES_ERR_DEV_ATT_PROC | Device attach failed due to a system error - * UCS_INIT_RES_ERR_NET_CFG | Network configuration failed - * UCS_INIT_RES_ERR_TIMEOUT | Initialization timeout occurred - */ -static void Ucs_InitResultCb(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Ucs_InitResult_t *result_ptr_ = (Ucs_InitResult_t *)result_ptr; - - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_InitResultCb(): Ucs_Init() completed, internal event code: %u", 1U, *result_ptr_)); - if (*result_ptr_ != UCS_INIT_RES_SUCCESS) - { - Ucs_StopAppNotification(self_); - } - - if (self_->init_result_fptr != NULL) - { - self_->init_result_fptr(*result_ptr_, self_->ucs_user_ptr); - } - - /* Start notification if initialization succeeded */ - if (*result_ptr_ == UCS_INIT_RES_SUCCESS) - { - self_->init_complete = true; - Ucs_StartAppNotification(self_); - } -} - -/*! \brief Callback function which announces the result of Ucs_Stop() - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Ucs_UninitResultCb(void *self, void *error_code_ptr) -{ - CUcs *self_ = (CUcs*)self; - uint32_t error_code = *((uint32_t *)error_code_ptr); - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_UninitResultCb(): Ucs_Stop() completed, internal event code: %u", 1U, error_code)); - - self_->init_complete = false; - Eh_DelObsrvInternalEvent(&self_->general.base.eh, &self_->uninit_result_obs); - - Ucs_StopAppNotification(self_); - - if (self_->uninit_result_fptr != NULL) - { - Ucs_StdResult_t result; - - result.code = UCS_RES_SUCCESS; - result.info_ptr = NULL; - result.info_size = 0U; - - if (error_code != EH_E_UNSYNC_COMPLETE) - { - result.code = UCS_RES_ERR_TIMEOUT; - } - - self_->uninit_result_fptr(result, self_->ucs_user_ptr); - self_->uninit_result_fptr = NULL; - } -} - -/*! \brief Starts the notification after the initialization has succeeded - * \param self The instance - */ -static void Ucs_StartAppNotification(CUcs *self) -{ - self->general.general_error_fptr = self->init_data.general.error_fptr; /* assign general error notification */ - Sobs_Ctor(&self->general.general_error_obs, self, &Ucs_OnGeneralError); - Eh_AddObsrvPublicError(&self->general.base.eh, &self->general.general_error_obs); - - if (self->init_data.network.status.cb_fptr != NULL) /* Start notification of Network Status */ - { - self->net.status_fptr = self->init_data.network.status.cb_fptr; - Mobs_Ctor(&self->net.status_obs, - self, - (uint32_t)self->init_data.network.status.notification_mask, - &Ucs_NetworkStatus); - Net_AddObserverNetworkStatus(&self->net.inst, &self->net.status_obs); - } - - if ((self->init_data.ams.tx.message_freed_fptr != NULL) && (self->msg.ams_tx_alloc_failed != false)) - { - self->msg.ams_tx_alloc_failed = false; - self->init_data.ams.tx.message_freed_fptr(self->ucs_user_ptr); - } - - if (self->init_data.inic.power_state_fptr != NULL) - { - self->inic.power_state = Inic_GetDevicePowerState(self->inic.local_inic); /* remember the current value */ - self->init_data.inic.power_state_fptr(self->inic.power_state, self->ucs_user_ptr); - Inic_AddObsvrDeviceStatus(self->inic.local_inic, &self->inic.device_status_obs); - } - - if(self->init_data.rm.xrm.most_port_status_fptr != NULL) /* Initialize callback pointer for MOST port status callback */ - { - self->xrm.most_port_status_fptr = self->init_data.rm.xrm.most_port_status_fptr; - Obs_Ctor(&self->xrm.most_port_status_obs, self, &Ucs_Most_PortStatusCb); - Inic_AddObsrvMostPortStatus(self->inic.local_inic, &self->xrm.most_port_status_obs); - } -} - -/*! \brief Stops application events for timer management and event service - * \param self The instance - */ -static void Ucs_StopAppNotification(CUcs *self) -{ - self->general.request_service_fptr = NULL; /* clear service request to avoid any pending events to be called again */ - Tm_StopService(&self->general.base.tm); /* stop timer service */ -} - -/*------------------------------------------------------------------------------------------------*/ -/* Message Routing */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Callback function to receive RCM Rx messages - * \param self The UCS instance - * \param tel_ptr The received RCM Rx message object - * \return Returns \c true to discard the message and free it to the pool (no-pass). - * Otherwise, returns \c false (pass). - */ -static void Ucs_OnRxRcm(void *self, Msg_MostTel_t *tel_ptr) -{ - CUcs *self_ = (CUcs*)self; - - if (tel_ptr->id.fblock_id == FB_EXC) - { - Exc_OnRcmRxFilter(&(self_->exc), tel_ptr); - } - else if (tel_ptr->id.fblock_id == FB_INIC) - { - if (!Nsm_OnRcmRxFilter(Fac_FindNsm(&self_->factory, tel_ptr->source_addr), tel_ptr)) - { - CInic * inic_ptr = Fac_FindInic(&self_->factory, tel_ptr->source_addr); - if (inic_ptr != NULL) - { - Inic_OnRcmRxFilter(inic_ptr, tel_ptr); - } - } - } - - Trcv_RxReleaseMsg(&self_->rcm_transceiver, tel_ptr); /* free Rx telegram */ -} - -/*! \brief Callback function which filters Control Rx messages - * \param self The UCS instance - * \param tel_ptr The received Rx message object - * \return Returns \c true to discard the message and free it to the pool (no-pass). - * Otherwise, returns \c false (pass). - */ -static bool Ucs_OnRxMsgFilter(void *self, Msg_MostTel_t *tel_ptr) -{ - CUcs *self_ = (CUcs*)self; - bool ret = false; /* just pass - do not discard message */ - - if (self_->rx_filter_fptr != NULL) - { - ret = self_->rx_filter_fptr(tel_ptr, self_->ucs_user_ptr); - } - - if (ret == false) - { - if ((tel_ptr->id.op_type == UCS_OP_ERROR) || (tel_ptr->id.op_type == UCS_OP_ERRORACK)) - { - if (self_->init_data.general.debug_error_msg_fptr != NULL) - { - self_->init_data.general.debug_error_msg_fptr(tel_ptr, self_->ucs_user_ptr); - } - } - } - else - { - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_OnRxMsgFilter(): message discarded by unit test", 0U)); - } - - return ret; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Observers / Basic API */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Callback function which is invoked to request the current tick count value - * \param self The instance - * \param tick_count_value_ptr Reference to the requested tick count value. The pointer must - * be casted into data type uint16_t. - */ -static void Ucs_OnGetTickCount(void *self, void *tick_count_value_ptr) -{ - CUcs *self_ = (CUcs*)self; - *((uint16_t *)tick_count_value_ptr) = self_->general.get_tick_count_fptr(self_->ucs_user_ptr); -} - -/*! \brief Callback function which is invoked to start the application timer when the UNICENS service - * is implemented event driven - * \param self The instance - * \param new_time_value_ptr Reference to the new timer value. The pointer must be casted into - * data type uint16_t. - */ -static void Ucs_OnSetApplicationTimer(void *self, void *new_time_value_ptr) -{ - CUcs *self_ = (CUcs*)self; - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_OnSetApplicationTimer(%d)", 1U, *((uint16_t *)new_time_value_ptr))); - self_->general.set_application_timer_fptr(*((uint16_t *)new_time_value_ptr), self_->ucs_user_ptr); -} - -/*! \brief Callback function which is invoked to announce a request for service - * \param self The instance - * \param result_ptr Result pointer (not used) - */ -static void Ucs_OnServiceRequest(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - - TR_ASSERT(self_->ucs_user_ptr, "[API]", self_->init_data.general.request_service_fptr != NULL); - self_->general.request_service_fptr(self_->ucs_user_ptr); /* Call application callback */ - MISC_UNUSED(result_ptr); -} - -/*! \brief Callback function which announces a general error - * \param self The instance - * \param result_ptr Reference to the result. Must be casted into Eh_PublicErrorData_t. - */ -static void Ucs_OnGeneralError(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Ucs_Error_t error_code = *((Ucs_Error_t *)result_ptr); - - self_->init_complete = false; /* General error occurred -> Lock UCS API */ - Ucs_StopAppNotification(self_); - - if (self_->general.general_error_fptr != NULL) /* callback is not assigned during initialization */ - { - self_->general.general_error_fptr(error_code, self_->ucs_user_ptr); - } -} - -/*! \brief Observer callback for Inic_MostPortStatus_Status/Error(). Casts the result and - * invokes the application result callback. - * \param self Instance pointer - * \param result_ptr Reference to result - */ -static void Ucs_Most_PortStatusCb(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - if(self_->xrm.most_port_status_fptr != NULL) - { - Inic_MostPortStatus_t status = *((Inic_MostPortStatus_t *)result_ptr); - self_->xrm.most_port_status_fptr(status.most_port_handle, - status.availability, - status.avail_info, - status.freestreaming_bw, - self_->ucs_user_ptr); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* INIC */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Observer callback function for INICs device status - * \param self The instance - * \param data_ptr Pointer to structure Inic_DeviceStatus_t - */ -static void Ucs_Inic_OnDeviceStatus(void *self, void *data_ptr) -{ - CUcs *self_ = (CUcs*)self; - Ucs_Inic_PowerState_t pws = ((Inic_DeviceStatus_t *)data_ptr)->power_state; - - if ((self_->init_data.inic.power_state_fptr != NULL) && (pws != self_->inic.power_state)) - { - self_->init_data.inic.power_state_fptr(pws, self_->ucs_user_ptr); - } - - self_->inic.power_state = pws; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Network Management */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Network_Startup(Ucs_Inst_t* self, uint16_t packet_bw, uint16_t forced_na_timeout, - Ucs_StdResultCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Inic_NwStartup(self_->inic.local_inic, forced_na_timeout, - packet_bw, &self_->net.startup_obs); - if (ret_val == UCS_RET_SUCCESS) - { - self_->net.startup_fptr = result_fptr; - } - } - return ret_val; -} - -/*! \brief Callback function which announces the result of Ucs_Network_Startup() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Ucs_NetworkStartupResult(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (self_->net.startup_fptr != NULL) - { - self_->net.startup_fptr(result_ptr_->result, self_->ucs_user_ptr); - } -} - -Ucs_Return_t Ucs_Network_Shutdown(Ucs_Inst_t *self, Ucs_StdResultCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Inic_NwShutdown(self_->inic.local_inic, &self_->net.shutdown_obs); - if (ret_val == UCS_RET_SUCCESS) - { - self_->net.shutdown_fptr = result_fptr; - } - } - return ret_val; -} - -/*! \brief Callback function which announces the result of Ucs_Network_Shutdown() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Ucs_NetworkShutdownResult(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (self_->net.shutdown_fptr != NULL) - { - self_->net.shutdown_fptr(result_ptr_->result, self_->ucs_user_ptr); - } -} - -Ucs_Return_t Ucs_Network_ForceNotAvailable(Ucs_Inst_t *self, bool force, Ucs_StdResultCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Inic_NwForceNotAvailable(self_->inic.local_inic, force, &self_->net.force_na_obs); - if (ret_val == UCS_RET_SUCCESS) - { - self_->net.force_na_fptr = result_fptr; - } - } - return ret_val; -} - -/*! \brief Callback function which announces the result of Network_ForceNotAvailable() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Ucs_NetworkForceNAResult(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (self_->net.force_na_fptr != NULL) - { - self_->net.force_na_fptr(result_ptr_->result, self_->ucs_user_ptr); - } -} - -Ucs_Return_t Ucs_Network_GetFrameCounter(Ucs_Inst_t *self, uint32_t reference, Ucs_Network_FrameCounterCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - if (self_->init_complete != false) - { - ret_val = Inic_NwFrameCounter_Get(self_->inic.local_inic, reference, &self_->net.frame_counter_obs); - if (ret_val == UCS_RET_SUCCESS) - { - self_->net.frame_counter_fptr = result_fptr; - } - } - return ret_val; -} - - -/*! \brief Callback function which announces the result of Ucs_Network_GetFrameCounter() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t and data_info - * must be casted into Inic_FrameCounterStatus_t. - */ -static void Ucs_NetworkFrameCounterResult(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - - if (self_->net.frame_counter_fptr != NULL) - { - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - uint32_t reference; - uint32_t frame_counter; - uint8_t lock; - - if (result_ptr_->data_info != NULL) - { - Inic_FrameCounterStatus_t *frame_counter_result_data_ptr = (Inic_FrameCounterStatus_t *)result_ptr_->data_info; - reference = frame_counter_result_data_ptr->reference; - frame_counter = frame_counter_result_data_ptr->frame_counter; - lock = frame_counter_result_data_ptr->lock; - } - else - { - reference = 0U; - frame_counter = 0U; - lock = 0U; - } - - self_->net.frame_counter_fptr(reference, frame_counter, lock, result_ptr_->result, self_->ucs_user_ptr); - } -} - -/*! \brief Observer callback which monitors the network status - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Net_NetworkStatusParam_t. - */ -static void Ucs_NetworkStatus(void *self, void *result_ptr) -{ - CUcs *self_ = (CUcs*)self; - Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)result_ptr; - - if (self_->net.status_fptr != NULL) - { - self_->net.status_fptr( result_ptr_->change_mask, - result_ptr_->events, - result_ptr_->availability, - result_ptr_->avail_info, - result_ptr_->avail_trans_cause, - result_ptr_->node_address, - result_ptr_->node_position, - result_ptr_->max_position, - result_ptr_->packet_bw, - self_->ucs_user_ptr); - } -} - -uint8_t Ucs_Network_GetNodesCount(Ucs_Inst_t *self) -{ - CUcs *self_ = (CUcs*)(void*)self; - return Inic_GetNumberOfNodes(self_->inic.local_inic); -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Node Discovery */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Nd_Start(Ucs_Inst_t* self) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (self_->init_complete != false) - { - ret_val = Nd_Start(&self_->nd); - } - return ret_val; -} - - -Ucs_Return_t Ucs_Nd_Stop(Ucs_Inst_t* self) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (self_->init_complete != false) - { - ret_val = Nd_Stop(&self_->nd); - } - return ret_val; -} - - -Ucs_Return_t Ucs_Nd_InitAll(Ucs_Inst_t* self) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (self_->init_complete != false) - { - Nd_InitAll(&self_->nd); - ret_val = UCS_RET_SUCCESS; - } - return ret_val; - -} - -/*! \brief Callback function to proxy the user callback for node evaluation - * \param self The instance - * \param signature_ptr Reference to the node signature - * \return The evaluation return value which defines how to proceed with the node. - */ -static Ucs_Nd_CheckResult_t Ucs_OnNdEvaluate(void *self, Ucs_Signature_t *signature_ptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Nd_CheckResult_t ret_val = UCS_ND_CHK_UNKNOWN; - - if (self_->init_data.nd.eval_fptr != NULL) - { - ret_val = self_->init_data.nd.eval_fptr(signature_ptr, self_->ucs_user_ptr); - } - - return ret_val; -} - -/*! \brief Callback function to proxy the user callback for node evaluation - * \param self The instance - * \param code The report code - * \param signature_ptr Reference to the node signature or NULL if no signature applies. - */ -static void Ucs_OnNdReport(void *self, Ucs_Nd_ResCode_t code, Ucs_Signature_t *signature_ptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - - if (self_->init_data.nd.report_fptr != NULL) - { - self_->init_data.nd.report_fptr(code, signature_ptr, self_->ucs_user_ptr); - } -} - - -/*------------------------------------------------------------------------------------------------*/ -/* BackChannel Diagnosis */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Bcd_Start(Ucs_Inst_t* self, Ucs_Bcd_ReportCb_t report_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (report_fptr == NULL) - { - ret_val = UCS_RET_ERR_PARAM; - } - else if (self_->init_complete != false) - { - Bcd_Start(&self_->bcd, report_fptr); - ret_val = UCS_RET_SUCCESS; - } - return ret_val; -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Programming service */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Return_t Ucs_Prog_Start(Ucs_Inst_t *self, - uint16_t node_id, - Ucs_Signature_t *signature, - Ucs_Prg_SessionType_t session_type, - Ucs_Prg_Command_t* command_list, - Ucs_Prg_ReportCb_t result_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (result_fptr == NULL) - { - ret_val = UCS_RET_ERR_PARAM; - } - else if (self_->init_complete != false) - { - Prg_Start(&self_->prg, node_id, signature, session_type, command_list, result_fptr); - ret_val = UCS_RET_SUCCESS; - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Message Handling */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initializes the port message service for application interface (MCM) - * \param self The instance - */ -static void Ucs_InitPmsComponentApp(CUcs *self) -{ - Fifo_InitData_t mcm_init; - Fifo_Config_t mcm_config; - - /* Initialize the MCM channel */ - mcm_init.base_ptr = &self->general.base; - mcm_init.channel_ptr = &self->pmch; - mcm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete; - mcm_init.rx_cb_inst = &self->msg.mcm_transceiver; - mcm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - mcm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00); - - /* Enable INIC watchdog */ - mcm_config.fifo_id = PMP_FIFO_ID_MCM; - mcm_config.tx_wd_timeout = 10U; /* Watchdog timeout: 1s */ - mcm_config.tx_wd_timer_value = 600U; /* Watchdog trigger every 600 ms */ - mcm_config.rx_ack_timeout = 10U; /* Acknowledge timeout: 10 ms */ - mcm_config.rx_busy_allowed = 0xFU; - mcm_config.rx_credits = PMCH_MCM_CREDITS; - mcm_config.rx_threshold = PMCH_MCM_THRESHOLD; - if (self->init_data.general.inic_watchdog_enabled == false) - { - /* Disable INIC watchdog */ - mcm_config.tx_wd_timeout = 0U; /* Watchdog timeout: 0 -> infinite */ - mcm_config.tx_wd_timer_value = 0U; /* Watchdog timer: 0 -> no timer */ - mcm_config.rx_ack_timeout = 0U; /* Acknowledge timeout: 0 -> infinite */ - } - Fifo_Ctor(&self->msg.mcm_fifo,&mcm_init, &mcm_config); -#if 0 - Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, NULL, &self->msg.mcm_fifo, NULL); - Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */ -#endif - - /* initialize transceivers and set reference to FIFO instance */ - Trcv_Ctor(&self->msg.mcm_transceiver, &self->msg.mcm_fifo, MSG_ADDR_EHC_APP, self->ucs_user_ptr, PMP_FIFO_ID_MCM); - Trcv_RxAssignFilter(&self->msg.mcm_transceiver, &Ucs_McmRx_FilterCallback, self); -} - -static void Ucs_InitAmsComponent(CUcs *self) -{ - Smm_Ctor(&self->msg.smm, self->ucs_user_ptr); - (void)Smm_LoadPlugin(&self->msg.smm, &self->msg.ams_allocator, SMM_SIZE_RX_MSG); - - TR_ASSERT(self->ucs_user_ptr, "[API]", (self->msg.ams_allocator.alloc_fptr != NULL)); - TR_ASSERT(self->ucs_user_ptr, "[API]", (self->msg.ams_allocator.free_fptr != NULL)); - - Amsp_Ctor(&self->msg.ams_pool, &self->msg.ams_allocator, self->ucs_user_ptr); - Ams_Ctor(&self->msg.ams, &self->general.base, &self->msg.mcm_transceiver, NULL, &self->msg.ams_pool, - SMM_SIZE_RX_MSG); - Ams_TxSetDefaultRetries(&self->msg.ams, self->init_data.ams.tx.default_llrbc); - - Amd_Ctor(&self->msg.amd, &self->general.base, &self->msg.ams); - Amd_AssignReceiver(&self->msg.amd, &Ucs_AmsRx_Callback, self); - /* Amd_RxAssignModificator(&self->amd, &Mnsa_AmdRx_Modificator, self); */ - - self->msg.ams_tx_alloc_failed = false; - Obs_Ctor(&self->msg.ams_tx_freed_obs, self, &Ucs_AmsTx_FreedCallback); - if (self->init_data.ams.tx.message_freed_fptr != NULL) - { - Ams_TxAssignMsgFreedObs(&self->msg.ams, &self->msg.ams_tx_freed_obs); - } - - Cmd_Ctor(&self->msg.cmd, &self->general.base); -} - -extern Ucs_AmsTx_Msg_t* Ucs_AmsTx_AllocMsg(Ucs_Inst_t *self, uint16_t data_size) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_AmsTx_Msg_t *ret_ptr = NULL; - - if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true)) - { - ret_ptr = Ams_TxGetMsg(&self_->msg.ams, data_size); - } - - self_->msg.ams_tx_alloc_failed = (ret_ptr == NULL) ? true : false; - return ret_ptr; -} - -extern Ucs_Return_t Ucs_AmsTx_SendMsg(Ucs_Inst_t *self, Ucs_AmsTx_Msg_t *msg_ptr, Ucs_AmsTx_CompleteCb_t tx_complete_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true)) - { - ret_val = Ams_TxSendMsg(&self_->msg.ams, msg_ptr, NULL, tx_complete_fptr, self_->ucs_user_ptr); - } - - return ret_val; -} - -extern void Ucs_AmsTx_FreeUnusedMsg(Ucs_Inst_t *self, Ucs_AmsTx_Msg_t *msg_ptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - - if (msg_ptr != NULL) - { - Ams_TxFreeUnusedMsg(&self_->msg.ams, msg_ptr); - } -} - -extern Ucs_AmsRx_Msg_t* Ucs_AmsRx_PeekMsg(Ucs_Inst_t *self) -{ - CUcs *self_ = (CUcs*)(void*)self; - Ucs_AmsRx_Msg_t *ret = NULL; - - if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true)) - { - ret = Amd_RxPeekMsg(&self_->msg.amd); - } - - return ret; -} - -extern void Ucs_AmsRx_ReleaseMsg(Ucs_Inst_t *self) -{ - CUcs *self_ = (CUcs*)(void*)self; - - if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true)) - { - Amd_RxReleaseMsg(&self_->msg.amd); - } -} - -extern uint16_t Ucs_AmsRx_GetMsgCnt(Ucs_Inst_t *self) -{ - CUcs *self_ = (CUcs*)(void*)self; - uint16_t ret = 0U; - - if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true)) - { - ret = Amd_RxGetMsgCnt(&self_->msg.amd); - } - return ret; -} - -/*! \brief Callback function which announces that a new application message - * is added to the Rx queue - * \param self The instance - */ -static void Ucs_AmsRx_Callback(void *self) -{ - CUcs *self_ = (CUcs*)self; - - if (self_->init_data.ams.rx.message_received_fptr != NULL) - { - self_->init_data.ams.rx.message_received_fptr(self_->ucs_user_ptr); - } -} - -/*! \brief Callback function which announces that the AMS Tx Pool provides again a Tx message object - * after a prior allocation has failed. - * \param self The instance - * \param data_ptr Not used (always \c NULL) - */ -static void Ucs_AmsTx_FreedCallback(void *self, void *data_ptr) -{ - CUcs *self_ = (CUcs*)self; - MISC_UNUSED(data_ptr); - - if ((self_->msg.ams_tx_alloc_failed != false) && (self_->init_complete != false)) - { - self_->msg.ams_tx_alloc_failed = false; - self_->init_data.ams.tx.message_freed_fptr(self_->ucs_user_ptr); - } -} - -/*! \brief Callback function which filters MCM Rx messages - * \param self The instance - * \param tel_ptr The received Rx message object - * \return Returns \c true to discard the message and free it to the pool (no-pass). - * Otherwise, returns \c false (pass). - */ -static bool Ucs_McmRx_FilterCallback(void *self, Msg_MostTel_t *tel_ptr) -{ - CUcs *self_ = (CUcs*)self; - bool ret = false; /* default: pass the message */ - - if ((tel_ptr->id.fblock_id != MSG_DEF_FBLOCK_ID) || (tel_ptr->id.op_type != MSG_DEF_OP_TYPE) || - ((tel_ptr->id.function_id & (uint16_t)0x000FU) != MSG_DEF_FUNC_ID_LSN)) - { - TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_McmRx_FilterCallback(): discarding Rx message with signature %02X.%02X.%03X.%X ", 4U, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type)); - ret = true; - } - - MISC_UNUSED(self_); - - return ret; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Message decoding */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Cmd_Return_t Ucs_Cmd_AddMsgIdTable(Ucs_Inst_t *self, Ucs_Cmd_MsgId_t *msg_id_tab_ptr) -{ - Ucs_Cmd_Return_t ret_val; - CUcs *self_ = (CUcs*)(void*)self; - - if (msg_id_tab_ptr != NULL) - { - ret_val = Cmd_AddMsgIdTable(&(self_->msg.cmd), msg_id_tab_ptr); - } - else - { - ret_val = UCS_CMD_RET_ERR_NULL_PTR; - } - - return ret_val; -} - - -Ucs_Cmd_Return_t Ucs_Cmd_RemoveMsgIdTable(Ucs_Inst_t *self) -{ - Ucs_Cmd_Return_t ret_val; - CUcs *self_ = (CUcs*)(void*)self; - - ret_val = Cmd_RemoveMsgIdTable(&(self_->msg.cmd)); - - return ret_val; -} - - -Ucs_Cmd_Return_t Ucs_Cmd_DecodeMsg(Ucs_Inst_t *self, Ucs_AmsRx_Msg_t *msg_rx_ptr) -{ - Ucs_Cmd_Return_t ret_val; - CUcs *self_ = (CUcs*)(void*)self; - - if(msg_rx_ptr != NULL) - { - ret_val = Cmd_DecodeMsg(&(self_->msg.cmd), msg_rx_ptr); - } - else - { - ret_val = UCS_CMD_RET_ERR_NULL_PTR; - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Unit tests only */ -/*------------------------------------------------------------------------------------------------*/ -extern void Ucs_AssignRxFilter(Ucs_Inst_t *self, Ucs_RxFilterCb_t callback_fptr) -{ - CUcs *self_ = (CUcs*)(void*)self; - self_->rx_filter_fptr = callback_fptr; -} - - -/*! - * @} - * \endcond - */ -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_cmd.c b/ucs2-lib/src/ucs_cmd.c deleted file mode 100644 index 4865b88..0000000 --- a/ucs2-lib/src/ucs_cmd.c +++ /dev/null @@ -1,191 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Command Interpreter. - * - * \cond UCS_INTERNAL_DOC - * - * \addtogroup G_UCS_CMD_INT - * @{ - */ - - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_cmd.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ - - -static Ucs_Cmd_Return_t Cmd_SearchMsgId(Ucs_Cmd_MsgId_t msg_id_tab[], uint16_t *index_ptr, - uint16_t message_id); - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -void Cmd_Ctor(CCmd *self, CBase *base_ptr) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */ - - self->msg_id_tab_ptr = NULL; - self->ucs_user_ptr = base_ptr->ucs_user_ptr; -} - - -/*! \brief Add a MessageId Table to the Command Interpreter. - * \param self Instance pointer - * \param msg_id_tab_ptr Reference to a MessageId Table - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------------- | ------------------------------------ - * UCS_CMD_RET_SUCCESS | MessageId Table was successfully added - * UCS_CMD_RET_ERR_ALREADY_ENTERED | MessageId Table already added - */ -Ucs_Cmd_Return_t Cmd_AddMsgIdTable(CCmd *self, Ucs_Cmd_MsgId_t *msg_id_tab_ptr) -{ - Ucs_Cmd_Return_t ret_val = UCS_CMD_RET_SUCCESS; - - - if (self->msg_id_tab_ptr != NULL) - { - ret_val = UCS_CMD_RET_ERR_ALREADY_ENTERED; - } - else - { - self->msg_id_tab_ptr = msg_id_tab_ptr; - } - - return ret_val; -} - -/*! \brief Remove an MessageId Table from the Command Interpreter. - * \param self Instance pointer of Cmd - * \return Possible return values are shown in the table below. - * Value | Description - * ---------------------------- | ------------------------------------ - * UCS_CMD_RET_SUCCESS | MessageId Table was successfully removed - */ -Ucs_Cmd_Return_t Cmd_RemoveMsgIdTable(CCmd *self) -{ - Ucs_Cmd_Return_t ret_val = UCS_CMD_RET_SUCCESS; - - self->msg_id_tab_ptr = NULL; - - return ret_val; -} - - -/*! \brief Decode an MCM message - * \param self Instance pointer - * \param msg_rx_ptr Pointer to the message to decode - * \return Possible return values are shown in the table below. - * Value | Description - * -------------------------------- | ------------------------------------ - * UCS_CMD_RET_SUCCESS | decoding was successful - * UCS_CMD_RET_ERR_MSGID_NOTAVAIL | MessageId not found - * UCS_CMD_RET_ERR_TX_BUSY | no Tx Buffer available - * UCS_CMD_RET_ERR_APPL | error happened in handler function - * UCS_CMD_RET_ERR_NULL_PTR | No MessageId Table available - */ -Ucs_Cmd_Return_t Cmd_DecodeMsg(CCmd *self, Ucs_AmsRx_Msg_t *msg_rx_ptr) -{ - Ucs_Cmd_Return_t result = UCS_CMD_RET_SUCCESS; - uint16_t index; - - result = Cmd_SearchMsgId(self->msg_id_tab_ptr, &index, msg_rx_ptr->msg_id); - - if (result == UCS_CMD_RET_SUCCESS) - { - /* call handler function */ - result = (Ucs_Cmd_Return_t)(self->msg_id_tab_ptr[index].handler_function_ptr(msg_rx_ptr, self->ucs_user_ptr)); - } - - return result; -} - - -/*! \brief Search in a MessageId Table for matching MessageId - * \details Function expects that the MessageId Table ends with a termination entry - * (handler_function_ptr == NULL). If this entry is not present, the search may end in an - * endless loop. - * \param msg_id_tab MessageId Table - * \param index_ptr pointer to the matching element - * \param message_id MessageId - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------------- | ------------------------------------ - * UCS_CMD_RET_SUCCESS | decoding was successful - * UCS_CMD_RET_ERR_MSGID_NOTAVAIL | MessageId not found - * UCS_CMD_RET_ERR_NULL_PTR | No MessageId Table available - */ -static Ucs_Cmd_Return_t Cmd_SearchMsgId(Ucs_Cmd_MsgId_t msg_id_tab[], uint16_t *index_ptr, - uint16_t message_id) -{ - Ucs_Cmd_Return_t ret_val = UCS_CMD_RET_SUCCESS; - uint16_t i = 0U; - - if (msg_id_tab == NULL) - { - ret_val = UCS_CMD_RET_ERR_NULL_PTR; - } - else - { - while (msg_id_tab[i].handler_function_ptr != NULL) /* last entry */ - { - if (msg_id_tab[i].msg_id != message_id) - { - ++i; /* goto next list element */ - } - else - { - *index_ptr = i; - break; - } - } - - if (msg_id_tab[i].handler_function_ptr == NULL) /* no match found */ - { - ret_val = UCS_CMD_RET_ERR_MSGID_NOTAVAIL; - } - } - return ret_val; -} - -/*! - * @} - * \endcond - */ - - - - - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_dec.c b/ucs2-lib/src/ucs_dec.c deleted file mode 100644 index b8aef2f..0000000 --- a/ucs2-lib/src/ucs_dec.c +++ /dev/null @@ -1,131 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Command Interpreter Module. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_DEC_INT - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_dec.h" -#include "ucs_misc.h" -#include "ucs_ret_pb.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Search in a FktOp table for matching FktID and OPType. This function is used for - * incoming ICM messages. - * \param list FktOp table - * \param index_ptr Reference to array index of the matching array element - * \param function_id FktID - * \param op_type OPType - * \return DEC_RET_SUCCESS Decoding was successful - * DEC_RET_FKTID_NOT_FOUND FktID/OPType not found - */ -Dec_Return_t Dec_SearchFktOpIcm(Dec_FktOpIcm_t const list[], uint16_t *index_ptr, - uint16_t function_id, Ucs_OpType_t op_type) -{ - uint16_t fktop; - uint16_t i = 0U; - Dec_Return_t ret_val = DEC_RET_FKTID_NOT_FOUND; - bool loop = true; - - fktop = DEC_FKTOP(function_id, op_type); - *index_ptr = 0U; - - while ((list[i].handler_function_ptr != NULL) && (loop != false)) - { - if(list[i].fkt_op == fktop) - { - ret_val = DEC_RET_SUCCESS; - *index_ptr = i; - loop = false; - } - else if (list[i].fkt_op > fktop) - { - loop = false; - } - else - { - i++; - } - } - - return ret_val; -} - -/*! \brief Search in a FktOp table for matching FktID and OPType. This function is used for - * MCM messages coming from FBlocks inside the INIC. - * \param list FktOp table - * \param index_ptr Reference to array index of the matching array element - * \param function_id FktID - * \param op_type OPType - * \return DEC_RET_SUCCESS Decoding was successful - * DEC_RET_FKTID_NOT_FOUND FktID/OPType not found - */ -Dec_Return_t Dec_SearchFktOpIsh(Dec_FktOpIsh_t const list[], uint16_t *index_ptr, - uint16_t function_id, Ucs_OpType_t op_type) -{ - uint16_t fktop; - uint16_t i = 0U; - Dec_Return_t ret_val = DEC_RET_FKTID_NOT_FOUND; - bool loop = true; - - fktop = DEC_FKTOP(function_id, op_type); - *index_ptr = 0U; - - while ((list[i].handler_function_ptr != NULL) && (loop != false)) - { - if(list[i].fkt_op == fktop) - { - ret_val = DEC_RET_SUCCESS; - *index_ptr = i; - loop = false; - } - else if (list[i].fkt_op > fktop) - { - loop = false; - } - else - { - i++; - } - } - - return ret_val; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_dl.c b/ucs2-lib/src/ucs_dl.c deleted file mode 100644 index 7bb106f..0000000 --- a/ucs2-lib/src/ucs_dl.c +++ /dev/null @@ -1,390 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 doubly linked list. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_DL - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_dl.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CDlList */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the doubly linked list class. - * \param self Instance pointer - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Dl_Ctor(CDlList *self, void *ucs_user_ptr) -{ - self->head = NULL; - self->tail = NULL; - self->size = 0U; - self->ucs_user_ptr = ucs_user_ptr; -} - -/*! \brief Inserts a new node after an arbitrary node. - * \param self Instance pointer - * \param node Reference of the initial node - * \param new_node Reference of the new node are to be inserted - */ -void Dl_InsertAfter(CDlList *self, CDlNode *node, CDlNode *new_node) -{ - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size <= 0xFFFFU)); - new_node->prev = node; - new_node->next = node->next; - if(node->next == NULL) /* Is initial node last node in list? */ - { - self->tail = new_node; /* Set new node as tail of list */ - } - else - { - node->next->prev = new_node; /* Adjust follower node */ - } - node->next = new_node; /* Adjust parent node */ - new_node->in_use = true; /* Signals that node is part of a list */ - self->size++; /* Increment number of nodes */ -} - -/*! \brief Inserts a new node before an arbitrary node. - * \param self Instance pointer - * \param node Reference of the initial node - * \param new_node Reference of the new node are to be inserted - */ -void Dl_InsertBefore(CDlList *self, CDlNode *node, CDlNode *new_node) -{ - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size <= 0xFFFFU)); - new_node->prev = node->prev; - new_node->next = node; - if(node->prev == NULL) /* Is initial node first node in list? */ - { - self->head = new_node; /* Set new node as head of list */ - } - else - { - node->prev->next = new_node; /* Adjust parent node */ - } - node->prev = new_node; /* Adjust follower node */ - new_node->in_use = true; /* Signals that node is part of a list */ - self->size++; /* Increment number of nodes */ -} - -/*! \brief Sets the new node as head of a doubly linked list. - * \param self Instance pointer - * \param new_node Reference of the new node are to be placed as head of the list - */ -void Dl_InsertHead(CDlList *self, CDlNode *new_node) -{ - if(self->head == NULL) /* Is list empty? */ - { - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size <= 0xFFFFU)); - self->head = new_node; - self->tail = new_node; - new_node->prev = NULL; - new_node->next = NULL; - new_node->in_use = true; /* Signals that node is part of a list */ - self->size++; /* Increment number of nodes */ - } - else - { - Dl_InsertBefore(self, self->head, new_node); - } -} - -/*! \brief Inserts the new node at the end of a doubly linked list. - * \param self Instance pointer - * \param new_node Reference of the new node are to be placed at the end of the list - */ -void Dl_InsertTail(CDlList *self, CDlNode *new_node) -{ - if(self->tail == NULL) /* Is list empty? */ - { - Dl_InsertHead(self, new_node); - } - else - { - Dl_InsertAfter(self, self->tail, new_node); - } -} - -/*! \brief Removes an arbitrary node from a doubly linked list. - * \param self Instance pointer - * \param node Reference of the node are to be removed from the list - * \return \c DL_OK: No error - * \return \c DL_UNKNOWN_NODE: Given node is not part of this list - */ -Dl_Ret_t Dl_Remove(CDlList *self, CDlNode *node) -{ - Dl_Ret_t ret_val = DL_UNKNOWN_NODE; - - if(Dl_IsNodeInList(self, node) != false) /* Is node part of list? */ - { - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size > 0U)); - if(node->prev == NULL) /* First node in list? */ - { - self->head = node->next; /* Replace head node with next node in list */ - } - else /* -> Not first node in list */ - { - node->prev->next = node->next; /* Set next pointer of previous node to next node */ - } - if(node->next == NULL) /* Last node in list? */ - { - self->tail = node->prev; /* Replace tail node with previous node in list */ - } - else /* -> Not last node in list */ - { - node->next->prev = node->prev; /* Set previous ptr of next node to previous node */ - } - node->prev = NULL; - node->next = NULL; - node->in_use = false; /* Signals that node is not part of a list */ - ret_val = DL_OK; - self->size--; /* Decrement number of nodes */ - } - - return ret_val; -} - -/*! \brief Removes the first node in a doubly linked list. - * \param self Instance pointer - * \return The reference of the removed head node or \c NULL if the list is empty. - */ -CDlNode * Dl_PopHead(CDlList *self) -{ - CDlNode *node = self->head; - - if(node != NULL) /* Is list not empty? */ - { - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size > 0U)); - self->head = node->next; /* Replace head node with next node in list */ - if(node->next == NULL) /* Last node in list? */ - { - self->tail = NULL; /* Replace tail node and set list's tail pointer - * to NULL - */ - } - else /* -> Not last node in list */ - { - node->next->prev = NULL; /* Set previous pointer of next node to NULL */ - } - node->prev = NULL; - node->next = NULL; - node->in_use = false; /* Signals that node is not part of a list */ - self->size--; /* Decrement number of nodes */ - } - - return node; -} - -/*! \brief Removes the last node in a doubly linked list. - * \param self Instance pointer - * \return The reference of the removed tail node or \c NULL if the list is empty. - */ -CDlNode * Dl_PopTail(CDlList *self) -{ - CDlNode *node = self->tail; - - if(node != NULL) /* Is list not empty? */ - { - TR_ASSERT(self->ucs_user_ptr, "[DL]", (self->size > 0U)); - if(node->prev == NULL) /* First node in list? */ - { - self->head = NULL; /* Replace head node and set list's head pointer - * to NULL - */ - } - else /* -> Not first node in list */ - { - node->prev->next = NULL; /* Set next pointer of previous node to NULL */ - } - self->tail = node->prev; /* Replace tail node with previous node in list */ - node->prev = NULL; - node->next = NULL; - node->in_use = false; /* Signals that node is not part of a list */ - self->size--; /* Decrement number of nodes */ - } - - return node; -} - -/*! \brief Returns the reference of the first node in a doubly linked list. - * \param self Instance pointer - * \return The reference of the head node or \c NULL if the list is empty. - */ -CDlNode * Dl_PeekHead(CDlList *self) -{ - return self->head; -} - -/*! \brief Returns the reference of the last node in a doubly linked list. - * \param self Instance pointer - * \return The reference of the tail node or NULL if the list is empty. - */ -CDlNode * Dl_PeekTail(CDlList *self) -{ - return self->tail; -} - -/*! \brief Calls the given function for each node in the doubly linked list. If the func_ptr - * returns true the loop is stopped and the current node will be returned. - * \param self Instance pointer - * \param func_ptr Reference of the callback function which is called for each node - * \param user_data_ptr Reference of optional user data given to func_ptr - * \return Returns the current node or \c NULL if the whole list is processed. - */ -CDlNode * Dl_Foreach(CDlList *self, Dl_ForeachFunc_t func_ptr, void *user_data_ptr) -{ - CDlNode *ret_val = NULL; - CDlNode *node = self->head; - - while(node != NULL) /* End of list reached? */ - { - if(func_ptr(node->data_ptr, user_data_ptr) != false) /* Data found? */ - { - ret_val = node; - break; - } - node = node->next; - } - return ret_val; -} - -/*! \brief Checks if a node is part of the given doubly linked list. - * \param self Instance pointer - * \param node Reference of the searched node - * \return \c true: Node is part of the given list - * \return \c false: Node is not part of the given list - */ -bool Dl_IsNodeInList(CDlList *self, const CDlNode *node) -{ - bool ret_val = false; - CDlNode *current_node = self->head; - - while(current_node != NULL) /* End of list reached? */ - { - if(current_node == node) /* Is current node the searched one */ - { - ret_val = true; - break; - } - current_node = current_node->next; - } - return ret_val; -} - -/*! \brief Appends one doubly linked list to another doubly linked list. - * \param self Instance pointer - * \param list_ptr Reference to the doubly linked list - */ -void Dl_AppendList(CDlList *self, CDlList *list_ptr) -{ - TR_ASSERT(self->ucs_user_ptr, "[DL]", (list_ptr != NULL)); - if(list_ptr->head != NULL) - { - if(self->tail == NULL) /* Is list empty? */ - { - self->head = list_ptr->head; - self->tail = list_ptr->tail; - self->size = list_ptr->size; - } - else - { - list_ptr->head->prev = self->tail; - self->tail->next = list_ptr->head; - self->tail = list_ptr->tail; - self->size += list_ptr->size; - } - list_ptr->head = NULL; - list_ptr->tail = NULL; - list_ptr->size = 0U; - } -} - -/*! \brief Interface function to retrieve the list size. - * \param self Instance pointer - * \return Size of the list - */ -uint16_t Dl_GetSize(CDlList *self) -{ - return self->size; -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CDlNode */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of doubly linked list nodes. - * \param self Instance pointer - * \param data_ptr Optional reference to data - */ -void Dln_Ctor(CDlNode *self, void *data_ptr) -{ - self->next = NULL; - self->prev = NULL; - self->in_use = false; - self->data_ptr = data_ptr; -} - -/*! \brief Interface function to set the data pointer of the given node. - * \param self Instance pointer - * \param data_ptr Reference of the new data - */ -void Dln_SetData(CDlNode *self, void *data_ptr) -{ - self->data_ptr = data_ptr; -} - -/*! \brief Interface function to request the data pointer of the given node. - * \param self Instance pointer - */ -void * Dln_GetData(CDlNode *self) -{ - return self->data_ptr; -} - -/*! \brief Checks if a node is part of a doubly linked list. - * \param self Instance pointer of the searched node - * \return \c true: Node is part of a list - * \return \c false: Node is not part of a list - */ -bool Dln_IsNodePartOfAList(CDlNode *self) -{ - return self->in_use; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_eh.c b/ucs2-lib/src/ucs_eh.c deleted file mode 100644 index bc11847..0000000 --- a/ucs2-lib/src/ucs_eh.c +++ /dev/null @@ -1,153 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 event handler. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_EH - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_eh.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static bool Eh_EncodeEvent(uint32_t event_code, Ucs_Error_t *public_error_code_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CEventHandler */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the event handler class. - * \param self Instance pointer - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Eh_Ctor(CEventHandler *self, void * ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - /* Save UNICENS instance ID */ - self->ucs_user_ptr = ucs_user_ptr; - /* Initialize subject for internal events */ - Sub_Ctor(&self->internal_event_subject, self->ucs_user_ptr); - /* Initialize subject for public error reporting */ - Ssub_Ctor(&self->public_error_subject, self->ucs_user_ptr); -} - -/*! \brief Adds an observer which reports public errors - * \param self Instance pointer - * \param obs_ptr Reference to an observer - */ -void Eh_AddObsrvPublicError(CEventHandler *self, CSingleObserver *obs_ptr) -{ - (void)Ssub_AddObserver(&self->public_error_subject, obs_ptr); -} - -/*! \brief Removes an observer registered by Eh_AddObsrvPublicError(). - * \param self Instance pointer - */ -void Eh_DelObsrvPublicError(CEventHandler *self) -{ - Ssub_RemoveObserver(&self->public_error_subject); -} - -/*! \brief Reports an event to the event handler. - * \param self Instance pointer - * \param event_code Event code to report - */ -void Eh_ReportEvent(CEventHandler *self, uint32_t event_code) -{ - Ucs_Error_t public_error_code; - /* Check if event code exists */ - if((event_code & EH_M_ALL_EVENTS) != 0U) - { - /* Encode internal event code */ - bool result = Eh_EncodeEvent(event_code, &public_error_code); - /* Notify all registered observers */ - Msub_Notify(&self->internal_event_subject, &event_code, event_code); - /* Report error to application? */ - if(result != false) - { - Ssub_Notify(&self->public_error_subject, &public_error_code, false); - } - } -} - -/*! \brief Encodes an internal event code. Some internal event codes are mapped to public - * error codes. - * \param event_code Internal event code to report - * \param public_error_code_ptr Returned public error code - * \return true if error must be reported to the application, otherwise false - */ -static bool Eh_EncodeEvent(uint32_t event_code, Ucs_Error_t *public_error_code_ptr) -{ - bool ret_val = true; - - /* Translate internal event code into public error code */ - switch(event_code) - { - case EH_E_BIST_FAILED: - *public_error_code_ptr = UCS_GEN_ERR_INIC; - break; - case EH_E_UNSYNC_COMPLETE: - case EH_E_UNSYNC_FAILED: - *public_error_code_ptr = UCS_GEN_ERR_COMMUNICATION; - break; - default: - ret_val = false; /* Do not report this event to application. */ - break; - } - - return ret_val; -} - -/*! \brief Registers an observer on the given event code. - * \param self Instance pointer - * \param obs_ptr Reference to the masked-observer object - */ -void Eh_AddObsrvInternalEvent(CEventHandler *self, CMaskedObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->internal_event_subject, &obs_ptr->parent); -} - -/*! \brief Unregisters the given observer from the given event code. - * \param self Instance pointer - * \param obs_ptr Reference to the masked-observer object - */ -void Eh_DelObsrvInternalEvent(CEventHandler *self, CMaskedObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->internal_event_subject, &obs_ptr->parent); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_encoder.c b/ucs2-lib/src/ucs_encoder.c deleted file mode 100644 index 46d90b5..0000000 --- a/ucs2-lib/src/ucs_encoder.c +++ /dev/null @@ -1,253 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 message encoder - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_ENCODER - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_encoder.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Constants */ -/*------------------------------------------------------------------------------------------------*/ -#define ENC_LLR_TIME_DEFAULT 11U /*! \brief Default LLR time required to transmit valid messages - * with ContentType 0x81 - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Enc_Encode_00(Msg_MostTel_t *tel_ptr, uint8_t header[]); -static void Enc_Decode_00(Msg_MostTel_t *tel_ptr, uint8_t header[]); - -static void Enc_Encode_80(Msg_MostTel_t *tel_ptr, uint8_t header[]); -static void Enc_Decode_80(Msg_MostTel_t *tel_ptr, uint8_t header[]); - -static void Enc_Encode_81(Msg_MostTel_t *tel_ptr, uint8_t header[]); -static void Enc_Decode_81(Msg_MostTel_t *tel_ptr, uint8_t header[]); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Retrieves the interface of a specific encoder - * \details Creates all encoder interfaces as singletons - * \param type Specifies the type of encoder to retrieve - * \return The desired interface to the specified encoder - */ -IEncoder *Enc_GetEncoder(Enc_MsgContent_t type) -{ - static IEncoder enc_content_00 = {ENC_CONTENT_00, 8U, 12U, &Enc_Encode_00, &Enc_Decode_00}; - static IEncoder enc_content_80 = {ENC_CONTENT_80, 6U, 11U, &Enc_Encode_80, &Enc_Decode_80}; - static IEncoder enc_content_81 = {ENC_CONTENT_81, 6U, 13U, &Enc_Encode_81, &Enc_Decode_81}; - IEncoder *encoder_ptr = NULL; - - switch (type) - { - case ENC_CONTENT_00: - encoder_ptr = &enc_content_00; - break; - case ENC_CONTENT_80: - encoder_ptr = &enc_content_80; - break; - case ENC_CONTENT_81: - encoder_ptr = &enc_content_81; - break; - default: - encoder_ptr = NULL; - break; - } - - return encoder_ptr; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Content type "00" */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Encodes a message telegram to the "ContentType 0x00" MOST message header - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Encode_00(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ - header[0] = MISC_HB(tel_ptr->source_addr); - header[1] = MISC_LB(tel_ptr->source_addr); - header[2] = MISC_HB(tel_ptr->destination_addr); - header[3] = MISC_LB(tel_ptr->destination_addr); - - header[4] = tel_ptr->id.fblock_id; - header[5] = tel_ptr->id.instance_id; - - header[6] = MISC_HB(tel_ptr->id.function_id); - header[7] = MISC_LB(tel_ptr->id.function_id); - - header[8] = (uint8_t)(tel_ptr->tel.tel_id << 4) | (uint8_t)((uint8_t)tel_ptr->id.op_type & 0xFU); - header[9] = tel_ptr->opts.llrbc; - - header[10] = tel_ptr->tel.tel_cnt; - header[11] = tel_ptr->tel.tel_len; -} - -/*! \brief Decodes a "ContentType 0x00" MOST message header to a message telegram structure - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Decode_00(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ - tel_ptr->source_addr = (uint16_t)((uint16_t)header[0] << 8) | (uint16_t)header[1]; - tel_ptr->destination_addr = (uint16_t)((uint16_t)header[2] << 8) | (uint16_t)header[3]; - - tel_ptr->id.fblock_id = header[4]; - tel_ptr->id.instance_id = header[5]; - - tel_ptr->id.function_id = (uint16_t)((uint16_t)header[6] << 8) | (uint16_t)header[7]; - - tel_ptr->tel.tel_id = header[8] >> 4; /* high nibble: TelId */ - tel_ptr->id.op_type = (Ucs_OpType_t)(header[8] & 0x0FU); /* low nibble: OPType */ - - tel_ptr->opts.llrbc = header[9]; - tel_ptr->tel.tel_cnt = header[10]; - tel_ptr->tel.tel_len = header[11]; - - tel_ptr->tel.tel_data_ptr = &header[12]; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Content type "0x80" */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Encodes a message telegram to the "ContentType 0x80" MOST message header - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Encode_80(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ /* high nibble: TelId low nibble: OPType */ - header[0] = (uint8_t)(tel_ptr->tel.tel_id << 4) | (uint8_t)((uint8_t)tel_ptr->id.op_type & 0xFU); - header[1] = tel_ptr->tel.tel_cnt; - header[2] = tel_ptr->tel.tel_len; - - header[3] = MISC_HB(tel_ptr->id.function_id); - header[4] = MISC_LB(tel_ptr->id.function_id); - - header[5] = MISC_HB(tel_ptr->source_addr); - header[6] = MISC_LB(tel_ptr->source_addr); - - header[7] = MISC_HB(tel_ptr->destination_addr); - header[8] = MISC_LB(tel_ptr->destination_addr); - - header[9] = tel_ptr->id.fblock_id; - header[10] = tel_ptr->id.instance_id; -} - -/*! \brief Decodes a "ContentType 0x80" MOST message header to a message telegram structure - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Decode_80(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ - tel_ptr->tel.tel_id = header[0] >> 4; /* high nibble: TelId */ - tel_ptr->id.op_type = (Ucs_OpType_t)(header[0] & 0x0FU); /* low nibble: OPType */ - - tel_ptr->tel.tel_cnt = header[1]; - tel_ptr->tel.tel_len = header[2]; - - tel_ptr->id.function_id = (uint16_t)((uint16_t)header[3] << 8) | (uint16_t)header[4]; - - tel_ptr->source_addr = (uint16_t)((uint16_t)header[5] << 8) | (uint16_t)header[6]; - tel_ptr->destination_addr = (uint16_t)((uint16_t)header[7] << 8) | (uint16_t)header[8]; - - tel_ptr->id.fblock_id = header[9]; - tel_ptr->id.instance_id = header[10]; - - tel_ptr->tel.tel_data_ptr = &header[11]; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Content type "0x81" */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Encodes a message telegram to the "ContentType 0x81" MOST message header - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Encode_81(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ - header[0] = tel_ptr->opts.llrbc; - header[1] = ENC_LLR_TIME_DEFAULT; - /* high nibble: TelId low nibble: OPType */ - header[2] = (uint8_t)(tel_ptr->tel.tel_id << 4) | (uint8_t)((uint8_t)tel_ptr->id.op_type & 0xFU); - header[3] = tel_ptr->tel.tel_cnt; - header[4] = tel_ptr->tel.tel_len; - - header[5] = MISC_HB(tel_ptr->id.function_id); - header[6] = MISC_LB(tel_ptr->id.function_id); - - header[7] = MISC_HB(tel_ptr->source_addr); - header[8] = MISC_LB(tel_ptr->source_addr); - - header[9] = MISC_HB(tel_ptr->destination_addr); - header[10] = MISC_LB(tel_ptr->destination_addr); - - header[11] = tel_ptr->id.fblock_id; - header[12] = tel_ptr->id.instance_id; -} - -/*! \brief Decodes a "ContentType 0x81" MOST message header to a message telegram structure - * \param tel_ptr Reference to the Msg_MostTel_t structure - * \param header The header buffer - */ -static void Enc_Decode_81(Msg_MostTel_t *tel_ptr, uint8_t header[]) -{ - tel_ptr->opts.llrbc = header[0]; - - tel_ptr->tel.tel_id = header[2] >> 4; /* high nibble: TelId */ - tel_ptr->id.op_type = (Ucs_OpType_t)(header[2] & 0x0FU); /* low nibble: OPType */ - - tel_ptr->tel.tel_cnt = header[3]; - tel_ptr->tel.tel_len = header[4]; - - tel_ptr->id.function_id = (uint16_t)((uint16_t)header[5] << 8) | (uint16_t)header[6]; - - tel_ptr->source_addr = (uint16_t)((uint16_t)header[7] << 8) | (uint16_t)header[8]; - tel_ptr->destination_addr = (uint16_t)((uint16_t)header[9] << 8) | (uint16_t)header[10]; - - tel_ptr->id.fblock_id = header[11]; - tel_ptr->id.instance_id = header[12]; - - tel_ptr->tel.tel_data_ptr = &header[13]; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_epm.c b/ucs2-lib/src/ucs_epm.c deleted file mode 100644 index adc5aab..0000000 --- a/ucs2-lib/src/ucs_epm.c +++ /dev/null @@ -1,495 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 EndPoint Management. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_EPM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_epm.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Epm_XrmReportCb (uint16_t node_address, uint16_t connection_label, Ucs_Xrm_Result_t result, void * user_arg); -static bool Epm_RsmReportSyncLost (Fac_Inst_t inst_type, void * inst_ptr, void *ud_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CEndpointManagement */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Remote Sync Manager class. - * \param self Instance pointer - * \param init_ptr init data_ptr - */ -void Epm_Ctor(CEndpointManagement *self, Epm_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CEndpointManagement)); - - /* Init all instances */ - self->fac_ptr = init_ptr->fac_ptr; - self->base_ptr = init_ptr->base_ptr; - self->res_debugging_fptr = init_ptr->res_debugging_fptr; - self->check_unmute_fptr = init_ptr->check_unmute_fptr; -} - -/*! \brief Initializes the internal information of the given endpoint object. - * - * Initialization is performed only if the magic number is not set. - * - * \param self Instance pointer - * \param ep_ptr Reference to the endpoint to be looked for - */ -void Epm_InitInternalInfos(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - if ((self != NULL) && (ep_ptr != NULL)) - { - if (ep_ptr->internal_infos.magic_number != (uint32_t)0x0BADC0DE) - { - MISC_MEM_SET(&ep_ptr->internal_infos, 0, sizeof(Ucs_Rm_EndPointInt_t)); - - ep_ptr->internal_infos.magic_number = (uint32_t)0x0BADC0DE; - Sub_Ctor(&ep_ptr->internal_infos.subject_obj, self->base_ptr->ucs_user_ptr); - /* Set the EndpointManagement instance */ - ep_ptr->internal_infos.epm_inst = (Epm_Inst_t *)(void *)self; - } - } -} - -/*! \brief Clears the internal information of the given endpoint object. - * - * Resetting the magic number of the given endpoint will enforce Its Re-Initialization. - * - * \param self Instance pointer - * \param ep_ptr Reference to the endpoint to be cleared. - */ -void Epm_ClearIntInfos(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - MISC_UNUSED (self); - if (ep_ptr != NULL) - { - ep_ptr->internal_infos.magic_number = 0x0U; - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Add an observer to the Endpoint's subject. - * \param ep_ptr Reference to the endpoint instance - * \param obs_ptr Reference to the observer object - */ -void Epm_AddObserver(Ucs_Rm_EndPoint_t * ep_ptr, CObserver * obs_ptr) -{ - Sub_Ret_t ret_val = SUB_UNKNOWN_OBSERVER; - - ret_val = Sub_AddObserver(&ep_ptr->internal_infos.subject_obj, obs_ptr); - if (ret_val == SUB_OK) - { - if ((ep_ptr != NULL) && (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE)) - { - if ((ep_ptr->internal_infos.endpoint_state == UCS_RM_EP_BUILT) && (ep_ptr->internal_infos.reference_cnt > 0U)) - { - ep_ptr->internal_infos.reference_cnt++; - } - } - } -} - -/*! \brief Removes an observer registered by Epm_AddObserver - * \param ep_ptr Reference to the endpoint instance - * \param obs_ptr Reference to the observer object - */ -void Epm_DelObserver(Ucs_Rm_EndPoint_t * ep_ptr, CObserver * obs_ptr) -{ - (void)Sub_RemoveObserver(&ep_ptr->internal_infos.subject_obj, obs_ptr); -} - -/*! \brief Processes the construction of the given endpoint - * \param self Instance pointer - * \param ep_ptr reference to an endpoint - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed. - * - \c UCS_RET_SUCCESS the build process was set successfully - * - \c UCS_RET_ERR_PARAM NULL pointer detected in the parameter list - * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set - */ -Ucs_Return_t Epm_SetBuildProcess(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (ep_ptr != NULL)) - { - /* Process Endpoint construction by XRM */ - result = Xrm_Process(Fac_GetXrm(self->fac_ptr, ep_ptr->node_obj_ptr->signature_ptr->node_address, &Epm_XrmResDebugCb, self->check_unmute_fptr), - ep_ptr->jobs_list_ptr, ep_ptr->internal_infos.connection_label, - (void *)ep_ptr, &Epm_XrmReportCb); - if (result == UCS_RET_SUCCESS) - { - if (ep_ptr->internal_infos.endpoint_state != UCS_RM_EP_BUILT) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_XRMPROCESSING; - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "XRM has been ordered to create following Endpoint: %X", 1U, ep_ptr)); - } - else - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has already been built", 1U, ep_ptr)); - } - } - else if (result == UCS_RET_ERR_ALREADY_SET) - { - if (ep_ptr->internal_infos.endpoint_state == UCS_RM_EP_IDLE) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_BUILT; - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has already been built", 1U, ep_ptr)); - } - } - else if (result == UCS_RET_ERR_NOT_AVAILABLE) - { - /* Set the internal error */ - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - ep_ptr->internal_infos.xrm_result.code = UCS_XRM_RES_ERR_BUILD; - ep_ptr->internal_infos.xrm_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - ep_ptr->internal_infos.xrm_result.details.int_result = result; - } - } - - return result; -} - -/*! \brief Processes the destruction of the given endpoint - * \param self Instance pointer - * \param ep_ptr reference to an endpoint - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed. - * - \c UCS_RET_SUCCESS the build process was set successfully - * - \c UCS_RET_ERR_PARAM At least one parameter is not correct, either NULL pointer in the param list or reference_cnt of the endpoint is NULL. - * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set - * - \c UCS_RET_ERR_NOT_AVAILABLE the endpoint cannot be destroyed since its reference_cnt is greater than 1, i.e. it's in use. - * - \c UCS_RET_ERR_INVALID_SHADOW the endpoint cannot be destroyed since its reference_cnt is greater than 1, i.e. it's in use. - */ -Ucs_Return_t Epm_SetDestroyProcess(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - bool can_be_destroyed = true; - - if ((self != NULL) && (ep_ptr != NULL) ) - { - if (UCS_RM_EP_SOURCE == ep_ptr->endpoint_type) - { - if (ep_ptr->internal_infos.reference_cnt == 0U) - { - can_be_destroyed = false; - result = UCS_RET_ERR_PARAM; - } - else if (ep_ptr->internal_infos.reference_cnt > 1U) - { - ep_ptr->internal_infos.reference_cnt--; - can_be_destroyed = false; - result = UCS_RET_ERR_INVALID_SHADOW; - } - } - - if (can_be_destroyed) - { - result = Xrm_Destroy(Fac_GetXrmByJobList(self->fac_ptr, ep_ptr->jobs_list_ptr), ep_ptr->jobs_list_ptr); - if (result == UCS_RET_SUCCESS) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_XRMPROCESSING; - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "XRM has been ordered to destroy following Endpoint {%X}", 1U, ep_ptr)); - } - else if (result == UCS_RET_ERR_ALREADY_SET) - { - if (ep_ptr->internal_infos.endpoint_state == UCS_RM_EP_BUILT) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has already been destroyed", 1U, ep_ptr)); - } - } - else if (result == UCS_RET_ERR_NOT_AVAILABLE) - { - if (ep_ptr->internal_infos.endpoint_state == UCS_RM_EP_BUILT) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - TR_INFO((self->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has already been destroyed", 1U, ep_ptr)); - } - } - } - } - - return result; -} - -/*! \brief Returns the state (idle, processing or built) of the given endpoint. - * \param self Instance pointer. - * \param ep_ptr Reference to the endpoint to be looked for - * \return state of the endpoint. - */ -Ucs_Rm_EndPointState_t Epm_GetState(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - MISC_UNUSED (self); - - return (ep_ptr != NULL) ? ep_ptr->internal_infos.endpoint_state:UCS_RM_EP_IDLE; -} - -/*! \brief Forces EPM to reset the state of this endpoint. - * \param self Instance pointer. - * \param ep_ptr Reference to the endpoint to be looked for. - */ -void Epm_ResetState(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - MISC_UNUSED (self); - - if (ep_ptr != NULL) - { - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - ep_ptr->internal_infos.xrm_result.code = UCS_XRM_RES_UNKNOWN; - } -} - -/*! \brief Sets the connection label of the given endpoint. - * \param self Instance pointer. - * \param ep_ptr Reference to the endpoint to be looked for - * \param conn_label connection label to be set - */ -void Epm_SetConnectionLabel(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr, uint16_t conn_label) -{ - MISC_UNUSED (self); - - if (ep_ptr != NULL) - { - ep_ptr->internal_infos.connection_label = conn_label; - } -} - -/*! \brief Returns the connection label of the given endpoint. - * \param self Instance pointer. - * \param ep_ptr Reference to the endpoint to be looked for - * \return connection label of the endpoint. - */ -uint16_t Epm_GetConnectionLabel(CEndpointManagement * self, Ucs_Rm_EndPoint_t * ep_ptr) -{ - MISC_UNUSED (self); - - return (ep_ptr != NULL) ? ep_ptr->internal_infos.connection_label:0U; -} - -/*! \brief This function must be called when a device get invalid. - * \param self Reference to the MNS instance. - * \param destination_address MOST device address of the target. - */ -void Epm_ReportInvalidDevice(CEndpointManagement *self, uint16_t destination_address) -{ - if (MSG_ADDR_INIC != destination_address) - { - CRemoteSyncManagement * rsm_inst = Fac_FindRsm(self->fac_ptr, destination_address); - if (NULL != rsm_inst) - { - Rsm_ReportSyncLost(rsm_inst); - } - } -} - -/*! \brief Whenever this function has been called, the EndpointManager has to inform his sub-modules that a shutdown occurred. - * This function forwards the Network "NotAvailable" information - * \param self Instance pointer. - */ -void Epm_ReportShutDown(CEndpointManagement * self) -{ - Fac_Foreach(self->fac_ptr, FAC_INST_RSM, &Epm_RsmReportSyncLost, NULL); -} - -/*! \brief Function signature used for monitoring the XRM resources. - * \param resource_type The XRM resource type to be looked for - * \param resource_ptr Reference to the resource to be looked for - * \param resource_infos Resource information - * \param endpoint_inst_ptr Reference to the endpoint object that encapsulates the given resource. - * \param user_ptr User reference provided in \ref Ucs_InitData_t "Ucs_InitData_t::user_ptr" - */ -void Epm_XrmResDebugCb (Ucs_Xrm_ResourceType_t resource_type, Ucs_Xrm_ResObject_t *resource_ptr, - Ucs_Xrm_ResourceInfos_t resource_infos, void *endpoint_inst_ptr, void *user_ptr) -{ - Ucs_Rm_EndPoint_t * ep_ptr = (Ucs_Rm_EndPoint_t *)endpoint_inst_ptr; - if (ep_ptr != NULL) - { - CEndpointManagement * self = (CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst; - if (self->res_debugging_fptr != NULL) - { - self->res_debugging_fptr(resource_type, resource_ptr, resource_infos, ep_ptr, user_ptr); - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Reports "SyncLost" to the RSM instance returned. - * \param inst_type The instance type to be looked for. - * \param inst_ptr Reference to the instance to be looked for. - * \param ud_ptr Reference to the user data. - * \return false in order to retrieve the next instance of the given type, otherwise false. - */ -static bool Epm_RsmReportSyncLost(Fac_Inst_t inst_type, void * inst_ptr, void *ud_ptr) -{ - bool ret_val = false; - MISC_UNUSED(ud_ptr); - - switch (inst_type) - { - case FAC_INST_RSM: - Rsm_ReportSyncLost((CRemoteSyncManagement *)inst_ptr); - break; - - default: - ret_val = true; - break; - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Callback Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief XRM report callback function. - * \param node_address The node address from which the results come - * \param connection_label Returned MOST network connection label - * \param result Result of the job - * \param user_arg Reference to the user argument - */ -static void Epm_XrmReportCb(uint16_t node_address, uint16_t connection_label, Ucs_Xrm_Result_t result, void * user_arg) -{ - Ucs_Rm_EndPoint_t * ep_ptr = (Ucs_Rm_EndPoint_t *)user_arg; - uint8_t handle_not_found = 0x32U; - uint8_t error_id = 2U; - - MISC_UNUSED (node_address); - - if (ep_ptr != NULL) - { - ep_ptr->internal_infos.xrm_result = result; - switch (result.code) - { - case UCS_XRM_RES_SUCCESS_BUILD: - ep_ptr->internal_infos.connection_label = connection_label; - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_BUILT; - if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) - { - ep_ptr->internal_infos.reference_cnt++; - } - TR_INFO((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has been successfully built", 1U, ep_ptr)); - break; - - case UCS_XRM_RES_SUCCESS_DESTROY: - ep_ptr->internal_infos.connection_label = 0xFFFFU; - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) - { - if (ep_ptr->internal_infos.reference_cnt > 0U) - { - ep_ptr->internal_infos.reference_cnt--; - } - } - TR_INFO((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has been successfully destroyed", 1U, ep_ptr)); - break; - - case UCS_XRM_RES_RC_AUTO_DESTROYED: - TR_ERROR((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Following Endpoint {%X} has been auto destroyed.", 1U, ep_ptr)); - ep_ptr->internal_infos.connection_label = 0xFFFFU; - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) - { - ep_ptr->internal_infos.reference_cnt = 0U; - } - if(Sub_GetNumObservers(&ep_ptr->internal_infos.subject_obj) > 0U) - { - Sub_Notify(&ep_ptr->internal_infos.subject_obj, (void *)ep_ptr); - } - break; - - case UCS_XRM_RES_ERR_CONFIG: - case UCS_XRM_RES_ERR_SYNC: - case UCS_XRM_RES_ERR_BUILD: - ep_ptr->internal_infos.connection_label = 0xFFFFU; - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - TR_ERROR((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Building endpoint {%X} failed. Error_Code: 0x%02X", 2U, ep_ptr, result.code)); - break; - - case UCS_XRM_RES_ERR_DESTROY: - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - if (ep_ptr->internal_infos.xrm_result.details.result_type == UCS_XRM_RESULT_TYPE_TGT) - { - if ((ep_ptr->internal_infos.xrm_result.details.inic_result.code == UCS_RES_ERR_CONFIGURATION) && - (ep_ptr->internal_infos.xrm_result.details.inic_result.info_ptr != NULL) && - (ep_ptr->internal_infos.xrm_result.details.inic_result.info_size > 2U)) - { - if (ep_ptr->internal_infos.xrm_result.details.inic_result.info_ptr[error_id] == handle_not_found) - { - ep_ptr->internal_infos.xrm_result.code = UCS_XRM_RES_SUCCESS_DESTROY; - } - } - } - if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) - { - ep_ptr->internal_infos.reference_cnt = 0U; - } - TR_ERROR((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Destroying endpoint {%X} failed. Error_Code: 0x%02X", 2U, ep_ptr, result.code)); - break; - - case UCS_XRM_RES_ERR_INV_LIST: - TR_ERROR((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Request of invalid lists on endpoint {%X} failed.", 1U, ep_ptr)); - if (ep_ptr->internal_infos.endpoint_state == UCS_RM_EP_BUILT) - { - ep_ptr->internal_infos.connection_label = 0xFFFFU; - ep_ptr->internal_infos.endpoint_state = UCS_RM_EP_IDLE; - if(Sub_GetNumObservers(&ep_ptr->internal_infos.subject_obj) > 0U) - { - Sub_Notify(&ep_ptr->internal_infos.subject_obj, (void *)ep_ptr); - } - } - break; - - default: - TR_ERROR((((CEndpointManagement *)(void *)ep_ptr->internal_infos.epm_inst)->base_ptr->ucs_user_ptr, "[EPM]", "Processing endpoint {%X} failed. Unknown Error_Code: 0x%02X", 2U, ep_ptr, result.code)); - break; - } - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_exc.c b/ucs2-lib/src/ucs_exc.c deleted file mode 100644 index 5f5b5db..0000000 --- a/ucs2-lib/src/ucs_exc.c +++ /dev/null @@ -1,1711 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 FBlock ExtendedNetworkControl - * \details Contains the housekeeping functions of INIC management - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_EXC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_misc.h" -#include "ucs_ret_pb.h" -#include "ucs_exc.h" - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal definitions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Bitmask for API method Exc_PhyTestResult_Get() used by API locking manager */ -#define EXC_API_PHY_LAY_TEST_RESULT 0x01U -/*! \brief Bitmask for API method Exc_MemSessionOpen_Sr() used by API locking manager */ -#define EXC_API_MEM_SESSION_OPEN 0x02U -/*! \brief Bitmask for API method Exc_MemSessionClose_Sr() used by API locking manager */ -#define EXC_API_MEM_SESSION_CLOSE 0x04U -/*! \brief Bitmask for API method Exc_MemoryRead_Sr() used by API locking manager */ -#define EXC_API_MEM_READ 0x08U -/*! \brief Bitmask for API method Exc_MemoryWrite_Sr() used by API locking manager */ -#define EXC_API_MEM_WRITE 0x10U - -/*! \brief max. number of elements used in MemoryWrite and MemoryWrite messages */ -#define MAX_UNIT_LEN 18U - -/*! \brief length of signature (V1) */ -#define EXC_SIGNATURE_LEN_V1 26U - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Exc_DecodeMsg(CExc *self, Msg_MostTel_t *msg_rx_ptr); -static void Exc_EnablePort_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_EnablePort_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Hello_Status(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Hello_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Welcome_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Welcome_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Signature_Status(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_Signature_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_DeviceInit_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_CableLinkDiag_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_CableLinkDiag_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_NwPhyTest_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_NwPhyTestResult_Status(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_NwPhyTestResult_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_BC_Diag_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_BC_Diag_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_BC_EnableTx_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_BC_EnableTx_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemoryRead_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemoryRead_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemoryWrite_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemoryWrite_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemSessionOpen_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemSessionOpen_Error(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemSessionClose_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Exc_MemSessionClose_Error(void *self, Msg_MostTel_t *msg_ptr); - -static void Exc_HandleApiTimeout(void *self, void *method_mask_ptr); - -static Ucs_StdResult_t Exc_TranslateError(CExc *self, uint8_t error_data[], uint8_t error_size); -static void Exc_Read_Signature(Ucs_Signature_t *dest, uint8_t source[]); - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief List of all EXC messages */ -static const Dec_FktOpIsh_t exc_handler[] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - { DEC_FKTOP(EXC_FID_HELLO, UCS_OP_STATUS), Exc_Hello_Status }, - { DEC_FKTOP(EXC_FID_HELLO, UCS_OP_ERROR), Exc_Hello_Error }, - { DEC_FKTOP(EXC_FID_WELCOME, UCS_OP_RESULT), Exc_Welcome_Result }, - { DEC_FKTOP(EXC_FID_WELCOME, UCS_OP_ERROR), Exc_Welcome_Error }, - { DEC_FKTOP(EXC_FID_SIGNATURE, UCS_OP_STATUS), Exc_Signature_Status }, - { DEC_FKTOP(EXC_FID_SIGNATURE, UCS_OP_ERROR), Exc_Signature_Error }, - { DEC_FKTOP(EXC_FID_DEVICE_INIT, UCS_OP_ERROR), Exc_DeviceInit_Error }, - { DEC_FKTOP(EXC_FID_ENABLEPORT, UCS_OP_RESULT), Exc_EnablePort_Result }, - { DEC_FKTOP(EXC_FID_ENABLEPORT, UCS_OP_ERROR), Exc_EnablePort_Error }, - { DEC_FKTOP(EXC_FID_CABLE_LINK_DIAG, UCS_OP_RESULT), Exc_CableLinkDiag_Result }, - { DEC_FKTOP(EXC_FID_CABLE_LINK_DIAG, UCS_OP_ERROR), Exc_CableLinkDiag_Error }, - { DEC_FKTOP(EXC_FID_PHY_LAY_TEST, UCS_OP_ERROR), Exc_NwPhyTest_Error }, - { DEC_FKTOP(EXC_FID_PHY_LAY_TEST_RES, UCS_OP_STATUS), Exc_NwPhyTestResult_Status }, - { DEC_FKTOP(EXC_FID_PHY_LAY_TEST_RES, UCS_OP_ERROR), Exc_NwPhyTestResult_Error }, - { DEC_FKTOP(EXC_FID_BC_DIAG, UCS_OP_RESULT), Exc_BC_Diag_Result }, - { DEC_FKTOP(EXC_FID_BC_DIAG, UCS_OP_ERROR), Exc_BC_Diag_Error }, - { DEC_FKTOP(EXC_FID_BC_ENABLE_TX, UCS_OP_RESULT), Exc_BC_EnableTx_Result }, - { DEC_FKTOP(EXC_FID_BC_ENABLE_TX, UCS_OP_ERROR), Exc_BC_EnableTx_Error }, - { DEC_FKTOP(EXC_FID_MEM_SESSION_OPEN, UCS_OP_RESULT), Exc_MemSessionOpen_Result }, - { DEC_FKTOP(EXC_FID_MEM_SESSION_OPEN, UCS_OP_ERROR), Exc_MemSessionOpen_Error }, - { DEC_FKTOP(EXC_FID_MEM_SESSION_CLOSE, UCS_OP_RESULT), Exc_MemSessionClose_Result }, - { DEC_FKTOP(EXC_FID_MEM_SESSION_CLOSE, UCS_OP_ERROR), Exc_MemSessionClose_Error }, - { DEC_FKTOP(EXC_FID_MEMORY_READ, UCS_OP_RESULT), Exc_MemoryRead_Result }, - { DEC_FKTOP(EXC_FID_MEMORY_READ, UCS_OP_ERROR), Exc_MemoryRead_Error }, - { DEC_FKTOP(EXC_FID_MEMORY_WRITE, UCS_OP_RESULT), Exc_MemoryWrite_Result }, - { DEC_FKTOP(EXC_FID_MEMORY_WRITE, UCS_OP_ERROR), Exc_MemoryWrite_Error }, - { DEC_FKTOP_TERMINATION, NULL } -}; - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CExc. - * \param self Reference to CExc instance - * \param base_ptr Reference to a Base instance - * \param rcm_ptr Reference to Transceiver instance - */ -void Exc_Ctor(CExc *self, CBase *base_ptr, CTransceiver *rcm_ptr) -{ - - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->base_ptr = base_ptr; - self->xcvr_ptr = rcm_ptr; - - self->fkt_op_list_ptr = &exc_handler[0]; - - - /* Initialize API locking mechanism */ - Sobs_Ctor(&self->lock.observer, self, &Exc_HandleApiTimeout); - Al_Ctor(&self->lock.api, &self->lock.observer, self->base_ptr->ucs_user_ptr); - Alm_RegisterApi(&self->base_ptr->alm, &self->lock.api); - -} - - -/*! \brief Callback function to filter RCM Rx messages - * \details Do not release the message object here - * \param self reference to INIC object - * \param tel_ptr received message - */ -void Exc_OnRcmRxFilter(void *self, Msg_MostTel_t *tel_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_DecodeMsg(self_, tel_ptr); - -} - - -/*! \brief Decode a message for FBlock EXC - * \param self Instance pointer to FBlock EXC - * \param msg_rx_ptr pointer to the MCM message to decode - */ -static void Exc_DecodeMsg(CExc *self, Msg_MostTel_t *msg_rx_ptr) -{ - Dec_Return_t result; - uint16_t index; - - result = Dec_SearchFktOpIsh(self->fkt_op_list_ptr, &index, msg_rx_ptr->id.function_id, msg_rx_ptr->id.op_type); - - if (result == DEC_RET_SUCCESS) - { - self->fkt_op_list_ptr[index].handler_function_ptr(self, msg_rx_ptr); - } - else - { - /* no handling of decoding error for shadow OpTypes */ - } -} - - - -/*! \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 Exc_HandleApiTimeout(void *self, void *method_mask_ptr) -{ - CExc *self_ = (CExc *)self; - Alm_ModuleMask_t method_mask = *((Alm_ModuleMask_t *)method_mask_ptr); - Exc_StdResult_t res_data; - - res_data.result.code = UCS_RES_ERR_TIMEOUT; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - res_data.data_info = NULL; - - switch(method_mask) - { -#if 0 /* System Diagnosis supervises timeouts for these functions */ - case EXC_API_ENABLE_PORT: - Ssub_Notify(&self_->ssubs.enableport, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_EnablePort_Sr().", 0U)); - break; - case EXC_API_HELLO: - Ssub_Notify(&self_->ssubs.hello, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_Hello_Get().", 0U)); - break; - case EXC_API_WELCOME: - Ssub_Notify(&self_->ssubs.welcome, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_Welcome_Sr().", 0U)); - break; - case EXC_API_CABLE_LINK_DIAG: - Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_CableLinkDiagnosis_Start().", 0U)); - break; -#endif - case EXC_API_PHY_LAY_TEST_RESULT: - Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_PhyTestResult_Get().", 0U)); - break; - case EXC_API_MEM_SESSION_OPEN: - Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemSessionOpen_Sr().", 0U)); - break; - case EXC_API_MEM_SESSION_CLOSE: - Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemSessionClose_Sr().", 0U)); - break; - case EXC_API_MEM_READ: - Ssub_Notify(&self_->ssubs.memoryread, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemoryRead_Sr().", 0U)); - break; - case EXC_API_MEM_WRITE: - Ssub_Notify(&self_->ssubs.memorywrite, &res_data, false); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemoryWrite_Sr().", 0U)); - break; - - default: - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "Unknown API locking bitmask detected. Mask: 0x%02X", 1U, method_mask)); - break; - } -} - - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal API */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief This method sends the Hello.Get message - * \param self Reference to CExc instance - * \param target_address Target address - * \param version_limit Signature version limit - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_Hello_Get(CExc *self, - uint16_t target_address, - uint8_t version_limit, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - if (version_limit > UCS_EXC_SIGNATURE_VERSION_LIMIT) - { - version_limit = UCS_EXC_SIGNATURE_VERSION_LIMIT; - } - - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_HELLO; - msg_ptr->id.op_type = UCS_OP_GET; - msg_ptr->tel.tel_data_ptr[0] = version_limit; - - msg_ptr->info_ptr = &self->ssubs.hello; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.hello, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief This method send the Welcome.StartResult message - * \param self Reference to CExc instance - * \param target_address Target address - * \param admin_node_address The node address used during system diagnosis - * \param version Signature version - * \param signature Signature of the device - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_Welcome_Sr(CExc *self, - uint16_t target_address, - uint16_t admin_node_address, - uint8_t version, - Ucs_Signature_t signature, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, EXC_SIGNATURE_LEN_V1 + 3U); /* Signature v1 */ - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_WELCOME; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(admin_node_address); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(admin_node_address); - msg_ptr->tel.tel_data_ptr[2] = version; - msg_ptr->tel.tel_data_ptr[3] = MISC_HB(signature.node_address); - msg_ptr->tel.tel_data_ptr[4] = MISC_LB(signature.node_address); - msg_ptr->tel.tel_data_ptr[5] = MISC_HB(signature.group_address); - msg_ptr->tel.tel_data_ptr[6] = MISC_LB(signature.group_address); - msg_ptr->tel.tel_data_ptr[7] = MISC_HB(signature.mac_47_32); - msg_ptr->tel.tel_data_ptr[8] = MISC_LB(signature.mac_47_32); - msg_ptr->tel.tel_data_ptr[9] = MISC_HB(signature.mac_31_16); - msg_ptr->tel.tel_data_ptr[10] = MISC_LB(signature.mac_31_16); - msg_ptr->tel.tel_data_ptr[11] = MISC_HB(signature.mac_15_0); - msg_ptr->tel.tel_data_ptr[12] = MISC_LB(signature.mac_15_0); - msg_ptr->tel.tel_data_ptr[13] = MISC_HB(signature.node_pos_addr); - msg_ptr->tel.tel_data_ptr[14] = MISC_LB(signature.node_pos_addr); - msg_ptr->tel.tel_data_ptr[15] = MISC_HB(signature.diagnosis_id); - msg_ptr->tel.tel_data_ptr[16] = MISC_LB(signature.diagnosis_id); - msg_ptr->tel.tel_data_ptr[17] = signature.num_ports; - msg_ptr->tel.tel_data_ptr[18] = signature.chip_id; - msg_ptr->tel.tel_data_ptr[19] = signature.fw_major; - msg_ptr->tel.tel_data_ptr[20] = signature.fw_minor; - msg_ptr->tel.tel_data_ptr[21] = signature.fw_release; - msg_ptr->tel.tel_data_ptr[22] = MISC_HB((signature.fw_build) >>16U); - msg_ptr->tel.tel_data_ptr[23] = MISC_LB((signature.fw_build) >>16U); - msg_ptr->tel.tel_data_ptr[24] = MISC_HB(signature.fw_build); - msg_ptr->tel.tel_data_ptr[25] = MISC_LB(signature.fw_build); - msg_ptr->tel.tel_data_ptr[26] = signature.cs_major; - msg_ptr->tel.tel_data_ptr[27] = signature.cs_minor; - msg_ptr->tel.tel_data_ptr[28] = signature.cs_release; -/* msg_ptr->tel.tel_data_ptr[29] = signature.uid_persistency; - msg_ptr->tel.tel_data_ptr[30] = MISC_HB((signature.uid) >>16U); - msg_ptr->tel.tel_data_ptr[31] = MISC_LB((signature.uid) >>16U); - msg_ptr->tel.tel_data_ptr[32] = MISC_HB(signature.uid); - msg_ptr->tel.tel_data_ptr[33] = MISC_LB(signature.uid); -*/ - - msg_ptr->info_ptr = &self->ssubs.welcome; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.welcome, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief This method sends the Signature.Get message - * \param self Reference to CExc instance - * \param target_address Target address - * \param version_limit Signature version limit - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_Signature_Get(CExc *self, - uint16_t target_address, - uint8_t version_limit, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - if (version_limit > UCS_EXC_SIGNATURE_VERSION_LIMIT) - { - version_limit = UCS_EXC_SIGNATURE_VERSION_LIMIT; - } - - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_SIGNATURE; - msg_ptr->id.op_type = UCS_OP_GET; - msg_ptr->tel.tel_data_ptr[0] = version_limit; - - msg_ptr->info_ptr = &self->ssubs.signature; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.signature, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief This method sends the DeviceInit.Start message - * \param self Reference to CExc instance - * \param target_address Target address - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_DeviceInit_Start(CExc *self, - uint16_t target_address, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_DEVICE_INIT; - msg_ptr->id.op_type = UCS_OP_START; - - msg_ptr->info_ptr = &self->ssubs.deviceinit; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.deviceinit, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief This method enables a port - * \param self Reference to CExc instance - * \param target_address Target address - * \param port_number PortNumber - * \param enabled Enabled - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_EnablePort_Sr(CExc *self, - uint16_t target_address, - uint8_t port_number, - bool enabled, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_ENABLEPORT; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = port_number; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)enabled; - - msg_ptr->info_ptr = &self->ssubs.enableport; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.enableport, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief This method starts the Cable Link Diagnosis - * \param self Reference to CExc instance - * \param target_address Target address - * \param port_number PortNumber - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_CableLinkDiagnosis_Start(CExc *self, - uint16_t target_address, - uint8_t port_number, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_CABLE_LINK_DIAG; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = port_number; - - msg_ptr->info_ptr = &self->ssubs.cablelinkdiag; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.cablelinkdiag, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief This method starts the Physical Layer Test - * \param self Reference to CExc instance - * \param port_number PortNumber - * \param type Type - * \param lead_in Lead-in - * \param duration Duration - * \param lead_out Lead-out - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_PhyTest_Start(CExc *self, - uint8_t port_number, - Ucs_Diag_PhyTest_Type_t type, - uint16_t lead_in, - uint32_t duration, - uint16_t lead_out, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 10U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = MSG_ADDR_INIC; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_PHY_LAY_TEST; - msg_ptr->id.op_type = UCS_OP_START; - msg_ptr->tel.tel_data_ptr[0] = port_number; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)type; - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(lead_in); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(lead_in); - msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((duration) >> 24); - msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((duration) >> 16); - msg_ptr->tel.tel_data_ptr[6] = (uint8_t)((duration) >> 8); - msg_ptr->tel.tel_data_ptr[7] = (uint8_t)(duration & (uint32_t)0xFF); - msg_ptr->tel.tel_data_ptr[8] = MISC_HB(lead_out); - msg_ptr->tel.tel_data_ptr[9] = MISC_LB(lead_out); - - - msg_ptr->info_ptr = &self->ssubs.phylaytest; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.phylaytest, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief Requests the EXC.PhysicalLayerTestResult.Status message - * \param self Reference to CExc instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Exc_PhyTestResult_Get(CExc *self, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, EXC_API_PHY_LAY_TEST_RESULT) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = MSG_ADDR_INIC; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_PHY_LAY_TEST_RES; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->info_ptr = &self->ssubs.phylaytestresult; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.phylaytestresult, obs_ptr); - } - else - { - Al_Release(&self->lock.api, EXC_API_PHY_LAY_TEST_RESULT); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - - -/*! Sends the BCDiag.Startresult command - * - * \param *self Reference to CExc instance - * \param position Position of the segment to be checked. - * \param admin_na Admin Node Address - * \param t_send Timing parameter t_Send - * \param t_wait4dut Timing parameter t_WaitForDUT - * \param t_switch Timing parameter t_Switch - * \param t_back Timing parameter t_Back - * \param autoback TBD - * \param *obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_BCDiag_Start(CExc *self, - uint8_t position, - uint16_t admin_na, - uint16_t t_send, - uint16_t t_wait4dut, - uint16_t t_switch, - uint16_t t_back, - bool autoback, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 12U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = UCS_ADDR_BROADCAST_BLOCKING; - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_BC_DIAG; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = position; - msg_ptr->tel.tel_data_ptr[1] = MISC_HB(admin_na); - msg_ptr->tel.tel_data_ptr[2] = MISC_LB(admin_na); - msg_ptr->tel.tel_data_ptr[3] = MISC_HB(t_send); - msg_ptr->tel.tel_data_ptr[4] = MISC_LB(t_send); - msg_ptr->tel.tel_data_ptr[5] = MISC_HB(t_wait4dut); - msg_ptr->tel.tel_data_ptr[6] = MISC_LB(t_wait4dut); - msg_ptr->tel.tel_data_ptr[7] = MISC_HB(t_switch); - msg_ptr->tel.tel_data_ptr[8] = MISC_LB(t_switch); - msg_ptr->tel.tel_data_ptr[9] = MISC_HB(t_back); - msg_ptr->tel.tel_data_ptr[10] = MISC_LB(t_back); - msg_ptr->tel.tel_data_ptr[11] = (uint8_t)autoback; - - - msg_ptr->info_ptr = &self->ssubs.bcdiag; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.bcdiag, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! Enables the signal during backChannel Diagnosis - * - * \param *self Reference to CExc instance - * \param port Number of port which has to be enabled. - * \param *obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Exc_BCEnableTx_StartResult(CExc *self, - uint8_t port, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = UCS_ADDR_BROADCAST_BLOCKING; - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_BC_ENABLE_TX; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = port; - - msg_ptr->info_ptr = &self->ssubs.enabletx; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.enabletx, obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief This function is used to open a memory session. - * - * A memory session is used to control access to the memory resources. Before a memory could - * be read or written, a session of the appropriate type has to be opened. - * Only a single memory session is supported. Once opened, the session must be first - * closed before a new session of a different type could be used. Some session types - * (0x01, 0x02 and 0x04) require a hardware reset after they were closed. - * Function Exc_MemSessionOpen_Sr() also performs some preprocessing, - * depending on the session_type. This includes clearing of the configuration - * and identification strings before the error memory is programmed or erased. - * - * \param *self Reference to CExc instance - * \param target_address Target address - * \param session_type Defines the set of MemIDs and the memory access type(s) (read and/or write) - * \param *obs_ptr Reference to an optional observer - * - * \return UCS_RET_SUCCESS message was created and sent to INIC - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Exc_MemSessionOpen_Sr(CExc *self, - uint16_t target_address, - uint8_t session_type, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, EXC_API_MEM_SESSION_OPEN) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_MEM_SESSION_OPEN; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = session_type; - - msg_ptr->info_ptr = &self->ssubs.memsessionopen; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.memsessionopen, obs_ptr); - } - else - { - Al_Release(&self->lock.api, EXC_API_MEM_SESSION_OPEN); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - -/*! \brief This function is used to close an active memory session that was previously opened by - * function Exc_MemSessionOpen_Sr(). - * - * In addition, the function performs some post-processing on given session types. This includes - * validation of the newly programmed configuration and identification strings as well as - * the deactivation of the current configuration and identification strings. In these cases, - * the new configuration becomes active after a hardware reset. - * - * \param *self Reference to CExc instance - * \param target_address Target address - * \param session_handle Unique number assigned to the active memory session - * \param *obs_ptr Reference to an optional observer - * - * \return UCS_RET_SUCCESS message was created and sent to INIC - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Exc_MemSessionClose_Sr(CExc *self, - uint16_t target_address, - uint16_t session_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, EXC_API_MEM_SESSION_CLOSE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_MEM_SESSION_CLOSE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); - - msg_ptr->info_ptr = &self->ssubs.memsessionclose; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.memsessionclose, obs_ptr); - } - else - { - Al_Release(&self->lock.api, EXC_API_MEM_SESSION_CLOSE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - -/*! \brief This function provides read access to the memories described by parameter MemID. - * - * In addition, the function can be used to retrieve the active Configuration String and - * Identification String. - * Reading the memory can only be done within an active memory session. Parameter - * session_handle authorizes the access to the memory resource defined by parameter - * MemID. The session_handle is provided by function Exc_MemSessionOpen_Sr(), - * which must be called in advance to memory access. - * - * \param *self Reference to CExc instance - * \param target_address Target address - * \param session_handle Unique number assigned to the active memory session - * \param mem_id Represents the memory resource to be read - * \param address Defines the memory location at which the reading operation starts - * \param unit_len Sets the number of memory units to be read. Memory units can be - * unsigned bytes, unsigned words or unsigned masked data depending - * on the memory type. - * \param *obs_ptr Reference to an optional observer - * - * \return UCS_RET_SUCCESS message was created and sent to INIC - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_PARAM parameter ubit_len ist too big - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Exc_MemoryRead_Sr(CExc *self, - uint16_t target_address, - uint16_t session_handle, - uint8_t mem_id, - uint32_t address, - uint8_t unit_len, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, EXC_API_MEM_READ) != false) - { - if (unit_len > MAX_UNIT_LEN) - { - result = UCS_RET_ERR_PARAM; - } - - if (result == UCS_RET_SUCCESS) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = target_address; - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_MEMORY_READ; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); - msg_ptr->tel.tel_data_ptr[2] = mem_id; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)((address) >> 24); - msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((address) >> 16); - msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((address) >> 8); - msg_ptr->tel.tel_data_ptr[6] = (uint8_t)(address & (uint32_t)0xFF); - msg_ptr->tel.tel_data_ptr[7] = unit_len; - - msg_ptr->info_ptr = &self->ssubs.memoryread; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.memoryread, obs_ptr); - } - else - { - Al_Release(&self->lock.api, EXC_API_MEM_READ); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - -/*! \brief This function provides write access to the memories described by parameter MemID. - * - * In addition, the function can be used to program a new Configuration String and Identification - * String. - * Writing the memory can only be done within an active memory session. Parameter - * SessionHandle authorizes the access to the memory resource defined by parameter - * MemID. The SessionHandle is provided by function ExtendedNetworkControl.MemorySessionOpen(), - * which must be called in advance to memory access. - * - * \param *self Reference to CExc instance - * \param target_address Target address - * \param session_handle Unique number assigned to the active memory session - * \param mem_id Represents the memory resource to be read - * \param address Defines the memory location at which the reading operation starts - * \param unit_len Sets the number of memory units to be read. Memory units can be - * unsigned bytes, unsigned words or unsigned masked data depending - * on the memory type. - * \param *unit_data Contains the actual data written to the memory resource and formatted - * as memory units - * \param *obs_ptr Reference to an optional observer - * - * \return UCS_RET_SUCCESS message was created and sent to INIC - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_PARAM parameter ubit_len ist too big - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Exc_MemoryWrite_Sr(CExc *self, - uint16_t target_address, - uint16_t session_handle, - uint8_t mem_id, - uint32_t address, - uint8_t unit_len, - uint8_t unit_data[], - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, EXC_API_MEM_WRITE) != false) - { - if (unit_len > MAX_UNIT_LEN) - { - result = UCS_RET_ERR_PARAM; - } - - if (result == UCS_RET_SUCCESS) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U + unit_len); - - if (msg_ptr != NULL) - { - uint8_t i; - - msg_ptr->destination_addr = target_address; - msg_ptr->id.fblock_id = FB_EXC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = EXC_FID_MEMORY_WRITE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); - msg_ptr->tel.tel_data_ptr[2] = mem_id; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)((address) >> 24); - msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((address) >> 16); - msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((address) >> 8); - msg_ptr->tel.tel_data_ptr[6] = (uint8_t)(address & (uint32_t)0xFF); - msg_ptr->tel.tel_data_ptr[7] = unit_len; - for (i=0U; i<unit_len; ++i) - { - msg_ptr->tel.tel_data_ptr[8U+i] = *(unit_data + i); - } - - msg_ptr->info_ptr = &self->ssubs.memorywrite; - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs.memorywrite, obs_ptr); - } - else - { - Al_Release(&self->lock.api, EXC_API_MEM_WRITE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - - -/*------------------------------------------------------------------------------------------------*/ -/* Handler functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Handler function for EXC.Hello.Status - * \param self Reference to EXC object - * \param msg_ptr Received message - */ -static void Exc_Hello_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_HelloStatus_t hello_data; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1 + 1U)) - { - hello_data.version = msg_ptr->tel.tel_data_ptr[0]; - Exc_Read_Signature(&(hello_data.signature), &(msg_ptr->tel.tel_data_ptr[1])); - - res_data.data_info = &hello_data; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - - /* Node Discovery sends the Hello.Get as broadcast message. So we will need the observer - several times. */ - Ssub_Notify(&self_->ssubs.hello, &res_data, false); - } -} - - -/*! \brief Handler function for EXC.Hello.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_Hello_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - /* Node Discovery sends the Hello.Get as broadcast message. So we will need the observer - several times. */ - Ssub_Notify(&self_->ssubs.hello, &res_data, false); - } -} - - -/*! \brief Handler function for EXC.Welcome.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_Welcome_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.welcome, &res_data, true); - } -} - -/*! \brief Handler function for the EXC.Welcome.Result message - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_Welcome_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_WelcomeResult_t welcome_data; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1 + 2U)) - { - welcome_data.res = msg_ptr->tel.tel_data_ptr[0]; - welcome_data.version = msg_ptr->tel.tel_data_ptr[1]; - Exc_Read_Signature(&(welcome_data.signature), &(msg_ptr->tel.tel_data_ptr[2])); - res_data.data_info = &welcome_data; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.welcome, &res_data, true); - } -} - - -/*! Handler function for the EXC.Signature.Status message - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_Signature_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_SignatureStatus_t signature_data; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1 + 1U)) - { - signature_data.version = msg_ptr->tel.tel_data_ptr[0]; - Exc_Read_Signature(&(signature_data.signature), &(msg_ptr->tel.tel_data_ptr[1])); - - res_data.data_info = &signature_data; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - - Ssub_Notify(&self_->ssubs.signature, &res_data, true); - } -} - - -/*! Handler function for the EXC.Signature.Error message - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_Signature_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.signature, &res_data, true); - } -} - - -/*! Handler function for the EXC.DeviceInit.Error message - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_DeviceInit_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len >0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.deviceinit, &res_data, true); - } -} - - -/*! \brief Handler function for EXC.EnablePort.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_EnablePort_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.enableport, &res_data, true); - } -} - -/*! \brief Handler function for EXC.EnablePort.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_EnablePort_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs.enableport, &res_data, true); -} - - -/*! \brief Handler function for EXC.CableLinkDiag.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_CableLinkDiag_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, true); - } -} - -/*! \brief Handler function for EXC.CableLinkDiag.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_CableLinkDiag_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_CableLinkDiagResult_t cable_link_diag_result_data; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - cable_link_diag_result_data.port_number = msg_ptr->tel.tel_data_ptr[0]; - cable_link_diag_result_data.result = msg_ptr->tel.tel_data_ptr[1]; - res_data.data_info = &cable_link_diag_result_data; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, true); - } -} - - -/*! \brief Handler function for EXC.PhysicalLayerTest.Error - * \param self reference to EXC object - * \param msg_ptr received message - */static void Exc_NwPhyTest_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.phylaytest, &res_data, true); - } -} - - -/*! \brief Handler function for EXC.MOSTNetworkPhysicalLayerTestResult.Status - * \param self Reference to EXC object - * \param msg_ptr Received message - */ -static void Exc_NwPhyTestResult_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_PhyTestResult_t phy_test_result; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - phy_test_result.port_number = msg_ptr->tel.tel_data_ptr[0]; - phy_test_result.lock_status = (msg_ptr->tel.tel_data_ptr[1] != 0U) ? true : false; - MISC_DECODE_WORD(&(phy_test_result.err_count), &(msg_ptr->tel.tel_data_ptr[2])); - res_data.data_info = &phy_test_result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_PHY_LAY_TEST_RESULT); -} - - -/*! \brief Handler function for EXC.MOSTNetworkPhysicalLayerTestResult.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_NwPhyTestResult_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_PHY_LAY_TEST_RESULT); -} - - - -/*! \brief Handler function for EXC.BCDiag.Status - * \param self Reference to EXC object - * \param msg_ptr Received message - */ -static void Exc_BC_Diag_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_BCDiagResult bcd_result; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 1U) - { - bcd_result.diag_result = (Exc_BCDiagResValue)(msg_ptr->tel.tel_data_ptr[0] >> 4U); - MISC_DECODE_WORD(&(bcd_result.admin_addr), &(msg_ptr->tel.tel_data_ptr[0])); - bcd_result.admin_addr &= 0x0FFFU; - res_data.data_info = &bcd_result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.bcdiag, &res_data, true); - } -} - - -/*! \brief Handler function for EXC.BCDiag.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_BC_Diag_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.bcdiag, &res_data, true); - } -} - - - - -/*! \brief Handler function for EXC.BCEnableTx.Result - * \param self Reference to EXC object - * \param msg_ptr Received message - */ -static void Exc_BC_EnableTx_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.enabletx, &res_data, true); - - MISC_UNUSED(msg_ptr); -} - - -/*! \brief Handler function for EXC.BCEnableTx.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_BC_EnableTx_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.enabletx, &res_data, true); - } -} - - -/*! \brief Handler function for EXC.MemorySessionOpen.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemSessionOpen_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - uint16_t session_handle; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - MISC_DECODE_WORD(&(session_handle), &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &session_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_OPEN); -} - - -/*! \brief Handler function for EXC.MemorySessionOpen.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemSessionOpen_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_OPEN); -} - - -/*! \brief Handler function for EXC.MemorySessionClose.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemSessionClose_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - uint8_t session_result; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - session_result = msg_ptr->tel.tel_data_ptr[0]; - res_data.data_info = &session_result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_CLOSE); -} - -/*! \brief Handler function for EXC.MemorySessionClose.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemSessionClose_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_CLOSE); -} - -/*! \brief Handler function for EXC.MemoryRead.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemoryRead_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_MemReadResult_t mem_read_result; - Exc_StdResult_t res_data; - uint8_t i; - - if (msg_ptr->tel.tel_len > 0U) - { - MISC_DECODE_WORD(&(mem_read_result.session_handle), &(msg_ptr->tel.tel_data_ptr[0])); - mem_read_result.mem_id = msg_ptr->tel.tel_data_ptr[2]; - MISC_DECODE_DWORD(&(mem_read_result.address), &(msg_ptr->tel.tel_data_ptr[3])); - mem_read_result.unit_len = msg_ptr->tel.tel_data_ptr[7]; - for (i=0U; (i<mem_read_result.unit_len) && (i<MAX_UNIT_LEN); ++i) - { - mem_read_result.unit_data[i] = msg_ptr->tel.tel_data_ptr[8U+i]; - } - - res_data.data_info = &mem_read_result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.memoryread, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_READ); -} - - -/*! \brief Handler function for EXC.MemoryRead.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemoryRead_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.memoryread, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_READ); -} - - -/*! \brief Handler function for EXC.MemoryWrite.Result - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemoryWrite_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_MemWriteResult_t mem_write_result; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - MISC_DECODE_WORD(&(mem_write_result.session_handle), &(msg_ptr->tel.tel_data_ptr[0])); - mem_write_result.mem_id = msg_ptr->tel.tel_data_ptr[2]; - - res_data.data_info = &mem_write_result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs.memorywrite, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_WRITE); -} - - -/*! \brief Handler function for EXC.MemoryWrite.Error - * \param self reference to EXC object - * \param msg_ptr received message - */ -static void Exc_MemoryWrite_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CExc *self_ = (CExc *)self; - Exc_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Exc_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (uint8_t)(msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs.memorywrite, &res_data, true); - } - Al_Release(&self_->lock.api, EXC_API_MEM_WRITE); -} - - - -/*------------------------------------------------------------------------------------------------*/ -/* Helper functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Translates EXC error codes into UNICENS error codes and wraps the raw INIC - * error data to a byte stream. - * \param self Instance of CExc - * \param error_data[] EXC error data - * \param error_size Size of EXC error data in bytes - * \return The formatted error - */ -static Ucs_StdResult_t Exc_TranslateError(CExc *self, uint8_t error_data[], uint8_t error_size) -{ - Ucs_StdResult_t ret_val; - MISC_UNUSED(self); - - if(error_data[0] != 0x20U) - { - ret_val.code = UCS_RES_ERR_MOST_STANDARD; - } - else - { - ret_val.code = (Ucs_Result_t)(error_data[1] + 1U); - } - - ret_val.info_ptr = &error_data[0]; - ret_val.info_size = error_size; - - return ret_val; -} - - -/*! \brief Reads a signature from a message's payload - * - * \param dest Pointer to signature - * \param source Pointer to start of signature inabyte array - */ -static void Exc_Read_Signature(Ucs_Signature_t *dest, uint8_t source[]) -{ - MISC_DECODE_WORD(&(dest->node_address), source); - MISC_DECODE_WORD(&(dest->group_address), &(source[2])); - MISC_DECODE_WORD(&(dest->mac_47_32), &(source[4])); - MISC_DECODE_WORD(&(dest->mac_31_16), &(source[6])); - MISC_DECODE_WORD(&(dest->mac_15_0), &(source[8])); - MISC_DECODE_WORD(&(dest->node_pos_addr), &(source[10])); - MISC_DECODE_WORD(&(dest->diagnosis_id), &(source[12])); - dest->num_ports = source[14]; - dest->chip_id = source[15]; - dest->fw_major = source[16]; - dest->fw_minor = source[17]; - dest->fw_release = source[18]; - MISC_DECODE_DWORD(&(dest->fw_build), &(source[19])); - dest->cs_major = source[23]; - dest->cs_minor = source[24]; - dest->cs_release = source[25]; -/* dest->uid_persistency = source[26];*/ /* Signature v1 */ -/* MISC_DECODE_DWORD(&(dest->uid), &(source[27]));*/ - -} -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_factory.c b/ucs2-lib/src/ucs_factory.c deleted file mode 100644 index 978e6d9..0000000 --- a/ucs2-lib/src/ucs_factory.c +++ /dev/null @@ -1,830 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 MNS Factory. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_FAC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_factory.h" -#include "ucs_xrm_pv.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal macros */ -/*------------------------------------------------------------------------------------------------*/ -#define IS_VALID_ADDR(addr) ((UCS_ADDR_LOCAL_DEV == (addr)) || ((0x0FU < (addr)) && (0x300U > (addr))) || ((0x04FFU < (addr)) && (0x0FF0U > (addr)))) /* parasoft-suppress MISRA2004-19_7 "common definition of type cast improves code" */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Fac_ConstructFbi (CFactory * self, CInic * fbi, uint16_t address); -static CInic * Fac_SearchFbi(CFactory * self, uint16_t address); -static void Fac_ConstructNsm (CFactory * self, CNodeScriptManagement * nsm, uint16_t address); -static CRemoteSyncManagement * Fac_SearchRsm(CFactory * self, uint16_t address); -static CExtendedResourceManager * Fac_SearchXrm(CFactory * self, uint16_t address); -static CGpio * Fac_SearchGpio(CFactory * self, uint16_t address); -static CI2c* Fac_SearchI2c(CFactory * self, uint16_t address); -static CNodeScriptManagement * Fac_SearchNsm(CFactory * self, uint16_t address); -static CInic * Fac_GetUninitializedFbi (CFactory * self); -static CNodeScriptManagement * Fac_GetUninitializedNsm (CFactory * self); -static CRemoteSyncManagement * Fac_GetUninitializedRsm (CFactory * self); -static CExtendedResourceManager * Fac_GetUninitializedXrm (CFactory * self); -static CGpio * Fac_GetUninitializedGpio (CFactory * self); -static CI2c * Fac_GetUninitializedI2c (CFactory * self); -static bool Fac_IsFbiUninitialized(CInic * fbi); -static bool Fac_IsRsmUninitialized(CRemoteSyncManagement * rsm); -static bool Fac_IsXrmUninitialized(CExtendedResourceManager * xrm); -static bool Fac_IsGpioUninitialized(CGpio * gpio); -static bool Fac_IsI2cUninitialized(CI2c * i2c); -static bool Fac_IsNsmUninitialized(CNodeScriptManagement * nsm); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CFactory */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the MNS Factory class. - * \param self Instance pointer - * \param init_ptr init data_ptr - */ -void Fac_Ctor(CFactory * self, Fac_InitData_t * init_ptr) -{ - uint8_t i; - Rsm_InitData_t rsm_init_data; - - MISC_MEM_SET(self, 0, sizeof(CFactory)); - - /* set base and net instances */ - self->base_ptr = init_ptr->base_ptr; - self->net_ptr = init_ptr->net_ptr; - self->xrmp_ptr = init_ptr->xrmp_ptr; - self->icm_transceiver = init_ptr->icm_transceiver; - self->rcm_transceiver = init_ptr->rcm_transceiver; - - rsm_init_data.base_ptr = self->base_ptr; - rsm_init_data.net_ptr = self->net_ptr; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - rsm_init_data.inic_ptr = &self->fbi_list[i]; - Rsm_Ctor(&self->rsm_list[i], &rsm_init_data); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Returns the XRM instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \param res_debugging_fptr The resources debugging callback function - * \param check_unmute_fptr The check unmute callback function - * \return a reference to a XRM instance or \c NULL if no appropriate instance has been found. - */ -CExtendedResourceManager * Fac_GetXrm(CFactory * self, uint16_t address, Ucs_Xrm_ResourceDebugCb_t res_debugging_fptr, Ucs_Xrm_CheckUnmuteCb_t check_unmute_fptr) -{ - CRemoteSyncManagement * rsm_inst = NULL; - CExtendedResourceManager * xrm_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - xrm_inst = Fac_SearchXrm(self, address); - if (xrm_inst == NULL) - { - rsm_inst = Fac_GetRsm(self, address); - if (rsm_inst != NULL) - { - Xrm_InitData_t xrm_init_data; - xrm_inst = Fac_GetUninitializedXrm(self); - if (xrm_inst != NULL) - { - xrm_init_data.base_ptr = self->base_ptr; - xrm_init_data.net_ptr = self->net_ptr; - xrm_init_data.rsm_ptr = rsm_inst; - xrm_init_data.inic_ptr = rsm_inst->inic_ptr; - xrm_init_data.xrmp_ptr = self->xrmp_ptr; - xrm_init_data.check_unmute_fptr = check_unmute_fptr; - xrm_init_data.res_debugging_fptr = res_debugging_fptr; - Xrm_Ctor(xrm_inst, &xrm_init_data); - } - } - } - Xrm_SetResourceDebugCbFn(xrm_inst, res_debugging_fptr); - } - - return xrm_inst; -} - -/*! \brief Returns the XRM instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \param check_unmute_fptr The check unmute callback function - * \return a reference to a XRM instance or \c NULL if no appropriate instance has been found. - */ -CExtendedResourceManager * Fac_GetXrmLegacy(CFactory * self, uint16_t address, Ucs_Xrm_CheckUnmuteCb_t check_unmute_fptr) -{ - return Fac_GetXrm(self, address, NULL, check_unmute_fptr); -} - - -/*! \brief Returns the XRM instance associated with the resource list. - * \note <b>This function should only be used in case of Ucs_Xrm_Destroy() since it's certain in that case that the XRM instance for the given job list already exists!</b> - * \param self Instance pointer - * \param resource_object_list Reference to the job list - * \return a reference to a XRM instance or \c NULL if no appropriate instance has been found. - */ -CExtendedResourceManager * Fac_GetXrmByJobList(CFactory * self, UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[]) -{ - uint8_t i; - CExtendedResourceManager * ret_xrm = NULL; - - for(i=0U; i<FAC_NUM_DEVICES; i++) - { - if (Xrm_IsInMyJobList(&self->xrm_list[i], resource_object_list)) - { - ret_xrm = &self->xrm_list[i]; - break; - } - } - - return ret_xrm; -} - -/*! \brief Returns the FBlock INIC instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \return a reference to a FBI instance or \c NULL if no suitable instance has been found. - */ -CInic * Fac_GetInic(CFactory * self, uint16_t address) -{ - CInic * fbi_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - fbi_inst = Fac_SearchFbi(self, address); - if (fbi_inst == NULL) - { - fbi_inst = Fac_GetUninitializedFbi(self); - if (fbi_inst != NULL) - { - Fac_ConstructFbi(self, fbi_inst, address); - } - } - } - - return fbi_inst; -} - -/*! \brief Returns the CNodeScriptManagement instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \return a reference to a FBI instance or \c NULL if no suitable instance has been found. - */ -CNodeScriptManagement * Fac_GetNsm(CFactory * self, uint16_t address) -{ - CNodeScriptManagement * nsm_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - nsm_inst = Fac_SearchNsm(self, address); - if (nsm_inst == NULL) - { - nsm_inst = Fac_GetUninitializedNsm(self); - if (nsm_inst != NULL) - { - Fac_ConstructNsm(self, nsm_inst, address); - } - } - } - - return nsm_inst; -} - -/*! \brief Returns the RSM instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \return a reference to a RSM instance or \c NULL if no suitable instance has been found. - */ -CRemoteSyncManagement * Fac_GetRsm(CFactory * self, uint16_t address) -{ - CRemoteSyncManagement * rsm_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - rsm_inst = Fac_SearchRsm(self, address); - if (rsm_inst == NULL) - { - rsm_inst = Fac_GetUninitializedRsm(self); - if (rsm_inst != NULL) - { - Fac_ConstructFbi(self, rsm_inst->inic_ptr, address); - } - } - } - - return rsm_inst; -} - -/*! \brief Returns the GPIO instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \param trigger_event_status_fptr User GPIO trigger event status callback function pointer. - * \return a reference to a GPIO instance or \c NULL if no suitable instance has been found. - */ -CGpio * Fac_GetGpio(CFactory * self, uint16_t address, Ucs_Gpio_TriggerEventResultCb_t trigger_event_status_fptr) -{ - CGpio * gpio_inst = NULL; - CNodeScriptManagement * nsm_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - gpio_inst = Fac_SearchGpio(self, address); - if (NULL == gpio_inst) - { - nsm_inst = Fac_GetNsm(self, address); - if (NULL != nsm_inst) - { - Gpio_InitData_t gpio_init_data; - gpio_inst = Fac_GetUninitializedGpio(self); - if (NULL != gpio_inst) - { - gpio_init_data.nsm_ptr = nsm_inst; - gpio_init_data.inic_ptr = nsm_inst->rsm_ptr->inic_ptr; - gpio_init_data.trigger_event_status_fptr = trigger_event_status_fptr; - Gpio_Ctor(gpio_inst, &gpio_init_data); - } - } - } - } - - return gpio_inst; -} - -/*! \brief Returns the I2C instance associated with the given address. - * \param self Instance pointer - * \param address Address of the device associated with the instance - * \param i2c_interrupt_report_fptr User GPIO trigger event status callback function pointer. - * \return a reference to an I2C instance or \c NULL if no suitable instance has been found. - */ -CI2c * Fac_GetI2c(CFactory * self, uint16_t address, Ucs_I2c_IntEventReportCb_t i2c_interrupt_report_fptr) -{ - CI2c * i2c_inst = NULL; - CNodeScriptManagement * nsm_inst = NULL; - - if (IS_VALID_ADDR(address)) - { - i2c_inst = Fac_SearchI2c (self, address); - if (NULL == i2c_inst) - { - nsm_inst = Fac_GetNsm(self, address); - if (nsm_inst != NULL) - { - I2c_InitData_t i2c_init_data; - i2c_inst = Fac_GetUninitializedI2c(self); - if (NULL != i2c_inst) - { - i2c_init_data.nsm_ptr = nsm_inst; - i2c_init_data.inic_ptr = nsm_inst->rsm_ptr->inic_ptr; - i2c_init_data.i2c_interrupt_report_fptr = i2c_interrupt_report_fptr; - I2c_Ctor(i2c_inst, &i2c_init_data); - } - } - } - } - - return i2c_inst; -} - -/*! \brief Searches for the INIC instance associated with the given address and returns It if found. - * \param self Instance pointer - * \param address Address of the device associated with this instance - * \return a reference to the found instance otherwise \c NULL. - */ -CInic * Fac_FindInic(CFactory * self, uint16_t address) -{ - return Fac_SearchFbi (self, address); -} - -/*! \brief Searches for the NSM instance associated with the given address and returns It if found. - * \param self Instance pointer - * \param address Address of the device associated with this instance - * \return a reference to the found instance otherwise \c NULL. - */ -CNodeScriptManagement * Fac_FindNsm(CFactory * self, uint16_t address) -{ - return Fac_SearchNsm (self, address); -} - -/*! \brief Searches for the RSM instance associated with the given address and returns It if found. - * \param self Instance pointer - * \param address Address of the device associated with this instance - * \return a reference to the found instance otherwise \c NULL. - */ -CRemoteSyncManagement * Fac_FindRsm(CFactory * self, uint16_t address) -{ - return Fac_SearchRsm (self, address); -} - -/*! \brief Calls the given function for each instance of inst_type type. If the func_ptr - * returns true the loop is stopped. - * \param self Reference to a Factory Instance - * \param inst_type The instance type to be looked for - * \param func_ptr Reference of the callback function which is called for each node - * \param user_data_ptr Reference of optional user data pass to the func_ptr - */ -void Fac_Foreach(CFactory * self, Fac_Inst_t inst_type, Fac_ForeachFunc_t func_ptr, void *user_data_ptr) -{ - uint8_t j; - void * curr_inst = NULL; - bool exit_loop = false; - - for(j=0U; j<FAC_NUM_DEVICES; j++) - { - switch(inst_type) - { - case FAC_INST_INIC: - curr_inst = &self->fbi_list[j]; - if (Fac_IsFbiUninitialized((CInic *)curr_inst)) - { - curr_inst = NULL; - } - break; - - case FAC_INST_RSM: - curr_inst = &self->rsm_list[j]; - if (Fac_IsRsmUninitialized((CRemoteSyncManagement *)curr_inst)) - { - curr_inst = NULL; - } - break; - - case FAC_INST_XRM: - curr_inst = &self->xrm_list[j]; - if (Fac_IsXrmUninitialized((CExtendedResourceManager *)curr_inst)) - { - curr_inst = NULL; - } - break; - - case FAC_INST_GPIO: - curr_inst = &self->gpio_list[j]; - if (Fac_IsGpioUninitialized((CGpio *)curr_inst)) - { - curr_inst = NULL; - } - break; - - case FAC_INST_I2C: - curr_inst = &self->i2c_list[j]; - if (Fac_IsI2cUninitialized((CI2c *)curr_inst)) - { - curr_inst = NULL; - } - break; - - default: - break; - } - - if (curr_inst != NULL) - { - if (func_ptr(inst_type, curr_inst, user_data_ptr) != false) - { - exit_loop = true; - } - } - else - { - exit_loop = true; - } - - if (exit_loop) - { - break; - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Search for the FBI instance associated with the given address and return It. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found FBI or \c NULL if no suitable instance has been found. - */ -static CInic * Fac_SearchFbi(CFactory * self, uint16_t address) -{ - CInic * found_fbi = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsFbiUninitialized(&self->fbi_list[i])); i++) - { - if (tmp_addr == Inic_GetTargetAddress(&self->fbi_list[i])) - { - found_fbi = &self->fbi_list[i]; - break; - } - } - - return found_fbi; -} - -/*! \brief Search for the NSM instance associated with the given address and return It. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found NSM or \c NULL if no suitable instance has been found. - */ -static CNodeScriptManagement * Fac_SearchNsm(CFactory * self, uint16_t address) -{ - CNodeScriptManagement * found_nsm = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsNsmUninitialized(&self->nsm_list[i])); i++) - { - if (tmp_addr == self->nsm_list[i].target_address) - { - found_nsm = &self->nsm_list[i]; - break; - } - } - - return found_nsm; -} - -/*! \brief Search for the RSM instance associated with the given address. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found RSM or \c NULL if no suitable instance has been found. - */ -static CRemoteSyncManagement * Fac_SearchRsm(CFactory * self, uint16_t address) -{ - CRemoteSyncManagement * found_rsm = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsFbiUninitialized(self->rsm_list[i].inic_ptr)); i++) - { - if (tmp_addr == Inic_GetTargetAddress(self->rsm_list[i].inic_ptr)) - { - found_rsm = &self->rsm_list[i]; - break; - } - } - - return found_rsm; -} - -/*! \brief Search for the XRM instance associated with the given address. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found XRM or \c NULL if no suitable instance has been found. - */ -static CExtendedResourceManager * Fac_SearchXrm(CFactory * self, uint16_t address) -{ - CExtendedResourceManager * found_xrm = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsXrmUninitialized(&self->xrm_list[i])); i++) - { - if (tmp_addr == Inic_GetTargetAddress(self->xrm_list[i].rsm_ptr->inic_ptr)) - { - found_xrm = &self->xrm_list[i]; - break; - } - } - - return found_xrm; -} - -/*! \brief Search for the Gpio instance associated with the given address. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found GPIO or \c NULL if no suitable instance has been found. - */ -static CGpio * Fac_SearchGpio(CFactory * self, uint16_t address) -{ - CGpio * found_gpio = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsGpioUninitialized(&self->gpio_list[i])); i++) - { - if (tmp_addr == Inic_GetTargetAddress(self->gpio_list[i].nsm_ptr->rsm_ptr->inic_ptr)) - { - found_gpio = &self->gpio_list[i]; - break; - } - } - - return found_gpio; -} - -/*! \brief Search for the I2c instance associated with the given address. - * \param self Instance pointer - * \param address Address to be looked for - * \return a reference to the found GPIO or \c NULL if no suitable instance has been found. - */ -static CI2c * Fac_SearchI2c(CFactory * self, uint16_t address) -{ - CI2c * found_i2c = NULL; - uint8_t i; - uint16_t tmp_addr = address; - - if ((tmp_addr != UCS_ADDR_LOCAL_DEV) && (Net_IsOwnAddress(self->net_ptr, tmp_addr) == NET_IS_OWN_ADDR_NODE)) - { - tmp_addr = UCS_ADDR_LOCAL_DEV; - } - - for (i = 0U; (i<FAC_NUM_DEVICES) && (!Fac_IsI2cUninitialized(&self->i2c_list[i])); i++) - { - if (tmp_addr == Inic_GetTargetAddress(self->i2c_list[i].nsm_ptr->rsm_ptr->inic_ptr)) - { - found_i2c = &self->i2c_list[i]; - break; - } - } - - return found_i2c; -} - -/*! \brief Returns the next free uninitialized XRM instance - * \param self Instance pointer - * \return a reference to the next free uninitialized XRM instance if found, otherwise \c NULL. - */ -static CExtendedResourceManager * Fac_GetUninitializedXrm (CFactory * self) -{ - CExtendedResourceManager * tmp_xrm = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (self->xrm_list[i].rsm_ptr == NULL) - { - tmp_xrm = &self->xrm_list[i]; - break; - } - } - - return tmp_xrm; -} - -/*! \brief Returns the next free uninitialized FBI instance - * \param self Instance pointer - * \return a reference to the next free uninitialized FBI instance if found, otherwise \c NULL. - */ -static CInic * Fac_GetUninitializedFbi (CFactory * self) -{ - CInic * tmp_inic = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (self->fbi_list[i].base_ptr == NULL) - { - tmp_inic = &self->fbi_list[i]; - break; - } - } - - return tmp_inic; -} - -/*! \brief Returns the next free uninitialized NSM instance - * \param self Instance pointer - * \return a reference to the next free uninitialized NSM instance if found, otherwise \c NULL. - */ -static CNodeScriptManagement * Fac_GetUninitializedNsm (CFactory * self) -{ - CNodeScriptManagement * tmp_nsm = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (self->nsm_list[i].base_ptr == NULL) - { - tmp_nsm = &self->nsm_list[i]; - break; - } - } - - return tmp_nsm; -} - -/*! \brief Returns the next free uninitialized RSM instance - * \param self Instance pointer - * \return a reference to the next free uninitialized RSM instance if found, otherwise \c NULL. - */ -static CRemoteSyncManagement * Fac_GetUninitializedRsm (CFactory * self) -{ - CRemoteSyncManagement * tmp_rsm = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (Inic_GetTargetAddress(self->rsm_list[i].inic_ptr) == 0x0U) - { - tmp_rsm = &self->rsm_list[i]; - break; - } - } - - return tmp_rsm; -} - -/*! \brief Returns the next free uninitialized GPIO instance - * \param self Instance pointer - * \return a reference to the next free uninitialized GPIO instance if found, otherwise \c NULL. - */ -static CGpio * Fac_GetUninitializedGpio (CFactory * self) -{ - CGpio * tmp_gpio = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (NULL == self->gpio_list[i].nsm_ptr) - { - tmp_gpio = &self->gpio_list[i]; - break; - } - } - - return tmp_gpio; -} - -/*! \brief Returns the next free uninitialized I2C instance - * \param self Instance pointer - * \return a reference to the next free uninitialized I2C instance if found, otherwise \c NULL. - */ -static CI2c * Fac_GetUninitializedI2c (CFactory * self) -{ - CI2c * tmp_i2c = NULL; - uint8_t i; - - for (i = 0U; i<FAC_NUM_DEVICES; i++) - { - if (NULL == self->i2c_list[i].nsm_ptr) - { - tmp_i2c = &self->i2c_list[i]; - break; - } - } - - return tmp_i2c; -} - -/*! \brief Constructs the given FBI instance - * \param self the MNS factory Instance pointer - * \param fbi the INIC Instance pointer - * \param address the device address of this FBlock INIC - */ -static void Fac_ConstructFbi (CFactory * self, CInic * fbi, uint16_t address) -{ - Inic_InitData_t inic_init_data; - - if (address == UCS_ADDR_LOCAL_DEV) - { - inic_init_data.xcvr_ptr = self->icm_transceiver; - } - else - { - inic_init_data.xcvr_ptr = self->rcm_transceiver; - } - - inic_init_data.base_ptr = self->base_ptr; - inic_init_data.tgt_addr = address; - - Inic_Ctor(fbi, &inic_init_data); -} - -/*! \brief Constructs the given NSM instance - * \param self the MNS factory Instance pointer - * \param nsm the NSM Instance pointer - * \param address the device address - */ -static void Fac_ConstructNsm (CFactory * self, CNodeScriptManagement * nsm, uint16_t address) -{ - Nsm_InitData_t nsm_init_data; - - nsm_init_data.base_ptr = self->base_ptr; - nsm_init_data.rcm_ptr = self->rcm_transceiver; - nsm_init_data.rsm_ptr = Fac_GetRsm(self, address); - - Nsm_Ctor(nsm, &nsm_init_data); -} - -/*! \brief Checks whether the given FBlock INIC instance is uninitialized - * \param fbi the INIC Instance pointer - * \return \c true if the given Fbi instance is not initialized, otherwise \c False. - */ -static bool Fac_IsFbiUninitialized(CInic * fbi) -{ - return (fbi->base_ptr == NULL) ; -} - -/*! \brief Checks whether the given NSM instance is uninitialized - * \param nsm the NSM Instance pointer - * \return \c true if the given NSM instance is not initialized, otherwise \c False. - */ -static bool Fac_IsNsmUninitialized(CNodeScriptManagement * nsm) -{ - return (nsm->base_ptr == NULL) ; -} - -/*! \brief Checks whether the given RSM instance is uninitialized - * \param rsm Reference to the RSM instance pointer - * \return \c true if the given Fbi instance is not initialized, otherwise \c False. - */ -static bool Fac_IsRsmUninitialized(CRemoteSyncManagement * rsm) -{ - return Fac_IsFbiUninitialized(rsm->inic_ptr); -} - -/*! \brief Checks whether the given XRM instance is uninitialized - * \param xrm the XRM Instance pointer - * \return \c true if the given XRM instance is not initialized, otherwise \c False. - */ -static bool Fac_IsXrmUninitialized(CExtendedResourceManager * xrm) -{ - return (xrm->rsm_ptr == NULL) ; -} - -/*! \brief Checks whether the given GPIO instance is uninitialized - * \param gpio the GPIO Instance pointer - * \return \c true if the given GPIO instance is not initialized, otherwise \c False. - */ -static bool Fac_IsGpioUninitialized(CGpio * gpio) -{ - return (NULL == gpio->nsm_ptr); -} - -/*! \brief Checks whether the given I2C instance is uninitialized - * \param i2c the I2C Instance pointer - * \return \c true if the given I2C instance is not initialized, otherwise \c False. - */ -static bool Fac_IsI2cUninitialized(CI2c * i2c) -{ - return (NULL == i2c->nsm_ptr); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_fsm.c b/ucs2-lib/src/ucs_fsm.c deleted file mode 100644 index c180b0a..0000000 --- a/ucs2-lib/src/ucs_fsm.c +++ /dev/null @@ -1,172 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Finite State Machine. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_FSM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_fsm.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal definitions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief NIL-event, indicates that no event is pending at the moment */ -#define FSM_E_NILEVENT 0 - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static Fsm_Act_t Fsm_StateEval(CFsm *self); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Finite State Machine class. - * \param self Instance pointer - * \param inst_ptr Instance pointer used for state machine actions - * \param trans_table_ptr Pointer to transition table - * \param num_events Maximum number of events - * \param init_state Initialization state to start with - */ -void Fsm_Ctor(CFsm *self, void *inst_ptr, const Fsm_StateElem_t *trans_table_ptr, - uint8_t num_events, int8_t init_state) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->inst_ptr = inst_ptr; - self->event_occured = FSM_E_NILEVENT; /* Clear event variable */ - self->current_state = init_state; /* Set initialization state */ - self->transition_table_ptr = trans_table_ptr; /* Set pointer to given transition table */ - self->num_events = num_events; /* Store maximum number of events */ - self->internal_state = FSM_STATE_IDLE; /* Clear internal state */ -} - -/*! \brief Determine required action - * \details This function determines the required action in dependency of the current state - * and the triggered event. The current state will be transitioned to the next state. - * The internal event variable will be cleared and the determined action will be - * returned. - * \param self Instance pointer - * \return Determined required action - * \return \c NULL if no action is required - */ -static Fsm_Act_t Fsm_StateEval(CFsm *self) -{ - Fsm_Act_t retval = NULL; /* Set default return value */ - - if(self->event_occured != FSM_E_NILEVENT) /* Event occurred ? */ - { - if((uint8_t)self->event_occured <= self->num_events) /* Check if event is valid */ - { - /* Get state-matrix-element in dependency of current state and triggered event */ - uint8_t i = ((uint8_t)self->current_state * self->num_events) + (uint8_t)self->event_occured; - Fsm_StateElem_t stateEvaluation = self->transition_table_ptr[i]; - self->current_state = stateEvaluation.next_state; /* Set new state */ - self->internal_state = FSM_STATE_IDLE; /* Set internal state to \c IDLE */ - retval = stateEvaluation.action_fptr; /* Return required action */ - } - else - { - self->internal_state = FSM_STATE_ERROR; /* Error occurred: Unknown event */ - } - - self->event_occured = FSM_E_NILEVENT; /* Clear event variable */ - } - - return retval; -} - -/*! \brief Service function for Finite State Machines - * \details The state machine will be serviced until it will be stopped by the user or no - * further event is triggered. If a state transition occurred the associated action - * will be executed. - * \param self Instance pointer - * \return Internal state of the state machine (see \ref Fsm_State_t). - */ -Fsm_State_t Fsm_Service(CFsm *self) -{ - /* Internal state is set to \c FSM_STATE_SERVICE and any event is triggered? */ - while((self->internal_state == FSM_STATE_SERVICE) && (self->event_occured != FSM_E_NILEVENT)) - { - Fsm_Act_t action_fptr = Fsm_StateEval(self); /* Execute state transition */ - if(action_fptr != NULL) /* Action required ? */ - { - (*action_fptr)(self->inst_ptr); /* Execute action */ - } - } - - return self->internal_state; /* Return internal state machine state */ -} - -/*! \brief Set an event - * \details This function sets the given event and triggers the service for the given - * state machine. - * \param self Instance pointer - * \param e New event - */ -void Fsm_SetEvent(CFsm *self, int8_t e) -{ - if(self->internal_state != FSM_STATE_END) - { - self->event_occured = e; /* Set new event */ - self->internal_state = FSM_STATE_SERVICE; /* Set internal state to \c FSM_STATE_SERVICE */ - } -} - -/*! \brief Sets the wait state - * \details This function sets the given state state machine into the wait state. The state - * machine stops and must be re-triggered. - * \param self Instance pointer - */ -void Fsm_Wait(CFsm *self) -{ - if(self->internal_state != FSM_STATE_END) - { - self->internal_state = FSM_STATE_WAIT; /* Set internal state to \c WAIT */ - } -} - -/*! \brief End processing of the state machine - * \details If this function is called the given state machine will be stopped immediately. - * \param self Instance pointer - */ -void Fsm_End(CFsm *self) -{ - self->internal_state = FSM_STATE_END; /* Set internal state to \c END */ -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_gpio.c b/ucs2-lib/src/ucs_gpio.c deleted file mode 100644 index 645978f..0000000 --- a/ucs2-lib/src/ucs_gpio.c +++ /dev/null @@ -1,713 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 GPIO module. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_GPIO - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_gpio.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Gpio_PortCreateResCb(void *self, void *result_ptr); -static void Gpio_PinModeConfigResCb(void *self, void *result_ptr); -static void Gpio_PinStateConfigResCb(void *self, void *result_ptr); -static void Gpio_TriggerEventStatusCb(void *self, void *result_ptr); -static bool Gpio_RxFilter4NsmCb(Msg_MostTel_t *tel_ptr, void *self); -static void Gpio_RxError(void *self, Msg_MostTel_t *msg_ptr, Gpio_ErrResultCb_t res_cb_fptr); -static void Gpio_PortCreate_Result(void *self, Msg_MostTel_t *msg_ptr); -static void Gpio_PortPinMode_Status(void *self, Msg_MostTel_t *msg_ptr); -static void Gpio_PortPinState_Status(void *self, Msg_MostTel_t *msg_ptr); -static void Gpio_NsmResultCb(void * self, Nsm_Result_t result); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class Gpio */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the GPIO class. - * \param self Reference to CGpio instance. - * \param init_ptr init data_ptr. - */ -void Gpio_Ctor(CGpio *self, Gpio_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CGpio)); - - /* Set class instances */ - self->inic_ptr = init_ptr->inic_ptr; - self->nsm_ptr = init_ptr->nsm_ptr; - - self->curr_user_data.trigger_event_status_fptr = init_ptr->trigger_event_status_fptr; - - /* Init observers */ - Obs_Ctor(&self->triggerevent_observer, self, &Gpio_TriggerEventStatusCb); - - /* Subscribe Observers */ - Inic_AddObsrvGpioTriggerEvent(self->inic_ptr, &self->triggerevent_observer); - - /* Set device target address */ - self->device_address = Inic_GetTargetAddress(self->inic_ptr); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Creates the GPIO port - * \param self Reference to CGpio instance. - * \param index The index of the GPIO Port instance. - * \param debounce_time The timeout for the GPIO debounce timer (in ms). - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Gpio_CreatePort(CGpio * self, uint8_t index, uint16_t debounce_time, Ucs_Gpio_CreatePortResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - Gpio_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = index; - tmp_script->cfg_data[1] = MISC_HB(debounce_time); - tmp_script->cfg_data[2] = MISC_LB(debounce_time); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_GPIO_PORT_CREATE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_STARTRESULT; - tmp_script->cfg_msg.DataLen = 3U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &Gpio_RxFilter4NsmCb, &Gpio_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.portcreate_res_cb = res_fptr; - self->curr_res_cb = &Gpio_PortCreateResCb; - } - } - } - - return result; -} - -/*! \brief Sets the pin mode configuration of the given GPIO port - * \param self Reference to CGpio instance. - * \param gpio_port_handle The GPIO Port resource handle. - * \param pin The GPIO pin that is to be configured. - * \param mode The mode of the GPIO pin. - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Gpio_SetPinModeConfig(CGpio * self, uint16_t gpio_port_handle, uint8_t pin, Ucs_Gpio_PinMode_t mode, Ucs_Gpio_ConfigPinModeResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - Gpio_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(gpio_port_handle); - tmp_script->cfg_data[1] = MISC_LB(gpio_port_handle); - tmp_script->cfg_data[2] = pin; - tmp_script->cfg_data[3] = (uint8_t)mode; - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_GPIO_PORT_PIN_MODE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_SETGET; - tmp_script->cfg_msg.DataLen = 4U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &Gpio_RxFilter4NsmCb, &Gpio_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.pinmode_res_cb = res_fptr; - self->curr_res_cb = &Gpio_PinModeConfigResCb; - } - } - } - - return result; -} - -/*! \brief Gets the pin mode configuration of the given GPIO port - * \param self Reference to CGpio instance. - * \param gpio_port_handle The GPIO Port resource handle. - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Gpio_GetPinModeConfig(CGpio * self, uint16_t gpio_port_handle, Ucs_Gpio_ConfigPinModeResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - Gpio_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(gpio_port_handle); - tmp_script->cfg_data[1] = MISC_LB(gpio_port_handle); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_GPIO_PORT_PIN_MODE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_GET; - tmp_script->cfg_msg.DataLen = 2U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &Gpio_RxFilter4NsmCb, &Gpio_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.pinmode_res_cb = res_fptr; - self->curr_res_cb = &Gpio_PinModeConfigResCb; - } - } - } - - return result; -} - -/*! \brief Sets the pin state configuration of the given GPIO port - * \param self Reference to CGpio instance. - * \param gpio_port_handle The GPIO Port resource handle. - * \param mask The GPIO pin to be written. - * \param data The state of the GPIO pin to be written. - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Gpio_SetPinStateConfig(CGpio * self, uint16_t gpio_port_handle, uint16_t mask, uint16_t data, Ucs_Gpio_PinStateResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - Gpio_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(gpio_port_handle); - tmp_script->cfg_data[1] = MISC_LB(gpio_port_handle); - tmp_script->cfg_data[2] = MISC_HB(mask); - tmp_script->cfg_data[3] = MISC_LB(mask); - tmp_script->cfg_data[4] = MISC_HB(data); - tmp_script->cfg_data[5] = MISC_LB(data); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_GPIO_PORT_PIN_STATE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_SETGET; - tmp_script->cfg_msg.DataLen = 6U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &Gpio_RxFilter4NsmCb, &Gpio_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.pinstate_res_cb = res_fptr; - self->curr_res_cb = &Gpio_PinStateConfigResCb; - } - } - } - - return result; -} - -/*! \brief Retrieves the pin state configuration of the given GPIO port - * \param self Reference to CGpio instance. - * \param gpio_port_handle The GPIO Port resource handle. - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Gpio_GetPinStateConfig(CGpio * self, uint16_t gpio_port_handle, Ucs_Gpio_PinStateResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - Gpio_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(gpio_port_handle); - tmp_script->cfg_data[1] = MISC_LB(gpio_port_handle); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_GPIO_PORT_PIN_STATE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_GET; - tmp_script->cfg_msg.DataLen = 2U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &Gpio_RxFilter4NsmCb, &Gpio_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.pinstate_res_cb = res_fptr; - self->curr_res_cb = &Gpio_PinStateConfigResCb; - } - } - } - - return result; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Handles the result of the GPIOPortCreate.StartResultAck - * \param self Reference to CGpio instance - * \param result_ptr result pointer - */ -static void Gpio_PortCreateResCb(void *self, void *result_ptr) -{ - CGpio *self_ = (CGpio *)self; - uint16_t gpio_port_handle; - Ucs_Gpio_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_Gpio_Result_t)); - - if (NULL != result_ptr_) - { - gpio_port_handle = 0U; - res.code = UCS_GPIO_RES_ERR_CMD; - res.details.result_type = UCS_GPIO_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_GPIO_RES_SUCCESS; - gpio_port_handle = *(uint16_t *)result_ptr_->data_info; - } - else if(result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - res.details.result_type = UCS_GPIO_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_GPIO_RES_ERR_SYNC; - } - } - - if (NULL != self_->curr_user_data.portcreate_res_cb) - { - self_->curr_user_data.portcreate_res_cb(self_->device_address, gpio_port_handle, res, self_->inic_ptr->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the GPIOPortPinMode.Status - * \param self Reference to CGpio instance - * \param result_ptr result pointer - */ -static void Gpio_PinModeConfigResCb(void *self, void *result_ptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_GpioPortPinModeStatus_t status; - Ucs_Gpio_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_Gpio_Result_t)); - - if (NULL != result_ptr_) - { - status.gpio_handle = 0U; - status.cfg_list = NULL; - status.len = 0U; - res.code = UCS_GPIO_RES_ERR_CMD; - res.details.result_type = UCS_GPIO_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_GPIO_RES_SUCCESS; - status = *(Inic_GpioPortPinModeStatus_t *)result_ptr_->data_info; - } - else if(result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - res.details.result_type = UCS_GPIO_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_GPIO_RES_ERR_SYNC; - } - } - - if (NULL != self_->curr_user_data.pinmode_res_cb) - { - self_->curr_user_data.pinmode_res_cb(self_->device_address, status.gpio_handle, status.cfg_list, status.len, res, self_->inic_ptr->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the GPIOPortPinSate.Status - * \param self Reference to CGpio instance - * \param result_ptr result pointer - */ -static void Gpio_PinStateConfigResCb(void *self, void *result_ptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_GpioPortPinStateStatus_t status; - Ucs_Gpio_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_Gpio_Result_t)); - - if (NULL != result_ptr_) - { - status.gpio_handle = 0U; - status.current_state = 0U; - status.sticky_state = 0U; - res.code = UCS_GPIO_RES_ERR_CMD; - res.details.result_type = UCS_GPIO_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_GPIO_RES_SUCCESS; - status = *(Inic_GpioPortPinStateStatus_t *)result_ptr_->data_info; - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_GPIO_RES_ERR_SYNC; - } - else - { - res.details.result_type = UCS_GPIO_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - } - - if (NULL != self_->curr_user_data.pinstate_res_cb) - { - self_->curr_user_data.pinstate_res_cb(self_->device_address, status.gpio_handle, status.current_state, status.sticky_state, res, self_->inic_ptr->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the GPIOPortTriggerEvent.Status - * \param self Reference to CGpio instance - * \param result_ptr result pointer - */ -static void Gpio_TriggerEventStatusCb(void *self, void *result_ptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_GpioTriggerEventStatus_t status; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (NULL != result_ptr_) - { - status = *(Inic_GpioTriggerEventStatus_t *)result_ptr_->data_info; - - if (NULL != self_->curr_user_data.trigger_event_status_fptr) - { - self_->curr_user_data.trigger_event_status_fptr(self_->device_address, status.gpio_handle, status.rising_edges, status.falling_edges, status.levels, self_->inic_ptr->base_ptr->ucs_user_ptr); - } - } -} - - -/*! \brief Checks whether the incoming is our message and handles It if it's. - * \param tel_ptr Reference to the message object. - * \param self Reference to the user argument. - * \return Returns \c true to discard the message and free it to the pool if it's our message. Otherwise, returns - * \c false. - */ -static bool Gpio_RxFilter4NsmCb(Msg_MostTel_t *tel_ptr, void *self) -{ - CGpio *self_ = (CGpio *)self; - bool ret_val = true; - - if ((tel_ptr != NULL) && (tel_ptr->id.function_id == self_->curr_script.script.send_cmd->FunktId)) - { - if (tel_ptr->id.op_type == UCS_OP_RESULT) - { - switch(tel_ptr->id.function_id) - { - case INIC_FID_GPIO_PORT_CREATE: - Gpio_PortCreate_Result(self_, tel_ptr); - break; - case INIC_FID_GPIO_PORT_PIN_MODE: - Gpio_PortPinMode_Status(self_, tel_ptr); - break; - case INIC_FID_GPIO_PORT_PIN_STATE: - Gpio_PortPinState_Status(self_, tel_ptr); - break; - default: - ret_val = false; - break; - } - } - else if (tel_ptr->id.op_type == UCS_OP_ERROR) - { - Gpio_ErrResultCb_t res_cb_fptr = self_->curr_res_cb; - Gpio_RxError(self_, tel_ptr, res_cb_fptr); - } - } - else - { - ret_val = false; - } - - return ret_val; -} - -/*! \brief Result callback function for NSM result. Whenever this function is called the NodeScripting has finished the - * script's execution. This function handles transmission and sync error. Only these two kind of errors can occur. - * \param self Reference to the called user instance. - * \param result Result of the scripting operation. - */ -static void Gpio_NsmResultCb(void * self, Nsm_Result_t result) -{ - CGpio *self_ = (CGpio *)self; - - if (self_ != NULL) - { - Inic_StdResult_t res_data; - bool allow_report = false; - - if ((result.code == UCS_NS_RES_ERROR) && (result.details.result_type == NS_RESULT_TYPE_TX)) - { - res_data.data_info = &result.details.tx_result; - res_data.result.code = UCS_RES_ERR_TRANSMISSION; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - allow_report = true; - } - else if ((result.code == UCS_NS_RES_ERROR) && (result.details.result_type == NS_RESULT_TYPE_TGT_SYNC)) - { - res_data.data_info = &result.details.inic_result; - res_data.result.code = result.details.inic_result.code; - res_data.result.info_ptr = result.details.inic_result.info_ptr; - res_data.result.info_size = result.details.inic_result.info_size; - allow_report = true; - } - else if ((result.code == UCS_NS_RES_ERROR) && ((result.details.tx_result == UCS_MSG_STAT_OK) || - (result.details.inic_result.code == UCS_RES_SUCCESS))) - { - res_data.data_info = NULL; - res_data.result.code = UCS_RES_ERR_TIMEOUT; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - - TR_ERROR((self_->nsm_ptr->base_ptr->ucs_user_ptr, "[GPIO]", "TIMEOUT ERROR occurred for currently GPIO command. No response received from target device with address 0x%X.", 1U, self_->device_address)); - } - - if ((self_->curr_res_cb != NULL) && (allow_report)) - { - self_->curr_res_cb(self_, &res_data); - } - } -} - -/*---------------------------------- GW Functions ----------------------------------*/ - -/*! \brief Error Handler function for all GPIO methods - * \param self Reference to CGpio instance - * \param msg_ptr Pointer to received message - * \param res_cb_fptr Pointer to a specified error handler function - */ -static void Gpio_RxError(void *self, Msg_MostTel_t *msg_ptr, Gpio_ErrResultCb_t res_cb_fptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_->inic_ptr, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - if (res_cb_fptr != NULL) - { - res_cb_fptr(self_, &res_data); - } -} - -/*! \brief Handler function for GPIOPortCreate.ResultAck - * \details Element res_data.data_info points to the variable gpio_port_handle which holds the - * GPIO Port resource handle. - * \param self Reference to CGpio instance - * \param msg_ptr Pointer to received message - */ -static void Gpio_PortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CGpio *self_ = (CGpio *)self; - uint16_t gpio_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&gpio_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &gpio_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Gpio_PortCreateResCb(self_, &res_data); -} - -/*! \brief Handler function for GPIOPortPinMode.Status - * \param self Reference to CGpio instance - * \param msg_ptr Pointer to received message - */ -static void Gpio_PortPinMode_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_GpioPortPinModeStatus_t res; - Inic_StdResult_t res_data; - uint8_t i = 2U, j = 0U; - Ucs_Gpio_PinConfiguration_t pin_ls[16U]; - - res.cfg_list = &pin_ls[0]; - res.len = (msg_ptr->tel.tel_len - 2U) >> 1U; - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&res.gpio_handle, &(msg_ptr->tel.tel_data_ptr[0])); - for (; (i < msg_ptr->tel.tel_len) && (j < 16U); i=i+2U) - { - pin_ls[j].pin = msg_ptr->tel.tel_data_ptr[i]; - pin_ls[j].mode = (Ucs_Gpio_PinMode_t)msg_ptr->tel.tel_data_ptr[i+1U]; - j++; - } - - Gpio_PinModeConfigResCb(self_, &res_data); -} - -/*! \brief Handler function for GPIOPortPinState.Status - * \param self Reference to CGpio instance - * \param msg_ptr Pointer to received message - */ -static void Gpio_PortPinState_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CGpio *self_ = (CGpio *)self; - Inic_GpioPortPinStateStatus_t res; - Inic_StdResult_t res_data; - - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&res.gpio_handle, &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_WORD(&res.current_state, &(msg_ptr->tel.tel_data_ptr[2])); - MISC_DECODE_WORD(&res.sticky_state, &(msg_ptr->tel.tel_data_ptr[4])); - - Gpio_PinStateConfigResCb(self_, &res_data); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_i2c.c b/ucs2-lib/src/ucs_i2c.c deleted file mode 100644 index d2523b0..0000000 --- a/ucs2-lib/src/ucs_i2c.c +++ /dev/null @@ -1,646 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 I2C Module. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_I2C - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_i2c.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void I2c_PortCreateResCb(void *self, void *result_ptr); -static void I2c_PortWriteResCb(void *self, void *result_ptr); -static void I2c_PortReadResCb(void *self, void *result_ptr); -static void I2c_TriggerEventStatusCb(void *self, void *result_ptr); -static bool I2c_RxFilter4NsmCb(Msg_MostTel_t *tel_ptr, void *self); -static void I2c_PortCreate_Result(void *self, Msg_MostTel_t *msg_ptr); -static void I2c_PortRead_Result(void *self, Msg_MostTel_t *msg_ptr); -static void I2c_PortWrite_Result(void *self, Msg_MostTel_t *msg_ptr); -static void I2c_RxError(void *self, Msg_MostTel_t *msg_ptr, I2c_ErrResultCb_t res_cb_fptr); -static void I2c_NsmResultCb(void * self, Nsm_Result_t result); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class I2C */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the I2C class. - * \param self Instance pointer - * \param init_ptr init data_ptr - */ -void I2c_Ctor(CI2c * self, I2c_InitData_t * init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CI2c)); - - /* Set class instances */ - self->inic_ptr = init_ptr->inic_ptr; - self->base_ptr = self->inic_ptr->base_ptr; - self->nsm_ptr = init_ptr->nsm_ptr; - - self->curr_user_data.i2c_interrupt_report_fptr = init_ptr->i2c_interrupt_report_fptr; - - /* Init GPIOTriggerEvent observer */ - Obs_Ctor(&self->triggerevent_observer, self, &I2c_TriggerEventStatusCb); - - /* Subscribe Observers */ - Inic_AddObsrvGpioTriggerEvent(self->inic_ptr, &self->triggerevent_observer); - - /* Set device id */ - self->device_address = Inic_GetTargetAddress(self->inic_ptr); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Creates an I2C Port with its associated parameter. - * \param self Reference to CI2c instance - * \param index I2C Port instance - * \param speed The speed grade of the I2C Port - * \param i2c_int_mask The I2C interrupt pin mask on the GPIO Port. - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t I2c_CreatePort(CI2c * self, uint8_t index, Ucs_I2c_Speed_t speed, uint8_t i2c_int_mask, Ucs_I2c_CreatePortResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - uint8_t address = 0x00U; /* Address will be ignored */ - uint8_t mode = 0x01U; /* Master Mode */ - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - I2c_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = index; - tmp_script->cfg_data[1] = address; - tmp_script->cfg_data[2] = mode; - tmp_script->cfg_data[3] = (uint8_t)speed; - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_I2C_PORT_CREATE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_STARTRESULT; - tmp_script->cfg_msg.DataLen = 4U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &I2c_RxFilter4NsmCb, &I2c_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.int_pin_mask = i2c_int_mask; - self->curr_user_data.portcreate_res_cb = res_fptr; - self->curr_res_cb = &I2c_PortCreateResCb; - } - } - } - - return result; -} - -/*! \brief Writes a block of bytes to an I2C device at a specified I2C address. - * \param self Reference to CI2c instance - * \param port_handle Port resource handle - * \param mode The write transfer mode - * \param block_count The number of blocks to be written to the I2C address. - * \param slave_address The 7-bit I2C slave address of the peripheral to be read - * \param timeout The timeout for the I2C Port write - * \param data_len Number of bytes to be written to the addressed I2C peripheral - * \param data_ptr Reference to the data to be written - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t I2c_WritePort(CI2c * self, uint16_t port_handle, Ucs_I2c_TrMode_t mode, uint8_t block_count, uint8_t slave_address, uint16_t timeout, uint8_t data_len, uint8_t data_ptr[], Ucs_I2c_WritePortResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - if ((0U < data_len) && (NULL != data_ptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - bool is_ok = true; - - result = UCS_RET_ERR_PARAM; - if ((UCS_I2C_BURST_MODE == mode) && (0U == block_count)) - { - is_ok = false; - } - - if (is_ok) - { - uint8_t i; - I2c_Script_t * tmp_script = &self->curr_script; - - for (i = 0U; i < data_len; i++) - { - tmp_script->cfg_data[8U + i] = data_ptr[i]; - } - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(port_handle); - tmp_script->cfg_data[1] = MISC_LB(port_handle); - tmp_script->cfg_data[2] = (uint8_t)mode; - tmp_script->cfg_data[3] = block_count; - tmp_script->cfg_data[4] = slave_address; - tmp_script->cfg_data[5] = (mode == UCS_I2C_BURST_MODE) ? (data_len/block_count):data_len; - tmp_script->cfg_data[6] = MISC_HB(timeout); - tmp_script->cfg_data[7] = MISC_LB(timeout); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_I2C_PORT_WRITE; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_STARTRESULT; - tmp_script->cfg_msg.DataLen = data_len + 8U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &I2c_RxFilter4NsmCb, &I2c_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.portwrite_res_cb = res_fptr; - self->curr_res_cb = &I2c_PortWriteResCb; - } - } - } - } - } - - return result; -} - -/*! \brief Reads a block of bytes from an I2C device at a specified I2C address. - * \param self Reference to CI2c instance - * \param port_handle Port resource handle - * \param slave_address The 7-bit I2C slave address of the peripheral to be read - * \param data_len Number of bytes to be read from the address - * \param timeout The timeout for the I2C Port read - * \param res_fptr Required result callback function pointer. - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t I2c_ReadPort(CI2c * self, uint16_t port_handle, uint8_t slave_address, uint8_t data_len, uint16_t timeout, Ucs_I2c_ReadPortResCb_t res_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((NULL != self) && (NULL != res_fptr)) - { - result = UCS_RET_ERR_API_LOCKED; - if (!Nsm_IsLocked(self->nsm_ptr)) - { - I2c_Script_t * tmp_script = &self->curr_script; - - /* Set Data */ - tmp_script->cfg_data[0] = MISC_HB(port_handle); - tmp_script->cfg_data[1] = MISC_LB(port_handle); - tmp_script->cfg_data[2] = slave_address; - tmp_script->cfg_data[3] = data_len; - tmp_script->cfg_data[4] = MISC_HB(timeout); - tmp_script->cfg_data[5] = MISC_LB(timeout); - - /* Set message id */ - tmp_script->cfg_msg.FBlockId = FB_INIC; - tmp_script->cfg_msg.InstId = 0U; - tmp_script->cfg_msg.FunktId = INIC_FID_I2C_PORT_READ; - tmp_script->cfg_msg.OpCode = (uint8_t)UCS_OP_STARTRESULT; - tmp_script->cfg_msg.DataLen = 6U; - tmp_script->cfg_msg.DataPtr = &tmp_script->cfg_data[0]; - - /* Set script */ - tmp_script->script.send_cmd = &tmp_script->cfg_msg; - tmp_script->script.pause = 0U; - - /* Transmit script */ - result = Nsm_Run_Pv(self->nsm_ptr, &tmp_script->script, 1U, self, &I2c_RxFilter4NsmCb, &I2c_NsmResultCb); - if(result == UCS_RET_SUCCESS) - { - self->curr_user_data.portread_res_cb = res_fptr; - self->curr_res_cb = &I2c_PortReadResCb; - } - } - } - - return result; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Handles the result of the I2CPortCreate.StartResultAck - * \param self Instance pointer - * \param result_ptr result pointer - */ -static void I2c_PortCreateResCb(void *self, void *result_ptr) -{ - CI2c *self_ = (CI2c *)self; - uint16_t i2c_port_handle; - Ucs_I2c_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_I2c_Result_t)); - - if (NULL != result_ptr_) - { - i2c_port_handle = 0U; - res.code = UCS_I2C_RES_ERR_CMD; - res.details.result_type = UCS_I2C_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_I2C_RES_SUCCESS; - i2c_port_handle = *(uint16_t *)result_ptr_->data_info; - } - else if(result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - res.details.result_type = UCS_I2C_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_I2C_RES_ERR_SYNC; - } - } - - if (NULL != self_->curr_user_data.portcreate_res_cb) - { - self_->curr_user_data.portcreate_res_cb(self_->device_address, i2c_port_handle, res, self_->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the I2CPortWrite.StartResultAck - * \param self Instance pointer - * \param result_ptr result pointer - */ -static void I2c_PortWriteResCb(void *self, void *result_ptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_I2cWriteResStatus_t wr_res; - Ucs_I2c_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_I2c_Result_t)); - - if (NULL != result_ptr_) - { - wr_res.data_len = 0U; - wr_res.port_handle = 0U; - wr_res.slave_address = 0U; - res.code = UCS_I2C_RES_ERR_CMD; - res.details.result_type = UCS_I2C_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_I2C_RES_SUCCESS; - wr_res = *(Inic_I2cWriteResStatus_t *)result_ptr_->data_info; - } - else if(result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - res.details.result_type = UCS_I2C_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_I2C_RES_ERR_SYNC; - } - } - - if (NULL != self_->curr_user_data.portwrite_res_cb) - { - self_->curr_user_data.portwrite_res_cb(self_->device_address, wr_res.port_handle, wr_res.slave_address, wr_res.data_len, res, self_->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the I2CPortRead.StartResultAck - * \param self Instance pointer - * \param result_ptr result pointer - */ -static void I2c_PortReadResCb(void *self, void *result_ptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_I2cReadResStatus_t read_res; - Ucs_I2c_Result_t res; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - /* Init result */ - MISC_MEM_SET(&res, 0, sizeof(Ucs_I2c_Result_t)); - - if (NULL != result_ptr_) - { - read_res.data_len = 0U; - read_res.data_ptr = NULL; - read_res.port_handle = 0U; - read_res.slave_address = 0U; - res.code = UCS_I2C_RES_ERR_CMD; - res.details.result_type = UCS_I2C_RESULT_TYPE_TGT; - res.details.inic_result = result_ptr_->result; - if (result_ptr_->data_info != NULL) - { - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - res.code = UCS_I2C_RES_SUCCESS; - read_res = *(Inic_I2cReadResStatus_t *)result_ptr_->data_info; - } - else if(result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - res.details.result_type = UCS_I2C_RESULT_TYPE_TX; - res.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else if (result_ptr_->result.code == UCS_RES_ERR_CONFIGURATION) - { - res.code = UCS_I2C_RES_ERR_SYNC; - } - } - - if (NULL != self_->curr_user_data.portread_res_cb) - { - self_->curr_user_data.portread_res_cb(self_->device_address, read_res.port_handle, read_res.slave_address, read_res.data_len, read_res.data_ptr, res, self_->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Handles the result of the GPIOPortTriggerEvent.Status - * \param self Instance pointer - * \param result_ptr result pointer - */ -static void I2c_TriggerEventStatusCb(void *self, void *result_ptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if ((NULL != result_ptr_) && - (NULL != self_->curr_user_data.i2c_interrupt_report_fptr)) - { - Inic_GpioTriggerEventStatus_t status; - uint16_t int_mask = self_->curr_user_data.int_pin_mask; - status = *(Inic_GpioTriggerEventStatus_t *)result_ptr_->data_info; - - if ((!status.is_first_report) && - ((int_mask == (status.rising_edges & int_mask)) || - (int_mask == (status.levels & int_mask)) || - (int_mask == (status.falling_edges & int_mask)))) - { - self_->curr_user_data.i2c_interrupt_report_fptr(self_->device_address, self_->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Checks whether the incoming is our message and handles It if it's. - * \param tel_ptr Reference to the message object. - * \param self Reference to the user argument. - * \return Returns \c true to discard the message and free it to the pool if it's our message. Otherwise, returns - * \c false. - */ -static bool I2c_RxFilter4NsmCb(Msg_MostTel_t *tel_ptr, void *self) -{ - CI2c *self_ = (CI2c *)self; - bool ret_val = true; - - if ((tel_ptr != NULL) && (tel_ptr->id.function_id == self_->curr_script.script.send_cmd->FunktId)) - { - if (tel_ptr->id.op_type == UCS_OP_RESULT) - { - switch(tel_ptr->id.function_id) - { - case INIC_FID_I2C_PORT_CREATE: - I2c_PortCreate_Result(self_, tel_ptr); - break; - case INIC_FID_I2C_PORT_READ: - I2c_PortRead_Result(self_, tel_ptr); - break; - case INIC_FID_I2C_PORT_WRITE: - I2c_PortWrite_Result(self_, tel_ptr); - break; - default: - ret_val = false; - break; - } - } - else if (tel_ptr->id.op_type == UCS_OP_ERROR) - { - I2c_ErrResultCb_t res_cb_fptr = self_->curr_res_cb; - I2c_RxError(self_, tel_ptr, res_cb_fptr); - } - } - else - { - ret_val = false; - } - - return ret_val; -} - -/*! \brief Result callback function for NSM result. Whenever this function is called the NodeScripting has finished the - * script's execution. This function handles transmission and sync error. Only these two kind of errors can occur. - * \param self Reference to the called user instance. - * \param result Result of the scripting operation. - */ -static void I2c_NsmResultCb(void * self, Nsm_Result_t result) -{ - CI2c *self_ = (CI2c *)self; - - if (self_ != NULL) - { - Inic_StdResult_t res_data; - bool allow_report = false; - - if ((result.code == UCS_NS_RES_ERROR) && (result.details.result_type == NS_RESULT_TYPE_TX)) - { - res_data.data_info = &result.details.tx_result; - res_data.result.code = UCS_RES_ERR_TRANSMISSION; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - allow_report = true; - } - else if ((result.code == UCS_NS_RES_ERROR) && (result.details.result_type == NS_RESULT_TYPE_TGT_SYNC)) - { - res_data.data_info = &result.details.inic_result; - res_data.result.code = result.details.inic_result.code; - res_data.result.info_ptr = result.details.inic_result.info_ptr; - res_data.result.info_size = result.details.inic_result.info_size; - allow_report = true; - } - else if ((result.code == UCS_NS_RES_ERROR) && ((result.details.tx_result == UCS_MSG_STAT_OK) || - (result.details.inic_result.code == UCS_RES_SUCCESS))) - { - res_data.data_info = NULL; - res_data.result.code = UCS_RES_ERR_TIMEOUT; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[I2C]", "TIMEOUT ERROR occurred for currently I2C command. No response received from target device with address 0x%X.", 1U, self_->device_address)); - } - - if ((self_->curr_res_cb != NULL) && (allow_report)) - { - self_->curr_res_cb(self_, &res_data); - } - } -} - -/*---------------------------------- GW Functions ----------------------------------*/ - -/*! \brief Error Handler function for all I2C methods - * \param self Reference to CI2c instance - * \param msg_ptr Pointer to received message - * \param res_cb_fptr Pointer to a specified error handler function - */ -static void I2c_RxError(void *self, Msg_MostTel_t *msg_ptr, I2c_ErrResultCb_t res_cb_fptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_->inic_ptr, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - if (res_cb_fptr != NULL) - { - res_cb_fptr(self_, &res_data); - } -} - -/*! \brief Handler function for I2CPortCreate.ResultAck - * \details Element res_data.data_info points to the variable i2c_port_handle which holds the - * I2C Port resource handle. - * \param self Reference to CI2c instance - * \param msg_ptr Pointer to received message - */ -static void I2c_PortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CI2c *self_ = (CI2c *)self; - uint16_t i2c_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&i2c_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &i2c_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - I2c_PortCreateResCb(self_, &res_data); -} - -/*! \brief Handler function for I2CPortRead.ResultAck - * \details Element res_data.data_info points to a variable of type Inic_I2cReadResStatus_t which holds the - * the results of the I2CPortRead.StartResultAck command. - * \param self Reference to CI2c instance - * \param msg_ptr Pointer to received message - */ -static void I2c_PortRead_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_I2cReadResStatus_t i2c_read_res; - Inic_StdResult_t res_data; - - res_data.data_info = &i2c_read_res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&i2c_read_res.port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - i2c_read_res.slave_address = msg_ptr->tel.tel_data_ptr[2]; - i2c_read_res.data_len = msg_ptr->tel.tel_data_ptr[3]; - i2c_read_res.data_ptr = &msg_ptr->tel.tel_data_ptr[4]; - - I2c_PortReadResCb(self_, &res_data); -} - -/*! \brief Handler function for I2CPortWrite.ResultAck - * \details Element res_data.data_info points to a variable of type Inic_I2cWriteResStatus_t which holds the - * the results of the I2CPortWrite.StartResultAck command. - * \param self Reference to CI2c instance - * \param msg_ptr Pointer to received message - */ -static void I2c_PortWrite_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CI2c *self_ = (CI2c *)self; - Inic_I2cWriteResStatus_t i2c_write_res; - Inic_StdResult_t res_data; - - res_data.data_info = &i2c_write_res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&i2c_write_res.port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - i2c_write_res.slave_address = msg_ptr->tel.tel_data_ptr[2]; - i2c_write_res.data_len = msg_ptr->tel.tel_data_ptr[3]; - - I2c_PortWriteResCb(self_, &res_data); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_inic.c b/ucs2-lib/src/ucs_inic.c deleted file mode 100644 index 5d96a49..0000000 --- a/ucs2-lib/src/ucs_inic.c +++ /dev/null @@ -1,1817 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 FBlock INIC - * \details Contains the general, device an network management parts of INIC management - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_INIC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_misc.h" -#include "ucs_ret_pb.h" -#include "ucs_inic.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief List of all INIC messages */ -static const Dec_FktOpIcm_t inic_handler[] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - { DEC_FKTOP(INIC_FID_NOTIFICATION, UCS_OP_STATUS), Inic_Notification_Status }, - { DEC_FKTOP(INIC_FID_NOTIFICATION, UCS_OP_ERROR), Inic_Notification_Error }, - { DEC_FKTOP(INIC_FID_DEVICE_STATUS, UCS_OP_STATUS), Inic_DeviceStatus_Status }, - { DEC_FKTOP(INIC_FID_DEVICE_STATUS, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_DEVICE_VERSION, UCS_OP_STATUS), Inic_DeviceVersion_Status }, - { DEC_FKTOP(INIC_FID_DEVICE_VERSION, UCS_OP_ERROR), Inic_DeviceVersion_Error }, - { DEC_FKTOP(INIC_FID_DEVICE_POWER_OFF, UCS_OP_STATUS), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_DEVICE_POWER_OFF, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_DEVICE_ATTACH, UCS_OP_RESULT), Inic_DeviceAttach_Result }, - { DEC_FKTOP(INIC_FID_DEVICE_ATTACH, UCS_OP_ERROR), Inic_DeviceAttach_Error }, - { DEC_FKTOP(INIC_FID_DEVICE_SYNC, UCS_OP_RESULT), Inic_DeviceSync_Result }, - { DEC_FKTOP(INIC_FID_DEVICE_SYNC, UCS_OP_ERROR), Inic_DeviceSync_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_STATUS, UCS_OP_STATUS), Inic_NwStatus_Status }, - { DEC_FKTOP(INIC_FID_MOST_NW_STATUS, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_MOST_NW_CFG, UCS_OP_STATUS), Inic_NwConfig_Status }, - { DEC_FKTOP(INIC_FID_MOST_NW_CFG, UCS_OP_ERROR), Inic_NwConfig_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_FRAME_COUNTER, UCS_OP_STATUS), Inic_NwFrameCounter_Status }, - { DEC_FKTOP(INIC_FID_MOST_NW_FRAME_COUNTER, UCS_OP_ERROR), Inic_NwFrameCounter_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_STARTUP, UCS_OP_RESULT), Inic_NwStartup_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_STARTUP, UCS_OP_ERROR), Inic_NwStartup_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_SHUTDOWN, UCS_OP_RESULT), Inic_NwShutdown_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_SHUTDOWN, UCS_OP_ERROR), Inic_NwShutdown_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_TRIGGER_RBD, UCS_OP_RESULT), Inic_NwTriggerRbd_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_TRIGGER_RBD, UCS_OP_ERROR), Inic_NwTriggerRbd_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_RBD_RESULT, UCS_OP_STATUS), Inic_NwRbdResult_Status }, - { DEC_FKTOP(INIC_FID_MOST_NW_RBD_RESULT, UCS_OP_ERROR), Inic_NwRbdResult_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_ATTACH, UCS_OP_RESULT), Inic_NwAttach_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_ATTACH, UCS_OP_ERROR), Inic_NwAttach_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_FORCE_NO_AVAIL, UCS_OP_STATUS), Inic_NwForceNotAvailable_Status }, - { DEC_FKTOP(INIC_FID_MOST_NW_FORCE_NO_AVAIL, UCS_OP_ERROR), Inic_NwForceNotAvailable_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_SYS_DIAGNOSIS, UCS_OP_RESULT), Inic_NwSysDiagnosis_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_SYS_DIAGNOSIS, UCS_OP_ERROR), Inic_NwSysDiagnosis_Error }, - { DEC_FKTOP(INIC_FID_MOST_NW_SYS_DIAG_END, UCS_OP_RESULT), Inic_NwSysDiagEnd_Result }, - { DEC_FKTOP(INIC_FID_MOST_NW_SYS_DIAG_END, UCS_OP_ERROR), Inic_NwSysDiagEnd_Error }, - { DEC_FKTOP(INIC_FID_BACK_CHANNEL_DIAGNOSIS, UCS_OP_RESULT), Inic_BCDiagnosis_Result }, - { DEC_FKTOP(INIC_FID_BACK_CHANNEL_DIAGNOSIS, UCS_OP_ERROR), Inic_BCDiagnosis_Error }, - { DEC_FKTOP(INIC_FID_BACK_CHANNEL_DIAG_END, UCS_OP_RESULT), Inic_BCDiagEnd_Result }, - { DEC_FKTOP(INIC_FID_BACK_CHANNEL_DIAG_END, UCS_OP_ERROR), Inic_BCDiagEnd_Error }, - { DEC_FKTOP(INIC_FID_MOST_PORT_STATUS, UCS_OP_STATUS), Inic_MostPortStatus_Status }, - { DEC_FKTOP(INIC_FID_MOST_PORT_STATUS, UCS_OP_ERROR), Inic_MostPortStatus_Error }, - { DEC_FKTOP(INIC_FID_MOST_SOCKET_CREATE, UCS_OP_RESULT), Inic_MostSocketCreate_Result }, - { DEC_FKTOP(INIC_FID_MOST_SOCKET_CREATE, UCS_OP_ERROR), Inic_MostSocketCreate_Error }, - { DEC_FKTOP(INIC_FID_MOST_SOCKET_STATUS, UCS_OP_STATUS), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_MOST_SOCKET_STATUS, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_MLB_PORT_CREATE, UCS_OP_RESULT), Inic_MlbPortCreate_Result }, - { DEC_FKTOP(INIC_FID_MLB_PORT_CREATE, UCS_OP_ERROR), Inic_MlbPortCreate_Error }, -/* { DEC_FKTOP(INIC_FID_MLB_PORT_ALLOCATE_ONLY, UCS_OP_RESULT), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_MLB_PORT_ALLOCATE_ONLY, UCS_OP_ERROR), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_MLB_PORT_DEALLOC_ONLY, UCS_OP_RESULT), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_MLB_PORT_DEALLOC_ONLY, UCS_OP_ERROR), Inic_DummyHandler }, */ - { DEC_FKTOP(INIC_FID_MLB_SOCKET_CREATE, UCS_OP_RESULT), Inic_MlbSocketCreate_Result }, - { DEC_FKTOP(INIC_FID_MLB_SOCKET_CREATE, UCS_OP_ERROR), Inic_MlbSocketCreate_Error }, - { DEC_FKTOP(INIC_FID_SPI_PORT_CREATE, UCS_OP_RESULT), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_SPI_PORT_CREATE, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_SPI_SOCKET_CREATE, UCS_OP_RESULT), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_SPI_SOCKET_CREATE, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_USB_PORT_CREATE, UCS_OP_RESULT), Inic_UsbPortCreate_Result }, - { DEC_FKTOP(INIC_FID_USB_PORT_CREATE, UCS_OP_ERROR), Inic_UsbPortCreate_Error }, - { DEC_FKTOP(INIC_FID_USB_SOCKET_CREATE, UCS_OP_RESULT), Inic_UsbSocketCreate_Result }, - { DEC_FKTOP(INIC_FID_USB_SOCKET_CREATE, UCS_OP_ERROR), Inic_UsbSocketCreate_Error }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_CONFIG, UCS_OP_STATUS), Inic_StreamPortConfig_Status }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_CONFIG, UCS_OP_ERROR), Inic_StreamPortConfig_Error }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_CREATE, UCS_OP_RESULT), Inic_StreamPortCreate_Result }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_CREATE, UCS_OP_ERROR), Inic_StreamPortCreate_Error }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_LOOPBACK, UCS_OP_STATUS), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_STREAM_PORT_LOOPBACK, UCS_OP_ERROR), Inic_DummyHandler }, - { DEC_FKTOP(INIC_FID_STREAM_SOCKET_CREATE, UCS_OP_RESULT), Inic_StreamSocketCreate_Result }, - { DEC_FKTOP(INIC_FID_STREAM_SOCKET_CREATE, UCS_OP_ERROR), Inic_StreamSocketCreate_Error }, - { DEC_FKTOP(INIC_FID_RMCK_PORT_CREATE, UCS_OP_RESULT), Inic_RmckPortCreate_Result }, - { DEC_FKTOP(INIC_FID_RMCK_PORT_CREATE, UCS_OP_ERROR), Inic_RmckPortCreate_Error }, - { DEC_FKTOP(INIC_FID_I2C_PORT_CREATE, UCS_OP_RESULT), Inic_I2cPortCreate_Result }, - { DEC_FKTOP(INIC_FID_I2C_PORT_CREATE, UCS_OP_ERROR), Inic_I2cPortCreate_Error }, - { DEC_FKTOP(INIC_FID_I2C_PORT_READ, UCS_OP_RESULT), Inic_I2cPortRead_Result }, - { DEC_FKTOP(INIC_FID_I2C_PORT_READ, UCS_OP_ERROR), Inic_I2cPortRead_Error }, - { DEC_FKTOP(INIC_FID_I2C_PORT_WRITE, UCS_OP_RESULT), Inic_I2cPortWrite_Result }, - { DEC_FKTOP(INIC_FID_I2C_PORT_WRITE, UCS_OP_ERROR), Inic_I2cPortWrite_Error }, - { DEC_FKTOP(INIC_FID_PCI_PORT_CREATE, UCS_OP_RESULT), Inic_PciPortCreate_Result }, - { DEC_FKTOP(INIC_FID_PCI_PORT_CREATE, UCS_OP_ERROR), Inic_PciPortCreate_Error }, - { DEC_FKTOP(INIC_FID_PCI_SOCKET_CREATE, UCS_OP_RESULT), Inic_PciSocketCreate_Result }, - { DEC_FKTOP(INIC_FID_PCI_SOCKET_CREATE, UCS_OP_ERROR), Inic_PciSocketCreate_Error }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_CREATE, UCS_OP_RESULT), Inic_GpioPortCreate_Result }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_CREATE, UCS_OP_ERROR), Inic_GpioPortCreate_Error }, - { DEC_FKTOP(INIC_FID_MOST_PORT_ENABLE, UCS_OP_RESULT), Inic_MostPortEnable_Result }, - { DEC_FKTOP(INIC_FID_MOST_PORT_ENABLE, UCS_OP_ERROR), Inic_MostPortEnable_Error }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_PIN_MODE, UCS_OP_STATUS), Inic_GpioPortPinMode_Status }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_PIN_MODE, UCS_OP_ERROR), Inic_GpioPortPinMode_Error }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_PIN_STATE, UCS_OP_STATUS), Inic_GpioPortPinState_Status }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_PIN_STATE, UCS_OP_ERROR), Inic_GpioPortPinState_Error }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_TRIGGER_EVENT, UCS_OP_STATUS), Inic_GpioPortTrigger_Status }, - { DEC_FKTOP(INIC_FID_GPIO_PORT_TRIGGER_EVENT, UCS_OP_ERROR), Inic_GpioPortTrigger_Error }, - { DEC_FKTOP(INIC_FID_RESOURCE_DESTROY, UCS_OP_RESULT), Inic_ResourceDestroy_Result }, - { DEC_FKTOP(INIC_FID_RESOURCE_DESTROY, UCS_OP_ERROR), Inic_ResourceDestroy_Error }, - { DEC_FKTOP(INIC_FID_RESOURCE_INVALID_LIST, UCS_OP_STATUS), Inic_ResourceInvalidList_Status }, - { DEC_FKTOP(INIC_FID_RESOURCE_INVALID_LIST, UCS_OP_ERROR), Inic_ResourceInvalidList_Error }, - { DEC_FKTOP(INIC_FID_RESOURCE_MONITOR, UCS_OP_STATUS), Inic_ResourceMonitor_Status }, - { DEC_FKTOP(INIC_FID_RESOURCE_MONITOR, UCS_OP_ERROR), Inic_ResourceMonitor_Error }, -/* { DEC_FKTOP(INIC_FID_PACKET_ATTACH_SOCKETS, UCS_OP_RESULT), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_PACKET_ATTACH_SOCKETS, UCS_OP_ERROR), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_PACKET_DETACH_SOCKETS, UCS_OP_RESULT), Inic_DummyHandler }, */ -/* { DEC_FKTOP(INIC_FID_PACKET_DETACH_SOCKETS, UCS_OP_ERROR), Inic_DummyHandler }, */ - { DEC_FKTOP(INIC_FID_QOS_CREATE, UCS_OP_RESULT), Inic_QoSCreate_Result }, - { DEC_FKTOP(INIC_FID_QOS_CREATE, UCS_OP_ERROR), Inic_QoSCreate_Error }, - { DEC_FKTOP(INIC_FID_AVP_CREATE, UCS_OP_RESULT), Inic_AvpCreate_Result }, - { DEC_FKTOP(INIC_FID_AVP_CREATE, UCS_OP_ERROR), Inic_AvpCreate_Error }, - { DEC_FKTOP(INIC_FID_SYNC_CREATE, UCS_OP_RESULT), Inic_SyncCreate_Result }, - { DEC_FKTOP(INIC_FID_SYNC_CREATE, UCS_OP_ERROR), Inic_SyncCreate_Error }, - { DEC_FKTOP(INIC_FID_SYNC_MUTE, UCS_OP_RESULT), Inic_SyncMute_Result }, - { DEC_FKTOP(INIC_FID_SYNC_MUTE, UCS_OP_ERROR), Inic_SyncMute_Error }, - { DEC_FKTOP(INIC_FID_SYNC_DEMUTE, UCS_OP_RESULT), Inic_SyncDemute_Result }, - { DEC_FKTOP(INIC_FID_SYNC_DEMUTE, UCS_OP_ERROR), Inic_SyncDemute_Error }, - { DEC_FKTOP(INIC_FID_DFIPHASE_CREATE, UCS_OP_RESULT), Inic_DfiPhaseCreate_Result }, - { DEC_FKTOP(INIC_FID_DFIPHASE_CREATE, UCS_OP_ERROR), Inic_DfiPhaseCreate_Error }, - { DEC_FKTOP(INIC_FID_IPC_CREATE, UCS_OP_RESULT), Inic_IpcCreate_Result }, - { DEC_FKTOP(INIC_FID_IPC_CREATE, UCS_OP_ERROR), Inic_IpcCreate_Error }, - { DEC_FKTOP(INIC_FID_COMBINER_CREATE, UCS_OP_RESULT), Inic_CombinerCreate_Result }, - { DEC_FKTOP(INIC_FID_COMBINER_CREATE, UCS_OP_ERROR), Inic_CombinerCreate_Error }, - { DEC_FKTOP(INIC_FID_SPLITTER_CREATE, UCS_OP_RESULT), Inic_SplitterCreate_Result }, - { DEC_FKTOP(INIC_FID_SPLITTER_CREATE, UCS_OP_ERROR), Inic_SplitterCreate_Error }, - { DEC_FKTOP_TERMINATION, NULL } -}; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal definitions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Bitmask for API method Inic_NwForceNotAvailable() used by API locking manager */ -#define INIC_API_NW_FORCE_NA 0x01U -/*! \brief Bitmask for API method Inic_NwShutdown() used by API locking manager */ -#define INIC_API_NW_SHUTDOWN 0x02U -/*! \brief Bitmask for API method Inic_NwFrameCounter_Get() used by API locking manager */ -#define INIC_API_NW_FRAME_COUNTER 0x04U -/*! \brief Bitmask for API method Inic_NwTriggerRbd() used by API locking manager */ -#define INIC_API_NW_TRIGGER_RBD 0x08U -/*! \brief Bitmask for API method Inic_NwRbdResult_Get() used by API locking manager */ -#define INIC_API_NW_RBD_RESULT 0x10U -/*! \brief Bitmask for API method Inic_DeviceVersion_Get() used by API locking manager */ -#define INIC_API_DEVICE_VERSION_GET 0x20U - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Inic_HandleInternalErrors(void *self, void *error_code_ptr); -static void Inic_HandleApiTimeout(void *self, void *method_mask_ptr); -static void Inic_DecodeIcm(CInic *self, Msg_MostTel_t *msg_ptr); -static void Inic_MsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CInic. - * \param self Reference to CInic instance - * \param init_ptr Reference to initialization data - */ -void Inic_Ctor(CInic *self, Inic_InitData_t *init_ptr) -{ - uint8_t i; - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->base_ptr = init_ptr->base_ptr; - self->xcvr_ptr = init_ptr->xcvr_ptr; - self->fkt_op_list_ptr = &inic_handler[0]; - self->target_address = init_ptr->tgt_addr; - - /* create instances of single-observers */ - for(i=0U; i<INIC_NUM_SSUB; i++) - { - Ssub_Ctor(&self->ssubs[i], self->base_ptr->ucs_user_ptr); - } - - /* create instances of "normal" observers */ - for(i=0U; i<INIC_NUM_SUB; i++) - { - Sub_Ctor(&self->subs[i], self->base_ptr->ucs_user_ptr); - } - - /* Observe internal errors and events */ - Mobs_Ctor(&self->internal_error_obs, self, EH_M_TERMINATION_EVENTS, &Inic_HandleInternalErrors); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->internal_error_obs); - - /* Initialize API locking mechanism */ - Sobs_Ctor(&self->lock.observer, self, &Inic_HandleApiTimeout); - Al_Ctor(&self->lock.api, &self->lock.observer, self->base_ptr->ucs_user_ptr); - Alm_RegisterApi(&self->base_ptr->alm, &self->lock.api); - - /* Initialize Resource Management part */ - Inic_InitResourceManagement(self); -} - -/*! \brief Handles internal errors and events - * \param self Instance pointer - * \param error_code_ptr Reference to reported error code - */ -static void Inic_HandleInternalErrors(void *self, void *error_code_ptr) -{ - uint8_t i; - Inic_StdResult_t res_data; - CInic *self_ = (CInic *)self; - MISC_UNUSED(error_code_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_ERR_SYSTEM; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - - /* Internal error has been occurred => Cancel running jobs */ - for(i=0U; i<INIC_NUM_SSUB; i++) - { - Ssub_Notify(&self_->ssubs[i], &res_data, true); - } -} - -/*! \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 Inic_HandleApiTimeout(void *self, void *method_mask_ptr) -{ - CInic *self_ = (CInic *)self; - Alm_ModuleMask_t method_mask = *((Alm_ModuleMask_t *)method_mask_ptr); - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_ERR_TIMEOUT; - res_data.result.info_ptr = NULL; - - switch(method_mask) - { - case INIC_API_NW_SHUTDOWN: - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SHUTDOWN], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC]", "API locking timeout occurred for method Inic_NwShutdown().", 0U)); - break; - case INIC_API_NW_FRAME_COUNTER: - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_FRAME_COUNTER], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC]", "API locking timeout occurred for method Inic_NwFrameCounter_Get().", 0U)); - break; - case INIC_API_NW_TRIGGER_RBD: - self_->lock.rbd_trigger_timeout_counter++; - if(self_->lock.rbd_trigger_timeout_counter < 5U) - { - (void)Al_Lock(&self_->lock.api, INIC_API_NW_TRIGGER_RBD); - } - else - { - Inic_StdResult_t rbd_result_data; - Ucs_StdResult_t result = {UCS_RES_ERR_TIMEOUT, NULL, 0U}; - rbd_result_data.data_info = NULL; - rbd_result_data.result = result; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_TRIGGER_RBD], &rbd_result_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC]", "API locking timeout occurred for method Inic_NwTriggerRbd().", 0U)); - } - break; - case INIC_API_NW_RBD_RESULT: - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_RBD_RESULT], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC]", "API locking timeout occurred for method Inic_NwRbdResult_Get().", 0U)); - break; - default: - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC]", "Unknown API locking bitmask detected. Mask: 0x%02X", 1U, method_mask)); - break; - } -} - -/*! \brief Decode an ICM message - * \param self Instance pointer to FBlock INIC - * \param msg_ptr pointer to the ICM message to decode - */ -static void Inic_DecodeIcm(CInic *self, Msg_MostTel_t *msg_ptr) -{ - Dec_Return_t result; - uint16_t index; - - result = Dec_SearchFktOpIcm(self->fkt_op_list_ptr, &index, msg_ptr->id.function_id, msg_ptr->id.op_type); - - if (result == DEC_RET_SUCCESS) - { - self->fkt_op_list_ptr[index].handler_function_ptr(self, msg_ptr); - } - else - { - TR_ERROR((self->base_ptr->ucs_user_ptr, "[INIC]", "Unknown ICM received. FBlockId: 0x%02X, InstId: 0x%02X, FktId: 0x%04X, OPType: 0x%02X", 4U, msg_ptr->id.fblock_id, msg_ptr->id.instance_id, msg_ptr->id.function_id, msg_ptr->id.op_type)); - } -} - -/*! \brief Receives ICMs - * \param self reference to INIC object - * \param tel_ptr received message - */ -void Inic_OnIcmRx(void *self, Msg_MostTel_t *tel_ptr) -{ - CInic *self_ = (CInic *)self; - - if ((tel_ptr->source_addr == MSG_ADDR_INIC) && (tel_ptr->destination_addr == MSG_ADDR_EHC_CFG)) - { - Inic_DecodeIcm(self_, tel_ptr); - } - - Trcv_RxReleaseMsg(self_->xcvr_ptr, tel_ptr); /* free Rx telegram */ -} - -/*! \brief Filters RCM Rx messages - * \details The filter function shall not release the message object - * \param self Reference to INIC object - * \param tel_ptr Reference to the RCM Rx message object - */ -void Inic_OnRcmRxFilter(void *self, Msg_MostTel_t *tel_ptr) -{ - uint16_t index; - CInic *self_ = (CInic *)self; - - if (Dec_SearchFktOpIcm(self_->fkt_op_list_ptr, &index, tel_ptr->id.function_id, tel_ptr->id.op_type) == DEC_RET_SUCCESS) - { - self_->fkt_op_list_ptr[index].handler_function_ptr(self, tel_ptr); - } -} - -/*! \brief Handle message Tx status and free message objects - * \param self The instance - * \param tel_ptr Reference to transmitted message - * \param status Status of the transmitted message - */ -static void Inic_MsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status) -{ - CInic *self_ = (CInic *)self; - - if ((status != UCS_MSG_STAT_OK) && (tel_ptr->info_ptr != NULL)) - { - Inic_StdResult_t res_data; - CSingleSubject *ssub_ptr = (CSingleSubject *)tel_ptr->info_ptr; - - res_data.data_info = &status; - res_data.result.code = UCS_RES_ERR_TRANSMISSION; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - Ssub_Notify(ssub_ptr, &res_data, true); - } - Trcv_TxReleaseMsg(tel_ptr); - - /* ICM messages pending? */ - if (Sub_GetNumObservers(&self_->subs[INIC_SUB_TX_MSG_OBJ_AVAIL]) > 0U) - { - Sub_Notify(&self_->subs[INIC_SUB_TX_MSG_OBJ_AVAIL], NULL); - } -} - -/*! \brief Add an observer to be notified when a tx message object is available - * \param self instance of CInic - * \param obs_ptr pointer to observer to be informed - */ -void Inic_AddObsrvOnTxMsgObjAvail(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_TX_MSG_OBJ_AVAIL], obs_ptr); -} - -/*! \brief Delete an observer set by Inic_AddObsrvOnTxMsgObjAvail() - * \param self instance of CInic - * \param obs_ptr pointer to observer to be removed - */ -void Inic_DelObsrvOnTxMsgObjAvail(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_TX_MSG_OBJ_AVAIL], obs_ptr); -} - -/*! \brief Add an observer to the NetworkStatus subject - * \param self instance of CInic - * \param obs_ptr pointer to observer to be informed - */ -void Inic_AddObsrvNwStatus(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_NW_STATUS], obs_ptr); -} - -/*! \brief Delete an observer to the NetworkStatus subject - * \param self instance of CInic - * \param obs_ptr pointer to observer to be removed - */ -void Inic_DelObsrvNwStatus(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_NW_STATUS], obs_ptr); -} - -/*! \brief Add an observer to the NetworkConfiguration subject - * \param self instance of CInic - * \param obs_ptr pointer to observer to be informed - */ -void Inic_AddObsvrNwConfig(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_NW_CONFIG], obs_ptr); -} - -/*! \brief Delete an observer to the NetworkConfiguration subject - * \param self instance of CInic - * \param obs_ptr pointer to observer to be removed - */ -void Inic_DelObsvrNwConfig(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_NW_CONFIG], obs_ptr); -} - -/*! \brief Add an observer to the DeviceStatus subject - * \details The provided data points to a \ref Inic_DeviceStatus_t structure - * \param self instance of CInic - * \param obs_ptr pointer to observer to be informed - */ -void Inic_AddObsvrDeviceStatus(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_DEVICE_STATUS], obs_ptr); -} - -/*! \brief Delete an observer to the DeviceStatus subject - * \param self instance of CInic - * \param obs_ptr pointer to observer to be removed - */ -void Inic_DelObsvrDeviceStatus(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_DEVICE_STATUS], obs_ptr); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Internal API */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief This method requests the INIC version info - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_DeviceVersion_Get(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, INIC_API_DEVICE_VERSION_GET) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_DEVICE_VERSION; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_DEVICE_VERSION]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_DEVICE_VERSION], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_DEVICE_VERSION_GET); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Attach EHC to the INIC - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_DeviceAttach(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_DEVICE_ATTACH; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_DEVICE_ATTACH]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_DEVICE_ATTACH], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Attaches the given PMS channel to the network - * \param self Reference to CInic instance - * \param pmp_channel_handle Port message channel resource handle - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_NwAttach(CInic *self, - uint16_t pmp_channel_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_ATTACH; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(pmp_channel_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(pmp_channel_handle); - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_ATTACH]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_ATTACH], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief Starts the System diagnosis - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_NwSysDiagnosis(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_SYS_DIAGNOSIS; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_SYS_DIAGNOSIS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_SYS_DIAGNOSIS], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Stops the System diagnosis - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_NwSysDiagEnd(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_SYS_DIAG_END; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_SYS_DIAGEND]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_SYS_DIAGEND], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Starts the Backchannel Diagnosis Mode - * - * \param *self Reference to CInic instance - * \param *obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_BCDiagnosis(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = MSG_ADDR_INIC; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_BACK_CHANNEL_DIAGNOSIS; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_BC_DIAGNOSIS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_BC_DIAGNOSIS], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Stops the Backchannel Diagnosis Mode - * - * \param *self Reference to CInic instance - * \param *obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_BCDiagEnd(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = MSG_ADDR_INIC; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_BACK_CHANNEL_DIAG_END; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_BC_DIAG_END]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_BC_DIAG_END], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - - -/*! \brief Requests the INIC.MOSTNetworRBDResult.Status message - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwRbdResult_Get(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, INIC_API_NW_RBD_RESULT) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_RBD_RESULT; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_RBD_RESULT]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_RBD_RESULT], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_NW_RBD_RESULT); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - -/*! \brief This functions starts up the MOST network. - * \param self Reference to CInic instance - * \param auto_forced_na The delay time to shutdown the network after INIC has entered the - * protected mode. - * \param packet_bandwidth The desired packed bandwidth - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwStartup(CInic *self, uint16_t auto_forced_na, - uint16_t packet_bandwidth, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if (self->startup_locked == false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - self->startup_locked = true; - - msg_ptr->destination_addr = self->target_address; - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_STARTUP; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(auto_forced_na); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(auto_forced_na); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(packet_bandwidth); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(packet_bandwidth); - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_STARTUP]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_STARTUP], obs_ptr); - } - else - { - self->startup_locked = false; - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function shuts down the entire MOST network. - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwShutdown(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, INIC_API_NW_SHUTDOWN) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_SHUTDOWN; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_SHUTDOWN]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_SHUTDOWN], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_NW_SHUTDOWN); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function triggers the Ring Break Diagnosis. - * \param self Reference to CInic instance - * \param type Specifies if the INIC starts the RBD as a TimingMaster or TimingSlave. - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwTriggerRbd(CInic *self, Ucs_Diag_RbdType_t type, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, INIC_API_NW_TRIGGER_RBD) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - self->lock.rbd_trigger_timeout_counter = 0U; - - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_TRIGGER_RBD; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)type; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_TRIGGER_RBD]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_TRIGGER_RBD], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_NW_TRIGGER_RBD); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function triggers the INIC to force the NotAvailable state - * \param self Reference to CInic instance - * \param force Is \c true if the INIC shall force the network in NotAvailable state. - * If \c false the INIC shall no no longer force the network to NotAvailable state. - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwForceNotAvailable(CInic *self, bool force, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if (Al_Lock(&self->lock.api, INIC_API_NW_FORCE_NA) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_FORCE_NO_AVAIL; - msg_ptr->id.op_type = UCS_OP_SETGET; - - if (force == false) - { - msg_ptr->tel.tel_data_ptr[0] = 0U; - } - else - { - msg_ptr->tel.tel_data_ptr[0] = 1U; - } - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_FORCE_NA]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_FORCE_NA], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_NW_FORCE_NA); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function modifies the INIC network configuration. - * \param self Reference to CInic instance - * \param mask Allows to change a single, multiple, or all parameters - * \param config Holds the parameter values - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_NwConfig_SetGet(CInic *self, uint16_t mask, Inic_NetworkConfig_t config, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 24U); - - if (msg_ptr != NULL) - { - mask = mask & 7U; /* allow only bit 0..2 */ - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_CFG; - msg_ptr->id.op_type = UCS_OP_SETGET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(mask); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(mask); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(config.node_address); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(config.node_address); - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(config.group_address); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(config.group_address); - msg_ptr->tel.tel_data_ptr[6] = config.llrbc; - MISC_MEM_SET(&msg_ptr->tel.tel_data_ptr[7], 0, 17U); - - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_CONFIG], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Requests the INIC.NetworkConfiguration.Status message - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_NwConfig_Get(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_CFG; - msg_ptr->id.op_type = UCS_OP_GET; - - Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_CONFIG], obs_ptr); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Requests the INIC.MOSTNetworkFrameCounter.Status message - * \param self Reference to CInic instance - * \param reference Reference counter value - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_NwFrameCounter_Get(CInic *self, uint32_t reference, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.api, INIC_API_NW_FRAME_COUNTER) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_NW_FRAME_COUNTER; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)(reference >> 24); - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)(reference >> 16); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)(reference >> 8); - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)reference; - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NW_FRAME_COUNTER]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_MsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NW_FRAME_COUNTER], obs_ptr); - } - else - { - Al_Release(&self->lock.api, INIC_API_NW_FRAME_COUNTER); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - - - - - -/*------------------------------------------------------------------------------------------------*/ -/* Handler functions */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Dummy handler function for unused INIC functions - * - * \param self instance of CInic - * \param msg_ptr Pointer to received message - */ -void Inic_DummyHandler(void *self, Msg_MostTel_t *msg_ptr) -{ - MISC_UNUSED(self); - MISC_UNUSED(msg_ptr); -} - -/*! \brief Handler function for INIC.DeviceStatus.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_DeviceStatus_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - - if (msg_ptr->tel.tel_len > 0U) - { - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[INIC]", (msg_ptr->tel.tel_len == 5U)); - self_->device_status.config_iface_state= (Inic_AttachState_t)msg_ptr->tel.tel_data_ptr[0]; - self_->device_status.app_iface_state = (Inic_AttachState_t)msg_ptr->tel.tel_data_ptr[1]; - self_->device_status.power_state = (Ucs_Inic_PowerState_t)msg_ptr->tel.tel_data_ptr[2]; - self_->device_status.bist = (Inic_Bist_t)msg_ptr->tel.tel_data_ptr[3]; - self_->device_status.last_reset_reason = (Ucs_Inic_LastResetReason_t)msg_ptr->tel.tel_data_ptr[4]; - - /* INIC BIST error detected */ - if (self_->device_status.bist == INIC_BIST_ERROR) - { - Eh_ReportEvent(&self_->base_ptr->eh, EH_E_BIST_FAILED); - } - - Sub_Notify(&self_->subs[INIC_SUB_DEVICE_STATUS], &self_->device_status); - } -} - -/*! \brief Handler function for INIC.DeviceVersion.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_DeviceVersion_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - MISC_DECODE_DWORD(&(self_->device_version.product_identifier), &(msg_ptr->tel.tel_data_ptr[0])); - self_->device_version.major_version = msg_ptr->tel.tel_data_ptr[4]; - self_->device_version.minor_version = msg_ptr->tel.tel_data_ptr[5]; - self_->device_version.release_version = msg_ptr->tel.tel_data_ptr[6]; - MISC_DECODE_DWORD(&(self_->device_version.build_version), &(msg_ptr->tel.tel_data_ptr[7])); - self_->device_version.hw_revision = msg_ptr->tel.tel_data_ptr[11]; - MISC_DECODE_WORD(&(self_->device_version.diagnosis_id), &(msg_ptr->tel.tel_data_ptr[12])); - - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[INIC]", (msg_ptr->tel.tel_data_ptr[14] == 0x01U)); /* ExtIdentifier == CFGS ? */ - - self_->device_version.cs_major_version = msg_ptr->tel.tel_data_ptr[15]; - self_->device_version.cs_minor_version = msg_ptr->tel.tel_data_ptr[16]; - self_->device_version.cs_release_version = msg_ptr->tel.tel_data_ptr[17]; - - - res_data.data_info = &self_->device_version; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_VERSION], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_DEVICE_VERSION_GET); -} - -/*! \brief Handler function for INIC.DeviceVersion.Error - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_DeviceVersion_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_VERSION], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_DEVICE_VERSION_GET); -} - -/*! \brief Handler function for INIC.NetworkStatus.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwStatus_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = &self_->network_status; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[INIC]", (msg_ptr->tel.tel_len == 11U)); - MISC_DECODE_WORD(&(self_->network_status.events), &(msg_ptr->tel.tel_data_ptr[0])); - self_->network_status.availability = (Ucs_Network_Availability_t)msg_ptr->tel.tel_data_ptr[2]; - self_->network_status.avail_info = (Ucs_Network_AvailInfo_t)msg_ptr->tel.tel_data_ptr[3]; - self_->network_status.avail_trans_cause = (Ucs_Network_AvailTransCause_t)msg_ptr->tel.tel_data_ptr[4]; - MISC_DECODE_WORD(&(self_->network_status.node_address), &(msg_ptr->tel.tel_data_ptr[5])); - self_->network_status.node_position = msg_ptr->tel.tel_data_ptr[7]; - self_->network_status.max_position = msg_ptr->tel.tel_data_ptr[8]; - MISC_DECODE_WORD(&(self_->network_status.packet_bw), &(msg_ptr->tel.tel_data_ptr[9])); - - Sub_Notify(&self_->subs[INIC_SUB_NW_STATUS], &res_data); - } -} - -/*! \brief Handler function for INIC.NetworkConfiguration.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwConfig_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 4U) - { - res_data.data_info = &self_->network_config; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&(self_->network_config.node_address), &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_WORD(&(self_->network_config.group_address), &(msg_ptr->tel.tel_data_ptr[2])); - self_->network_config.llrbc = msg_ptr->tel.tel_data_ptr[4]; - - Sub_Notify(&self_->subs[INIC_SUB_NW_CONFIG], &res_data); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_CONFIG], &res_data, true); - } -} - -/*! \brief Handler function for INIC.NetworkConfiguration.Error - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwConfig_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_CONFIG], &res_data, true); - } -} - -/*! \brief Handler function for INIC.MOSTNetworkFrameCounter.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwFrameCounter_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - Inic_FrameCounterStatus_t frame_counter_status; - - if (msg_ptr->tel.tel_len > 0U) - { - MISC_DECODE_DWORD(&frame_counter_status.reference, &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_DWORD(&frame_counter_status.frame_counter, &(msg_ptr->tel.tel_data_ptr[4])); - frame_counter_status.lock = msg_ptr->tel.tel_data_ptr[8]; - res_data.data_info = &frame_counter_status; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_FRAME_COUNTER], &res_data, true); /* provides pointer to Inic_StdResult_t structure */ - } - Al_Release(&self_->lock.api, INIC_SSUB_NW_FRAME_COUNTER); -} - -/*! \brief Handler function for INIC.MOSTNetworkFrameCounter.Error - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwFrameCounter_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_FRAME_COUNTER], &res_data, true); /* provides pointer to Inic_StdResult_t structure */ - } - Al_Release(&self_->lock.api, INIC_SSUB_NW_FRAME_COUNTER); -} - -/*! \brief Handler function for INIC.MOSTNetworkStartup.ErrorAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwStartup_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - self_->startup_locked = false; - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_STARTUP], &res_data, true); -} - -/*! \brief Handler function for INIC.MOSTNetworkStartup.ResultAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwStartup_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - self_->startup_locked = false; - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_STARTUP], &res_data, true); -} - -/*! \brief Handler function for INIC.MOSTNetworkShutdown.ErrorAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwShutdown_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SHUTDOWN], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_NW_SHUTDOWN); -} - -/*! \brief Handler function for INIC.MOSTNetworkShutdown.ResultAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwShutdown_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SHUTDOWN], &res_data, true); - Al_Release(&self_->lock.api, INIC_API_NW_SHUTDOWN); -} - -/*! \brief Handler function for INIC.MOSTNetworkTriggerRBD.ErrorAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwTriggerRbd_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_TRIGGER_RBD], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_NW_TRIGGER_RBD); -} - -/*! \brief Handler function for INIC.MOSTNetworkTriggerRBD.ResultAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwTriggerRbd_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_TRIGGER_RBD], &res_data, true); - Al_Release(&self_->lock.api, INIC_API_NW_TRIGGER_RBD); -} - -/*! \brief Handler function for INIC.MOSTNetworkForceNotAvailable.ErrorAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwForceNotAvailable_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_FORCE_NA], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_NW_FORCE_NA); -} - -/*! \brief Handler function for INIC.MOSTNetworkForceNotAvailable.ResultAck - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_NwForceNotAvailable_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_FORCE_NA], &res_data, true); - Al_Release(&self_->lock.api, INIC_API_NW_FORCE_NA); -} - -/*! \brief Handler function for INIC.DeviceAttach.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DeviceAttach_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_ATTACH], &res_data, true); - } -} - -/*! \brief Handler function for INIC.DeviceAttach.Result - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DeviceAttach_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_ATTACH], &res_data, true); -} - -/*! \brief Handler function for INIC.NetworkAttach.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwAttach_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_ATTACH], &res_data, true); - } -} - -/*! \brief Handler function for INIC.NetworkAttach.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwAttach_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_ATTACH], &res_data, true); -} - - - - -/*! \brief Handler function for INIC.MOSTNetworkSystemDiagnosis.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwSysDiagnosis_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SYS_DIAGNOSIS], &res_data, true); - } -} - -/*! \brief Handler function for INIC.MOSTNetworkSystemDiagnosis.Result - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwSysDiagnosis_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SYS_DIAGNOSIS], &res_data, true); -} - -/*! \brief Handler function for INIC.MOSTNetworkSystemDiagnosisEnd.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwSysDiagEnd_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SYS_DIAGEND], &res_data, true); - } -} - -/*! \brief Handler function for INIC.MOSTNetworkSystemDiagnosisEnd.Result - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwSysDiagEnd_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_SYS_DIAGEND], &res_data, true); -} - - - -/*! \brief Handler function for INIC.BCDiag.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_BCDiagnosis_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_BC_DIAGNOSIS], &res_data, true); -} - -/*! \brief Handler function for INIC.BCDiag.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_BCDiagnosis_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_BC_DIAGNOSIS], &res_data, true); -} - -/*! \brief Handler function for INIC.BCDiagEnd.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_BCDiagEnd_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_BC_DIAG_END], &res_data, true); -} - -/*! \brief Handler function for INIC.BCDiagEnd.Result - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_BCDiagEnd_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_BC_DIAG_END], &res_data, true); -} - - - - - -/*! \brief Handler function for INIC.MOSTNetworkRBDResult.Status - * \param self Reference to INIC object - * \param msg_ptr Received message - */ -void Inic_NwRbdResult_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_RbdResult_t rbd_result_data; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - rbd_result_data.result = (Ucs_Diag_RbdResult_t)msg_ptr->tel.tel_data_ptr[0]; - rbd_result_data.position = msg_ptr->tel.tel_data_ptr[1]; - rbd_result_data.status = msg_ptr->tel.tel_data_ptr[2]; - MISC_DECODE_WORD(&(rbd_result_data.diag_id), &(msg_ptr->tel.tel_data_ptr[3])); - res_data.data_info = &rbd_result_data; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_RBD_RESULT], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_NW_RBD_RESULT); -} - -/*! \brief Handler function for INIC.MOSTNetworkRBDResult.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_NwRbdResult_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - if (msg_ptr->tel.tel_len > 0U) - { - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NW_RBD_RESULT], &res_data, true); - } - Al_Release(&self_->lock.api, INIC_API_NW_RBD_RESULT); -} - - - - -/*------------------------------------------------------------------------------------------------*/ -/* Helper functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Translates INIC error codes into UNICENS error codes and wraps the raw INIC - * error data to a byte stream. - * \param self Instance of CInic - * \param error_data[] INIC error data - * \param error_size Size of INIC error data in bytes - * \return The formatted error - */ -Ucs_StdResult_t Inic_TranslateError(CInic *self, uint8_t error_data[], uint8_t error_size) -{ - Ucs_StdResult_t ret_val; - MISC_UNUSED(self); - - if(error_data[0] != 0x20U) - { - ret_val.code = UCS_RES_ERR_MOST_STANDARD; - } - else - { - ret_val.code = (Ucs_Result_t)(error_data[1] + 1U); - } - - ret_val.info_ptr = &error_data[0]; - ret_val.info_size = error_size; - - return ret_val; -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Synchronous Getters */ -/*------------------------------------------------------------------------------------------------*/ -uint16_t Inic_GetGroupAddress(CInic *self) -{ - return self->network_config.group_address; -} - -uint16_t Inic_GetPacketDataBandwidth(CInic *self) -{ - return self->network_status.packet_bw; -} - -uint16_t Inic_GetNodeAddress(CInic *self) -{ - return self->network_status.node_address; -} - -uint8_t Inic_GetNodePosition(CInic *self) -{ - return self->network_status.node_position; -} - -uint8_t Inic_GetNumberOfNodes(CInic *self) -{ - return self->network_status.max_position; -} - -uint8_t Inic_GetInicLlrbc(CInic *self) -{ - return self->network_config.llrbc; -} - -Ucs_Inic_Version_t Inic_GetDeviceVersion(CInic *self) -{ - return self->device_version; -} - -Ucs_Inic_LastResetReason_t Inic_GetLastResetReason(CInic *self) -{ - return self->device_status.last_reset_reason; -} - -Ucs_Inic_PowerState_t Inic_GetDevicePowerState(CInic *self) -{ - return self->device_status.power_state; -} - -Ucs_Network_Availability_t Inic_GetAvailability(CInic *self) -{ - return self->network_status.availability; -} - -uint16_t Inic_GetTargetAddress (CInic *self) -{ - return self->target_address; -} - -/*! - * @} - * \endcond - */ -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_inic_res.c b/ucs2-lib/src/ucs_inic_res.c deleted file mode 100644 index b9ab104..0000000 --- a/ucs2-lib/src/ucs_inic_res.c +++ /dev/null @@ -1,3735 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 FBlock INIC (resource management parts of INIC management) - * \details Contains the resource management parts of INIC management - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_INIC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_misc.h" -#include "ucs_ret_pb.h" -#include "ucs_inic.h" -#include "ucs_base.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal macros */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief API locking Bitmask for all INIC create methods. */ -#define INIC_API_CREATE_CLASS 0x0001U -/*! \brief API locking Bitmask of method Inic_ResourceDestroy(). */ -#define INIC_API_RESOURCE_DESTROY 0x0002U -/*! \brief API locking Bitmask of method Inic_ResourceInvalidList_Get(). */ -#define INIC_API_RESOURCE_INVAL_LIST 0x0004U -/*! \brief API locking Bitmask of method Inic_Notification_Set(). */ -#define INIC_API_NOTIFICATION 0x0008U -/*! \brief API locking Bitmask of method Inic_StreamPortConfig_Get(). */ -#define INIC_API_STREAM_PORT_CONFIG 0x0010U -/*! \brief API locking Bitmask of method Inic_SyncMute(). */ -#define INIC_API_SYNC_MUTE 0x0020U -/*! \brief API locking Bitmask of method Inic_SyncDemute(). */ -#define INIC_API_SYNC_DEMUTE 0x0040U -/*! \brief API locking Bitmask of method Inic_MostPortEnable(). */ -#define INIC_API_MOST_PORT_ENABLE 0x0080U -/*! \brief API locking Bitmask of method Inic_MostPortEnFullStr(). */ -#define INIC_API_MOST_PORT_EN_FULL_STR 0x0100U -/*! \brief API locking Bitmask of method Inic_GpioPortPinMode_SetGet(). */ -#define INIC_API_GPIO_PIN_MODE 0x0200U -/*! \brief API locking Bitmask of method Inic_GpioPortPinState_SetGet(). */ -#define INIC_API_GPIO_PIN_STATE 0x0400U -/*! \brief API locking Bitmask of methods Inic_I2cPortRead_StartResultAck() and Inic_I2cPortWrite_StartResultAck(). */ -#define INIC_API_I2C_PORT_WR 0x0800U -/*! \brief Bitmask for API method Inic_DeviceSync() used by API locking manager */ -#define INIC_API_DEVICE_SYNC 0x1000U - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Inic_HandleResApiTimeout(void *self, void *method_mask_ptr); -static void Inic_ResMsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initialization function of the INIC Resource Management part. Called by Inic_Ctor(). - * \param self Instance pointer - */ -void Inic_InitResourceManagement(CInic *self) -{ - Sobs_Ctor(&self->lock.res_observer, self, &Inic_HandleResApiTimeout); - Al_Ctor(&self->lock.res_api, &self->lock.res_observer, self->base_ptr->ucs_user_ptr); - Alm_RegisterApi(&self->base_ptr->alm, &self->lock.res_api); - - /* initializes the gpio report time status */ - self->gpio_rt_status.first_report = true; -} - -/*! \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 Inic_HandleResApiTimeout(void *self, void *method_mask_ptr) -{ - CInic *self_ = (CInic *)self; - Alm_ModuleMask_t method_mask = *((Alm_ModuleMask_t *)method_mask_ptr); - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_ERR_TIMEOUT; - res_data.result.info_ptr = NULL; - - switch(method_mask) - { - case INIC_API_CREATE_CLASS: - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for INIC create method.", 0U)); - break; - case INIC_API_RESOURCE_DESTROY: - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_DESTROY], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_ResourceDestroy().", 0U)); - break; - case INIC_API_RESOURCE_INVAL_LIST: - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_ResourceInvalidList_Get().", 0U)); - break; - case INIC_API_NOTIFICATION: - Ssub_Notify(&self_->ssubs[INIC_SSUB_NOTIFICATION], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_Notification_Get().", 0U)); - break; - case INIC_API_STREAM_PORT_CONFIG: - Ssub_Notify(&self_->ssubs[INIC_SSUB_STREAM_PORT_CONFIG], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_StreamPortConfig_Get().", 0U)); - break; - case INIC_API_SYNC_MUTE: - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_MUTE], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_SyncMute().", 0U)); - break; - case INIC_API_SYNC_DEMUTE: - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_DEMUTE], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_SyncDemute().", 0U)); - break; - case INIC_API_MOST_PORT_ENABLE: - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_ENABLE], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_MostPortEnable().", 0U)); - break; - case INIC_API_MOST_PORT_EN_FULL_STR: - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_EN_FULL_STR], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_MostPortEnFullStr().", 0U)); - break; - case INIC_API_GPIO_PIN_MODE: - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_MODE], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_GpioPortPinMode_SetGet().", 0U)); - break; - case INIC_API_GPIO_PIN_STATE: - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_STATE], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_GpioPortPinState_SetGet().", 0U)); - break; - case INIC_API_DEVICE_SYNC: - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_SYNC], &res_data, true); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "API locking timeout occurred for method Inic_DeviceSync_StartResult().", 0U)); - break; - default: - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[INIC_RES]", "Unknown API locking bitmask detected. Mask: 0x%02X", 1U, method_mask)); - break; - } -} - -/*! \brief Add an observer to the ResourceMonitor subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_AddObsrvResMonitor(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_RES_MONITOR], obs_ptr); -} - -/*! \brief Delete an observer from the ResourceMonitor subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_DelObsrvResMonitor(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_RES_MONITOR], obs_ptr); -} - -/*! \brief Add an observer to the MOSTPortStatus subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_AddObsrvMostPortStatus(CInic *self, CObserver *obs_ptr) -{ - if (Sub_AddObserver(&self->subs[INIC_SUB_MOST_PORT_STATUS], obs_ptr) != SUB_UNKNOWN_OBSERVER) - { - Sub_Notify(&self->subs[INIC_SUB_MOST_PORT_STATUS], &self->most_port_status); - } -} - -/*! \brief Delete an observer from the MOSTPortStatus subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_DelObsrvMostPortStatus(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_MOST_PORT_STATUS], obs_ptr); -} - -/*! \brief Add an observer to the GpioTriggerEvent subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_AddObsrvGpioTriggerEvent(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->subs[INIC_SUB_GPIO_TRIGGER_EVENT], obs_ptr); -} - -/*! \brief Removes an observer from the GpioTriggerEvent subject - * \param self Instance of CInic - * \param obs_ptr Pointer to observer to be informed - */ -void Inic_DelObsrvGpioTriggerEvent(CInic *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->subs[INIC_SUB_GPIO_TRIGGER_EVENT], obs_ptr); -} - -/*! \brief Destroys the resources associated with the given resource handles - * \param self Reference to CInic instance - * \param res_handle_list resource handle list - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - * \return UCS_RET_ERR_PARAM Wrong length of resource handle list - */ -Ucs_Return_t Inic_ResourceDestroy(CInic *self, - Inic_ResHandleList_t res_handle_list, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - uint8_t len; - - if(Al_Lock(&self->lock.res_api, INIC_API_RESOURCE_DESTROY) != false) - { - /* sender handle + number of resource handles */ - len = 2U * res_handle_list.num_handles; - - if ((len == 0U) || ((MAX_INVALID_HANDLES_LIST << 1) < len)) - { - Al_Release(&self->lock.res_api, INIC_API_RESOURCE_DESTROY); - result = UCS_RET_ERR_PARAM; - } - else - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, len); - - if (msg_ptr != NULL) - { - uint8_t i; - - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_RESOURCE_DESTROY; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - for (i=0U; i < res_handle_list.num_handles; ++i) - { - msg_ptr->tel.tel_data_ptr[2U*i] = MISC_HB(res_handle_list.res_handles[i]); - msg_ptr->tel.tel_data_ptr[1U + (2U*i)] = MISC_LB(res_handle_list.res_handles[i]); - } - - self->ssubs[INIC_SSUB_RESOURCE_DESTROY].user_mask = INIC_API_RESOURCE_DESTROY; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_RESOURCE_DESTROY]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_RESOURCE_DESTROY], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_RESOURCE_DESTROY); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Retrieves the list of invalid resources - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer. The result must be casted into type - * Inic_StdResult_t. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_ResourceInvalidList_Get(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_RESOURCE_INVAL_LIST) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_RESOURCE_INVALID_LIST; - msg_ptr->id.op_type = UCS_OP_GET; - - self->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST].user_mask = INIC_API_RESOURCE_INVAL_LIST; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_RESOURCE_INVAL_LIST); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Resets the resource monitor back to its default state. - * \param self Reference to CInic instance - * \param control Used to reset the resource monitor - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_ResourceMonitor_Set(CInic *self, Ucs_Resource_MonitorCtrl_t control) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_RESOURCE_MONITOR; - msg_ptr->id.op_type = UCS_OP_SET; - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)control; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - - return result; -} - -/*! \brief Triggers notification of the given function_id list. - * \param self Reference to CInic instance - * \param control control command used - * \param device_id Id of the sending device (local node address). - * \param fktid_list function ids list. - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_PARAM parameter exceeds its admissible range was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_Notification_Set(CInic *self, Ucs_Inic_NotificationCtrl_t control, uint16_t device_id, Inic_FktIdList_t fktid_list) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - /* control + device_id + size of the funcids list */ - uint8_t len = 1U + 2U + (2U * fktid_list.num_fktids); - - if (len > MSG_MAX_SIZE_PAYLOAD) - { - result = UCS_RET_ERR_PARAM; - } - else - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, len); - - if (msg_ptr != NULL) - { - uint8_t i; - - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_NOTIFICATION; - msg_ptr->id.op_type = UCS_OP_SET; - - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)control; - msg_ptr->tel.tel_data_ptr[1] = MISC_HB(device_id); - msg_ptr->tel.tel_data_ptr[2] = MISC_LB(device_id); - - if ((len > 3U) && (fktid_list.fktids_ptr != NULL) ) - { - for (i=0U; i < fktid_list.num_fktids; ++i) - { - msg_ptr->tel.tel_data_ptr[3U+(2U*i)] = MISC_HB(fktid_list.fktids_ptr[i]); - msg_ptr->tel.tel_data_ptr[4U+(2U*i)] = MISC_LB(fktid_list.fktids_ptr[i]); - } - } - - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NOTIFICATION]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - } - else - { - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - - return result; -} - -/*! \brief Gets the device id that has notified the given function_id - * \param self Reference to CInic instance - * \param fktid The function id to be looked for - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_Notification_Get(CInic *self, uint16_t fktid, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_NOTIFICATION) != false) - { - Msg_MostTel_t * msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_NOTIFICATION; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(fktid); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(fktid); - - self->ssubs[INIC_SSUB_NOTIFICATION].user_mask = INIC_API_NOTIFICATION; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_NOTIFICATION]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_NOTIFICATION], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_NOTIFICATION); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a synchronous data connection. The connection can be directly associated with - * an input and output socket. - * \param self Reference to CInic instance - * \param resource_handle_in The ID number of the socket or splitter resource that is the - * starting point of the link. - * \param resource_handle_out The ID number of the socket or splitter resource that is the ending - * point of the link. - * \param default_mute specifies if the connection is muted by default - * \param mute_mode Configures how the resource monitor shall handle events that may - * the streamed data invalid. - * \param offset Denotes the offset from/to where data from/to a socket should be - * routed from/to a splitter/combiner. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_SyncCreate(CInic *self, - uint16_t resource_handle_in, - uint16_t resource_handle_out, - bool default_mute, - Ucs_Sync_MuteMode_t mute_mode, - uint16_t offset, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_SYNC_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(resource_handle_in); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(resource_handle_in); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(resource_handle_out); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(resource_handle_out); - msg_ptr->tel.tel_data_ptr[4] = (default_mute != false) ? 1U : 0U; - msg_ptr->tel.tel_data_ptr[5] = (uint8_t)mute_mode; - msg_ptr->tel.tel_data_ptr[6] = MISC_HB(offset); - msg_ptr->tel.tel_data_ptr[7] = MISC_LB(offset); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function manually mutes a synchronous data connection. - * \param self Reference to CInic instance - * \param sync_handle Resource handle of the synchronous connection - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_SyncMute(CInic *self, - uint16_t sync_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_SYNC_MUTE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_SYNC_MUTE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(sync_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(sync_handle); - - self->ssubs[INIC_SSUB_SYNC_MUTE].user_mask = INIC_API_SYNC_MUTE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_SYNC_MUTE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_SYNC_MUTE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_SYNC_MUTE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function manually de-mutes a synchronous data connection. - * \param self Reference to CInic instance - * \param sync_handle Resource handle of the synchronous connection - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_SyncDemute(CInic *self, - uint16_t sync_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_SYNC_DEMUTE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_SYNC_DEMUTE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(sync_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(sync_handle); - - self->ssubs[INIC_SSUB_SYNC_DEMUTE].user_mask = INIC_API_SYNC_DEMUTE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_SYNC_DEMUTE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_SYNC_DEMUTE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_SYNC_DEMUTE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a DiscreteFrame Isochronous streaming phase connection. The connection can be - * directly associated with an input and output socket. - * \param self Reference to CInic instance - * \param resource_handle_in The ID number of the socket or splitter resource that is the - * starting point of the link. - * \param resource_handle_out The ID number of the socket or splitter resource that is the ending - * point of the link. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_DfiPhaseCreate(CInic *self, - uint16_t resource_handle_in, - uint16_t resource_handle_out, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_DFIPHASE_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(resource_handle_in); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(resource_handle_in); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(resource_handle_out); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(resource_handle_out); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a combiner resource. A Combiner enables grouping of data from multiple network - * sockets into the same port socket. - * \param self Reference to CInic instance - * \param port_socket_handle Only supported sockets are Streaming Port, MLB, USB (OS81118) or PCI - * (OS81160) sockets of data type Synchronous. Direction must be OUT. - * \param most_port_handle When the splitter is created with a MOST socket, the socket must be - * created on the same port indicated by this handle. - * \param bytes_per_frame Specifies the total number of data bytes that are to be transferred - * each MOST frame. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_CombinerCreate(CInic *self, - uint16_t port_socket_handle, - uint16_t most_port_handle, - uint16_t bytes_per_frame, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_COMBINER_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(port_socket_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(port_socket_handle); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(most_port_handle); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(most_port_handle); - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(bytes_per_frame); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(bytes_per_frame); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a splitter resource. A Splitter enables splitting up the data from a single - * channel into multiple channels. - * \param self Reference to CInic instance - * \param socket_handle_in All sockets of data type Synchronous are supported, regardless of - * the port the socket is created on. The direction must be IN. - * \param most_port_handle When the splitter is created with a MOST socket, the socket must be - * created on the same port indicated by this handle. - * \param bytes_per_frame Specifies the total number of data bytes that are to be transferred - * each MOST frame. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_SplitterCreate(CInic *self, - uint16_t socket_handle_in, - uint16_t most_port_handle, - uint16_t bytes_per_frame, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_SPLITTER_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(socket_handle_in); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(socket_handle_in); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(most_port_handle); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(most_port_handle); - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(bytes_per_frame); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(bytes_per_frame); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates an Quality of Service IP Streaming data connection. - * \param self Reference to CInic instance - * \param socket_in_handle The ID number of the created socket that is the starting point of - * the link. Must be a socket of type Input. - * \param socket_out_handle The ID number of the created socket that is the ending point of - * the link. Must be a socket of type Output. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_QoSCreate(CInic *self, - uint16_t socket_in_handle, - uint16_t socket_out_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_QOS_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(socket_out_handle); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(socket_out_handle); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates an IPC (Inter-Processor Communication) packet connection. - * \param self Reference to CInic instance - * \param socket_in_handle The ID number of the created socket that is the starting point of - * the link. Must be a socket of type Input. - * \param socket_out_handle The ID number of the created socket that is the ending point of - * the link. Must be a socket of type Output. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_IpcCreate(CInic *self, - uint16_t socket_in_handle, - uint16_t socket_out_handle, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_IPC_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(socket_out_handle); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(socket_out_handle); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates an A/V Packetized Isochronous Streaming data connection. - * \param self Reference to CInic instance - * \param socket_in_handle The ID number of the created socket that is the starting point of - * the link. Must be a socket of type Input. - * \param socket_out_handle The ID number of the created socket that is the ending point of - * the link. Must be a socket of type Output. - * \param isoc_packet_size Specifies the size of data packets that are to be transported over - * the isochronous channel. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_AvpCreate(CInic *self, - uint16_t socket_in_handle, - uint16_t socket_out_handle, - Ucs_Avp_IsocPacketSize_t isoc_packet_size, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_AVP_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(socket_in_handle); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(socket_out_handle); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(socket_out_handle); - msg_ptr->tel.tel_data_ptr[4] = MISC_HB((uint16_t)isoc_packet_size); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB((uint16_t)isoc_packet_size); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates a MOST socket bound to the MOST Network Port. - * \param self Reference to CInic instance - * \param most_port_handle MOST Network Port resource handle - * \param direction indicates the direction of the data stream from the perspective of - * the INIC - * \param data_type Specifies the data type - * \param bandwidth Required socket bandwidth in bytes. Maximum value depends on current - * free network resources. - * \param connection_label MOST network connection label. When used as parameter with direction - * Input, the connection label is used to connect to the appropriate MOST - * frame bytes. When used as parameter with direction Output, the - * connection label is not used and must be set to 0xFFFF. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_MostSocketCreate(CInic *self, - uint16_t most_port_handle, - Ucs_SocketDirection_t direction, - Ucs_Most_SocketDataType_t data_type, - uint16_t bandwidth, - uint16_t connection_label, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_SOCKET_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(most_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(most_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)direction; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)data_type; - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(bandwidth); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(bandwidth); - msg_ptr->tel.tel_data_ptr[6] = MISC_HB(connection_label); - msg_ptr->tel.tel_data_ptr[7] = MISC_LB(connection_label); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates the MediaLB Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param index MediaLB Port instance - * \param clock_config Stores the clock speed configuration. The value is a multiple - * of the MOST network frame rate Fs; this means the MediaLB Port - * can only be frequency locked to the network's system clock. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_MlbPortCreate(CInic *self, - uint8_t index, - Ucs_Mlb_ClockConfig_t clock_config, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MLB_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)clock_config; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a MediaLB socket bound to the MediaLB Port with the associated port instance - * identifier. If INIC enters Protected Mode, the MediaLB socket will be automatically - * destroyed. - * \param self Reference to CInic instance - * \param mlb_port_handle MediaLB Port resource handle - * \param direction Indicates the direction of the data stream from the perspective of - * the INIC - * \param data_type Specifies the data type - * \param bandwidth Required socket bandwidth in bytes - * \param channel_address Indicates the MediaLB ChannelAddress where the socket is mapped to. - * If the MediaLB Port is created by default, ChannelAddresses 0x0002 - * and 0x0004 are reserved and cannot be used. - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_MlbSocketCreate(CInic *self, - uint16_t mlb_port_handle, - Ucs_SocketDirection_t direction, - Ucs_Mlb_SocketDataType_t data_type, - uint16_t bandwidth, - uint16_t channel_address, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MLB_SOCKET_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(mlb_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(mlb_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)direction; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)data_type; - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(bandwidth); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(bandwidth); - msg_ptr->tel.tel_data_ptr[6] = MISC_HB(channel_address); - msg_ptr->tel.tel_data_ptr[7] = MISC_LB(channel_address); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates the USB Port with its associated port instance identifier. The instance - * identifier of an USB Port is always directly bound to a specific hardware port. - * \param self Reference to CInic instance - * \param index USB Port instance - * \param physical_layer USB Port physical layer - * \param devices_interfaces USB Interfaces supported by the device - * \param streaming_if_ep_out_count number of USB OUT Endpoints being provided through the USB streaming interface - * \param streaming_if_ep_in_count number of USB IN Endpoints being provided through the USB Streaming interface - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_UsbPortCreate(CInic *self, - uint8_t index, - Ucs_Usb_PhysicalLayer_t physical_layer, - uint16_t devices_interfaces, - uint8_t streaming_if_ep_out_count, - uint8_t streaming_if_ep_in_count, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_USB_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)physical_layer; - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(devices_interfaces); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(devices_interfaces); - msg_ptr->tel.tel_data_ptr[4] = streaming_if_ep_out_count; - msg_ptr->tel.tel_data_ptr[5] = streaming_if_ep_in_count; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Creates a USB socket bound to the USB port with its associated port instance identifier. - * If INIC enters Protected Mode, the USB socket will be automatically destroyed. - * \param self Reference to CInic instance - * \param usb_port_handle USB Port resource handle - * \param direction Indicates the direction of the data stream from the perspective of - * the INIC - * \param data_type Specifies the data type - * \param end_point_addr Denotes the address of a USB endpoint as per its description in the - * USB 2.0 Specification - * \param frames_per_transfer Indicates the number of MOST frames per transfer per one USB - * transaction - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_UsbSocketCreate(CInic *self, - uint16_t usb_port_handle, - Ucs_SocketDirection_t direction, - Ucs_Usb_SocketDataType_t data_type, - uint8_t end_point_addr, - uint16_t frames_per_transfer, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 7U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_USB_SOCKET_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(usb_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(usb_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)direction; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)data_type; - msg_ptr->tel.tel_data_ptr[4] = end_point_addr; - msg_ptr->tel.tel_data_ptr[5] = MISC_HB(frames_per_transfer); - msg_ptr->tel.tel_data_ptr[6] = MISC_LB(frames_per_transfer); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function is used to configure the Streaming Ports. - * \param self Reference to CInic instance - * \param index Streaming Port instance - * \param op_mode Streaming Port Operation mode - * \param port_option Streaming Port Options - * \param clock_mode Stream Port Clock Mode - * \param clock_data_delay Stream Port Clock Data Delay - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_StreamPortConfig_SetGet(CInic *self, - uint8_t index, - Ucs_Stream_PortOpMode_t op_mode, - Ucs_Stream_PortOption_t port_option, - Ucs_Stream_PortClockMode_t clock_mode, - Ucs_Stream_PortClockDataDelay_t clock_data_delay, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_STREAM_PORT_CONFIG) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 5U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_STREAM_PORT_CONFIG; - msg_ptr->id.op_type = UCS_OP_SETGET; - - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)index; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)op_mode; - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)port_option; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)clock_mode; - msg_ptr->tel.tel_data_ptr[4] = (uint8_t)clock_data_delay; - - self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG].user_mask = INIC_API_STREAM_PORT_CONFIG; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_STREAM_PORT_CONFIG); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function is used to request the configurations of the Streaming Ports. - * \param self Reference to CInic instance - * \param index Streaming Port Instance ID - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_StreamPortConfig_Get(CInic *self, - uint8_t index, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_STREAM_PORT_CONFIG) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_STREAM_PORT_CONFIG; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->tel.tel_data_ptr[0] = (uint8_t)index; - - self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG].user_mask = INIC_API_STREAM_PORT_CONFIG; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_STREAM_PORT_CONFIG], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_STREAM_PORT_CONFIG); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates the Streaming Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param index Streaming Port instance - * \param clock_config Clock speed configuration of the SCK signal - * \param data_alignment Defines the alignment of the data bytes within the streaming port frame - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_StreamPortCreate(CInic *self, - uint8_t index, - Ucs_Stream_PortClockConfig_t clock_config, - Ucs_Stream_PortDataAlign_t data_alignment, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 3U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_STREAM_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)clock_config; - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)data_alignment; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates a Synchronous or DiscreteFrame Isochronous Streaming data socket - * bound to the Streaming Port with the denoted port instance identifier. - * \param self Reference to CInic instance - * \param stream_port_handle Streaming Port resource handle - * \param direction Indicates the direction of the data stream, from the INIC's - * perspective - * \param data_type Specifies the data type - * \param bandwidth Required socket bandwidth in bytes - * \param stream_pin_id ID of the serial interface pin of the addressed Streaming Port - * instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_StreamSocketCreate(CInic *self, - uint16_t stream_port_handle, - Ucs_SocketDirection_t direction, - Ucs_Stream_SocketDataType_t data_type, - uint16_t bandwidth, - Ucs_Stream_PortPinId_t stream_pin_id, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 7U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_STREAM_SOCKET_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(stream_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(stream_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)direction; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)data_type; - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(bandwidth); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(bandwidth); - msg_ptr->tel.tel_data_ptr[6] = (uint8_t)stream_pin_id; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates an RMCK Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param index RMCK Port instance - * \param clock_source Indicates the source of the RMCK clock - * \param divisor Divisor of the clock source - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_RmckPortCreate(CInic *self, - uint8_t index, - Ucs_Rmck_PortClockSource_t clock_source, - uint16_t divisor, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_RMCK_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - msg_ptr->tel.tel_data_ptr[1] = (uint8_t)clock_source; - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(divisor); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(divisor); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates an I2C Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param index I2C Port instance - * \param address The 7-bit I2C slave address of the peripheral to be read. - * \param mode The operation mode of the I2C Port - * \param speed The speed grade of the I2C Port - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_I2cPortCreate(CInic *self, - uint8_t index, - uint8_t address, - uint8_t mode, - Ucs_I2c_Speed_t speed, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_I2C_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - msg_ptr->tel.tel_data_ptr[1] = address; - msg_ptr->tel.tel_data_ptr[2] = mode; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)speed; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function reads a block of bytes from an I2C device at a specified I2C address. - * \param self Reference to CInic instance - * \param port_handle Port resource handle - * \param slave_address The 7-bit I2C slave address of the peripheral to be read - * \param data_len Number of bytes to be read from the address - * \param timeout The timeout for the I2C Port read - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_I2cPortRead(CInic *self, - uint16_t port_handle, - uint8_t slave_address, - uint8_t data_len, - uint16_t timeout, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_I2C_PORT_WR) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_I2C_PORT_READ; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(port_handle); - msg_ptr->tel.tel_data_ptr[2] = slave_address; - msg_ptr->tel.tel_data_ptr[3] = data_len; - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(timeout); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(timeout); - - self->ssubs[INIC_SSUB_I2C_PORT_WR].user_mask = INIC_API_I2C_PORT_WR; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_I2C_PORT_WR]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_I2C_PORT_WR], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_I2C_PORT_WR); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function writes a block of bytes to an I2C device at a specified I2C address. - * \param self Reference to CInic instance - * \param port_handle Port resource handle - * \param mode The write transfer mode - * \param block_count The number of blocks to be written to the I2C address. - * \param slave_address The 7-bit I2C slave address of the peripheral to be read - * \param timeout The timeout for the I2C Port write - * \param data_len Number of bytes to be written to the addressed I2C peripheral - * \param data_list Reference to the data list to be written - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_I2cPortWrite(CInic *self, - uint16_t port_handle, - Ucs_I2c_TrMode_t mode, - uint8_t block_count, - uint8_t slave_address, - uint16_t timeout, - uint8_t data_len, - uint8_t data_list[], - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_I2C_PORT_WR) != false) - { - uint8_t i; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, (8U + data_len)); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_I2C_PORT_WRITE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)mode; - msg_ptr->tel.tel_data_ptr[3] = block_count; - msg_ptr->tel.tel_data_ptr[4] = slave_address; - msg_ptr->tel.tel_data_ptr[5] = (mode == UCS_I2C_BURST_MODE) ? (data_len/block_count):data_len; - msg_ptr->tel.tel_data_ptr[6] = MISC_HB(timeout); - msg_ptr->tel.tel_data_ptr[7] = MISC_LB(timeout); - - if (data_list != NULL) - { - for (i = 0U; i < data_len; i++) - { - msg_ptr->tel.tel_data_ptr[8U + i] = data_list[i]; - } - } - - self->ssubs[INIC_SSUB_I2C_PORT_WR].user_mask = INIC_API_I2C_PORT_WR; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_I2C_PORT_WR]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_I2C_PORT_WR], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_I2C_PORT_WR); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates an PCIe Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param index PCIe Port instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_PciPortCreate(CInic *self, - uint8_t index, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_PCI_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = index; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates a PCIe socket bound to the PCIe Port with the associated port - * instance identifier. If the EHC detaches, the PCIe socket will be automatically - * destroyed. - * \param self Reference to CInic instance - * \param pci_port_handle PCIe Port resource handle - * \param direction Indicates the direction of the data stream from the perspective of - * the INIC - * \param data_type Specifies the data type - * \param dma_channel Specifies the DMA channel - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_PciSocketCreate(CInic *self, - uint16_t pci_port_handle, - Ucs_SocketDirection_t direction, - Ucs_Pci_SocketDataType_t data_type, - uint8_t dma_channel, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 5U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_PCI_SOCKET_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(pci_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(pci_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (uint8_t)direction; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)data_type; - msg_ptr->tel.tel_data_ptr[4] = dma_channel; - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function creates a GPIO Port with its associated port instance identifier. - * \param self Reference to CInic instance - * \param gpio_port_index GPIO Port instance - * \param debounce_time Timeout for the GPIO debounce timer - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_GpioPortCreate(CInic *self, - uint8_t gpio_port_index, - uint16_t debounce_time, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_CREATE_CLASS) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 3U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_GPIO_PORT_CREATE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = gpio_port_index; - msg_ptr->tel.tel_data_ptr[1] = MISC_HB(debounce_time); - msg_ptr->tel.tel_data_ptr[2] = MISC_LB(debounce_time); - - self->ssubs[INIC_SSUB_CREATE_CLASS].user_mask = INIC_API_CREATE_CLASS; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_CREATE_CLASS]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_CREATE_CLASS], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_CREATE_CLASS); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function enables or disables a specific MOST Network Port. - * \param self Reference to CInic instance - * \param most_port_handle Port resource handle - * \param enabled Indicates whether a MOST Network Port should be enabled or disabled - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_MostPortEnable(CInic *self, - uint16_t most_port_handle, - bool enabled, - CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_MOST_PORT_ENABLE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 3U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_MOST_PORT_ENABLE; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(most_port_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(most_port_handle); - msg_ptr->tel.tel_data_ptr[2] = (enabled != false) ? 1U : 0U; - - self->ssubs[INIC_SSUB_MOST_PORT_ENABLE].user_mask = INIC_API_MOST_PORT_ENABLE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_MOST_PORT_ENABLE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_MOST_PORT_ENABLE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_MOST_PORT_ENABLE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function retrieves the current pin mode of the given GPIO Port. - * \param self Reference to CInic instance - * \param gpio_handle GPIO Port instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_GpioPortPinMode_Get(CInic *self, uint16_t gpio_handle, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_GPIO_PIN_MODE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_GPIO_PORT_PIN_MODE; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(gpio_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(gpio_handle); - - self->ssubs[INIC_SSUB_GPIO_PIN_MODE].user_mask = INIC_API_GPIO_PIN_MODE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_GPIO_PIN_MODE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_GPIO_PIN_MODE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_GPIO_PIN_MODE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function sets and retrieves the mode of a pin on the GPIO Port - * \param self Reference to CInic instance - * \param gpio_handle GPIO Port instance - * \param pin The GPIO pin that is to be configured - * \param mode The mode of the GPIO pin - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_GpioPortPinMode_SetGet(CInic *self, uint16_t gpio_handle, uint8_t pin, Ucs_Gpio_PinMode_t mode, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_GPIO_PIN_MODE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 4U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_GPIO_PORT_PIN_MODE; - msg_ptr->id.op_type = UCS_OP_SETGET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(gpio_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(gpio_handle); - msg_ptr->tel.tel_data_ptr[2] = pin; - msg_ptr->tel.tel_data_ptr[3] = (uint8_t)mode; - - self->ssubs[INIC_SSUB_GPIO_PIN_MODE].user_mask = INIC_API_GPIO_PIN_MODE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_GPIO_PIN_MODE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_GPIO_PIN_MODE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_GPIO_PIN_MODE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function retrieves the pin state of the given GPIO Port. - * \param self Reference to CInic instance - * \param gpio_handle GPIO Port instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_GpioPortPinState_Get(CInic *self, uint16_t gpio_handle, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_GPIO_PIN_STATE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_GPIO_PORT_PIN_STATE; - msg_ptr->id.op_type = UCS_OP_GET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(gpio_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(gpio_handle); - - self->ssubs[INIC_SSUB_GPIO_PIN_STATE].user_mask = INIC_API_GPIO_PIN_STATE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_GPIO_PIN_STATE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_GPIO_PIN_STATE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_GPIO_PIN_STATE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function sets and retrieves the state of a pin on the GPIO Port - * \param self Reference to CInic instance - * \param gpio_handle GPIO Port instance - * \param mask The GPIO pins to be written - * \param data The state of the GPIO pins to be written - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_GpioPortPinState_SetGet(CInic *self, uint16_t gpio_handle, uint16_t mask, uint16_t data, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_GPIO_PIN_STATE) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 6U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_GPIO_PORT_PIN_STATE; - msg_ptr->id.op_type = UCS_OP_SETGET; - - msg_ptr->tel.tel_data_ptr[0] = MISC_HB(gpio_handle); - msg_ptr->tel.tel_data_ptr[1] = MISC_LB(gpio_handle); - msg_ptr->tel.tel_data_ptr[2] = MISC_HB(mask); - msg_ptr->tel.tel_data_ptr[3] = MISC_LB(mask); - msg_ptr->tel.tel_data_ptr[4] = MISC_HB(data); - msg_ptr->tel.tel_data_ptr[5] = MISC_LB(data); - - self->ssubs[INIC_SSUB_GPIO_PIN_STATE].user_mask = INIC_API_GPIO_PIN_STATE; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_GPIO_PIN_STATE]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_GPIO_PIN_STATE], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_GPIO_PIN_STATE); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief This function enables full streaming for a specific MOST Network Port. - * \param self Reference to CInic instance - * \param most_port_handle Port resource handle - * \param enabled Indicates whether full streaming is enabled or disabled - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - * \return UCS_RET_ERR_API_LOCKED Resource API is already used by another command - */ -Ucs_Return_t Inic_MostPortEnFullStr(CInic *self, - uint16_t most_port_handle, - bool enabled, - CSingleObserver *obs_ptr) -{ - MISC_UNUSED(self); - MISC_UNUSED(most_port_handle); - MISC_UNUSED(enabled); - MISC_UNUSED(obs_ptr); - - return UCS_RET_ERR_NOT_SUPPORTED; -} - -/*! \brief Allows remote synchronization of the given device - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_DeviceSync(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - if(Al_Lock(&self->lock.res_api, INIC_API_DEVICE_SYNC) != false) - { - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_DEVICE_SYNC; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = 0x01U; - - self->ssubs[INIC_SSUB_DEVICE_SYNC].user_mask = INIC_API_DEVICE_SYNC; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_DEVICE_SYNC]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_DEVICE_SYNC], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_DEVICE_SYNC); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*! \brief Un-synchronizes to the given remote device - * \param self Reference to CInic instance - * \param obs_ptr Reference to an optional observer - * \return UCS_RET_SUCCESS message was created - * \return UCS_RET_ERR_BUFFER_OVERFLOW no message buffer available - */ -Ucs_Return_t Inic_DeviceUnsync(CInic *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U); - - if(Al_Lock(&self->lock.res_api, INIC_API_DEVICE_SYNC) != false) - { - if (msg_ptr != NULL) - { - msg_ptr->destination_addr = self->target_address; - - msg_ptr->id.fblock_id = FB_INIC; - msg_ptr->id.instance_id = 0U; - msg_ptr->id.function_id = INIC_FID_DEVICE_SYNC; - msg_ptr->id.op_type = UCS_OP_STARTRESULT; - - msg_ptr->tel.tel_data_ptr[0] = 0U; - - self->ssubs[INIC_SSUB_DEVICE_SYNC].user_mask = INIC_API_DEVICE_SYNC; - msg_ptr->info_ptr = &self->ssubs[INIC_SSUB_DEVICE_SYNC]; - Trcv_TxSendMsgExt(self->xcvr_ptr, msg_ptr, &Inic_ResMsgTxStatusCb, self); - - (void)Ssub_AddObserver(&self->ssubs[INIC_SSUB_DEVICE_SYNC], obs_ptr); - } - else - { - Al_Release(&self->lock.res_api, INIC_API_DEVICE_SYNC); - result = UCS_RET_ERR_BUFFER_OVERFLOW; - } - } - else - { - result = UCS_RET_ERR_API_LOCKED; - } - - return result; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Handler functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \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 Inic_ResMsgTxStatusCb(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status) -{ - CInic *self_ = (CInic *)self; - CSingleSubject *ssub_ptr = (CSingleSubject *)tel_ptr->info_ptr; - - if ((status != UCS_MSG_STAT_OK) && (tel_ptr->info_ptr != NULL)) - { - Inic_StdResult_t res_data; - - res_data.data_info = &status; - res_data.result.code = UCS_RES_ERR_TRANSMISSION; - res_data.result.info_ptr = NULL; - res_data.result.info_size = 0U; - Ssub_Notify(ssub_ptr, &res_data, true); - - if ((ssub_ptr != NULL) && (ssub_ptr->user_mask != 0U)) - { - Al_Release(&self_->lock.res_api, (Alm_ModuleMask_t)ssub_ptr->user_mask); - } - } - Trcv_TxReleaseMsg(tel_ptr); - /* Reset user mask of the single subject if available */ - if (ssub_ptr != NULL) - { - ssub_ptr->user_mask = 0U; - } - - /* ICM messages pending? */ - if (Sub_GetNumObservers(&self_->subs[INIC_SUB_TX_MSG_OBJ_AVAIL]) > 0U) - { - Sub_Notify(&self_->subs[INIC_SUB_TX_MSG_OBJ_AVAIL], NULL); - } -} - -/*! \brief Handler function for INIC.ResourceDestroy.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceDestroy_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_DESTROY], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_RESOURCE_DESTROY); -} - -/*! \brief Handler function for INIC.ResourceDestroy.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceDestroy_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_DESTROY], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_RESOURCE_DESTROY); -} - -/*! \brief Handler function for INIC.ResourceInvalidList.Status - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceInvalidList_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - Inic_ResHandleList_t result; - uint8_t i; - uint16_t inv_res_handles[22]; /* Max. ICM message size is 45 -> max. 22 16-bit values */ - - res_data.data_info = &result; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - /* Length of message must be even, since 16-Bit values are transmitted via two 8-bit fields. */ - TR_ASSERT(self_->base_ptr->ucs_user_ptr, "[INIC_RES]", ((msg_ptr->tel.tel_len % 2U) == 0U)); - - for(i=0U; (i < (uint8_t)(msg_ptr->tel.tel_len >> 1)); i++) - { - MISC_DECODE_WORD(&inv_res_handles[i], - &(msg_ptr->tel.tel_data_ptr[(uint8_t)((uint8_t)i << 1)])); - } - result.res_handles = &inv_res_handles[0]; - result.num_handles = (uint8_t)((uint8_t)msg_ptr->tel.tel_len >> 1); - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_RESOURCE_INVAL_LIST); -} - -/*! \brief Handler function for INIC.ResourceInvalidList.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceInvalidList_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Ssub_Notify(&self_->ssubs[INIC_SSUB_RESOURCE_INVAL_LIST], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_RESOURCE_INVAL_LIST); -} - -/*! \brief Handler function for INIC.ResourceMonitor.Status - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceMonitor_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - Ucs_Resource_MonitorState_t state; - - res_data.data_info = &state; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - state = (Ucs_Resource_MonitorState_t)msg_ptr->tel.tel_data_ptr[0]; - Sub_Notify(&self_->subs[INIC_SUB_RES_MONITOR], &res_data); -} - -/*! \brief Handler function for INIC.ResourceMonitor.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_ResourceMonitor_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Sub_Notify(&self_->subs[INIC_SUB_RES_MONITOR], &res_data); -} - -/*! \brief Handler function for INIC.SyncCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.SyncCreate.ResultAck. res_data.data_info points to the - * resource handle of the synchronous connection which was created. - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - - -/*! \brief Handler function for INIC.SyncMute.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncMute_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_MUTE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_SYNC_MUTE); -} - -/*! \brief Handler function for INIC.SyncMute.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncMute_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_MUTE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_SYNC_MUTE); -} - -/*! \brief Handler function for INIC.SyncDemute.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncDemute_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_DEMUTE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_SYNC_DEMUTE); -} - -/*! \brief Handler function for INIC.SyncDemute.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SyncDemute_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_SYNC_DEMUTE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_SYNC_DEMUTE); -} - -/*! \brief Handler function for INIC.DFIPhaseCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DfiPhaseCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.DFIPhaseCreate.ResultAck. res_data.data_info points to the - * resource handle of the DFIPhase streaming phase connection which was created. - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DfiPhaseCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.CombinerCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_CombinerCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.CombinerCreate.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_CombinerCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.SplitterCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SplitterCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.SplitterCreate.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_SplitterCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.QoSCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_QoSCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.QoSCreate.ResultAck.res_data.data_info points to the Resource - * handle of the Quality of Service IP Streaming data connection which was created. - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_QoSCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.IPCPacketCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_IpcCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.IPCPacketCreate.ResultAck.res_data.data_info points to the resource - * handle of the Inter-Processor Communication packet connection which was created. - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_IpcCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.AVPCreate.ErrorAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_AvpCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.AVPCreate.ResultAck. res_data.data_info points to the Resource - * handle of the A/V Packetized Isochronous Streaming connection which was created. - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_AvpCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MOSTPortStatus.Status - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortStatus_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_MostPortStatus_t result; - - MISC_DECODE_WORD(&(result.most_port_handle), &(msg_ptr->tel.tel_data_ptr[0])); - result.availability = (Ucs_Most_PortAvail_t)msg_ptr->tel.tel_data_ptr[2]; - result.avail_info = (Ucs_Most_PortAvailInfo_t)msg_ptr->tel.tel_data_ptr[3]; - result.fullstreaming_enabled = (msg_ptr->tel.tel_data_ptr[4] != 0U) ? true : false; - MISC_DECODE_WORD(&(result.freestreaming_bw), &(msg_ptr->tel.tel_data_ptr[5])); - - self_->most_port_status = result; - - Sub_Notify(&self_->subs[INIC_SUB_MOST_PORT_STATUS], &result); -} - -/*! \brief Handler function for INIC.MOSTPortStatus.Error - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortStatus_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - - Sub_Notify(&self_->subs[INIC_SUB_MOST_PORT_STATUS], &res_data); -} - -/*! \brief Handler function for INIC.MOSTSocketCreate.ErrorAck. Result is delivered via the - * SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostSocketCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MOSTSocketCreate.ResultAck - * \details Result is delivered via the SingleObserver element ssubs[INIC_SSUB_CREATE_CLASS]. Element - * res_data.data_info points to a variable of type Inic_MostSocketCreate_Result_t - * which holds the results of the MOSTSocketCreate command. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostSocketCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - Inic_MostSocketCreate_Result_t res; - - MISC_DECODE_WORD(&(res.most_socket_handle), &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_WORD(&(res.conn_label), &(msg_ptr->tel.tel_data_ptr[2])); - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - - -/*! \brief Handler function for INIC.MLBPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MlbPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MLBPortCreate.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * Element res_data.data_info points to the variable mlb_port_handle which holds the - * MediaLB Port resource handle. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MlbPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t mlb_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&mlb_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &mlb_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MLBSocketCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MlbSocketCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MLBSocketCreate.ResultAck - * \details Element res_data.data_info points to the variable mlb_socket_handle which holds the - * MediaLB Socket resource handle of the created socket. Result is delivered via the - * SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MlbSocketCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t mlb_socket_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&mlb_socket_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &mlb_socket_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.USBPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_UsbPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.USBPortCreate.ResultAck - * \details Element res_data.data_info points to the variable usb_port_handle which holds the USB - * Port resource handle. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_UsbPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t usb_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&usb_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &usb_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.USBSocketCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_UsbSocketCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.USBSocketCreate.ResultAck - * \details Element res_data.data_info points to the variable usb_socket_handle which holds the - * Socket resource handle of the created socket. Result is delivered via the - * SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_UsbSocketCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t usb_socket_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&usb_socket_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &usb_socket_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.StreamPortConfiguration.Status - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_STREAM_PORT_CONFIG]. - * Element res_data.data_info points to a variable of type Inic_StreamPortConfigStatus_t - * which holds the results of the INIC.StreamPortConfiguration.Get command. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamPortConfig_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StreamPortConfigStatus_t res; - Inic_StdResult_t res_data; - - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - res.index = msg_ptr->tel.tel_data_ptr[0]; - res.op_mode = (Ucs_Stream_PortOpMode_t)msg_ptr->tel.tel_data_ptr[1]; - res.port_option = (Ucs_Stream_PortOption_t)msg_ptr->tel.tel_data_ptr[2]; - res.clock_mode = (Ucs_Stream_PortClockMode_t)msg_ptr->tel.tel_data_ptr[3]; - res.clock_data_delay = (Ucs_Stream_PortClockDataDelay_t)msg_ptr->tel.tel_data_ptr[4]; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_STREAM_PORT_CONFIG], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_STREAM_PORT_CONFIG); -} - -/*! \brief Handler function for INIC.StreamPortConfiguration.Error - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_STREAM_PORT_CONFIG]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamPortConfig_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Ssub_Notify(&self_->ssubs[INIC_SSUB_STREAM_PORT_CONFIG], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_STREAM_PORT_CONFIG); -} - -/*! \brief Handler function for INIC.StreamPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.StreamPortCreate.ResultAck - * \details Element res_data.data_info points to the variable stream_port_handle which holds the - * Streaming Port resource handle. Result is delivered via the SingleObserver object - * ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t stream_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&stream_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &stream_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.StreamSocketCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamSocketCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.StreamSocketCreate.ResultAck - * \details Element res_data.data_info points to the variable stream_socket_handle which holds - * the Socket resource handle of the created socket. Result is delivered via the - * SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_StreamSocketCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t stream_socket_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&stream_socket_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &stream_socket_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.RMCKOutPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_RmckPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.RMCKOutPortCreate.ResultAck - * \details Element res_data.data_info points to the variable rmck_port_handle which holds the - * RMCK Port resource handle. Result is delivered via the SingleObserver object - * ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_RmckPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t rmck_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&rmck_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &rmck_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.I2CPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.I2CPortCreate.ResultAck - * \details Element res_data.data_info points to the variable i2c_port_handle which holds the - * I2C Port resource handle. Result is delivered via the SingleObserver object - * ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t i2c_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&i2c_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &i2c_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.I2CPortRead.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_I2C_PORT_WR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortRead_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_I2C_PORT_WR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_I2C_PORT_WR); -} - -/*! \brief Handler function for INIC.I2CPortRead.ResultAck - * \details Element res_data.data_info points to a variable of type Inic_I2cReadResStatus_t which holds the - * the results of the INIC.I2CPortRead.StartResultAck command. - * Result is delivered via the SingleObserver object ssubs[INIC_SSUB_I2C_PORT_WR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortRead_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_I2cReadResStatus_t i2c_read_res; - Inic_StdResult_t res_data; - - res_data.data_info = &i2c_read_res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&i2c_read_res.port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - i2c_read_res.slave_address = msg_ptr->tel.tel_data_ptr[2]; - i2c_read_res.data_len = msg_ptr->tel.tel_data_ptr[3]; - i2c_read_res.data_ptr = &msg_ptr->tel.tel_data_ptr[4]; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_I2C_PORT_WR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_I2C_PORT_WR); -} - -/*! \brief Handler function for INIC.I2CPortWrite.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_I2C_PORT_WR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortWrite_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_I2C_PORT_WR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_I2C_PORT_WR); -} - -/*! \brief Handler function for INIC.I2CPortWrite.ResultAck - * \details Element res_data.data_info points to a variable of type Inic_I2cWriteResStatus_t which holds the - * the results of the INIC.I2CPortWrite.StartResultAck command. - * Result is delivered via the SingleObserver object ssubs[INIC_SSUB_I2C_PORT_WR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_I2cPortWrite_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_I2cWriteResStatus_t i2c_write_res; - Inic_StdResult_t res_data; - - res_data.data_info = &i2c_write_res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&i2c_write_res.port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - i2c_write_res.slave_address = msg_ptr->tel.tel_data_ptr[2]; - i2c_write_res.data_len = msg_ptr->tel.tel_data_ptr[3]; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_I2C_PORT_WR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_I2C_PORT_WR); -} - -/*! \brief Handler function for INIC.PCIPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_PciPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.PCIPortCreate.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_PciPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t pci_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&pci_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &pci_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.PCISocketCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_PciSocketCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.PCISocketCreate.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_PciSocketCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t pci_socket_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&pci_socket_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &pci_socket_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.GPIOPortCreate.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortCreate_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.GPIOPortCreate.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_CREATE_CLASS]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortCreate_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - uint16_t gpio_port_handle; - Inic_StdResult_t res_data; - - MISC_DECODE_WORD(&gpio_port_handle, &(msg_ptr->tel.tel_data_ptr[0])); - res_data.data_info = &gpio_port_handle; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_CREATE_CLASS], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_CREATE_CLASS); -} - -/*! \brief Handler function for INIC.MOSTPortEnable.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_MOST_PORT_ENABLE]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortEnable_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_ENABLE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_MOST_PORT_ENABLE); -} - -/*! \brief Handler function for INIC.MOSTPortEnable.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_MOST_PORT_ENABLE]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortEnable_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_ENABLE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_MOST_PORT_ENABLE); -} - -/*! \brief Handler function for INIC.GPIOPortPinMode.Status - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_PIN_MODE]. - * Element res_data.data_info points to a variable of type Inic_GpioPortPinModeStatus_t - * which holds the results of the INIC.GPIOPortPinMode.Get command. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortPinMode_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_GpioPortPinModeStatus_t res; - Inic_StdResult_t res_data; - uint8_t i = 2U, j = 0U; - Ucs_Gpio_PinConfiguration_t pin_ls[16U]; - - res.cfg_list = &pin_ls[0]; - res.len = (msg_ptr->tel.tel_len - 2U) >> 1U; - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&res.gpio_handle, &(msg_ptr->tel.tel_data_ptr[0])); - for (; (i < msg_ptr->tel.tel_len) && (j < 16U); i=i+2U) - { - pin_ls[j].pin = msg_ptr->tel.tel_data_ptr[i]; - pin_ls[j].mode = (Ucs_Gpio_PinMode_t)msg_ptr->tel.tel_data_ptr[i+1U]; - j++; - } - - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_MODE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_GPIO_PIN_MODE); -} - -/*! \brief Handler function for INIC.GPIOPortPinMode.Error - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_PIN_MODE]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortPinMode_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_MODE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_GPIO_PIN_MODE); -} - -/*! \brief Handler function for INIC.GPIOPortPinState.Status - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_PIN_STATE]. - * Element res_data.data_info points to a variable of type Inic_GpioPortPinStateStatus_t - * which holds the results of the INIC.GPIOPortPinState.Get command. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortPinState_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_GpioPortPinStateStatus_t res; - Inic_StdResult_t res_data; - - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&res.gpio_handle, &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_WORD(&res.current_state, &(msg_ptr->tel.tel_data_ptr[2])); - MISC_DECODE_WORD(&res.sticky_state, &(msg_ptr->tel.tel_data_ptr[4])); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_STATE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_GPIO_PIN_STATE); -} - -/*! \brief Handler function for INIC.GPIOPortPinState.Error - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_PIN_STATE]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortPinState_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Ssub_Notify(&self_->ssubs[INIC_SSUB_GPIO_PIN_STATE], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_GPIO_PIN_STATE); -} - -/*! \brief Handler function for INIC.GPIOPortTriggerEvent.Status - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_TRIGGER_EVENT]. - * Element res_data.data_info points to a variable of type Inic_GpioTriggerEventStatus_t - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortTrigger_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_GpioTriggerEventStatus_t res; - Inic_StdResult_t res_data; - - res_data.data_info = &res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(&res.gpio_handle, &(msg_ptr->tel.tel_data_ptr[0])); - MISC_DECODE_WORD(&res.rising_edges, &(msg_ptr->tel.tel_data_ptr[2])); - MISC_DECODE_WORD(&res.falling_edges, &(msg_ptr->tel.tel_data_ptr[4])); - MISC_DECODE_WORD(&res.levels, &(msg_ptr->tel.tel_data_ptr[6])); - res.is_first_report = self_->gpio_rt_status.first_report; - if (self_->gpio_rt_status.first_report) - { - self_->gpio_rt_status.first_report = false; - } - - Sub_Notify(&self_->subs[INIC_SUB_GPIO_TRIGGER_EVENT], &res_data); -} - -/*! \brief Handler function for INIC.GPIOPortTriggerEvent.Error - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_GPIO_TRIGGER_EVENT]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_GpioPortTrigger_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - msg_ptr->tel.tel_len); - Sub_Notify(&self_->subs[INIC_SUB_GPIO_TRIGGER_EVENT], &res_data); -} - -/*! \brief Handler function for INIC.MOSTPortEnableFullStreaming.ErrorAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_MOST_PORT_EN_FULL_STR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortEnFullStr_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_EN_FULL_STR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_MOST_PORT_EN_FULL_STR); -} - -/*! \brief Handler function for INIC.MOSTPortEnableFullStreaming.ResultAck - * \details Result is delivered via the SingleObserver object ssubs[INIC_SSUB_MOST_PORT_EN_FULL_STR]. - * \param self Reference to CInic instance - * \param msg_ptr Pointer to received message - */ -void Inic_MostPortEnFullStr_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - Ssub_Notify(&self_->ssubs[INIC_SSUB_MOST_PORT_EN_FULL_STR], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_MOST_PORT_EN_FULL_STR); -} - -/*! \brief Handler function for INIC.Notification.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_Notification_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NOTIFICATION], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_NOTIFICATION); -} - -/*! \brief Handler function for INIC.Notification.ResultAck - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_Notification_Status(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - Inic_NotificationResult_t notif_res; - - res_data.data_info = ¬if_res; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - MISC_DECODE_WORD(¬if_res.func_id, &(msg_ptr->tel.tel_data_ptr[0])); - if (msg_ptr->tel.tel_len == 4U) - { - MISC_DECODE_WORD(¬if_res.device_id, &(msg_ptr->tel.tel_data_ptr[2])); - } - else - { - notif_res.device_id = 0U; - } - - Ssub_Notify(&self_->ssubs[INIC_SSUB_NOTIFICATION], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_NOTIFICATION); -} - -/*! \brief Handler function for INIC.DeviceSync.Error - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DeviceSync_Error(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - res_data.data_info = NULL; - res_data.result = Inic_TranslateError(self_, - &msg_ptr->tel.tel_data_ptr[0], - (msg_ptr->tel.tel_len)); - - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_SYNC], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_DEVICE_SYNC); -} - -/*! \brief Handler function for INIC.DeviceSync.Result - * \param self reference to INIC object - * \param msg_ptr received message - */ -void Inic_DeviceSync_Result(void *self, Msg_MostTel_t *msg_ptr) -{ - CInic *self_ = (CInic *)self; - Inic_StdResult_t res_data; - - MISC_UNUSED(msg_ptr); - - res_data.data_info = NULL; - res_data.result.code = UCS_RES_SUCCESS; - res_data.result.info_ptr = NULL; - - Ssub_Notify(&self_->ssubs[INIC_SSUB_DEVICE_SYNC], &res_data, true); - Al_Release(&self_->lock.res_api, INIC_API_DEVICE_SYNC); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_jobs.c b/ucs2-lib/src/ucs_jobs.c deleted file mode 100644 index 2ef6c8d..0000000 --- a/ucs2-lib/src/ucs_jobs.c +++ /dev/null @@ -1,369 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Job classes - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_MGR - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_jobs.h" -#include "ucs_misc.h" -/*#include "ucs_scheduler.h" -#include "ucs_trace.h"*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -static const uint8_t JBS_SRV_PRIO = 246U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Jbs_Service(void *self); -static void Jbq_OnJobResult(void *self, void *data_ptr); -static bool Jbs_ForEachJbq(void *d_ptr, void *ud_ptr); -static bool Jbq_CheckState(CJobQ *self, CJob *job_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* CJobService Methods */ -/*------------------------------------------------------------------------------------------------*/ -void Jbs_Ctor(CJobService *self, CBase *base_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->base_ptr = base_ptr; - Dl_Ctor(&self->list, base_ptr->ucs_user_ptr); - Srv_Ctor(&self->service, JBS_SRV_PRIO, self, &Jbs_Service); - (void)Scd_AddService(&self->base_ptr->scd, &self->service); -} - -void Jbs_RegisterJobQ(CJobService *self, CDlNode *job_q_node) -{ - Dl_InsertTail(&self->list, job_q_node); -} - -void Jbs_TriggerEvent(CJobService *self, Srv_Event_t id) -{ - Srv_SetEvent(&self->service, id); -} - -static bool Jbs_ForEachJbq(void *d_ptr, void *ud_ptr) -{ - Srv_Event_t *event_ptr = (Srv_Event_t*)ud_ptr; - CJobQ *jobQ_ptr = (CJobQ*)d_ptr; - - if ((*event_ptr & Jbq_GetEventId(jobQ_ptr)) != 0U) - { - Jbq_Service(jobQ_ptr); - } - - return false; /* continue loop for all jobQs */ -} - -static void Jbs_Service(void *self) -{ - CJobService *self_ = (CJobService *)self; - Srv_Event_t event_mask; - - Srv_GetEvent(&self_->service, &event_mask); /* save and reset current events */ - Srv_ClearEvent(&self_->service, event_mask); - - Dl_Foreach(&self_->list, &Jbs_ForEachJbq, &event_mask); /* service jobQ with the corresponding event */ -} - - -/*------------------------------------------------------------------------------------------------*/ -/* CJobQ Methods */ -/*------------------------------------------------------------------------------------------------*/ -void Jbq_Ctor(CJobQ *self, CJobService *job_service_ptr, Srv_Event_t event_id, CJob *job_list[]) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->job_service_ptr = job_service_ptr; - self->event_id = event_id; - self->job_list = job_list; - - self->index = 0U; - self->state = JOB_S_STOPPED; - self->result = JOB_R_NA; - - Dln_Ctor(&self->node, self); - Ssub_Ctor(&self->q_subject, 0U /*inst id*/); - Sobs_Ctor(&self->result_obs, self, &Jbq_OnJobResult); - Jbs_RegisterJobQ(self->job_service_ptr, &self->node); -} - -Srv_Event_t Jbq_GetEventId(CJobQ *self) -{ - return self->event_id; -} - -void Jbq_Start(CJobQ *self, CSingleObserver *result_obs_ptr) -{ - if (self->state != JOB_S_STARTED) - { - if (self->job_list[self->index] != NULL) - { - TR_INFO((0U, "[JBQ]", "Jbq_Start(): Starting job queue. Id: 0x%04X", 1U, self->event_id)); - self->index = 0U; - self->state = JOB_S_STARTED; - self->result = JOB_R_NA; - (void)Ssub_AddObserver(&self->q_subject, result_obs_ptr); /* register observer for finished queue */ - Job_Start(self->job_list[self->index], &self->result_obs); /* pass own observer for finished job */ - } - else - { - TR_ERROR((0U, "[JBQ]", "Jbq_Start(): Invalid job list. Id: 0x%04X", 1U, self->event_id)); - } - } - else - { - TR_ERROR((0U, "[JBQ]", "Jbq_Start(): JobQ already started. Id: 0x%04X", 1U, self->event_id)); - } -} - -void Jbq_Stop(CJobQ *self) -{ - if (self->state == JOB_S_STARTED) - { - if (self->job_list[self->index] != NULL) - { - self->index = 0U; - self->state = JOB_S_STOPPED; - self->result = JOB_R_NA; - (void)Ssub_RemoveObserver(&self->q_subject); - Job_Stop(self->job_list[self->index]); - } - } -} - - -static void Jbq_OnJobResult(void *self, void *data_ptr) -{ - CJobQ *self_ = (CJobQ *)self; - Job_Result_t *result_ptr = (Job_Result_t *)data_ptr; - - if (self_->state == JOB_S_STARTED) - { - TR_INFO((0U, "[JBQ]", "Jbq_OnJobResult(): Receiving job result. event_id=0x%04X, result=0x%02X", 2U, self_->event_id, *result_ptr)); - Jbs_TriggerEvent(self_->job_service_ptr, self_->event_id); - } - else - { - TR_INFO((0U, "[JBQ]", "Jbq_OnJobResult(): Receiving job result for stopped job. Id: 0x%04X", 1U, self_->event_id)); - } - - MISC_UNUSED(result_ptr); -} - - -static bool Jbq_CheckState(CJobQ *self, CJob *job_ptr) -{ - bool ret = false; - - if (self->state == JOB_S_STARTED) - { - if (job_ptr != NULL) - { - if ((Job_GetState(job_ptr) == JOB_S_FINISHED) && (Job_GetResult(job_ptr) != JOB_R_NA)) - { - ret = true; /* job attributes are correct -> process */ - } - } - else - { - TR_ERROR((0U, "[JBQ]", "Jbq_Service(): Invalid job list. Id: 0x%04X", 1U, self->event_id)); - } - } - else - { - TR_ERROR((0U, "[JBQ]", "Jbq_Service(): JobQ not started. Id: 0x%04X", 1U, self->event_id)); - } - - return ret; -} - -void Jbq_Service(CJobQ *self) -{ - CJob *curr_job_ptr = self->job_list[self->index]; - CJob *next_job_ptr = self->job_list[self->index + 1U]; - - if (Jbq_CheckState(self, curr_job_ptr)) - { - if (curr_job_ptr != NULL) - { - Job_Result_t tmp_res = Job_GetResult(curr_job_ptr); - - if ((next_job_ptr != NULL) && (tmp_res == JOB_R_SUCCESS)) /* job successfully and next job available */ - { - self->index += 1U; - Job_Start(next_job_ptr, &self->result_obs); - } - else /* current job not successful or last job */ - { - self->result = tmp_res; /* copy status from last job and finish */ - self->state = JOB_S_FINISHED; - Ssub_Notify(&self->q_subject, &tmp_res, true/*auto-remove*/); - } - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* CJob Methods */ -/*------------------------------------------------------------------------------------------------*/ - -void Job_Ctor(CJob *self, Job_StartCb_t start_fptr, void *inst_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->start_fptr = start_fptr; - self->inst_ptr = inst_ptr; - - self->state = JOB_S_STOPPED; - self->result = JOB_R_NA; - Ssub_Ctor(&self->subject, 0U /*ucs instance*/); -} - -void Job_Start(CJob *self, CSingleObserver *result_obs_ptr) -{ - if (self->state != JOB_S_STARTED) - { - TR_ASSERT(0U, "[JOB]", (self->start_fptr != NULL)); - (void)Ssub_AddObserver(&self->subject, result_obs_ptr); - self->state = JOB_S_STARTED; - self->result = JOB_R_NA; - - TR_INFO((0U, "[JOB]", "Job_Start(): starting job", 0U)); - self->start_fptr(self->inst_ptr); - } - else - { - TR_INFO((0U, "[JOB]", "Job_Start(): ambiguous state during job start", 0U)); - } -} - -void Job_Stop(CJob *self) -{ - self->state = JOB_S_STOPPED; - self->result = JOB_R_NA; - Ssub_RemoveObserver(&self->subject); - TR_INFO((0U, "[JOB]", "Job_Stop()", 0U)); -} - -void Job_SetResult(CJob *self, Job_Result_t result) -{ - TR_INFO((0U, "[JOB]", "Job_SetResult(): result=%d", 1U, result)); - - if (self->state == JOB_S_STARTED) - { - self->state = JOB_S_FINISHED; - self->result = result; - Ssub_Notify(&self->subject, &result, true/*auto-remove*/); - MISC_UNUSED(self); - MISC_UNUSED(result); - } - else - { - TR_ERROR((0U, "[JOB]", "Job_SetResult(): called in ambiguous state=%d", 1U, self->state)); - } -} - -Job_State_t Job_GetState(CJob *self) -{ - return self->state; -} - -Job_Result_t Job_GetResult(CJob *self) -{ - return self->result; -} - - - - - - - - - - - - - - - - - -#if 0 - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of Manager class - * \param self The instance - * \param base_ptr Reference to base component - * \param inic_ptr Reference to INIC component - * \param net_ptr Reference to net component - * \param packet_bw Desired packet bandwidth - */ -void Mgr_Ctor(CManager *self, CBase *base_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr, uint16_t packet_bw) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->base_ptr = base_ptr; - self->inic_ptr = inic_ptr; - self->net_ptr = net_ptr; - self->packet_bw = packet_bw; - - Srv_Ctor(&self->service, MGR_SRV_PRIO, self, &Mgr_Service); /* register service */ - (void)Scd_AddService(&self->base_ptr->scd, &self->service); - - Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Mgr_OnInitComplete); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer); - - Sobs_Ctor(&self->startup_obs, self, &Mgr_OnNwStartupResult); - Sobs_Ctor(&self->shutdown_obs, self, &Mgr_OnNwShutdownResult); - Mobs_Ctor(&self->nwstatus_mobs, self, MGR_NWSTATUS_MASK, &Mgr_OnNwStatus); - Fsm_Ctor(&self->fsm, self, &(mgr_state_tbl[0][0]), (uint8_t)MGR_EV_MAX_NUM_EVENTS, MGR_EV_NIL/*init.event*/); -} - -#endif - - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_lldpool.c b/ucs2-lib/src/ucs_lldpool.c deleted file mode 100644 index b0b833d..0000000 --- a/ucs2-lib/src/ucs_lldpool.c +++ /dev/null @@ -1,99 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 LLD Message Pool - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMF - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_lldpool.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Returns an unused LLD Tx message object back to the pool - * \param self The instance - * \param owner_ptr Assigns messages to the respective FIFO - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Lldp_Ctor(CLldPool *self, void *owner_ptr, void* ucs_user_ptr) -{ - uint8_t cnt; - MISC_MEM_SET(self, 0, sizeof(*self)); - - Dl_Ctor(&self->list, ucs_user_ptr); - - for (cnt = 0U; cnt < LLDP_NUM_HANDLES; cnt++) /* setup LLD Tx handles */ - { - TR_ASSERT(ucs_user_ptr, "[FIFO]", (self->messages[cnt].msg_ptr == NULL) ); - Dln_Ctor(&self->messages[cnt].node, &self->messages[cnt]); - self->messages[cnt].owner_ptr = owner_ptr; - Dl_InsertTail(&self->list, &self->messages[cnt].node); - } -} - -/*! \brief Returns an unused LLD Tx message object back to the pool - * \param self The instance - * \param msg_ptr The unused LLD Tx message object - */ -void Lldp_ReturnTxToPool(CLldPool *self, Lld_IntTxMsg_t *msg_ptr) -{ - Dl_InsertTail(&self->list, &msg_ptr->node); -} - -/*! \brief Allocates an unused LLD Tx message object from the pool - * \param self The instance - * \return An internal LLD Tx message object or \c NULL if no message object is - * available. - */ -Lld_IntTxMsg_t* Lldp_GetTxFromPool(CLldPool *self) -{ - CDlNode *node_ptr = NULL; - Lld_IntTxMsg_t *handle_ptr = NULL; - - node_ptr = Dl_PopHead(&self->list); - - if (node_ptr != NULL) - { - handle_ptr = (Lld_IntTxMsg_t*)Dln_GetData(node_ptr); - } - - return handle_ptr; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_message.c b/ucs2-lib/src/ucs_message.c deleted file mode 100644 index e39e165..0000000 --- a/ucs2-lib/src/ucs_message.c +++ /dev/null @@ -1,353 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class message - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_MESSAGE - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_message.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of common MOST message class - * \param self The instance - */ -void Msg_Ctor(CMessage *self) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - Dln_Ctor(&self->node, self); - - self->rsvd_memory.allocator_ptr = NULL; - self->rsvd_memory.mem_info_ptr = NULL; - self->rsvd_memory.public_buffer.next_buffer_ptr = NULL; - self->rsvd_memory.public_buffer.data_ptr = &self->rsvd_buffer[0]; - self->rsvd_memory.public_buffer.data_size = MSG_SIZE_RSVD_BUFFER; - self->rsvd_memory.public_buffer.total_size = MSG_SIZE_RSVD_BUFFER; - - self->start_ptr = &self->rsvd_buffer[0]; - self->pb_msg.tel.tel_data_ptr = &self->rsvd_buffer[0]; -/* self->pb_msg.tel.tel_id = 0U; - self->pb_msg.tel.tel_cnt = 0U; - self->pb_msg.tel.tel_len = 0U; */ - - self->pb_msg.opts.llrbc = MSG_LLRBC_DEFAULT; - -/* self->header_rsvd_sz = 0U; - self->header_curr_idx = 0U; - self->header_curr_sz = 0U; - self->ref_ptr = NULL; */ -} - -/*! \brief Prepares the message for re-usage - * \details In future this function has to take care that external memory - * has to be reinitialize properly. - * \param self The instance - */ -void Msg_Cleanup(CMessage *self) -{ - void *handle = self->lld_handle_ptr; /* restore associated LLD message object */ - void *pool_ptr = self->pool_ptr; /* restore associated pool reference */ - - Msg_Ctor(self); /* simply call constructor now */ - - self->lld_handle_ptr = handle; - self->pool_ptr = pool_ptr; -} - -/*! \brief Adds external message payload to the message - * \details The internally reserved message payload is no longer in in use. - * \param self The instance - * \param payload_ptr Pointer to externally allocated payload - * \param payload_sz Size of externally allocated payload - * \param mem_info_ptr Reference to additional memory information - */ -void Msg_SetExtPayload(CMessage *self, uint8_t *payload_ptr, uint8_t payload_sz, void* mem_info_ptr) -{ - self->pb_msg.tel.tel_data_ptr = payload_ptr; - self->pb_msg.tel.tel_len = payload_sz; - - self->ext_memory.allocator_ptr = NULL; - self->ext_memory.mem_info_ptr = mem_info_ptr; - self->ext_memory.public_buffer.data_ptr = payload_ptr; - self->ext_memory.public_buffer.data_size = payload_sz; - self->ext_memory.public_buffer.total_size = payload_sz; - self->ext_memory.public_buffer.next_buffer_ptr = NULL; -} - -/*! \brief Initially defines a header space in front of the data body - * \details Ensure that \c start_ptr is assigned correctly before calling - * this functions. - * \param self The instance - * \param header_sz Size of the header - */ -void Msg_ReserveHeader(CMessage *self, uint8_t header_sz) -{ - /* self->start_ptr stays */ - self->header_rsvd_sz = header_sz; - self->header_curr_idx = header_sz; - self->header_curr_sz = 0U; - - self->pb_msg.tel.tel_data_ptr = &self->start_ptr[header_sz]; -} - -/*! \brief Adds a defined header space in front of the current header - * \param self The instance - * \param header_sz Size of the header - */ -void Msg_PullHeader(CMessage *self, uint8_t header_sz) -{ -/* UCS_ASSERT(header_sz <= self->curr_header_sz); */ - -/* self->pb_msg.tel.tel_data_ptr = &self->rsvd_buffer[MSG_SIZE_RSVD_HEADER];*/ - self->header_curr_idx -= header_sz; - self->header_curr_sz += header_sz; -} - -/*! \brief Undoes a message header of a defined size - * \param self The instance - * \param header_sz Size of the header - */ -void Msg_PushHeader(CMessage *self, uint8_t header_sz) -{ - self->header_curr_idx += header_sz; - self->header_curr_sz -= header_sz; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Class Properties (get/set) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Retrieves the reference to the containing MOST Telegrams structure - * \param self The instance - * \return Pointer to the internal MOST Telegram structure - */ -Msg_MostTel_t* Msg_GetMostTel(CMessage *self) -{ - return &self->pb_msg; -} - -/*! \brief Retrieves the start of the current message header - * \param self The instance - * \return Pointer to the current header start - */ -uint8_t* Msg_GetHeader(CMessage *self) -{ - return &(self->rsvd_buffer[self->header_curr_idx]); -} - -/*! \brief Retrieves the size of the current message header - * \param self The instance - * \return Size of the current header in bytes - */ -uint8_t Msg_GetHeaderSize(CMessage * self) -{ - return (self->header_curr_sz); -} - -/*! \brief Retrieves the message buffer as memory structure - * \param self The instance - * \return Reference to the message memory structure - */ -Ucs_Mem_Buffer_t* Msg_GetMemTx(CMessage *self) -{ - self->rsvd_memory.public_buffer.data_ptr = &(self->rsvd_buffer[self->header_curr_idx]); - - if (self->ext_memory.public_buffer.data_size == 0U) - { - self->rsvd_memory.public_buffer.next_buffer_ptr = NULL; - self->rsvd_memory.public_buffer.data_size = (uint16_t)self->header_curr_sz + (uint16_t)self->pb_msg.tel.tel_len; - self->rsvd_memory.public_buffer.total_size = (uint16_t)self->header_curr_sz + (uint16_t)self->pb_msg.tel.tel_len; - } - else - { - self->rsvd_memory.public_buffer.next_buffer_ptr = &self->ext_memory.public_buffer; - self->rsvd_memory.public_buffer.data_size = (uint16_t)self->header_curr_sz; /* only header is enclosed */ - self->rsvd_memory.public_buffer.total_size = self->rsvd_memory.public_buffer.data_size - + self->ext_memory.public_buffer.data_size; - } - - return &self->rsvd_memory.public_buffer; -} - -/*! \brief Assigns a message status handler which is called as soon as the message is processed - * \param self The instance - * \param callback_fptr Reference to the status callback function - * \param inst_ptr The instance which implements the status callback - */ -void Msg_SetTxStatusHandler(CMessage *self, Msg_TxStatusCb_t callback_fptr, void *inst_ptr) -{ - self->tx_status_inst = inst_ptr; - self->tx_status_fptr = callback_fptr; -} - -/*! \brief Marks the message as occupied by the LLD - * \param self The instance - * \param active Set to \c true if the message is occupied by the LLD, otherwise \c false. - */ -void Msg_SetTxActive(CMessage *self, bool active) -{ - self->tx_active = active; -} - -/*! \brief Checks if the message as occupied by the LLD - * \param self The instance - * \return Returns \c true if the message is occupied by the LLD, otherwise \c false. - */ -bool Msg_IsTxActive(CMessage *self) -{ - return self->tx_active; -} - -/*! \brief Marks the message as bypass message - * \param self The instance - * \param bypass Set to \c true if the message is supposed to be a bypass message, otherwise \c false. - */ -void Msg_SetTxBypass(CMessage *self, bool bypass) -{ - self->tx_bypass = bypass; -} - -/*! \brief Checks if the message is marked as bypass message - * \param self The instance - * \return Returns \c true if the message is marked as bypass message, otherwise \c false. - */ -bool Msg_IsTxBypass(CMessage *self) -{ - return self->tx_bypass; -} - -/*! \brief Fires a status notification for the message object - * \param self The instance - * \param status The transmission status - */ -void Msg_NotifyTxStatus(CMessage *self, Ucs_MsgTxStatus_t status) -{ - if (self->tx_status_fptr != NULL) - { - self->tx_status_fptr(self->tx_status_inst, &self->pb_msg, status); - } -} - -/*! \brief Assigns a low-level driver message - * \param self The instance - * \param handle The reference to a low-level driver message object (Tx or Rx) - */ -void Msg_SetLldHandle(CMessage *self, void *handle) -{ - self->lld_handle_ptr = handle; -} - -/*! \brief Retrieves the reference to a low-level driver message - * \param self The instance - * \return The reference to a low-level driver message object or \c NULL - * if no message is assigned. - */ -void *Msg_GetLldHandle(CMessage *self) -{ - return self->lld_handle_ptr; -} - -/*! \brief Assigns a reference for the owning pool - * \param self The instance - * \param pool_ptr The reference to the owning pool - */ -void Msg_SetPoolReference(CMessage *self, void *pool_ptr) -{ - self->pool_ptr = pool_ptr; -} - -/*! \brief Retrieves a reference for the owning pool - * \param self The instance - * \return The reference to the owning pool or \c NULL - * if no pool is assigned. - */ -void *Msg_GetPoolReference(CMessage *self) -{ - return self->pool_ptr; -} - -/*! \brief Retrieves the reference to the internal node member - * \param self The instance - * \return The reference the internal list node - */ -CDlNode *Msg_GetNode(CMessage *self) -{ - return &self->node; -} - -/*! \brief Performs checks on length payload length - * \param self The instance - * \return Returns \c true if the verification succeeded. Otherwise \c false. - */ -bool Msg_VerifyContent(CMessage *self) -{ - bool success = (self->pb_msg.tel.tel_len <= MSG_MAX_SIZE_PAYLOAD) ? true : false; - - return success; -} - -/*! \brief Merges the alternate message id into a the most message id - * \param self The instance - * \return The alternate message id - */ -uint16_t Msg_GetAltMsgId(CMessage *self) -{ - uint16_t msg_id; - msg_id = (uint16_t)(self->pb_msg.id.function_id >> 4); - msg_id = (uint16_t)((uint16_t)self->pb_msg.id.instance_id << 8) | msg_id; - return msg_id; -} - -/*! \brief Extracts the alternate message id from a the most message id - * \param self The instance - * \param alt_id The alternate message id - */ -void Msg_SetAltMsgId(CMessage *self, uint16_t alt_id) -{ - self->pb_msg.id.fblock_id = MSG_DEF_FBLOCK_ID; - self->pb_msg.id.instance_id = MISC_HB(alt_id); - self->pb_msg.id.function_id = (uint16_t)((((alt_id) & (uint16_t)0xFF)) << 4) | (uint16_t)MSG_DEF_FUNC_ID_LSN; - self->pb_msg.id.op_type = MSG_DEF_OP_TYPE; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_mgr.c b/ucs2-lib/src/ucs_mgr.c deleted file mode 100644 index 23443b9..0000000 --- a/ucs2-lib/src/ucs_mgr.c +++ /dev/null @@ -1,354 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 CManager class - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_MGR - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_mgr.h" -#include "ucs_misc.h" -#include "ucs_scheduler.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Priority of the Application Message Service */ -static const uint8_t MGR_SRV_PRIO = 245U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ -/*! \brief Event which triggers the service */ -static const Srv_Event_t MGR_SRV_EV_SERVICE = 1U; - -/*! \brief Network status mask */ -static const uint32_t MGR_NWSTATUS_MASK = 0x0FU; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ -/*! \brief The time in milliseconds the INIC will go to AutoForcedNA after sync lost. */ -static const uint16_t MGR_AUTOFORCED_NA_TIME = 5000U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Mgr_OnInitComplete(void *self, void *error_code_ptr); -static void Mgr_OnNwStatus(void *self, void *data_ptr); -static void Mgr_OnJobQResult(void *self, void *result_ptr); -static void Mgr_Startup(void *self); -static void Mgr_OnNwStartupResult(void *self, void *result_ptr); -static void Mgr_LeaveForcedNA(void *self); -static void Mgr_OnLeaveForcedNAResult(void *self, void *result_ptr); -#if 0 -static void Mgr_Shutdown(void *self); -static void Mgr_OnNwShutdownResult(void *self, void *result_ptr); -#endif - -/*------------------------------------------------------------------------------------------------*/ -/* Class methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of Manager class - * \param self The instance - * \param base_ptr Reference to base component - * \param inic_ptr Reference to INIC component - * \param net_ptr Reference to net component - * \param nd_ptr Reference to NodeDiscovery component - * \param packet_bw Desired packet bandwidth - */ -void Mgr_Ctor(CManager *self, CBase *base_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr, CNodeDiscovery *nd_ptr, uint16_t packet_bw) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->initial = true; - self->base_ptr = base_ptr; - self->inic_ptr = inic_ptr; - self->net_ptr = net_ptr; - self->nd_ptr = nd_ptr; - self->packet_bw = packet_bw; - - Jbs_Ctor(&self->job_service, base_ptr); - Job_Ctor(&self->job_leave_forced_na, &Mgr_LeaveForcedNA, self); - Job_Ctor(&self->job_startup, &Mgr_Startup, self); -#if 0 - Job_Ctor(&self->job_shutdown, &Mgr_Shutdown, self); -#endif - - self->list_startup[0] = &self->job_startup; - self->list_startup[1] = NULL; - self->list_force_startup[0] = &self->job_leave_forced_na; - self->list_force_startup[1] = &self->job_startup; - self->list_force_startup[2] = NULL; -#if 0 - self->list_shutdown[0] = &self->job_shutdown; - self->list_shutdown[1] = NULL; -#endif - - Jbq_Ctor(&self->job_q_startup, &self->job_service, 1U, self->list_startup); - Jbq_Ctor(&self->job_q_force_startup, &self->job_service, 2U, self->list_force_startup); -#if 0 - Jbq_Ctor(&self->job_q_shutdown, &self->job_service, 4U, self->list_shutdown); -#endif - - Sobs_Ctor(&self->startup_obs, self, &Mgr_OnNwStartupResult); - Sobs_Ctor(&self->force_na_obs, self, &Mgr_OnLeaveForcedNAResult); -#if 0 - Sobs_Ctor(&self->shutdown_obs, self, &Mgr_OnNwShutdownResult); -#endif - Sobs_Ctor(&self->job_q_obs, self, &Mgr_OnJobQResult); - - Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Mgr_OnInitComplete); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer); - Mobs_Ctor(&self->nwstatus_mobs, self, MGR_NWSTATUS_MASK, &Mgr_OnNwStatus); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Callback Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Callback function which is invoked if the initialization is complete - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Mgr_OnInitComplete(void *self, void *error_code_ptr) -{ - CManager *self_ = (CManager*)self; - MISC_UNUSED(error_code_ptr); - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Received init complete event", 0U)); - Net_AddObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_mobs); /* register observer */ - (void)Nd_Start(self_->nd_ptr); -} - -/*! \brief NetworkStatus callback function - * \details The function is only active if \c listening flag is \c true. - * This avoids to re-register und un-register the observer for several times. - * \param self The instance - * \param data_ptr Reference to \ref Net_NetworkStatusParam_t - */ -static void Mgr_OnNwStatus(void *self, void *data_ptr) -{ - CManager *self_ = (CManager*)self; - Net_NetworkStatusParam_t *param_ptr = (Net_NetworkStatusParam_t *)data_ptr; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus()", 0U)); - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): mask=0x%04X, events=0x%04X", 2U, param_ptr->change_mask ,param_ptr->events)); - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): avail=0x%X, avail_i=0x%X, bw=0x%X", 3U, param_ptr->availability, param_ptr->avail_info, param_ptr->packet_bw)); - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): addr=0x%03X, pos=0x%X, mpr=0x%X", 3U, param_ptr->node_address, param_ptr->node_position, param_ptr->max_position)); - - if ((param_ptr->change_mask & ((uint16_t)UCS_NW_M_AVAIL | (uint16_t)UCS_NW_M_PACKET_BW)) != 0U) - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): trigger event", 0U)); - - if (self_->current_q_ptr != NULL) - { - Jbq_Stop(self_->current_q_ptr); - } - - if (param_ptr->avail_info == UCS_NW_AVAIL_INFO_FORCED_NA) - { - self_->current_q_ptr = &self_->job_q_force_startup; /* stop forcing NA, then startup */ - Jbq_Start(&self_->job_q_force_startup, &self_->job_q_obs); - } - else if (param_ptr->availability == UCS_NW_NOT_AVAILABLE) - { - self_->current_q_ptr = &self_->job_q_startup; /* just startup */ - Jbq_Start(&self_->job_q_startup, &self_->job_q_obs); - } -#if 0 - else if ((param_ptr->node_position != 0U) || (param_ptr->packet_bw != self_->packet_bw)) - { - self_->current_q_ptr = &self_->job_q_shutdown; /* just shutdown - startup is triggered automatically */ - Jbq_Start(&self_->job_q_shutdown, &self_->job_q_obs); - } -#endif - if (self_->initial != false) - { - self_->initial = false; - if (self_->current_q_ptr == NULL) /* trigger InitAll() if no job is required for the */ - { /* initial network status notification */ - Nd_InitAll(self_->nd_ptr); - } - } - } -} - -/*! \brief Callback function that is triggered after finished a job. - * \details Failed jobs will be restarted here. - * \param self The instance - * \param result_ptr Reference to the job result \ref Job_Result_t. - */ -static void Mgr_OnJobQResult(void *self, void *result_ptr) -{ - CManager *self_ = (CManager*)self; - Job_Result_t *res = (Job_Result_t *)result_ptr; - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnJobQResult(): result=%d", 1U, *res)); - - if ((*res != JOB_R_SUCCESS) && (self_->current_q_ptr != NULL)) - { - Jbq_Start(self_->current_q_ptr, &self_->job_q_obs); - } - else - { - self_->current_q_ptr = NULL; - } -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Job: LeaveForcedNA */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Action that sets the INIC from "Forced-NotAvailable" to "NotAvailable" - * \param self The instance - */ -static void Mgr_LeaveForcedNA(void *self) -{ - CManager *self_ = (CManager*)self; - Ucs_Return_t ret; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_LeaveForcedNA()", 0U)); - ret = Inic_NwForceNotAvailable(self_->inic_ptr, false /*no longer force NA*/, &self_->force_na_obs); - - if (ret != UCS_RET_SUCCESS) - { - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_LeaveForcedNA(), function returns 0x%02X", 1U, ret)); - Job_SetResult(&self_->job_leave_forced_na, JOB_R_FAILED); - } -} - -/*! \brief Callback function which announces the result of Inic_NwForceNotAvailable() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Mgr_OnLeaveForcedNAResult(void *self, void *result_ptr) -{ - CManager *self_ = (CManager*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnLeaveForcedNAResult(): code=0x%02X", 1U, result_ptr_->result.code)); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Job_SetResult(&self_->job_leave_forced_na, JOB_R_SUCCESS); - } - else - { - Job_SetResult(&self_->job_leave_forced_na, JOB_R_FAILED); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Job: Startup */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Action that starts the network with the given parameters - * \param self The instance - */ -static void Mgr_Startup(void *self) -{ - CManager *self_ = (CManager*)self; - Ucs_Return_t ret; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Startup()", 0U)); - ret = Inic_NwStartup(self_->inic_ptr, MGR_AUTOFORCED_NA_TIME, self_->packet_bw, &self_->startup_obs); /* Startup without ForcedNA */ - - if (ret != UCS_RET_SUCCESS) - { - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Startup(), startup returns 0x%02X", 1U, ret)); - Job_SetResult(&self_->job_startup, JOB_R_FAILED); - } -} - -/*! \brief Callback function which announces the result of Net_NetworkStartup() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Mgr_OnNwStartupResult(void *self, void *result_ptr) -{ - CManager *self_ = (CManager*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStartupResult(): code=0x%02X", 1U, result_ptr_->result.code)); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Job_SetResult(&self_->job_startup, JOB_R_SUCCESS); - } - else - { - Job_SetResult(&self_->job_startup, JOB_R_FAILED); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Job: Shutdown */ -/*------------------------------------------------------------------------------------------------*/ -#if 0 -/*! \brief Action that performs a network shutdown. - * \param self The instance - */ -static void Mgr_Shutdown(void *self) -{ - CManager *self_ = (CManager*)self; - Ucs_Return_t ret; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Shutdown()", 0U)); - ret = Inic_NwShutdown(self_->inic_ptr, &self_->shutdown_obs); - - if (ret != UCS_RET_SUCCESS) - { - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Shutdown(), shutdown returns 0x%02X", 1U, ret)); - Job_SetResult(&self_->job_shutdown, JOB_R_FAILED); - } -} - -/*! \brief Callback function which announces the result of Net_NetworkShutdown() - * \param self The instance - * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t. - */ -static void Mgr_OnNwShutdownResult(void *self, void *result_ptr) -{ - CManager *self_ = (CManager*)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwShutdownResult(): code=0x%02X", 1U, result_ptr_->result.code)); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Job_SetResult(&self_->job_shutdown, JOB_R_SUCCESS); - } - else - { - Job_SetResult(&self_->job_shutdown, JOB_R_FAILED); - } -} -#endif - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_misc.c b/ucs2-lib/src/ucs_misc.c deleted file mode 100644 index 8c018a4..0000000 --- a/ucs2-lib/src/ucs_misc.c +++ /dev/null @@ -1,80 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 library module which contains miscellaneous helper functions. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_MISC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief UNICENS internal memset-function. - * \param dst_ptr Pointer to the block of memory to fill - * \param value Value to be set - * \param size Number of bytes to be set to the value - */ -void Misc_MemSet(void *dst_ptr, int32_t value, uint32_t size) -{ - uint8_t *dst_ptr_ = (uint8_t *)dst_ptr; - uint32_t i; - - for(i=0U; i<size; i++) - { - dst_ptr_[i] = (uint8_t)value; /* parasoft-suppress MISRA2004-17_4 "void pointer required for memset-function signature (stdlib)" */ - } -} - -/*! \brief UNICENS internal memcpy-function. - * \param dst_ptr Pointer to the destination array where the content is to be copied - * \param src_ptr Pointer to the source of data to be copied - * \param size Number of bytes to copy - */ -void Misc_MemCpy(void *dst_ptr, void *src_ptr, uint32_t size) -{ - uint8_t *dst_ptr_ = (uint8_t *)dst_ptr; - uint8_t *src_ptr_ = (uint8_t *)src_ptr; - uint32_t i; - - for(i=0U; i<size; i++) - { - dst_ptr_[i] = src_ptr_[i]; /* parasoft-suppress MISRA2004-17_4 "void pointers required for memcpy-function signature (stdlib)" */ - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_net.c b/ucs2-lib/src/ucs_net.c deleted file mode 100644 index 4e4b274..0000000 --- a/ucs2-lib/src/ucs_net.c +++ /dev/null @@ -1,310 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Network Management. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_NET - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_net.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the NET service used by scheduler */ -static const uint8_t NET_SRV_PRIO = 251U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Event to trigger notification of MOST Network Status */ -static const Srv_Event_t NET_EVENT_NOTIFY_NW_STATUS = 1U; -/*! \brief Event to trigger notification of MOST Network Configuration */ -static const Srv_Event_t NET_EVENT_NOTIFY_NW_CONFIG = 2U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Default value used for INIC sender handles */ -static const uint16_t NET_DEFAULT_SENDER_HANDLE = 0x0001U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Initialization timeout in milliseconds (t = 7s) */ -static const uint16_t NET_PBW_TIMEOUT = 7000U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Net_Service(void *self); -static void Net_UpdateNetworkStatus(void *self, void *data_ptr); -static void Net_UpdateNetworkConfiguration(void *self, void *data_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CNetworkManagement */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Network Management class. - * \param self Instance pointer - * \param init_ptr Reference to the initialization data - */ -void Net_Ctor(CNetworkManagement *self, Net_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->base_ptr = init_ptr->base_ptr; - self->inic_ptr = init_ptr->inic_ptr; - Obs_Ctor(&self->network_status.observer, self, &Net_UpdateNetworkStatus); - Inic_AddObsrvNwStatus(self->inic_ptr, &self->network_status.observer); - self->network_status.param.change_mask = 0xFFFFU; /* Used for initial notification! */ - Sub_Ctor(&self->network_status.pre_subject, self->base_ptr->ucs_user_ptr); - Sub_Ctor(&self->network_status.subject, self->base_ptr->ucs_user_ptr); - - Obs_Ctor(&self->network_configuration.observer, self, &Net_UpdateNetworkConfiguration); - Inic_AddObsvrNwConfig(self->inic_ptr, &self->network_configuration.observer); - self->network_configuration.param.change_mask = 0xFFFFU; /* Used for initial notification! */ - Sub_Ctor(&self->network_configuration.pre_subject, self->base_ptr->ucs_user_ptr); - Sub_Ctor(&self->network_configuration.subject, self->base_ptr->ucs_user_ptr); - - Srv_Ctor(&self->net_srv, NET_SRV_PRIO, self, &Net_Service); /* Initialize Network Management service */ - (void)Scd_AddService(&self->base_ptr->scd, &self->net_srv); /* Add NET service to scheduler */ -} - -/*! \brief Service function of the network management. - * \param self Instance pointer - */ -static void Net_Service(void *self) -{ - CNetworkManagement *self_ = (CNetworkManagement *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->net_srv, &event_mask); - /* Notification of MOST Network Status triggered? */ - if((event_mask & NET_EVENT_NOTIFY_NW_STATUS) == NET_EVENT_NOTIFY_NW_STATUS) - { - Srv_ClearEvent(&self_->net_srv, NET_EVENT_NOTIFY_NW_STATUS); - self_->network_status.param.change_mask = 0xFFFFU; - Sub_Notify(&self_->network_status.pre_subject, &self_->network_status.param); - self_->network_status.param.change_mask = 0U; - (void)Sub_SwitchObservers(&self_->network_status.subject, - &self_->network_status.pre_subject); - } - /* Notification of MOST Network Configuration triggered? */ - if((event_mask & NET_EVENT_NOTIFY_NW_CONFIG) == NET_EVENT_NOTIFY_NW_CONFIG) - { - Srv_ClearEvent(&self_->net_srv, NET_EVENT_NOTIFY_NW_CONFIG); - self_->network_configuration.param.change_mask = 0xFFFFU; - Sub_Notify(&self_->network_configuration.pre_subject, &self_->network_configuration.param); - self_->network_configuration.param.change_mask = 0U; - (void)Sub_SwitchObservers(&self_->network_configuration.subject, - &self_->network_configuration.pre_subject); - } -} - -/*! \brief Adds an observer which is called if the network status has been changed. - * \param self Instance pointer - * \param obs_ptr Reference to an observer - */ -void Net_AddObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr) -{ - (void)Msub_AddObserver(&self->network_status.pre_subject, obs_ptr); - Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_STATUS); -} - -/*! \brief Removes an observer registered by Net_AddObserverNetworkStatus(). - * \param self Instance pointer - * \param obs_ptr Reference to observer to be removed - - */ -void Net_DelObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr) -{ - (void)Msub_RemoveObserver(&self->network_status.pre_subject, obs_ptr); - (void)Msub_RemoveObserver(&self->network_status.subject, obs_ptr); -} - -/*! \brief Adds an observer which is called if the network configuration has been changed. - * \param self Instance pointer - * \param obs_ptr Reference to an observer - */ -void Net_AddObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr) -{ - (void)Msub_AddObserver(&self->network_configuration.pre_subject, obs_ptr); - Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_CONFIG); -} - -/*! \brief Removes an observer registered by Net_AddObserverNetworkConfig(). - * \param self Instance pointer - * \param obs_ptr Reference to observer to be removed - */ -void Net_DelObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr) -{ - (void)Msub_RemoveObserver(&self->network_configuration.pre_subject, obs_ptr); - (void)Msub_RemoveObserver(&self->network_configuration.subject, obs_ptr); -} - -/*! \brief Observer callback used for the MOST Network Status - * \param self Instance pointer - * \param data_ptr Reference to the data structure - */ -static void Net_UpdateNetworkStatus(void *self, void *data_ptr) -{ - Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr; - - if(data_ptr_->result.code == UCS_RES_SUCCESS) - { - CNetworkManagement *self_ = (CNetworkManagement *)self; - Inic_NetworkStatus_t result = *((Inic_NetworkStatus_t *)data_ptr_->data_info); - - /* Check for changes */ - if(result.events != 0U) /* Notify only if at least one event flag is set */ - { - self_->network_status.param.change_mask |= 0x0001U; - } - if(self_->network_status.param.availability != result.availability) - { - self_->network_status.param.change_mask |= 0x0002U; - } - if(self_->network_status.param.avail_info != result.avail_info) - { - self_->network_status.param.change_mask |= 0x0004U; - } - if(self_->network_status.param.avail_trans_cause != result.avail_trans_cause) - { - self_->network_status.param.change_mask |= 0x0008U; - } - if(self_->network_status.param.node_address != result.node_address) - { - self_->network_status.param.change_mask |= 0x0010U; - } - if(self_->network_status.param.node_position != result.node_position) - { - self_->network_status.param.change_mask |= 0x0020U; - } - if(self_->network_status.param.max_position != result.max_position) - { - self_->network_status.param.change_mask |= 0x0040U; - } - if(self_->network_status.param.packet_bw != result.packet_bw) - { - self_->network_status.param.change_mask |= 0x0080U; - } - - /* Update MOST Network Status parameters */ - self_->network_status.param.events = result.events; - self_->network_status.param.availability = result.availability; - self_->network_status.param.avail_info = result.avail_info; - self_->network_status.param.avail_trans_cause = result.avail_trans_cause; - self_->network_status.param.node_address = result.node_address; - self_->network_status.param.node_position = result.node_position; - self_->network_status.param.max_position = result.max_position; - self_->network_status.param.packet_bw = result.packet_bw; - - /* Notify observer? */ - Msub_Notify(&self_->network_status.subject, - &self_->network_status.param, - (uint32_t)self_->network_status.param.change_mask); - - /* Clear change-mask */ - self_->network_status.param.change_mask = 0U; - } -} - -/*! \brief Observer callback used for the MOST Network Configuration - * \param self Instance pointer - * \param data_ptr Reference to the data structure - */ -static void Net_UpdateNetworkConfiguration(void *self, void *data_ptr) -{ - Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr; - - if(data_ptr_->result.code == UCS_RES_SUCCESS) - { - CNetworkManagement *self_ = (CNetworkManagement *)self; - Inic_NetworkConfig_t result = *((Inic_NetworkConfig_t *)data_ptr_->data_info); - - /* Check for changes */ - if(self_->network_configuration.param.node_address != result.node_address) - { - self_->network_configuration.param.change_mask |= 0x0001U; - } - if(self_->network_configuration.param.group_address != result.group_address) - { - self_->network_configuration.param.change_mask |= 0x0002U; - } - if(self_->network_configuration.param.llrbc != result.llrbc) - { - self_->network_configuration.param.change_mask |= 0x0004U; - } - - /* Update MOST Network Configuration parameters */ - self_->network_configuration.param.node_address = result.node_address; - self_->network_configuration.param.group_address = result.group_address; - self_->network_configuration.param.llrbc = result.llrbc; - - /* Notify observer? */ - Msub_Notify(&self_->network_configuration.subject, - &self_->network_configuration.param, - (uint32_t)self_->network_configuration.param.change_mask); - - /* Clear change-mask */ - self_->network_configuration.param.change_mask = 0U; - } -} - -/*! \brief Checks if the given address matches with the own node address, node position or group address. - * \param self Instance pointer - * \param address Address to be checked - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------- | ------------------------------------------------------------- - * NET_IS_OWN_ADDR_NODE | Is own node position address or own logical node address - * NET_IS_OWN_ADDR_GROUP | Is own group address - * NET_IS_OWN_ADDR_NONE | Is foreign address - */ -Net_IsOwnAddrResult_t Net_IsOwnAddress(CNetworkManagement *self, uint16_t address) -{ - Net_IsOwnAddrResult_t ret_val; - - if((self->network_status.param.node_address == address) || - (((uint16_t)self->network_status.param.node_position + (uint16_t)0x400) == address)) - { - ret_val = NET_IS_OWN_ADDR_NODE; - } - else if(self->network_configuration.param.group_address == address) - { - ret_val = NET_IS_OWN_ADDR_GROUP; - } - else - { - ret_val = NET_IS_OWN_ADDR_NONE; - } - - return ret_val; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_nodedis.c b/ucs2-lib/src/ucs_nodedis.c deleted file mode 100644 index b9f2f5a..0000000 --- a/ucs2-lib/src/ucs_nodedis.c +++ /dev/null @@ -1,1038 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Discovery. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_NODE_DIS - * @{ - - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_inic_pb.h" -#include "ucs_nodedis.h" -#include "ucs_misc.h" - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -#define ND_NUM_STATES 5U /*!< \brief Number of state machine states */ -#define ND_NUM_EVENTS 14U /*!< \brief Number of state machine events */ - -#define ND_TIMEOUT_PERIODIC 5000U /*!< \brief 5s timeout */ -#define ND_TIMEOUT_COMMAND 300U /*!< \brief supervise EXC commands */ - -#define ND_SIGNATURE_VERSION 1U /*!< \brief signature version used for Node Discovery */ - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the Node Discovery service used by scheduler */ -static const uint8_t ND_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the Node Discovery service */ -static const Srv_Event_t ND_EVENT_SERVICE = 1U; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal enumerators */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Possible events of the Node Discovery state machine */ -typedef enum Nd_Events_ -{ - ND_E_NIL = 0U, /*!< \brief NIL Event */ - ND_E_START = 1U, /*!< \brief API start command was called. */ - ND_E_STOP = 2U, /*!< \brief Stop request occurred. */ - ND_E_CHECK = 3U, /*!< \brief Check conditions in CHECK_HELLO state. */ - ND_E_NET_OFF = 4U, /*!< \brief NetOff occurred. */ - ND_E_HELLO_STATUS = 5U, /*!< \brief Hello.Status message available to be processed. */ - ND_E_RES_NODE_OK = 6U, /*!< \brief Evaluation result of node: ok. */ - ND_E_RES_UNKNOWN = 7U, /*!< \brief Evaluation result of node: unknown node. */ - ND_E_RES_CHECK_UNIQUE = 8U, /*!< \brief Evaluation result of node: check if node is unique. */ - ND_E_WELCOME_SUCCESS = 9U, /*!< \brief Welcome command was successful. */ - ND_E_WELCOME_NOSUCCESS = 10U, /*!< \brief Welcome command was not successful. */ - ND_E_SIGNATURE_SUCCESS = 11U, /*!< \brief Signature command was successful. */ - ND_E_TIMEOUT = 12U, /*!< \brief Timeout occurred. */ - ND_E_ERROR = 13U /*!< \brief An unexpected error occurred. */ - -} Nd_Events_t; - - -/*! \brief States of the Node Discovery state machine */ -typedef enum Nd_State_ -{ - ND_S_IDLE = 0U, /*!< \brief Idle state */ - ND_S_CHECK_HELLO = 1U, /*!< \brief Node Discovery started */ - ND_S_WAIT_EVAL = 2U, /*!< \brief Evaluate next Hello.Status message */ - ND_S_WAIT_WELCOME = 3U, /*!< \brief Wait for Welcome.Status */ - ND_S_WAIT_PING = 4U /*!< \brief Wait for Signature.Status */ -} Nd_State_t; - - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Nd_Service(void *self); - -static void Nd_HelloStatusCb(void *self, void *result_ptr); -static void Nd_WelcomeResultCb(void *self, void *result_ptr); -static void Nd_SignatureStatusCb(void *self, void *result_ptr); -static void Nd_InitCb(void *self, void *result_ptr); -static void Nd_TimerCb(void *self); -static void Nd_OnTerminateEventCb(void *self, void *result_ptr); -static void Nd_NetworkStatusCb(void *self, void *result_ptr); - -static void Nd_Reset_Lists(void *self); - -static void Nd_A_Start(void *self); -static void Nd_A_Stop(void *self); -static void Nd_A_CheckConditions(void *self); -static void Nd_A_Eval_Hello(void *self); -static void Nd_A_Welcome(void *self); -static void Nd_A_Unknown(void *self); -static void Nd_A_CheckUnique(void *self); -static void Nd_A_WelcomeSuccess(void *self); -static void Nd_A_WelcomeNoSuccess(void *self); -static void Nd_A_WelcomeTimeout(void *self); -static void Nd_A_Timeout_Hello(void *self); -static void Nd_A_NetOff(void *self); -static void Nd_A_Signature_Timeout(void *self); -static void Nd_A_Signature_Success(void *self); -static void Nd_A_Error(void *self); - -static void Nd_Send_Hello_Get(void *self); -static void Nd_Start_Periodic_Timer(void *self); -static void Nd_Send_Welcome_SR(void *self, Ucs_Signature_t *signature); -static void Nd_Send_Signature_Get(void *self, uint16_t target_address); - - -/*------------------------------------------------------------------------------------------------*/ -/* State transition table (used by finite state machine) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief State transition table */ -static const Fsm_StateElem_t nd_trans_tab[ND_NUM_STATES][ND_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - { /* State ND_S_IDLE */ - /* ND_E_NIL */ {NULL, ND_S_IDLE }, - /* ND_E_START */ {&Nd_A_Start, ND_S_CHECK_HELLO }, - /* ND_E_STOP */ {NULL, ND_S_IDLE }, - /* ND_E_CHECK */ {NULL, ND_S_IDLE }, - /* ND_E_NET_OFF */ {NULL, ND_S_IDLE }, - /* ND_E_HELLO_STATUS */ {NULL, ND_S_IDLE }, - /* ND_E_RES_NODE_OK */ {NULL, ND_S_IDLE }, - /* ND_E_RES_UNKNOWN */ {NULL, ND_S_IDLE }, - /* ND_E_RES_CHECK_UNIQUE */ {NULL, ND_S_IDLE }, - /* ND_E_WELCOME_SUCCESS */ {NULL, ND_S_IDLE }, - /* ND_E_WELCOME_NOSUCCESS */ {NULL, ND_S_IDLE }, - /* ND_E_SIGNATURE_SUCCESS */ {NULL, ND_S_IDLE }, - /* ND_E_TIMEOUT */ {NULL, ND_S_IDLE }, - /* ND_E_ERROR */ {NULL, ND_S_IDLE } - - }, - { /* State ND_S_CHECK_HELLO */ - /* ND_E_NIL */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_START */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_STOP */ {&Nd_A_Stop, ND_S_IDLE }, - /* ND_E_CHECK */ {&Nd_A_CheckConditions, ND_S_CHECK_HELLO }, - /* ND_E_NET_OFF */ {&Nd_A_NetOff, ND_S_CHECK_HELLO }, - /* ND_E_HELLO_STATUS */ {&Nd_A_Eval_Hello, ND_S_WAIT_EVAL }, - /* ND_E_RES_NODE_OK */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_RES_UNKNOWN */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_RES_CHECK_UNIQUE */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_WELCOME_SUCCESS */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_WELCOME_NOSUCCESS */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_SIGNATURE_SUCCESS */ {NULL, ND_S_CHECK_HELLO }, - /* ND_E_TIMEOUT */ {&Nd_A_Timeout_Hello, ND_S_CHECK_HELLO }, - /* ND_E_ERROR */ {&Nd_A_Error, ND_S_IDLE } - }, - { /* State ND_S_WAIT_EVAL */ - /* ND_E_NIL */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_START */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_STOP */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_CHECK */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_NET_OFF */ {&Nd_A_NetOff, ND_S_CHECK_HELLO }, - /* ND_E_HELLO_STATUS */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_RES_NODE_OK */ {&Nd_A_Welcome, ND_S_WAIT_WELCOME }, - /* ND_E_RES_UNKNOWN */ {&Nd_A_Unknown, ND_S_CHECK_HELLO }, - /* ND_E_RES_CHECK_UNIQUE */ {&Nd_A_CheckUnique, ND_S_WAIT_PING }, - /* ND_E_WELCOME_SUCCESS */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_WELCOME_NOSUCCESS */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_SIGNATURE_SUCCESS */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_TIMEOUT */ {NULL, ND_S_WAIT_EVAL }, - /* ND_E_ERROR */ {&Nd_A_Error, ND_S_IDLE } - }, - - {/* ND_S_WAIT_WELCOME */ - /* ND_E_NIL */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_START */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_STOP */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_CHECK */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_NET_OFF */ {&Nd_A_NetOff, ND_S_CHECK_HELLO }, - /* ND_E_HELLO_STATUS */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_RES_NODE_OK */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_RES_UNKNOWN */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_RES_CHECK_UNIQUE */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_WELCOME_SUCCESS */ {&Nd_A_WelcomeSuccess, ND_S_CHECK_HELLO }, - /* ND_E_WELCOME_NOSUCCESS */ {&Nd_A_WelcomeNoSuccess, ND_S_CHECK_HELLO }, - /* ND_E_SIGNATURE_SUCCESS */ {NULL, ND_S_WAIT_WELCOME }, - /* ND_E_TIMEOUT */ {&Nd_A_WelcomeTimeout, ND_S_CHECK_HELLO }, - /* ND_E_ERROR */ {&Nd_A_Error, ND_S_IDLE } - }, - {/* ND_S_WAIT_PING */ - /* ND_E_NIL */ {NULL, ND_S_WAIT_PING }, - /* ND_E_START */ {NULL, ND_S_WAIT_PING }, - /* ND_E_STOP */ {NULL, ND_S_WAIT_PING }, - /* ND_E_CHECK */ {NULL, ND_S_WAIT_PING }, - /* ND_E_NET_OFF */ {&Nd_A_NetOff, ND_S_CHECK_HELLO }, - /* ND_E_HELLO_STATUS */ {NULL, ND_S_WAIT_PING }, - /* ND_E_RES_NODE_OK */ {NULL, ND_S_WAIT_PING }, - /* ND_E_RES_UNKNOWN */ {NULL, ND_S_WAIT_PING }, - /* ND_E_RES_CHECK_UNIQUE */ {NULL, ND_S_WAIT_PING }, - /* ND_E_WELCOME_SUCCESS */ {NULL, ND_S_WAIT_PING }, - /* ND_E_WELCOME_NOSUCCESS */ {NULL, ND_S_WAIT_PING }, - /* ND_E_SIGNATURE_SUCCESS */ {&Nd_A_Signature_Success, ND_S_CHECK_HELLO }, - /* ND_E_TIMEOUT */ {&Nd_A_Signature_Timeout, ND_S_WAIT_WELCOME }, - /* ND_E_ERROR */ {&Nd_A_Error, ND_S_IDLE } - } -}; - - - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CNodeDiscovery. - * \param self Reference to CNodeDiscovery instance - * \param inic Reference to CInic instance - * \param base Reference to CBase instance - * \param exc Reference to CExc instance - * \param init_ptr Report callback function - */ -void Nd_Ctor(CNodeDiscovery *self, CInic *inic, CBase *base, CExc *exc, Nd_InitData_t *init_ptr) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->inic = inic; - self->exc = exc; - self->base = base; - self->cb_inst_ptr = init_ptr->inst_ptr; - self->report_fptr = init_ptr->report_fptr; - self->eval_fptr = init_ptr->eval_fptr; - - Fsm_Ctor(&self->fsm, self, &(nd_trans_tab[0][0]), ND_NUM_EVENTS, ND_E_NIL); - - Nd_Reset_Lists(self); - - Sobs_Ctor(&self->nd_hello, self, &Nd_HelloStatusCb); - Sobs_Ctor(&self->nd_welcome, self, &Nd_WelcomeResultCb); - Sobs_Ctor(&self->nd_signature, self, &Nd_SignatureStatusCb); - Sobs_Ctor(&self->nd_init, self, &Nd_InitCb); - - /* register termination events */ - Mobs_Ctor(&self->nd_terminate, self, EH_M_TERMINATION_EVENTS, &Nd_OnTerminateEventCb); - Eh_AddObsrvInternalEvent(&self->base->eh, &self->nd_terminate); - - /* Register NetOn and MPR events */ - Obs_Ctor(&self->nd_nwstatus, self, &Nd_NetworkStatusCb); - Inic_AddObsrvNwStatus(self->inic, &self->nd_nwstatus); - self->neton = false; - - /* Initialize Node Discovery service */ - Srv_Ctor(&self->service, ND_SRV_PRIO, self, &Nd_Service); - /* Add Node Discovery service to scheduler */ - (void)Scd_AddService(&self->base->scd, &self->service); - -} - - -/*! \brief Service function of the Node Discovery service. - * \param self Reference to Node Discovery object - */ -static void Nd_Service(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->service, &event_mask); - if(ND_EVENT_SERVICE == (event_mask & ND_EVENT_SERVICE)) /* Is event pending? */ - { - Fsm_State_t result; - Srv_ClearEvent(&self_->service, ND_EVENT_SERVICE); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); - result = Fsm_Service(&self_->fsm); - TR_ASSERT(self_->base->ucs_user_ptr, "[ND]", (result != FSM_STATE_ERROR)); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "FSM -> %d", 1U, self_->fsm.current_state)); - MISC_UNUSED(result); - } -} - - - -/**************************************************************************************************/ -/* API functions */ -/**************************************************************************************************/ -/*! \brief Start the Node Discovery - * - * \param *self Reference to Node Discovery object - * \return UCS_RET_SUCCESS Operation successful - * \return UCS_RET_ERR_API_LOCKED Node Discovery was already started - */ -Ucs_Return_t Nd_Start(CNodeDiscovery *self) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - - if (self->running == false) - { - Fsm_SetEvent(&self->fsm, ND_E_START); - Srv_SetEvent(&self->service, ND_EVENT_SERVICE); - self->running = true; - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_Start", 0U)); - } - else - { - ret_val = UCS_RET_ERR_API_LOCKED; - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_Start failed", 0U)); - } - - return ret_val; - - - - -} - -/*! \brief Stops the Node Discovery - * - * \param *self Reference to Node Discovery object - * \return UCS_RET_SUCCESS Operation successful - * \return UCS_RET_ERR_NOT_AVAILABLE Node Discovery not running - */ -Ucs_Return_t Nd_Stop(CNodeDiscovery *self) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - if (self->running == true) /* check if Node Discovery was started */ - { - self->stop_request = true; - Fsm_SetEvent(&self->fsm, ND_E_CHECK); - Srv_SetEvent(&self->service, ND_EVENT_SERVICE); - - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_Stop", 0U)); - } - else - { - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_Stop failed", 0U)); - } - - return ret_val; -} - - -/*! \brief Sends the Init command to all nodes - * - * \param *self Reference to Node Discovery object - */ -void Nd_InitAll(CNodeDiscovery *self) -{ - Ucs_Return_t result; - - result = Exc_DeviceInit_Start(self->exc, UCS_ADDR_BROADCAST_BLOCKING, NULL); - if (result == UCS_RET_SUCCESS) - { - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_InitAll", 0U)); - } - else - { - TR_INFO((self->base->ucs_user_ptr, "[ND]", "Nd_InitAll failed", 0U)); - } - -} - - - - -/**************************************************************************************************/ -/* FSM Actions */ -/**************************************************************************************************/ -/*! \brief Action on start event - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Start(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - /* empty new_list*/ - Nd_Reset_Lists(self_); - - Nd_Send_Hello_Get(self_); - - Nd_Start_Periodic_Timer(self_); - - self_->stop_request = false; - self_->hello_mpr_request = false; - self_->hello_neton_request = false; -} - -/*! \brief Action on stop event - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Stop(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t *dummy = NULL; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_STOPPED, dummy); - } - self_->running = false; -} - -/*! \brief Check conditions - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_CheckConditions(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - if (self_->stop_request == true) - { - Fsm_SetEvent(&self_->fsm, ND_E_STOP); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); - } - else if (self_->hello_mpr_request == true) - { - Nd_Reset_Lists(self_); - Nd_Send_Hello_Get(self_); - Nd_Start_Periodic_Timer(self_); - self_->hello_mpr_request = false; - self_->hello_neton_request = false; - } - else if (self_->hello_neton_request == true) - { - Nd_Send_Hello_Get(self_); - Nd_Start_Periodic_Timer(self_); - self_->hello_neton_request = false; - } - else if (Dl_GetSize(&(self_->new_list)) > 0U) - { - Fsm_SetEvent(&self_->fsm, ND_E_HELLO_STATUS); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); - } - else - { - Nd_Start_Periodic_Timer(self_); - } - -} - - -/*! \brief Evaluate the signature of the next node - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Eval_Hello(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - CDlNode *node; - Ucs_Nd_CheckResult_t result; - bool service_flag = false; - Ucs_Signature_t temp_sig; - - if (Dl_GetSize(&(self_->new_list)) > 0U) - { - node = Dl_PopHead(&(self_->new_list)); - self_->current_sig = *((Ucs_Signature_t *)(node->data_ptr)); - - if (self_->eval_fptr != NULL) - { - temp_sig = self_->current_sig; /* provide only a copy to the application */ - result = self_->eval_fptr(self_->cb_inst_ptr, &temp_sig); - - switch (result) - { - case UCS_ND_CHK_UNKNOWN: - Fsm_SetEvent(&self_->fsm, ND_E_RES_UNKNOWN); - service_flag = true; - break; - - case UCS_ND_CHK_WELCOME: - Fsm_SetEvent(&self_->fsm, ND_E_RES_NODE_OK); - service_flag = true; - break; - - case UCS_ND_CHK_UNIQUE: - Fsm_SetEvent(&self_->fsm, ND_E_RES_CHECK_UNIQUE); - service_flag = true; - break; - - default: - Fsm_SetEvent(&self_->fsm, ND_E_ERROR); - service_flag = true; - break; - } - } - } - - if (service_flag == true) - { - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); - } -} - - -/*! \brief Sends a Welcome message to the current node - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Welcome(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Nd_Send_Welcome_SR(self, &self_->current_sig); -} - - -/*! \brief Report the current node as unknown - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Unknown(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t temp_sig; - - if (self_->report_fptr != NULL) - { - temp_sig = self_->current_sig; /* provide only a copy to the application */ - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_UNKNOWN, &temp_sig); - } - - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - -/*! \brief Check if the current node has already got a Welcome message - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_CheckUnique(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Nd_Send_Signature_Get(self, self_->current_sig.node_address); - -} - - -/*! \brief Report a successful Welcome.Result - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_WelcomeSuccess(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t temp_sig; - - if (self_->report_fptr != NULL) - { - temp_sig = self_->current_sig; /* provide only a copy to the application */ - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_WELCOME_SUCCESS, &temp_sig); - } - - /* initiate a Hello.Get if the current node is the local INIC */ - if (self_->current_sig.node_pos_addr == 0x0400U) - { - Nd_Send_Hello_Get(self_); - Nd_Start_Periodic_Timer(self_); - } - - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief Report an unsuccessful Welcome.Result - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_WelcomeNoSuccess(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - /* same reaction as for MPR event */ - self_->hello_mpr_request = true; - - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief Reaction on a timeout for the Welcome messsage - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_WelcomeTimeout(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - /* same reaction as for MPR event */ - self_->hello_mpr_request = true; - - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief The periodic timer elapsed - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Timeout_Hello(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Nd_Send_Hello_Get(self_); - Nd_Start_Periodic_Timer(self_); -} - - -/*! \brief Reaction on a NetOff event - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_NetOff(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t *dummy = NULL; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_NETOFF, dummy); - } - - Nd_Reset_Lists(self_); - -} - - -/*! \brief Reaction on a timeout of the Signature command - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Signature_Timeout(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Nd_Send_Welcome_SR(self, &self_->current_sig); -} - - -/*! \brief Reaction on a successful Signature answer - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Signature_Success(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t temp_sig; - - if (self_->report_fptr != NULL) - { - temp_sig = self_->current_sig; /* provide only a copy to the application */ - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_MULTI, &temp_sig); - } -} - - -/*! \brief An unecpected error occurred - * - * \param *self Reference to Node Discovery object - */ -static void Nd_A_Error(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t *dummy = NULL; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_ERROR, dummy); - } - self_->running = false; -} - - -/**************************************************************************************************/ -/* Callback functions */ -/**************************************************************************************************/ - -/*! Callback function for the Exc.Hello.Status message - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Result of the Exc_Hello_Get() command - */ -static void Nd_HelloStatusCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - CDlNode *node; - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - /* read signature and store it in the new_list */ - node = Dl_PopHead(&(self_->unused_list)); /* get an unused list element */ - if (node != NULL) - { - ((Nd_Node *)(node->data_ptr))->signature = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).signature; - Dl_InsertTail(&(self_->new_list), node); - - Fsm_SetEvent(&self_->fsm, ND_E_HELLO_STATUS); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_HelloStatusCb UCS_RES_SUCCESS", 0U)); - } - else - { - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_HelloStatusCb No list entry av.", 0U)); - } - } - else - { - Fsm_SetEvent(&self_->fsm, ND_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_HelloStatusCb ND_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief Function is called on reception of the Welcome.Result messsage - * \param self Reference to Node Discovery object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Nd_WelcomeResultCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - /* read signature and store it */ - self_->welcome_result = *(Exc_WelcomeResult_t *)(result_ptr_->data_info); - if (self_->welcome_result.res == EXC_WELCOME_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, ND_E_WELCOME_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_WelcomeResultCb ND_E_WELCOME_SUCCESS", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, ND_E_WELCOME_NOSUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_WelcomeResultCb ND_E_WELCOME_NOSUCCESS", 0U)); - } - } - else - { - uint8_t i; - - if ( (result_ptr_->result.info_size == 3U) - && (result_ptr_->result.info_ptr[0] == 0x20U) - && (result_ptr_->result.info_ptr[1] == 0x03U) - && (result_ptr_->result.info_ptr[2] == 0x31U)) - { /* Device has not yet received an ExtendedNetworkControl.Hello.Get() message. */ - Fsm_SetEvent(&self_->fsm, ND_E_WELCOME_NOSUCCESS); - } - else - { - Fsm_SetEvent(&self_->fsm, ND_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_WelcomeResultCb Error (code) 0x%x", 1U, result_ptr_->result.code)); - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_WelcomeResultCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i])); - } - } - } - - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief Callback function for Signature status and error messages - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Pointer to the result of the Signature message - */ -static void Nd_SignatureStatusCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - self_->signature_status = *(Exc_SignatureStatus_t *)(result_ptr_->data_info); - Fsm_SetEvent(&self_->fsm, ND_E_SIGNATURE_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_SignatureStatusCb ND_E_SIGNATURE_SUCCESS", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, ND_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_SignatureStatusCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! \brief Callback function for Init error messages - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Pointer to the result of the Init message - */ -static void Nd_InitCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - MISC_UNUSED(self_); - MISC_UNUSED(result_ptr_); - -} - - -/*! \brief Timer callback used for supervising INIC command timeouts. - * \param self Reference to Node Discovery object - */ -static void Nd_TimerCb(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Fsm_SetEvent(&self_->fsm, ND_E_TIMEOUT); - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_TimerCb ND_E_TIMEOUT", 0U)); - - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - -/*! Function is called on severe internal errors - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Reference to data - */ -static void Nd_OnTerminateEventCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Ucs_Signature_t *dummy = NULL; - - MISC_UNUSED(result_ptr); - - if (self_->fsm.current_state != ND_S_IDLE) - { - Tm_ClearTimer(&self_->base->tm, &self_->timer); - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->cb_inst_ptr, UCS_ND_RES_ERROR, dummy); - } - Nd_Reset_Lists(self_); - } -} - - -/*! \brief Callback function for the INIC.NetworkStatus status and error messages - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Pointer to the result of the INIC.NetworkStatus message - */ -static void Nd_NetworkStatusCb(void *self, void *result_ptr) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Nd_NetworkStatusCb 0x%x", 1U, result_ptr_->result.code)); - /* check for NetOn/NetOff events */ - if ( (self_->neton == true) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) ) - { - self_->neton = false; - Fsm_SetEvent(&self_->fsm, ND_E_NET_OFF); - } - /* check for NetOn/NetOff events */ - else if ( (self_->neton == false) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) ) - { - self_->neton = true; - self_->hello_neton_request = true; - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - } - /* check for MPR event */ - else if ( (((Inic_NetworkStatus_t *)(result_ptr_->data_info))->events & UCS_NETWORK_EVENT_NCE) - == UCS_NETWORK_EVENT_NCE) - { - self_->hello_mpr_request = true; - Fsm_SetEvent(&self_->fsm, ND_E_CHECK); - } - } - - Srv_SetEvent(&self_->service, ND_EVENT_SERVICE); -} - - - -/**************************************************************************************************/ -/* Helper functions */ -/**************************************************************************************************/ -/*! \brief Reset the list of new detected nodes - * - * \param *self Reference to Node Discovery object - */ -static void Nd_Reset_Lists(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - uint16_t i; - - Dl_Ctor(&self_->new_list, self_->base->ucs_user_ptr); - Dl_Ctor(&self_->unused_list, self_->base->ucs_user_ptr); - - for(i=0U; i < ND_NUM_NODES; ++i) - { - Dln_Ctor(&(self_->nodes[i]).node, &(self_->nodes[i])); - Dl_InsertTail(&(self_->unused_list), &(self_->nodes[i]).node); - } -} - - -/*! \brief Send the Hello.Get message - * - * \param *self Reference to Node Discovery object - */ -static void Nd_Send_Hello_Get(void *self) -{ - Ucs_Return_t ret_val; - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - ret_val = Exc_Hello_Get(self_->exc, UCS_ADDR_BROADCAST_BLOCKING, - ND_SIGNATURE_VERSION, &self_->nd_hello); - - TR_ASSERT(self_->base->ucs_user_ptr, "[ND]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - - -/*! \brief Send the Welcome.StartResult message - * - * \param *self Reference to Node Discovery object - * \param *signature signature parameter - */ -static void Nd_Send_Welcome_SR(void *self, Ucs_Signature_t *signature) -{ - Ucs_Return_t ret_val; - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - uint16_t target_address; - - if (signature->node_pos_addr == 0x0400U) - { - target_address = 0x0001U; - } - else - { - target_address = signature->node_pos_addr; - } - - ret_val = Exc_Welcome_Sr(self_->exc, - target_address, - 0xFFFFU, - ND_SIGNATURE_VERSION, - *signature, - &self_->nd_welcome); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Nd_TimerCb, - self_, - ND_TIMEOUT_COMMAND, - 0U); - TR_ASSERT(self_->base->ucs_user_ptr, "[ND]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - - -/*! \brief Send the Signature.Get message - * - * \param *self Reference to Node Discovery object - * \param target_address target address for the command - */ -static void Nd_Send_Signature_Get(void *self, uint16_t target_address) -{ - Ucs_Return_t ret_val; - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - ret_val = Exc_Signature_Get(self_->exc, target_address, ND_SIGNATURE_VERSION, &self_->nd_signature); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Nd_TimerCb, - self_, - ND_TIMEOUT_COMMAND, - 0U); - TR_ASSERT(self_->base->ucs_user_ptr, "[ND]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - -/*! \brief Starts the periodic timer - * - * \param *self Reference to Node Discovery object - */ -static void Nd_Start_Periodic_Timer(void *self) -{ - CNodeDiscovery *self_ = (CNodeDiscovery *)self; - - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Nd_TimerCb, - self, - ND_TIMEOUT_PERIODIC, - 0U); -} - -/*! - * @} - * \endcond - */ - - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_nodeobserver.c b/ucs2-lib/src/ucs_nodeobserver.c deleted file mode 100644 index 5832e41..0000000 --- a/ucs2-lib/src/ucs_nodeobserver.c +++ /dev/null @@ -1,341 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 CNodeObserver class - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_NODEOBSERVER - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_nodeobserver.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -#define NOBS_ADDR_ADMIN_MIN 0xF80U /*!< \brief Start of address range to park unknown devices */ -#define NOBS_ADDR_ADMIN_MAX 0xFDFU /*!< \brief End of address range to park unknown devices */ - -#define NOBS_ADDR_RANGE1_MIN 0x200U /*!< \brief Start of first static address range */ -#define NOBS_ADDR_RANGE1_MAX 0x2FFU /*!< \brief End of first static address range */ -#define NOBS_ADDR_RANGE2_MIN 0x500U /*!< \brief Start of second static address range */ -#define NOBS_ADDR_RANGE2_MAX 0xEFFU /*!< \brief End of second static address range */ - -#define NOSB_JOIN_NO 0x00U -#define NOSB_JOIN_WAIT 0x01U -#define NOSB_JOIN_YES 0x02U - -#define NOBS_WAIT_TIME 200U /*!< \brief Wait time between node not_available -> available */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Nobs_OnInitComplete(void *self, void *error_code_ptr); -static void Nobs_OnWakeupTimer(void *self); -static bool Nobs_CheckAddrRange(CNodeObserver *self, Ucs_Signature_t *signature_ptr); -static void Nobs_InitAllNodes(CNodeObserver *self); -static void Nobs_InvalidateAllNodes(CNodeObserver *self); -static void Nobs_InvalidateNode(CNodeObserver *self, Ucs_Rm_Node_t *node_ptr); -static Ucs_Rm_Node_t* Nobs_GetNodeBySignature(CNodeObserver *self, Ucs_Signature_t *signature_ptr); -static void Nobs_NotifyApp(CNodeObserver *self, Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Class methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of NodeObserver class - * \param self The instance - * \param base_ptr Reference to base component - * \param nd_ptr Reference to NodeDiscovery component - * \param rtm_ptr Reference to RoutingManagement component - * \param init_ptr Reference to initialization data - */ -void Nobs_Ctor(CNodeObserver *self, CBase *base_ptr, CNodeDiscovery *nd_ptr, CRouteManagement *rtm_ptr, Ucs_Mgr_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->base_ptr = base_ptr; - self->nd_ptr = nd_ptr; - self->rtm_ptr = rtm_ptr; - if (init_ptr != NULL) - { - self->init_data = *init_ptr; - } - Nobs_InitAllNodes(self); - T_Ctor(&self->wakeup_timer); - - Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Nobs_OnInitComplete); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer); -} - -/*! \brief Callback function which is invoked if the initialization is complete - * \param self The instance - * \param error_code_ptr Reference to the error code - */ -static void Nobs_OnInitComplete(void *self, void *error_code_ptr) -{ - CNodeObserver *self_ = (CNodeObserver*)self; - MISC_UNUSED(error_code_ptr); - - (void)Nd_Start(self_->nd_ptr); - (void)Rtm_StartProcess(self_->rtm_ptr, self_->init_data.routes_list_ptr, self_->init_data.routes_list_size); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Callback Methods */ -/*------------------------------------------------------------------------------------------------*/ -Ucs_Nd_CheckResult_t Nobs_OnNdEvaluate(void *self, Ucs_Signature_t *signature_ptr) -{ - CNodeObserver *self_ = (CNodeObserver*)self; - Ucs_Rm_Node_t *node_ptr = NULL; - Ucs_Nd_CheckResult_t ret = UCS_ND_CHK_UNKNOWN; /* ignore by default */ - - if (signature_ptr != NULL) - { - if (Nobs_CheckAddrRange(self_, signature_ptr) != false) - { - node_ptr = Nobs_GetNodeBySignature(self_, signature_ptr); - - if (node_ptr != NULL) - { - if (node_ptr->internal_infos.mgr_joined == NOSB_JOIN_NO) - { - ret = UCS_ND_CHK_WELCOME; /* welcome new node */ - } - else if (node_ptr->internal_infos.mgr_joined == NOSB_JOIN_YES) - { - ret = UCS_ND_CHK_UNIQUE; /* node already available - check for reset */ - } - /* else if (node_ptr->internal_infos.mgr_joined == NOSB_JOIN_WAIT) --> ignore waiting nodes */ - /* future version compare node position to improve handling */ - } - } - - self_->eval_signature = *signature_ptr; - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdEvaluate(): node=0x%03X, node_pos=0x%03X, ret=0x%02X", 2U, signature_ptr->node_address, signature_ptr->node_pos_addr, ret)); - } - else - { - MISC_MEM_SET(&self_->eval_signature, 0, sizeof(self_->eval_signature)); /* reset signature */ - TR_FAILED_ASSERT(self_->base_ptr->ucs_user_ptr, "[NOBS]"); /* signature missing - it is evident for evaluation */ - } - - self_->eval_node_ptr = node_ptr; - self_->eval_action = ret; - - if ((ret == UCS_ND_CHK_UNKNOWN) && (signature_ptr != NULL)) /* notify unknown node */ - { - Nobs_NotifyApp(self_, UCS_MGR_REP_IGNORED_UNKNOWN, signature_ptr->node_address, NULL); - } - - return ret; -} - -void Nobs_OnNdReport(void *self, Ucs_Nd_ResCode_t code, Ucs_Signature_t *signature_ptr) -{ - CNodeObserver *self_ = (CNodeObserver*)self; - Ucs_Rm_Node_t *node_ptr = NULL; - - if (signature_ptr != NULL) - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): code=0x%02X, node=0x%03X, node_pos=0x%03X", 3U, code, signature_ptr->node_address, signature_ptr->node_pos_addr)); - node_ptr = Nobs_GetNodeBySignature(self_, signature_ptr); - if (node_ptr != self_->eval_node_ptr) /* if signature available -> expecting the same node_ptr as previously announced in Nobs_OnNdEvaluate */ - { - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): sanity check failed node_ptr=%p, eval_node_ptr=%p", 2U, node_ptr, self_->eval_node_ptr)); - node_ptr = NULL; /* do not handle node */ - } - } - else - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): code=0x%02X", 1U, code)); - } - - if (code == UCS_ND_RES_NETOFF) - { - Nobs_InvalidateAllNodes(self_); - } - else if (node_ptr == NULL) - { - /* no not handle events with unspecified node */ - } - else if ((code == UCS_ND_RES_WELCOME_SUCCESS) && (self_->eval_action == UCS_ND_CHK_WELCOME)) /* is new node? */ - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): welcome of new node=0x%03X", 1U, signature_ptr->node_address)); - node_ptr->internal_infos.mgr_joined = NOSB_JOIN_YES; - (void)Rtm_SetNodeAvailable(self_->rtm_ptr, node_ptr, true); - Nobs_NotifyApp(self_, UCS_MGR_REP_AVAILABLE, signature_ptr->node_address, node_ptr); - } - else if ((code == UCS_ND_RES_WELCOME_SUCCESS) && (self_->eval_action == UCS_ND_CHK_UNIQUE)) /* is node that previously joined */ - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): welcome of existing node=0x%03X (RESET -> not_available)", 1U, signature_ptr->node_address)); - node_ptr->internal_infos.mgr_joined = NOSB_JOIN_WAIT; - (void)Rtm_SetNodeAvailable(self_->rtm_ptr, node_ptr, false); - Nobs_NotifyApp(self_, UCS_MGR_REP_NOT_AVAILABLE, signature_ptr->node_address, node_ptr); - (void)Nd_Stop(self_->nd_ptr); /* stop node discovery and restart after timeout, */ - Tm_SetTimer(&self_->base_ptr->tm, &self_->wakeup_timer, &Nobs_OnWakeupTimer, /* transition from node not_available -> available */ - self, /* needs some time and no callback is provided. */ - NOBS_WAIT_TIME, - 0U - ); - } - else if ((code == UCS_ND_RES_MULTI) && (self_->eval_action == UCS_ND_CHK_UNIQUE)) /* is node that causes address conflict */ - { - /* just ignore */ - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): ignoring duplicate node=0x%03X", 1U, signature_ptr->node_address)); - Nobs_NotifyApp(self_, UCS_MGR_REP_IGNORED_DUPLICATE, signature_ptr->node_address, NULL); - } - else if (code == UCS_ND_RES_UNKNOWN) - { - /* just ignore */ - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): ignoring unknown node=0x%03X", 1U, signature_ptr->node_address)); - } - else - { - /* just ignore */ - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnNdReport(): ignoring node in unexpected, node=0x%03X, code=0x02X ", 2U, signature_ptr->node_address, code)); - } -} - -static void Nobs_OnWakeupTimer(void *self) -{ - CNodeObserver *self_ = (CNodeObserver*)self; - - if (self_->eval_node_ptr != NULL) - { - if (self_->eval_node_ptr->internal_infos.mgr_joined == NOSB_JOIN_WAIT) - { - TR_INFO((self_->base_ptr->ucs_user_ptr, "[NOBS]", "Nobs_OnWakeupTimer(): welcome of existing node 0x%03X (RESET -> available)", 1U, self_->eval_node_ptr->signature_ptr->node_address)); - self_->eval_node_ptr->internal_infos.mgr_joined = NOSB_JOIN_YES; - (void)Rtm_SetNodeAvailable(self_->rtm_ptr, self_->eval_node_ptr, true); - Nobs_NotifyApp(self_, UCS_MGR_REP_AVAILABLE, self_->eval_signature.node_address, self_->eval_node_ptr); - } - } - (void)Nd_Start(self_->nd_ptr); -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Helper Methods */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Checks if the node address in signature is in supported address range - * \param self The instance - * \param signature_ptr Reference to the nodes signature - * \return Returns \c true if the address in signature is supported, otherwise \c false. - */ -static bool Nobs_CheckAddrRange(CNodeObserver *self, Ucs_Signature_t *signature_ptr) -{ - bool ret = false; - - if (((signature_ptr->node_address >= NOBS_ADDR_RANGE1_MIN) && (signature_ptr->node_address <= NOBS_ADDR_RANGE1_MAX)) || - ((signature_ptr->node_address >= NOBS_ADDR_RANGE2_MIN) && (signature_ptr->node_address <= NOBS_ADDR_RANGE2_MAX))) - { - ret = true; - } - MISC_UNUSED(self); - - return ret; -} - -static void Nobs_InitAllNodes(CNodeObserver *self) -{ - if (self->init_data.nodes_list_ptr != NULL) - { - uint32_t cnt = 0U; - - for (cnt = 0U; cnt < self->init_data.nodes_list_size; cnt++) - { - self->init_data.nodes_list_ptr[cnt].internal_infos.available = 0U; - self->init_data.nodes_list_ptr[cnt].internal_infos.mgr_joined = NOSB_JOIN_NO; - } - } -} - -static void Nobs_InvalidateAllNodes(CNodeObserver *self) -{ - if (self->init_data.nodes_list_ptr != NULL) - { - uint32_t cnt = 0U; - - for (cnt = 0U; cnt < self->init_data.nodes_list_size; cnt++) - { - Nobs_InvalidateNode(self, &self->init_data.nodes_list_ptr[cnt]); - } - } -} - -static void Nobs_InvalidateNode(CNodeObserver *self, Ucs_Rm_Node_t *node_ptr) -{ - if (node_ptr->internal_infos.mgr_joined == NOSB_JOIN_YES) /* notify welcomed nodes as invalid */ - { - Nobs_NotifyApp(self, UCS_MGR_REP_NOT_AVAILABLE, node_ptr->signature_ptr->node_address, node_ptr); - } - - node_ptr->internal_infos.mgr_joined = NOSB_JOIN_NO; - /* RoutingManagement individually cares for network-not-available event */ - /* (void)Rtm_SetNodeAvailable(self->rtm_ptr, &self->init_data.nodes_list_ptr[cnt], false); */ -} - -static Ucs_Rm_Node_t* Nobs_GetNodeBySignature(CNodeObserver *self, Ucs_Signature_t *signature_ptr) -{ - Ucs_Rm_Node_t* ret = NULL; - - if ((signature_ptr != NULL) && (self->init_data.nodes_list_ptr != NULL)) - { - uint32_t cnt = 0U; - uint16_t node_addr = signature_ptr->node_address; - - for (cnt = 0U; cnt < self->init_data.nodes_list_size; cnt++) - { - if (node_addr == self->init_data.nodes_list_ptr[cnt].signature_ptr->node_address) - { - ret = &self->init_data.nodes_list_ptr[cnt]; - break; - } - } - } - - return ret; -} - -static void Nobs_NotifyApp(CNodeObserver *self, Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr) -{ - if (self->init_data.report_fptr != NULL) - { - self->init_data.report_fptr(code, node_address, node_ptr, self->base_ptr->ucs_user_ptr); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_nsm.c b/ucs2-lib/src/ucs_nsm.c deleted file mode 100644 index 1e3a7e5..0000000 --- a/ucs2-lib/src/ucs_nsm.c +++ /dev/null @@ -1,725 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_obs.c b/ucs2-lib/src/ucs_obs.c deleted file mode 100644 index d67cd0c..0000000 --- a/ucs2-lib/src/ucs_obs.c +++ /dev/null @@ -1,449 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 observer library module. The module consists of the two classes - * CSubject and CObserver. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_OBS - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_obs.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Sub_UpdateList(CSubject *self); -static bool Sub_CheckObserver(void *current_obs_ptr, void *subject_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CSubject */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the subject class. Initializes a subject which distributes its data to - * a list of observers. - * \param self Instance pointer - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Sub_Ctor(CSubject *self, void *ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->ucs_user_ptr = ucs_user_ptr; - Dl_Ctor(&self->list, self->ucs_user_ptr); - Dl_Ctor(&self->add_list, self->ucs_user_ptr); -} - -/*! \brief Adds an observer to a subjects list. - * \param self Instance pointer - * \param obs_ptr Pointer to observer instance - * \return \c SUB_OK: No error - * \return \c SUB_ALREADY_ADDED: Observer is already added - * \return \c SUB_UNKNOWN_OBSERVER: Given observer is not valid - */ -Sub_Ret_t Sub_AddObserver(CSubject *self, CObserver *obs_ptr) -{ - Sub_Ret_t ret_val; - if(obs_ptr == NULL) - { - ret_val = SUB_UNKNOWN_OBSERVER; - } - else if(obs_ptr->valid != false) - { - ret_val = SUB_ALREADY_ADDED; - } - else if((self->notify != false) && - (Dl_IsNodeInList(&self->list, &obs_ptr->node) == false) && - (Dl_IsNodeInList(&self->add_list, &obs_ptr->node) == false)) - { - TR_ASSERT(self->ucs_user_ptr, "[OBS]", (self->num_observers < 0xFFU)); - Dl_InsertTail(&self->add_list, &obs_ptr->node); - obs_ptr->valid = true; - self->changed = true; - ret_val = SUB_DELAYED; - } - else if((self->notify == false) && (Dl_IsNodeInList(&self->list, &obs_ptr->node) == false)) - { - TR_ASSERT(self->ucs_user_ptr, "[OBS]", (self->num_observers < 0xFFU)); - ret_val = SUB_OK; - Dl_InsertTail(&self->list, &obs_ptr->node); - obs_ptr->valid = true; - self->num_observers++; - } - else - { - ret_val = SUB_UNKNOWN_OBSERVER; - } - return ret_val; -} - -/*! \brief Removes an observer from a subjects list. - * \param self Instance pointer - * \param obs_ptr Pointer to observer instance - * \return \c SUB_OK: No error - * \return \c SUB_UNKNOWN_OBSERVER: Unknown observer is given - * \return \c SUB_UNKNOWN_OBSERVER: Given observer is not valid - */ -Sub_Ret_t Sub_RemoveObserver(CSubject *self, CObserver *obs_ptr) -{ - Sub_Ret_t ret_val; - if(obs_ptr == NULL) - { - ret_val = SUB_UNKNOWN_OBSERVER; - } - else if(obs_ptr->valid == false) - { - ret_val = SUB_UNKNOWN_OBSERVER; - } - else if((self->notify != false) && - (Dl_IsNodeInList(&self->list, &obs_ptr->node) != false)) - { - TR_ASSERT(self->ucs_user_ptr, "[OBS]", (self->num_observers > 0U)); - obs_ptr->valid = false; - self->changed = true; - self->num_observers--; - ret_val = SUB_DELAYED; - } - else if((self->notify == false) && - (Dl_Remove(&self->list, &obs_ptr->node) == DL_OK)) - { - TR_ASSERT(self->ucs_user_ptr, "[OBS]", (self->num_observers > 0U)); - self->num_observers--; - ret_val = SUB_OK; - } - else - { - ret_val = SUB_UNKNOWN_OBSERVER; - } - return ret_val; -} - -/*! \brief Notifies all registered observers of a subject. - * \param self Instance pointer - * \param data_ptr Reference to value to distribute (optional) - */ -void Sub_Notify(CSubject *self, void *data_ptr) -{ - if(self != NULL) - { - CDlNode *n_tmp = self->list.head; - self->notify = true; - self->changed = false; - while(n_tmp != NULL) - { - CObserver *o_tmp = (CObserver *)n_tmp->data_ptr; - if((o_tmp->update_fptr != NULL) && (o_tmp->valid != false)) - { - (o_tmp->update_fptr)(o_tmp->inst_ptr, data_ptr); - } - n_tmp = n_tmp->next; - } - if(self->changed != false) - { - Sub_UpdateList(self); - } - self->notify = false; - } -} - -/*! \brief Updates the list of observers. Delayed remove- and add-operations are processed. - * \param self Instance pointer - */ -static void Sub_UpdateList(CSubject *self) -{ - (void)Dl_Foreach(&self->list, &Sub_CheckObserver, self); - Dl_AppendList(&self->list, &self->add_list); -} - -/*! \brief Checks if the given observer is still valid. If the observer is invalid it will be - * removed from the list. This function is used by the foreach loop in Sub_UpdateList(). - * \param current_obs_ptr Reference to the current observer object - * \param subject_ptr Reference to the subject object - * \return Returns always \c false. Force to process the whole list. - */ -static bool Sub_CheckObserver(void *current_obs_ptr, void *subject_ptr) -{ - CObserver *current_obs_ptr_ = (CObserver *)current_obs_ptr; - CSubject *subject_ptr_ = (CSubject *)subject_ptr; - - if(current_obs_ptr_->valid == false) - { - (void)Dl_Remove(&subject_ptr_->list, ¤t_obs_ptr_->node); - } - return false; -} - -/*! \brief Returns the number of registered observers of a subject. - * \param self Instance pointer - * \return The number of registered observers - */ -uint8_t Sub_GetNumObservers(CSubject *self) -{ - return self->num_observers; -} - -/*! \brief Switches all observers of the source-subject to the target-subject. - * \param sub_target Target subject - * \param sub_source Source subject - * \return \c SUB_OK: No error - * \return \c SUB_INVALID_OPERATION: Target and source must be different objects - */ -Sub_Ret_t Sub_SwitchObservers(CSubject *sub_target, CSubject *sub_source) -{ - Sub_Ret_t ret_val; - - if(sub_target == sub_source) - { - ret_val = SUB_INVALID_OPERATION; - } - else - { - Dl_AppendList(&sub_target->list, &sub_source->list); - sub_target->num_observers += sub_source->num_observers; - sub_source->num_observers = 0U; - ret_val = SUB_OK; - } - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CObserver */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the observer class. Initializes an observer which is notified - * by a corresponding subject. - * \param self Instance pointer - * \param inst_ptr Instance pointer used by update_fptr() - * \param update_fptr Callback function to update the observer - */ -void Obs_Ctor(CObserver *self, void *inst_ptr, Obs_UpdateCb_t update_fptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->inst_ptr = inst_ptr; - self->update_fptr = update_fptr; - Dln_Ctor(&self->node, self); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CSingleSubject */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the single-subject class. Initializes a single-subject which distributes - * its data to the registered single-observer. - * \param self Instance pointer - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Ssub_Ctor(CSingleSubject *self, void *ucs_user_ptr) -{ - self->observer_ptr = NULL; - self->ucs_user_ptr = ucs_user_ptr; - self->user_mask = 0U; -} - -/*! \brief Adds a single-observer to a single-subject. - * \param self Instance pointer - * \param obs_ptr Pointer to single-observer instance - * \return \c SSUB_OK: No error - * \return \c SSUB_ALREADY_ADDED: Observer is already added - * \return \c SSUB_UNKNOWN_OBSERVER: Given observer is not valid - */ -Ssub_Ret_t Ssub_AddObserver(CSingleSubject *self, CSingleObserver *obs_ptr) -{ - Ssub_Ret_t ret_val; - if(obs_ptr == NULL) - { - ret_val = SSUB_UNKNOWN_OBSERVER; - } - else if(self->observer_ptr != obs_ptr) - { -#ifdef UCS_TR_INFO - if(self->observer_ptr != NULL) - { - TR_INFO((self->ucs_user_ptr, "[SSUB]", "Observer callback has been overwritten", 0U)); - } -#endif - ret_val = SSUB_OK; - self->observer_ptr = obs_ptr; - } - else - { - ret_val = SSUB_ALREADY_ADDED; - } - - return ret_val; -} - -/*! \brief Removes an single-observer from a single-subject. - * \param self Instance pointer - */ -void Ssub_RemoveObserver(CSingleSubject *self) -{ - self->observer_ptr = NULL; -} - -/*! \brief Notifies the registered single-observer of the given single-subject. - * \param self Instance pointer - * \param data_ptr Reference to value to distribute (optional) - * \param auto_remove If true the observer will be removed - */ -void Ssub_Notify(CSingleSubject *self, void *data_ptr, bool auto_remove) -{ - void *inst_ptr = NULL; - Obs_UpdateCb_t update_fptr = NULL; - if(self->observer_ptr != NULL) - { - inst_ptr = self->observer_ptr->inst_ptr; - update_fptr = self->observer_ptr->update_fptr; - if(auto_remove != false) - { - self->observer_ptr = NULL; - } - } - if(update_fptr != NULL) - { - update_fptr(inst_ptr, data_ptr); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CSingleObserver */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the single-observer class. Initializes an single-observer which is - * notified by a corresponding single-subject. - * \param self Instance pointer - * \param inst_ptr Instance pointer used by update_fptr() - * \param update_fptr Callback function to update the observer - */ -void Sobs_Ctor(CSingleObserver *self, void *inst_ptr, Sobs_UpdateCb_t update_fptr) -{ - self->inst_ptr = inst_ptr; - self->update_fptr = update_fptr; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CMaskedObserver */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the masked-observer class. Initializes an observer which is notified - * by a corresponding subject. - * \param self Instance pointer - * \param inst_ptr Instance pointer used by update_fptr() - * \param notification_mask Notification bitmask - * \param update_fptr Callback function to update the observer - */ -void Mobs_Ctor(CMaskedObserver *self, - void *inst_ptr, - uint32_t notification_mask, - Obs_UpdateCb_t update_fptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - Obs_Ctor(&self->parent, inst_ptr, update_fptr); - self->notification_mask = notification_mask; -} - -/*! \brief Sets the notification mask of a masked-observer. - * \param self Instance pointer - * \param mask Bitmask to set - */ -void Mobs_SetNotificationMask(CMaskedObserver *self, uint32_t mask) -{ - self->notification_mask = mask; -} - -/*! \brief Retrieves the notification mask of a masked-observer. - * \param self Instance pointer - * \return Returns the current notification bitmask of the given observer - */ -uint32_t Mobs_GetNotificationMask(CMaskedObserver *self) -{ - return self->notification_mask; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Additional methods of class CSubject used in combination with CMaskedObserver */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Adds an masked-observer to a masked-subjects list. - * \param self Instance pointer - * \param obs_ptr Pointer to observer instance - * \return \c SUB_OK: No error - * \return \c SUB_ALREADY_ADDED: Observer is already added - * \return \c SUB_UNKNOWN_OBSERVER: Given observer is not valid - */ -Sub_Ret_t Msub_AddObserver(CSubject *self, CMaskedObserver *obs_ptr) -{ - return Sub_AddObserver(self, &obs_ptr->parent); -} - -/*! \brief Removes an masked-observer from a subjects list. - * \param self Instance pointer - * \param obs_ptr Pointer to observer instance - * \return \c SUB_OK: No error - * \return \c SUB_UNKNOWN_OBSERVER: Unknown observer is given - * \return \c SUB_UNKNOWN_OBSERVER: Given observer is not valid - */ -Sub_Ret_t Msub_RemoveObserver(CSubject *self, CMaskedObserver *obs_ptr) -{ - return Sub_RemoveObserver(self, &obs_ptr->parent); -} - -/*! \brief Notifies all registered masked-observers of a masked-subject. - * \param self Instance pointer - * \param data_ptr Reference to value to distribute (optional) - * \param notification_mask Bitmask indicates notified observers - */ -void Msub_Notify(CSubject *self, void *data_ptr, uint32_t notification_mask) -{ - if(self != NULL) - { - CDlNode *n_tmp = self->list.head; - self->notify = true; - self->changed = false; - while(n_tmp != NULL) - { - CMaskedObserver *o_tmp = (CMaskedObserver *)n_tmp->data_ptr; - if( (o_tmp->parent.update_fptr != NULL) && - (o_tmp->parent.valid != false) && - ((o_tmp->notification_mask & notification_mask) != 0U) ) - { - (o_tmp->parent.update_fptr)(o_tmp->parent.inst_ptr, data_ptr); - } - n_tmp = n_tmp->next; - } - if(self->changed != false) - { - Sub_UpdateList(self); - } - self->notify = false; - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmchannel.c b/ucs2-lib/src/ucs_pmchannel.c deleted file mode 100644 index 2c6bbba..0000000 --- a/ucs2-lib/src/ucs_pmchannel.c +++ /dev/null @@ -1,307 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Port Message Channel - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMC - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmchannel.h" -#include "ucs_pmp.h" -#include "ucs_pmcmd.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal typedefs */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -/* LLD related interface functions */ -static Ucs_Lld_RxMsg_t* Pmch_RxAllocate(void *self, uint16_t buffer_size); -static void Pmch_RxUnused(void *self, Ucs_Lld_RxMsg_t *msg_ptr); -static void Pmch_RxReceive(void *self, Ucs_Lld_RxMsg_t *msg_ptr); -static void Pmch_TxRelease(void *self, Ucs_Lld_TxMsg_t *msg_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CPmChannel - * \param self The instance - * \param init_ptr Reference to initialization data structure - */ -void Pmch_Ctor(CPmChannel *self, const Pmch_InitData_t *init_ptr) -{ - uint16_t cnt; - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->init_data = *init_ptr; - self->lld_active = false; - - self->ucs_iface.rx_allocate_fptr = &Pmch_RxAllocate; - self->ucs_iface.rx_receive_fptr = &Pmch_RxReceive; - self->ucs_iface.rx_free_unused_fptr = &Pmch_RxUnused; - self->ucs_iface.tx_release_fptr = &Pmch_TxRelease; - - Pool_Ctor(&self->rx_msgs_pool, self->rx_msgs, /* initialize Rx message pool */ - PMCH_POOL_SIZE_RX, self->init_data.ucs_user_ptr); - for (cnt = 0U; cnt < PMCH_POOL_SIZE_RX; cnt++) /* and assign LLD Rx handles */ - { - Msg_SetLldHandle(&self->rx_msgs[cnt], &self->lld_rx_msgs[cnt]); - self->lld_rx_msgs[cnt].msg_ptr = &self->rx_msgs[cnt]; - } -} - -/*! \brief Registers an Rx callback function dedicated to one FIFO - * \param self The instance - * \param fifo_id The FIFO identifier - * \param rx_fptr The Rx callback function - * \param inst_ptr Reference to the instance required to invoke the callback - */ -void Pmch_RegisterReceiver(CPmChannel *self, Pmp_FifoId_t fifo_id, Pmch_OnRxMsg_t rx_fptr, void *inst_ptr) -{ - TR_ASSERT(self->init_data.ucs_user_ptr, "[PMCH]", (((uint8_t)fifo_id == (uint8_t)PMP_FIFO_ID_ICM)||((uint8_t)fifo_id == (uint8_t)PMP_FIFO_ID_MCM)||((uint8_t)fifo_id == (uint8_t)PMP_FIFO_ID_RCM))); - - self->receivers[fifo_id].rx_fptr = rx_fptr; - self->receivers[fifo_id].inst_ptr = inst_ptr; -} - -/*! \brief Un-initializes the LLD interface of the channel - * \param self The instance - */ -void Pmch_Initialize(CPmChannel *self) -{ - if (self->lld_active == false) - { - self->lld_active = true; - TR_INFO((self->init_data.ucs_user_ptr, "[PMCH]", "Pmch_Initialize(): LLD_START()", 0U)); - self->init_data.lld_iface.start_fptr(&self->ucs_iface, self, self->init_data.lld_iface.lld_user_ptr); - } -} - -/*! \brief Un-initializes the LLD interface of the channel - * \param self The instance - */ -extern void Pmch_Uninitialize(CPmChannel *self) -{ - TR_INFO((self->init_data.ucs_user_ptr, "[PMCH]", "Pmch_Uninitialize(): Channel un-synchronization started", 0U)); - - if (self->lld_active != false) - { - self->lld_active = false; - TR_INFO((self->init_data.ucs_user_ptr, "[PMCH]", "Pmch_Uninitialize(): LLD_STOP()", 0U)); - self->init_data.lld_iface.stop_fptr(self->init_data.lld_iface.lld_user_ptr); - } -} - -/*! \brief Wrapper for LLD transmit - * \details This function which shall be used by all internal classes. No class shall - * invoke the LLD transmit function directly. Thus, it might be possible - * in future to handle transmission failures and retries. - * \param self The instance - * \param msg_ptr Reference to the public LLD message structure - */ -void Pmch_Transmit(CPmChannel *self, Ucs_Lld_TxMsg_t *msg_ptr) -{ - if (self->lld_active != false) - { - self->init_data.lld_iface.tx_transmit_fptr(msg_ptr, self->init_data.lld_iface.lld_user_ptr); - } - else - { - Pmch_TxRelease(self, msg_ptr); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* The exposed low-level driver interface */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Allocates an Rx message object - * \param self The instance - * \param buffer_size Size of the memory chunk in bytes which is needed to - * copy the Rx message. - * \return Reference to an allocated Rx message object or \c NULL if no message object is available. - */ -static Ucs_Lld_RxMsg_t* Pmch_RxAllocate(void *self, uint16_t buffer_size) -{ - CMessage *msg_ptr = NULL; - Ucs_Lld_RxMsg_t *handle = NULL; - CPmChannel *self_ = (CPmChannel*)self; - - if (buffer_size <= MSG_SIZE_RSVD_BUFFER) - { - msg_ptr = Pool_GetMsg(&self_->rx_msgs_pool); - - if (msg_ptr != NULL) - { - Msg_Cleanup(msg_ptr); - handle = &((Lld_IntRxMsg_t*)Msg_GetLldHandle(msg_ptr))->lld_msg; - - TR_ASSERT(self_->init_data.ucs_user_ptr, "[PMCH]", (handle != NULL)); - - handle->data_size = buffer_size; - handle->data_ptr = Msg_GetHeader(msg_ptr); - } - else - { - self_->rx_trigger_available = true; - TR_INFO((self_->init_data.ucs_user_ptr, "[PMCH]", "Pmch_RxAllocate(): Allocation failed, size=%u", 1U, buffer_size)); - } - } - else - { - self_->rx_trigger_available = true; - TR_FAILED_ASSERT(self_->init_data.ucs_user_ptr, "[PMCH]"); - } - - return handle; -} - -/*! \brief Frees an unused Rx message object - * \param self The instance - * \param msg_ptr Reference to the unused Rx message object - */ -static void Pmch_RxUnused(void *self, Ucs_Lld_RxMsg_t *msg_ptr) -{ - CPmChannel *self_ = (CPmChannel*)self; - CMessage *pb_handle = ((Lld_IntRxMsg_t*)(void*)msg_ptr)->msg_ptr; - - TR_ASSERT(self_->init_data.ucs_user_ptr, "[PMCH]", (pb_handle != NULL)); - Pmch_ReturnRxToPool(self_, pb_handle); -} - -/*! \brief Pass an Rx message to UNICENS - * \param self The instance - * \param msg_ptr Reference to the Rx message object containing the received - * message. - */ -static void Pmch_RxReceive(void *self, Ucs_Lld_RxMsg_t *msg_ptr) -{ - bool found = false; - CPmChannel *self_ = (CPmChannel*)self; - - if (msg_ptr->data_ptr != NULL) - { - if (msg_ptr->data_size >= PMP_PM_MIN_SIZE_HEADER) /* ignore incomplete messages */ - { - uint8_t fifo_no = (uint8_t)Pmp_GetFifoId(msg_ptr->data_ptr); /* get channel id (FIFO number) */ - - if ((fifo_no < PMP_MAX_NUM_FIFOS) && (self_->receivers[fifo_no].inst_ptr != NULL)) - { - CMessage *handle = ((Lld_IntRxMsg_t*)(void*)msg_ptr)->msg_ptr; - /* forward message to the respective FIFO/channel */ - self_->receivers[fifo_no].rx_fptr(self_->receivers[fifo_no].inst_ptr, handle); - found = true; - } - else - { - TR_ERROR((self_->init_data.ucs_user_ptr, "[PMCH]", "Pmch_RxReceive(): received message for unregistered FIFO no=%u", 1U, fifo_no)); - } - } - else - { - TR_ERROR((self_->init_data.ucs_user_ptr, "[PMCH]", "Pmch_RxReceive(): received incomplete message of size=%u", 1U, msg_ptr->data_size)); - } - } - else - { - TR_ERROR((self_->init_data.ucs_user_ptr, "[PMCH]", "Pmch_RxReceive(): message data is not valid", 0U)); - } - - if (found == false) - { - Pmch_RxUnused(self_, msg_ptr); /* Just return message to pool until PMC is implemented */ - } -} - -/*! \brief Notifies that the LLD no longer needs to access the Tx message object - * \param self The instance - * \param msg_ptr Reference to the Tx message object which is no longer accessed - * by the low-level driver - */ -static void Pmch_TxRelease(void *self, Ucs_Lld_TxMsg_t *msg_ptr) -{ - CPmChannel *self_ = (CPmChannel*)self; - Lld_IntTxMsg_t *tx_ptr = (Lld_IntTxMsg_t*)(void*)msg_ptr; - - if ((tx_ptr->owner_ptr == NULL) && (tx_ptr->msg_ptr == NULL)) /* tx_ptr is command */ - { - Pmcmd_Release((CPmCommand*)(void*)tx_ptr); - } - else if (tx_ptr->owner_ptr != NULL) /* release message to FIFO */ - { - self_->init_data.tx_release_fptr(tx_ptr->owner_ptr, msg_ptr); - } - else - { - TR_FAILED_ASSERT(self_->init_data.ucs_user_ptr, "[PMCH]"); /* unknown FIFO - invalid message object */ - } - - TR_ASSERT(self_->init_data.ucs_user_ptr, "[PMCH]", (msg_ptr->custom_next_msg_ptr == NULL) ); /* concatenation destroyed by the LLD */ - -} - -/*------------------------------------------------------------------------------------------------*/ -/* FIFO Related Callback Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Returns an unused Rx message object back to the pool - * \param self The instance - * \param msg_ptr The unused Rx message object - */ -void Pmch_ReturnRxToPool(void *self, CMessage *msg_ptr) -{ - CPmChannel *self_ = (CPmChannel*)self; - - Pool_ReturnMsg(msg_ptr); - - if (self_->rx_trigger_available == true) - { - self_->rx_trigger_available = false; - - if (self_->init_data.lld_iface.rx_available_fptr != NULL) - { - self_->init_data.lld_iface.rx_available_fptr(self_->init_data.lld_iface.lld_user_ptr); - } - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmcmd.c b/ucs2-lib/src/ucs_pmcmd.c deleted file mode 100644 index d4055b0..0000000 --- a/ucs2-lib/src/ucs_pmcmd.c +++ /dev/null @@ -1,155 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class CPmCommand - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PM_CMD - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmcmd.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of CPmCommand class - * \param self The instance - * \param fifo The dedicated FIFO - * \param type The port message type - */ -void Pmcmd_Ctor(CPmCommand *self, Pmp_FifoId_t fifo, Pmp_MsgType_t type) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); /* setup attributes */ - self->memory.data_ptr = &self->data[0]; - self->tx_obj.lld_msg.memory_ptr = &self->memory; - self->tx_obj.msg_ptr = NULL; /* label message as command by setting */ - self->tx_obj.owner_ptr = NULL; /* msg_ptr and owner_ptr to NULL */ - self->trigger = false; - - Pmp_SetPmhl(self->data, 3U); /* PMHL is always "3" for control/status messages */ - Pmp_SetFph(self->data, fifo, type); -} - -/*! \brief Retrieves reference to the LLD Tx message object required to call Pmch_Transmit() - * \param self The instance - * \return Returns a reference to the LLD Tx message object - */ -Ucs_Lld_TxMsg_t* Pmcmd_GetLldTxObject(CPmCommand *self) -{ - return (Ucs_Lld_TxMsg_t*)(void*)self; -} - -/*! \brief Sets the content of a command/status message - * \param self The instance - * \param sid The sequence id - * \param ext_type The ExtType type - * \param ext_code The ExtType code - * \param add_data_ptr Additional payload data - * \param add_data_sz The size of additional payload data, valid values: 0..4 - */ -void Pmcmd_SetContent(CPmCommand *self, uint8_t sid, uint8_t ext_type, uint8_t ext_code, uint8_t add_data_ptr[], uint8_t add_data_sz) -{ - if ((add_data_ptr != NULL) && (add_data_sz != 0U)) - { - MISC_MEM_CPY(&self->data[6U], add_data_ptr, (size_t)add_data_sz); - } - - self->memory.data_size = 6U + (uint16_t)add_data_sz; - self->memory.total_size = 6U + (uint16_t)add_data_sz; - - Pmp_SetPml(self->data, 4U + add_data_sz); - Pmp_SetSid(self->data, sid); - Pmp_SetExtType(self->data, ext_type, ext_code); -} - -/*! \brief Updates the content of a command/status message - * \details The length and the content of the payload is not modified. - * It is important to call Pmcmd_SetContent() before. - * \param self The instance - * \param sid The sequence id - * \param ext_type The ExtType type - * \param ext_code The ExtType code - */ -void Pmcmd_UpdateContent(CPmCommand *self, uint8_t sid, uint8_t ext_type, uint8_t ext_code) -{ - Pmp_SetSid(self->data, sid); - Pmp_SetExtType(self->data, ext_type, ext_code); -} - -/*! \brief Reserves the command object if it is available - * \param self The instance - * \return \c true if the command object is available, \c false - * if the command object is (still) in usage - */ -bool Pmcmd_Reserve(CPmCommand *self) -{ - bool succ = false; - - if (self->reserved == false) - { - self->reserved = true; - succ = true; - } - return succ; -} - -/*! \brief Releases the command object after usage - * \param self The instance - */ -void Pmcmd_Release(CPmCommand *self) -{ - self->reserved = false; -} - -/*! \brief Sets or resets the trigger attribute - * \param self The instance - * \param trigger The trigger value - */ -void Pmcmd_SetTrigger(CPmCommand *self, bool trigger) -{ - self->trigger = trigger; -} - -/*! \brief Returns the trigger value - * \param self The instance - * \return Returns \c true if the trigger attribute is set, otherwise \c false. - */ -bool Pmcmd_IsTriggered(CPmCommand *self) -{ - return self->trigger; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmevent.c b/ucs2-lib/src/ucs_pmevent.c deleted file mode 100644 index cc3d1d1..0000000 --- a/ucs2-lib/src/ucs_pmevent.c +++ /dev/null @@ -1,130 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Port Message Event Handler - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMEH - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmevent.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Pmev_OnFifosEvent(void *self, void *data_ptr); -static void Pmev_OnSystemEvent(void *self, void *data_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CPmEventHandler - * \param self The instance - * \param base_ptr Reference to base object - * \param fifos_ptr Reference to CPmFifos object - */ -void Pmev_Ctor(CPmEventHandler *self, CBase *base_ptr, CPmFifos *fifos_ptr) -{ - self->base_ptr = base_ptr; - self->fifos_ptr = fifos_ptr; - - Obs_Ctor(&self->observer, self, &Pmev_OnFifosEvent); - - Mobs_Ctor(&self->sys_observer, self, (EH_E_BIST_FAILED | EH_E_INIT_FAILED), &Pmev_OnSystemEvent); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->sys_observer); -} - -/*! \brief Start reporting events to EH - * \param self The instance - */ -void Pmev_Start(CPmEventHandler *self) -{ - Fifos_AddEventObserver(self->fifos_ptr, &self->observer); -} - -/*! \brief Stops reporting events to EH - * \param self The instance - */ -void Pmev_Stop(CPmEventHandler *self) -{ - Fifos_RemoveEventObserver(self->fifos_ptr, &self->observer); -} - -/*! \brief Callback function to handle a PMS event - * \param self The instance -* \param data_ptr Reference to the PMS event - */ -static void Pmev_OnFifosEvent(void *self, void *data_ptr) -{ - CPmEventHandler *self_ = (CPmEventHandler*)self; - Fifos_Event_t *event_ptr = (Fifos_Event_t*)data_ptr; - - switch (*event_ptr) - { - case FIFOS_EV_SYNC_LOST: - Eh_ReportEvent(&self_->base_ptr->eh, EH_E_SYNC_LOST); - break; - case FIFOS_EV_SYNC_ESTABLISHED: - /* not relevant */ - break; - case FIFOS_EV_SYNC_FAILED: - /* not relevant */ - break; - case FIFOS_EV_UNSYNC_COMPLETE: - Eh_ReportEvent(&self_->base_ptr->eh, EH_E_UNSYNC_COMPLETE); - break; - case FIFOS_EV_UNSYNC_FAILED: - Eh_ReportEvent(&self_->base_ptr->eh, EH_E_UNSYNC_FAILED); - break; - default: - /* not relevant */ - break; - } -} - -/*! \brief Callback function to handle an UCS system events - * \param self The instance -* \param data_ptr Reference to the system event event - */ -static void Pmev_OnSystemEvent(void *self, void *data_ptr) -{ - CPmEventHandler *self_ = (CPmEventHandler*)self; - Fifos_ForceTermination(self_->fifos_ptr); - MISC_UNUSED(data_ptr); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmfifo.c b/ucs2-lib/src/ucs_pmfifo.c deleted file mode 100644 index 90f8db7..0000000 --- a/ucs2-lib/src/ucs_pmfifo.c +++ /dev/null @@ -1,1366 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Port Message FIFO - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMF - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmfifo.h" -#include "ucs_pmp.h" -#include "ucs_pmcmd.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal macros */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ -static const uint8_t FIFO_SRV_PRIO = 252U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ -static const Srv_Event_t FIFO_SE_RX_SERVICE = 1U; /*!< \brief Event which triggers the Rx service */ -static const Srv_Event_t FIFO_SE_TX_SERVICE = 2U; /*!< \brief Event which triggers the Rx service */ -static const Srv_Event_t FIFO_SE_TX_APPLY_STATUS = 4U; /*!< \brief Event which triggers to apply the current INIC status */ -static const Srv_Event_t FIFO_SE_ALL = 7U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Fifo_InitCounters(CPmFifo *self, uint8_t tx_sid_complete, uint8_t tx_credits); -static void Fifo_Service(void *self); - -static void Fifo_RxService(CPmFifo *self); -static void Fifo_RxCheckStatusTrigger(CPmFifo *self); -static void Fifo_RxGetCredit(CPmFifo *self); -static void Fifo_RxReleaseCredit(CPmFifo *self); -static bool Fifo_RxProcessData(CPmFifo *self, CMessage *msg_ptr); -static void Fifo_RxProcessStatus(CPmFifo *self, CMessage *msg_ptr); -static void Fifo_RxProcessCommand(CPmFifo *self, CMessage *msg_ptr); -static void Fifo_RxProcessSyncStatus(CPmFifo *self, uint8_t sid, uint8_t type, uint8_t code, uint8_t *header_ptr); -static uint8_t Fifo_RxCheckFailureCode(CPmFifo *self, uint8_t failure_code); -static void Fifo_OnRx(void *self, CMessage *msg_ptr); - -static void Fifo_TxService(CPmFifo *self); -static void Fifo_TxProcessData(CPmFifo *self); -static void Fifo_TxProcessStatus(CPmFifo *self); -static void Fifo_TxProcessCommand(CPmFifo *self); - -static void Fifo_TxEnqueueBypassMsg(CPmFifo *self, CDlList *q_ptr, CMessage *msg_ptr); -static bool Fifo_FindFirstRegularMsg(void *d_ptr, void *ud_ptr); - -static void Fifo_TxExecuteCancel(CPmFifo *self, uint8_t failure_sid, uint8_t failure_code); -static void Fifo_TxExecuteCancelAll(CPmFifo *self, uint8_t failure_sid, uint8_t failure_code); -static void Fifo_TxFinishedCancelAll(CPmFifo *self); -static uint8_t Fifo_TxPendingGetFollowerId(CPmFifo *self); -static void Fifo_TxCancelFollowers(CPmFifo *self, uint8_t follower_id, Ucs_MsgTxStatus_t status); - -static bool Fifo_TxHasAccessPending(CPmFifo *self); -static void Fifo_TxRestorePending(CPmFifo *self); - -static void Fifo_TxOnWatchdogTimer(void *self); -static void Fifo_TxStartWatchdog(CPmFifo *self); - -static uint8_t Fifo_TxGetValidAcknowledges(CPmFifo *self, uint8_t sid); -static bool Fifo_TxNotifyStatus(CPmFifo *self, uint8_t sid, Ucs_MsgTxStatus_t status); -static void Fifo_TxApplyCurrentStatus(CPmFifo *self); -static void Fifo_TxUpdateCurrentStatus(CPmFifo *self, uint8_t sid, uint8_t type, uint8_t code); -static bool Fifo_TxIsIncomingSidValid(CPmFifo *self, uint8_t sid); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of message FIFO - * \param self The instance - * \param init_ptr Reference to initialization data - * \param config_ptr Reference to configuration - */ -void Fifo_Ctor(CPmFifo *self, const Fifo_InitData_t *init_ptr, const Fifo_Config_t *config_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->init = *init_ptr; - self->config = *config_ptr; - - self->sync_state = FIFO_S_UNSYNCED_INIT; /* initialize members */ - Sub_Ctor(&self->sync_state_subject, self->init.base_ptr->ucs_user_ptr); - - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Ctor(): state: %u", 1U, self->sync_state)); - - Srv_Ctor(&self->service, FIFO_SRV_PRIO, self, &Fifo_Service); /* registration of service */ - (void)Scd_AddService(&self->init.base_ptr->scd, &self->service); - - T_Ctor(&self->wd.timer); /* setup watchdog */ - self->wd.timer_value = self->config.tx_wd_timer_value; - Pmcmd_Ctor(&self->wd.wd_cmd, self->config.fifo_id, PMP_MSG_TYPE_CMD); - Pmcmd_SetContent(&self->wd.wd_cmd, 0U, PMP_CMD_TYPE_REQ_STATUS, PMP_CMD_CODE_REQ_STATUS, NULL, 0U); - - /* init Rx part */ - Dl_Ctor(&self->rx.queue, self->init.base_ptr->ucs_user_ptr); - self->rx.encoder_ptr = self->init.rx_encoder_ptr; - self->rx.on_complete_fptr = self->init.rx_cb_fptr; - self->rx.on_complete_inst = self->init.rx_cb_inst; - - self->rx.ack_threshold = self->config.rx_threshold; - - if (self->config.rx_threshold > self->config.rx_credits)/* configuration error - use single acknowledge */ - { - self->rx.ack_threshold = 1U; - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); - } - - self->rx.wait_processing = false; - Pmcmd_Ctor(&self->rx.status, self->config.fifo_id, PMP_MSG_TYPE_STATUS); - Pmcmd_SetContent(&self->rx.status, 0U, PMP_STATUS_TYPE_FLOW, PMP_STATUS_CODE_SUCCESS, NULL, 0U); - - /* init Tx part */ - Dl_Ctor(&self->tx.waiting_queue, self->init.base_ptr->ucs_user_ptr); - Dl_Ctor(&self->tx.pending_q, self->init.base_ptr->ucs_user_ptr); - - Pmcmd_Ctor(&self->tx.cancel_cmd, self->config.fifo_id, PMP_MSG_TYPE_CMD); - Pmcmd_SetContent(&self->tx.cancel_cmd, 0U, PMP_CMD_TYPE_MSG_ACTION, PMP_CMD_CODE_ACTION_CANCEL, NULL, 0U); - - Fifo_InitCounters(self, 0U, 0U); /* values are incremented on each sync attempt */ - self->tx.encoder_ptr = init_ptr->tx_encoder_ptr; - - /* FIFO synchronization command */ - self->sync_cnt = 0xFFU; - self->sync_params[0] = config_ptr->rx_credits; - self->sync_params[1] = config_ptr->rx_busy_allowed; - self->sync_params[2] = config_ptr->rx_ack_timeout; - self->sync_params[3] = config_ptr->tx_wd_timeout; - Pmcmd_Ctor(&self->tx.sync_cmd, self->config.fifo_id, PMP_MSG_TYPE_CMD); - Pmcmd_SetContent(&self->tx.sync_cmd, 0U, PMP_CMD_TYPE_SYNCHRONIZATION, PMP_CMD_CODE_SYNC, self->sync_params, 4U); - - /* default PM header for Tx */ - self->tx.pm_header.pml = 6U; - self->tx.pm_header.pmhl = self->tx.encoder_ptr->pm_hdr_sz - 3U; - Pmh_SetFph(&self->tx.pm_header, self->config.fifo_id, PMP_MSG_TYPE_DATA); - self->tx.pm_header.sid = 0U; - self->tx.pm_header.ext_type = (uint8_t)self->tx.encoder_ptr->content_type; - - Lldp_Ctor(&self->tx.lld_pool, self, self->init.base_ptr->ucs_user_ptr); - - Pmch_RegisterReceiver(self->init.channel_ptr, self->config.fifo_id, &Fifo_OnRx, self); -} - -/*! \brief Initializes flow control and related counters - * \param self The instance - * \param tx_sid_complete Reference to initialization data - * \param tx_credits Number of credits for Tx - */ -static void Fifo_InitCounters(CPmFifo *self, uint8_t tx_sid_complete, uint8_t tx_credits) -{ - self->rx.busy_num = 0U; - self->rx.expected_sid = tx_sid_complete + 1U; - self->rx.ack_last_ok_sid = tx_sid_complete; - - self->tx.credits = tx_credits; - self->tx.sid_next_to_use = tx_sid_complete +1U; - self->tx.sid_last_completed = tx_sid_complete; - - self->tx.failure_status = 0U; - self->tx.failure_sid = 0U; - - self->tx.current_sid = tx_sid_complete; - self->tx.current_type = PMP_STATUS_TYPE_FLOW; - self->tx.current_code = (uint8_t)PMP_STATUS_CODE_SUCCESS; -} - -/*! \brief Adds an observer of synchronization state changes - * \param self The instance - * \param obs_ptr The observer. The notification result type is \ref Pmp_FifoId_t. - */ -void Fifo_AddStateObserver(CPmFifo *self, CObserver *obs_ptr) -{ - (void)Sub_AddObserver(&self->sync_state_subject, obs_ptr); -} - -/*! \brief Removes an observer of synchronization state changes - * \param self The instance - * \param obs_ptr The observer. - */ -void Fifo_RemoveStateObserver(CPmFifo *self, CObserver *obs_ptr) -{ - (void)Sub_RemoveObserver(&self->sync_state_subject, obs_ptr); -} - -/*! \brief Stops execution of a FIFO and notifies sync lost if necessary - * \param self The instance - * \param new_state The new synchronization state - * \param allow_notification Set to \c false in order to avoid recursion - */ -void Fifo_Stop(CPmFifo *self, Fifo_SyncState_t new_state, bool allow_notification) -{ - bool notify = false; - - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Stop(): FIFO: %u, state: %u, new_state: %u", 3U, self->config.fifo_id, self->sync_state, new_state)); - - if (self->sync_state != new_state) - { - notify = true; - } - - self->sync_state = new_state; - self->tx.credits = 0U; - - if (self->wd.timer_value != 0U) - { - Tm_ClearTimer(&self->init.base_ptr->tm, &self->wd.timer); - } - - if ((notify != false) && (allow_notification != false)) - { - Sub_Notify(&self->sync_state_subject, &self->config.fifo_id); - } -} - -/*! \brief Releases all external references - * \details It is important to call Fifo_Stop() prior to this functions. The low-level driver - * must be stopped as well to avoid concurrent access to message objects. - * \param self The instance - */ -void Fifo_Cleanup(CPmFifo *self) -{ - CMessage *msg_ptr = NULL; - CDlNode *node_ptr = NULL; - - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (self->sync_state == FIFO_S_UNSYNCED_INIT)); - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Cleanup(): FIFO: %u", 1U, self->config.fifo_id)); - - /* cleanup pending queue */ - for (node_ptr = Dl_PopHead(&self->tx.pending_q); node_ptr != NULL; node_ptr = Dl_PopHead(&self->tx.pending_q)) - { - msg_ptr = (CMessage*)Dln_GetData(node_ptr); - - Msg_NotifyTxStatus(msg_ptr, UCS_MSG_STAT_ERROR_SYNC); - Lldp_ReturnTxToPool(&self->tx.lld_pool, (Lld_IntTxMsg_t*)Msg_GetLldHandle(msg_ptr)); - Msg_SetLldHandle(msg_ptr, NULL); /* remove link to LLD message object */ - } - - /* cleanup waiting queue */ - for (node_ptr = Dl_PopHead(&self->tx.waiting_queue); node_ptr != NULL; node_ptr = Dl_PopHead(&self->tx.waiting_queue)) - { - msg_ptr = (CMessage*)Dln_GetData(node_ptr); - - Msg_NotifyTxStatus(msg_ptr, UCS_MSG_STAT_ERROR_SYNC); - } - - /* cleanup Rx queue */ - for (node_ptr = Dl_PopHead(&self->rx.queue); node_ptr != NULL; node_ptr = Dl_PopHead(&self->rx.queue)) - { - msg_ptr = (CMessage*)Dln_GetData(node_ptr); - - Pmch_ReturnRxToPool(self->init.channel_ptr, msg_ptr); - } - - Srv_ClearEvent(&self->service, FIFO_SE_ALL); -} - - -/*! \brief Service function of FIFO - * \details The processing order of Rx followed by Tx is important for Fifo_RxProcessCommand() - * \param self The instance - */ -static void Fifo_Service(void *self) -{ - CPmFifo *self_ = (CPmFifo*)self; - Srv_Event_t event_mask; - - Srv_GetEvent(&self_->service, &event_mask); - - if(FIFO_SE_RX_SERVICE == (event_mask & FIFO_SE_RX_SERVICE)) /* Is event pending? */ - { - Srv_ClearEvent(&self_->service, FIFO_SE_RX_SERVICE); - Fifo_RxService(self_); - } - - if((event_mask & FIFO_SE_TX_APPLY_STATUS) == FIFO_SE_TX_APPLY_STATUS) - { - Srv_ClearEvent(&self_->service, FIFO_SE_TX_APPLY_STATUS); - Fifo_TxApplyCurrentStatus(self_); - } - - if(FIFO_SE_TX_SERVICE == (event_mask & FIFO_SE_TX_SERVICE)) /* Is event pending? */ - { - Srv_ClearEvent(&self_->service, FIFO_SE_TX_SERVICE); - Fifo_TxService(self_); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Tx Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Enqueues a message for transmission - * \param self The instance - * \param msg_ptr The Tx message object - * \param bypass Use \c true if the message shall bypass all other messages - * in the FIFO. Otherwise \c false. - */ -void Fifo_Tx(CPmFifo *self, CMessage *msg_ptr, bool bypass) -{ - uint8_t *msg_hdr_ptr = NULL; - - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (msg_ptr != NULL)); - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Tx(): FIFO: %u, msg_ptr: 0x%p, FuncId: 0x%X, queued Tx message", 3U, self->config.fifo_id, msg_ptr, msg_ptr->pb_msg.id.function_id)); - - Msg_PullHeader(msg_ptr, self->tx.encoder_ptr->msg_hdr_sz); - msg_hdr_ptr = Msg_GetHeader(msg_ptr); - self->tx.encoder_ptr->encode_fptr(Msg_GetMostTel(msg_ptr), msg_hdr_ptr); - - if (bypass == false) - { - Dl_InsertTail(&self->tx.waiting_queue, Msg_GetNode(msg_ptr)); /* enqueue message for asynchronous transmission */ - } - else - { - Fifo_TxEnqueueBypassMsg(self, &self->tx.waiting_queue, msg_ptr); /* queue before first non-bypass message */ - } - - Srv_SetEvent(&self->service, FIFO_SE_TX_SERVICE); -} - -/*! \brief Enqueues a bypass message between the last bypass and the first regular message in a queue - * \param self The instance - * \param q_ptr The message queue - * \param msg_ptr The Tx message object - */ -static void Fifo_TxEnqueueBypassMsg(CPmFifo *self, CDlList *q_ptr, CMessage *msg_ptr) -{ - CDlNode *node_ptr = Dl_Foreach(q_ptr, &Fifo_FindFirstRegularMsg, NULL); /* find first "non-bypass" message */ - Msg_SetTxBypass(msg_ptr, true); /* mark new message as bypass message */ - - if (node_ptr == NULL) /* no message or only bypass messages found */ - { - Dl_InsertTail(&self->tx.waiting_queue, Msg_GetNode(msg_ptr)); /* enqueue message to tail */ - } - else /* first "non-bypass" message is found */ - { /* insert the bypass message before the first regular message found */ - Dl_InsertBefore(&self->tx.waiting_queue, node_ptr, Msg_GetNode(msg_ptr)); - } -} - -/*! \brief Required as "for-each" function to find the first "regular message" - * \param d_ptr Points to a message object in the queue - * \param ud_ptr Unused data reference, always \c NULL - * \return Returns \c true if a regular (non-bypass) message is found. - */ -static bool Fifo_FindFirstRegularMsg(void *d_ptr, void *ud_ptr) -{ - bool ret = true; - MISC_UNUSED(ud_ptr); - - if (Msg_IsTxBypass((CMessage*)d_ptr)) - { - ret = false; - } - - return ret; -} - -/*! \brief Processing of data, status and command messages - * \param self The instance - */ -static void Fifo_TxService(CPmFifo *self) -{ - Fifo_TxProcessCommand(self); - Fifo_TxProcessStatus(self); - Fifo_TxProcessData(self); -} - -/*! \brief Processing of status messages - * \param self The instance - */ -static void Fifo_TxProcessStatus(CPmFifo *self) -{ - if (Pmcmd_IsTriggered(&self->rx.status) != false) - { - if (Pmcmd_Reserve(&self->rx.status) != false) - { - Pmcmd_SetTrigger(&self->rx.status, false); - self->rx.ack_last_ok_sid = (self->rx.expected_sid - self->rx.busy_num) - 1U; - self->rx.wait_processing = false; - - if (self->rx.busy_num == 0U) /* currently no processing of data messages active */ - { /* notify the latest with SUCCESS */ - Pmcmd_UpdateContent(&self->rx.status, self->rx.expected_sid - 1U, PMP_STATUS_TYPE_FLOW, PMP_STATUS_CODE_SUCCESS); - } - else /* message processing is active */ - { /* notify code busy according to remaining credits */ - Pmcmd_UpdateContent(&self->rx.status, self->rx.expected_sid - self->rx.busy_num, PMP_STATUS_TYPE_FLOW, PMP_STATUS_CODE_BUSY); - } - - Pmch_Transmit(self->init.channel_ptr, Pmcmd_GetLldTxObject(&self->rx.status)); - } - } -} - -/*! \brief Processing of queued data messages - * \param self The instance - */ -static void Fifo_TxProcessData(CPmFifo *self) -{ - /* process all queued messages as long as credits are available, - * process all queued messages if FIFO is not synced - */ - while ((self->tx.cancel_all_running == false) && (self->tx.credits > 0U)) - { - CMessage *msg_ptr = NULL; - CDlNode *node_ptr = NULL; - uint8_t *msg_hdr_ptr = NULL; - Lld_IntTxMsg_t *lld_tx_ptr = NULL; - - node_ptr = Dl_PopHead(&self->tx.waiting_queue); /* get message node */ - if (node_ptr == NULL) - { - msg_ptr = NULL; /* stop processing - no further messages in queue */ - break; - } - - msg_ptr = (CMessage*)Dln_GetData(node_ptr); /* get message object */ - - if (self->sync_state != FIFO_S_SYNCED) - { - Msg_NotifyTxStatus(msg_ptr, UCS_MSG_STAT_ERROR_SYNC); /* notify sync error while not synced */ - } - else - { - lld_tx_ptr = Lldp_GetTxFromPool(&self->tx.lld_pool); - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (msg_ptr != NULL)); - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (lld_tx_ptr != NULL)); - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxProcessData(): FIFO: %u, msg_ptr: 0x%p, FuncId: 0x%X, SID: 0x%02X, queued Tx message", 4U, self->config.fifo_id, msg_ptr, msg_ptr->pb_msg.id.function_id, self->tx.sid_next_to_use)); - - Msg_SetLldHandle(msg_ptr, lld_tx_ptr); /* link message objects */ - lld_tx_ptr->msg_ptr = msg_ptr; - - Msg_PullHeader(msg_ptr, self->tx.encoder_ptr->pm_hdr_sz); /* get PM header pointer */ - msg_hdr_ptr = Msg_GetHeader(msg_ptr); - - { - uint8_t tel_length = Msg_GetMostTel(msg_ptr)->tel.tel_len; - self->tx.pm_header.pml = (Msg_GetHeaderSize(msg_ptr) + tel_length) - 2U; - } - - self->tx.pm_header.sid = self->tx.sid_next_to_use; /* assign SeqID */ - self->tx.sid_next_to_use++; - - Pmh_BuildHeader(&self->tx.pm_header, msg_hdr_ptr); /* build PM header */ - lld_tx_ptr->lld_msg.memory_ptr = Msg_GetMemTx(msg_ptr); - - Msg_SetTxActive(msg_ptr, true); - Dl_InsertTail(&self->tx.pending_q, Msg_GetNode(msg_ptr)); - - Pmch_Transmit(self->init.channel_ptr, (Ucs_Lld_TxMsg_t*)(void*)lld_tx_ptr); - - self->tx.credits--; - } - } -} - -/*! \brief Processing of status messages - * \param self The instance - */ -static void Fifo_TxProcessCommand(CPmFifo *self) -{ - if (Pmcmd_IsTriggered(&self->tx.sync_cmd) != false) - { - if (Pmcmd_Reserve(&self->tx.sync_cmd) != false) - { - Pmcmd_SetTrigger(&self->tx.sync_cmd, false); - - if (self->sync_state == FIFO_S_SYNCING) - { - self->sync_cnt++; - Pmcmd_SetContent(&self->tx.sync_cmd, self->sync_cnt, PMP_CMD_TYPE_SYNCHRONIZATION, PMP_CMD_CODE_SYNC, self->sync_params, 4U); - Pmch_Transmit(self->init.channel_ptr, Pmcmd_GetLldTxObject(&self->tx.sync_cmd)); - } - else if (self->sync_state == FIFO_S_UNSYNCING) - { - Pmcmd_SetContent(&self->tx.sync_cmd, 0U, PMP_CMD_TYPE_SYNCHRONIZATION, PMP_CMD_CODE_UNSYNC, NULL, 0U); - Pmch_Transmit(self->init.channel_ptr, Pmcmd_GetLldTxObject(&self->tx.sync_cmd)); - } - else - { - Pmcmd_Release(&self->tx.sync_cmd); - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); - } - } - else - { - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); - } - } -} - -/*! \brief Releases a LLD Tx message object - * \param self The instance - * \param handle_ptr The unused LLD Tx message object - * \details If Fifo_TxApplyStatus() is waiting for a message object - * being released - */ -void Fifo_TxOnRelease(void *self, Ucs_Lld_TxMsg_t *handle_ptr) -{ - CPmFifo *self_ = (CPmFifo*)self; - Lld_IntTxMsg_t *tx_ptr = (Lld_IntTxMsg_t*)(void*)handle_ptr; - - if (tx_ptr->msg_ptr != NULL) - { - Msg_SetTxActive(tx_ptr->msg_ptr, false); - } - else - { - TR_FAILED_ASSERT(self_->init.base_ptr->ucs_user_ptr, "[FIFO]"); - } - - if (self_->tx.status_waiting_release != false) - { - self_->tx.status_waiting_release = false; - Srv_SetEvent(&self_->service, (FIFO_SE_TX_APPLY_STATUS | FIFO_SE_TX_SERVICE)); - } -} - -/*! \brief Triggers a command CANCEL_ALL and stops further Tx processing - * \details CANCEL_ALL shall be called only, if the front-most pending message - * has followers (is segmented, i.e. \c cancel_id > 0). Use command CANCEL - * if the front-most message has no followers (\c cancel_id == NULL). - * \param self The instance - * \param failure_sid The failure sid - * \param failure_code The failure code reported by the INIC - */ -static void Fifo_TxExecuteCancelAll(CPmFifo *self, uint8_t failure_sid, uint8_t failure_code) -{ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxExecuteCancelAll(): FIFO: %u, SID: %u, Code: %u", 3U, self->config.fifo_id, failure_sid, failure_code)); - - if (Pmcmd_Reserve(&self->tx.cancel_cmd) != false) /* prepare cancel command */ - { - Pmcmd_UpdateContent(&self->tx.cancel_cmd, self->tx.current_sid, - PMP_CMD_TYPE_MSG_ACTION, PMP_CMD_CODE_ACTION_CANCEL_ALL); - Pmch_Transmit(self->init.channel_ptr, Pmcmd_GetLldTxObject(&self->tx.cancel_cmd)); - } - else - { - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); /* Unable to reserve cancel command */ - } - - self->tx.cancel_all_running = true; - self->tx.failure_sid = failure_sid; - self->tx.failure_status = failure_code; -} - -/*! \brief Shall be called if the command CANCEL_ALL was processed completely - * \param self The instance - * \details Since the CANCEL_ALL is used to cancel the front-most message and - * all of its followers (same cancel_id) - - for mid-level retries, the canceled messages - * are moved from the processing_q to the waiting_q again. The MLR timer is - * started. As soon as the timer elapses, Tx processing is continued again. - * If the front-most message has a follower id, all pending messages are - * moved to the waiting queue and all messages with the same follower id - * are notified as failed. - */ -static void Fifo_TxFinishedCancelAll(CPmFifo *self) -{ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxFinishedCancelAll(): FIFO: %u, FailureStatus: %u,", 2U, self->config.fifo_id, self->tx.failure_status)); - - if (self->tx.failure_status != 0U) /* avoid multiple execution of the same CANCELED status */ - { /* and all of its followers */ - uint8_t follower_id = Fifo_TxPendingGetFollowerId(self); - Fifo_TxRestorePending(self); /* move remaining messages to waiting_q */ - Fifo_TxCancelFollowers(self, follower_id, (Ucs_MsgTxStatus_t)self->tx.failure_status); - /* notify front-most and message and all of its followers */ - self->tx.cancel_all_running = false; /* continue with Tx processing */ - self->tx.failure_sid = 0U; - self->tx.failure_status = 0U; - Srv_SetEvent(&self->service, FIFO_SE_TX_SERVICE); - } -} - -/*! \brief Triggers a command CANCEL while Tx processing continues - * \param self The instance - * \param failure_sid The failure sid - * \param failure_code The failure code reported by the INIC - */ -static void Fifo_TxExecuteCancel(CPmFifo *self, uint8_t failure_sid, uint8_t failure_code) -{ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxExecuteCancel(): FIFO: %u, SID: %u, Code: %u", 3U, self->config.fifo_id, failure_sid, failure_code)); - - if (Pmcmd_Reserve(&self->tx.cancel_cmd) != false) - { - Pmcmd_UpdateContent(&self->tx.cancel_cmd, self->tx.current_sid, - PMP_CMD_TYPE_MSG_ACTION, PMP_CMD_CODE_ACTION_CANCEL); - Pmch_Transmit(self->init.channel_ptr, Pmcmd_GetLldTxObject(&self->tx.cancel_cmd)); - } - else - { - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); /* Unable to reserve cancel command */ - } - - self->tx.cancel_all_running = false; - self->tx.failure_sid = failure_sid; - self->tx.failure_status = failure_code; -} - -/*! \brief Checks if the LLD has released all messages in the pending_q - * \param self The instance - * \return Returns \c true if all messages are released by the LLD, otherwise \c false. - */ -static bool Fifo_TxHasAccessPending(CPmFifo *self) -{ - bool ret = true; - CDlNode *node_ptr = Dl_PeekTail(&self->tx.pending_q); /* if the tail is not active, then all */ - /* pending message are not active */ - if (node_ptr != NULL) - { - CMessage *msg_ptr = (CMessage*)Dln_GetData(node_ptr); - - if (Msg_IsTxActive(msg_ptr) != false) - { - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxHasAccessPending(): FIFO: %u, msg_ptr: 0x%p, still in use", 2U, self->config.fifo_id, msg_ptr)); - self->tx.status_waiting_release = true; - ret = false; - } - } - - return ret; -} - -/*! \brief Moves all pending messages to the waiting_q - * \details All messages from pending_q will be moved to the waiting_g and - * all consumed credits are restored. The message objects are restored - * to the queue in the same order as they have been forwarded to the LLD. - * This method is typically called to restore the waiting_q in the correct - * order before notifying a - * \param self The instance - */ -static void Fifo_TxRestorePending(CPmFifo *self) -{ - /* take tail from pending_q to the head of waiting_q */ - CMessage *msg_ptr = NULL; - CDlNode *node_ptr = NULL; - - /* cleanup pending queue */ - for (node_ptr = Dl_PopTail(&self->tx.pending_q); node_ptr != NULL; node_ptr = Dl_PopTail(&self->tx.pending_q)) - { - msg_ptr = (CMessage*)Dln_GetData(node_ptr); - - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxRestorePending(): FIFO: %u, msg_ptr: 0x%p", 2U, self->config.fifo_id, msg_ptr)); - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (Msg_IsTxActive(msg_ptr) == false)); - - self->tx.sid_last_completed++; - self->tx.credits++; - Lldp_ReturnTxToPool(&self->tx.lld_pool, (Lld_IntTxMsg_t*)Msg_GetLldHandle(msg_ptr)); - Msg_SetLldHandle(msg_ptr, NULL); /* remove link to LLD message object */ - Msg_PushHeader(msg_ptr, self->tx.encoder_ptr->pm_hdr_sz); /* set index to position of message header */ - Dl_InsertHead(&self->tx.waiting_queue, node_ptr); /* enqueue message to waiting_q */ - } -} - -/*! \brief Retrieves the follower id of the front-most pending message - * \param self The instance - * \return Returns the follower id of the front-most pending message. - */ -static uint8_t Fifo_TxPendingGetFollowerId(CPmFifo *self) -{ - CDlNode *node_ptr; - CMessage *tx_ptr; - uint8_t ret = 0U; - - node_ptr = Dl_PeekHead(&self->tx.pending_q); - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (node_ptr != NULL)); - - if (node_ptr != NULL) - { - tx_ptr = (CMessage*)Dln_GetData(node_ptr); - ret = tx_ptr->pb_msg.opts.cancel_id; - } - - return ret; -} - -/*! \brief Aborts the transmission of all messages in the waiting_q with a given follower id - * \param self The instance - * \param follower_id The follower id a message needs to have to be canceled - * \param status The transmission status that shall be notified - */ -static void Fifo_TxCancelFollowers(CPmFifo *self, uint8_t follower_id, Ucs_MsgTxStatus_t status) -{ - CDlNode *node_ptr; - CDlList temp_queue; - - Dl_Ctor(&temp_queue, self->init.base_ptr->ucs_user_ptr); - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxCancelFollowers(): FIFO: %u: FollowerId: %u", 2U, self->config.fifo_id, follower_id)); - - for (node_ptr = Dl_PopHead(&self->tx.waiting_queue); node_ptr != NULL; node_ptr = Dl_PopHead(&self->tx.waiting_queue)) - { - CMessage *tx_ptr = (CMessage*)Dln_GetData(node_ptr); - - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (Msg_GetLldHandle(tx_ptr) == NULL)); - - if (tx_ptr->pb_msg.opts.cancel_id == follower_id) - { - Msg_NotifyTxStatus(tx_ptr, status); /* notify failed transmission of message and all followers */ - } - else - { - Dl_InsertTail(&temp_queue, node_ptr); /* add to temporary queue and keep order of messages */ - } - } - - if (Dl_GetSize(&temp_queue) > 0U) /* restore temp_queue to waiting_q */ - { - Dl_AppendList(&self->tx.waiting_queue, &temp_queue);/* temp_queue will be empty now */ - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Tx Message Processing */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Retrieves the number of (implicit) acknowledges that are related to one SID - * \param self The instance - * \param sid The sequence ID - * \return The number of implicit acknowledges that are related to the SID - */ -static uint8_t Fifo_TxGetValidAcknowledges(CPmFifo *self, uint8_t sid) -{ - uint8_t diff_s = (uint8_t)(sid - self->tx.sid_last_completed); /* number of implicit acknowledged data */ - uint8_t diff_b = (uint8_t)(self->tx.sid_next_to_use - self->tx.sid_last_completed); /* number of "sent but un-acknowledged data" + 1 */ - - if (diff_b <= diff_s) /* check valid acknowledges */ - { - diff_s = 0U; - } - - return diff_s; -} - - -/*! \brief Checks id an incoming SID of a status message is valid. - * \param self The instance - * \param sid The sequence ID - * \return Returns \c true if the SID is valid, otherwise \c false. - */ -static bool Fifo_TxIsIncomingSidValid(CPmFifo *self, uint8_t sid) -{ - bool ret = false; - uint8_t diff_s = (uint8_t)(sid - self->tx.sid_last_completed); /* number of implicit acknowledged data */ - uint8_t diff_b = (uint8_t)(self->tx.sid_next_to_use - self->tx.sid_last_completed); /* number of "sent but un-acknowledged data" + 1 */ - uint8_t diff_p = (uint8_t)(self->tx.current_sid - self->tx.sid_last_completed); /* pending/known acknowledges */ - - if (diff_b > diff_s) /* check if SID fits in valid range */ - { - if (diff_s >= diff_p) /* avoid overwriting with smaller values */ - { - ret = true; - } - } - - return ret; -} - -/*! \brief Implicitly notifies transmission status to calling classes - * \param self The instance - * \param sid The sequence ID until the status shall be notified - * \param status The status which is notified - * \return Returns \c true if all desired messages had been notified, - * otherwise \c false. - */ -static bool Fifo_TxNotifyStatus(CPmFifo *self, uint8_t sid, Ucs_MsgTxStatus_t status) -{ - bool ret = true; - uint8_t acks = Fifo_TxGetValidAcknowledges(self, sid); - - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxNotifyStatus(): FIFO: %u, calculated_acks: %u", 2U, self->config.fifo_id, acks)); - - while (acks > 0U) - { - CDlNode *node_ptr = Dl_PopHead(&self->tx.pending_q); - - if (node_ptr != NULL) - { - CMessage *tx_ptr = (CMessage*)node_ptr->data_ptr; - - if (!Msg_IsTxActive(tx_ptr)) - { - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (tx_ptr != NULL)); - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxNotifyStatus(): FIFO: %u, FuncId: 0x%X, notified status: %u", 3U, self->config.fifo_id, tx_ptr->pb_msg.id.function_id, status)); - Msg_NotifyTxStatus(tx_ptr, status); - Lldp_ReturnTxToPool(&self->tx.lld_pool, (Lld_IntTxMsg_t*)Msg_GetLldHandle(tx_ptr)); - Msg_SetLldHandle(tx_ptr, NULL); /* remove link to LLD message object */ - - self->tx.credits++; /* increment credits */ - self->tx.sid_last_completed++; /* update last acknowledge SID */ - } - else - { - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxNotifyStatus(): FIFO: %u, LLD objects still occupied", 1U, self->config.fifo_id)); - Dl_InsertHead(&self->tx.pending_q, node_ptr); - self->tx.status_waiting_release = true; - ret = false; - break; - } - } - else - { - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); /* not yet handled */ - /* trigger sync again */ - } - - acks--; - } - - return ret; -} - -/*! \brief Updates the current Tx status with the content of a received FIFO status - * \param self The instance - * \param sid The sequence id of the FIFO status - * \param type The type of the FIFO status. Valid types are only: - * - PMP_STATUS_TYPE_FLOW - * - PMP_STATUS_TYPE_FAILURE - * \param code The code of the FIFO status - */ -static void Fifo_TxUpdateCurrentStatus(CPmFifo *self, uint8_t sid, uint8_t type, uint8_t code) -{ - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (type == (uint8_t)PMP_STATUS_TYPE_FAILURE) || (type == (uint8_t)PMP_STATUS_TYPE_FLOW)); - if (Fifo_TxIsIncomingSidValid(self, sid)) /* is new or updating status */ - { - self->tx.current_sid = sid; /* update current status */ - self->tx.current_type = (Pmp_StatusType_t)type; - self->tx.current_code = code; - } - else - { - TR_ERROR((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxUpdateCurrentStatus(): FIFO: %u, sid: %u, type: %u, code: %u, INVALID SID", 4U, self->config.fifo_id, sid, type, code)); - } -} - -/*! \brief Analyses the current Tx status, tries to notify statuses to the transmitter and triggers - * retry/cancel actions. - * \param self The instance - */ -static void Fifo_TxApplyCurrentStatus(CPmFifo *self) -{ - if ((self->tx.cancel_all_running == false) && (self->tx.failure_status != 0U)) /* Command(CANCEL) is pending */ - { - if (Fifo_TxGetValidAcknowledges(self, self->tx.current_sid) > 1U) /* ?>=1? "single cancel" is valid and implicit */ - { - if (Fifo_TxNotifyStatus(self, self->tx.failure_sid, (Ucs_MsgTxStatus_t)self->tx.failure_status)) - { - self->tx.failure_status = 0U; /* implicit canceled stops retries */ - self->tx.failure_sid = 0U; - } - } - } - - if ((self->tx.current_type == PMP_STATUS_TYPE_FAILURE) && (self->tx.status_waiting_release == false)) - { - if (self->tx.cancel_all_running == false) - { - if (Fifo_TxNotifyStatus(self, self->tx.current_sid - 1U, UCS_MSG_STAT_OK) != false) - { - /* important: failed message now is front-most message in the tx.pending_q, */ - /* any implicit acknowledge was done before */ - if (self->tx.failure_status == 0U) /* failure not yet handled - avoid multiple calls */ - { - if (Fifo_TxPendingGetFollowerId(self) == 0U) - { - Fifo_TxExecuteCancel(self, self->tx.current_sid, self->tx.current_code); /* execute simple cancel */ - } - else - { - Fifo_TxExecuteCancelAll(self, self->tx.current_sid, self->tx.current_code); /* execute cancel all */ - /* self->tx.cancel_all_running now is 'true' and Tx is stopped */ - } - } - } - } - } - - if ((self->tx.current_type == PMP_STATUS_TYPE_FLOW) && (self->tx.status_waiting_release == false)) - { - if ((uint8_t)PMP_STATUS_CODE_SUCCESS == self->tx.current_code) /* acknowledge pending messages */ - { - /* no further retries possible */ - (void)Fifo_TxNotifyStatus(self, self->tx.current_sid, UCS_MSG_STAT_OK); - } - else if ((uint8_t)PMP_STATUS_CODE_CANCELED == self->tx.current_code) - { - if (self->tx.cancel_all_running != false) - { - /* wait until the last SID is notified */ - if (self->tx.current_sid == (uint8_t)(self->tx.sid_next_to_use - (uint8_t)1U)) - { - /* cancel done if none of pending messages is active */ - if (Fifo_TxHasAccessPending(self) != false) - { - Fifo_TxFinishedCancelAll(self); - } - } - } - else if (Fifo_TxNotifyStatus(self, self->tx.current_sid, (Ucs_MsgTxStatus_t)self->tx.failure_status)) - { - self->tx.failure_status = 0U; - self->tx.failure_sid = 0U; - } - } - else - { - if (Fifo_TxNotifyStatus(self, self->tx.current_sid - 1U, UCS_MSG_STAT_OK)) /* just implicitly acknowledge preceding message */ - { - if ((uint8_t)PMP_STATUS_CODE_NACK == self->tx.current_code) - { - Fifo_Stop(self, FIFO_S_UNSYNCED_INIT, true); - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); - } - } - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Rx Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Receives a message on the respective FIFO - * \param self The instance - * \param msg_ptr Reference to the Rx message - */ -static void Fifo_OnRx(void *self, CMessage *msg_ptr) -{ - CPmFifo *self_ = (CPmFifo*)self; - Dl_InsertTail(&self_->rx.queue, Msg_GetNode(msg_ptr)); /* enqueue in rx_queue */ - Srv_SetEvent(&self_->service, (FIFO_SE_RX_SERVICE | FIFO_SE_TX_APPLY_STATUS | FIFO_SE_TX_SERVICE)); -} - -/*! \brief Processes the Rx queue completely and triggers possible Tx events - * \param self The instance - */ -static void Fifo_RxService(CPmFifo *self) -{ - while (self->rx.wait_processing == false) /* process all Rx messages if possible */ - { - CMessage *msg_ptr; - uint8_t *header_ptr; - Pmp_MsgType_t type; - bool ok; - - bool free_msg = true; /* default: free every status or command message */ - CDlNode *node_ptr = Dl_PopHead(&self->rx.queue); - - if (node_ptr == NULL) - { - msg_ptr = NULL; /* stop processing - no further messages in queue */ - break; - } - - msg_ptr = (CMessage*)node_ptr->data_ptr; - header_ptr = Msg_GetHeader(msg_ptr); - type = Pmp_GetMsgType(header_ptr); - ok = Pmp_VerifyHeader(header_ptr, MSG_SIZE_RSVD_BUFFER); - - if (ok != false) - { - switch (type) - { - case PMP_MSG_TYPE_CMD: - Fifo_RxProcessCommand(self, msg_ptr); - break; - case PMP_MSG_TYPE_STATUS: - Fifo_RxProcessStatus(self, msg_ptr); - break; - case PMP_MSG_TYPE_DATA: - free_msg = Fifo_RxProcessData(self, msg_ptr); /* important: message can be freed */ - break; /* synchronously */ - default: - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); /* unknown FIFO message type */ - break; - } - } - else - { - TR_FAILED_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]"); /* invalid message header */ - } - - if (free_msg != false) - { - Pmch_ReturnRxToPool(self->init.channel_ptr, msg_ptr); - } - } -} - -/*! \brief Evaluates the trigger condition to transmit a Rx status - * \details Needs to be called before and after processing Rx data messages - * \param self The instance - */ -static void Fifo_RxCheckStatusTrigger(CPmFifo *self) -{ - /* calculate the number of credits the INIC has consumed */ - /* if less messages are processing, the freed can be acknowledged */ - uint8_t consumed_inic_credits = (self->rx.expected_sid - self->rx.ack_last_ok_sid) - 1U; - uint8_t possible_acks = consumed_inic_credits - self->rx.busy_num; - - if ((consumed_inic_credits >= self->rx.ack_threshold) && (possible_acks > 0U)) - { - if (Pmcmd_IsTriggered(&self->rx.status) == false) - { - Pmcmd_SetTrigger(&self->rx.status, true); /* INIC might run out of credits */ - Srv_SetEvent(&self->service, FIFO_SE_TX_SERVICE); - } - } -} - -/*! \brief This function shall be called before processing a valid FIFO data message - * \param self The instance - */ -static void Fifo_RxGetCredit(CPmFifo *self) -{ - self->rx.busy_num++; - Fifo_RxCheckStatusTrigger(self); -} - -/*! \brief This function shall be called after processing a valid FIFO data message - * \details It is important to call this function after the message object is freed, - * so that the flow control can be updated. - * \param self The instance - */ -static void Fifo_RxReleaseCredit(CPmFifo *self) -{ - self->rx.busy_num--; - Fifo_RxCheckStatusTrigger(self); -} - -/*! \brief Releases a FIFO data message which was received and forwarded by the FIFO - * \details The function returns the message to the channel's Rx message pool and - * has to update the number of credits (processing handles). - * A FIFO data message is initially allocated from the channel's Rx message pool. - * When processing the handle the determined FIFO need to calculate the amount of - * credits. When freeing the message the handle needs to be returned to the channel's - * Rx pool again and the FIFO needs to refresh the status and credits calculation. - * Therefore the message has to be freed to the respective FIFO again. - * \param self The instance - * \param msg_ptr The Rx data message - */ -void Fifo_RxReleaseMsg(CPmFifo *self, CMessage *msg_ptr) -{ - Pmch_ReturnRxToPool(self->init.channel_ptr, msg_ptr); - Fifo_RxReleaseCredit(self); -} - -/*! \brief Processes an Rx data message - * \param self The instance - * \param msg_ptr The Rx data message - * \return \c true if the message object is no longer needed. - * Otherwise \c false. - */ -static bool Fifo_RxProcessData(CPmFifo *self, CMessage *msg_ptr) -{ - bool free_msg = true; - uint8_t content_header_sz = 0U; - uint8_t sid = 0U; - uint8_t *header_ptr = Msg_GetHeader(msg_ptr); - sid = Pmp_GetSid(header_ptr); - - if (self->sync_state != FIFO_S_SYNCED) - { /* discard Rx messages while FIFO is not synced */ - TR_ERROR((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_RxProcessData(): FIFO: %u, state: %u, discards Rx message with SID=0x%02X while not synced (warning)", 3U, self->config.fifo_id, self->sync_state, sid)); - } - else if (sid == self->rx.expected_sid) /* check if SID is ok */ - { - uint8_t pm_header_sz = Pmp_GetPmhl(header_ptr) + 3U; - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (pm_header_sz == self->rx.encoder_ptr->pm_hdr_sz)); - - self->rx.expected_sid++; /* update SID */ - content_header_sz = self->rx.encoder_ptr->msg_hdr_sz; - - /* parasoft suppress item MISRA2004-17_4 reason "necessary offset usage" */ - self->rx.encoder_ptr->decode_fptr(Msg_GetMostTel(msg_ptr), &(header_ptr[pm_header_sz])); - /* parasoft unsuppress item MISRA2004-17_4 reason "necessary offset usage" */ - - Msg_ReserveHeader(msg_ptr, content_header_sz + pm_header_sz); - Msg_PullHeader(msg_ptr, content_header_sz + pm_header_sz); - - if (Msg_VerifyContent(msg_ptr)) - { - if (self->rx.on_complete_fptr != NULL) - { - (void)Fifo_RxGetCredit(self); - free_msg = false; /* callback is responsible to free the message */ - self->rx.on_complete_fptr(self->rx.on_complete_inst, msg_ptr); - /* Fifo_RxReleaseCredit() is called when message is freed */ - } - } - } - else - { - TR_ERROR((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_RxProcessData(): FIFO: %u, state: %u, discards Rx message with unexpected SID=0x%02X (warning)", 3U, self->config.fifo_id, self->sync_state, sid)); - } - - return free_msg; -} - -/*! \brief Processes an Rx status message - * \param self The instance - * \param msg_ptr The Rx status message - */ -static void Fifo_RxProcessStatus(CPmFifo *self, CMessage *msg_ptr) -{ - CPmh pm_header; - uint8_t current_sid; - uint8_t current_type; - uint8_t current_code; - uint8_t *header_ptr = Msg_GetHeader(msg_ptr); - - Pmh_DecodeHeader(&pm_header, header_ptr); - current_sid = pm_header.sid; - current_type = (uint8_t)Pmh_GetExtStatusType(&pm_header); - current_code = (uint8_t)Pmh_GetExtStatusCode(&pm_header); - - self->wd.request_started = false; /* status finishes a wd request */ - - switch ((Pmp_StatusType_t)current_type) - { - case PMP_STATUS_TYPE_FAILURE: - Fifo_TxUpdateCurrentStatus(self, current_sid, current_type, Fifo_RxCheckFailureCode(self, current_code)); /* just update status type FAILURE */ - break; - case PMP_STATUS_TYPE_FLOW: - Fifo_TxUpdateCurrentStatus(self, current_sid, current_type, current_code); /* just update status type FLOW (codes: BUSY, NACK, SUCCESS, CANCELED) */ - break; - case PMP_STATUS_TYPE_SYNCED: - Fifo_RxProcessSyncStatus(self, current_sid, current_type, current_code, header_ptr); - break; - case PMP_STATUS_TYPE_UNSYNCED_BSY: - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_RxProcessStatus(): FIFO: %u, state: %u, received UNSYNCED_BSY", 2U, self->config.fifo_id, self->sync_state)); - if (self->sync_state != FIFO_S_SYNCING) - { - Fifo_Stop(self, FIFO_S_UNSYNCED_BUSY, true); - } - break; - case PMP_STATUS_TYPE_UNSYNCED_RDY: - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_RxProcessStatus(): FIFO: %u, state: %u, received UNSYNCED_RDY", 2U, self->config.fifo_id, self->sync_state)); - if (self->sync_state == FIFO_S_SYNCING) - { - if (current_code == (uint8_t)PMP_UNSYNC_R_COMMAND) - { - Fifo_Synchronize(self); /* retry synchronization */ - } - } - else - { - Fifo_Stop(self, FIFO_S_UNSYNCED_READY, true); - } - break; - default: - /* ignore status */ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_RxProcessStatus(): FIFO: %u, state: %u, received UNKNOWN TYPE: %u", 3U, self->config.fifo_id, self->sync_state, current_type)); - break; - } -} - -/*! \brief Checks failure_code and sets invalid code to UCS_MSG_STAT_ERROR_UNKNOWN - * \param self The instance - * \param failure_code The INIC failure code - * \return Returns the checked failure code - */ -static uint8_t Fifo_RxCheckFailureCode(CPmFifo *self, uint8_t failure_code) -{ - uint8_t ret; - MISC_UNUSED(self); - - switch (failure_code) - { - case (uint8_t)UCS_MSG_STAT_ERROR_CFG_NO_RCVR: - case (uint8_t)UCS_MSG_STAT_ERROR_BF: - case (uint8_t)UCS_MSG_STAT_ERROR_CRC: - case (uint8_t)UCS_MSG_STAT_ERROR_ID: - case (uint8_t)UCS_MSG_STAT_ERROR_ACK: - case (uint8_t)UCS_MSG_STAT_ERROR_TIMEOUT: - case (uint8_t)UCS_MSG_STAT_ERROR_FATAL_WT: - case (uint8_t)UCS_MSG_STAT_ERROR_FATAL_OA: - case (uint8_t)UCS_MSG_STAT_ERROR_NA_TRANS: - case (uint8_t)UCS_MSG_STAT_ERROR_NA_OFF: - ret = failure_code; - break; - default: - ret = (uint8_t)UCS_MSG_STAT_ERROR_UNKNOWN; - break; - } - - return ret; -} - -/*! \brief Processes an Rx command message - * \param self The instance - * \param msg_ptr The Rx command message - */ -static void Fifo_RxProcessCommand(CPmFifo *self, CMessage *msg_ptr) -{ - MISC_UNUSED(msg_ptr); - /* be aware that PMHL might vary */ - Pmcmd_SetTrigger(&self->rx.status, true); /* just trigger latest Rx status now */ -} - -/*! \brief Processes a status SYNCED from the INIC - * \param self The instance - * \param sid The sid of the sync status - * \param type The type of the sync status - * \param code The code of the sync status - * \param header_ptr Pointer to the raw port message - * \return The current synchronization state - */ -static void Fifo_RxProcessSyncStatus(CPmFifo *self, uint8_t sid, uint8_t type, uint8_t code, uint8_t *header_ptr) -{ - bool check = false; - uint8_t tx_credits = 0U; - - TR_ASSERT(self->init.base_ptr->ucs_user_ptr, "[FIFO]", (type==(uint8_t)PMP_STATUS_TYPE_SYNCED)); - MISC_UNUSED(type); - MISC_UNUSED(code); - - if (Pmp_GetDataSize(header_ptr) == 4U) - { - tx_credits = Pmp_GetData(header_ptr, 0U) & (uint8_t)PMP_CREDITS_MASK; - - if ((tx_credits >= PMP_CREDITS_MIN) && - (Pmp_GetData(header_ptr, 1U) == self->sync_params[1]) && - (Pmp_GetData(header_ptr, 2U) == self->sync_params[2]) && - (Pmp_GetData(header_ptr, 3U) == self->sync_params[3]) && - (sid == (self->sync_cnt))) - { - check = true; /* the sync status parameters are correct */ - } - } - - if ((check != false) && (self->sync_state == FIFO_S_SYNCING)) - { - Fifo_InitCounters(self, sid, tx_credits); /* values are incremented on each sync attempt */ - self->sync_state = FIFO_S_SYNCED; /* sync status shall have 4 bytes message body */ - self->rx.wait_processing = false; - Fifo_TxStartWatchdog(self); - Sub_Notify(&self->sync_state_subject, &self->config.fifo_id); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Synchronization */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Synchronizes the FIFO - * \param self The instance - */ -void Fifo_Synchronize(CPmFifo *self) -{ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Synchronize(): FIFO: %u, state: %u", 2U, self->config.fifo_id, self->sync_state)); - self->sync_state = FIFO_S_SYNCING; - Pmcmd_SetTrigger(&self->tx.sync_cmd, true); - Srv_SetEvent(&self->service, FIFO_SE_TX_SERVICE); -} - -/*! \brief Un-synchronizes the FIFO - * \param self The instance - */ -void Fifo_Unsynchronize(CPmFifo *self) -{ - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_Unsynchronize(): FIFO: %u, state: %u", 2U, self->config.fifo_id, self->sync_state)); - if (self->sync_state != FIFO_S_UNSYNCED_READY) - { - self->sync_state = FIFO_S_UNSYNCING; - Pmcmd_SetTrigger(&self->tx.sync_cmd, true); - Srv_SetEvent(&self->service, FIFO_SE_TX_SERVICE); - } -} - -/*! \brief Retrieves the current synchronization state - * \param self The instance - * \return The current synchronization state - */ -Fifo_SyncState_t Fifo_GetState(CPmFifo *self) -{ - return self->sync_state; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Watchdog */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Starts the watchdog handling - * \param self The instance - */ -static void Fifo_TxStartWatchdog(CPmFifo *self) -{ - self->wd.request_started = false; - - TR_INFO((self->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxStartWatchdog(): fifo_id: %u, timeout: %u", 2U, self->config.fifo_id, self->wd.timer_value)); - - if (self->wd.timer_value != 0U) - { - Tm_SetTimer(&self->init.base_ptr->tm, &self->wd.timer, &Fifo_TxOnWatchdogTimer, - self, - self->wd.timer_value, - self->wd.timer_value - ); - } -} - -/*! \brief Callback function which is invoked if the watchdog timer expires - * \param self The instance - */ -static void Fifo_TxOnWatchdogTimer(void *self) -{ - CPmFifo *self_ = (CPmFifo*)self; - - TR_INFO((self_->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxOnWatchdogTimer(): FIFO: %u, state: %u", 2U, self_->config.fifo_id, self_->sync_state)); - - if (self_->wd.request_started == false) - { - if (Pmcmd_Reserve(&self_->wd.wd_cmd) != false) - { - self_->wd.request_started = true; /* indicate that a status is expected */ - Pmcmd_UpdateContent(&self_->wd.wd_cmd, self_->tx.sid_next_to_use - 1U, PMP_CMD_TYPE_REQ_STATUS, PMP_CMD_CODE_REQ_STATUS); - Pmch_Transmit(self_->init.channel_ptr, Pmcmd_GetLldTxObject(&self_->wd.wd_cmd)); - } - else - { - TR_ERROR((self_->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxOnWatchdogTimer(): Unable to reserve watchdog command ", 0U)); - Fifo_Stop(self_, FIFO_S_UNSYNCED_INIT, true); - } - } - else /* status not received in time - notify communication error */ - { - TR_ERROR((self_->init.base_ptr->ucs_user_ptr, "[FIFO]", "Fifo_TxOnWatchdogTimer(): Missing response on status request", 0U)); - Fifo_Stop(self_, FIFO_S_UNSYNCED_INIT, true); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmfifos.c b/ucs2-lib/src/ucs_pmfifos.c deleted file mode 100644 index 347c1b9..0000000 --- a/ucs2-lib/src/ucs_pmfifos.c +++ /dev/null @@ -1,448 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class CPmFifos - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMFIFOS - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmfifos.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief The initialization value of sync_count. It is incremented for each sync or un-sync attempt. */ -static const uint8_t FIFOS_SYNC_CNT_INITIAL = 0xFFU; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal typedefs */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Fifos_Cleanup(CPmFifos *self); -static void Fifos_OnSyncTimeout(void *self); -static void Fifos_OnUnsyncTimeout(void *self); -static void Fifos_OnFifoEvent(void *self, void *fifo_id_ptr); - -static void Fifos_HandleFifoStateChange(CPmFifos *self, Pmp_FifoId_t fifo_id); -static bool Fifos_AreAllFifosInState(CPmFifos *self, Fifo_SyncState_t target_state); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CPmFifos - * \param self The instance - * \param base_ptr Reference to basic services - * \param channel_ptr Reference to the port message channel - * \param icm_fifo_ptr Reference to ICM FIFO, or NULL. - * \param mcm_fifo_ptr Reference to MCM FIFO, or NULL. - * \param rcm_fifo_ptr Reference to RCM FIFO, or NULL. - * \details At least one FIFO (MCM or ICM) must be provided. - */ -void Fifos_Ctor(CPmFifos *self, CBase *base_ptr, CPmChannel *channel_ptr, CPmFifo *icm_fifo_ptr, CPmFifo *mcm_fifo_ptr, CPmFifo *rcm_fifo_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - - self->base_ptr = base_ptr; - self->channel_ptr = channel_ptr; - self->state = FIFOS_S_UNSYNCED; - - self->unsync_initial = false; - Fifos_ConfigureSyncParams(self, FIFOS_SYNC_RETRIES, FIFOS_SYNC_TIMEOUT); - - self->fifos[PMP_FIFO_ID_ICM] = icm_fifo_ptr; - self->fifos[PMP_FIFO_ID_RCM] = rcm_fifo_ptr; - self->fifos[PMP_FIFO_ID_MCM] = mcm_fifo_ptr; - - T_Ctor(&self->init_timer); - Sub_Ctor(&self->event_subject, self->base_ptr->ucs_user_ptr); - Obs_Ctor(&self->obs_icm, self, &Fifos_OnFifoEvent); - Obs_Ctor(&self->obs_rcm, self, &Fifos_OnFifoEvent); - Obs_Ctor(&self->obs_mcm, self, &Fifos_OnFifoEvent); - - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[FIFOS]", (!((icm_fifo_ptr == NULL) && (mcm_fifo_ptr == NULL)))); - - if (icm_fifo_ptr != NULL) - { - Fifo_AddStateObserver(icm_fifo_ptr, &self->obs_icm); - } - - if (rcm_fifo_ptr != NULL) - { - Fifo_AddStateObserver(rcm_fifo_ptr, &self->obs_rcm); - } - - if (mcm_fifo_ptr != NULL) - { - Fifo_AddStateObserver(mcm_fifo_ptr, &self->obs_mcm); - } - - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_Ctor(): FIFOS created, state %d", 1U, self->state)); -} - -/*! \brief Adds an observer of synchronization events - * \param self The instance - * \param obs_ptr The observer. The notification result type is Fifos_Event_t. - */ -void Fifos_AddEventObserver(CPmFifos *self, CObserver *obs_ptr) -{ - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[FIFOS]", (obs_ptr != 0)); - (void)Sub_AddObserver(&self->event_subject, obs_ptr); -} - -/*! \brief Removes an observer of synchronization events - * \param self The instance - * \param obs_ptr The observer. - */ -void Fifos_RemoveEventObserver(CPmFifos *self, CObserver *obs_ptr) -{ - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[FIFOS]", (obs_ptr != 0)); - (void)Sub_RemoveObserver(&self->event_subject, obs_ptr); -} - -/*! \brief Forces all FIFOs to state UNSYNCED without waiting for INIC responses and - * without throwing events - * \details Stops the LLD interface and releases all pending message resources. - * This function shall be called if the UCS requires a un-normal termination - * which is not detected by port message protocol. - * \param self The instance - */ -void Fifos_ForceTermination(CPmFifos *self) -{ - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_ForceTermination(): Termination started, state: %d", 1U, self->state)); - Fifos_Cleanup(self); - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_ForceTermination(): Termination done, state: %d", 1U, self->state)); -} - -/*! \brief Configures retries and timeout for synchronize or un-synchronize - * operation - * \details This method shall be called before starting a synchronization or un-synchronization - * or after it has finished. The current counter of synchronization attempts is reset. - * \param self The instance - * \param retries The number of retries until event FIFOS_EV_SYNC_FAILED or - * FIFOS_EV_UNSYNC_FAILED will be notified - * \param timeout The timeout in milliseconds when the retry is performed - */ -void Fifos_ConfigureSyncParams(CPmFifos *self, uint8_t retries, uint16_t timeout) -{ - self->cmd_retries = retries; - self->cmd_timeout = timeout; - self->sync_cnt = FIFOS_SYNC_CNT_INITIAL; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Synchronization */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Initializes all port message FIFOs - * \details Possible results of the operation are the following events which are fired - * asynchronously. Refer also Fifos_AddEventObserver() and \ref Fifos_Event_t. - * - \ref FIFOS_EV_SYNC_ESTABLISHED - * - \ref FIFOS_EV_SYNC_FAILED - * \param self The instance - * \param reset_cnt If \c true resets the synchronization counter. In this case an automatic - * retries will be done after the first synchronization timeout. - * \param force_sync If \c true the method will also trigger the synchronization of already - * synced \ref CPmFifo objects. - */ -void Fifos_Synchronize(CPmFifos *self, bool reset_cnt, bool force_sync) -{ - uint8_t cnt; - self->state = FIFOS_S_SYNCING; - self->unsync_initial = false; - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_Synchronize(): Synchronization started, state: %d", 1U, self->state)); - - if (reset_cnt) - { - self->sync_cnt = FIFOS_SYNC_CNT_INITIAL; - } - - self->sync_cnt++; - Pmch_Initialize(self->channel_ptr); /* Start LLD if not already done */ - - for (cnt = 0U; cnt < PMP_MAX_NUM_FIFOS; cnt++) - { - if (self->fifos[cnt] != NULL) - { - if (force_sync || (Fifo_GetState(self->fifos[cnt]) != FIFO_S_SYNCED)) - { - Fifo_Synchronize(self->fifos[cnt]); - } - } - } - - Tm_SetTimer(&self->base_ptr->tm, &self->init_timer, - &Fifos_OnSyncTimeout, self, - self->cmd_timeout, 0U); -} - -/*! \brief Un-initializes all port message FIFOs - * \details Possible results of the operation are the following events which are fired - * asynchronously. Refer also Fifos_AddEventObserver() and \ref Fifos_Event_t. - * - \ref FIFOS_EV_UNSYNC_COMPLETE - * - \ref FIFOS_EV_UNSYNC_FAILED - * \param self The instance - * \param reset_cnt If \c true resets the synchronization counter. In this case an automatic - * retries will be done after the first synchronization timeout. - * \param initial If the un-synchronization shall be executed prior to a initial synchronization - * it is recommended to set the argument to \c true. After notifying the event - * FIFOS_EV_UNSYNC_COMPLETE the LLD interface will not be stopped. The subsequent - * call of Fifos_Synchronize() will not start the LLD interface un-necessarily. - * To trigger a final un-synchronization \c initial shall be set to \c false. - * I.e., FIFOS_EV_UNSYNC_COMPLETE stops the LLD interface. - */ -void Fifos_Unsynchronize(CPmFifos *self, bool reset_cnt, bool initial) -{ - uint8_t cnt; - self->state = FIFOS_S_UNSYNCING; - self->unsync_initial = initial; - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_Unsynchronize(): Un-synchronization started, state: %d", 1U, self->state)); - - if (reset_cnt) - { - self->sync_cnt = FIFOS_SYNC_CNT_INITIAL; - } - - self->sync_cnt++; - Pmch_Initialize(self->channel_ptr); /* Start LLD if not already done */ - - for (cnt = 0U; cnt < PMP_MAX_NUM_FIFOS; cnt++) - { - if (self->fifos[cnt] != NULL) - { - if (initial || (Fifo_GetState(self->fifos[cnt]) != FIFO_S_UNSYNCED_READY)) - { - Fifo_Unsynchronize(self->fifos[cnt]); - } - } - } - - Tm_SetTimer(&self->base_ptr->tm, &self->init_timer, - &Fifos_OnUnsyncTimeout, self, - self->cmd_timeout, 0U); -} - -/*! \brief Handles the synchronization timeout - * \param self The instance - */ -static void Fifos_OnSyncTimeout(void *self) -{ - CPmFifos *self_ = (CPmFifos*)self; - Fifos_Event_t the_event = FIFOS_EV_SYNC_FAILED; - - self_->state = FIFOS_S_UNSYNCED; - - TR_INFO((self_->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_OnSyncTimeout(): state: %d", 1U, self_->state)); - - if (self_->sync_cnt < self_->cmd_retries) - { - Fifos_Synchronize(self_, false, false); /* retry synchronization after first timeout */ - } - else - { - Fifos_Cleanup(self_); - Sub_Notify(&self_->event_subject, &the_event); - } -} - -/*! \brief Handles the un-synchronization timeout - * \param self The instance - */ -static void Fifos_OnUnsyncTimeout(void *self) -{ - CPmFifos *self_ = (CPmFifos*)self; - Fifos_Event_t the_event = FIFOS_EV_UNSYNC_FAILED; - - self_->state = FIFOS_S_UNSYNCED; - TR_INFO((self_->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_OnUnsyncTimeout(): state: %d", 1U, self_->state)); - - if (self_->sync_cnt < self_->cmd_retries) - { - Fifos_Unsynchronize(self_, false, self_->unsync_initial); /* retry synchronization after first timeout */ - } - else - { - self_->unsync_initial = false; /* un-sync timeout will lead to termination - stop LLD */ - Fifos_Cleanup(self_); - Sub_Notify(&self_->event_subject, &the_event); - } -} - -/*! \brief Performs a cleanup of the Port Message Channel and the dedicated FIFOs - * \details Releases all message objects which are currently in use. - * \param self The instance - */ -static void Fifos_Cleanup(CPmFifos *self) -{ - uint8_t count; - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_Cleanup(): Channel cleanup started", 0U)); - - if (self->unsync_initial == false) - { - Pmch_Uninitialize(self->channel_ptr); - } - - for (count = 0U; count < PMP_MAX_NUM_FIFOS; count++) /* stop & cleanup all FIFOs */ - { - if (self->fifos[count] != NULL) - { /* stop and avoid recursion */ - Fifo_Stop(self->fifos[count], FIFO_S_UNSYNCED_INIT, false); - Fifo_Cleanup(self->fifos[count]); - } - } - - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_Cleanup(): Channel cleanup completed", 0U)); - - /* notify external event after message objects were released */ - self->state = FIFOS_S_UNSYNCED; -} - -/*------------------------------------------------------------------------------------------------*/ -/* FIFO observation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Notifies an event to the host class - * \param self The instance - * \param fifo_id_ptr Specific event identifier, pointer to "fifo_id" - */ -static void Fifos_OnFifoEvent(void *self, void *fifo_id_ptr) -{ - CPmFifos *self_ = (CPmFifos*)self; - Fifos_HandleFifoStateChange(self_, *((Pmp_FifoId_t*)fifo_id_ptr)); -} - -/*! \brief Executes transition to new synchronization states - * \param self The instance - * \param fifo_id The FIFO identifier - */ -static void Fifos_HandleFifoStateChange(CPmFifos *self, Pmp_FifoId_t fifo_id) -{ - Fifos_Event_t the_event; - - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): FIFOs state: %d, FIFO: %d, FIFO State: %d", 3U, - self->state, fifo_id, Fifo_GetState(self->fifos[fifo_id]))); - - switch (self->state) - { - case FIFOS_S_SYNCING: - if (Fifos_AreAllFifosInState(self, FIFO_S_SYNCED)) - { - self->state = FIFOS_S_SYNCED; /* now the complete channel is synced */ - Tm_ClearTimer(&self->base_ptr->tm, &self->init_timer); - Fifos_ConfigureSyncParams(self, FIFOS_UNSYNC_RETRIES, FIFOS_UNSYNC_TIMEOUT); - the_event = FIFOS_EV_SYNC_ESTABLISHED; - Sub_Notify(&self->event_subject, &the_event); - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Synchronization of Port Message channel completed", 0U)); - } - break; - - case FIFOS_S_UNSYNCING: - if (Fifos_AreAllFifosInState(self, FIFO_S_UNSYNCED_READY)) - { - Fifos_Cleanup(self); - self->state = FIFOS_S_UNSYNCED; /* now the complete channel is un-synced */ - Tm_ClearTimer(&self->base_ptr->tm, &self->init_timer); - the_event = FIFOS_EV_UNSYNC_COMPLETE; - Sub_Notify(&self->event_subject, &the_event); - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Un-synchronization of Port Message channel completed", 0U)); - } - break; - - case FIFOS_S_SYNCED: - if (!Fifos_AreAllFifosInState(self, FIFO_S_SYNCED)) - { - self->state = FIFOS_S_UNSYNCING; /* set state to 'unsyncing' and wait until all FIFOs are unsynced */ - self->sync_cnt = 0U; /* pretend having triggered an un-sync which starts the timer */ - Tm_SetTimer(&self->base_ptr->tm, &self->init_timer, - &Fifos_OnUnsyncTimeout, self, - FIFOS_UNSYNC_TIMEOUT, 0U); - the_event = FIFOS_EV_SYNC_LOST; - Sub_Notify(&self->event_subject, &the_event); - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Lost synchronization of Port Message channel", 0U)); - } - if (Fifos_AreAllFifosInState(self, FIFO_S_UNSYNCED_READY)) - { - Fifos_Cleanup(self); - self->state = FIFOS_S_UNSYNCED; /* the complete channel suddenly goes unsynced_complete */ - Tm_ClearTimer(&self->base_ptr->tm, &self->init_timer); - the_event = FIFOS_EV_UNSYNC_COMPLETE; - Sub_Notify(&self->event_subject, &the_event); - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Sudden un-synchronization of Port Message channel completed", 0U)); - } - break; - - case FIFOS_S_UNSYNCED: - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Unexpected FIFO event in state unsynced", 0U)); - break; - - default: - TR_INFO((self->base_ptr->ucs_user_ptr, "[FIFOS]", "Fifos_HandleFifoStateChange(): Unexpected FIFOs state", 0U)); - break; - } - - MISC_UNUSED(fifo_id); -} - -/*! \brief Helper function that evaluates if all configured FIFOs are in a given state - * \param self The instance - * \param target_state The required state that is evaluated for all FIFOs - * \return \c true if all FIFOs are in the given \c target_state, otherwise \c false. - */ -static bool Fifos_AreAllFifosInState(CPmFifos *self, Fifo_SyncState_t target_state) -{ - bool ret = true; - uint8_t cnt; - - for (cnt = 0U; cnt < PMP_MAX_NUM_FIFOS; cnt++) - { - if (self->fifos[cnt] != NULL) - { - Fifo_SyncState_t state = Fifo_GetState(self->fifos[cnt]); - - if (state != target_state) - { - ret = false; - } - } - } - - return ret; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pmp.c b/ucs2-lib/src/ucs_pmp.c deleted file mode 100644 index ae33306..0000000 --- a/ucs2-lib/src/ucs_pmp.c +++ /dev/null @@ -1,350 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Port Message Protocol - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PMH - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pmp.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* PMP Indexes */ -/*------------------------------------------------------------------------------------------------*/ -#define PMP_IDX_PML_H 0U -#define PMP_IDX_PML_L 1U -#define PMP_IDX_PMHL 2U -#define PMP_IDX_FPH 3U -#define PMP_IDX_SID 4U -#define PMP_IDX_EXT_TYPE 5U - -/*------------------------------------------------------------------------------------------------*/ -/* Masks and shifts for bit fields */ -/*------------------------------------------------------------------------------------------------*/ -#define PMP_PMHL_MASK 0x1FU /* 0b00011111 */ -#define PMP_VERSION_MASK 0xE0U /* 0b11100000 */ -#define PMP_VERSION 0x40U /* Version: "2" */ -#define PMP_FPH_TYPE_POS 1U -#define PMP_FPH_TYPE_MASK 0x06U /* 0b00000110 */ -#define PMP_FPH_ID_POS 3U -#define PMP_FPH_ID_MASK 0x38U /* 0b00111000 */ -#define PMP_FPH_DIR_RX 0x01U /* RX: "1" */ -#define PMP_FPH_DIR_MASK 0x01U /* 0b00000001 */ -#define PMP_EXT_TYPE_POS 5U -#define PMP_EXT_TYPE_MASK 0xE0U /* 0b11100000 */ -#define PMP_EXT_CODE_MASK 0x1FU /* 0b00011111 */ - -/*------------------------------------------------------------------------------------------------*/ -/* PMP Verification */ -/*------------------------------------------------------------------------------------------------*/ -#define PMP_PML_MAX_SIZE_CTRL 69U -#define PMP_PMHL_MIN_SIZE 3U -#define PMP_PMHL_MAX_SIZE 5U - -/*------------------------------------------------------------------------------------------------*/ -/* Macro like functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Sets the port message length within a given message header - * \param header The message header - * \param length The port message length - */ -void Pmp_SetPml(uint8_t header[], uint8_t length) -{ - header[PMP_IDX_PML_H] = 0U; - header[PMP_IDX_PML_L] = length; -} - -/*! \brief Sets the port message header length within a given message header - * \param header The message header - * \param length The port message header length. Valid values: 3..5. - * Invalid values will set the PMHL to \c 0. - */ -void Pmp_SetPmhl(uint8_t header[], uint8_t length) -{ - if ((length < PMP_PMHL_MIN_SIZE) || (length > PMP_PMHL_MAX_SIZE)) - { - length = 0U; - } - - header[PMP_IDX_PMHL] = length | PMP_VERSION; -} - -/*! \brief Sets the FIFO protocol header within a given message header - * \param header The message header - * \param id The FIFO id - * \param type The port message type - */ -void Pmp_SetFph(uint8_t header[], Pmp_FifoId_t id, Pmp_MsgType_t type) -{ - header[PMP_IDX_FPH] = (uint8_t)((uint8_t)type << PMP_FPH_TYPE_POS) | (uint8_t)((uint8_t)id << PMP_FPH_ID_POS) | (uint8_t)PMP_DIR_TX; -} - -/*! \brief Sets the field ExtType within a given message header - * \param header The message header - * \param type The command or status type - * \param code The command or status code - */ -void Pmp_SetExtType(uint8_t header[], uint8_t type, uint8_t code) -{ - header[PMP_IDX_EXT_TYPE] = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK); -} - -/*! \brief Sets the sequence id within a given message header - * \param header The message header - * \param sid The sequence id - */ -void Pmp_SetSid(uint8_t header[], uint8_t sid) -{ - header[PMP_IDX_SID] = sid; -} - -/*! \brief Retrieves the port message length of a given port message buffer - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \return The port message length in bytes or 0 if the PML is greater than 255. - */ -uint8_t Pmp_GetPml(uint8_t header[]) -{ - uint8_t pml; - if (header[PMP_IDX_PML_H] != 0U) - { - pml = 0U; - } - else - { - pml = header[PMP_IDX_PML_L]; - } - - return pml; -} - -/*! \brief Retrieves the port message header length of a given port message buffer - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \return The port message header length in bytes - */ -uint8_t Pmp_GetPmhl(uint8_t header[]) -{ - return ((uint8_t)(header[PMP_IDX_PMHL] & (uint8_t)PMP_PMHL_MASK)); -} - -/*! \brief Retrieves the FIFO number of a given port message buffer - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \return The FIFO number - */ -Pmp_FifoId_t Pmp_GetFifoId(uint8_t header[]) -{ - return (Pmp_FifoId_t)(((uint8_t)PMP_FPH_ID_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_ID_POS); -} - -/*! \brief Retrieves the FIFO Type of a given port message buffer - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \return The FIFO type - */ -Pmp_MsgType_t Pmp_GetMsgType(uint8_t header[]) -{ - return ((Pmp_MsgType_t)((PMP_FPH_TYPE_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_TYPE_POS)); -} - -/*! \brief Retrieves the SequenceID of a given port message buffer - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \return The SequenceID - */ -uint8_t Pmp_GetSid(uint8_t header[]) -{ - return ((header)[PMP_IDX_SID]); -} - -/*! \brief Retrieves payload data of a port message - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \param index The index of the payload byte starting with '0' - * \return The content of a payload data byte - */ -uint8_t Pmp_GetData(uint8_t header[], uint8_t index) -{ - return header[Pmp_GetPmhl(header) + 3U + index]; -} - -/*! \brief Retrieves the payload size of the port message - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \details The function Pmp_VerifyHeader() must be called before - * to verify that the port message fields are consistent. - * \return The payload size of a port message - */ -uint8_t Pmp_GetDataSize(uint8_t header[]) -{ - return Pmp_GetPml(header) - (Pmp_GetPmhl(header) + 1U); -} - -/*! \brief Checks if header length fields are set to valid values - * \param header Data buffer containing the port message. - * The required size of this buffer is 6 bytes. - * \param buf_len Length of the complete port message in bytes - * \return Returns \c true if the header was checked successfully, - * otherwise \c false. - */ -bool Pmp_VerifyHeader(uint8_t header[], uint8_t buf_len) -{ - uint8_t pml = Pmp_GetPml(header); - uint8_t pmhl = Pmp_GetPmhl(header); - bool ok = true; - - ok = ((pmhl >= 3U)&&(pmhl <= 5U)) ? ok : false; - ok = ((header[PMP_IDX_PMHL] & PMP_VERSION_MASK) == PMP_VERSION) ? ok : false; - ok = (pml >= (pmhl + 1U)) ? ok : false; - ok = ((pml + 2U) <= buf_len) ? ok : false; - ok = (pml <= PMP_PML_MAX_SIZE_CTRL) ? ok : false; - ok = ((header[PMP_IDX_FPH] & PMP_FPH_DIR_MASK) == PMP_FPH_DIR_RX) ? ok : false; - - return ok; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Creates a Port Message Header instance - * \param self The instance - */ -void Pmh_Ctor(CPmh *self) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); -} - -/*! \brief Inserts a port message header of the specified size into a given buffer - * \param self Header content to be written to the buffer (source) - * \param data Data buffer the header shall be written to (target) - */ -void Pmh_BuildHeader(CPmh *self, uint8_t data[]) -{ - uint8_t cnt; - - data[PMP_IDX_PML_H] = 0U; - data[PMP_IDX_PML_L] = (uint8_t)self->pml; - data[PMP_IDX_PMHL] = (uint8_t)PMP_VERSION | self->pmhl; - data[PMP_IDX_FPH] = (uint8_t)PMP_DIR_TX | ((uint8_t)((self->fifo_id) << PMP_FPH_ID_POS)) | - ((uint8_t)((self->msg_type) << PMP_FPH_TYPE_POS)); - - data[PMP_IDX_SID] = self->sid; - data[PMP_IDX_EXT_TYPE]= self->ext_type; - - for (cnt=3U; cnt < self->pmhl; cnt++) - { - data[3U + cnt] = 0U; /* add stuffing bytes */ - } -} - -/*! \brief Decodes a given data buffer into a provided port message header structure - * \param self Header content structure (target) - * \param data Data buffer containing the port message with a minimum size - * of 6 bytes (source) - */ -void Pmh_DecodeHeader(CPmh *self, uint8_t data[]) -{ - self->pml = Pmp_GetPml(data); - self->pmhl = data[PMP_IDX_PMHL] & PMP_PMHL_MASK; /* ignore version */ - - self->fifo_id = Pmp_GetFifoId(data); - self->msg_type = Pmp_GetMsgType(data); - self->sid = data[PMP_IDX_SID]; - self->ext_type = data[PMP_IDX_EXT_TYPE]; -} - -/*! \brief Setter function for FIFO protocol header which contains several subfields - * \details The "retransmitted" flag is currently not supported (always Tx) - * \param self Reference to the PM content structure that shall be modified - * \param fifo_id Id of the PM FIFO - * \param msg_type PM type - */ -void Pmh_SetFph(CPmh *self, Pmp_FifoId_t fifo_id, Pmp_MsgType_t msg_type) -{ - self->msg_type = msg_type; - self->fifo_id = fifo_id; -} - -/*! \brief Retrieves the ExtType StatusType - * \param self The instance - * \return Returns The Status Type - */ -Pmp_StatusType_t Pmh_GetExtStatusType(CPmh *self) -{ - return ((Pmp_StatusType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS)); -} - -/*! \brief Retrieves the ExtType StatusCode - * \param self The instance - * \return Returns The Status Code - */ -Pmp_CommandCode_t Pmh_GetExtCommandCode(CPmh *self) -{ - return ((Pmp_CommandCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type)); -} - -/*! \brief Retrieves the ExtType StatusType - * \param self The instance - * \return Returns The Status Type - */ -Pmp_CommandType_t Pmh_GetExtCommandType(CPmh *self) -{ - return ((Pmp_CommandType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS)); -} - -/*! \brief Retrieves the ExtType StatusCode - * \param self The instance - * \return Returns The Status Code - */ -Pmp_StatusCode_t Pmh_GetExtStatusCode(CPmh *self) -{ - return ((Pmp_StatusCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type)); -} - -/*! \brief Sets the ExtType field by passing the values for type and code - * \details The function is applicable for status and command - * \param self The Instance - * \param type The status or command type - * \param code The status or command code - */ -void Pmh_SetExtType(CPmh *self, uint8_t type, uint8_t code) -{ - self->ext_type = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_pool.c b/ucs2-lib/src/ucs_pool.c deleted file mode 100644 index 1824b27..0000000 --- a/ucs2-lib/src/ucs_pool.c +++ /dev/null @@ -1,126 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 message pool class - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_POOL - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_pool.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of message pool class - * \param self The instance - * \param messages Reference to an array of message objects - * \param size Number of message objects the \c messages array is comprising. - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Pool_Ctor(CPool *self, CMessage messages[], uint16_t size, void *ucs_user_ptr) -{ - uint16_t index; - - MISC_MEM_SET(self, 0, sizeof(*self)); - self->ucs_user_ptr = ucs_user_ptr; - self->initial_size = size; - self->messages = messages; - - Dl_Ctor(&self->message_list, self->ucs_user_ptr); - - for (index = 0U; index < size; index++) - { - Msg_Ctor(&messages[index]); - Msg_SetPoolReference(&messages[index], self); - Dl_InsertTail(&self->message_list, Msg_GetNode(&messages[index])); - } -} - -/*! \brief Retrieves a message object from the pool - * \param self The instance - * \return Reference to the CMessage structure if a message is available. - * Otherwise \c NULL. - */ -CMessage* Pool_GetMsg(CPool *self) -{ - CMessage *msg = NULL; - CDlNode *node = Dl_PopHead(&self->message_list); - - if (node != NULL) - { - msg = (CMessage*)node->data_ptr; - } - - return msg; -} - -/*! \brief Returns a message object to the pool pre-assigned pool - * \param msg_ptr Reference to the message object which needs - * to be returned to the pool. - */ -void Pool_ReturnMsg(CMessage *msg_ptr) -{ - CPool *pool_ptr = (CPool*)Msg_GetPoolReference(msg_ptr); - - if (pool_ptr != NULL) - { - TR_ASSERT(pool_ptr->ucs_user_ptr, "[POOL]", (Pool_GetCurrentSize(pool_ptr) < pool_ptr->initial_size)); - Dl_InsertTail(&pool_ptr->message_list, Msg_GetNode(msg_ptr)); - } - else - { - TR_ERROR((0U, "[POOL]", "Pool_ReturnMsg(): released msg_ptr=0x%p without pool reference", 1U, msg_ptr)); - } -} - -/*! \brief Retrieves the current number of available message objects in the pool - * \param self The instance - * \return The current number of available message objects in the pool - */ -uint16_t Pool_GetCurrentSize(CPool *self) -{ - uint16_t list_size = Dl_GetSize(&self->message_list); - - return list_size; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_prog.c b/ucs2-lib/src/ucs_prog.c deleted file mode 100644 index e64d519..0000000 --- a/ucs2-lib/src/ucs_prog.c +++ /dev/null @@ -1,957 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Programming Service. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_PROG_MODE - * @{ - - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_inic_pb.h" -#include "ucs_prog.h" -#include "ucs_misc.h" - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -#define PRG_NUM_STATES 6U /*!< \brief Number of state machine states */ -#define PRG_NUM_EVENTS 13U /*!< \brief Number of state machine events */ - -#define PRG_TIMEOUT_COMMAND 100U /*!< \brief supervise EXC commands */ - -#define PRG_SIGNATURE_VERSION 1U /*!< \brief signature version used for Node Discovery */ - -#define PRG_ADMIN_BASE_ADDR 0x0F00U /*!< \brief bas admin address */ - - -/* Error values */ -#define PRG_HW_RESET_REQ 0x200110U /* HW reset required */ -#define PRG_SESSION_ACTIVE 0x200111U /* Session already active */ -#define PRG_CFG_STRING_ERROR 0x200220U /* A configuration string erase error has occurred. */ -#define PRG_MEM_ERASE_ERROR 0x200221U /* An error memory erase error has occurred.*/ -#define PRG_CFG_WRITE_ERROR 0x200225U /* Configuration memory write error. */ -#define PRG_CFG_FULL_ERROR 0x200226U /* Configuration memory is full. */ -#define PRG_HDL_MATCH_ERROR 0x200330U /* The SessionHandle does not match the current memory session. */ -#define PRG_MEMID_ERROR 0x200331U /* The memory session does not support the requested MemID. */ -#define PRG_ADDR_EVEN_ERROR 0x200332U /* The Address is not even when writing the configuration memory. */ -#define PRG_LEN_EVEN_ERROR 0x200333U /* The UnitLen is not even when writing the configuration memory. */ - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the Programming service used by scheduler */ -static const uint8_t PRG_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the Programming service */ -static const Srv_Event_t PRG_EVENT_SERVICE = 1U; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal enumerators */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Possible events of the system diagnosis state machine */ -typedef enum Prg_Events_ -{ - PRG_E_NIL = 0U, /*!< \brief NIL Event */ - PRG_E_START = 1U, /*!< \brief API start command was called. */ - PRG_E_STOP = 2U, /*!< \brief Stop request occurred. */ - PRG_E_WELCOME_SUCCESS = 3U, /*!< \brief Welcome command was successful. */ - PRG_E_WELCOME_NOSUCCESS = 4U, /*!< \brief Welcome command was not successful. */ - PRG_E_MEM_WRITE_CMD = 5U, /*!< \brief MemorySessionOpen command was succcessful */ - PRG_E_MEM_WRITE_FINISH = 6U, /*!< \brief MemoryWrite command was succcessful */ - PRG_E_MEM_CLOSE_SUCCESS = 7U, /*!< \brief MemorySessionClose command was succcessful */ - PRG_E_NET_OFF = 8U, /*!< \brief NetOff occurred. */ - PRG_E_TIMEOUT = 9U, /*!< \brief Timeout occurred. */ - PRG_E_ERROR = 10U, /*!< \brief An error occurred which requires no command to be sent to the INIC. */ - PRG_E_ERROR_INIT = 11U, /*!< \brief Error requires Init.Start to be sent. */ - PRG_E_ERROR_CLOSE_INIT = 12U /*!< \brief Error requires MemorySessionClose.SR and Init.Start to be sent. */ -} Prg_Events_t; - - -/*! \brief States of the node discovery state machine */ -typedef enum Prg_State_ -{ - PRG_S_IDLE = 0U, /*!< \brief Idle state. */ - PRG_S_WAIT_WELCOME = 1U, /*!< \brief Programming started. */ - PRG_S_WAIT_MEM_OPEN = 2U, /*!< \brief Wait for MemorySessionOpen result. */ - PRG_S_WAIT_MEM_WRITE = 3U, /*!< \brief Wait for MemoryWrite result. */ - PRG_S_WAIT_MEM_CLOSE = 4U, /*!< \brief Wait for MemorySessionClose result. */ - PRG_S_WAIT_MEM_ERR_CLOSE = 5U /*!< \brief Wait for MemorySessionClose result in error case. */ -} Prg_State_t; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Prg_Service(void *self); - -static void Prg_WelcomeResultCb(void *self, void *result_ptr); -static void Prg_MemOpenResultCb(void *self, void *result_ptr); -static void Prg_MemWriteResultCb(void *self, void *result_ptr); -static void Prg_MemCloseResultCb(void *self, void *result_ptr); - -static void Prg_OnTerminateEventCb(void *self, void *result_ptr); -static void Prg_NetworkStatusCb(void *self, void *result_ptr); - -static void Prg_A_Start(void *self); -static void Prg_A_MemOpen(void *self); -static void Prg_A_MemWrite(void *self); -static void Prg_A_MemClose(void *self); -static void Prg_A_InitDevice(void *self); -static void Prg_A_NetOff(void *self); -static void Prg_A_Timeout(void *self); -static void Prg_A_Error(void *self); -static void Prg_A_Error_Init(void *self); -static void Prg_A_Error_Close_Init(void *self); - - -static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val); -static uint32_t Prg_CalcError(uint8_t val[]); - -static void Prg_TimerCb(void *self); - -/*------------------------------------------------------------------------------------------------*/ -/* State transition table (used by finite state machine) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief State transition table */ -static const Fsm_StateElem_t prg_trans_tab[PRG_NUM_STATES][PRG_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - { /* State PRG_S_IDLE */ - /* PRG_E_NIL */ {NULL, PRG_S_IDLE }, - /* PRG_E_START */ {Prg_A_Start, PRG_S_WAIT_WELCOME }, - /* PRG_E_STOP */ {NULL, PRG_S_IDLE }, - /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_IDLE }, - /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_IDLE }, - /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_IDLE }, - /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_IDLE }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_IDLE }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {NULL, PRG_S_IDLE }, - /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_IDLE }, - }, - { /* State PRG_S_WAIT_WELCOME */ - /* PRG_E_NIL */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_START */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_STOP */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_WELCOME_SUCCESS */ {Prg_A_MemOpen, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_WELCOME_NOSUCCESS */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {NULL, PRG_S_WAIT_WELCOME }, - /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_WAIT_WELCOME } - }, - { /* State PRG_S_WAIT_MEM_OPEN */ - /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_MEM_WRITE_CMD */ {Prg_A_MemWrite, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, - /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE } - }, - { /* State PRG_S_WAIT_MEM_WRITE */ - /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, - /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE } - }, - { /* State PRG_S_WAIT_MEM_CLOSE */ - /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_CLOSE }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_InitDevice, PRG_S_IDLE }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, - /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE }, - }, - { /* State PRG_S_WAIT_MEM_ERR_CLOSE */ - /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, - /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_Error_Init, PRG_S_IDLE }, - /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, - /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, - /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, - /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, - /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE }, - } - -}; - - -/*! \brief Constructor of class CProgramming. - * \param self Reference to CProgramming instance - * \param inic Reference to CInic instance - * \param base Reference to CBase instance - * \param exc Reference to CExc instance - */ - /* \param init_ptr Report callback function*/ -void Prg_Ctor(CProgramming *self, CInic *inic, CBase *base, CExc *exc) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->inic = inic; - self->exc = exc; - self->base = base; - - Fsm_Ctor(&self->fsm, self, &(prg_trans_tab[0][0]), PRG_NUM_EVENTS, PRG_E_NIL); - - Sobs_Ctor(&self->prg_welcome, self, &Prg_WelcomeResultCb); - Sobs_Ctor(&self->prg_memopen, self, &Prg_MemOpenResultCb); - Sobs_Ctor(&self->prg_memwrite, self, &Prg_MemWriteResultCb); - Sobs_Ctor(&self->prg_memclose, self, &Prg_MemCloseResultCb); - - /* register termination events */ - Mobs_Ctor(&self->prg_terminate, self, EH_M_TERMINATION_EVENTS, &Prg_OnTerminateEventCb); - Eh_AddObsrvInternalEvent(&self->base->eh, &self->prg_terminate); - - /* Register NetOn and MPR events */ - Obs_Ctor(&self->prg_nwstatus, self, &Prg_NetworkStatusCb); - Inic_AddObsrvNwStatus(self->inic, &self->prg_nwstatus); - self->neton = false; - - /* Initialize Programming service */ - Srv_Ctor(&self->service, PRG_SRV_PRIO, self, &Prg_Service); - /* Add Programming service to scheduler */ - (void)Scd_AddService(&self->base->scd, &self->service); - -} - - -/*! \brief Service function of the Node Discovery service. - * \param self Reference to Programming service object - */ -static void Prg_Service(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->service, &event_mask); - if(PRG_EVENT_SERVICE == (event_mask & PRG_EVENT_SERVICE)) /* Is event pending? */ - { - Fsm_State_t result; - Srv_ClearEvent(&self_->service, PRG_EVENT_SERVICE); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); - result = Fsm_Service(&self_->fsm); - TR_ASSERT(self_->base->ucs_user_ptr, "[PRG]", (result != FSM_STATE_ERROR)); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM -> %d", 1U, self_->fsm.current_state)); - MISC_UNUSED(result); - } -} - - - -/**************************************************************************************************/ -/* API functions */ -/**************************************************************************************************/ -/*! - * - * \param *self Reference to Programming service object - */ -/*! \brief Program a node - * - * \param *self Reference to Programming service object - * \param node_id Node position address of the node to be programmed - * \param *signature Signature of the node to be programmed - * \param session_type Defines the memory access type. - * \param command_list Refers to array of programming tasks. - * \param report_fptr Report callback function - */ -void Prg_Start(CProgramming *self, - uint16_t node_id, - Ucs_Signature_t *signature, - Ucs_Prg_SessionType_t session_type, - Ucs_Prg_Command_t* command_list, - Ucs_Prg_ReportCb_t report_fptr) -{ - - - self->node_id = node_id; - self->signature = *signature; - self->session_type = session_type; - self->command_list = command_list; - self->report_fptr = report_fptr; - self->current_function = UCS_PRG_FKT_DUMMY; - - if (self->neton == true) - { - Fsm_SetEvent(&self->fsm, PRG_E_START); - Srv_SetEvent(&self->service, PRG_EVENT_SERVICE); - - TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start", 0U)); - } - else - { - if (self->report_fptr != NULL) - { - self->report_fptr(UCS_PRG_RES_NET_OFF, - self->current_function, - 0U, - NULL, - self->base->ucs_user_ptr); - } - TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start failed: NET_OFF", 0U)); - } -} - - - -/**************************************************************************************************/ -/* FSM Actions */ -/**************************************************************************************************/ -/*! Action on Start command - * - * \param *self Reference to Node Discovery object - */ -static void Prg_A_Start(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Ucs_Return_t ret_val; - - if (self_->node_id == 0x0400U) - { - self_->target_address = UCS_ADDR_LOCAL_INIC; - } - else - { - self_->target_address = self_->node_id; - } - - self_->admin_node_address = PRG_ADMIN_BASE_ADDR + ((self_->node_id) & 0x00FFU); - self_->current_function = UCS_PRG_FKT_WELCOME; - - ret_val = Exc_Welcome_Sr(self_->exc, - self_->target_address, - self_->admin_node_address, - PRG_SIGNATURE_VERSION, - self_->signature, - &self_->prg_welcome); - Prg_Check_RetVal(self_, ret_val); -} - -static void Prg_A_MemOpen(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Ucs_Return_t ret_val; - - self_->current_function = UCS_PRG_FKT_MEM_OPEN; - - ret_val = Exc_MemSessionOpen_Sr(self_->exc, - self_->admin_node_address, - self_->session_type, - &self_->prg_memopen); - Prg_Check_RetVal(self_, ret_val); -} - -static void Prg_A_MemWrite(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Ucs_Return_t ret_val; - - self_->current_function = UCS_PRG_FKT_MEM_WRITE; - - ret_val = Exc_MemoryWrite_Sr(self_->exc, - self_->admin_node_address, - self_->session_handle, - self_->command_list[self_->command_index].mem_id, - self_->command_list[self_->command_index].address, - self_->command_list[self_->command_index].unit_length, - self_->command_list[self_->command_index].data, - &self_->prg_memwrite); - Prg_Check_RetVal(self_, ret_val); -} - -static void Prg_A_MemClose(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Ucs_Return_t ret_val; - - self_->current_function = UCS_PRG_FKT_MEM_CLOSE; - ret_val = Exc_MemSessionClose_Sr(self_->exc, - self_->admin_node_address, - self_->session_handle, - &self_->prg_memclose); - Prg_Check_RetVal(self_, ret_val); -} - -static void Prg_A_InitDevice(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - Ucs_Return_t ret_val; - - self_->current_function = UCS_PRG_FKT_INIT; - ret_val = Exc_DeviceInit_Start(self_->exc, - self_->admin_node_address, - NULL); - Prg_Check_RetVal(self_, ret_val); - - if (ret_val == UCS_RET_SUCCESS) - { - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_PRG_RES_SUCCESS, - UCS_PRG_FKT_DUMMY, - 0U, - NULL, - self_->base->ucs_user_ptr); - } - } -} - -static void Prg_A_NetOff(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_PRG_RES_NET_OFF, - self_->current_function, - 0U, - NULL, - self_->base->ucs_user_ptr); - } -} - -static void Prg_A_Timeout(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_PRG_RES_TIMEOUT, - self_->current_function, - 0U, - NULL, - self_->base->ucs_user_ptr); - } -} - -static void Prg_A_Error(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - uint8_t *data_ptr = NULL; - - if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) - && (self_->error.ret_len != 0U)) - { - data_ptr = &(self_->error.parm[0]); - } - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->error.code, - self_->error.function, - self_->error.ret_len, - data_ptr, - self_->base->ucs_user_ptr); - } -} - - -static void Prg_A_Error_Init(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - uint8_t *data_ptr = NULL; - Ucs_Return_t ret_val; - - ret_val = Exc_DeviceInit_Start(self_->exc, - self_->admin_node_address, - NULL); - Prg_Check_RetVal(self_, ret_val); - - if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) - && (self_->error.ret_len != 0U)) - { - data_ptr = &(self_->error.parm[0]); - } - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->error.code, - self_->error.function, - self_->error.ret_len, - data_ptr, - self_->base->ucs_user_ptr); - } -} - -static void Prg_A_Error_Close_Init(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - uint8_t *data_ptr = NULL; - Ucs_Return_t ret_val; - - ret_val = Exc_DeviceInit_Start(self_->exc, - self_->admin_node_address, - NULL); - Prg_Check_RetVal(self_, ret_val); - - - if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) - && (self_->error.ret_len != 0U)) - { - data_ptr = &(self_->error.parm[0]); - } - - if (self_->report_fptr != NULL) - { - self_->report_fptr(self_->error.code, - self_->error.function, - self_->error.ret_len, - data_ptr, - self_->base->ucs_user_ptr); - } -} - - -/**************************************************************************************************/ -/* Callback functions */ -/**************************************************************************************************/ - -/*! \brief Function is called on reception of the Welcome.Result messsage - * \param self Reference to Programming service object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Prg_WelcomeResultCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Exc_WelcomeResult_t welcome_result; - /* read signature and store it */ - welcome_result = *(Exc_WelcomeResult_t *)(result_ptr_->data_info); - if (welcome_result.res == EXC_WELCOME_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_SUCCESS", 0U)); - } - else - { - /* store error paramters */ - self_->error.code = UCS_PRG_RES_FKT_ASYNCH; - self_->error.function = UCS_PRG_FKT_WELCOME_NOSUCCESS; - self_->error.ret_len = 0U; - - Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_NOSUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_NOSUCCESS", 0U)); - } - } - else - { - uint8_t i; - /* store error paramters */ - self_->error.code = UCS_PRG_RES_FKT_ASYNCH; - self_->error.function = UCS_PRG_FKT_WELCOME; - self_->error.ret_len = result_ptr_->result.info_size; - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - self_->error.parm[i] = result_ptr_->result.info_ptr[i]; - } - - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); - - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (code) 0x%x", 1U, result_ptr_->result.code)); - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i])); - } - } - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - - -/*! \brief Function is called on reception of the MemorySessionOpen.Result messsage - * \param self Reference to Programming service object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Prg_MemOpenResultCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - self_->session_handle = *(uint16_t *)(result_ptr_->data_info); - self_->command_index = 0U; - - if ( (self_->command_list[self_->command_index].data_length == 0U) - || (self_->command_list[self_->command_index].data == NULL)) - { - Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb No Tasks", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb successful", 0U)); - } - } - else - { - uint8_t i; - uint32_t fs_error; - - /* store error paramters */ - self_->error.code = UCS_PRG_RES_FKT_ASYNCH; - self_->error.function = UCS_PRG_FKT_MEM_OPEN; - self_->error.ret_len = result_ptr_->result.info_size; - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - self_->error.parm[i] = result_ptr_->result.info_ptr[i]; - } - - fs_error = Prg_CalcError(&(self_->error.parm[0])); - - switch (fs_error) - { - case PRG_HW_RESET_REQ: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); - break; - - case PRG_SESSION_ACTIVE: - self_->session_handle = (uint16_t)(((uint16_t)(self_->error.parm[3])) << 8U) + self_->error.parm[4]; /* get correct session handle */ - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - default: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); - break; - } - - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - -/*! \brief Function is called on reception of the MemoryWrite.Result messsage - * \param self Reference to Programming service object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Prg_MemWriteResultCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - self_->command_index++; - if ( (self_->command_list[self_->command_index].data_length == 0U) - || (self_->command_list[self_->command_index].data == NULL)) - { - Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb PRG_E_MEM_WRITE_FINISH", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb successful", 0U)); - } - } - else - { - uint8_t i; - uint32_t fs_error; - - /* store error paramters */ - self_->error.code = UCS_PRG_RES_FKT_ASYNCH; - self_->error.function = UCS_PRG_FKT_MEM_WRITE; - self_->error.ret_len = result_ptr_->result.info_size; - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - self_->error.parm[i] = result_ptr_->result.info_ptr[i]; - } - - fs_error = Prg_CalcError(&(self_->error.parm[0])); - - switch (fs_error) - { - case PRG_CFG_WRITE_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - case PRG_CFG_FULL_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - case PRG_HDL_MATCH_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); - break; - - case PRG_MEMID_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - case PRG_ADDR_EVEN_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - case PRG_LEN_EVEN_ERROR: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); - break; - - default: - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); - break; - } - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - -/*! \brief Function is called on reception of the MemorySessionClose.Result messsage - * \param self Reference to Programming service object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Prg_MemCloseResultCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - uint8_t session_result = *(uint8_t *)(result_ptr_->data_info); - - if (session_result == 0U) - { - Fsm_SetEvent(&self_->fsm, PRG_E_MEM_CLOSE_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb PRG_E_MEM_CLOSE_SUCCESS", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb ErrResult PRG_E_ERROR_INIT", 0U)); - } - } - else - { - uint8_t i; - uint32_t fs_error; - - /* store error paramters */ - self_->error.code = UCS_PRG_RES_FKT_ASYNCH; - self_->error.function = UCS_PRG_FKT_MEM_CLOSE; - self_->error.ret_len = result_ptr_->result.info_size; - for (i=0U; i< result_ptr_->result.info_size; ++i) - { - self_->error.parm[i] = result_ptr_->result.info_ptr[i]; - } - - fs_error = Prg_CalcError(&(self_->error.parm[0])); - - if (fs_error == PRG_HDL_MATCH_ERROR) - { - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); - } - else - { - Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); - } - - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb Error 0x%x", 1U, result_ptr_->result.code)); - } - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - - - -/*! Function is called on severe internal errors - * - * \param *self Reference to Programming object - * \param *result_ptr Reference to data - */ -static void Prg_OnTerminateEventCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - - MISC_UNUSED(result_ptr); - - if (self_->fsm.current_state != PRG_S_IDLE) - { - Tm_ClearTimer(&self_->base->tm, &self_->timer); - if (self_->report_fptr != NULL) - { - self_->report_fptr(UCS_PRG_RES_ERROR, - self_->current_function, - 0U, - NULL, - self_->base->ucs_user_ptr); - } - - /* reset FSM */ - self_->fsm.current_state = PRG_S_IDLE; - } -} - - -/*! \brief Callback function for the INIC.NetworkStatus status and error messages - * - * \param *self Reference to Node Discovery object - * \param *result_ptr Pointer to the result of the INIC.NetworkStatus message - */ -static void Prg_NetworkStatusCb(void *self, void *result_ptr) -{ - CProgramming *self_ = (CProgramming *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_NetworkStatusCb 0x%x", 1U, result_ptr_->result.code)); - /* check for NetOn/NetOff events */ - if ( (self_->neton == true) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) ) - { - self_->neton = false; - Fsm_SetEvent(&self_->fsm, PRG_E_NET_OFF); - } - else if ( (self_->neton == false) - && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) ) - { - self_->neton = true; - } - } - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - - -/*! \brief Timer callback used for supervising INIC command timeouts. - * \param self Reference to System Diagnosis object - */ -static void Prg_TimerCb(void *self) -{ - CProgramming *self_ = (CProgramming *)self; - - Fsm_SetEvent(&self_->fsm, PRG_E_TIMEOUT); - TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_TimerCb PRG_E_TIMEOUT", 0U)); - - Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); -} - - - -/**************************************************************************************************/ -/* Helper functions */ -/**************************************************************************************************/ - -static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val) -{ - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self->base->tm, - &self->timer, - &Prg_TimerCb, - self, - PRG_TIMEOUT_COMMAND, - 0U); - } - else - { - TR_ASSERT(self->base->ucs_user_ptr, "[PRG]", ret_val == UCS_RET_SUCCESS); - - /* store error paramter */ - self->error.code = UCS_PRG_RES_FKT_SYNCH; - self->error.function = self->current_function; - self->error.ret_len = (uint8_t)ret_val; - - Fsm_SetEvent(&self->fsm, PRG_E_ERROR); - Srv_SetEvent(&self->service, PRG_EVENT_SERVICE); - } -} - - -static uint32_t Prg_CalcError(uint8_t val[]) -{ - uint32_t temp; - - temp = val[0] + (((uint32_t)val[1]) << 8U) + (((uint32_t)val[2]) << 16U); - - return temp; -} - - - - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_rsm.c b/ucs2-lib/src/ucs_rsm.c deleted file mode 100644 index bb40743..0000000 --- a/ucs2-lib/src/ucs_rsm.c +++ /dev/null @@ -1,640 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Sync Management. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_RSM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_rsm.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the RSM service used by scheduler */ -static const uint8_t RSM_SRV_PRIO = 250U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Event for processing one of the below tasks */ -static const Srv_Event_t RSM_EVENT_PROCESS_DEV = 0x01U; -/*! \brief Event for signaling the SyncLost event */ -static const Srv_Event_t RSM_EVENT_SIG_SYNCLOST = 0x02U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Mask for the Network Availability Info */ -static const uint32_t RSM_MASK_NETWORK_AVAILABILITY = 0x0002U; -/*! \brief Mask for the Network NodeAddress Info */ -static const uint32_t RSM_MASK_NETWORK_NODE_ADDRESS = 0x0010U; -/*! \brief Mask for the Network MaxPosition Info */ -static const uint32_t RSM_MASK_NETWORK_MAX_POSITION = 0x0040U; - -/*! \brief Invalid device node address */ -static const uint16_t RSM_INVALID_NODE_ADDRESS = 0x0000U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Rsm_Service (void *self); -static void Rsm_ProcessJob (CRemoteSyncManagement *self); -static Ucs_Return_t Rsm_SendSync (CRemoteSyncManagement *self); -static Ucs_Return_t Rsm_RequestNtfDevId (CRemoteSyncManagement *self); -static Ucs_Return_t Rsm_ClearLastNtfDevId (CRemoteSyncManagement *self); -static Ucs_Return_t Rsm_SetNotificationAll (CRemoteSyncManagement * self); -static Ucs_Return_t Rsm_SetNotificationGpio (CRemoteSyncManagement * self); -static Ucs_Return_t Rsm_ProcessDeviceJob (CRemoteSyncManagement *self); -static bool Rsm_IsLocal (CRemoteSyncManagement * self); -static void Rsm_MnsInitSucceededCb(void *self, void *event_ptr); -static void Rsm_MnsNwStatusInfosCb(void *self, void *event_ptr); -static void Rsm_SyncResultCb(void *self, void *result_ptr); -static void Rsm_MsgObjAvailCb(void *self, void *result_ptr); -static void Rsm_SignalSyncCompleted (CRemoteSyncManagement * self); -static void Rsm_SignalSyncError (CRemoteSyncManagement * self); -static void Rsm_SignalSyncLost (CRemoteSyncManagement * self); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CRemoteSyncManager */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Remote Sync Manager class. - * \param self Instance pointer - * \param init_ptr init data_ptr - */ -void Rsm_Ctor(CRemoteSyncManagement *self, Rsm_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CRemoteSyncManagement)); - - /* Init all instances */ - self->base_ptr = init_ptr->base_ptr; - self->inic_ptr = init_ptr->inic_ptr; - self->net_ptr = init_ptr->net_ptr; - - /* Init observer */ - Mobs_Ctor(&self->event_param.ucsinit_observer, self, EH_E_INIT_SUCCEEDED, &Rsm_MnsInitSucceededCb); - Sobs_Ctor(&self->event_param.stdresult_observer, self, &Rsm_SyncResultCb); - Obs_Ctor(&self->event_param.txavailability_observer, self, &Rsm_MsgObjAvailCb); - - /* Init event_param variables */ - self->event_param.own_device_address = RSM_INVALID_NODE_ADDRESS; - - /* Initialize Sync Management service */ - Srv_Ctor(&self->rsm_srv, RSM_SRV_PRIO, self, &Rsm_Service); - /* Add RSM service to scheduler */ - (void)Scd_AddService(&self->base_ptr->scd, &self->rsm_srv); - /* Add Observer for MNS initialization Result */ - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_param.ucsinit_observer); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Add an observer to the SyncLost Event subject - * \param self Instance pointer - * \param obs init data_ptr - */ -void Rsm_AddObserver(CRemoteSyncManagement * self, CObserver * obs) -{ - (void)Sub_AddObserver(&self->event_param.subject, obs); -} - -/*! \brief Removes an observer registered by Rsm_AddObserver - * \param self Instance pointer - * \param obs_ptr observer to be removed - */ -void Rsm_DelObserver(CRemoteSyncManagement * self, CObserver * obs_ptr) -{ - (void)Sub_RemoveObserver(&self->event_param.subject, obs_ptr); -} - -/*! \brief Synchronizes to the given device - * \param self Instance pointer - * \param user_data reference to the user data that'll be attached in the sync_complete_fptr callback function - * \param sync_complete_fptr result callback function to the device to be synchronized - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_PARAM parameter exceeds its admissible range - */ -Ucs_Return_t Rsm_SyncDev(CRemoteSyncManagement * self, void* user_data, Rsm_ResultCb_t sync_complete_fptr) -{ - Ucs_Return_t result = UCS_RET_ERR_API_LOCKED; - - if (self->dev_infos.sync_state != RSM_DEV_SYNCING) - { - self->dev_infos.curr_user_data = user_data; - self->dev_infos.curr_res_cb_fptr = sync_complete_fptr; - if (self->dev_infos.sync_state == RSM_DEV_SYNCED) - { - self->dev_infos.next_st = RSM_ST_SYNC_SUCC; - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_PROCESS_DEV); - result = UCS_RET_SUCCESS; - } - else - { - if (Rsm_IsLocal(self)) - { - self->dev_infos.next_st = RSM_ST_NTF_GPIO; - } - else - { - self->dev_infos.next_st = RSM_ST_SYNC_REQ; - } - result = Rsm_ProcessDeviceJob (self); - } - } - - return result; -} - -/*! \brief Returns the state (ready or busy) of the given device. - * \param self Instance pointer. - * \return state of the given device. - */ -Rsm_DevSyncState_t Rsm_GetDevState(CRemoteSyncManagement * self) -{ - return self->dev_infos.sync_state; -} - -/*! \brief Reports SyncLost for the given RSM instance. - * \param self Reference to the instance ptr - */ -void Rsm_ReportSyncLost (CRemoteSyncManagement * self) -{ - self->last_synclost_cause = RSM_SLC_CFGNOTOK; - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_SIG_SYNCLOST); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Service function of the Sync management. - * \param self Instance pointer - */ -static void Rsm_Service (void *self) -{ - CRemoteSyncManagement *self_ = (CRemoteSyncManagement *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->rsm_srv, &event_mask); - - /* Handle event to process jobs within devices */ - if((event_mask & RSM_EVENT_PROCESS_DEV) == RSM_EVENT_PROCESS_DEV) - { - Srv_ClearEvent(&self_->rsm_srv, RSM_EVENT_PROCESS_DEV); - Rsm_ProcessJob(self_); - } - - /* Handle event to signal "SyncLost" */ - if((event_mask & RSM_EVENT_SIG_SYNCLOST) == RSM_EVENT_SIG_SYNCLOST) - { - Srv_ClearEvent(&self_->rsm_srv, RSM_EVENT_SIG_SYNCLOST); - Rsm_SignalSyncLost(self_); - } -} - -/*! \brief Processes the next job, if available, in a device. - * \param self Instance pointer - */ -static void Rsm_ProcessJob (CRemoteSyncManagement *self) -{ - if (self->dev_infos.next_st != RSM_ST_IDLE) - { - (void)Rsm_ProcessDeviceJob(self); - } -} - -/*! \brief Processes the next job for the given device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_API_LOCKED The INIC API is locked - * - \c UCS_RET_ERR_PARAM parameter exceeds its admissible range - */ -static Ucs_Return_t Rsm_ProcessDeviceJob (CRemoteSyncManagement *self) -{ - Ucs_Return_t result = UCS_RET_SUCCESS; - - switch (self->dev_infos.next_st) - { - case RSM_ST_SYNC_REQ: - result = Rsm_SendSync (self); - break; - - case RSM_ST_NTF_REQ: - result = Rsm_RequestNtfDevId (self); - break; - - case RSM_ST_NTF_CLEAR: - result = Rsm_ClearLastNtfDevId (self); - break; - - case RSM_ST_NTF_ALL: - result = Rsm_SetNotificationAll (self); - break; - - case RSM_ST_NTF_GPIO: - result = Rsm_SetNotificationGpio (self); - break; - - case RSM_ST_SYNC_SUCC: - Rsm_SignalSyncCompleted (self); - break; - - case RSM_ST_SYNC_ERR: - Rsm_SignalSyncError (self); - break; - - default: - TR_ERROR((self->base_ptr->ucs_user_ptr, "[RSM]", "Unexpected State Transition: 0x%02X", 1U, (Rsm_StateTransition_t)(self->dev_infos.next_st))); - break; - } - - return result; -} - -/*! \brief Sends a Sync command to the given device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - */ -static Ucs_Return_t Rsm_SendSync (CRemoteSyncManagement *self) -{ - Ucs_Return_t result; - - result = Inic_DeviceSync (self->inic_ptr, - &self->event_param.stdresult_observer); - - if(result == UCS_RET_SUCCESS) - { - self->dev_infos.sync_state = RSM_DEV_SYNCING; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RSM]", "Start synchronization to remote device", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->event_param.txavailability_observer); - } - - return result; -} - -/*! \brief Retrieves the ID of the device that has notified to the INIC.DeviceStatus() FktIDs on the given remote device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_API_LOCKED The INIC API is locked - */ -static Ucs_Return_t Rsm_RequestNtfDevId (CRemoteSyncManagement *self) -{ - Ucs_Return_t result; - uint16_t funcid_devstatus = (uint16_t)0x0220; - - result = Inic_Notification_Get(self->inic_ptr, funcid_devstatus, &self->event_param.stdresult_observer); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RSM]", "DeviceId Request for INIC.DeviceStatus() succeeded", 0U)); - } - else if (result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->event_param.txavailability_observer); - } - else - { - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_PROCESS_DEV); - } - - return result; -} - -/*! \brief Clears the current DevId of all remote functions on the given remote device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_PARAM parameter exceeds its admissible range - */ -static Ucs_Return_t Rsm_ClearLastNtfDevId (CRemoteSyncManagement *self) -{ - Ucs_Return_t result; - Ucs_Inic_NotificationCtrl_t control = UCS_INIC_NTF_CLEAR_ALL; - Inic_FktIdList_t rm_fktid_list; - rm_fktid_list.fktids_ptr = NULL; - rm_fktid_list.num_fktids = 0U; - - result = Inic_Notification_Set(self->inic_ptr, control, self->event_param.own_device_address, rm_fktid_list); - if(result == UCS_RET_SUCCESS) - { - self->dev_infos.next_st = RSM_ST_NTF_ALL; - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_PROCESS_DEV); - TR_INFO((self->base_ptr->ucs_user_ptr, "[RSM]", "Clear DevId for all Remote functions succeeded", 0U)); - } - else if (result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->event_param.txavailability_observer); - } - - return result; -} - -/*! \brief Sets all notification for the given remote device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_PARAM parameter exceeds its admissible range - */ -static Ucs_Return_t Rsm_SetNotificationAll (CRemoteSyncManagement * self) -{ - Ucs_Return_t result; - Ucs_Inic_NotificationCtrl_t control = UCS_INIC_NTF_SET_FUNC; - - uint16_t funcid_list[2] = {0x0705U, 0x0802U}; - Inic_FktIdList_t rm_fktid_list; - rm_fktid_list.fktids_ptr = &funcid_list[0]; - rm_fktid_list.num_fktids = 2U; - - result = Inic_Notification_Set(self->inic_ptr, control, self->event_param.own_device_address, rm_fktid_list); - if(result == UCS_RET_SUCCESS) - { - self->dev_infos.next_st = RSM_ST_SYNC_SUCC; - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_PROCESS_DEV); - TR_INFO((self->base_ptr->ucs_user_ptr, "[RSM]", "Set Notification for All Remote functions succeeded", 0U)); - } - else if (result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->event_param.txavailability_observer); - } - - return result; -} - -/*! \brief Sets Gpio notification for the local device. - * \param self Instance pointer - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - */ -static Ucs_Return_t Rsm_SetNotificationGpio (CRemoteSyncManagement * self) -{ - Ucs_Return_t result; - /*! \brief GPIO TriggerEvent function id */ - uint16_t RSM_GPIOTREVENT_FUNCID = 0x0705U; - /*! \brief Local EHC address */ - uint16_t RSM_EHC_ADDRESS = 0x0002U; - - Ucs_Inic_NotificationCtrl_t control = UCS_INIC_NTF_SET_FUNC; - uint16_t funcid_resmonitor = RSM_GPIOTREVENT_FUNCID; - Inic_FktIdList_t rm_fktid_list; - rm_fktid_list.fktids_ptr = &funcid_resmonitor; - rm_fktid_list.num_fktids = 1U; - - result = Inic_Notification_Set(self->inic_ptr, control, RSM_EHC_ADDRESS, rm_fktid_list); - if(result == UCS_RET_SUCCESS) - { - self->dev_infos.next_st = RSM_ST_SYNC_SUCC; - Srv_SetEvent(&self->rsm_srv, RSM_EVENT_PROCESS_DEV); - } - else if (result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->event_param.txavailability_observer); - } - - return result; -} - -/*! \brief Check whether the given device is local or remote. - * \param self Instance pointer - * \return Returns \c true if the device is local, otherwise \c false. - */ -static bool Rsm_IsLocal (CRemoteSyncManagement *self) -{ - return (Inic_GetTargetAddress(self->inic_ptr) == UCS_ADDR_LOCAL_DEV); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Callback Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Called if MNS initialization has been succeeded. - * \param self Instance pointer - * \param event_ptr Reference to reported event - */ -static void Rsm_MnsInitSucceededCb(void *self, void *event_ptr) -{ - CRemoteSyncManagement *self_ = (CRemoteSyncManagement *)self; - MISC_UNUSED(event_ptr); - - /* Remove ucsinit_observer */ - Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->event_param.ucsinit_observer); - - /* Add network status observer */ - Mobs_Ctor(&self_->event_param.nwstatus_observer, self, RSM_MASK_NETWORK_NODE_ADDRESS, &Rsm_MnsNwStatusInfosCb); - Net_AddObserverNetworkStatus(self_->net_ptr, &self_->event_param.nwstatus_observer); -} - -/*! \brief Result callback for the "Sync Request". - * \param self Instance pointer - * \param result_ptr Reference to the result. - */ -static void Rsm_SyncResultCb(void *self, void *result_ptr) -{ - CRemoteSyncManagement *self_ = (CRemoteSyncManagement *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - Inic_NotificationResult_t * res_inf = NULL; - - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - if (self_->dev_infos.sync_state == RSM_DEV_SYNCING) - { - switch (self_->dev_infos.next_st) - { - case RSM_ST_SYNC_REQ: - self_->dev_infos.next_st = RSM_ST_NTF_REQ; - TR_INFO((self_->base_ptr->ucs_user_ptr, "[RSM]", "Remote DeviceSync has been successfully created.", 0U)); - break; - - case RSM_ST_NTF_REQ: - res_inf = (Inic_NotificationResult_t *)result_ptr_->data_info; - if (res_inf != NULL) - { - if (res_inf->device_id == RSM_INVALID_NODE_ADDRESS) - { - self_->dev_infos.next_st = RSM_ST_NTF_ALL; - } - else - { - self_->dev_infos.next_st = RSM_ST_NTF_CLEAR; - } - } - break; - - default: - break; - } - Srv_SetEvent(&self_->rsm_srv, RSM_EVENT_PROCESS_DEV); - } - } - else - { - self_->dev_infos.next_st = RSM_ST_SYNC_ERR; - self_->dev_infos.curr_result.code = RSM_RES_ERR_SYNC; - self_->dev_infos.curr_result.details.inic_result = result_ptr_->result; - if (result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->dev_infos.curr_result.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - } - else - { - self_->dev_infos.curr_result.details.tx_result = UCS_MSG_STAT_OK; - } - - Srv_SetEvent(&self_->rsm_srv, RSM_EVENT_PROCESS_DEV); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[RSM]", "Synchronization to the remote device failed. Result code: 0x%02X", 1U, result_ptr_->result.code)); - if (result_ptr_->result.info_ptr != NULL) - { - TR_ERROR_INIC_RESULT(self_->base_ptr->ucs_user_ptr, "[RSM]", result_ptr_->result.info_ptr, result_ptr_->result.info_size); - } - } -} - -/*! \brief Event Callback function for the network status. - * \param self Instance pointer - * \param event_ptr Reference to the events - */ -static void Rsm_MnsNwStatusInfosCb(void *self, void *event_ptr) -{ - CRemoteSyncManagement *self_ = (CRemoteSyncManagement *)self; - Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)event_ptr; - bool signal_synclost = false; - - if ((RSM_MASK_NETWORK_NODE_ADDRESS & result_ptr_->change_mask) == RSM_MASK_NETWORK_NODE_ADDRESS) - { - if (result_ptr_->node_address != 0xFFFFU) - { - if ((self_->event_param.own_device_address != RSM_INVALID_NODE_ADDRESS) && - (result_ptr_->node_address != self_->event_param.own_device_address)) - { - self_->last_synclost_cause = RSM_SLC_SYSMODIF; - signal_synclost = true; - } - - self_->event_param.own_device_address = result_ptr_->node_address; - } - } - - if (signal_synclost) - { - Srv_SetEvent(&self_->rsm_srv, RSM_EVENT_SIG_SYNCLOST); - } -} - -/*! \brief Event Callback function that signals that a TxMsgObj is now available. - * \param self Instance pointer - * \param result_ptr Reference to the results - */ -static void Rsm_MsgObjAvailCb(void *self, void *result_ptr) -{ - CRemoteSyncManagement *self_ = (CRemoteSyncManagement *)self; - MISC_UNUSED(result_ptr); - - Srv_SetEvent(&self_->rsm_srv, RSM_EVENT_PROCESS_DEV); - - /* delete observer */ - Inic_DelObsrvOnTxMsgObjAvail(self_->inic_ptr, &self_->event_param.txavailability_observer); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Notification Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Signals the successful synchronization to a remote device. - * \param self Instance pointer - */ -static void Rsm_SignalSyncCompleted (CRemoteSyncManagement * self) -{ - Rsm_ResultCb_t tmp_res_cb = self->dev_infos.curr_res_cb_fptr; - void * data = self->dev_infos.curr_user_data; - Rsm_Result_t res = {RSM_RES_SUCCESS, {UCS_MSG_STAT_OK, {UCS_RES_SUCCESS, NULL, 0}}}; - - self->dev_infos.sync_state = RSM_DEV_SYNCED; - self->dev_infos.next_st = RSM_ST_IDLE; - self->dev_infos.curr_res_cb_fptr = NULL; - self->dev_infos.curr_user_data = NULL; - - if (tmp_res_cb != NULL) - { - tmp_res_cb(data, res); - } -} - -/*! \brief Signals that the synchronization to a remote device failed. - * \param self Instance pointer - */ -static void Rsm_SignalSyncError (CRemoteSyncManagement * self) -{ - Rsm_ResultCb_t tmp_res_cb = self->dev_infos.curr_res_cb_fptr; - void * data = self->dev_infos.curr_user_data; - - self->dev_infos.sync_state = RSM_DEV_UNSYNCED; - self->dev_infos.next_st = RSM_ST_IDLE; - self->dev_infos.curr_res_cb_fptr = NULL; - self->dev_infos.curr_user_data = NULL; - - if (tmp_res_cb != NULL) - { - tmp_res_cb(data, self->dev_infos.curr_result); - } -} - -/*! \brief Signals that the synchronization to a remote device has been lost. - * \param self Instance pointer - */ -static void Rsm_SignalSyncLost (CRemoteSyncManagement * self) -{ - if ((self->dev_infos.sync_state == RSM_DEV_SYNCED) && - (!Rsm_IsLocal(self))) - { - self->dev_infos.sync_state = RSM_DEV_UNSYNCED; - if(Sub_GetNumObservers(&self->event_param.subject) > 0U) - { - Sub_Notify(&self->event_param.subject, &self->last_synclost_cause); - } - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_rtm.c b/ucs2-lib/src/ucs_rtm.c deleted file mode 100644 index 6bc2ef1..0000000 --- a/ucs2-lib/src/ucs_rtm.c +++ /dev/null @@ -1,1366 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Route Management. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_RTM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_rtm.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Priority of the RSM service used by scheduler */ -static const uint8_t RTM_SRV_PRIO = 250U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Event for resuming the handling of routes */ -static const Srv_Event_t RTM_EVENT_HANDLE_NEXTROUTE = 0x01U; -/*! \brief Event for pausing the processing of routes */ -static const Srv_Event_t RTM_EVENT_PROCESS_PAUSE = 0x02U; -/*! \brief Interval (in ms) for checking the RoutingJob queue */ -static const uint16_t RTM_JOB_CHECK_INTERVAL = 50U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Mask for the Network Availability Info */ -static const uint32_t RTM_MASK_NETWORK_AVAILABILITY = 0x0002U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Rtm_Service(void *self); -static void Rtm_HandleNextRoute(CRouteManagement * self); -static void Rtm_BuildRoute(CRouteManagement * self); -static void Rtm_DestroyRoute(CRouteManagement * self); -static bool Rtm_SetNextRouteIndex(CRouteManagement * self); -static void Rtm_HandleRoutingError(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static void Rtm_ApiLocking(CRouteManagement *self, bool status); -static bool Rtm_IsApiFree(CRouteManagement *self); -static Ucs_Return_t Rtm_BuildEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr); -static Ucs_Return_t Rtm_DeactivateRouteEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr); -static Ucs_Rm_Route_t * Rtm_GetNextRoute(CRouteManagement * self); -static bool Rtm_IsRouteBuildable(CRouteManagement * self); -static bool Rtm_IsRouteDestructible(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static bool Rtm_IsRouteActivatable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static void Rtm_DisableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static void Rtm_EnableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static bool Rtm_CheckEpResultSeverity(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr); -static void Rtm_EndPointDeterioredCb(void *self, void *result_ptr); -static void Rtm_StartTmr4HandlingRoutes(CRouteManagement * self); -static void Rtm_ExecRoutesHandling(void * self); -static void Rtm_HandleProcessTermination(CRouteManagement * self); -static void Rtm_StopRoutesHandling(CRouteManagement * self); -static void Rtm_StartRoutingTimer (CRouteManagement * self); -static void Rtm_ResetNodesAvailable(CRouteManagement * self); -static bool Rtm_AreRouteNodesAvailable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static bool Rtm_UnlockPossibleBlockings(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr); -static void Rtm_ReleaseSuspendedRoutes(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr); -static void Rtm_ForcesRouteToIdle(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr); -static void Rtm_UcsInitSucceededCb(void *self, void *event_ptr); -static void Rtm_MnsNwStatusInfosCb(void *self, void *event_ptr); -static void Rtm_UninitializeService(void *self, void *error_code_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CRouteManagement */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Remote Sync Manager class. - * \param self Instance pointer - * \param init_ptr init data_ptr - */ -void Rtm_Ctor(CRouteManagement *self, Rtm_InitData_t *init_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CRouteManagement)); - - /* Init all reference instances */ - self->base_ptr = init_ptr->base_ptr; - self->epm_ptr = init_ptr->epm_ptr; - self->tm_ptr = &init_ptr->base_ptr->tm; - self->net_ptr = init_ptr->net_ptr; - self->report_fptr = init_ptr->report_fptr; - - /* Initialize Route Management service */ - Srv_Ctor(&self->rtm_srv, RTM_SRV_PRIO, self, &Rtm_Service); - - /* Add Observer for UCS initialization Result */ - Mobs_Ctor(&self->ucsinit_observer, self, EH_E_INIT_SUCCEEDED, &Rtm_UcsInitSucceededCb); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucsinit_observer); - - /* Init and Add observer to the UCS termination event */ - Mobs_Ctor(&self->ucstermination_observer, self, EH_M_TERMINATION_EVENTS, &Rtm_UninitializeService); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucstermination_observer); - - /* Add RTM service to scheduler */ - (void)Scd_AddService(&self->base_ptr->scd, &self->rtm_srv); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Starts the process to buildup the given routes list. - * - * This function shall only be called once. - * \param self Instance pointer - * \param routes_list Routes list to be built - * \param size Size of the routes list - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available - * - \c UCS_RET_ERR_PARAM At least one parameter is wrong - */ -Ucs_Return_t Rtm_StartProcess(CRouteManagement * self, Ucs_Rm_Route_t routes_list[], uint16_t size) -{ - Ucs_Return_t result = UCS_RET_ERR_API_LOCKED; - - if (Rtm_IsApiFree(self) != false) - { - result = UCS_RET_ERR_PARAM; - if ((self != NULL) && (routes_list != NULL) && (size > 0U)) - { - uint8_t k = 0U; - /* Function remains from now locked */ - Rtm_ApiLocking(self, true); - - /* Initializes private variables */ - self->routes_list_size = size; - self->curr_route_index = 0U; - self->routes_list_ptr = &routes_list[0]; - - /* Initializes internal data structure */ - for (; k < size; k++) - { - MISC_MEM_SET(&routes_list[k].internal_infos, 0, sizeof(Ucs_Rm_RouteInt_t)); - } - - Rtm_StartTmr4HandlingRoutes(self); - result = UCS_RET_SUCCESS; - } - } - - return result; -} - -/*! \brief Deactivates respectively destroys the given route reference - * \param self Instance pointer - * \param route_ptr Reference to the route to be destroyed - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_PARAM At least one parameter is NULL - * - \c UCS_RET_ERR_ALREADY_SET Route is already inactive - */ -Ucs_Return_t Rtm_DeactivateRoute (CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (route_ptr != NULL)) - { - if (Rtm_IsRouteDestructible(self, route_ptr)) - { - Rtm_DisableRoute(self, route_ptr); - Rtm_StartTmr4HandlingRoutes(self); - result = UCS_RET_SUCCESS; - } - else - { - result = UCS_RET_ERR_ALREADY_SET; - } - } - - return result; -} - -/*! \brief Builds respectively activates the given route reference - * \param self Instance pointer - * \param route_ptr Reference to the route to be destroyed - * \return Possible return values are - * - \c UCS_RET_SUCCESS if the transmission was started successfully - * - \c UCS_RET_ERR_PARAM At least one parameter is NULL - * - \c UCS_RET_ERR_ALREADY_SET Route is already active - */ -Ucs_Return_t Rtm_ActivateRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (route_ptr != NULL)) - { - if (Rtm_IsRouteActivatable(self, route_ptr)) - { - Rtm_EnableRoute(self, route_ptr); - Rtm_StartTmr4HandlingRoutes(self); - result = UCS_RET_SUCCESS; - } - else - { - result = UCS_RET_ERR_ALREADY_SET; - } - } - - return result; -} - -/*! \brief Sets the given node to \c available or \c not \c available and triggers the routing process to handle this change. - * \details In case of \c Available the function starts the routing process that checks whether there are endpoints to build on this node. - * In case of \c Unavailable the function informs sub modules like XRM to check whether there are resources to release and simultaneously unlock \c suspended routes that - * link to this node. - * \param self The routing instance pointer - * \param node_ptr Reference to the node to be looked for. - * \param available Specifies whether the node is available or not - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | --------------------------------------------------------------------- - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_ALREADY_SET | Node is already set to "available" or "not available" - * UCS_RET_ERR_PARAM | At least one parameter is NULL. - * UCS_RET_ERR_NOT_INITIALIZED | UNICENS is not initialized - * UCS_RET_ERR_NOT_AVAILABLE | The function cannot be processed because the network is not available - */ -Ucs_Return_t Rtm_SetNodeAvailable(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr, bool available) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (node_ptr != NULL) && (node_ptr->signature_ptr != NULL)) - { - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - if (self->nw_available) - { - ret_val = UCS_RET_ERR_ALREADY_SET; - if (available) - { - if (node_ptr->internal_infos.available == 0x00U) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Node with Addr {%X} is available", 1U, node_ptr->signature_ptr->node_address)); - node_ptr->internal_infos.available = 0x01U; - Rtm_StartRoutingTimer(self); - ret_val = UCS_RET_SUCCESS; - } - } - else - { - if (node_ptr->internal_infos.available == 0x01U) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Node with Addr {%X} is not available", 1U, node_ptr->signature_ptr->node_address)); - node_ptr->internal_infos.available = 0x00U; - Rtm_ReleaseSuspendedRoutes(self, node_ptr); - Epm_ReportInvalidDevice (self->epm_ptr, node_ptr->signature_ptr->node_address); - ret_val = UCS_RET_SUCCESS; - } - } - } - } - - return ret_val; -} - -/*! \brief Retrieves the "available" flag of the given node. - * \param self The routing instance pointer - * \param node_ptr Reference to the node to be looked for. - * \return The "available" flag of the node. - */ -bool Rtm_GetNodeAvailable(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr) -{ - bool ret_val = false; - - MISC_UNUSED (self); - - if (node_ptr != NULL) - { - ret_val = (node_ptr->internal_infos.available == 0x01U) ? true:false; - } - - return ret_val; -} - -/*! \brief Retrieves currently references of all routes attached to the given endpoint and stores It into an external routes table provided by user application. - * Thus, User application should provide an external reference to an empty routes table where the potential routes will be stored. - * That is, user application is responsible to allocate enough space to store the found routes. Otherwise, the max routes found will - * equal the list size. - * \param self The routing instance pointer - * \param ep_inst Reference to the endpoint to be looked for. - * \param ext_routes_list External empty table allocated by user application - * \param size_list Size of the provided list - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | --------------------------------------------------------------------- - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is NULL. - */ -Ucs_Return_t Rtm_GetAttachedRoutes(CRouteManagement * self, Ucs_Rm_EndPoint_t * ep_inst, - Ucs_Rm_Route_t * ext_routes_list[], uint16_t size_list) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_PARAM; - - MISC_UNUSED (self); - - if ((ep_inst != NULL) && (ext_routes_list != NULL) && (size_list > 0U)) - { - bool curr_index_empty = true; - uint8_t k = 0U, num_attached_routes = Sub_GetNumObservers(&ep_inst->internal_infos.subject_obj); - CDlNode *n_tmp = (&(ep_inst->internal_infos.subject_obj))->list.head; - Ucs_Rm_Route_t * tmp_rt = NULL; - ret_val = UCS_RET_SUCCESS; - - for (; ((k < size_list) && (num_attached_routes > 0U) && (n_tmp != NULL)); k++) - { - ext_routes_list[k] = NULL; - do - { - CObserver *o_tmp = (CObserver *)n_tmp->data_ptr; - tmp_rt = (Ucs_Rm_Route_t *)o_tmp->inst_ptr; - if ((tmp_rt != NULL) && ((tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_BUILT) || - (tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) || - (tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_DESTRUCTION))) - { - curr_index_empty = false; - ext_routes_list[k] = tmp_rt; - } - n_tmp = n_tmp->next; - num_attached_routes--; - - } while ((curr_index_empty) && (num_attached_routes > 0U)); - curr_index_empty = true; - } - - if (k < size_list) - { - ext_routes_list[k] = NULL; - } - } - - return ret_val; -} - -/*! \brief Retrieves the \c ConnectionLabel of the given route. - * \param self The routing instance pointer - * \param route_ptr Reference to the route to be looked for. - * \return The "ConnectionLabel" of this route. - */ -uint16_t Rtm_GetConnectionLabel (CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - uint16_t conn_label = 0U; - - if ((self != NULL) && (route_ptr != NULL) && (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT)) - { - conn_label = Epm_GetConnectionLabel(self->epm_ptr, route_ptr->source_endpoint_ptr); - } - - return conn_label; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Private Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Service function of the Sync management. - * \param self Instance pointer - */ -static void Rtm_Service(void *self) -{ - CRouteManagement *self_ = (CRouteManagement *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->rtm_srv, &event_mask); - - /* Event to process list of routes */ - if((event_mask & RTM_EVENT_HANDLE_NEXTROUTE) == RTM_EVENT_HANDLE_NEXTROUTE) - { - Srv_ClearEvent(&self_->rtm_srv, RTM_EVENT_HANDLE_NEXTROUTE); - Rtm_HandleNextRoute(self_); - } - - /* Event to pause processing of routes list */ - if ((event_mask & RTM_EVENT_PROCESS_PAUSE) == RTM_EVENT_PROCESS_PAUSE) - { - Srv_ClearEvent(&self_->rtm_srv, RTM_EVENT_PROCESS_PAUSE); - Rtm_StopRoutesHandling(self_); - } -} - -/*! \brief This function starts the routing timer. - * - * Whenever this function is called the routing management process will resume in case it has been paused. - * \param self Instance pointer - */ -static void Rtm_StartRoutingTimer (CRouteManagement * self) -{ - if ((NULL != self) && (NULL != self->routes_list_ptr) && - (0U < self->routes_list_size)) - { - Rtm_StartTmr4HandlingRoutes(self); - } -} - -/*! \brief Handles the next route in the list. - * \param self Instance pointer - */ -static void Rtm_HandleNextRoute(CRouteManagement * self) -{ - Ucs_Rm_Route_t * tmp_route; - self->curr_route_ptr = Rtm_GetNextRoute(self); - tmp_route = self->curr_route_ptr; - - switch (tmp_route->internal_infos.route_state) - { - case UCS_RM_ROUTE_IDLE: - if (Rtm_IsRouteBuildable(self) == true) - { - Rtm_BuildRoute(self); - } - break; - - case UCS_RM_ROUTE_CONSTRUCTION: - Rtm_BuildRoute(self); - break; - - case UCS_RM_ROUTE_DETERIORATED: - Rtm_HandleRoutingError(self, tmp_route); - break; - - case UCS_RM_ROUTE_DESTRUCTION: - Rtm_DestroyRoute(self); - break; - - case UCS_RM_ROUTE_SUSPENDED: - case UCS_RM_ROUTE_BUILT: - if (tmp_route->active == false) - { - Rtm_DestroyRoute(self); - } - break; - - default: - break; - } -} - -/*! \brief Checks whether the given route is buildable. - * \param self Instance pointer - * \return \c true if the route is buildable, otherwise \c false. - */ -static bool Rtm_IsRouteBuildable(CRouteManagement * self) -{ - bool result_check = false; - - if (self->curr_route_ptr != NULL) - { - if ((self->curr_route_ptr->internal_infos.route_state == UCS_RM_ROUTE_IDLE) && - (self->curr_route_ptr->active == true) && - (self->curr_route_ptr->source_endpoint_ptr != NULL) && - (self->curr_route_ptr->sink_endpoint_ptr != NULL)) - { - result_check = true; - } - } - - return result_check; -} - -/*! \brief Checks whether the given route is destructible. - * \param self Instance pointer - * \param route_ptr Reference route to be checked - * \return \c true if the route is destructible, otherwise \c false. - */ -static bool Rtm_IsRouteDestructible(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - bool result_check = false; - MISC_UNUSED (self); - - if ((route_ptr != NULL) && (route_ptr->active == 0x01U) && ((route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT) || - (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED))) - { - result_check = true; - } - - return result_check; -} - -/*! \brief Checks whether the given route can be activated. - * \param self Instance pointer - * \param route_ptr Reference route to be checked - * \return \c true if the route is destructible, otherwise \c false. - */ -static bool Rtm_IsRouteActivatable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - bool result_check = false; - MISC_UNUSED (self); - - if ((route_ptr != NULL) && (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_IDLE) && (route_ptr->active == 0x0U)) - { - result_check = true; - } - - return result_check; -} - -/*! \brief Deactivates the given route reference. - * \param self Instance pointer - * \param route_ptr Reference route to be deactivated - */ -static void Rtm_DisableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - MISC_UNUSED (self); - - if (route_ptr != NULL) - { - route_ptr->active = false; - } -} - -/*! \brief Activates the given route reference. - * \param self Instance pointer - * \param route_ptr Reference route to be activated - */ -static void Rtm_EnableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - MISC_UNUSED (self); - - if (route_ptr != NULL) - { - route_ptr->active = true; - } -} - -/*! \brief Builds the current Route. - * \param self Instance pointer - */ -static void Rtm_BuildRoute(CRouteManagement * self) -{ - bool result_critical = false; - Ucs_Rm_EndPointState_t ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr); - switch (ep_state) - { - case UCS_RM_EP_IDLE: - result_critical = Rtm_CheckEpResultSeverity(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr); - if (!result_critical) - { - if (self->curr_route_ptr->internal_infos.src_obsvr_initialized == 0U) - { - self->curr_route_ptr->internal_infos.src_obsvr_initialized = 1U; - Epm_DelObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer); - Obs_Ctor(&self->curr_route_ptr->internal_infos.source_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb); - /* Initializes source endpoint internal data */ - Epm_InitInternalInfos (self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr); - } - (void)Rtm_BuildEndPoint(self, self->curr_route_ptr->source_endpoint_ptr); - } - break; - - case UCS_RM_EP_BUILT: - /* In case of shared source endpoint by another route */ - if (self->curr_route_ptr->internal_infos.src_obsvr_initialized == 0U) - { - self->curr_route_ptr->internal_infos.src_obsvr_initialized = 1U; - Epm_DelObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer); - Obs_Ctor(&self->curr_route_ptr->internal_infos.source_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb); - Epm_AddObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer); - } - ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr); - switch(ep_state) - { - case UCS_RM_EP_IDLE: - result_critical = Rtm_CheckEpResultSeverity(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr); - if (!result_critical) - { - if (self->curr_route_ptr->internal_infos.sink_obsvr_initialized == 0U) - { - self->curr_route_ptr->internal_infos.sink_obsvr_initialized = 1U; - Obs_Ctor(&self->curr_route_ptr->internal_infos.sink_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb); - /* Initializes sink endpoint internal data */ - Epm_InitInternalInfos (self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr); - } - Epm_SetConnectionLabel(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr, Epm_GetConnectionLabel(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr)); - (void)Rtm_BuildEndPoint(self, self->curr_route_ptr->sink_endpoint_ptr); - } - break; - - case UCS_RM_EP_BUILT: - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is built", 1U, self->curr_route_ptr->route_id)); - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_BUILT; - if (self->report_fptr != NULL) - { - self->report_fptr(self->curr_route_ptr, UCS_RM_ROUTE_INFOS_BUILT, self->base_ptr->ucs_user_ptr); - } - break; - - case UCS_RM_EP_XRMPROCESSING: - default: - result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr); - break; - } - break; - - case UCS_RM_EP_XRMPROCESSING: - default: - result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr); - break; - } - - if (result_critical) - { - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DETERIORATED; - } -} - -/*! \brief Destroys the current Route. - * \param self Instance pointer - */ -static void Rtm_DestroyRoute(CRouteManagement * self) -{ - bool result_critical = false; - bool destruction_completed = false; - - Ucs_Rm_EndPointState_t ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr); - switch (ep_state) - { - case UCS_RM_EP_BUILT: - (void)Rtm_DeactivateRouteEndPoint(self, self->curr_route_ptr->sink_endpoint_ptr); - break; - - case UCS_RM_EP_IDLE: - ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr); - switch(ep_state) - { - case UCS_RM_EP_BUILT: - /* if source endpoint cannot be built since it's used in another route(s), however consider that the route is destroyed. */ - if (Rtm_DeactivateRouteEndPoint(self, self->curr_route_ptr->source_endpoint_ptr) == UCS_RET_ERR_INVALID_SHADOW) - { - destruction_completed = true; - } - break; - - case UCS_RM_EP_IDLE: - destruction_completed = true; - break; - - case UCS_RM_EP_XRMPROCESSING: - default: - result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr); - break; - } - break; - - case UCS_RM_EP_XRMPROCESSING: - default: - result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr); - break; - } - - if (result_critical) - { - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DETERIORATED; - } - else if (destruction_completed) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} has been destroyed", 1U, self->curr_route_ptr->route_id)); - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_IDLE; - self->curr_route_ptr->internal_infos.src_obsvr_initialized = 0U; - - if (self->report_fptr != NULL) - { - self->report_fptr(self->curr_route_ptr, UCS_RM_ROUTE_INFOS_DESTROYED, self->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Builds the given endpoint. - * \param self Instance pointer - * \param endpoint_ptr Reference to the endpoint to be looked for - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed. - * - \c UCS_RET_SUCCESS the build process was set successfully - * - \c UCS_RET_ERR_PARAM NULL pointer detected in the parameter list - * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set - */ -static Ucs_Return_t Rtm_BuildEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (endpoint_ptr != NULL)) - { - result = Epm_SetBuildProcess(self->epm_ptr, endpoint_ptr); - if (result == UCS_RET_SUCCESS) - { - Epm_AddObserver (endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? &self->curr_route_ptr->internal_infos.source_ep_observer: &self->curr_route_ptr->internal_infos.sink_ep_observer); - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_CONSTRUCTION; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Start Building Endpoint {%X} of type %s for route id %X", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id)); - } - else if (result == UCS_RET_ERR_ALREADY_SET) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X has already been built", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id)); - } - } - - return result; -} - -/*! \brief Destroys the given endpoint. - * \param self Instance pointer - * \param endpoint_ptr Reference to the endpoint to be looked for - * \return Possible return values are - * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed. - * - \c UCS_RET_SUCCESS the build process was set successfully - * - \c UCS_RET_ERR_PARAM NULL pointer detected in the parameter list - * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set - * - \c UCS_RET_ERR_NOT_AVAILABLE the endpoint is no more available. - * - \c UCS_RET_ERR_INVALID_SHADOW the endpoint cannot be destroyed since it's still in use by another routes. - */ -static Ucs_Return_t Rtm_DeactivateRouteEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr) -{ - Ucs_Return_t result = UCS_RET_ERR_PARAM; - - if ((self != NULL) && (endpoint_ptr != NULL) && (endpoint_ptr->node_obj_ptr != NULL) && - (endpoint_ptr->node_obj_ptr->signature_ptr != NULL)) - { - if ((endpoint_ptr->node_obj_ptr->internal_infos.available == 1U) || - (endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV)) - { - result = Epm_SetDestroyProcess(self->epm_ptr, endpoint_ptr); - if (result == UCS_RET_SUCCESS) - { - self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DESTRUCTION; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Start Destroying Endpoint {%X} of type %s for route id %X", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id)); - } - else if (result == UCS_RET_ERR_ALREADY_SET) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X has already been destroyed", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id)); - } - else if (result == UCS_RET_ERR_INVALID_SHADOW) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X cannot be destroyed since it's still used", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id)); - } - else if (result == UCS_RET_ERR_NOT_AVAILABLE) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X is no more available", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source" : "Sink", self->curr_route_ptr->route_id)); - } - } - else - { - /* Completed */ - Epm_ResetState(self->epm_ptr, endpoint_ptr); - } - } - - return result; -} - -/*! \brief Classifies and sets the corresponding route error and then informs user about the new state. - * \param self Instance pointer - * \param route_ptr Reference to the route to be looked for - */ -static void Rtm_HandleRoutingError(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - Ucs_Rm_Route_t * tmp_route = route_ptr; - Ucs_Rm_RouteInfos_t result_route = UCS_RM_ROUTE_INFOS_DESTROYED; - Ucs_Rm_RouteResult_t res_rt = tmp_route->internal_infos.last_route_result; - - tmp_route->internal_infos.route_state = UCS_RM_ROUTE_IDLE; - tmp_route->internal_infos.last_route_result = UCS_RM_ROUTE_NOERROR; - - if (res_rt != UCS_RM_ROUTE_CRITICAL) - { - if (tmp_route->source_endpoint_ptr->internal_infos.endpoint_state == UCS_RM_EP_IDLE) - { - if (Rtm_CheckEpResultSeverity(self, tmp_route, tmp_route->source_endpoint_ptr)) - { - Epm_ResetState(self->epm_ptr, tmp_route->source_endpoint_ptr); - tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED; - result_route = UCS_RM_ROUTE_INFOS_SUSPENDED; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id)); - } - } - else if (tmp_route->sink_endpoint_ptr->internal_infos.endpoint_state == UCS_RM_EP_IDLE) - { - if (Rtm_CheckEpResultSeverity(self, tmp_route, tmp_route->sink_endpoint_ptr)) - { - Epm_ResetState(self->epm_ptr, tmp_route->sink_endpoint_ptr); - tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED; - result_route = UCS_RM_ROUTE_INFOS_SUSPENDED; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id)); - } - } - else - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is destroyed", 1U, tmp_route->route_id)); - } - } - else - { - Epm_ResetState(self->epm_ptr, tmp_route->source_endpoint_ptr); - Epm_ResetState(self->epm_ptr, tmp_route->sink_endpoint_ptr); - tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED; - result_route = UCS_RM_ROUTE_INFOS_SUSPENDED; - TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id)); - } - - if (self->report_fptr != NULL) - { - self->report_fptr(tmp_route, result_route, self->base_ptr->ucs_user_ptr); - } -} - -/*! \brief Checks whether the endpoint's result is critical or not and stores the result into the target route. - * \param self Instance pointer - * \param tgt_route_ptr Reference to the route that contains the endpoint to be looked for - * \param endpoint_ptr Reference to the endpoint to be looked for - * \return \c true if the endpoint result is critical, otherwise \c false. - */ -static bool Rtm_CheckEpResultSeverity(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr) -{ - bool result_check = false; - Ucs_Rm_RouteResult_t result = UCS_RM_ROUTE_NOERROR; - /*! \brief Maximum number of retries allowed in error situation */ - uint8_t RTM_MAX_NUM_RETRIES_IN_ERR = 0xFFU; - - if ((endpoint_ptr != NULL) && (tgt_route_ptr != NULL)) - { - switch (endpoint_ptr->internal_infos.xrm_result.code) - { - case UCS_XRM_RES_ERR_BUILD: - case UCS_XRM_RES_ERR_DESTROY: - case UCS_XRM_RES_ERR_SYNC: - switch (endpoint_ptr->internal_infos.xrm_result.details.result_type) - { - case UCS_XRM_RESULT_TYPE_TX: - if ((UCS_MSG_STAT_ERROR_CFG_NO_RCVR == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_FATAL_OA == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR)) - { - result = UCS_RM_ROUTE_CRITICAL; - TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the transmission error code {Ucs_MsgTxStatus_t:0x%02X} observed in XRM.", 2U, - tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.tx_result)); - } - else if ((UCS_MSG_STAT_ERROR_UNKNOWN == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_FATAL_WT == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_TIMEOUT == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_BF == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_CRC == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_NA_TRANS == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_ACK == endpoint_ptr->internal_infos.xrm_result.details.tx_result) || - (UCS_MSG_STAT_ERROR_ID == endpoint_ptr->internal_infos.xrm_result.details.tx_result)) - { - endpoint_ptr->internal_infos.num_retries++; - result = UCS_RM_ROUTE_UNCRITICAL; - } - break; - - case UCS_XRM_RESULT_TYPE_TGT: - if ((UCS_RES_ERR_CONFIGURATION == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) || - (UCS_RES_ERR_MOST_STANDARD == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) || - (UCS_RES_ERR_SYSTEM == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) || - (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR)) - { - result = UCS_RM_ROUTE_CRITICAL; - TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the INIC result code {Ucs_Result_t:0x%02X} observed in XRM.", 2U, - tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.inic_result.code)); - } - else if ((UCS_RES_ERR_BUSY == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) || - (UCS_RES_ERR_TIMEOUT == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) || - (UCS_RES_ERR_PROCESSING == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code)) - { - endpoint_ptr->internal_infos.num_retries++; - result = UCS_RM_ROUTE_UNCRITICAL; - } - break; - - case UCS_XRM_RESULT_TYPE_INT: - if ((endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_AVAILABLE) || - (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_SUPPORTED) || - (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_PARAM) || - (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_INITIALIZED) || - (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR)) - { - result = UCS_RM_ROUTE_CRITICAL; - TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the internal error code {Ucs_Return_t:0x%02X} observed in XRM.", 2U, - tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.int_result)); - } - else if ((endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_BUFFER_OVERFLOW) || - (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_API_LOCKED) || - (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_INVALID_SHADOW)) - { - endpoint_ptr->internal_infos.num_retries++; - result = UCS_RM_ROUTE_UNCRITICAL; - } - break; - - default: - break; - } - break; - - case UCS_XRM_RES_ERR_CONFIG: - result = UCS_RM_ROUTE_CRITICAL; - break; - - case UCS_XRM_RES_SUCCESS_BUILD: - case UCS_XRM_RES_SUCCESS_DESTROY: - endpoint_ptr->internal_infos.num_retries = 0U; - break; - - default: - break; - } - - /* Sets route result */ - tgt_route_ptr->internal_infos.last_route_result = result; - if (result == UCS_RM_ROUTE_CRITICAL) - { - result_check = true; - } - } - - MISC_UNUSED(self); - - return result_check; -} - -/*! \brief Sets curr_route_ptr to the next route. - * \param self Instance pointer - * \return \c true if the endpoint result is critical, otherwise \c false. - */ -static bool Rtm_SetNextRouteIndex(CRouteManagement * self) -{ - bool found = false; - - if ((self->routes_list_size > 0U) && (self->nw_available)) - { - uint16_t tmp_idx; - self->curr_route_index++; - self->curr_route_index = self->curr_route_index%self->routes_list_size; - tmp_idx = self->curr_route_index; - - do - { - if (((self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED) && - (self->routes_list_ptr[self->curr_route_index].active == true)) || - ((self->routes_list_ptr[self->curr_route_index].active == true) && - (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_BUILT)) || - ((self->routes_list_ptr[self->curr_route_index].active == false) && - (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_IDLE)) || - ((Rtm_AreRouteNodesAvailable(self, &self->routes_list_ptr[self->curr_route_index]) == false) && - (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_IDLE))) - { - self->curr_route_index++; - self->curr_route_index = self->curr_route_index%self->routes_list_size; - } - else - { - found = true; - } - } - while ((tmp_idx != self->curr_route_index) && - (found == false)); - } - - return found; -} - -/*! \brief Starts the timer for handling routes. - * \param self Instance pointer - */ -static void Rtm_StartTmr4HandlingRoutes(CRouteManagement * self) -{ - if((T_IsTimerInUse(&self->route_check) == false) && - (!self->ucs_is_stopping)) - { - Tm_SetTimer(self->tm_ptr, - &self->route_check, - &Rtm_ExecRoutesHandling, - self, - RTM_JOB_CHECK_INTERVAL, - RTM_JOB_CHECK_INTERVAL); - } -} - -/*! \brief Gets the next route. - * \param self Instance pointer - * \return the next route to be handled - */ -static Ucs_Rm_Route_t * Rtm_GetNextRoute(CRouteManagement * self) -{ - self->routes_list_ptr[self->curr_route_index].internal_infos.rtm_inst = (Rtm_Inst_t *)(void *)self; - return &self->routes_list_ptr[self->curr_route_index]; -} - -/*! \brief Checks if the API is locked. - * \param self Instance pointer - * \return \c true if the API is not locked and the UCS are initialized, otherwise \c false. - */ -static bool Rtm_IsApiFree(CRouteManagement *self) -{ - return (self->lock_api == false); -} - -/*! \brief Locks/Unlocks the RTM API. - * \param self Instance pointer - * \param status Locking status. \c true = Lock, \c false = Unlock - */ -static void Rtm_ApiLocking(CRouteManagement *self, bool status) -{ - self->lock_api = status; -} - -/*! \brief Checks whether the nodes (source and sink) of the current route is available. - * \param self Instance pointer - * \param route_ptr Reference to the Route to be looked for - * \return \c true if the source endpoint's node is available, otherwise \c false. - */ -static bool Rtm_AreRouteNodesAvailable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - bool result = false; - MISC_UNUSED (self); - - if ((route_ptr->source_endpoint_ptr != NULL) && (route_ptr->sink_endpoint_ptr != NULL)) - { - if ((route_ptr->source_endpoint_ptr->node_obj_ptr != NULL) && - (route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr != NULL) && - (route_ptr->sink_endpoint_ptr->node_obj_ptr != NULL) && - (route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr != NULL)) - { - if (((1U == route_ptr->source_endpoint_ptr->node_obj_ptr->internal_infos.available) || - (route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV) || - (Net_IsOwnAddress(self->net_ptr, route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr->node_address) == NET_IS_OWN_ADDR_NODE)) && - ((Net_IsOwnAddress(self->net_ptr, route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address) == NET_IS_OWN_ADDR_NODE) || - (route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV) || - (1U == route_ptr->sink_endpoint_ptr->node_obj_ptr->internal_infos.available))) - { - result = true; - } - } - } - else - { - TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "ERROR PARAMETER on route id {%X}: At least one endpoint is NULL.", 1U, route_ptr->route_id)); - } - - return result; -} - -/*! \brief Checks if we encountered a deadlock situation with the given route and if we do, resolves It by resetting the endpoint concerned. - * - * Since we can encounter the situation that the construction of an endpoint fails and the routing management is not aware of that (synchronous vs asynchronous response) - * and still consider that the route is processing. In such a case the RTM process will never get a response and will wait in vain for It. - * Therefore, the role of this function is to release the blocking situation in resetting the concerned endpoint. - * \param self Instance pointer - * \param tgt_route_ptr Reference to the route that contains the endpoint to be looked for - * \param endpoint_ptr Reference to the endpoint to be looked for - * \return \c true if the endpoint's result is critical, otherwise \c false - */ -static bool Rtm_UnlockPossibleBlockings(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr) -{ - bool result_critical = Rtm_CheckEpResultSeverity(self, tgt_route_ptr, endpoint_ptr); - if (!result_critical) - { - if (UCS_RM_ROUTE_UNCRITICAL == self->curr_route_ptr->internal_infos.last_route_result) - { - Epm_ResetState(self->epm_ptr, endpoint_ptr); - } - } - return result_critical; -} - -/*! \brief Stops routes handling. - * \param self Instance pointer - */ -static void Rtm_StopRoutesHandling(CRouteManagement * self) -{ - Tm_ClearTimer(self->tm_ptr, &self->route_check); -} - -/*! \brief Releases all routes endpoints and notifies that the process is terminated for all "active" routes, which are not built or suspended. - * \param self Instance pointer - */ -static void Rtm_HandleProcessTermination(CRouteManagement * self) -{ - if ((self->routes_list_ptr != NULL) && (self->routes_list_size > 0U)) - { - uint8_t k = 0U; - - for (; k < self->routes_list_size; k++) - { - Epm_ClearIntInfos(self->epm_ptr, self->routes_list_ptr[k].source_endpoint_ptr); - Epm_ClearIntInfos(self->epm_ptr, self->routes_list_ptr[k].sink_endpoint_ptr); - - if ((self->routes_list_ptr[k].active == 1U) && - (self->routes_list_ptr[k].internal_infos.notify_termination == 0U) && - (self->routes_list_ptr[k].internal_infos.route_state != UCS_RM_ROUTE_BUILT) && - (self->routes_list_ptr[k].internal_infos.route_state != UCS_RM_ROUTE_SUSPENDED)) - { - if ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) || - (self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_DESTRUCTION)) - { - self->routes_list_ptr[k].internal_infos.route_state = UCS_RM_ROUTE_IDLE; - } - - self->routes_list_ptr[k].internal_infos.notify_termination = 0x01U; - if (self->report_fptr != NULL) - { - self->report_fptr(&self->routes_list_ptr[k], UCS_RM_ROUTE_INFOS_PROCESS_STOP, self->base_ptr->ucs_user_ptr); - } - } - } - } -} - -/*! \brief Resets the availability flag of all nodes involved in routing process. - * \param self Instance pointer - */ -static void Rtm_ResetNodesAvailable(CRouteManagement * self) -{ - uint8_t k = 0U; - - if ((self->routes_list_ptr != NULL) && (self->routes_list_size > 0U)) - { - for (; k < self->routes_list_size; k++) - { - if ((self->routes_list_ptr[k].sink_endpoint_ptr != NULL) && - (self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr != NULL)) - { - self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr->internal_infos.available = 0U; - } - - if ((self->routes_list_ptr[k].source_endpoint_ptr != NULL) && - (self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr != NULL)) - { - self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr->internal_infos.available = 0U; - } - } - } -} - -/*! \brief Releases all suspended routes of the given node. - * \details This function should only be called when the provided node, on which the suspended routes are, - * is set to "not available". - * \param self Instance pointer - * \param node_ptr Reference to the node to be looked for - */ -static void Rtm_ReleaseSuspendedRoutes(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr) -{ - uint8_t k = 0U; - bool is_ep_result_critical = false; - - if ((self != NULL) && (self->routes_list_ptr != NULL) && - (self->routes_list_size > 0U) && (node_ptr != NULL)) - { - for (; k < self->routes_list_size; k++) - { - is_ep_result_critical = Rtm_CheckEpResultSeverity(self, &self->routes_list_ptr[k], self->routes_list_ptr[k].sink_endpoint_ptr); - if ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED) || - ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_DETERIORATED) && - (self->routes_list_ptr[k].internal_infos.last_route_result == UCS_RM_ROUTE_CRITICAL)) || - ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) && - (is_ep_result_critical))) - { - if (((self->routes_list_ptr[k].source_endpoint_ptr != NULL) && - (self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr == node_ptr)) || - ((self->routes_list_ptr[k].sink_endpoint_ptr != NULL) && - (self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr == node_ptr))) - { - Rtm_ForcesRouteToIdle(self, &self->routes_list_ptr[k]); - } - } - } - } -} - -/*! \brief Sets the given routes to the "Idle" state and resets its internal variables. - * \details This function is risky and should only be used in Rtm_ReleaseSuspendedRoutes(). Because it forces a route's state to "Idle" - * without any external events. - * \param self Instance pointer - * \param route_ptr Reference to the route to be set - */ -static void Rtm_ForcesRouteToIdle(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr) -{ - if ((self != NULL) && (route_ptr != NULL)) - { - route_ptr->internal_infos.route_state = UCS_RM_ROUTE_IDLE; - route_ptr->internal_infos.last_route_result = UCS_RM_ROUTE_NOERROR; - if (route_ptr->source_endpoint_ptr != NULL) - { - if (Rtm_CheckEpResultSeverity(self, route_ptr, route_ptr->source_endpoint_ptr)) - { - Epm_ResetState(self->epm_ptr, route_ptr->source_endpoint_ptr); - } - } - if (route_ptr->sink_endpoint_ptr != NULL) - { - if (Rtm_CheckEpResultSeverity(self, route_ptr, route_ptr->sink_endpoint_ptr)) - { - Epm_ResetState(self->epm_ptr, route_ptr->sink_endpoint_ptr); - } - } - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Callback Functions */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Called if UCS initialization has been succeeded. - * \param self Instance pointer - * \param event_ptr Reference to reported event - */ -static void Rtm_UcsInitSucceededCb(void *self, void *event_ptr) -{ - CRouteManagement *self_ = (CRouteManagement *)self; - MISC_UNUSED(event_ptr); - - /* Remove ucsinit_observer */ - Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucsinit_observer); - - /* Add network status observer */ - Mobs_Ctor(&self_->nwstatus_observer, self, RTM_MASK_NETWORK_AVAILABILITY, &Rtm_MnsNwStatusInfosCb); - Net_AddObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_observer); -} - -/*! \brief Handle internal errors and un-initialize RTM service. - * \param self Instance pointer - * \param error_code_ptr Reference to internal error code - */ -static void Rtm_UninitializeService(void *self, void *error_code_ptr) -{ - CRouteManagement *self_ = (CRouteManagement *)self; - MISC_UNUSED(error_code_ptr); - - self_->ucs_is_stopping = true; - - /* Notify destruction of current routes */ - Rtm_HandleProcessTermination(self_); - - /* Remove RTM service from schedulers list */ - (void)Scd_RemoveService(&self_->base_ptr->scd, &self_->rtm_srv); - /* Remove error/event observers */ - Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucstermination_observer); - Net_DelObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_observer); - - /* Unlock API */ - Rtm_ApiLocking(self_, false); -} - -/*! \brief Event Callback function for the network status. - * \param self Instance pointer - * \param event_ptr Reference to the events - */ -static void Rtm_MnsNwStatusInfosCb(void *self, void *event_ptr) -{ - CRouteManagement *self_ = (CRouteManagement *)self; - Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)event_ptr; - - if (RTM_MASK_NETWORK_AVAILABILITY == (RTM_MASK_NETWORK_AVAILABILITY & result_ptr_->change_mask)) - { - if (UCS_NW_NOT_AVAILABLE == result_ptr_->availability) - { - self_->nw_available = false; - /* Resets Nodes availability flag */ - Rtm_ResetNodesAvailable(self_); - /* Reports Network Status "NotAvailabe" */ - Epm_ReportShutDown(self_->epm_ptr); - } - else - { - self_->nw_available = true; - /* Check whether there are routes to be processed */ - Rtm_StartRoutingTimer (self_); - } - } -} - -/*! \brief Event Callback function that signals that an endpoint is unavailable. - * \param self Instance pointer - * \param result_ptr Reference to the results - */ -static void Rtm_EndPointDeterioredCb(void *self, void *result_ptr) -{ - Ucs_Rm_Route_t * route_ptr = (Ucs_Rm_Route_t *)self; - Ucs_Rm_EndPoint_t * ep_ptr = (Ucs_Rm_EndPoint_t *)result_ptr; - - if ((route_ptr->source_endpoint_ptr == ep_ptr) || - (route_ptr->sink_endpoint_ptr == ep_ptr)) - { - if (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT) - { - TR_INFO((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->base_ptr->ucs_user_ptr, "[RTM]", "Route id %X is deteriorated", 1U, route_ptr->route_id)); - if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) - { - route_ptr->internal_infos.src_obsvr_initialized = 0U; - } - - Rtm_HandleRoutingError((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst, route_ptr); - - if ((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->nw_available) && - (!((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->ucs_is_stopping)) - { - Rtm_StartTmr4HandlingRoutes((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst); - } - else if (((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->ucs_is_stopping) - { - Rtm_HandleProcessTermination((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst); - } - } - } - else - { - TR_ERROR((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->base_ptr->ucs_user_ptr, "[RTM]", "Wrong endpoint {%X} of type %s on route id {%X}.", 3U, - ep_ptr, (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", route_ptr->route_id)); - } -} - -/*! \brief Processes the handling of all routes. This method is the callback function of the routing timer - * \c route_chek. - * \param self Instance pointer - */ -static void Rtm_ExecRoutesHandling(void* self) -{ - CRouteManagement *self_ = (CRouteManagement *)self; - if (!self_->ucs_is_stopping) - { - bool index_set = Rtm_SetNextRouteIndex(self_); - if (index_set) - { - Srv_SetEvent(&self_->rtm_srv, RTM_EVENT_HANDLE_NEXTROUTE); - } - else - { - Srv_SetEvent(&self_->rtm_srv, RTM_EVENT_PROCESS_PAUSE); - TR_INFO((self_->base_ptr->ucs_user_ptr, "[RTM]", "Handling process of routes is paused", 0U)); - } - } - else - { - Rtm_HandleProcessTermination(self_); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_scheduler.c b/ucs2-lib/src/ucs_scheduler.c deleted file mode 100644 index be7f7b8..0000000 --- a/ucs2-lib/src/ucs_scheduler.c +++ /dev/null @@ -1,258 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 scheduler module. The module consists of the two classes - * CScheduler and CService. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_SCHEDULER - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_scheduler.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Constants */ -/*------------------------------------------------------------------------------------------------*/ -const Srv_Event_t SRV_EMPTY_EVENT_MASK = (Srv_Event_t)0x00000000; /*!< \brief Empty event mask */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static bool Scd_SearchSlot(void *current_prio_ptr, void *new_prio_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CScheduler */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the scheduler class. - * \param self Instance pointer - * \param init_ptr Reference to the initialization data - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Scd_Ctor(CScheduler *self, Scd_InitData_t *init_ptr, void * ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->ucs_user_ptr = ucs_user_ptr; - Dl_Ctor(&self->srv_list, ucs_user_ptr); - Ssub_Ctor(&self->service_request_subject, ucs_user_ptr); - (void)Ssub_AddObserver(&self->service_request_subject, - init_ptr->service_request_obs_ptr); - self->scd_srv_is_running = false; -} - -/*! \brief Add the given service to the scheduler. All services are arranged in priority order. - * A service with a higher priority will execute before a service with a lower priority. - * \param self Instance pointer - * \param srv_ptr Reference of the service which shall be added - * \return SCD_OK: Service added - * \return SCD_SRV_ALREADY_LISTED: Services already listed - */ -Scd_Ret_t Scd_AddService(CScheduler *self, CService *srv_ptr) -{ - Scd_Ret_t ret_val; - - /* Check that service is not already part of scheduler */ - if(Dl_IsNodeInList(&self->srv_list, &srv_ptr->list_node) == false) - { - /* Search slot where the service must be inserted depending on the priority value. */ - CDlNode *result_ptr = Dl_Foreach(&self->srv_list, &Scd_SearchSlot, &srv_ptr->priority); - - if(result_ptr != NULL) /* Slot found? */ - { - Dl_InsertBefore(&self->srv_list, result_ptr, &srv_ptr->list_node); - } - else /* No slot found -> Insert as last node */ - { - Dl_InsertTail(&self->srv_list, &srv_ptr->list_node); - } - /* Create back link service -> scheduler */ - srv_ptr->scd_ptr = self; - Dln_SetData(&srv_ptr->list_node, &srv_ptr->priority); - ret_val = SCD_OK; - } - else /* Service is already part of schedulers list */ - { - ret_val = SCD_SRV_ALREADY_LISTED; - } - - return ret_val; -} - -/*! \brief Remove the given service from the schedulers list. - * \param self Instance pointer - * \param srv_ptr Reference of the service which shall be removed - * \return SCD_OK: Service removed - * \return SCD_UNKNOWN_SRV: Unknown service can not be removed - */ -Scd_Ret_t Scd_RemoveService(CScheduler *self, CService *srv_ptr) -{ - Scd_Ret_t ret_val = SCD_OK; - - /* Error occurred? */ - if(Dl_Remove(&self->srv_list, &srv_ptr->list_node) == DL_UNKNOWN_NODE) - { - ret_val = SCD_UNKNOWN_SRV; - } - - return ret_val; -} - -/*! \brief Service function of the scheduler module. - * \param self Instance pointer - */ -void Scd_Service(CScheduler *self) -{ - CService *current_srv_ptr = (CService *)(void*)self->srv_list.head; - - /* Scheduler service is running. Important for event handling */ - self->scd_srv_is_running = true; - - while(current_srv_ptr != NULL) /* Process registered services */ - { - if(current_srv_ptr->service_fptr != NULL) - { - /* Are events pending for the current service */ - if(current_srv_ptr->event_mask != SRV_EMPTY_EVENT_MASK) - { - /* Execute service callback function */ - current_srv_ptr->service_fptr(current_srv_ptr->instance_ptr); - /* Was the current service removed from the schedulers list? */ - if((current_srv_ptr->list_node.prev == NULL) && (current_srv_ptr->list_node.next == NULL)) - { - break; /* Abort scheduler service */ - } - } - } - current_srv_ptr = (CService *)(void*)current_srv_ptr->list_node.next; - } - /* Scheduler services finished */ - self->scd_srv_is_running = false; -} - -/*! \brief Searches for pending events. - * \param self Instance pointer - * \return true: At least one event is active - * \return false: No event is pending - */ -bool Scd_AreEventsPending(CScheduler *self) -{ - bool ret_val = false; - CService *current_srv_ptr = (CService *)(void*)self->srv_list.head; - - while(current_srv_ptr != NULL) - { - if(current_srv_ptr->event_mask != SRV_EMPTY_EVENT_MASK) - { - ret_val = true; - break; - } - current_srv_ptr = (CService *)(void*)current_srv_ptr->list_node.next; - } - - return ret_val; -} - -/*! \brief Searches the slot where the new service has to be inserted. The position depends on - * the given priority. If a the priority of the new service is higher than the priority - * of the current service \c true is returned which stops the search. - * \param current_prio_ptr Current service which is analyzed - * \param new_prio_ptr Priority of the new service - * \return false: The priority of the current service is greater than the new priority - * \return true: The priority of the current service is less than or equal to the new priority - */ -static bool Scd_SearchSlot(void *current_prio_ptr, void *new_prio_ptr) -{ - uint8_t current_prio_ptr_ = *((uint8_t *)current_prio_ptr); - uint8_t new_prio_ = *((uint8_t*)new_prio_ptr); - bool ret_val = false; - - if(current_prio_ptr_ <= new_prio_) - { - ret_val = true; - } - - return ret_val; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CService */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Parameter constructor of the service class. - * \param self Instance pointer - * \param instance_ptr Reference to object which contains the corresponding service - * \param priority Priority of the service - * \param service_fptr Service callback - */ -void Srv_Ctor(CService *self, uint8_t priority, void *instance_ptr, Srv_Cb_t service_fptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - Dln_Ctor(&self->list_node, NULL); - self->priority = priority; - self->instance_ptr = instance_ptr; - self->service_fptr = service_fptr; -} - -/*! \brief Sets events for the given service according to the given event mask. - * \param self Instance pointer - * \param event_mask Mask of the events to be set - */ -void Srv_SetEvent(CService *self, Srv_Event_t event_mask) -{ - self->event_mask |= event_mask; - if(self->scd_ptr->scd_srv_is_running == false) - { - Ssub_Notify(&self->scd_ptr->service_request_subject, NULL, false); - } -} - -/*! \brief The function returns the current state of all event bits of the service. - * \param self Instance pointer - * \param event_mask_ptr Reference to the memory of the returned event mask - */ -void Srv_GetEvent(CService *self, Srv_Event_t *event_mask_ptr) -{ - *event_mask_ptr = self->event_mask; -} - -/*! \brief Clears events for the given service according to the given event mask. - * \param self Instance pointer - * \param event_mask Mask of the events to be clear - */ -void Srv_ClearEvent(CService *self, Srv_Event_t event_mask) -{ - self->event_mask &= ~event_mask; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_segmentation.c b/ucs2-lib/src/ucs_segmentation.c deleted file mode 100644 index bbdd786..0000000 --- a/ucs2-lib/src/ucs_segmentation.c +++ /dev/null @@ -1,550 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 AMS Segmentation Class - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_AMSSEGM - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_segmentation.h" -#include "ucs_ams.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ - /*!\brief Timeout for garbage collector */ -static const uint16_t SEGM_GC_TIMEOUT = 5000U; /* parasoft-suppress MISRA2004-8_7 "intended usage as configuration parameter" */ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal typedefs */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static Ucs_AmsRx_Msg_t *Segm_RxRetrieveProcessingHandle(CSegmentation *self, Msg_MostTel_t *tel_ptr); -static void Segm_RxStoreProcessingHandle(CSegmentation *self, Ucs_AmsRx_Msg_t *msg_ptr); -static bool Segm_RxSearchProcessingHandle(void *current_data, void *search_data); -static bool Segm_RxGcSetLabel(void *current_data, void *search_data); -static Ucs_AmsRx_Msg_t* Segm_RxProcessTelId0(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr); -static void Segm_RxProcessTelId1(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr); -static void Segm_RxProcessTelId2(CSegmentation *self, Msg_MostTel_t *tel_ptr); -static Ucs_AmsRx_Msg_t* Segm_RxProcessTelId3(CSegmentation *self, Msg_MostTel_t *tel_ptr); -static void Segm_RxProcessTelId4(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Initialization methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CSegmentation - * \param self The instance - * \param base_ptr Reference to base services - * \param pool_ptr Reference to the (Rx) message pool - * \param rx_def_payload_sz Default memory size that is allocated when receiving segmented messages - * without size prefix - */ -void Segm_Ctor(CSegmentation *self, CBase *base_ptr, CAmsMsgPool *pool_ptr, uint16_t rx_def_payload_sz) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->base_ptr = base_ptr; /* initialize members */ - self->pool_ptr = pool_ptr; - - self->rx_default_payload_sz = rx_def_payload_sz; - - Dl_Ctor(&self->processing_list, self->base_ptr->ucs_user_ptr); - T_Ctor(&self->gc_timer); - Tm_SetTimer(&self->base_ptr->tm, /* start garbage collector timer */ - &self->gc_timer, - &Segm_RxGcScanProcessingHandles, - self, - SEGM_GC_TIMEOUT, - SEGM_GC_TIMEOUT - ); -} - -/*! \brief Constructor of class CSegmentation - * \param self The instance - * \param error_fptr Reference to segmentation error callback function - * \param error_inst Reference to segmentation error instance - */ -void Segm_AssignRxErrorHandler(CSegmentation *self, Segm_OnError_t error_fptr, void *error_inst) -{ - self->error_fptr = error_fptr; - self->error_inst = error_inst; -} - -/*! \brief Performs cleanup of pending messages - * \param self The instance - */ -void Segm_Cleanup(CSegmentation *self) -{ - CDlNode *node_ptr = NULL; - /* cleanup Tx queue */ - for (node_ptr = Dl_PopHead(&self->processing_list); node_ptr != NULL; node_ptr = Dl_PopHead(&self->processing_list)) - { - Ucs_AmsRx_Msg_t *rx_ptr = (Ucs_AmsRx_Msg_t*)Dln_GetData(node_ptr); - - Amsp_FreeRxPayload(self->pool_ptr, rx_ptr); - Amsp_FreeRxObj(self->pool_ptr, rx_ptr); - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Tx segmentation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Builds next MOST telegram according to given Application Messages - * \param self The instance - * \param msg_ptr Reference to the Application Message Tx handle - * \param tel_ptr Reference to the MOST Telegram handle - * \return Returns \c True if segmentation was completed for the Application Message. Otherwise \c false. - */ -bool Segm_TxBuildSegment(CSegmentation *self, Ucs_AmsTx_Msg_t* msg_ptr, Msg_MostTel_t *tel_ptr) -{ - bool finished = false; - MISC_UNUSED(self); - - tel_ptr->destination_addr = msg_ptr->destination_address; - Msg_SetAltMsgId((CMessage*)(void*)tel_ptr, msg_ptr->msg_id); - tel_ptr->opts.llrbc = msg_ptr->llrbc; - tel_ptr->info_ptr = msg_ptr; /* info_ptr must carry the reference to AMS Tx message object */ - tel_ptr->opts.cancel_id = Amsg_TxGetFollowerId(msg_ptr); - - if (msg_ptr->data_size <= SEGM_MAX_SIZE_TEL) /* is single transfer? */ - { - Msg_SetExtPayload((CMessage*)(void*)tel_ptr, msg_ptr->data_ptr, (uint8_t)msg_ptr->data_size, NULL); - finished = true; - } - else /* is segmented transfer? */ - { - uint16_t next_segm_cnt = Amsg_TxGetNextSegmCnt(msg_ptr); - - if (next_segm_cnt == 0xFFFFU) /* first segment: size prefixed segmented message TelId = "4" */ - { - tel_ptr->tel.tel_id = 4U; - tel_ptr->tel.tel_data_ptr[0] = MISC_HB(msg_ptr->data_size); - tel_ptr->tel.tel_data_ptr[1] = MISC_LB(msg_ptr->data_size); - tel_ptr->tel.tel_len = 2U; - } - else /* further segments: TelId = "1,2,3" */ - { - uint16_t index = next_segm_cnt * ((uint16_t)SEGM_MAX_SIZE_TEL - 1U); - uint16_t remaining_sz = msg_ptr->data_size - index; - uint8_t tel_sz = SEGM_MAX_SIZE_TEL - 1U; - - if (remaining_sz < SEGM_MAX_SIZE_TEL) - { - tel_ptr->tel.tel_id = 3U; /* is last segment */ - tel_sz = (uint8_t)remaining_sz; - finished = true; - } - else - { - if (index == 0U) - { - tel_ptr->tel.tel_id = 1U; /* is first segment */ - } - else - { - tel_ptr->tel.tel_id = 2U; /* is subsequent segment */ - } - } - - tel_ptr->tel.tel_cnt = (uint8_t)next_segm_cnt; - Msg_SetExtPayload((CMessage*)(void*)tel_ptr, &msg_ptr->data_ptr[index], tel_sz, NULL); - } - - Amsg_TxIncrementNextSegmCnt(msg_ptr); - } - - return finished; -} - -/*------------------------------------------------------------------------------------------------*/ -/* Rx pools */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Retrieves a processing Rx Application message object to a corresponding MOST telegram - * \param self The instance - * \param tel_ptr Reference to the MOST telegram - * \return The reference to the corresponding Rx Application Message or \c NULL if no appropriate - * Rx Application Message is available. - */ -static Ucs_AmsRx_Msg_t* Segm_RxRetrieveProcessingHandle(CSegmentation *self, Msg_MostTel_t *tel_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - CDlNode *result_node_ptr = Dl_Foreach(&self->processing_list, &Segm_RxSearchProcessingHandle, tel_ptr); - - if (result_node_ptr != NULL) - { - Dl_Ret_t ret = Dl_Remove(&self->processing_list, result_node_ptr); - TR_ASSERT(self->base_ptr->ucs_user_ptr, "[SEGM]", (ret == DL_OK)); - msg_ptr = (Ucs_AmsRx_Msg_t*)Dln_GetData(result_node_ptr); - MISC_UNUSED(ret); - } - - return msg_ptr; -} - -/*! \brief Stores a processing Rx Application message object into a dedicated list - * \param self The instance - * \param msg_ptr Reference to the Rx Application Message - */ -static void Segm_RxStoreProcessingHandle(CSegmentation *self, Ucs_AmsRx_Msg_t *msg_ptr) -{ - Amsg_RxSetGcMarker(msg_ptr, false); - Amsg_RxEnqueue(msg_ptr, &self->processing_list); /* insert at tail, since garbage collector starts at head */ -} - -/*! \brief Performs garbage collection of outdated message objects - * \param self The instance - */ -void Segm_RxGcScanProcessingHandles(void *self) -{ - CSegmentation *self_ = (CSegmentation*)self; - /* first remove outdated messages */ - CDlNode *node_ptr = Dl_PeekHead(&self_->processing_list); /* get first candidate from head */ - - while (node_ptr != NULL) - { - Ucs_AmsRx_Msg_t *msg_ptr = (Ucs_AmsRx_Msg_t*)Dln_GetData(node_ptr); - - if (Amsg_RxGetGcMarker(msg_ptr) != false) - { - Msg_MostTel_t tel; - - Amsg_RxCopySignatureToTel(msg_ptr, &tel); - self_->error_fptr(self_->error_inst, &tel, SEGM_ERR_5); - - (void)Dl_Remove(&self_->processing_list, node_ptr); - - Amsp_FreeRxPayload(self_->pool_ptr, msg_ptr); - Amsp_FreeRxObj(self_->pool_ptr, msg_ptr); - - node_ptr = Dl_PeekHead(&self_->processing_list); /* get next candidate from head */ - } - else - { - break; - } - } - - (void)Dl_Foreach(&self_->processing_list, &Segm_RxGcSetLabel, NULL); /* set label of all remaining messages */ -} - -/*! \brief Sets garbage collector flags for all list members - * \param current_data The Application message object present in list - * \param search_data unused (\c NULL) - * \return Returns always false in order to handle all list members */ -static bool Segm_RxGcSetLabel(void *current_data, void *search_data) -{ - Ucs_AmsRx_Msg_t *msg_ptr = (Ucs_AmsRx_Msg_t*)current_data; - Amsg_RxSetGcMarker(msg_ptr, true); - MISC_UNUSED(search_data); - return false; -} - -/*! \brief Search routine to identify message objects with the same signature - * than a given MOST telegram - * \param current_data The Application message object present in list - * \param search_data The MOST Telegram object - * \return Returns \c true if both handles have the same functional signature, - * otherwise \c false. */ -static bool Segm_RxSearchProcessingHandle(void *current_data, void *search_data) -{ - Ucs_AmsRx_Msg_t *msg_ptr = (Ucs_AmsRx_Msg_t*)current_data; - Msg_MostTel_t *tel_ptr = (Msg_MostTel_t*)search_data; - - return Amsg_RxHandleIsIdentical(msg_ptr, tel_ptr); -} - -/*------------------------------------------------------------------------------------------------*/ -/* Rx segmentation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Processes segmentation for a received MOST telegram - * \param self The instance - * \param tel_ptr The received MOST telegram - * \param result_ptr The result of the segmentation process - * \return The completed Rx Application Message or \c NULL if segmentation process is still - * ongoing. - */ -Ucs_AmsRx_Msg_t* Segm_RxExecuteSegmentation(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = NULL; - *result_ptr = SEGM_RES_OK; - - switch (tel_ptr->tel.tel_id) /* parasoft-suppress MISRA2004-15_3 "ignore unexpected TelIds" */ - { - case 0U: - msg_ptr = Segm_RxProcessTelId0(self, tel_ptr, result_ptr); - break; - case 1U: - Segm_RxProcessTelId1(self, tel_ptr, result_ptr); - break; - case 2U: - Segm_RxProcessTelId2(self, tel_ptr); - break; - case 3U: - msg_ptr = Segm_RxProcessTelId3(self, tel_ptr); - break; - case 4U: - Segm_RxProcessTelId4(self, tel_ptr, result_ptr); - break; - default: - break; - } - - return msg_ptr; /* return completed message */ -} - -/*! \brief Processes segmentation for a received MOST telegram with \c TelId="0" - * \param self The instance - * \param tel_ptr The received MOST telegram - * \param result_ptr Result of segmentation process - * \return The completed Rx Application Message or \c NULL if segmentation process - * does not finish successfully. - */ -static Ucs_AmsRx_Msg_t* Segm_RxProcessTelId0(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Segm_RxRetrieveProcessingHandle(self, tel_ptr); - *result_ptr = SEGM_RES_OK; - - if (msg_ptr != NULL) /* treat error: segmentation process is ongoing */ - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_7); - Amsp_FreeRxPayload(self->pool_ptr, msg_ptr);/* free assigned user payload and throw segmentation error */ - Amsp_FreeRxObj(self->pool_ptr, msg_ptr); - msg_ptr = NULL; - } - /* try to allocate handle, memory is NetServices provided (payload <= 45 bytes) */ - msg_ptr = Amsp_AllocRxObj(self->pool_ptr, (uint16_t)tel_ptr->tel.tel_len); - - if (msg_ptr == NULL) - { - msg_ptr = Amsp_AllocRxRsvd(self->pool_ptr); - } - - if (msg_ptr != NULL) /* handle available: setup Rx Application Message */ - { - Amsg_RxCopySignatureFromTel(msg_ptr, tel_ptr); - - if (tel_ptr->tel.tel_len > 0U) - { /* copy payload to message */ - Amsg_RxCopyToPayload(msg_ptr, tel_ptr->tel.tel_data_ptr, tel_ptr->tel.tel_len); - } - else - { /* set payload length to zero */ - msg_ptr->data_ptr = NULL; - msg_ptr->data_size = 0U; - } - } - else - { - *result_ptr = SEGM_RES_RETRY; /* retry when next Rx object is released */ - } - - return msg_ptr; -} - -/*! \brief Processes segmentation for a received MOST telegram with \c TelId="1" - * \param self The instance - * \param tel_ptr The received MOST telegram - * \param result_ptr Result of segmentation process - */ -static void Segm_RxProcessTelId1(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr) -{ - *result_ptr = SEGM_RES_OK; - - if (tel_ptr->tel.tel_cnt != 0U) /* handle incorrect tel_cnt */ - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_3); - } - else /* tel_cnt is correct -> continue segmentation */ - { - Ucs_AmsRx_Msg_t *msg_ptr = Segm_RxRetrieveProcessingHandle(self, tel_ptr); - bool is_size_prefixed = false; - - if (msg_ptr != NULL) /* has previous message */ - { - if ((Amsg_RxGetExpTelCnt(msg_ptr) != 0U) || (msg_ptr->data_size > 0U)) - { /* error: previous message already contains segments */ - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_7); - Amsp_FreeRxPayload(self->pool_ptr, msg_ptr); - Amsg_RxHandleSetup(msg_ptr); /* initialize message for re-use */ - } - else /* message and payload had been allocated by TelId '4' */ - { - is_size_prefixed = true; - } - } - else /* allocate message object if pre-allocation was not initiated by TelId "4" */ - { - msg_ptr = Amsp_AllocRxObj(self->pool_ptr, 0U); - } - - if (msg_ptr != NULL) /* now allocate payload */ - { - if (is_size_prefixed == false) - { - Amsg_RxCopySignatureFromTel(msg_ptr, tel_ptr); /* save signature and try to allocate */ - (void)Amsp_AllocRxPayload(self->pool_ptr, self->rx_default_payload_sz, msg_ptr); - } - - if (!Amsg_RxHasExternalPayload(msg_ptr)) /* allocation of payload failed */ - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_2); - Amsp_FreeRxObj(self->pool_ptr, msg_ptr); - msg_ptr = NULL; - } - else /* allocation of payload succeeded */ - { - (void)Amsg_RxAppendPayload(msg_ptr, tel_ptr); - Segm_RxStoreProcessingHandle(self, msg_ptr); - msg_ptr = NULL; - } - } - else /* no message object allocated */ - { /* send segmentation error */ - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_4); - } - } -} - -/*! \brief Processes segmentation for a received MOST telegram with \c TelId="2" - * \param self The instance - * \param tel_ptr The received MOST telegram - */ -static void Segm_RxProcessTelId2(CSegmentation *self, Msg_MostTel_t *tel_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Segm_RxProcessTelId3(self, tel_ptr); /* pretend having TelId '2' but store the */ - /* assembled message again */ - if (msg_ptr != NULL) - { - Segm_RxStoreProcessingHandle(self, msg_ptr); - } -} - -/*! \brief Processes segmentation for a received MOST telegram with \c TelId="3" - * \param self The instance - * \param tel_ptr The received MOST telegram - * \return The assembled Rx Application Message or \c NULL if segmentation process - * did not process successfully. - */ -static Ucs_AmsRx_Msg_t* Segm_RxProcessTelId3(CSegmentation *self, Msg_MostTel_t *tel_ptr) -{ - Ucs_AmsRx_Msg_t *msg_ptr = Segm_RxRetrieveProcessingHandle(self, tel_ptr); - - if (msg_ptr == NULL) /* is first segment missing */ - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_1); - } - else - { - uint8_t exp_tel_cnt = Amsg_RxGetExpTelCnt(msg_ptr); - - if ((exp_tel_cnt == 0U) && (msg_ptr->data_size == 0U)) - { /* error: did not receive first segment */ - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_1); - Segm_RxStoreProcessingHandle(self, msg_ptr); - msg_ptr = NULL; - } - else if (exp_tel_cnt != tel_ptr->tel.tel_cnt) - { /* has wrong TelCnt */ - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_3); - Segm_RxStoreProcessingHandle(self, msg_ptr); - msg_ptr = NULL; - } - - if (msg_ptr != NULL) - { - bool succ = Amsg_RxAppendPayload(msg_ptr, tel_ptr); - - if (succ == false) - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_2); - Amsp_FreeRxPayload(self->pool_ptr, msg_ptr); - Amsp_FreeRxObj(self->pool_ptr, msg_ptr); - msg_ptr = NULL; - } - } - } - - return msg_ptr; -} - -/*! \brief Processes segmentation for a received MOST telegram with \c TelId="4" - * \param self The instance - * \param tel_ptr The received MOST telegram - * \param result_ptr Result of segmentation process - */ -static void Segm_RxProcessTelId4(CSegmentation *self, Msg_MostTel_t *tel_ptr, Segm_Result_t *result_ptr) -{ - *result_ptr = SEGM_RES_OK; - - if (tel_ptr->tel.tel_len >= 2U) /* telegrams has necessary length */ - { - uint16_t msg_size; - MISC_DECODE_WORD(&msg_size, tel_ptr->tel.tel_data_ptr); - - if (msg_size > SEGM_MAX_SIZE_TEL) /* application message has correct size */ - { - Ucs_AmsRx_Msg_t *msg_ptr = Segm_RxRetrieveProcessingHandle(self, tel_ptr); - - if (msg_ptr != NULL) /* treat error: segmentation process is ongoing */ - { - Amsp_FreeRxPayload(self->pool_ptr, msg_ptr); - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_7); - Amsg_RxHandleSetup(msg_ptr); /* initialize message for re-use */ - } - else - { /* try to allocate handle, memory is NetServices provided (payload <= 45 bytes) */ - msg_ptr = Amsp_AllocRxObj(self->pool_ptr, 0U); - } - - if (msg_ptr != NULL) /* allocation succeeded: decode length and allocate payload */ - { - Amsg_RxCopySignatureFromTel(msg_ptr, tel_ptr); - (void)Amsp_AllocRxPayload(self->pool_ptr, msg_size, msg_ptr); - Segm_RxStoreProcessingHandle(self, msg_ptr);/* store handle and don't care if payload was allocated or not */ - msg_ptr = NULL; /* segmentation error 2 is treated by TelId 1 */ - } - else - { - self->error_fptr(self->error_inst, tel_ptr, SEGM_ERR_4); - } - } - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_smm.c b/ucs2-lib/src/ucs_smm.c deleted file mode 100644 index f201d36..0000000 --- a/ucs2-lib/src/ucs_smm.c +++ /dev/null @@ -1,219 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class CStaticMemoryManager. - * \cond UCS_INTERNAL_DOC - * \addtogroup G_UCS_SMM_CLASS - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_smm.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static Smm_Descriptor_t* Smm_GetTypeDescriptor(CStaticMemoryManager *self, Ams_MemUsage_t type); -static void* Smm_Allocate(void *self, uint16_t mem_size, Ams_MemUsage_t type, void** custom_info_pptr); -static void Smm_Free(void *self, void *mem_ptr, Ams_MemUsage_t type, void* custom_info_ptr); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the static memory manager - * \param self The instance - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Smm_Ctor(CStaticMemoryManager *self, void *ucs_user_ptr) -{ - uint8_t index; - self->ucs_user_ptr = ucs_user_ptr; - - Dl_Ctor(&self->tx_object_descr.list, ucs_user_ptr); /* initialize descriptor lists */ - Dl_Ctor(&self->rx_object_descr.list, ucs_user_ptr); - Dl_Ctor(&self->tx_payload_descr.list, ucs_user_ptr); - Dl_Ctor(&self->rx_payload_descr.list, ucs_user_ptr); - Dl_Ctor(&self->null_descr.list, ucs_user_ptr); - - self->tx_object_descr.max_mem_size = AMSG_TX_OBJECT_SZ; /* initialize descriptor memory sizes */ - self->rx_object_descr.max_mem_size = AMSG_RX_OBJECT_SZ; - self->tx_payload_descr.max_mem_size = SMM_SIZE_TX_MSG; - self->rx_payload_descr.max_mem_size = SMM_SIZE_RX_MSG; - self->null_descr.max_mem_size = 0U; - - for (index = 0U; index < SMM_NUM_TX_MSGS; index++) /* initialize Tx objects and payload */ - { /* CDlNode::data_ptr has to point to the memory */ - Dln_Ctor(&self->resources.tx_objects[index].node, &self->resources.tx_objects[index].object); - Dl_InsertTail(&self->tx_object_descr.list, &self->resources.tx_objects[index].node); - - Dln_Ctor(&self->resources.tx_payload[index].node, &self->resources.tx_payload[index].data); - Dl_InsertTail(&self->tx_payload_descr.list, &self->resources.tx_payload[index].node); - } - - for (index = 0U; index < SMM_NUM_RX_MSGS; index++) /* initialize Rx objects and payload */ - { /* CDlNode::data_ptr has to point to the memory */ - Dln_Ctor(&self->resources.rx_objects[index].node, &self->resources.rx_objects[index].object); - Dl_InsertTail(&self->rx_object_descr.list, &self->resources.rx_objects[index].node); - - Dln_Ctor(&self->resources.rx_payload[index].node, &self->resources.rx_payload[index].data); - Dl_InsertTail(&self->rx_payload_descr.list, &self->resources.rx_payload[index].node); - } -} - -/*! \brief Load function of the static memory management plug-in. - * \param self The instance - * \param allocator_ptr Assignable interface for allocate and free functions - * \param rx_def_payload_size The default Rx allocation size the AMS uses if TelId "4" is missing. - * Just use for checks. Do not overrule. - * \return Returns \c UCS_RET_SUCCESS if the initialization succeeded, otherwise \c UCS_RET_ERR_PARAM. - */ -Ucs_Return_t Smm_LoadPlugin(CStaticMemoryManager *self, Ams_MemAllocator_t *allocator_ptr, uint16_t rx_def_payload_size) -{ - Ucs_Return_t ret = UCS_RET_SUCCESS; - - allocator_ptr->inst_ptr = self; /* assign instance to allocator */ - allocator_ptr->alloc_fptr = &Smm_Allocate; /* assign callback functions */ - allocator_ptr->free_fptr = &Smm_Free; - - if (rx_def_payload_size != SMM_SIZE_RX_MSG) - { - ret = UCS_RET_ERR_PARAM; - TR_ERROR((self->ucs_user_ptr, "[SMM]", "SMM initialization failed: wrong configuration of rx_def_payload_size.", 0U)); - } - - return ret; -} - -/*! \brief Retrieves a descriptor for a memory type - * \param self The instance - * \param type Usage type of the requested memory - * \return Returns the respective descriptor for a memory type - */ -static Smm_Descriptor_t* Smm_GetTypeDescriptor(CStaticMemoryManager *self, Ams_MemUsage_t type) -{ - Smm_Descriptor_t* descr_ptr = NULL; - - switch (type) - { - case AMS_MU_RX_OBJECT: - descr_ptr = &self->rx_object_descr; - break; - case AMS_MU_RX_PAYLOAD: - descr_ptr = &self->rx_payload_descr; - break; - case AMS_MU_TX_OBJECT: - descr_ptr = &self->tx_object_descr; - break; - case AMS_MU_TX_PAYLOAD: - descr_ptr = &self->tx_payload_descr; - break; - default: - TR_FAILED_ASSERT(self->ucs_user_ptr, "[SMM]"); /* requested memory for unknown type */ - descr_ptr = &self->null_descr; - break; - } - - return descr_ptr; -} - -/*! \brief Allocates memory of a certain type - * \param self The instance - * \param mem_size Size of the memory in bytes - * \param type The memory usage type - * \param custom_info_pptr Reference to custom information - * \return Returns a reference to the allocated memory or \c NULL if the allocation is not possible - */ -static void* Smm_Allocate(void *self, uint16_t mem_size, Ams_MemUsage_t type, void** custom_info_pptr) -{ - CStaticMemoryManager *self_ = (CStaticMemoryManager*)self; - void *mem_ptr = NULL; - CDlNode *node_ptr = NULL; - - Smm_Descriptor_t* descr_ptr = Smm_GetTypeDescriptor(self_, type); - - if (mem_size <= descr_ptr->max_mem_size) - { - node_ptr = Dl_PopHead(&descr_ptr->list); /* size is ok, retrieve a node from the list */ - } - - if (node_ptr != NULL) - { - mem_ptr = Dln_GetData(node_ptr); /* retrieve reference of whole message object */ - *custom_info_pptr = node_ptr; - } - - return mem_ptr; -} - -/*! \brief Frees memory of a certain type - * \param self The instance - * \param mem_ptr Reference to the memory chunk - * \param type The memory usage type - * \param custom_info_ptr Reference to custom information - */ -static void Smm_Free(void *self, void *mem_ptr, Ams_MemUsage_t type, void* custom_info_ptr) -{ - CStaticMemoryManager *self_ = (CStaticMemoryManager*)self; - Smm_Descriptor_t* descr_ptr = Smm_GetTypeDescriptor(self_, type); - - Dl_InsertHead(&descr_ptr->list, (CDlNode*)custom_info_ptr); - MISC_UNUSED(mem_ptr); -} - -/*! \brief Retrieves the current number of unused message objects. - * \param self The instance - * \param rx_cnt_ptr Application provided reference to write the current number of unused Rx message objects. - * \param tx_cnt_ptr Application provided reference to write the current number of unused Tx message objects. - * \return Returns \c UCS_RET_ERR_PARAM if \c NULL is provided otherwise \c UCS_RET_SUCCESS. - */ -Ucs_Return_t Smm_GetFreeBufferCnt(CStaticMemoryManager *self, uint16_t *rx_cnt_ptr, uint16_t *tx_cnt_ptr) -{ - Ucs_Return_t ret = UCS_RET_SUCCESS; - - if ((tx_cnt_ptr != NULL) && (rx_cnt_ptr != NULL)) - { - *rx_cnt_ptr = Dl_GetSize(&self->rx_object_descr.list); - *tx_cnt_ptr = Dl_GetSize(&self->tx_object_descr.list); - } - else - { - ret = UCS_RET_ERR_PARAM; - } - - return ret; -} - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_sys_diag.c b/ucs2-lib/src/ucs_sys_diag.c deleted file mode 100644 index 0c80eb6..0000000 --- a/ucs2-lib/src/ucs_sys_diag.c +++ /dev/null @@ -1,1343 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 System Diagnosis class - * \details Performs the System Diagnosis - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_SYS_DIAG - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_misc.h" -#include "ucs_ret_pb.h" -#include "ucs_sys_diag.h" -/*#include "ucs_mnsa.h"*/ - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ -#define SYS_DIAG_NUM_STATES 10U /*!< \brief Number of state machine states */ -#define SYS_DIAG_NUM_EVENTS 17U /*!< \brief Number of state machine events */ - -#define SD_NUM_HELLO 10U /*!< \brief Number of Hello.Get Retries */ -#define SD_TIMEOUT_HELLO 150U /*!< \brief timeout used for repeating Hello.Get messages */ -#define SD_TIMEOUT_COMMAND 100U /*!< \brief timeout used for supervising INIC commands */ -#define SD_TIMEOUT_CABLE_DIAGNOSIS 3000U /*!< \brief timeout used for supervising cable link diagnosis */ -#define SD_DIAG_ADDR_BASE 0x0500U /*!< \brief Diagnosis Node Address of own node */ - -#define SD_WELCOME_SUCCESS 0U /*!< \brief Welcome.Result reports success */ - -#define SD_SIGNATURE_VERSION 1U /*!< \brief signature version used for System Diagnosis */ - - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the System Diagnosis service used by scheduler */ -static const uint8_t SD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the System Diagnosis service */ -static const Srv_Event_t SD_EVENT_SERVICE = 1U; - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal enumerators */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Possible events of the system diagnosis state machine */ -typedef enum SysDiag_Events_ -{ - SD_E_NIL = 0U, /*!< \brief NIL Event */ - SD_E_STARTDIAG = 1U, /*!< \brief StartDiag API function was called */ - SD_E_SD_RES_OK = 2U, /*!< \brief MOSTNetworkSystemDiagnosis.Result received */ - SD_E_ABORT = 3U, /*!< \brief Application requires stop of System Diagnosis */ - SD_E_HELLO_OK = 4U, /*!< \brief Hello.Status received */ - SD_E_HELLO_RETRY = 5U, /*!< \brief Retry the Hello.Get command */ - SD_E_HELLO_ALL_DONE = 6U, /*!< \brief All retries of the Hello.Get command are done */ - SD_E_WELCOME = 7U, /*!< \brief Welcome.Result, may be Ok or NotOk*/ - SD_E_ALL_DONE = 8U, /*!< \brief All branches and segments of the network were explored*/ - SD_E_PORT_FOUND = 9U, /*!< \brief An unexplored port was found */ - SD_E_PORT_ENABLED = 10U, /*!< \brief A port was succesful enabled */ - SD_E_PORT_DISABLED = 11U, /*!< \brief A port was succesful disabled */ - SD_E_BRANCH_FOUND = 12U, /*!< \brief Another branch was found */ - SD_E_CABLE_LINK_RES = 13U, /*!< \brief The CableLinkDiagnosis reported a result */ - SD_E_ERROR = 14U, /*!< \brief An error was detected */ - SD_E_TIMEOUT = 15U, /*!< \brief An timeout has been occurred */ - SD_E_NO_SUCCESS = 16U /*!< \brief Welcome result was NoSuccess */ -} SysDiag_Events_t; - -/*! \brief States of the system diagnosis state machine */ -typedef enum SysDiag_State_ -{ - SD_S_IDLE = 0U, /*!< \brief Idle state */ - SD_S_WAIT_DIAG = 1U, /*!< \brief System Diagnosis started */ - SD_S_WAIT_HELLO = 2U, /*!< \brief Hello command sent */ - SD_S_HELLO_TIMEOUT = 3U, /*!< \brief Hello command timed out */ - SD_S_WAIT_WELCOME = 4U, /*!< \brief Welcome sent */ - SD_S_NEXT_PORT = 5U, /*!< \brief Next port found to be tested */ - SD_S_WAIT_ENABLE = 6U, /*!< \brief Port Enable sent */ - SD_S_WAIT_DISABLE = 7U, /*!< \brief Port Disable sent */ - SD_S_CABLE_LINK_DIAG = 8U, /*!< \brief Wait for CableL Link Diagnosis Result */ - SD_S_END = 9U /*!< \brief Wait for System Diagnosis stop */ -} SysDiag_State_t; - - - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Sd_Service(void *self); - -static void Sd_SysDiagInit(void* self); -static void Sd_SysDiagStart(void *self); -static void Sd_SysDiagStop(void *self); -static void Sd_SendHello(void *self); -static void Sd_Error(void *self); -static void Sd_ErrorWelcome(void *self); -static void Sd_SendWelcome(void *self); -static void Sd_CableLinkDiagnosis(void *self); -static void Sd_CalcPort(void *self); -static void Sd_AllDone(void *self); -static void Sd_EnablePort(void *self); -static void Sd_DisablePort(void *self); -static void Sd_Finish(void *self); -static void Sd_Abort(void *self); -static void Sd_StopDiagFailed(void *self); - -static void Sd_HelloTimeout(void *self); -static void Sd_SysDiagTimeout(void *self); -static void Sd_WelcomeTimeout(void *self); -static void Sd_EnablePortTimeout(void *self); -static void Sd_DisablePortTimeout(void *self); -static void Sd_CableLinkDiagnosisTimeout(void *self); - -static void Sd_SysDiagStartResultCb(void *self, void *result_ptr); -static void Sd_SysDiagStopResultCb(void *self, void *result_ptr); -static void Sd_HelloStatusCb(void *self, void *result_ptr); -static void Sd_WelcomeResultCb(void *self, void *result_ptr); -static void Sd_EnablePortResultCb(void *self, void *result_ptr); -static void Sd_DisablePortResultCb(void *self, void *result_ptr); -static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr); -static void Sd_OnTerminateEventCb(void *self, void *result_ptr); -static void Sd_TimerCb(void *self); - - - - -/*------------------------------------------------------------------------------------------------*/ -/* State transition table (used by finite state machine) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief State transition table */ -static const Fsm_StateElem_t sys_diag_trans_tab[SYS_DIAG_NUM_STATES][SYS_DIAG_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -{ - - { /* State SD_S_IDLE */ - /* SD_E_NIL */ {NULL, SD_S_IDLE }, - /* SD_E_STARTDIAG */ {&Sd_SysDiagStart, SD_S_WAIT_DIAG }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_IDLE }, - /* SD_E_ABORT */ {NULL, SD_S_IDLE }, - /* SD_E_HELLO_OK */ {NULL, SD_S_IDLE }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_IDLE }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_IDLE }, - /* SD_E_WELCOME */ {NULL, SD_S_IDLE }, - /* SD_E_ALL_DONE */ {NULL, SD_S_IDLE }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_IDLE }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_IDLE }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_IDLE }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_IDLE }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_IDLE }, - /* SD_E_ERROR */ {NULL, SD_S_IDLE }, - /* SD_E_TIMEOUT */ {NULL, SD_S_IDLE }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_IDLE } - }, - - { /* State SD_S_WAIT_DIAG */ - /* SD_E_NIL */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_SD_RES_OK */ {&Sd_SendHello, SD_S_WAIT_HELLO }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DIAG }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_SysDiagTimeout, SD_S_END }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DIAG } - }, - - { /* State SD_S_WAIT_HELLO*/ - /* SD_E_NIL */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {&Sd_SendWelcome, SD_S_WAIT_WELCOME }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_WELCOME */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_HELLO }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_HelloTimeout, SD_S_HELLO_TIMEOUT }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_HELLO } - }, - - { /* State SD_S_HELLO_TIMEOUT */ - /* SD_E_NIL */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_STARTDIAG */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_HELLO_RETRY */ {&Sd_SendHello, SD_S_WAIT_HELLO }, - /* SD_E_HELLO_ALL_DONE */ {&Sd_CableLinkDiagnosis, SD_S_CABLE_LINK_DIAG }, - /* SD_E_WELCOME */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_ALL_DONE */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {NULL, SD_S_HELLO_TIMEOUT }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_HELLO_TIMEOUT } - }, - - { /* State SD_S_WAIT_WELCOME */ - /* SD_E_NIL */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_WELCOME */ {&Sd_CalcPort, SD_S_NEXT_PORT }, - /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_WELCOME }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_WelcomeTimeout, SD_S_END }, - /* SD_E_NO_SUCCESS */ {&Sd_ErrorWelcome, SD_S_END } - }, - - { /* State SD_S_NEXT_PORT */ - /* SD_E_NIL */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_STARTDIAG */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_WELCOME */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_ALL_DONE */ {&Sd_AllDone, SD_S_END }, - /* SD_E_PORT_FOUND */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_BRANCH_FOUND */ {&Sd_DisablePort, SD_S_WAIT_DISABLE }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {NULL, SD_S_NEXT_PORT }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_NEXT_PORT } - }, - - { /* State SD_S_WAIT_ENABLE */ - /* SD_E_NIL */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_WELCOME */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_PORT_ENABLED */ {&Sd_SendHello, SD_S_WAIT_HELLO }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_ENABLE }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_EnablePortTimeout, SD_S_END }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_ENABLE } - }, - - { /* State SD_S_WAIT_DISABLE */ - /* SD_E_NIL */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_PORT_DISABLED */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DISABLE }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_DisablePortTimeout, SD_S_END }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DISABLE } - }, - - { /* State SD_S_CABLE_LINK_DIAG */ - /* SD_E_NIL */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_STARTDIAG */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_SD_RES_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_WELCOME */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, - /* SD_E_CABLE_LINK_RES */ {&Sd_CalcPort, SD_S_NEXT_PORT }, - /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, - /* SD_E_TIMEOUT */ {&Sd_CableLinkDiagnosisTimeout, SD_S_END }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_CABLE_LINK_DIAG } - }, - - { /* State SD_S_END */ - /* SD_E_NIL */ {NULL, SD_S_END }, - /* SD_E_STARTDIAG */ {NULL, SD_S_END }, - /* SD_E_SD_RES_OK */ {Sd_Finish, SD_S_IDLE }, - /* SD_E_ABORT */ {NULL, SD_S_END }, - /* SD_E_HELLO_OK */ {NULL, SD_S_END }, - /* SD_E_HELLO_RETRY */ {NULL, SD_S_END }, - /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_END }, - /* SD_E_WELCOME */ {NULL, SD_S_END }, - /* SD_E_ALL_DONE */ {NULL, SD_S_END }, - /* SD_E_PORT_FOUND */ {NULL, SD_S_END }, - /* SD_E_PORT_ENABLED */ {NULL, SD_S_END }, - /* SD_E_PORT_DISABLED */ {NULL, SD_S_END }, - /* SD_E_BRANCH_FOUND */ {NULL, SD_S_END }, - /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_END }, - /* SD_E_ERROR */ {Sd_StopDiagFailed, SD_S_IDLE }, - /* SD_E_TIMEOUT */ {Sd_StopDiagFailed, SD_S_IDLE }, - /* SD_E_NO_SUCCESS */ {NULL, SD_S_END } - } - -}; - - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ - -/*! \brief Constructor of class CSysDiag. - * \param self Reference to CSysDiag instance - * \param inic Reference to CInic instance - * \param base Reference to CBase instance - * \param exc Reference to CExc instance - */ - void SysDiag_Ctor(CSysDiag *self, CInic *inic, CBase *base, CExc *exc) -{ - MISC_MEM_SET((void *)self, 0, sizeof(*self)); - - self->inic = inic; - self->exc = exc; - self->base = base; - - Fsm_Ctor(&self->fsm, self, &(sys_diag_trans_tab[0][0]), SYS_DIAG_NUM_EVENTS, SD_E_NIL); - - Sobs_Ctor(&self->sys_diag_start, self, &Sd_SysDiagStartResultCb); - Sobs_Ctor(&self->sys_diag_stop, self, &Sd_SysDiagStopResultCb); - Sobs_Ctor(&self->sys_hello, self, &Sd_HelloStatusCb); - Sobs_Ctor(&self->sys_welcome, self, &Sd_WelcomeResultCb); - Sobs_Ctor(&self->sys_enable_port, self, &Sd_EnablePortResultCb); - Sobs_Ctor(&self->sys_disable_port, self, &Sd_DisablePortResultCb); - Sobs_Ctor(&self->sys_cable_link_diagnosis, self, &Sd_CableLinkDiagnosisResultCb); - - /* register termination events */ - Mobs_Ctor(&self->sys_terminate, self, EH_M_TERMINATION_EVENTS, &Sd_OnTerminateEventCb); - Eh_AddObsrvInternalEvent(&self->base->eh, &self->sys_terminate); - - /* Initialize System Diagnosis service */ - Srv_Ctor(&self->sd_srv, SD_SRV_PRIO, self, &Sd_Service); - /* Add System Diagnosis service to scheduler */ - (void)Scd_AddService(&self->base->scd, &self->sd_srv); - -} - -/*! \brief Service function of the System Diagnosis service. - * \param self Reference to System Diagnosis object - */ -static void Sd_Service(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->sd_srv, &event_mask); - if(SD_EVENT_SERVICE == (event_mask & SD_EVENT_SERVICE)) /* Is event pending? */ - { - Fsm_State_t result; - Srv_ClearEvent(&self_->sd_srv, SD_EVENT_SERVICE); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); - result = Fsm_Service(&self_->fsm); - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", (result != FSM_STATE_ERROR)); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM -> %d", 1U, self_->fsm.current_state)); - MISC_UNUSED(result); - } -} - - -/*! \brief Starts the System Diagnosis State machine - * - * \param *self Reference to System Diagnosis object - * \param *obs_ptr Observer pointer - * \return UCS_RET_SUCCESS Operation successful - * \return UCS_RET_ERR_API_LOCKED System Diagnosis was already started - * \return UCS_RET_ERR_BUFFER_OVERFLOW Invalid observer - */ -Ucs_Return_t SysDiag_Run(CSysDiag *self, CSingleObserver *obs_ptr) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - if (self->startup_locked == false) - { - Ssub_Ret_t ret_ssub; - - ret_ssub = Ssub_AddObserver(&self->sysdiag, obs_ptr); - if (ret_ssub != SSUB_UNKNOWN_OBSERVER) /* obs_ptr == NULL ? */ - { - self->startup_locked = true; - - Sd_SysDiagInit(self); - - Fsm_SetEvent(&self->fsm, SD_E_STARTDIAG); - Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); - - TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Run", 0U)); - } - else - { - ret_val = UCS_RET_ERR_BUFFER_OVERFLOW; /* obs_ptr was invalid */ - } - } - else - { - ret_val = UCS_RET_ERR_API_LOCKED; - } - - return ret_val; -} - - -/*! \brief Aborts the System Diagnosis State machine - * - * \param *self Reference to System Diagnosis object - * \return UCS_RET_SUCCESS Operation successful - * \return UCS_RET_ERR_NOT_AVAILABLE System Diagnosis not running - */ -Ucs_Return_t SysDiag_Abort(CSysDiag *self) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - if (self->startup_locked == true) /* check if System Diagnosis was started */ - { - Tm_ClearTimer(&self->base->tm, &self->timer); - - Fsm_SetEvent(&self->fsm, SD_E_ABORT); - Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); - TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Abort", 0U)); - } - else - { - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - } - - return ret_val; -} - -/*! Initialize the System Diagnosis - * - * \param self Reference to System Diagnosis object - */ -static void Sd_SysDiagInit(void* self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - self_->hello_retry = SD_NUM_HELLO; - self_->segment_nr = 0U; - self_->num_ports = 0U; - self_->curr_branch = 0U; - self_->source.node_address = 0xFFFFU; - self_->source.available = false; - self_->last_result = SD_INIT; - - self_->target.node_address = 0x0001U; /* address of own INIC */ - self_->target.available = false; - - self_->admin_node_address = SD_DIAG_ADDR_BASE; -} - - -/*! FSM action function: sets the INIC into System Diagnosis Mode - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_SysDiagStart(void *self) -{ - Ucs_Return_t ret_val; - - CSysDiag *self_ = (CSysDiag *)self; - - ret_val = Inic_NwSysDiagnosis(self_->inic, &self_->sys_diag_start); - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStart", 0U)); - - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_COMMAND, - 0U); - - MISC_UNUSED(ret_val); -} - - -/*! Callback function for the Inic_NwSysDiagnosis() command - * - * \param *self Reference to System Diagnosis object - * \param *result_ptr Result of the Inic_NwSysDiagnosis() command - */ -static void Sd_SysDiagStartResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_SD_RES_OK", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - -/*! FSM action function: Timeout occured - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_SysDiagTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Sd_SysDiagStop(self_); -} - -/*! FSM action function: Timeout occured - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_EnablePortTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Sd_SysDiagStop(self_); -} - -/*! FSM action function: Timeout occured - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_DisablePortTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Sd_SysDiagStop(self_); -} - -/*! Helper function. Stops the System Diagnosis - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_SysDiagStop(void *self) -{ - Ucs_Return_t ret_val; - - CSysDiag *self_ = (CSysDiag *)self; - - ret_val = Inic_NwSysDiagEnd(self_->inic, &self_->sys_diag_stop); - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStop", 0U)); - if (ret_val == UCS_RET_SUCCESS) - { - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_COMMAND, - 0U); - } - else - { - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; - - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); - } -} - - -/*! \brief Callback function for the Inic_NwSysDiagEnd() command - * - * \param *self Reference to System Diagnosis object - * \param *result_ptr Result of the Inic_NwSysDiagEnd() command - */ -static void Sd_SysDiagStopResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", UCS_RES_SUCCESS == result_ptr_->result.code); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_SD_RES_OK", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - - -/*! FSM action function: Send Hello.Get command - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_SendHello(void *self) -{ - Ucs_Return_t ret_val; - - CSysDiag *self_ = (CSysDiag *)self; - - ret_val = Exc_Hello_Get(self_->exc, - UCS_ADDR_BROADCAST_BLOCKING, - SD_SIGNATURE_VERSION, - &self_->sys_hello); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_HELLO, - 0U); - - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - -/*! Callback function for the Enc.Hello.Status message - * - * \param *self Reference to System Diagnosis object - * \param *result_ptr Result of the Exc_Hello_Get() command - */ -static void Sd_HelloStatusCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - /* read signature and store it for the Welcome command */ - self_->target.signature = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).signature; - self_->target.version = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).version; - - if (self_->segment_nr != 0U) - { - self_->target.node_address = self_->segment_nr + 0x0400U; - - } - - Fsm_SetEvent(&self_->fsm, SD_E_HELLO_OK); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_SD_RES_OK", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - -/*! \brief Timer callback used for supervising INIC command timeouts. - * \param self Reference to System Diagnosis object - */ -static void Sd_TimerCb(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - Fsm_SetEvent(&self_->fsm, SD_E_TIMEOUT); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_TimerCb SD_E_TIMEOUT", 0U)); - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - -/*! FSM action function: retry hello command or start CableLinkDiagnosis - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_HelloTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - if (self_->hello_retry > 0U) - { - --self_->hello_retry; - Fsm_SetEvent(&self_->fsm, SD_E_HELLO_RETRY); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_RETRY", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_HELLO_ALL_DONE); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_ALL_DONE", 0U)); - } - - /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ -} - - -/*! FSM action function: Send Welcome message - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_SendWelcome(void *self) -{ - Ucs_Return_t ret_val; - CSysDiag *self_ = (CSysDiag *)self; - - self_->admin_node_address = SD_DIAG_ADDR_BASE + self_->segment_nr; - - ret_val = Exc_Welcome_Sr(self_->exc, - self_->target.node_address, - self_->admin_node_address, - SD_SIGNATURE_VERSION, - self_->target.signature, - &self_->sys_welcome); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_COMMAND, - 0U); - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - - -/*! \brief Function is called on reception of the Welcome.Result messsage - * \param self Reference to System Diagnosis object - * \param result_ptr Pointer to the result of the Welcome message - */ -static void Sd_WelcomeResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - /* read signature and store it for the Welcome command */ - self_->target.result = (*(Exc_WelcomeResult_t *)(result_ptr_->data_info)).res; - - if (self_->target.result == SD_WELCOME_SUCCESS) - { - self_->target.available = true; - - if (self_->segment_nr == 0U) - { - self_->num_ports = self_->target.signature.num_ports; - } - else - { - self_->last_result = SD_SEGMENT; - } - /* do not report result for own node */ - if (self_->segment_nr != 0U) - { - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - - self_->report.code = UCS_SD_TARGET_FOUND; - self_->report.segment.branch = self_->curr_branch; - self_->report.segment.num = self_->segment_nr; - self_->report.segment.source = self_->source.signature; - self_->report.segment.target = self_->target.signature; - /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ - /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ - - Ssub_Notify(&self_->sysdiag, &self_->report, false); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb ReportSegment", 0U)); - } - - Fsm_SetEvent(&self_->fsm, SD_E_WELCOME); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb SD_E_WELCOME", 0U)); - } - else - { - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - - self_->report.code = UCS_SD_ERROR; - self_->report.segment.branch = self_->curr_branch; - self_->report.segment.num = self_->segment_nr; - self_->report.segment.source = self_->source.signature; - self_->report.segment.target = self_->target.signature; - /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ - self_->report.err_info = UCS_SD_ERR_WELCOME_NO_SUCCESS; - - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Fsm_SetEvent(&self_->fsm, SD_E_NO_SUCCESS); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb reported NoSuccess", 0U)); - } - - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb Error SD_E_ERROR 0x%x", 1U, result_ptr_->result.code)); - - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - -/*! \brief FSM action function: Calculate the next port tobe examined - * \param self Reference to System Diagnosis object - */ -static void Sd_CalcPort(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - switch (self_->last_result) - { - case SD_INIT: - self_->curr_branch = 0U; /* Master device has at least one port */ - self_->source = self_->target; - self_->master = self_->target; - - MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); - self_->last_result = SD_SEGMENT; - Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); - break; - - case SD_SEGMENT: - if (self_->target.signature.num_ports > 1U) - { - self_->source = self_->target; - MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); - Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); - } - else /* switch to next branch if possible*/ - { - if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ - { - Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); - } - else - { - self_->segment_nr = 1U; /* reset segment number */ - self_->curr_branch++; /* switch to next port */ - self_->source = self_->master; - MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); - Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); - } - } - break; - - case SD_CABLE_LINK: - if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ - { - Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); - } - else - { - self_->segment_nr = 1U; /* reset segment number */ - self_->curr_branch++; /* switch to next port */ - self_->source = self_->master; - MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); - Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); - } - break; - - default: - break; - } - - /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ -} - - -/*! \brief FSM action function: Enable port - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_EnablePort(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - uint16_t target_address; - uint8_t port_number; - Ucs_Return_t ret_val; - - if (self_->segment_nr == 0U) - { - port_number = self_->curr_branch; - target_address = 0x0001U; - } - else - { - port_number = 1U; - target_address = self_->source.node_address; - } - - ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, true, &self_->sys_enable_port); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_COMMAND, - 0U); - - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - - -/*! Function is called on reception of the EnablePort.Result messsage - * - * \param *self Reference to System Diagnosis object - * \param *result_ptr - */ -static void Sd_EnablePortResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - self_->segment_nr++; - Fsm_SetEvent(&self_->fsm, SD_E_PORT_ENABLED); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_PORT_ENABLED", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - -/*! \brief FSM action function: - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_DisablePort(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - uint16_t target_address; - uint8_t port_number; - Ucs_Return_t ret_val; - - target_address = self_->admin_node_address; - port_number = self_->curr_branch; - - ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, false, &self_->sys_disable_port); - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_COMMAND, - 0U); - - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - - -static void Sd_DisablePortResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - Fsm_SetEvent(&self_->fsm, SD_E_PORT_DISABLED); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_PORT_DISABLED", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_ERROR", 0U)); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); -} - - -/*! \brief FSM action function: Start CableLinkDiagnosis - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_CableLinkDiagnosis(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - uint16_t target_address; - uint8_t port_number; - Ucs_Return_t ret_val; - - - if (self_->segment_nr != 0U) /* do not start CableLinkDiagnosis when connecting to local INIC */ - { - target_address = self_->source.node_address; - - if (self_->segment_nr == 1U) - { - port_number = self_->curr_branch; - } - else - { - port_number = 1U; /* OS81119: always port 1 */ - } - - self_->last_result = SD_CABLE_LINK; - - ret_val = Exc_CableLinkDiagnosis_Start(self_->exc, target_address, port_number, &self_->sys_cable_link_diagnosis); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosis", 0U)); - - Tm_SetTimer(&self_->base->tm, - &self_->timer, - &Sd_TimerCb, - self_, - SD_TIMEOUT_CABLE_DIAGNOSIS, - 0U); - - TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); - MISC_UNUSED(ret_val); -} - else /* stop SystemDiagnosis when connecting to local INIC failed */ - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); - } -} - - -static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - - Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; - - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - if (result_ptr_->result.code == UCS_RES_SUCCESS) - { - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - - self_->report.code = UCS_SD_CABLE_LINK_RES; - self_->report.segment.branch = self_->curr_branch; - self_->report.segment.num = self_->segment_nr; - self_->report.segment.source = self_->source.signature; - /*self_->report.segment.target = self_->target.signature;*/ /* structure is not written deliberately */ - self_->report.cable_link_info = (*(Exc_CableLinkDiagResult_t *)(result_ptr_->data_info)).result; - /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ - - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - - Fsm_SetEvent(&self_->fsm, SD_E_CABLE_LINK_RES); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_CABLE_LINK_RES", 0U)); - } - else - { - Fsm_SetEvent(&self_->fsm, SD_E_ERROR); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_ERROR %02X %02X %02X", 3U, result_ptr_->result.info_ptr[0], result_ptr_->result.info_ptr[1], result_ptr_->result.info_ptr[2])); - } - - Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); - -} - - -/*! \brief FSM action function: React on Timeout of CableLinkDiagnosis - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_CableLinkDiagnosisTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); - Sd_SysDiagStop(self_); -} - -/*! \brief FSM action function: React on Timeout of Welcome - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_WelcomeTimeout(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); - Sd_SysDiagStop(self_); -} - - - - -/*! \brief FSM action function: All branches and segments explored, finish System Diagnosis - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_AllDone(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_AllDone", 0U)); - - Sd_SysDiagStop(self_); -} - - -/*! \brief FSM action function: INIC system Diagnosis mode ended - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_Finish(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - - self_->report.code = UCS_SD_FINISHED; - Ssub_Notify(&self_->sysdiag, &self_->report, true); - - self_->startup_locked = false; - - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Finish", 0U)); -} - -/*! \brief FSM action function: An unexpected error occurred. - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_Error(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Sd_SysDiagStop(self_); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Error", 0U)); -} - -/*! \brief FSM action function: Welcome reports NoSuccess. - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_ErrorWelcome(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - Sd_SysDiagStop(self_); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_ErrorWelcome", 0U)); -} - -/*! \brief FSM action function: stopping system diagnosis mode failed - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_StopDiagFailed(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - /* always finish the System Diagnosis with event UCS_SD_FINISHED */ - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_FINISHED; - Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ - - self_->startup_locked = false; - - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_StopDiagFailed", 0U)); -} - -/*! \brief FSM action function: Application requested to abort the System Diagnosis. - * - * \param *self Reference to System Diagnosis object - */ -static void Sd_Abort(void *self) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ABORTED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - Sd_SysDiagStop(self_); - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Abort", 0U)); -} - - - -/*! Function is called on severe internal errors - * - * \param *self Reference to System Diagnosis object - * \param *result_ptr Reference to data - */ -static void Sd_OnTerminateEventCb(void *self, void *result_ptr) -{ - CSysDiag *self_ = (CSysDiag *)self; - - MISC_UNUSED(result_ptr); - - if (self_->fsm.current_state != SD_S_IDLE) - { - Tm_ClearTimer(&self_->base->tm, &self_->timer); - - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_ERROR; - self_->report.err_info = UCS_SD_ERR_TERMINATED; - Ssub_Notify(&self_->sysdiag, &self_->report, false); - - /* always finish the System Diagnosis with event UCS_SD_FINISHED */ - MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); - self_->report.code = UCS_SD_FINISHED; - Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ - - TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_OnTerminateEventCb", 0U)); - - /* reset FSM */ - self_->startup_locked = false; - Sd_SysDiagInit(self_); - self_->fsm.current_state = SD_S_IDLE; - } -} - - - - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_telqueue.c b/ucs2-lib/src/ucs_telqueue.c deleted file mode 100644 index d969981..0000000 --- a/ucs2-lib/src/ucs_telqueue.c +++ /dev/null @@ -1,117 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class CTelQueue - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_MSG_QUEUE - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_telqueue.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal constants */ -/*------------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CTelQueue - * \param self The instance - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Telq_Ctor(CTelQueue *self, void *ucs_user_ptr) -{ - self->ucs_user_ptr = ucs_user_ptr; - Dl_Ctor(&self->list, self->ucs_user_ptr); -} - -/*! \brief Retrieves the head object of the telegram queue - * \param self The instance - * \return Reference to the telegram if a telegram object is available. - * Otherwise \c NULL. - */ -Msg_MostTel_t* Telq_Dequeue(CTelQueue *self) -{ - Msg_MostTel_t *tel_ptr = NULL; - CDlNode *node_ptr = Dl_PopHead(&self->list); - - if (node_ptr != NULL) - { - tel_ptr = (Msg_MostTel_t*)Dln_GetData(node_ptr); - } - - return tel_ptr; -} - -/*! \brief Retrieves a reference to the head object - * without removing it from the telegram queue - * \param self The instance - * \return Reference to the telegram if a telegram object is available. - * Otherwise \c NULL. - */ -Msg_MostTel_t* Telq_Peek(CTelQueue *self) -{ - Msg_MostTel_t *tel_ptr = NULL; - CDlNode *node_ptr = Dl_PeekHead(&self->list); - - if (node_ptr != NULL) - { - tel_ptr = (Msg_MostTel_t*)Dln_GetData(node_ptr); - } - - return tel_ptr; -} - -/*! \brief Adds a telegram to the tail of the queue - * \param self The instance - * \param tel_ptr Reference to the telegram - */ -void Telq_Enqueue(CTelQueue *self, Msg_MostTel_t *tel_ptr) -{ - Dl_InsertTail(&self->list, Msg_GetNode((CMessage*)(void*)tel_ptr)); -} - -/*! \brief Retrieves the current number of objects in the telegram queue - * \param self The instance - * \return The current number of available telegram objects in the pool - */ -uint8_t Telq_GetSize(CTelQueue *self) -{ - return (uint8_t)Dl_GetSize(&self->list); -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_timer.c b/ucs2-lib/src/ucs_timer.c deleted file mode 100644 index 6563374..0000000 --- a/ucs2-lib/src/ucs_timer.c +++ /dev/null @@ -1,456 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 timer management module. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_TIMER - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_timer.h" -#include "ucs_misc.h" -#include "ucs_trace.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the TM service used by scheduler */ -static const uint8_t TM_SRV_PRIO = 255U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! Main event for the TM service */ -static const Srv_Event_t TM_EVENT_UPDATE_TIMERS = 1U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Tm_Service(void *self); -static void Tm_UpdateTimers(CTimerManagement *self); -static bool Tm_HandleElapsedTimer(CTimerManagement *self); -static bool Tm_UpdateTimersAdd(void *c_timer_ptr, void *n_timer_ptr); -static void Tm_SetTimerInternal(CTimerManagement *self, - CTimer *timer_ptr, - Tm_Handler_t handler_fptr, - void *args_ptr, - uint16_t elapse, - uint16_t period); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CTimerManagement */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the timer management class. - * \param self Instance pointer - * \param scd Scheduler instance - * \param init_ptr Reference to the initialization data - * \param ucs_user_ptr User reference that needs to be passed in every callback function - */ -void Tm_Ctor(CTimerManagement *self, CScheduler *scd, const Tm_InitData_t *init_ptr, void * ucs_user_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->ucs_user_ptr = ucs_user_ptr; - /* Initialize subjects and add observers */ - Ssub_Ctor(&self->get_tick_count_subject, self->ucs_user_ptr); - (void)Ssub_AddObserver(&self->get_tick_count_subject, - init_ptr->get_tick_count_obs_ptr); - if(init_ptr->set_application_timer_obs_ptr != NULL) - { - self->delayed_tm_service_enabled = true; - Ssub_Ctor(&self->set_application_timer_subject, self->ucs_user_ptr); - (void)Ssub_AddObserver(&self->set_application_timer_subject, - init_ptr->set_application_timer_obs_ptr); - } - /* Initialize timer management service */ - Srv_Ctor(&self->tm_srv, TM_SRV_PRIO, self, &Tm_Service); - /* Add timer management service to scheduler */ - (void)Scd_AddService(scd, &self->tm_srv); -} - -/*! \brief Service function of the timer management. - * \param self Instance pointer - */ -static void Tm_Service(void *self) -{ - CTimerManagement *self_ = (CTimerManagement *)self; - Srv_Event_t event_mask; - - Srv_GetEvent(&self_->tm_srv, &event_mask); - - if(TM_EVENT_UPDATE_TIMERS == (event_mask & TM_EVENT_UPDATE_TIMERS)) /* Is event pending? */ - { - Srv_ClearEvent(&self_->tm_srv, TM_EVENT_UPDATE_TIMERS); - Tm_UpdateTimers(self_); - } -} - -/*! \brief If event TM_EVENT_UPDATE_TIMERS is set this function is called. Handles the update - * of the timer list. If a timer has expired the corresponding callback function is - * executed. If the expired timer is a periodic timer, the timer will be set again. - * \param self Instance pointer - */ -static void Tm_UpdateTimers(CTimerManagement *self) -{ - uint16_t current_tick_count; - Ssub_Notify(&self->get_tick_count_subject, ¤t_tick_count, false); - - if(self->timer_list.head != NULL) /* At least one timer is running? */ - { - bool continue_loop = true; - /* Calculate time difference between the current and the last TM service run */ - uint16_t tick_count_diff = (uint16_t)(current_tick_count - self->last_tick_count); - /* Save current tick count for next service run */ - self->last_tick_count = current_tick_count; - - /* Loop while timer list is not empty */ - while((self->timer_list.head != NULL) && (continue_loop!= false)) - { - /* Is not first timer in list elapsed yet? */ - if(tick_count_diff <= ((CTimer *)self->timer_list.head->data_ptr)->delta) - { - /* Update delta of first timer in list */ - ((CTimer *)self->timer_list.head->data_ptr)->delta -= tick_count_diff; - tick_count_diff = 0U; - } - else /* At least first timer in list elapsed */ - { - /* Update tick count difference for next timer in list */ - tick_count_diff -= ((CTimer *)self->timer_list.head->data_ptr)->delta; - /* First timer elapsed */ - ((CTimer *)self->timer_list.head->data_ptr)->delta = 0U; - } - - /* First timer in list elapsed? */ - if(0U == ((CTimer *)self->timer_list.head->data_ptr)->delta) - { - /* Handle elapsed timer */ - continue_loop = Tm_HandleElapsedTimer(self); - } - else /* No elapsed timer in list. */ - { - /* First timer in list updated! Set trigger to inform application (see - Tm_CheckForNextService()) and stop TM service. */ - self->set_service_timer = true; - continue_loop = false; - } - } - } -} - -/*! \brief This function is called if the first timer in list is elapsed. The timer handler - * callback function is invoked. If the timer is a periodic timer it is wound up again. - * \param self Instance pointer - * \return \c true if the next timer must be check. - * \return \c false if the wound up timer (periodic timer) is new head of timer list - */ -static bool Tm_HandleElapsedTimer(CTimerManagement *self) -{ - bool ret_val = true; - - CDlNode *node = self->timer_list.head; - /* Reset flag to be able to check if timer object has changed within handler - callback function */ - ((CTimer *)node->data_ptr)->changed = false; - /* Call timer handler callback function */ - ((CTimer *)node->data_ptr)->handler_fptr(((CTimer *)node->data_ptr)->args_ptr); - - /* Timer object hasn't changed within handler callback function? */ - if(false == ((CTimer *)node->data_ptr)->changed) - { - /* Remove current timer from list */ - (void)Dl_Remove(&self->timer_list, node); - /* Mark timer as unused */ - ((CTimer *)node->data_ptr)->in_use = false; - /* Is current timer a periodic timer? */ - if(((CTimer *)node->data_ptr)->period > 0U) - { - /* Reload current timer */ - Tm_SetTimerInternal(self, - ((CTimer *)node->data_ptr), - ((CTimer *)node->data_ptr)->handler_fptr, - ((CTimer *)node->data_ptr)->args_ptr, - ((CTimer *)node->data_ptr)->period, - ((CTimer *)node->data_ptr)->period); - - if(node == self->timer_list.head) /* Is current timer new head of list? */ - { - /* Set trigger to inform application (see Tm_CheckForNextService()) and - stop TM service. */ - self->set_service_timer = true; - ret_val = false; - } - } - } - - return ret_val; -} - -/*! \brief Calls an application callback function to inform the application that the UCS must be - * serviced not later than the passed time period. If the timer list is empty a possible - * running application timer will be stopped. This function is called at the end of - * Ucs_Service(). - * \param self Instance pointer - */ -void Tm_CheckForNextService(CTimerManagement *self) -{ - if(self->delayed_tm_service_enabled != false) - { - uint16_t current_tick_count; - Ssub_Notify(&self->get_tick_count_subject, ¤t_tick_count, false); - /* Has head of timer list changed? */ - if(self->set_service_timer != false) - { - uint16_t new_time; - uint16_t diff = current_tick_count - self->last_tick_count; - self->set_service_timer = false; - if (self->timer_list.head != NULL) - { - /* Timer expired since last TM service? */ - if(diff >= ((CTimer *)self->timer_list.head->data_ptr)->delta) - { - new_time = 1U; /* Return minimum value */ - } - else - { - /* Calculate new timeout */ - new_time = (uint16_t)(((CTimer *)self->timer_list.head->data_ptr)->delta - diff); - } - /* Inform the application that the UCS must be serviced not later than the passed - time period. */ - Ssub_Notify(&self->set_application_timer_subject, &new_time, false); - } - } - } - else - { - Tm_TriggerService(self); /* Application timer not implemented -> Retrigger TM */ - } -} - -/*! \brief Helper function to set the TM service event. - * \details This function is used by the application to trigger a service call of the Timer - * Management if the application timer has expired. - * \param self Instance pointer - */ -void Tm_TriggerService(CTimerManagement *self) -{ - if(self->timer_list.head != NULL) /* At least one timer is running? */ - { - Srv_SetEvent(&self->tm_srv, TM_EVENT_UPDATE_TIMERS); - } -} - -/*! \brief Helper function to stop the TM service. - * \param self Instance pointer - */ -void Tm_StopService(CTimerManagement *self) -{ - uint16_t new_time = 0U; - - /* Clear probable running application timer */ - Ssub_Notify(&self->set_application_timer_subject, &new_time, false); - - /* Reset the service timer. Not necessary ? */ - self->set_service_timer = false; - - /* Clear the timer head queue to prevent any event to be set */ - self->timer_list.head = NULL; -} - -/*! \brief Creates a new timer. The timer expires at the specified elapse time and then after - * every specified period. When the timer expires the specified callback function is - * called. - * \param self Instance pointer - * \param timer_ptr Reference to the timer object - * \param handler_fptr Callback function which is called when the timer expires - * \param args_ptr Reference to an optional parameter which is passed to the specified - * callback function - * \param elapse The elapse value before the timer expires for the first time, in - * milliseconds - * \param period The period of the timer, in milliseconds. If this parameter is zero, the - * timer is signaled once. If the parameter is greater than zero, the timer - * is periodic. - */ -void Tm_SetTimer(CTimerManagement *self, - CTimer *timer_ptr, - Tm_Handler_t handler_fptr, - void *args_ptr, - uint16_t elapse, - uint16_t period) -{ - (void)Tm_ClearTimer(self, timer_ptr); /* Clear timer if running */ - /* Call the internal method to set the new timer (-> does not trigger TM service!) */ - Tm_SetTimerInternal(self, timer_ptr, handler_fptr, args_ptr, elapse, period); - Tm_TriggerService(self); /* New timer added -> trigger timer list update */ -} - -/*! \brief This function contains the internal part when adding a new timer. The function is - * called within Tm_SetTimer() and within Tm_UpdateTimers(). - * \param self Instance pointer - * \param timer_ptr Reference to the timer object - * \param handler_fptr Callback function which is called when the timer expires - * \param args_ptr Reference to an optional parameter which is passed to the specified - * callback function - * \param elapse The elapse value before the timer expires for the first time, in - * milliseconds - * \param period The period of the timer, in milliseconds. If this parameter is zero, the - * timer is signaled once. If the parameter is greater than zero, the timer - * is periodic. - */ -static void Tm_SetTimerInternal(CTimerManagement *self, - CTimer *timer_ptr, - Tm_Handler_t handler_fptr, - void *args_ptr, - uint16_t elapse, - uint16_t period) -{ - uint16_t current_tick_count; - Ssub_Notify(&self->get_tick_count_subject, ¤t_tick_count, false); - - /* Save timer specific values */ - timer_ptr->changed = true; /* Flag is needed by Tm_UpdateTimers() */ - timer_ptr->in_use = true; - timer_ptr->handler_fptr = handler_fptr; - timer_ptr->args_ptr = args_ptr; - timer_ptr->elapse = elapse; - timer_ptr->period = period; - timer_ptr->delta = elapse; - - /* Create back link to be able to point from node to timer object */ - timer_ptr->node.data_ptr = (void *)timer_ptr; - - if(self->timer_list.head == NULL) /* Is timer list empty? */ - { - Dl_InsertHead(&self->timer_list, &timer_ptr->node); /* Add first timer to list */ - /* Save current tick count */ - Ssub_Notify(&self->get_tick_count_subject, &self->last_tick_count, false); - } - else /* Timer list is not empty */ - { - CDlNode *result_ptr = NULL; - - /* Set delta value in relation to last saved tick count (last TM service) */ - timer_ptr->delta += (uint16_t)(current_tick_count - self->last_tick_count); - - /* Search slot where new timer must be inserted. Update delta of new timer - and delta of the following timer in the list. */ - result_ptr = Dl_Foreach(&self->timer_list, &Tm_UpdateTimersAdd, (void *)timer_ptr); - - if(result_ptr != NULL) /* Slot found? */ - { - /* Insert new timer at found position */ - Dl_InsertBefore(&self->timer_list, result_ptr, &timer_ptr->node); - } - else /* No slot found -> Insert as last node */ - { - /* Add new timer to end of list */ - Dl_InsertTail(&self->timer_list, &timer_ptr->node); - } - } -} - -/*! \brief Removes the specified timer from the timer list. - * \param self Instance pointer - * \param timer_ptr Reference to the timer object - * \attention Make sure that for a timer object Tm_SetTimer() is called before Tm_ClearTimer() - * is called! - */ -void Tm_ClearTimer(CTimerManagement *self, CTimer *timer_ptr) -{ - if(timer_ptr->in_use != false) /* Is timer currently in use? */ - { - timer_ptr->changed = true; /* Flag is needed by Tm_UpdateTimers() */ - - if(timer_ptr->node.next != NULL) /* Has deleted timer a follower? */ - { - /* Adjust delta of following timer */ - ((CTimer *)timer_ptr->node.next->data_ptr)->delta += timer_ptr->delta; - } - - (void)Dl_Remove(&self->timer_list, &timer_ptr->node); - timer_ptr->in_use = false; - - Tm_TriggerService(self); /* Timer removed -> trigger timer list update */ - } -} - -/*! \brief Used by Tm_SetTimer() to find the slot where the new timer must be inserted. - * \param c_timer_ptr Reference to current timer processed by foreach loop - * \param n_timer_ptr Reference to new timer - * \return \c true: Slot found, stop foreach loop - * \return \c false: Slot not found, continue foreach loop - */ -static bool Tm_UpdateTimersAdd(void *c_timer_ptr, void *n_timer_ptr) -{ - CTimer *current_timer_ptr = (CTimer *)c_timer_ptr; - CTimer *new_timer_ptr = (CTimer *)n_timer_ptr; - bool ret_val; - - /* Is current timer lesser than new timer? */ - if(current_timer_ptr->delta <= new_timer_ptr->delta) - { - /* Update delta of new timer and continue foreach loop */ - new_timer_ptr->delta -= current_timer_ptr->delta; - ret_val = false; - } - else /* Slot found! */ - { - /* Correct delta of current timer and stop foreach loop */ - current_timer_ptr->delta -= new_timer_ptr->delta; - ret_val = true; - } - - return ret_val; -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CTimer */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Timer class. - * \param self Instance pointer - */ -void T_Ctor(CTimer *self) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); -} - -/*! \brief Returns the status of the given timer. - * \param self Instance pointer - * \return \c true if the timer is currently in use - * \return \c false if the timer is not currently in use - */ -bool T_IsTimerInUse(CTimer *self) -{ - return self->in_use; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_transceiver.c b/ucs2-lib/src/ucs_transceiver.c deleted file mode 100644 index 54fdf0e..0000000 --- a/ucs2-lib/src/ucs_transceiver.c +++ /dev/null @@ -1,290 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 class CTransceiver - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_TRCV - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_transceiver.h" -#include "ucs_misc.h" -#include "ucs_pmp.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static void Trcv_OnTxStatusInternal(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of class CTransceiver - * \param self The instance - * \param fifo_ptr Reference to the dedicated port message FIFO - * \param def_src_addr Source address that is preset in Tx message object - * \param ucs_user_ptr User reference that needs to be passed in every callback function - * \param trace_id ID specifies FIFO in traces if multiple transceivers are running - */ -void Trcv_Ctor(CTransceiver *self, CPmFifo *fifo_ptr, uint16_t def_src_addr, void *ucs_user_ptr, uint8_t trace_id) -{ - MISC_MEM_SET(self, 0, sizeof(*self)); - self->fifo_ptr = fifo_ptr; - self->tx_def_src = def_src_addr; - self->ucs_user_ptr = ucs_user_ptr; - self->own_id = trace_id; - Pool_Ctor(&self->tx_msg_pool, self->tx_msgs, TRCV_SIZE_TX_POOL, ucs_user_ptr); - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (fifo_ptr != NULL)); -} - -/*! \brief Assigns a function of another class to receive messages - * \details The assigned function is responsible to call Trcv_RxReleaseMsg() it has finished to process it - * \param self The instance - * \param callback_fptr Callback function - * \param inst_ptr The instance of the receiver class - */ -void Trcv_RxAssignReceiver(CTransceiver *self, Trcv_RxCompleteCb_t callback_fptr, void *inst_ptr) -{ - self->rx_complete_fptr = callback_fptr; - self->rx_complete_inst = inst_ptr; -} - -/*! \brief Assigns a function of another class to filter Rx messages - * \details The assigned function is responsible to discard or pass Rx messages - * \param self The instance - * \param callback_fptr Callback function - * \param inst_ptr The instance of the filter class - */ -void Trcv_RxAssignFilter(CTransceiver *self, Trcv_RxFilterCb_t callback_fptr, void *inst_ptr) -{ - self->rx_filter_fptr = callback_fptr; - self->rx_filter_inst = inst_ptr; -} - -/*! \brief Releases an Rx message which was received by the assigned receiver - * \param self The instance - * \param tel_ptr Reference to the received message - */ -void Trcv_RxReleaseMsg(CTransceiver *self, Msg_MostTel_t *tel_ptr) -{ - CMessage *msg_ptr = (CMessage*)(void*)tel_ptr; - bool check_ok = !Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)); /* message object shall not be part of a list */ - /* because it was provided in an earlier step */ - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", check_ok); - if (check_ok) - { - Fifo_RxReleaseMsg(self->fifo_ptr, msg_ptr); - } -} - -/*! \brief Retrieves a message object from the pool - * \param self The instance - * \param size Size of the message in bytes. Valid range: 0..45. - * \return Reference to the Msg_MostTel_t structure if a message is available. - * Otherwise \c NULL. - */ -extern Msg_MostTel_t* Trcv_TxAllocateMsg(CTransceiver *self, uint8_t size) -{ - const uint8_t TRCV_CTRL_MAX_SIZE = 45U; /* replace by PMS constant in future */ - CMessage *handle = NULL; - Msg_MostTel_t *tel_ptr = NULL; - - if (size <= TRCV_CTRL_MAX_SIZE) - { - handle = Pool_GetMsg(&self->tx_msg_pool); - - if (handle != NULL) - { - Msg_Cleanup(handle); /* reset headers and fields */ - Msg_ReserveHeader(handle, PMP_PM_MAX_SIZE_HEADER + ENC_MAX_SIZE_CONTENT); - tel_ptr = Msg_GetMostTel(handle); /* return public struct of the message object */ - tel_ptr->tel.tel_id = 0U; - tel_ptr->tel.tel_len = size; - tel_ptr->tel.tel_cnt = 0U; - tel_ptr->source_addr = self->tx_def_src; - } - } - - return tel_ptr; -} - -/*! \brief Returns a message object to the transceiver pool a message was allocated from - * \param tel_ptr Reference to the message object which needs to be returned. - */ -void Trcv_TxReleaseMsg(Msg_MostTel_t *tel_ptr) -{ - CMessage* msg_ptr = (CMessage*)(void*)tel_ptr; /* avoid MISRA-C warning by converting to "void*" */ - bool check_ok = !Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)); /* message object shall not be part of a list */ - TR_ASSERT(0U, "[TRCV]", check_ok); /* because it was provided in an earlier step */ - - if (check_ok) - { - Pool_ReturnMsg(msg_ptr); - } -} - -/*! \brief Prepares a message object for re-transmission - * \param tel_ptr Reference to the Tx message object which needs - * to be reused. - */ -void Trcv_TxReuseMsg(Msg_MostTel_t *tel_ptr) -{ - CMessage* msg_ptr = (CMessage*)(void*)tel_ptr; - TR_ASSERT(0U, "[TRCV]", (!Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)))); /* message object shall not be part of a list */ - /* because it was provided in an earlier step */ - Msg_Cleanup(msg_ptr); /* reset headers and fields */ - Msg_ReserveHeader(msg_ptr, PMP_PM_MAX_SIZE_HEADER + ENC_MAX_SIZE_CONTENT); -} - -/*! \brief Transmits a given message object to the INIC - * \details After completed transmission the message object is released automatically - * \param self The instance - * \param tel_ptr Reference to the message object - */ -void Trcv_TxSendMsg(CTransceiver *self, Msg_MostTel_t *tel_ptr) -{ - CMessage *msg_ptr; - - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL)); - msg_ptr = (CMessage*)(void*)tel_ptr; - - TR_INFO((self->ucs_user_ptr, "[TRCV]", "Trcv_TxSendMsg(): FIFO: %u, MSG(tgt:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self->own_id, tel_ptr->destination_addr, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type)); - Msg_SetTxStatusHandler(msg_ptr, &Trcv_OnTxStatusInternal, self); /* just release the message */ - Fifo_Tx(self->fifo_ptr, msg_ptr, false); -} - -/*! \brief Transmits a given message object to the INIC with a dedicated result callback - * \param self The instance - * \param tel_ptr Reference to the message object - * \param callback_fptr Callback function which is invoked after message transmission has finished. - * Must be \c NULL to avoid that a callback function is invoked. In this case - * the message object is freed internally. Hence, the message object must - * not provide external payload. - * \param inst_ptr Reference to the instance which is invoked with callback_fptr. Has to be \c - * NULL if callback_fptr is \c NULL. - * \note The provided callback function is responsible to free the message object by calling - * Trcv_TxReleaseMsg() or to reuse the message object by calling Trcv_TxReuseMsg() before - * passing it to one of the transmit functions again. - */ -void Trcv_TxSendMsgExt(CTransceiver *self, Msg_MostTel_t *tel_ptr, Msg_TxStatusCb_t callback_fptr, void *inst_ptr) -{ - CMessage *msg_ptr; - - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL)); - msg_ptr = (CMessage*)(void*)tel_ptr; - - if (callback_fptr == NULL) - { - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (inst_ptr == NULL)); - callback_fptr = &Trcv_OnTxStatusInternal; - inst_ptr = self; - } - - TR_INFO((self->ucs_user_ptr, "[TRCV]", "Trcv_TxSendMsgExt(): FIFO: %u, MSG(tgt:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self->own_id, tel_ptr->destination_addr, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type)); - Msg_SetTxStatusHandler(msg_ptr, callback_fptr, inst_ptr); - Fifo_Tx(self->fifo_ptr, msg_ptr, false); -} - -/*! \brief Transmits a given message object to the INIC bypassing all other messages in the FIFO - * \param self The instance - * \param tel_ptr Reference to the message object - * \param callback_fptr Callback function which is invoked after message transmission has finished. - * Must be \c NULL to avoid that a callback function is invoked. In this case - * the message object is freed internally. Hence, the message object must - * not provide external payload. - * \param inst_ptr Reference to the instance which is invoked - * \note The provided callback function is responsible to free the message object by calling - * Trcv_TxReleaseMsg() or to reuse the message object by calling Trcv_TxReuseMsg() before - * passing it to one of the transmit functions again. - */ -void Trcv_TxSendMsgBypass(CTransceiver *self, Msg_MostTel_t *tel_ptr, Msg_TxStatusCb_t callback_fptr, void *inst_ptr) -{ - CMessage *msg_ptr; - - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL)); - msg_ptr = (CMessage*)(void*)tel_ptr; - - if (callback_fptr == NULL) - { - TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (inst_ptr == NULL)); - callback_fptr = &Trcv_OnTxStatusInternal; - inst_ptr = self; - } - - Msg_SetTxStatusHandler(msg_ptr, callback_fptr, inst_ptr); - Fifo_Tx(self->fifo_ptr, msg_ptr, true); -} - -/*! \brief Callback function which is invoked instead of an external callback - * as soon as channel transmission was finished in PMS. - * \param self The instance - * \param tel_ptr Reference to the message object - * \param status Transmission status - */ -static void Trcv_OnTxStatusInternal(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status) -{ - Trcv_TxReleaseMsg(tel_ptr); - MISC_UNUSED(self); - MISC_UNUSED(status); -} - -/*! \brief Internal callback function which is intended to be - * invoked by the port message channel on completed reception. - * \param self The instance - * \param tel_ptr Reference to the message object - */ -void Trcv_RxOnMsgComplete(void *self, CMessage *tel_ptr) -{ - CTransceiver *self_ = (CTransceiver*)self; - bool discard = false; - - TR_INFO((self_->ucs_user_ptr, "[TRCV]", "Trcv_RxOnMsgComplete(): FIFO: %u, MSG(src:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self_->own_id, tel_ptr->pb_msg.source_addr, tel_ptr->pb_msg.id.fblock_id, tel_ptr->pb_msg.id.instance_id, tel_ptr->pb_msg.id.function_id, tel_ptr->pb_msg.id.op_type)); - if (self_->rx_filter_fptr != NULL) - { - discard = self_->rx_filter_fptr(self_->rx_filter_inst, Msg_GetMostTel(tel_ptr)); - } - - if ((self_->rx_complete_fptr != NULL) && (discard == false)) - { - /* the assigned Rx function is responsible to release the message */ - self_->rx_complete_fptr(self_->rx_complete_inst, Msg_GetMostTel(tel_ptr)); - } - else - { - Fifo_RxReleaseMsg(self_->fifo_ptr, tel_ptr); - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_xrm.c b/ucs2-lib/src/ucs_xrm.c deleted file mode 100644 index d8cbbf6..0000000 --- a/ucs2-lib/src/ucs_xrm.c +++ /dev/null @@ -1,1174 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Extended Resource Manager. This file contains the implementation of - * the basic functions of the class CExtendedResourceManager. - * \cond UCS_INTERNAL_DOC - * \addtogroup G_UCS_XRM_INT - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_xrm.h" -#include "ucs_xrm_pv.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Service parameters */ -/*------------------------------------------------------------------------------------------------*/ -/*! Priority of the XRM service used by scheduler */ -const uint8_t XRM_SRV_PRIO = 250U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Event to trigger Extended Resource Manager service */ -const Srv_Event_t XRM_EVENT_PROCESS = 0x01U; -/*! \brief Event to trigger error handling */ -const Srv_Event_t XRM_EVENT_ERROR = 0x02U; -/*! \brief Event to trigger request list of invalid resource handles */ -const Srv_Event_t XRM_EVENT_REQ_INV_RES_LST = 0x04U; -/*! \brief Event to trigger destruction of invalid resources */ -const Srv_Event_t XRM_EVENT_DESTROY_INV_RES = 0x08U; -/*! \brief Event to resume the destruction of resources */ -const Srv_Event_t XRM_EVENT_RESUME_JOB_DESTRUCT = 0x10U; -/*! \brief Event to reset INIC's Resource Monitor */ -const Srv_Event_t XRM_EVENT_RESET_RES_MONITOR = 0x20U; -/*! \brief Event to trigger notification for automatically destroyed resources */ -const Srv_Event_t XRM_EVENT_NOTIFY_AUTO_DEST_RES = 0x40U; -/*! \brief Event to trigger notification for destroyed resources */ -const Srv_Event_t XRM_EVENT_NOTIFY_DESTROYED_JOB = 0x80U; -/*! \brief Event to trigger notification for automatically destroyed resources on remote devices */ -const Srv_Event_t XRM_EVENT_NOTIFY_AUTO_DEST_RESR = 0x100U; -/*! \brief Event to trigger configuration of a stream port */ -const Srv_Event_t XRM_EVENT_STREAMPORT_CONFIG_SET = 0x200U; -/*! \brief Event to read configuration of a stream port */ -const Srv_Event_t XRM_EVENT_STREAMPORT_CONFIG_GET = 0x400U; - -/*------------------------------------------------------------------------------------------------*/ -/* Internal Constants */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Invalid resource handle */ -const uint16_t XRM_INVALID_RESOURCE_HANDLE = 0xFFFFU; -/*! \brief Invalid MOST connection label */ -const uint16_t XRM_INVALID_CONNECTION_LABEL = 0xFFFFU; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ -/*! \brief Default value used for INIC sender handles */ -const uint16_t XRM_DEFAULT_SENDER_HANDLE = 0x0001U; -/*! \brief Invalid device node address */ -const uint16_t XRM_INVALID_NODE_ADDRESS = 0x0000U; -/*! \brief Mask for network availability info */ -const uint16_t XRM_MASK_NETWORK_AVAILABILITY = 0x0002U; -/*! \brief Mask for node address update info */ -const uint16_t XRM_MASK_NETWORK_NODE_ADDRESS = 0x0010U; - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CExtendedResourceManager */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the Extended Resource Manager class. - * \param self Instance pointer - * \param data_ptr Data pointer (receive reference to MNS instance) - */ -void Xrm_Ctor(CExtendedResourceManager *self, Xrm_InitData_t *data_ptr) -{ - MISC_MEM_SET(self, 0, sizeof(CExtendedResourceManager)); - - /* Retrieve the initialization data */ - self->net_ptr = data_ptr->net_ptr; - self->base_ptr = data_ptr->base_ptr; - self->rsm_ptr = data_ptr->rsm_ptr; - self->inic_ptr = data_ptr->inic_ptr; - self->xrmp_ptr = data_ptr->xrmp_ptr; - self->res_debugging_fptr = data_ptr->res_debugging_fptr; - - /* Set the flag that indicates the run mode of the instance */ - self->IsInRemoteControlMode = (UCS_ADDR_LOCAL_DEV != Inic_GetTargetAddress(self->inic_ptr)) ? true:false; - - /* Initialize observers */ - Obs_Ctor(&self->obs.tx_msg_obj_obs, self, &Xrm_MsgObjAvailCb); - Obs_Ctor(&self->obs.resource_monitor_obs, self, &Xrm_ResourceMonitorCb); - Sobs_Ctor(&self->obs.std_result_obs, self, &Xrm_StdResultCb); - Sobs_Ctor(&self->obs.resource_invalid_list_obs, self, &Xrm_RequestResourceListResultCb); - Sobs_Ctor(&self->obs.resource_destroy_obs, self, &Xrm_DestroyResourcesResultCb); - Sobs_Ctor(&self->obs.stream_port_config_obs, self, &Xrm_Stream_PortConfigResult); - Sobs_Ctor(&self->obs.most_port_enable_obs, self, &Xrm_Most_PortEnableResult); - Sobs_Ctor(&self->obs.most_port_en_full_str_obs, self, &Xrm_Most_PortEnFullStrResult); - Obs_Ctor(&self->obs.rsm_sync_lost_obs, self, &Xrm_RmtDevSyncLostCb); - - /* Add observer to resource monitor subject */ - Inic_AddObsrvResMonitor(self->inic_ptr, &self->obs.resource_monitor_obs); - /* Initialize callback pointer for unmute callback */ - self->obs.check_unmute_fptr = data_ptr->check_unmute_fptr; - - /* Add observer to the MNS termination event */ - Mobs_Ctor(&self->obs.internal_error_obs, self, EH_M_TERMINATION_EVENTS, &Xrm_UninitializeService); - Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->obs.internal_error_obs); - /* Add observer to the MNS network event */ - Mobs_Ctor(&self->obs.nw_status_obs, self, (XRM_MASK_NETWORK_AVAILABILITY | XRM_MASK_NETWORK_NODE_ADDRESS), &Xrm_MnsNwStatusInfosCb); - Net_AddObserverNetworkStatus(self->net_ptr, &self->obs.nw_status_obs); - /* Add observer to the MNS RSM event */ - Rsm_AddObserver(self->rsm_ptr, &self->obs.rsm_sync_lost_obs); - - /* Initialize the Jobs list queue */ - Dl_Ctor(&self->job_list, self->base_ptr->ucs_user_ptr); - - /* Initialize XRM service */ - Srv_Ctor(&self->xrm_srv, XRM_SRV_PRIO, self, &Xrm_Service); - /* Add XRM service to scheduler */ - (void)Scd_AddService(&self->base_ptr->scd, &self->xrm_srv); -} - -/*! \brief Service function of the Extended Resource Manager. - * \param self Instance pointer - */ -void Xrm_Service(void *self) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Srv_Event_t event_mask; - Srv_GetEvent(&self_->xrm_srv, &event_mask); - - /* Handle event to process a XRM job */ - if((event_mask & XRM_EVENT_PROCESS) == XRM_EVENT_PROCESS) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_PROCESS); - Xrm_ProcessJob(self_); - } - /* Handle event to request the list of invalid resource handles */ - if((event_mask & XRM_EVENT_REQ_INV_RES_LST) == XRM_EVENT_REQ_INV_RES_LST) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_REQ_INV_RES_LST); - Xrm_RequestResourceList(self_); - } - /* Handle event to destroy invalid INIC resources */ - if((event_mask & XRM_EVENT_DESTROY_INV_RES) == XRM_EVENT_DESTROY_INV_RES) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_DESTROY_INV_RES); - Xrm_DestroyResources(self_, &Xrm_DestroyResourcesResultCb); - } - /* Handle event to resume the destruction of all INIC resources of a job */ - if((event_mask & XRM_EVENT_RESUME_JOB_DESTRUCT) == XRM_EVENT_RESUME_JOB_DESTRUCT) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_RESUME_JOB_DESTRUCT); - Xrm_ResumeJobDestruction(self_); - } - /* Handle event to resume the destruction of all INIC resources of a job */ - if((event_mask & XRM_EVENT_RESET_RES_MONITOR) == XRM_EVENT_RESET_RES_MONITOR) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_RESET_RES_MONITOR); - Xrm_ResetResourceMonitor(self_); - } - /* Handle error event */ - if((event_mask & XRM_EVENT_ERROR) == XRM_EVENT_ERROR) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - Xrm_HandleError(self_); - } - /* Handle event to notify application of automatically destroyed resources */ - if((event_mask & XRM_EVENT_NOTIFY_AUTO_DEST_RES) == XRM_EVENT_NOTIFY_AUTO_DEST_RES) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RES); - Xrm_ReportAutoDestructionResult(self_); - } - /* Handle event to report result of resource destruction of a specific XRM job */ - if((event_mask & XRM_EVENT_NOTIFY_DESTROYED_JOB) == XRM_EVENT_NOTIFY_DESTROYED_JOB) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_DESTROYED_JOB); - Xrm_ReportJobDestructionResult(self_); - } - /* Handle event to notify application that resources on remote devices have been automatically destroyed */ - if ((event_mask & XRM_EVENT_NOTIFY_AUTO_DEST_RESR) == XRM_EVENT_NOTIFY_AUTO_DEST_RESR) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR); - Xrm_ReleaseResrcHandles(self_); - } - /* Handle event to set streaming port configuration */ - if ((event_mask & XRM_EVENT_STREAMPORT_CONFIG_SET) == XRM_EVENT_STREAMPORT_CONFIG_SET) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_STREAMPORT_CONFIG_SET); - (void)Xrm_SetStreamPortConfiguration(self_); - } - /* Handle event to get streaming port configuration */ - if ((event_mask & XRM_EVENT_STREAMPORT_CONFIG_GET) == XRM_EVENT_STREAMPORT_CONFIG_GET) - { - Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_STREAMPORT_CONFIG_GET); - (void)Xrm_GetStreamPortConfiguration(self_); - } -} - -/*! \brief Checks if the API is locked and the MNS are initialized. - * \param self Instance pointer - * \return \c true if the API is not locked and the MNS are initialized, otherwise \c false. - */ -bool Xrm_IsApiFree(CExtendedResourceManager *self) -{ - return (self->lock_api == false); -} - -/*! \brief Locks/Unlocks the XRM API. - * \param self Instance pointer - * \param status Locking status. \c true = Lock, \c false = Unlock - */ -void Xrm_ApiLocking(CExtendedResourceManager *self, bool status) -{ - self->lock_api = status; -} - -/*! \brief Add observer to be notified if ICM TX message object is available. Store pending events. - * \param self Instance pointer - * \param event_mask Event to be queued - */ -void Xrm_WaitForTxMsgObj(CExtendedResourceManager *self, Srv_Event_t event_mask) -{ - Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->obs.tx_msg_obj_obs); - self->queued_event_mask |= event_mask; -} - -/*! \brief Checks whether the given resource object list is part of the given Job - * \param job_ptr Reference to a job list - * \param ud_ptr Reference to the user data. Not used ! - * \return \c true if it's part of my job list, otherwise \c false. - */ -bool Xrm_SetNtfForThisJob(void * job_ptr, void * ud_ptr) -{ - Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr; - MISC_UNUSED(ud_ptr); - - if(job_ptr_->valid != false) - { - job_ptr_->notify = true; - } - - return false; -} - -/*! \brief Handle internal errors and un-initialize XRM service. - * \param self Instance pointer - * \param error_code_ptr Reference to internal error code - */ -void Xrm_UninitializeService(void *self, void *error_code_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - MISC_UNUSED(error_code_ptr); - - Xrm_ApiLocking(self_, true); - - MISC_MEM_SET(&self_->report_result, 0x00, sizeof(Ucs_Xrm_Result_t)); - self_->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED; - - (void)Dl_Foreach(&self_->job_list, &Xrm_SetNtfForThisJob, NULL); - - /* Notify destruction of current connections */ - Xrm_NotifyInvalidJobs(self_); - /* Remove XRM service from schedulers list */ - (void)Scd_RemoveService(&self_->base_ptr->scd, &self_->xrm_srv); - /* Remove error/event observers */ - Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->obs.internal_error_obs); - /* Remove rsm observers */ - Rsm_DelObserver(self_->rsm_ptr, &self_->obs.rsm_sync_lost_obs); -} - - -/*! \brief Handle the network status information mask "Availability" and "NodeAddress". - * \param self Instance pointer - * \param result_ptr Reference to the results - */ -void Xrm_MnsNwStatusInfosCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)result_ptr; - - if ((XRM_MASK_NETWORK_AVAILABILITY & result_ptr_->change_mask) == XRM_MASK_NETWORK_AVAILABILITY) - { - if ((result_ptr_->availability == UCS_NW_NOT_AVAILABLE) && - (self_->IsInRemoteControlMode)) - { - /* Release all resources */ - Xrm_ReleaseResrcHandles(self_); - } - } -} - -/*! \brief Whenever this function is called, a message object (ICM or MCM) is available. - * \param self Instance pointer - * \param result_ptr Not used! - */ -void Xrm_MsgObjAvailCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - MISC_UNUSED(result_ptr); - Srv_SetEvent(&self_->xrm_srv, self_->queued_event_mask); - self_->queued_event_mask = 0U; - Inic_DelObsrvOnTxMsgObjAvail(self_->inic_ptr, &self_->obs.tx_msg_obj_obs); -} - -/*! \brief Whenever this function is called, all remote devices have lost the synchronization. - * \param self instance pointer - * \param result_ptr Not Used ! - */ -void Xrm_RmtDevSyncLostCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - MISC_UNUSED(result_ptr); - - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR); -} - -/*! \brief Processes the XRM job that is specified by the given resource object list. - * \param self Instance pointer - * \param resource_object_list[] Reference to array of references to INIC resource objects - * \param most_network_connection_label MOST network connection label - * \param user_arg User argument - * \param report_fptr Report function pointer - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_NOT_AVAILABLE | Associated job not found - * UCS_RET_ERR_PARAM | Null pointer detected - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Xrm_Process(CExtendedResourceManager *self, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[], - uint16_t most_network_connection_label, - void * user_arg, - Ucs_Xrm_ReportCb_t report_fptr) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - if (self != NULL) - { - if(Xrm_IsApiFree(self) != false) - { - if((resource_object_list != NULL) && (report_fptr != NULL)) - { - Xrm_ApiLocking(self, true); - self->current_job_ptr = Xrm_GetJob(self, resource_object_list); - if(self->current_job_ptr != NULL) - { - bool job_is_mine = Dl_IsNodeInList(&self->job_list, &self->current_job_ptr->node); - if (job_is_mine) - { - if(self->current_job_ptr->valid == false) - { - self->current_job_ptr->user_arg = user_arg; - self->current_job_ptr->valid = true; - self->current_job_ptr->notify = false; - self->current_job_ptr->report_fptr = report_fptr; - self->current_job_ptr->most_network_connection_label = most_network_connection_label; - self->current_job_ptr->resource_object_list_ptr = resource_object_list; - self->current_obj_pptr = &self->current_job_ptr->resource_object_list_ptr[0]; - Xrm_ProcessJob(self); - } - else - { - ret_val = UCS_RET_ERR_ALREADY_SET; - Xrm_ApiLocking(self, false); - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - Xrm_ApiLocking(self, false); - } - } - else - { - Xrm_ApiLocking(self, false); - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - } - } - else - { - ret_val = UCS_RET_ERR_API_LOCKED; - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - } - - return ret_val; -} - -/*! \brief Destroys all resources that are specified by the given resource object list. - * \details This function triggers the destruction of all resources which are used by the given - * job. A resource will be destroyed only if it is not used by other valid resources. - * \param self Instance pointer - * \param resource_object_list[] Reference to array of references to INIC resource objects - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------- | ------------------------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_ALREADY_SET | Connection is already destroyed - * UCS_RET_ERR_NOT_AVAILABLE | Associated job not found - * UCS_RET_ERR_PARAM | Null pointer detected - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Xrm_Destroy(CExtendedResourceManager *self, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[]) -{ - Ucs_Return_t ret_val = UCS_RET_SUCCESS; - - if (self != NULL) - { - if(Xrm_IsApiFree(self) != false) - { - if(resource_object_list != NULL) - { - Xrm_ApiLocking(self, true); - self->current_job_ptr = Xrm_GetJob(self, resource_object_list); - if((self->current_job_ptr != NULL) && - (self->current_job_ptr->resource_object_list_ptr != NULL)) - { - Xrm_PreJobDestrResult_t result; - - result = Xrm_PrepareJobDestruction(self); - if(result == XRM_PRE_JOB_DEST_TASKS_EXIST) - { - Xrm_DestroyResources(self, &Xrm_DestroyJobResourcesResultCb); - } - else if(result == XRM_PRE_JOB_DEST_DONE) - { - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_NOTIFY_DESTROYED_JOB); - } - else if (result == XRM_PRE_JOB_DEST_BUSY) - { - Xrm_ApiLocking(self, false); - ret_val = UCS_RET_ERR_API_LOCKED; - } - else - { - Xrm_ApiLocking(self, false); - ret_val = UCS_RET_ERR_ALREADY_SET; - } - } - else - { - Xrm_ApiLocking(self, false); - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - } - } - else - { - ret_val = UCS_RET_ERR_API_LOCKED; - } - } - else - { - /* This means that there is no instance associated to this job, - * what in turn means that the job is not available. - */ - ret_val = UCS_RET_ERR_NOT_AVAILABLE; - } - - return ret_val; -} - -/*! \brief Prepares the destruction of INIC resources of the current job. - * \param self Instance pointer - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------------- | ------------------------------------ - * XRM_PRE_JOB_DEST_TASKS_EXIST | There are resources to destroy - * XRM_PRE_JOB_DEST_NO_TASKS_EXIST | All resources already destroyed - * XRM_PRE_JOB_DEST_DONE | Only shared resources affected. Invoke result callback immediately - * XRM_PRE_JOB_DEST_BUSY | Preparation of JobDestruction is currently not possible. Other resources are currently being destroyed - */ -Xrm_PreJobDestrResult_t Xrm_PrepareJobDestruction(CExtendedResourceManager *self) -{ - Xrm_PreJobDestrResult_t ret_val = XRM_PRE_JOB_DEST_BUSY; - if (self->inv_resource_handle_list_size == 0U) - { - ret_val = Xrm_UnsafePrepareJobDestruction(self); - } - return ret_val; -} - -/*! \brief Prepares precariously the destruction of INIC resources of the current job (This was legacy code and is unsafe). - * \param self Instance pointer - * \return Possible return values are shown in the table below. - * Value | Description - * ------------------------------- | ------------------------------------ - * XRM_PRE_JOB_DEST_TASKS_EXIST | There are resources to destroy - * XRM_PRE_JOB_DEST_NO_TASKS_EXIST | All resources already destroyed - * XRM_PRE_JOB_DEST_DONE | Only shared resources affected. Invoke result callback immediately - */ -Xrm_PreJobDestrResult_t Xrm_UnsafePrepareJobDestruction(CExtendedResourceManager *self) -{ - uint8_t i; - uint16_t resource_handle; - Xrm_PreJobDestrResult_t ret_val = XRM_PRE_JOB_DEST_NO_TASKS_EXIST; - self->inv_resource_handle_index = 0U; - self->inv_resource_handle_list_size = 0U; - for(i=Xrm_CountResourceObjects(self, self->current_job_ptr); (i>0U) && (self->inv_resource_handle_list_size < XRM_NUM_RES_HDL_PER_ICM); i--) - { - uint8_t count = Xrm_CountResourceHandleEntries(self, self->current_job_ptr->resource_object_list_ptr[i - 1U]); - if(count == 1U) - { - resource_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, self->current_job_ptr->resource_object_list_ptr[i - 1U], NULL); - if(resource_handle != XRM_INVALID_RESOURCE_HANDLE) - { - self->inv_resource_handle_list[self->inv_resource_handle_list_size] = resource_handle; - self->inv_resource_handle_list_size++; - ret_val = XRM_PRE_JOB_DEST_TASKS_EXIST; - } - } - else if(count > 0U) - { - Xrm_ReleaseResourceHandle(self, self->current_job_ptr, self->current_job_ptr->resource_object_list_ptr[i - 1U]); - ret_val = (ret_val == XRM_PRE_JOB_DEST_NO_TASKS_EXIST) ? XRM_PRE_JOB_DEST_DONE : ret_val; - } - } - return ret_val; -} - - -/*! \brief Resumes the destruction of all resources of the current job. - * \param self Instance pointer - */ -void Xrm_ResumeJobDestruction(CExtendedResourceManager *self) -{ - if(Xrm_UnsafePrepareJobDestruction(self) == XRM_PRE_JOB_DEST_TASKS_EXIST) - { - Xrm_DestroyResources(self, &Xrm_DestroyJobResourcesResultCb); - } - else - { - MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t)); - self->report_result.code = UCS_XRM_RES_SUCCESS_DESTROY; - Xrm_NotifyInvalidJobs(self); - Xrm_ApiLocking(self, false); - } -} - -/*! \brief Returns the number of resource objects for the job that is identified by the given job - * reference. - * \param self Instance pointer - * \param job_ptr Reference to job - * \return Number of INIC resource objects of the desired job - */ -uint8_t Xrm_CountResourceObjects(CExtendedResourceManager *self, Xrm_Job_t *job_ptr) -{ - uint8_t num_resource_objects = 0U; - MISC_UNUSED(self); - while(job_ptr->resource_object_list_ptr[num_resource_objects] != NULL) - { - num_resource_objects++; - } - - return num_resource_objects; -} - -/*! \brief Returns the reference of the job that is identified by the given resource object list. - * \param self Instance pointer - * \param resource_object_list[] Reference to array of references to INIC resource objects - * \return Reference to the desired job if the job was found, otherwise NULL. - */ -Xrm_Job_t * Xrm_GetJob(CExtendedResourceManager *self, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[]) -{ - Xrm_Job_t *ret_ptr = NULL; - - ret_ptr = Xrmp_GetJob(self->xrmp_ptr, resource_object_list); - if (ret_ptr != NULL) - { - if ((!Dl_IsNodeInList(&self->job_list, &ret_ptr->node)) && - (!Dln_IsNodePartOfAList(&ret_ptr->node))) - { - Dln_SetData(&ret_ptr->node, ret_ptr); - Dl_InsertTail(&self->job_list, &ret_ptr->node); - } - } - - return ret_ptr; -} - -/*! \brief Checks whether the given resource object list is part of the given Job - * \param job_ptr Reference to a job list - * \param resrc_obj_ptr Reference to array of references to INIC resource objects - * \return \c true if it's part of my job list, otherwise \c false. - */ -bool Xrm_IsPartOfJobList (void * job_ptr, void * resrc_obj_ptr) -{ - Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr; - bool ret_val = false; - - if(job_ptr_->resource_object_list_ptr == (UCS_XRM_CONST Ucs_Xrm_ResObject_t **)resrc_obj_ptr) - { - ret_val = true; - } - - return ret_val; -} - -/*! \brief Checks whether the given resource object list is part of my Job list - * \param self Instance pointer - * \param resource_object_list[] Reference to array of references to INIC resource objects - * \return \c true if it's part of my job list, otherwise \c false. - */ -bool Xrm_IsInMyJobList(CExtendedResourceManager *self, UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[]) -{ - return (NULL != Dl_Foreach(&self->job_list, &Xrm_IsPartOfJobList, (void *)resource_object_list)); -} - -/*! \brief Returns the table index of the given resource object. - * \param self Instance pointer - * \param job_ptr Reference to job - * \param obj_pptr Reference to array of references to INIC resource objects - * \return Table index of the given resource object. If entry is not found 0xFF is returned. - */ -uint8_t Xrm_GetResourceObjectIndex(CExtendedResourceManager *self, - Xrm_Job_t *job_ptr, - UCS_XRM_CONST Ucs_Xrm_ResObject_t **obj_pptr) -{ - return Xrmp_GetResourceHandleIdx(self->xrmp_ptr, job_ptr, obj_pptr); -} - -/*! \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. - */ -bool Xrm_IsCurrDeviceAlreadyAttached(CExtendedResourceManager *self) -{ - bool ret_val = true; - - if (Rsm_GetDevState(self->rsm_ptr) == RSM_DEV_UNSYNCED) - { - ret_val = false; - } - - return ret_val; -} - -/*! \brief Check if the current device is already attached respectively sync'ed. - * \param self XRM Instance pointer - * \param job_ptr Reference to the XRM job to be looked for - * \return \c true if the given job is part of my jobs_list, otherwise \c false. - */ -bool Xrm_IsInMyJobsList (void * self, void * job_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr; - bool ret_val = false; - - if ((self_ != NULL) && (job_ptr_ != NULL) && - (Dl_IsNodeInList(&self_->job_list, &job_ptr_->node))) - { - ret_val = true; - } - - return ret_val; -} - -/*! \brief Search for the next resource object to process. - * \param self Instance pointer - * \return \c true if no error occurred, otherwise \c false. - */ -bool Xrm_SearchNextResourceObject(CExtendedResourceManager *self) -{ - uint16_t tmp_resource_handle; - bool ret_val = true; - - while(*self->current_obj_pptr != NULL) - { - if(Xrm_IsDefaultCreatedPort(self, *self->current_obj_pptr) != false) - { - self->current_obj_pptr++; - } - else - { - tmp_resource_handle = Xrm_GetResourceHandle(self, NULL, *self->current_obj_pptr, &Xrm_IsInMyJobsList); - if(tmp_resource_handle == XRM_INVALID_RESOURCE_HANDLE) - { - break; - } - else - { - if(Xrm_GetResourceHandle(self, self->current_job_ptr, *self->current_obj_pptr, NULL) == XRM_INVALID_RESOURCE_HANDLE) - { - if(Xrm_StoreResourceHandle(self, tmp_resource_handle, self->current_job_ptr, *self->current_obj_pptr) == false) - { - self->report_result.code = UCS_XRM_RES_ERR_CONFIG; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Misconfiguration. Resource handle list is too small.", 0U)); - ret_val = false; - } - } - self->current_obj_pptr++; - } - } - } - - return ret_val; -} - -/*! \brief Process the next INIC resource object in the resource object list of the current job. - * \param self Instance pointer - */ -void Xrm_ProcessJob(CExtendedResourceManager *self) -{ - if(Xrm_SearchNextResourceObject(self) != false) - { - if(*self->current_obj_pptr != NULL) - { - if (Xrm_IsCurrDeviceAlreadyAttached(self) == false) - { - (void)Xrm_RemoteDeviceAttach(self, XRM_EVENT_PROCESS); - } - else - { - switch(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr)) - { - case UCS_XRM_RC_TYPE_MOST_SOCKET: - Xrm_CreateMostSocket(self); - break; - case UCS_XRM_RC_TYPE_MLB_PORT: - Xrm_CreateMlbPort(self); - break; - case UCS_XRM_RC_TYPE_MLB_SOCKET: - Xrm_CreateMlbSocket(self); - break; - case UCS_XRM_RC_TYPE_USB_PORT: - Xrm_CreateUsbPort(self); - break; - case UCS_XRM_RC_TYPE_USB_SOCKET: - Xrm_CreateUsbSocket(self); - break; - case UCS_XRM_RC_TYPE_RMCK_PORT: - Xrm_CreateRmckPort(self); - break; - case UCS_XRM_RC_TYPE_STRM_PORT: - Xrm_CreateStreamPort(self); - break; - case UCS_XRM_RC_TYPE_STRM_SOCKET: - Xrm_CreateStreamSocket(self); - break; - case UCS_XRM_RC_TYPE_SYNC_CON: - Xrm_CreateSyncCon(self); - break; - case UCS_XRM_RC_TYPE_DFIPHASE_CON: - Xrm_CreateDfiPhaseCon(self); - break; - case UCS_XRM_RC_TYPE_COMBINER: - Xrm_CreateCombiner(self); - break; - case UCS_XRM_RC_TYPE_SPLITTER: - Xrm_CreateSplitter(self); - break; - case UCS_XRM_RC_TYPE_AVP_CON: - Xrm_CreateAvpCon(self); - break; - case UCS_XRM_RC_TYPE_QOS_CON: - Xrm_CreateQoSCon(self); - break; - default: - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Unexpected Resource Type: 0x%02X", 1U, *(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr))); - self->report_result.code = UCS_XRM_RES_ERR_CONFIG; - Xrm_HandleError(self); - break; - } - } - } - else - { - Xrm_FinishJob(self); - } - } -} - -/*! \brief Checks if the given resource object is from type "Default Created Port". - * \param self Instance pointer - * \param resource_object_ptr Reference to the resource object - * \return Returns \c true if resource object is from type "Default Created Port", otherwise \c false. - */ -bool Xrm_IsDefaultCreatedPort(CExtendedResourceManager *self, UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr) -{ - MISC_UNUSED(self); - return (*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resource_object_ptr) == UCS_XRM_RC_TYPE_DC_PORT); -} - -/*! \brief Stores the given resource handle in the resource handle list. - * \param self Instance pointer - * \param resource_handle Resource handle to save - * \param job_ptr Reference to job - * \param resource_object_ptr Reference to resource object - * \return \c true if free slot in handle list was found, otherwise \c false - */ -bool Xrm_StoreResourceHandle(CExtendedResourceManager *self, - uint16_t resource_handle, - Xrm_Job_t *job_ptr, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr) -{ - return Xrmp_StoreResourceHandle(self->xrmp_ptr, resource_handle, job_ptr, resource_object_ptr); -} - -/*! \brief Retrieves the resource handle identified by the given job reference and the given - * resource object reference. - * \param self Instance pointer - * \param job_ptr Reference to the job. Use NULL as wildcard. - * \param resource_object_ptr Reference to the resource object - * \param func_ptr Reference to a function that checks if found jobs by XRMP belongs to our own job list - * \return Resource handle if handle was found, otherwise XRM_INVALID_RESOURCE_HANDLE. - */ -uint16_t Xrm_GetResourceHandle(CExtendedResourceManager *self, - Xrm_Job_t *job_ptr, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr, Xrmp_CheckJobListFunc_t func_ptr) -{ - return Xrmp_GetResourceHandle(self->xrmp_ptr, job_ptr, resource_object_ptr, func_ptr, self); -} - -/*! \brief Checks for the resource handle in the given resource handle list and counts It if found. - * \param resrc_ptr Reference to the resource handle list to be looked for. - * \param job_ptr Reference to the job list to be looked for. - * \param param_ptr Reference to the user parameter. - * \param user_arg Reference to the user argument. - * \return \c false to continue the for-each-loop of the resources list queue. - */ -bool Xrm_IncrResHandleEntryCnt (void *resrc_ptr, void *job_ptr, void *param_ptr, void * user_arg) -{ - Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr; - Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr; - Xrm_CntEntriesResHandle_t * param_ptr_ = (Xrm_CntEntriesResHandle_t *)param_ptr; - MISC_UNUSED(user_arg); - - if((resrc_ptr_->resource_handle != XRM_INVALID_RESOURCE_HANDLE) && - (resrc_ptr_->job_ptr == job_ptr_) && - (resrc_ptr_->resource_object_ptr == param_ptr_->resource_object_ptr)) - { - (*param_ptr_->cnt_res)++; - } - - return false; -} - -/*! \brief Finds the resource handle to be counted in my job list and pass it to the record callback function . - * \param job_ptr Reference to the job to be looked for. - * \param param_ptr Reference to the user parameter. - * \return \c false to continue the for-each-loop of the job_list queue - */ -bool Xrm_CntResHandleEntries(void * job_ptr, void * param_ptr) -{ - Xrm_CntEntriesResHandle_t * param_ptr_ = (Xrm_CntEntriesResHandle_t *)param_ptr; - - Xrmp_Foreach(param_ptr_->xrm_inst->xrmp_ptr, &Xrm_IncrResHandleEntryCnt, job_ptr, param_ptr_, NULL); - - return false; -} - -/*! \brief Retrieves the number of list entries that uses the given resource handle. - * \param self Instance pointer - * \param resource_object_ptr Reference to the current resource object - * \return Number of list entries - */ -uint8_t Xrm_CountResourceHandleEntries(CExtendedResourceManager *self, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr) -{ - uint8_t ret_val = 0U; - Xrm_CntEntriesResHandle_t cnt_entry_param; - cnt_entry_param.xrm_inst = self; - cnt_entry_param.cnt_res = &ret_val; - cnt_entry_param.resource_object_ptr = resource_object_ptr; - - (void)Dl_Foreach(&self->job_list, &Xrm_CntResHandleEntries, &cnt_entry_param); - - return ret_val; -} - -/*! \brief Releases the given resource handle. - * \param resrc_ptr Reference to the resource handle list to be looked for. - * \param job_ptr Reference to the job list to be looked for. - * \param resrc_obj_pptr Reference to the resource object to be looked for. - * \param user_arg Reference to the user argument - * \return \c true to stop the foreach loop when the resource handle has been found, otherwise \c false - */ -bool Xrm_ReleaseResrcHandle(void *resrc_ptr, void *job_ptr, void *resrc_obj_pptr, void * user_arg) -{ - bool ret_val = false; - Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr; - Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr; - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resrc_obj_ptr_ = *(UCS_XRM_CONST Ucs_Xrm_ResObject_t **)resrc_obj_pptr; - MISC_UNUSED(user_arg); - - if((resrc_ptr_->job_ptr == job_ptr_) && - (resrc_ptr_->resource_object_ptr == resrc_obj_ptr_)) - { - resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE; - resrc_ptr_->job_ptr = NULL; - resrc_ptr_->resource_object_ptr = NULL; - ret_val = true; - } - - return ret_val; -} - -/*! \brief Releases the given resource handle. Frees the corresponding table row. - * \param self Instance pointer - * \param job_ptr Reference to the job - * \param resource_object_ptr Reference to the resource object - */ -void Xrm_ReleaseResourceHandle(CExtendedResourceManager *self, - Xrm_Job_t *job_ptr, - UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr) -{ - void * resource_object_pptr = (void *)&resource_object_ptr; - Xrmp_Foreach(self->xrmp_ptr, &Xrm_ReleaseResrcHandle, job_ptr, resource_object_pptr, NULL); -} - -/*! \brief Releases the given resource and sets the notification to \c true. - * \param resrc_ptr Reference to the resource handle list to be looked for. - * \param resrc_handle Reference to the resource handle to be found. - * \param job_ptr Reference to the job to be looked for. - * \param user_arg Reference to a user argument. - * \return \c false to continue the for-each-loop of the resources list table - */ -bool Xrm_FreeResrcHandleAndNtf(void *resrc_ptr, void *resrc_handle, void *job_ptr, void * user_arg) -{ - Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr; - uint16_t * resrc_handle_ = (uint16_t *)resrc_handle; - Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr; - CExtendedResourceManager *self = (CExtendedResourceManager *) user_arg; - - if((resrc_ptr_->resource_handle == *resrc_handle_) && - (*resrc_handle_ != XRM_INVALID_RESOURCE_HANDLE) && - ((resrc_ptr_->job_ptr == job_ptr_) || - (Dl_IsNodeInList(&self->job_list, &resrc_ptr_->job_ptr->node)))) - { - resrc_ptr_->job_ptr->notify = true; - resrc_ptr_->job_ptr->valid = false; - resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE; - resrc_ptr_->job_ptr = NULL; - - if (self->res_debugging_fptr != NULL) - { - self->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resrc_ptr_->resource_object_ptr), - resrc_ptr_->resource_object_ptr, UCS_XRM_INFOS_DESTROYED, self->current_job_ptr->user_arg, self->base_ptr->ucs_user_ptr); - } - - resrc_ptr_->resource_object_ptr = NULL; - } - - return false; -} - -/*! \brief Releases all given resource handles. Frees the corresponding table rows. Marks the - * corresponding job(s) as invalid and sets the notification flag. - * \param self Instance pointer - * \param job_ptr Reference to the job. Use NULL as wildcard. - * \param resource_handle_list Resource handle list - * \param resource_handle_list_size Size of list resource_handle_list[] - * \param failed_resource_handle This parameter can be used to specify where the release - * process has to be stopped. All resource handles prior to - * the failed handle are released. If this feature is not - * used \c failed_resource_handle must be set to - * \ref XRM_INVALID_RESOURCE_HANDLE. - * \return the index of the resource where the release process has stopped. - */ -uint8_t Xrm_ReleaseResourceHandles(CExtendedResourceManager *self, - Xrm_Job_t *job_ptr, - uint16_t resource_handle_list[], - uint8_t resource_handle_list_size, - uint16_t failed_resource_handle) -{ - uint8_t i; - - for(i=0U; i<resource_handle_list_size; i++) - { - if((failed_resource_handle != XRM_INVALID_RESOURCE_HANDLE) && - (resource_handle_list[i] == failed_resource_handle)) - { - break; - } - - Xrmp_Foreach(self->xrmp_ptr, &Xrm_FreeResrcHandleAndNtf, &resource_handle_list[i], job_ptr, self); - } - - return i; -} - -/*! \brief Releases all resource handles created on remote devices. Frees the corresponding table rows. Marks the - * corresponding job(s) as invalid and sets the notification flag. - * \param self Instance pointer - */ -void Xrm_ReleaseResrcHandles(CExtendedResourceManager *self) -{ - if(Xrm_IsApiFree(self) != false) - { - Xrm_ApiLocking(self, true); - - Xrm_MarkResrcAndJobsAsInvalid(self); - Xrm_NotifyInvalidJobs(self); - Xrm_ApiLocking(self, false); - } - else - { - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR); - } -} - -/*! \brief Handles and reports Extended Resource Manager errors. - * \param self Instance pointer - */ -void Xrm_HandleError(CExtendedResourceManager *self) -{ - self->current_job_ptr->valid = false; - self->current_job_ptr->notify = false; - self->current_job_ptr->report_fptr(Inic_GetTargetAddress(self->inic_ptr), XRM_INVALID_CONNECTION_LABEL, self->report_result, self->current_job_ptr->user_arg); - Xrm_ApiLocking(self, false); -} - -/*! \brief Reports result of automatically destroyed resources - * \param self Instance pointer - */ -void Xrm_ReportAutoDestructionResult(CExtendedResourceManager *self) -{ - MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t)); - self->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED; - Xrm_NotifyInvalidJobs(self); - Xrm_ApiLocking(self, false); -} - -/*! \brief Reports result of resource destruction for a specific XRM job - * \param self Instance pointer - */ -void Xrm_ReportJobDestructionResult(CExtendedResourceManager *self) -{ - MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t)); - self->report_result.code = UCS_XRM_RES_SUCCESS_DESTROY; - self->current_job_ptr->notify = true; - Xrm_NotifyInvalidJobs(self); - Xrm_ApiLocking(self, false); -} - -/*! \brief Reports the conclusion of Extended Resource Manager jobs. - * \param self Instance pointer - */ -void Xrm_FinishJob(CExtendedResourceManager *self) -{ - MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t)); - self->report_result.code = UCS_XRM_RES_SUCCESS_BUILD; - self->current_job_ptr->report_fptr(Inic_GetTargetAddress(self->inic_ptr), self->current_job_ptr->connection_label, self->report_result, self->current_job_ptr->user_arg); - Xrm_ApiLocking(self, false); -} - -/*! \brief Marks the given resource as invalid and sets the notification. - * \param resrc_ptr Reference to the resource handle list to be looked for. - * \param xrm_inst Reference to the XRM instance to be looked for. - * \param ud_ptr2 Optional reference to the user data 2. Not used ! - * \param ud_ptr3 Optional reference to the user data 3. Not used ! - * \return \c false to continue the for-each-loop of the job_list queue - */ -bool Xrm_MarkThisResrcAsInvalid (void *resrc_ptr, void * xrm_inst, void *ud_ptr2, void *ud_ptr3) -{ - Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr; - CExtendedResourceManager * xrm_inst_ = (CExtendedResourceManager *)xrm_inst; - MISC_UNUSED(ud_ptr2); - MISC_UNUSED(ud_ptr3); - - if (Dl_IsNodeInList(&xrm_inst_->job_list, &resrc_ptr_->job_ptr->node)) - { - if (resrc_ptr_->job_ptr->valid == true) - { - resrc_ptr_->job_ptr->valid = false; - resrc_ptr_->job_ptr->notify = true; - } - - /* Inform monitor callback function */ - if (xrm_inst_->res_debugging_fptr != NULL) - { - xrm_inst_->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resrc_ptr_->resource_object_ptr), - resrc_ptr_->resource_object_ptr, UCS_XRM_INFOS_DESTROYED, xrm_inst_->current_job_ptr->user_arg, xrm_inst_->base_ptr->ucs_user_ptr); - } - - resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE; - resrc_ptr_->job_ptr = NULL; - resrc_ptr_->resource_object_ptr = NULL; - } - - return false; -} - -/*! \brief Marks all jobs on remote devices as "invalid". - * \param self Instance pointer - */ -void Xrm_MarkResrcAndJobsAsInvalid (CExtendedResourceManager *self) -{ - Xrmp_Foreach(self->xrmp_ptr, &Xrm_MarkThisResrcAsInvalid, self, NULL, NULL); - - self->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED; -} - -/*! \brief Calls the result callbacks of jobs that were marked as invalid. - * \param job_ptr Reference to the job to be looked for. - * \param xrm_inst XRM Instance pointer. - * \return \c false to continue the for-each-loop of the job_list queue - */ -bool Xrm_SetJobAsInvalid(void * job_ptr, void * xrm_inst) -{ - Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr; - CExtendedResourceManager * xrm_inst_ = (CExtendedResourceManager *)xrm_inst; - - if(job_ptr_->notify != false) - { - job_ptr_->report_fptr(Inic_GetTargetAddress(xrm_inst_->inic_ptr), job_ptr_->connection_label, xrm_inst_->report_result, job_ptr_->user_arg); - job_ptr_->notify = false; - } - - return false; -} - -/*! \brief Calls the result callbacks of jobs that were marked as invalid. - * \param self Instance pointer - */ -void Xrm_NotifyInvalidJobs(CExtendedResourceManager *self) -{ - (void)Dl_Foreach(&self->job_list, &Xrm_SetJobAsInvalid, self); -} - -/*! \brief Sets the monitoring callback for XRM resources. - * \param self Reference to the XRM Instance to be looked for. - * \param dbg_cb_fn Debug callback function to set. - */ -void Xrm_SetResourceDebugCbFn(CExtendedResourceManager *self, Ucs_Xrm_ResourceDebugCb_t dbg_cb_fn) -{ - if ((self != NULL) && (dbg_cb_fn != NULL)) - { - self->res_debugging_fptr = dbg_cb_fn; - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_xrm_res.c b/ucs2-lib/src/ucs_xrm_res.c deleted file mode 100644 index 900671d..0000000 --- a/ucs2-lib/src/ucs_xrm_res.c +++ /dev/null @@ -1,1443 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Extended Resource Manager. This file contains the implementation of - * the INIC Resource Management functions and result/error handlers. - * \cond UCS_INTERNAL_DOC - * \addtogroup G_UCS_XRM_INT - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_xrm.h" -#include "ucs_xrm_pv.h" -#include "ucs_xrm_cfg.h" -#include "ucs_misc.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Internal prototypes */ -/*------------------------------------------------------------------------------------------------*/ -static uint16_t Xrm_CreatePortHandle(CExtendedResourceManager *self, - Ucs_Xrm_PortType_t port_type, - uint8_t index); - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CExtendedResourceManager (Handling of resource objects) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Creates the corresponding INIC port handle depending on the given port type and the - * given port instance id. - * \param self Instance pointer - * \param port_type Type of the port - * \param index Port instance id - * \return Returns the created INIC port handle. - */ -static uint16_t Xrm_CreatePortHandle(CExtendedResourceManager *self, - Ucs_Xrm_PortType_t port_type, - uint8_t index) -{ - MISC_UNUSED(self); - return ((uint16_t)((uint16_t)port_type << 8) | (uint16_t)index); -} - -/*! \brief Activates remote synchronization on the current device - * \param self Instance pointer - * \param next_set_event Next event to set once the remote synchronization succeeded - * \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 - */ -extern Ucs_Return_t Xrm_RemoteDeviceAttach (CExtendedResourceManager *self, Srv_Event_t next_set_event) -{ - Ucs_Return_t result; - - result = Rsm_SyncDev(self->rsm_ptr, self, &Xrm_RmtDevAttachResultCb); - - if(result == UCS_RET_SUCCESS) - { - self->queued_event_mask |= next_set_event; - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start Synchronization of remote device", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, next_set_event); - } - - return result; -} - -/*! \brief Triggers the creation of a MOST socket. - * \param self Instance pointer - */ -void Xrm_CreateMostSocket(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_MostSocket_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_MostSocket_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t con_label = (cfg_ptr->direction == UCS_SOCKET_DIR_INPUT) ? self->current_job_ptr->most_network_connection_label : 0xFFFFU; - Ucs_Return_t result = Inic_MostSocketCreate(self->inic_ptr, - cfg_ptr->most_port_handle, - cfg_ptr->direction, - cfg_ptr->data_type, - cfg_ptr->bandwidth, - con_label, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MOST socket", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_MOST_SOCKET; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MOST socket failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of the MediaLB port. - * \param self Instance pointer - */ -void Xrm_CreateMlbPort(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_MlbPort_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_MlbPort_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - Ucs_Return_t result = Inic_MlbPortCreate(self->inic_ptr, - cfg_ptr->index, - cfg_ptr->clock_config, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MediaLB port", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_MLB_PORT; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MediaLB port failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a MediaLB socket. - * \param self Instance pointer - */ -void Xrm_CreateMlbSocket(CExtendedResourceManager *self) -{ - Ucs_Return_t result; - uint16_t mlb_port_handle; - UCS_XRM_CONST Ucs_Xrm_MlbSocket_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_MlbSocket_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - if(Xrm_IsDefaultCreatedPort(self, cfg_ptr->mlb_port_obj_ptr) != false) - { - mlb_port_handle = Xrm_CreatePortHandle(self, - UCS_XRM_PORT_TYPE_MLB, - ((UCS_XRM_CONST Ucs_Xrm_DefaultCreatedPort_t *)(UCS_XRM_CONST void*)(cfg_ptr->mlb_port_obj_ptr))->index); - } - else - { - mlb_port_handle= Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->mlb_port_obj_ptr, NULL); - } - result = Inic_MlbSocketCreate(self->inic_ptr, - mlb_port_handle, - cfg_ptr->direction, - cfg_ptr->data_type, - cfg_ptr->bandwidth, - cfg_ptr->channel_address, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MediaLB socket", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_MLB_SOCKET; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating MediaLB socket failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of the USB port. - * \param self Instance pointer - */ -void Xrm_CreateUsbPort(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_UsbPort_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_UsbPort_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - Ucs_Return_t result = Inic_UsbPortCreate(self->inic_ptr, - cfg_ptr->index, - cfg_ptr->physical_layer, - cfg_ptr->devices_interfaces, - cfg_ptr->streaming_if_ep_out_count, - cfg_ptr->streaming_if_ep_in_count, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating USB port", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_USB_PORT; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating USB port failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a USB socket. - * \param self Instance pointer - */ -void Xrm_CreateUsbSocket(CExtendedResourceManager *self) -{ - Ucs_Return_t result; - uint16_t usb_port_handle; - UCS_XRM_CONST Ucs_Xrm_UsbSocket_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_UsbSocket_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - if(Xrm_IsDefaultCreatedPort(self, cfg_ptr->usb_port_obj_ptr) != false) - { - usb_port_handle = Xrm_CreatePortHandle(self, - UCS_XRM_PORT_TYPE_USB, - ((UCS_XRM_CONST Ucs_Xrm_DefaultCreatedPort_t *)(UCS_XRM_CONST void*)(cfg_ptr->usb_port_obj_ptr))->index); - } - else - { - usb_port_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->usb_port_obj_ptr, NULL); - } - result = Inic_UsbSocketCreate(self->inic_ptr, - usb_port_handle, - cfg_ptr->direction, - cfg_ptr->data_type, - cfg_ptr->end_point_addr, - cfg_ptr->frames_per_transfer, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating USB socket", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_USB_SOCKET; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating USB socket failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of the RMCK port. - * \param self Instance pointer - */ -void Xrm_CreateRmckPort(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_RmckPort_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_RmckPort_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - Ucs_Return_t result = Inic_RmckPortCreate(self->inic_ptr, - cfg_ptr->index, - cfg_ptr->clock_source, - cfg_ptr->divisor, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating RMCK port", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_RMCK_PORT; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating RMCK port failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a streaming port. - * \param self Instance pointer - */ -void Xrm_CreateStreamPort(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_StrmPort_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_StrmPort_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - Ucs_Return_t result = Inic_StreamPortCreate(self->inic_ptr, - cfg_ptr->index, - cfg_ptr->clock_config, - cfg_ptr->data_alignment, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating streaming port", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_STRM_PORT; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating streaming port failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a streaming data socket. - * \param self Instance pointer - */ -void Xrm_CreateStreamSocket(CExtendedResourceManager *self) -{ - Ucs_Return_t result; - uint16_t stream_port_handle; - UCS_XRM_CONST Ucs_Xrm_StrmSocket_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_StrmSocket_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - if(Xrm_IsDefaultCreatedPort(self, cfg_ptr->stream_port_obj_ptr) != false) - { - stream_port_handle = Xrm_CreatePortHandle(self, - UCS_XRM_PORT_TYPE_STRM, - ((UCS_XRM_CONST Ucs_Xrm_DefaultCreatedPort_t *)(UCS_XRM_CONST void*)(cfg_ptr->stream_port_obj_ptr))->index); - } - else - { - stream_port_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->stream_port_obj_ptr, NULL); - } - result = Inic_StreamSocketCreate(self->inic_ptr, - stream_port_handle, - cfg_ptr->direction, - cfg_ptr->data_type, - cfg_ptr->bandwidth, - cfg_ptr->stream_pin_id, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating streaming data socket", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_STRM_SOCKET; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating streaming data socket failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a synchronous data connection. - * \param self Instance pointer - */ -void Xrm_CreateSyncCon(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_SyncCon_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_SyncCon_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t in_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_in_obj_ptr, NULL); - uint16_t out_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_out_obj_ptr, NULL); - Ucs_Return_t result = Inic_SyncCreate(self->inic_ptr, - in_socket_handle, - out_socket_handle, - false, - cfg_ptr->mute_mode, - cfg_ptr->offset, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating synchronous data connection", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_SYNC_CON; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating synchronous data connection failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a DiscreteFrame Isochronous streaming phase connection. - * \param self Instance pointer - */ -void Xrm_CreateDfiPhaseCon(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_DfiPhaseCon_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_DfiPhaseCon_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t in_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_in_obj_ptr, NULL); - uint16_t out_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_out_obj_ptr, NULL); - Ucs_Return_t result = Inic_DfiPhaseCreate(self->inic_ptr, - in_socket_handle, - out_socket_handle, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating DFIPhase connection", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_DFIPHASE_CON; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating DFIPhase connection failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a combiner resource. - * \param self Instance pointer - */ -void Xrm_CreateCombiner(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_Combiner_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_Combiner_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t port_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->port_socket_obj_ptr, NULL); - Ucs_Return_t result = Inic_CombinerCreate(self->inic_ptr, - port_socket_handle, - cfg_ptr->most_port_handle, - cfg_ptr->bytes_per_frame, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating combiner resource", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_COMBINER; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating combiner resource failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a splitter resource. - * \param self Instance pointer - */ -void Xrm_CreateSplitter(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_Splitter_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_Splitter_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t socket_handle_in = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_in_obj_ptr, NULL); - Ucs_Return_t result = Inic_SplitterCreate(self->inic_ptr, - socket_handle_in, - cfg_ptr->most_port_handle, - cfg_ptr->bytes_per_frame, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating splitter resource", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_SPLITTER; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating splitter resource failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a A/V packetized isochronous streaming data connection. - * \param self Instance pointer - */ -void Xrm_CreateAvpCon(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_AvpCon_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_AvpCon_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t in_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_in_obj_ptr, NULL); - uint16_t out_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_out_obj_ptr, NULL); - Ucs_Return_t result = Inic_AvpCreate(self->inic_ptr, - in_socket_handle, - out_socket_handle, - cfg_ptr->isoc_packet_size, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating A/V packetized isochronous streaming data connection", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_AVP_CON; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating A/V packetized isochronous streaming data connection failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Triggers the creation of a Quality of Service IP streaming data connection. - * \param self Instance pointer - */ -void Xrm_CreateQoSCon(CExtendedResourceManager *self) -{ - UCS_XRM_CONST Ucs_Xrm_QoSCon_t *cfg_ptr = (UCS_XRM_CONST Ucs_Xrm_QoSCon_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr); - uint16_t in_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_in_obj_ptr, NULL); - uint16_t out_socket_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, cfg_ptr->socket_out_obj_ptr, NULL); - Ucs_Return_t result = Inic_QoSCreate(self->inic_ptr, - in_socket_handle, - out_socket_handle, - &self->obs.std_result_obs); - if(result == UCS_RET_SUCCESS) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating QoS IP streaming data connection", 0U)); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_PROCESS); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_BUILD; - self->report_result.details.resource_type = UCS_XRM_RC_TYPE_QOS_CON; - self->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self, - self->current_job_ptr, - self->current_obj_pptr); - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Xrm_HandleError(self); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start creating QoS IP streaming data connection failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Process the result of the INIC resource monitor. - * \param self Instance pointer - * \param result_ptr Reference to result data. Result must be casted into data type - * Inic_StdResult_t. - */ -void Xrm_ResourceMonitorCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if((result_ptr_->result.code == UCS_RES_SUCCESS) && (result_ptr_->data_info != NULL)) - { - Ucs_Resource_MonitorState_t state = *((Ucs_Resource_MonitorState_t *)result_ptr_->data_info); - if(state == UCS_INIC_RES_MON_STATE_ACT_REQ) - { - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_REQ_INV_RES_LST); - } - else if((state == UCS_INIC_RES_MON_STATE_OK) && (self_->obs.check_unmute_fptr != NULL)) - { - self_->obs.check_unmute_fptr(Inic_GetTargetAddress(self_->inic_ptr), self_->base_ptr->ucs_user_ptr); - } - } -} - -/*! \brief Retrieves the list of invalid resources. - * \param self Instance pointer - */ -void Xrm_RequestResourceList(CExtendedResourceManager *self) -{ - if(Xrm_IsApiFree(self) != false) - { - Ucs_Return_t result; - result = Inic_ResourceInvalidList_Get(self->inic_ptr, - &self->obs.resource_invalid_list_obs); - if(result == UCS_RET_SUCCESS) - { - Xrm_ApiLocking(self, true); - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_REQ_INV_RES_LST); - } - else - { - self->report_result.code = UCS_XRM_RES_ERR_INV_LIST; - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start requesting invalid resources failed. Return value: 0x%02X", 1U, result)); - } - } - else - { - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_REQ_INV_RES_LST); - } -} - -/*! \brief Process the received list of invalid resources. - * \param self Instance pointer - * \param result_ptr Reference to result data. Result must be casted into data type - * Inic_StdResult_t. - */ -void Xrm_RequestResourceListResultCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if((result_ptr_->result.code == UCS_RES_SUCCESS) && (result_ptr_->data_info != NULL)) - { - Inic_ResHandleList_t resource_handle_list = *((Inic_ResHandleList_t *)result_ptr_->data_info); - if((resource_handle_list.res_handles != NULL) && (resource_handle_list.num_handles > 0U)) - { - MISC_MEM_CPY(&self_->inv_resource_handle_list[0], - &resource_handle_list.res_handles[0], - (resource_handle_list.num_handles * sizeof(resource_handle_list.res_handles[0]))); - } - self_->inv_resource_handle_list_size = resource_handle_list.num_handles; - self_->inv_resource_handle_index = 0U; - - Xrmp_Foreach(self_->xrmp_ptr, &Xrm_SetCurrJobPtr, &resource_handle_list.res_handles[0], NULL, self); - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_DESTROY_INV_RES); - } - else - { - self_->report_result.code = UCS_XRM_RES_ERR_INV_LIST; - if (result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->report_result.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TX; - } - else - { - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TGT; - } - - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Request of invalid resources failed. Return value: 0x%02X", 1U, result_ptr_->result.code)); - TR_ERROR_INIC_RESULT(self_->base_ptr->ucs_user_ptr, "[XRM]", result_ptr_->result.info_ptr, result_ptr_->result.info_size); - } - - Xrm_ApiLocking(self_, false); -} - -/*! \brief Triggers the destruction of INIC resources. - * \param self Instance pointer - * \param result_fptr Result callback function pointer - */ -void Xrm_DestroyResources(CExtendedResourceManager *self, Sobs_UpdateCb_t result_fptr) -{ - Ucs_Return_t result; - Inic_ResHandleList_t list; - list.res_handles = &self->inv_resource_handle_list[self->inv_resource_handle_index]; - if (self->inv_resource_handle_list_size > MAX_INVALID_HANDLES_LIST) - { - list.num_handles = MAX_INVALID_HANDLES_LIST; - self->curr_dest_resource_handle_size = list.num_handles; - } - else - { - list.num_handles = self->inv_resource_handle_list_size; - self->curr_dest_resource_handle_size = list.num_handles; - if(self->inv_resource_handle_list[(self->inv_resource_handle_index + self->inv_resource_handle_list_size) - 1U] == XRM_INVALID_RESOURCE_HANDLE) - { - list.num_handles--; - } - } - Sobs_Ctor(&self->obs.resource_destroy_obs, self, result_fptr); - result = Inic_ResourceDestroy(self->inic_ptr, - list, - &self->obs.resource_destroy_obs); - if(result == UCS_RET_SUCCESS) - { - /* No error */ -#ifdef UCS_TR_INFO - uint8_t i; - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "Destruction of invalid resource handles been successfully started:", 0U)); - for(i=0U; i<list.num_handles; i++) - { - TR_INFO((self->base_ptr->ucs_user_ptr, "[XRM]", "--> Handle: 0x%04X", 1U, list.res_handles[i])); - } -#endif - } - else if (result == UCS_RET_ERR_PARAM) - { - /* empty list */ - if ((list.num_handles == 0U) && (list.res_handles[0] == XRM_INVALID_RESOURCE_HANDLE)) - { - self->inv_resource_handle_list_size = 0U; - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_RESET_RES_MONITOR); - } - } - else if(result == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_DESTROY_INV_RES); - } - else - { - self->inv_resource_handle_list_size = 0U; - self->report_result.code = UCS_XRM_RES_ERR_DESTROY; - self->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self->report_result.details.int_result = result; - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Start destroying invalid resources failed. Return value: 0x%02X", 1U, result)); - } -} - -/*! \brief Resets the INIC's Resource Monitor. - * \param self Instance pointer - */ -void Xrm_ResetResourceMonitor(CExtendedResourceManager *self) -{ - Ucs_Return_t result = Inic_ResourceMonitor_Set(self->inic_ptr, UCS_INIC_RES_MON_CTRL_RESET); - if(result == UCS_RET_SUCCESS) - { - Srv_SetEvent(&self->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RES); - } - else - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_RESET_RES_MONITOR); - } -} - - -/*! \brief Handles the result of resource destructions. - * \param self Instance pointer - * \param result_ptr Reference to result data. Result must be casted into data type - * Inic_StdResult_t. - */ -void Xrm_DestroyResourcesResultCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - (void)Xrm_ReleaseResourceHandles(self_, - NULL, - &self_->inv_resource_handle_list[self_->inv_resource_handle_index], - self_->curr_dest_resource_handle_size, - XRM_INVALID_RESOURCE_HANDLE); - - if (self_->inv_resource_handle_list_size >= self_->curr_dest_resource_handle_size) - { - self_->inv_resource_handle_list_size -= self_->curr_dest_resource_handle_size; - if (self_->inv_resource_handle_list_size > 0U) - { - self_->inv_resource_handle_index += self_->curr_dest_resource_handle_size; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_DESTROY_INV_RES); - } - else - { - if(self_->inv_resource_handle_list[(self_->inv_resource_handle_index + self_->curr_dest_resource_handle_size) - 1U] != XRM_INVALID_RESOURCE_HANDLE) - { - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_REQ_INV_RES_LST); - } - else - { - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_RESET_RES_MONITOR); - } - TR_INFO((self_->base_ptr->ucs_user_ptr, "[XRM]", "INIC resources been successfully destroyed.", 0U)); - } - } - else - { - self_->inv_resource_handle_list_size = 0U; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.code = UCS_XRM_RES_ERR_DESTROY; - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Destruction of invalid resources failed. Internal resources handles List is corrupted", 0U)); - } - } - else if(result_ptr_->result.code == UCS_RES_ERR_BUSY) - { - uint8_t stop_index; - uint16_t failed_resource_handle; - MISC_DECODE_WORD(&(failed_resource_handle), &(result_ptr_->result.info_ptr[3])); - stop_index = Xrm_ReleaseResourceHandles(self_, - NULL, - &self_->inv_resource_handle_list[self_->inv_resource_handle_index], - self_->curr_dest_resource_handle_size, - failed_resource_handle); - - if (stop_index > 0U) - { - self_->inv_resource_handle_index = stop_index; - self_->inv_resource_handle_list_size -= stop_index; - } - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_DESTROY_INV_RES); - } - else - { - self_->inv_resource_handle_list_size = 0U; - if (result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->report_result.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TX; - } - else - { - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TGT; - } - self_->report_result.code = UCS_XRM_RES_ERR_DESTROY; - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Destruction of invalid resources failed. Return value: 0x%02X", 1U, result_ptr_->result.code)); - TR_ERROR_INIC_RESULT(self_->base_ptr->ucs_user_ptr, "[XRM]", result_ptr_->result.info_ptr, result_ptr_->result.info_size); - } -} - -/*! \brief Handles the result of resource destructions for all resources of a job. - * \param self Instance pointer - * \param result_ptr Reference to result data. Result must be casted into data type - * Inic_StdResult_t. - */ -void Xrm_DestroyJobResourcesResultCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - if(result_ptr_->result.code == UCS_RES_SUCCESS) - { - (void)Xrm_ReleaseResourceHandles(self_, - self_->current_job_ptr, - &self_->inv_resource_handle_list[self_->inv_resource_handle_index], - self_->curr_dest_resource_handle_size, - XRM_INVALID_RESOURCE_HANDLE); - - if (self_->inv_resource_handle_list_size >= self_->curr_dest_resource_handle_size) - { - self_->inv_resource_handle_list_size -= self_->curr_dest_resource_handle_size; - self_->inv_resource_handle_index = 0U; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_RESUME_JOB_DESTRUCT); - TR_INFO((self_->base_ptr->ucs_user_ptr, "[XRM]", "INIC resources been successfully destroyed.", 0U)); - } - else - { - self_->inv_resource_handle_list_size = 0U; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_INT; - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.code = UCS_XRM_RES_ERR_DESTROY; - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Destruction of invalid resources failed. Internal resources handles List is corrupted", 0U)); - } - } - else if(result_ptr_->result.code == UCS_RES_ERR_BUSY) - { - uint16_t failed_handle; - MISC_DECODE_WORD(&(failed_handle), &(result_ptr_->result.info_ptr[3])); - (void)Xrm_ReleaseResourceHandles(self_, - NULL, - &self_->inv_resource_handle_list[self_->inv_resource_handle_index], - self_->curr_dest_resource_handle_size, - failed_handle); - - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_RESUME_JOB_DESTRUCT); - } - else - { - self_->inv_resource_handle_list_size = 0U; - if (result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->report_result.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TX; - } - else - { - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TGT; - } - - self_->report_result.code = UCS_XRM_RES_ERR_DESTROY; - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Destruction of invalid resources failed. Return value: 0x%02X", 1U, result_ptr_->result.code)); - TR_ERROR_INIC_RESULT(self_->base_ptr->ucs_user_ptr, "[XRM]", result_ptr_->result.info_ptr, result_ptr_->result.info_size); - } -} - -/*! \brief Handles the result of "create port", "create socket" and "create connection" operations. - * \param self Instance pointer - * \param result_ptr Reference to result data. Result must be casted into data type - * Inic_StdResult_t. - */ -void Xrm_StdResultCb(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - - if((result_ptr_->result.code == UCS_RES_SUCCESS) && (result_ptr_->data_info != NULL)) - { - uint16_t resource_handle = 0U; - if(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self_->current_obj_pptr) == UCS_XRM_RC_TYPE_MOST_SOCKET) - { - Inic_MostSocketCreate_Result_t res_ack = {0U, 0U}; - res_ack = *((Inic_MostSocketCreate_Result_t *)result_ptr_->data_info); - resource_handle = res_ack.most_socket_handle; - self_->current_job_ptr->connection_label = res_ack.conn_label; - } - else - { - resource_handle = *((uint16_t *)result_ptr_->data_info); - } - - if(Xrm_StoreResourceHandle(self_, resource_handle, self_->current_job_ptr, *self_->current_obj_pptr) != false) - { - if (self_->res_debugging_fptr != NULL) - { - self_->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self_->current_obj_pptr), *self_->current_obj_pptr, UCS_XRM_INFOS_BUILT, - self_->current_job_ptr->user_arg, self_->base_ptr->ucs_user_ptr); - } - - self_->current_obj_pptr++; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_PROCESS); - TR_INFO((self_->base_ptr->ucs_user_ptr, "[XRM]", "Resource has been successfully created. Handle: 0x%04X", 1U, resource_handle)); - } - else - { - self_->report_result.code = UCS_XRM_RES_ERR_CONFIG; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Misconfiguration. Resource handle list is too small.", 0U)); - } - } - else - { - self_->current_job_ptr->valid = false; - - if (result_ptr_->result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->report_result.details.tx_result = *(Ucs_MsgTxStatus_t *)(result_ptr_->data_info); - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TX; - } - else - { - self_->report_result.details.tx_result = UCS_MSG_STAT_OK; - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TGT; - } - - self_->report_result.code = UCS_XRM_RES_ERR_BUILD; - self_->report_result.details.resource_type = *(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self_->current_obj_pptr); - self_->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self_, - self_->current_job_ptr, - self_->current_obj_pptr); - self_->report_result.details.inic_result = result_ptr_->result; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - - if (self_->res_debugging_fptr != NULL) - { - self_->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self_->current_obj_pptr), - *self_->current_obj_pptr, UCS_XRM_INFOS_ERR_BUILT, self_->current_job_ptr->user_arg, self_->base_ptr->ucs_user_ptr); - } - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Creation of resource failed. Result code: 0x%02X", 1U, result_ptr_->result.code)); - if (result_ptr_->result.info_ptr != NULL) - { - TR_ERROR_INIC_RESULT(self_->base_ptr->ucs_user_ptr, "[XRM]", result_ptr_->result.info_ptr, result_ptr_->result.info_size); - } - } -} - -/*! \brief Handles the result of "device.sync" operations. - * \param self Instance pointer - * \param result RSM result - */ -void Xrm_RmtDevAttachResultCb(void *self, Rsm_Result_t result) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - if (result.code == RSM_RES_SUCCESS) - { - Srv_SetEvent(&self_->xrm_srv, self_->queued_event_mask); - self_->queued_event_mask = 0U; - TR_INFO((self_->base_ptr->ucs_user_ptr, "[XRM]", "Remote device has been successfully synchronized.", 0U)); - } - else - { - /* In case of StreamingConfig, simulate an error configuration since there - * is currently no possibility to signal SyncLost - */ - if ((self_->queued_event_mask == XRM_EVENT_STREAMPORT_CONFIG_SET) || - (self_->queued_event_mask == XRM_EVENT_STREAMPORT_CONFIG_GET)) - { - Inic_StdResult_t sim_inic_res; - sim_inic_res.result.code = result.details.inic_result.code; - sim_inic_res.result.info_ptr = NULL; - sim_inic_res.result.info_size = 0U; - sim_inic_res.data_info = NULL; - - self_->queued_event_mask = 0U; - /* Force a Notification of the Streaming observer */ - self_->obs.stream_port_config_fptr = self_->current_streamport_config.result_fptr; - self_->obs.stream_port_config_obs.update_fptr(self, &sim_inic_res); - } - else - { - if (result.details.inic_result.code == UCS_RES_ERR_TRANSMISSION) - { - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TX; - } - else - { - self_->report_result.details.result_type = UCS_XRM_RESULT_TYPE_TGT; - } - self_->report_result.code = UCS_XRM_RES_ERR_SYNC; - self_->report_result.details.inic_result.code = result.details.inic_result.code; - self_->report_result.details.inic_result.info_ptr = result.details.inic_result.info_ptr; - self_->report_result.details.inic_result.info_size = result.details.inic_result.info_size; - self_->report_result.details.resource_type = *(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self_->current_obj_pptr); - self_->report_result.details.resource_index = Xrm_GetResourceObjectIndex(self_, - self_->current_job_ptr, - self_->current_obj_pptr); - self_->report_result.details.tx_result = (Ucs_MsgTxStatus_t)result.details.tx_result; - - self_->queued_event_mask = 0U; - Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_ERROR); - TR_ERROR((self_->base_ptr->ucs_user_ptr, "[XRM]", "Synchronization to the remote device failed. Result code: 0x%02X", 1U, result)); - } - } -} - - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class CExtendedResourceManager (INIC Resource Management API) */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief This function is used to configure a Streaming Port. - * \param self Instance pointer - * \param index Streaming Port instance. - * \param op_mode Operation mode of the Streaming Port. - * \param port_option Direction of the physical pins of the indexed Streaming Port. - * \param clock_mode Configuration of the FSY/SCK signals. - * \param clock_data_delay Configuration of the FSY/SCK signals for Generic Streaming. - * \param result_fptr Required result callback - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | Invalid callback pointer - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Xrm_Stream_SetPortConfig(CExtendedResourceManager *self, - uint8_t index, - Ucs_Stream_PortOpMode_t op_mode, - Ucs_Stream_PortOption_t port_option, - Ucs_Stream_PortClockMode_t clock_mode, - Ucs_Stream_PortClockDataDelay_t clock_data_delay, - Ucs_Xrm_Stream_PortCfgResCb_t result_fptr) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_API_LOCKED; - - if ((self != NULL) && (result_fptr != NULL) ) - { - if(Xrm_IsApiFree(self) != false) - { - Xrm_ApiLocking(self, true); - - self->current_streamport_config.index = index; - self->current_streamport_config.op_mode = op_mode; - self->current_streamport_config.port_option = port_option; - self->current_streamport_config.clock_mode = clock_mode; - self->current_streamport_config.clock_data_delay = clock_data_delay; - self->current_streamport_config.result_fptr = result_fptr; - - ret_val = Xrm_SetStreamPortConfiguration(self); - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - } - - return ret_val; -} - -/*! \brief This function is used to configure a Streaming Port. - * \param self Instance pointer - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | Invalid callback pointer - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - */ -Ucs_Return_t Xrm_SetStreamPortConfiguration (CExtendedResourceManager *self) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (Xrm_IsCurrDeviceAlreadyAttached(self) == false) - { - ret_val = Xrm_RemoteDeviceAttach(self, XRM_EVENT_STREAMPORT_CONFIG_SET); - } - else - { - ret_val = Inic_StreamPortConfig_SetGet(self->inic_ptr, - self->current_streamport_config.index, - self->current_streamport_config.op_mode, - self->current_streamport_config.port_option, - self->current_streamport_config.clock_mode, - self->current_streamport_config.clock_data_delay, - &self->obs.stream_port_config_obs); - if(ret_val == UCS_RET_SUCCESS) - { - self->obs.stream_port_config_fptr = self->current_streamport_config.result_fptr; - } - else if(ret_val == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_STREAMPORT_CONFIG_SET); - } - else if (ret_val == UCS_RET_ERR_API_LOCKED) - { - Xrm_ApiLocking(self, false); - } - } - - return ret_val; -} - -/*! \brief This function requests the configurations of a Streaming Port. - * \param self Instance pointer - * \param index Streaming Port instance. - * \param result_fptr Required result callback - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ---------------------------------------------- - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | At least one parameter is wrong - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - * UCS_RET_ERR_API_LOCKED | API is currently locked - * UCS_RET_ERR_NOT_AVAILABLE | Associated device not found - */ -Ucs_Return_t Xrm_Stream_GetPortConfig(CExtendedResourceManager *self, - uint8_t index, - Ucs_Xrm_Stream_PortCfgResCb_t result_fptr) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_API_LOCKED; - - if((self != NULL) && (result_fptr != NULL) ) - { - if(Xrm_IsApiFree(self) != false) - { - Xrm_ApiLocking(self, true); - - self->current_streamport_config.index = index; - self->current_streamport_config.result_fptr = result_fptr; - - ret_val = Xrm_GetStreamPortConfiguration(self); - if (ret_val == UCS_RET_ERR_API_LOCKED) - { - /* from another process locked */ - Xrm_ApiLocking(self, false); - } - } - } - else - { - ret_val = UCS_RET_ERR_PARAM; - } - - return ret_val; -} - -/*! \brief This function is used to configure a Streaming Port. - * \param self Instance pointer - * \return Possible return values are shown in the table below. - * Value | Description - * --------------------------- | ------------------------------------ - * UCS_RET_SUCCESS | No error - * UCS_RET_ERR_PARAM | Invalid callback pointer - * UCS_RET_ERR_BUFFER_OVERFLOW | No message buffer available - */ -Ucs_Return_t Xrm_GetStreamPortConfiguration (CExtendedResourceManager *self) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if (Xrm_IsCurrDeviceAlreadyAttached(self) == false) - { - ret_val = Xrm_RemoteDeviceAttach(self, XRM_EVENT_STREAMPORT_CONFIG_GET); - } - else - { - ret_val = Inic_StreamPortConfig_Get(self->inic_ptr, - self->current_streamport_config.index, - &self->obs.stream_port_config_obs); - if(ret_val == UCS_RET_SUCCESS) - { - self->obs.stream_port_config_fptr = self->current_streamport_config.result_fptr; - } - else if(ret_val == UCS_RET_ERR_BUFFER_OVERFLOW) - { - Xrm_WaitForTxMsgObj(self, XRM_EVENT_STREAMPORT_CONFIG_GET); - } - } - - return ret_val; -} - -/*! \brief Observer callback for Inic_StreamPortConfig_Get(). Casts the result and invokes - * the application result callback. - * \param self Instance pointer - * \param result_ptr Reference to result - */ -void Xrm_Stream_PortConfigResult(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - Inic_StreamPortConfigStatus_t status; - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - Ucs_StdResult_t res = result_ptr_->result; - - if(self_->obs.stream_port_config_fptr != NULL) - { - if((result_ptr_->result.code == UCS_RES_SUCCESS) && (result_ptr_->data_info != NULL)) - { - status = *((Inic_StreamPortConfigStatus_t *)result_ptr_->data_info); - } - else - { - /* Fill param callback function with default (dummy) values */ - status.index = 0x00U; - status.op_mode = UCS_STREAM_PORT_OP_MODE_GENERIC; - status.port_option = UCS_STREAM_PORT_OPT_IN_OUT; - status.clock_mode = UCS_STREAM_PORT_CLK_MODE_OUTPUT; - status.clock_data_delay = UCS_STREAM_PORT_CLK_DLY_NONE; - } - self_->obs.stream_port_config_fptr(Inic_GetTargetAddress(self_->inic_ptr), - status.index, - status.op_mode, - status.port_option, - status.clock_mode, - status.clock_data_delay, - res, - self_->base_ptr->ucs_user_ptr); - } - - Xrm_ApiLocking(self_, false); -} - -/*! \brief Enables or disables a specific MOST Network Port. - * \param self Instance pointer - * \param most_port_handle Port resource handle. - * \param enabled State of the MOST Port. - * \param result_fptr Optional result callback. - * \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 - * UCS_RET_ERR_API_LOCKED | API is currently locked - * UCS_RET_ERR_NOT_INITIALIZED | UNICENS is not initialized - */ -Ucs_Return_t Xrm_Most_EnablePort(CExtendedResourceManager *self, - uint16_t most_port_handle, - bool enabled, - Ucs_StdResultCb_t result_fptr) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if(Xrm_IsApiFree(self) != false) - { - ret_val = Inic_MostPortEnable(self->inic_ptr, - most_port_handle, - enabled, - &self->obs.most_port_enable_obs); - if(ret_val == UCS_RET_SUCCESS) - { - self->obs.most_port_enable_fptr = result_fptr; - } - } - - return ret_val; -} - -/*! \brief Enables full streaming for a specific MOST Network Port. - * \param self Instance pointer - * \param most_port_handle Port resource handle. - * \param enabled State of the MOST Port related to full streaming. - * \param result_fptr Optional result callback. - * \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 - * UCS_RET_ERR_API_LOCKED | API is currently locked - * UCS_RET_ERR_NOT_INITIALIZED | UNICENS is not initialized - */ -Ucs_Return_t Xrm_Most_PortEnFullStr(CExtendedResourceManager *self, - uint16_t most_port_handle, - bool enabled, - Ucs_StdResultCb_t result_fptr) -{ - Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED; - - if(Xrm_IsApiFree(self) != false) - { - ret_val = Inic_MostPortEnFullStr(self->inic_ptr, - most_port_handle, - enabled, - &self->obs.most_port_en_full_str_obs); - if(ret_val == UCS_RET_SUCCESS) - { - self->obs.most_port_en_full_str_fptr = result_fptr; - } - } - - return ret_val; -} - -/*! \brief Observer callback for Inic_MostPortEnable(). Casts the result and invokes - * the application result callback. - * \param self Instance pointer - * \param result_ptr Reference to result - */ -void Xrm_Most_PortEnableResult(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - if(self_->obs.most_port_enable_fptr != NULL) - { - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - self_->obs.most_port_enable_fptr(result_ptr_->result, self_->base_ptr->ucs_user_ptr); - } -} - -/*! \brief Observer callback for Inic_MostPortEnFullStr(). Casts the result and invokes - * the application result callback. - * \param self Instance pointer - * \param result_ptr Reference to result - */ -void Xrm_Most_PortEnFullStrResult(void *self, void *result_ptr) -{ - CExtendedResourceManager *self_ = (CExtendedResourceManager *)self; - if(self_->obs.most_port_en_full_str_fptr != NULL) - { - Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; - self_->obs.most_port_en_full_str_fptr(result_ptr_->result, self_->base_ptr->ucs_user_ptr); - } -} - -/*! \brief Sets the current job pointer of the CExtendedResourceManager instance. - * \param resrc_ptr Reference to the resource handle list to be looked for. - * \param resrc_handle Reference to the resource handle to be found. - * \param job_ptr Reference to the job to be looked for. - * \param user_arg Reference to a user argument. - * \return \c false to continue the for-each-loop of the resources list table, otherwise \c true - */ -bool Xrm_SetCurrJobPtr(void *resrc_ptr, void *resrc_handle, void *job_ptr, void * user_arg) -{ - bool ret_val = false; - Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr; - uint16_t * resrc_handle_ = (uint16_t *)resrc_handle; - CExtendedResourceManager *self = (CExtendedResourceManager *)user_arg; - - MISC_UNUSED(job_ptr); - - if ((resrc_ptr_->resource_handle == *resrc_handle_) && - (*resrc_handle_ != XRM_INVALID_RESOURCE_HANDLE) && - (Dl_IsNodeInList(&self->job_list, &resrc_ptr_->job_ptr->node))) - { - self->current_job_ptr = resrc_ptr_->job_ptr; - ret_val = true; - } - - return ret_val; -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - diff --git a/ucs2-lib/src/ucs_xrmpool.c b/ucs2-lib/src/ucs_xrmpool.c deleted file mode 100644 index 116253b..0000000 --- a/ucs2-lib/src/ucs_xrmpool.c +++ /dev/null @@ -1,210 +0,0 @@ -/*------------------------------------------------------------------------------------------------*/ -/* 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 Connection Storage Pool. - * - * \cond UCS_INTERNAL_DOC - * \addtogroup G_UCS_XRM_INT - * @{ - */ - -/*------------------------------------------------------------------------------------------------*/ -/* Includes */ -/*------------------------------------------------------------------------------------------------*/ -#include "ucs_xrmpool.h" -#include "ucs_xrm_pv.h" - -/*------------------------------------------------------------------------------------------------*/ -/* Implementation of class XrmPool */ -/*------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------*/ -/* Initialization Methods */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Constructor of the XrmPool class. - * \param self Instance pointer - */ -void Xrmp_Ctor(CXrmPool * self) -{ - uint8_t i; - MISC_MEM_SET(self, 0, sizeof(CXrmPool)); - - /* Initialize resource handle list */ - for(i=0U; i<XRM_NUM_RESOURCE_HANDLES; i++) - { - self->resource_handle_list[i].resource_handle = XRM_INVALID_RESOURCE_HANDLE; - self->resource_handle_list[i].job_ptr = NULL; - self->resource_handle_list[i].resource_object_ptr = NULL; - } -} - -/*------------------------------------------------------------------------------------------------*/ -/* Service */ -/*------------------------------------------------------------------------------------------------*/ -/*! \brief Stores the given resource handle in the resource handle list. - * \param self_ptr XrmPool Instance pointer - * \param resource_handle Resource handle to save - * \param job_ptr Reference to job - * \param resource_object_ptr Reference to resource object - * \return \c true if free slot in handle list was found, otherwise \c false - */ -bool Xrmp_StoreResourceHandle(CXrmPool * self_ptr, uint16_t resource_handle, Xrm_Job_t * job_ptr, UCS_XRM_CONST Ucs_Xrm_ResObject_t * resource_object_ptr) -{ - bool ret_val = false; - uint8_t i; - - for(i=0U; i<XRM_NUM_RESOURCE_HANDLES; i++) - { - if(self_ptr->resource_handle_list[i].job_ptr == NULL) - { - self_ptr->resource_handle_list[i].job_ptr = job_ptr; - self_ptr->resource_handle_list[i].resource_object_ptr = resource_object_ptr; - self_ptr->resource_handle_list[i].resource_handle = resource_handle; - ret_val = true; - break; - } - } - - return ret_val; -} - -/*! \brief Retrieves the resource handle identified by the given job reference and the given - * resource object reference. - * \param self Instance pointer - * \param job_ptr Reference to the job. Use NULL as wildcard. - * \param resource_object_ptr Reference to the resource object - * \param func_ptr Optional function pointer in order to check whether the found job belongs to the provided XRM instance. - * \param usr_ptr User pointer used to store the XRM instance to be looked for - * \return Resource handle if handle was found, otherwise XRM_INVALID_RESOURCE_HANDLE. - */ -uint16_t Xrmp_GetResourceHandle(CXrmPool * self, Xrm_Job_t * job_ptr, UCS_XRM_CONST Ucs_Xrm_ResObject_t * resource_object_ptr, Xrmp_CheckJobListFunc_t func_ptr, void * usr_ptr) -{ - uint16_t ret_val = XRM_INVALID_RESOURCE_HANDLE; - uint8_t i; - bool job_found = true; - - for(i=0U; i<XRM_NUM_RESOURCE_HANDLES; i++) - { - if(((self->resource_handle_list[i].job_ptr == job_ptr) || (job_ptr == NULL)) && - (self->resource_handle_list[i].resource_object_ptr == resource_object_ptr)) - { - if ((func_ptr != NULL) && (usr_ptr != NULL)) - { - job_found = func_ptr(usr_ptr, self->resource_handle_list[i].job_ptr); - } - - if (job_found) - { - ret_val = self->resource_handle_list[i].resource_handle; - break; - } - } - } - - return ret_val; -} - -/*! \brief Returns the table index of the given resource object. - * \param self Instance pointer - * \param job_ptr Reference to job - * \param obj_pptr Reference to array of references to INIC resource objects - * \return Table index of the given resource object. If entry is not found 0xFF is returned. - */ -uint8_t Xrmp_GetResourceHandleIdx(CXrmPool *self, Xrm_Job_t *job_ptr, UCS_XRM_CONST Ucs_Xrm_ResObject_t **obj_pptr) -{ - uint8_t i = 0U; - uint8_t ret_val = 0xFFU; - - MISC_UNUSED(self); - - while(job_ptr->resource_object_list_ptr[i] != NULL) - { - if(job_ptr->resource_object_list_ptr[i] == *obj_pptr) - { - ret_val = i; - break; - } - i++; - } - - return ret_val; -} - -/*! \brief Returns the reference of the job that is identified by the given resource object list. - * \param self Instance pointer - * \param resource_object_list[] Reference to array of references to INIC resource objects - * \return Reference to the desired job if the job was found, otherwise NULL. - */ -Xrm_Job_t * Xrmp_GetJob(CXrmPool * self, UCS_XRM_CONST Ucs_Xrm_ResObject_t * resource_object_list[]) -{ - uint8_t i; - Xrm_Job_t *ret_ptr = NULL; - - for(i=0U; i<(uint8_t)XRM_NUM_JOBS; i++) - { - if(self->job_list[i].resource_object_list_ptr == resource_object_list) - { - ret_ptr = &self->job_list[i]; - break; - } - else if((self->job_list[i].resource_object_list_ptr == NULL) && (ret_ptr == NULL)) - { - ret_ptr = &self->job_list[i]; - } - } - - return ret_ptr; -} - -/*! \brief Calls the given function for each node in the resource list. If the func_ptr - * returns true the loop is stopped. - * \param self Instance pointer - * \param func_ptr Reference of the callback function which is called for each node - * \param user_data_ptr1 Reference of optional user data 1 pass to func_ptr - * \param user_data_ptr2 Reference of optional user data 2 pass to func_ptr - * \param user_data_ptr3 Reference of optional user data 3 pass to func_ptr - */ -void Xrmp_Foreach(CXrmPool *self, Xrmp_ForeachFunc_t func_ptr, void *user_data_ptr1, void *user_data_ptr2, void *user_data_ptr3) -{ - uint8_t j; - - for(j=0U; j<XRM_NUM_RESOURCE_HANDLES; j++) - { - if (self->resource_handle_list[j].job_ptr != NULL) - { - if (func_ptr(&self->resource_handle_list[j], user_data_ptr1, user_data_ptr2, user_data_ptr3) != false) - { - break; - } - } - } -} - -/*! - * @} - * \endcond - */ - -/*------------------------------------------------------------------------------------------------*/ -/* End of file */ -/*------------------------------------------------------------------------------------------------*/ - |