diff options
Diffstat (limited to 'ucs2-lib/src/ucs_net.c')
-rw-r--r-- | ucs2-lib/src/ucs_net.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_net.c b/ucs2-lib/src/ucs_net.c new file mode 100644 index 0000000..4e4b274 --- /dev/null +++ b/ucs2-lib/src/ucs_net.c @@ -0,0 +1,310 @@ +/*------------------------------------------------------------------------------------------------*/ +/* 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 */ +/*------------------------------------------------------------------------------------------------*/ + |