1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491 */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
5 /* This program is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 2 of the License, or */
8 /* (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* You may also obtain this software under a propriety license from Microchip. */
19 /* Please contact Microchip for further information. */
20 /*------------------------------------------------------------------------------------------------*/
24 * \brief Implementation of the Network Management.
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
36 #include "ucs_trace.h"
38 /*------------------------------------------------------------------------------------------------*/
39 /* Service parameters */
40 /*------------------------------------------------------------------------------------------------*/
41 /*! Priority of the NET service used by scheduler */
42 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." */
43 /*! \brief Event to trigger notification of MOST Network Status */
44 static const Srv_Event_t NET_EVENT_NOTIFY_NW_STATUS = 1U;
45 /*! \brief Event to trigger notification of MOST Network Configuration */
46 static const Srv_Event_t NET_EVENT_NOTIFY_NW_CONFIG = 2U;
48 /*------------------------------------------------------------------------------------------------*/
49 /* Internal constants */
50 /*------------------------------------------------------------------------------------------------*/
51 /*! \brief Default value used for INIC sender handles */
52 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." */
53 /*! \brief Initialization timeout in milliseconds (t = 7s) */
54 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." */
56 /*------------------------------------------------------------------------------------------------*/
57 /* Internal prototypes */
58 /*------------------------------------------------------------------------------------------------*/
59 static void Net_Service(void *self);
60 static void Net_UpdateNetworkStatus(void *self, void *data_ptr);
61 static void Net_UpdateNetworkConfiguration(void *self, void *data_ptr);
63 /*------------------------------------------------------------------------------------------------*/
64 /* Implementation of class CNetworkManagement */
65 /*------------------------------------------------------------------------------------------------*/
66 /*! \brief Constructor of the Network Management class.
67 * \param self Instance pointer
68 * \param init_ptr Reference to the initialization data
70 void Net_Ctor(CNetworkManagement *self, Net_InitData_t *init_ptr)
72 MISC_MEM_SET(self, 0, sizeof(*self));
73 self->base_ptr = init_ptr->base_ptr;
74 self->inic_ptr = init_ptr->inic_ptr;
75 Obs_Ctor(&self->network_status.observer, self, &Net_UpdateNetworkStatus);
76 Inic_AddObsrvNwStatus(self->inic_ptr, &self->network_status.observer);
77 self->network_status.param.change_mask = 0xFFFFU; /* Used for initial notification! */
78 Sub_Ctor(&self->network_status.pre_subject, self->base_ptr->ucs_user_ptr);
79 Sub_Ctor(&self->network_status.subject, self->base_ptr->ucs_user_ptr);
81 Obs_Ctor(&self->network_configuration.observer, self, &Net_UpdateNetworkConfiguration);
82 Inic_AddObsvrNwConfig(self->inic_ptr, &self->network_configuration.observer);
83 self->network_configuration.param.change_mask = 0xFFFFU; /* Used for initial notification! */
84 Sub_Ctor(&self->network_configuration.pre_subject, self->base_ptr->ucs_user_ptr);
85 Sub_Ctor(&self->network_configuration.subject, self->base_ptr->ucs_user_ptr);
87 Srv_Ctor(&self->net_srv, NET_SRV_PRIO, self, &Net_Service); /* Initialize Network Management service */
88 (void)Scd_AddService(&self->base_ptr->scd, &self->net_srv); /* Add NET service to scheduler */
91 /*! \brief Service function of the network management.
92 * \param self Instance pointer
94 static void Net_Service(void *self)
96 CNetworkManagement *self_ = (CNetworkManagement *)self;
97 Srv_Event_t event_mask;
98 Srv_GetEvent(&self_->net_srv, &event_mask);
99 /* Notification of MOST Network Status triggered? */
100 if((event_mask & NET_EVENT_NOTIFY_NW_STATUS) == NET_EVENT_NOTIFY_NW_STATUS)
102 Srv_ClearEvent(&self_->net_srv, NET_EVENT_NOTIFY_NW_STATUS);
103 self_->network_status.param.change_mask = 0xFFFFU;
104 Sub_Notify(&self_->network_status.pre_subject, &self_->network_status.param);
105 self_->network_status.param.change_mask = 0U;
106 (void)Sub_SwitchObservers(&self_->network_status.subject,
107 &self_->network_status.pre_subject);
109 /* Notification of MOST Network Configuration triggered? */
110 if((event_mask & NET_EVENT_NOTIFY_NW_CONFIG) == NET_EVENT_NOTIFY_NW_CONFIG)
112 Srv_ClearEvent(&self_->net_srv, NET_EVENT_NOTIFY_NW_CONFIG);
113 self_->network_configuration.param.change_mask = 0xFFFFU;
114 Sub_Notify(&self_->network_configuration.pre_subject, &self_->network_configuration.param);
115 self_->network_configuration.param.change_mask = 0U;
116 (void)Sub_SwitchObservers(&self_->network_configuration.subject,
117 &self_->network_configuration.pre_subject);
121 /*! \brief Adds an observer which is called if the network status has been changed.
122 * \param self Instance pointer
123 * \param obs_ptr Reference to an observer
125 void Net_AddObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr)
127 (void)Msub_AddObserver(&self->network_status.pre_subject, obs_ptr);
128 Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_STATUS);
131 /*! \brief Removes an observer registered by Net_AddObserverNetworkStatus().
132 * \param self Instance pointer
133 * \param obs_ptr Reference to observer to be removed
136 void Net_DelObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr)
138 (void)Msub_RemoveObserver(&self->network_status.pre_subject, obs_ptr);
139 (void)Msub_RemoveObserver(&self->network_status.subject, obs_ptr);
142 /*! \brief Adds an observer which is called if the network configuration has been changed.
143 * \param self Instance pointer
144 * \param obs_ptr Reference to an observer
146 void Net_AddObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr)
148 (void)Msub_AddObserver(&self->network_configuration.pre_subject, obs_ptr);
149 Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_CONFIG);
152 /*! \brief Removes an observer registered by Net_AddObserverNetworkConfig().
153 * \param self Instance pointer
154 * \param obs_ptr Reference to observer to be removed
156 void Net_DelObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr)
158 (void)Msub_RemoveObserver(&self->network_configuration.pre_subject, obs_ptr);
159 (void)Msub_RemoveObserver(&self->network_configuration.subject, obs_ptr);
162 /*! \brief Observer callback used for the MOST Network Status
163 * \param self Instance pointer
164 * \param data_ptr Reference to the data structure
166 static void Net_UpdateNetworkStatus(void *self, void *data_ptr)
168 Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr;
170 if(data_ptr_->result.code == UCS_RES_SUCCESS)
172 CNetworkManagement *self_ = (CNetworkManagement *)self;
173 Inic_NetworkStatus_t result = *((Inic_NetworkStatus_t *)data_ptr_->data_info);
175 /* Check for changes */
176 if(result.events != 0U) /* Notify only if at least one event flag is set */
178 self_->network_status.param.change_mask |= 0x0001U;
180 if(self_->network_status.param.availability != result.availability)
182 self_->network_status.param.change_mask |= 0x0002U;
184 if(self_->network_status.param.avail_info != result.avail_info)
186 self_->network_status.param.change_mask |= 0x0004U;
188 if(self_->network_status.param.avail_trans_cause != result.avail_trans_cause)
190 self_->network_status.param.change_mask |= 0x0008U;
192 if(self_->network_status.param.node_address != result.node_address)
194 self_->network_status.param.change_mask |= 0x0010U;
196 if(self_->network_status.param.node_position != result.node_position)
198 self_->network_status.param.change_mask |= 0x0020U;
200 if(self_->network_status.param.max_position != result.max_position)
202 self_->network_status.param.change_mask |= 0x0040U;
204 if(self_->network_status.param.packet_bw != result.packet_bw)
206 self_->network_status.param.change_mask |= 0x0080U;
209 /* Update MOST Network Status parameters */
210 self_->network_status.param.events = result.events;
211 self_->network_status.param.availability = result.availability;
212 self_->network_status.param.avail_info = result.avail_info;
213 self_->network_status.param.avail_trans_cause = result.avail_trans_cause;
214 self_->network_status.param.node_address = result.node_address;
215 self_->network_status.param.node_position = result.node_position;
216 self_->network_status.param.max_position = result.max_position;
217 self_->network_status.param.packet_bw = result.packet_bw;
219 /* Notify observer? */
220 Msub_Notify(&self_->network_status.subject,
221 &self_->network_status.param,
222 (uint32_t)self_->network_status.param.change_mask);
224 /* Clear change-mask */
225 self_->network_status.param.change_mask = 0U;
229 /*! \brief Observer callback used for the MOST Network Configuration
230 * \param self Instance pointer
231 * \param data_ptr Reference to the data structure
233 static void Net_UpdateNetworkConfiguration(void *self, void *data_ptr)
235 Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr;
237 if(data_ptr_->result.code == UCS_RES_SUCCESS)
239 CNetworkManagement *self_ = (CNetworkManagement *)self;
240 Inic_NetworkConfig_t result = *((Inic_NetworkConfig_t *)data_ptr_->data_info);
242 /* Check for changes */
243 if(self_->network_configuration.param.node_address != result.node_address)
245 self_->network_configuration.param.change_mask |= 0x0001U;
247 if(self_->network_configuration.param.group_address != result.group_address)
249 self_->network_configuration.param.change_mask |= 0x0002U;
251 if(self_->network_configuration.param.llrbc != result.llrbc)
253 self_->network_configuration.param.change_mask |= 0x0004U;
256 /* Update MOST Network Configuration parameters */
257 self_->network_configuration.param.node_address = result.node_address;
258 self_->network_configuration.param.group_address = result.group_address;
259 self_->network_configuration.param.llrbc = result.llrbc;
261 /* Notify observer? */
262 Msub_Notify(&self_->network_configuration.subject,
263 &self_->network_configuration.param,
264 (uint32_t)self_->network_configuration.param.change_mask);
266 /* Clear change-mask */
267 self_->network_configuration.param.change_mask = 0U;
271 /*! \brief Checks if the given address matches with the own node address, node position or group address.
272 * \param self Instance pointer
273 * \param address Address to be checked
274 * \return Possible return values are shown in the table below.
275 * Value | Description
276 * --------------------- | -------------------------------------------------------------
277 * NET_IS_OWN_ADDR_NODE | Is own node position address or own logical node address
278 * NET_IS_OWN_ADDR_GROUP | Is own group address
279 * NET_IS_OWN_ADDR_NONE | Is foreign address
281 Net_IsOwnAddrResult_t Net_IsOwnAddress(CNetworkManagement *self, uint16_t address)
283 Net_IsOwnAddrResult_t ret_val;
285 if((self->network_status.param.node_address == address) ||
286 (((uint16_t)self->network_status.param.node_position + (uint16_t)0x400) == address))
288 ret_val = NET_IS_OWN_ADDR_NODE;
290 else if(self->network_configuration.param.group_address == address)
292 ret_val = NET_IS_OWN_ADDR_GROUP;
296 ret_val = NET_IS_OWN_ADDR_NONE;
307 /*------------------------------------------------------------------------------------------------*/
309 /*------------------------------------------------------------------------------------------------*/