Merge pull request #2 from ronan22/master
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_net.c
1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491                                                                            */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG.                              */
4 /*                                                                                                */
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.                                                            */
9 /*                                                                                                */
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.                                                   */
14 /*                                                                                                */
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/>.                          */
17 /*                                                                                                */
18 /* You may also obtain this software under a propriety license from Microchip.                    */
19 /* Please contact Microchip for further information.                                              */
20 /*------------------------------------------------------------------------------------------------*/
21
22 /*!
23  * \file
24  * \brief Implementation of the Network Management.
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup G_NET
28  * @{
29  */
30
31 /*------------------------------------------------------------------------------------------------*/
32 /* Includes                                                                                       */
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_net.h"
35 #include "ucs_misc.h"
36 #include "ucs_trace.h"
37
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;
47
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." */
55
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);
62
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
69  */
70 void Net_Ctor(CNetworkManagement *self, Net_InitData_t *init_ptr)
71 {
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);
80
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);
86
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 */
89 }
90
91 /*! \brief Service function of the network management.
92  *  \param self    Instance pointer
93  */
94 static void Net_Service(void *self)
95 {
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)
101     {
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);
108     }
109     /* Notification of MOST Network Configuration triggered? */
110     if((event_mask & NET_EVENT_NOTIFY_NW_CONFIG) == NET_EVENT_NOTIFY_NW_CONFIG)
111     {
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);
118     }
119 }
120
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
124  */
125 void Net_AddObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr)
126 {
127     (void)Msub_AddObserver(&self->network_status.pre_subject, obs_ptr);
128     Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_STATUS);
129 }
130
131 /*! \brief Removes an observer registered by Net_AddObserverNetworkStatus().
132  *  \param self        Instance pointer
133  *  \param obs_ptr     Reference to observer to be removed
134
135  */
136 void Net_DelObserverNetworkStatus(CNetworkManagement *self, CMaskedObserver *obs_ptr)
137 {
138     (void)Msub_RemoveObserver(&self->network_status.pre_subject, obs_ptr);
139     (void)Msub_RemoveObserver(&self->network_status.subject, obs_ptr);
140 }
141
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
145  */
146 void Net_AddObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr)
147 {
148     (void)Msub_AddObserver(&self->network_configuration.pre_subject, obs_ptr);
149     Srv_SetEvent(&self->net_srv, NET_EVENT_NOTIFY_NW_CONFIG);
150 }
151
152 /*! \brief Removes an observer registered by Net_AddObserverNetworkConfig().
153  *  \param self        Instance pointer
154  *  \param obs_ptr     Reference to observer to be removed
155  */
156 void Net_DelObserverNetworkConfig(CNetworkManagement *self, CMaskedObserver *obs_ptr)
157 {
158     (void)Msub_RemoveObserver(&self->network_configuration.pre_subject, obs_ptr);
159     (void)Msub_RemoveObserver(&self->network_configuration.subject, obs_ptr);
160 }
161
162 /*! \brief Observer callback used for the MOST Network Status
163  *  \param self        Instance pointer
164  *  \param data_ptr    Reference to the data structure
165  */
166 static void Net_UpdateNetworkStatus(void *self, void *data_ptr)
167 {
168     Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr;
169
170     if(data_ptr_->result.code == UCS_RES_SUCCESS)
171     {
172         CNetworkManagement *self_ = (CNetworkManagement *)self;
173         Inic_NetworkStatus_t result = *((Inic_NetworkStatus_t *)data_ptr_->data_info);
174
175         /* Check for changes */
176         if(result.events != 0U)     /* Notify only if at least one event flag is set */
177         {
178             self_->network_status.param.change_mask |= 0x0001U;
179         }
180         if(self_->network_status.param.availability != result.availability)
181         {
182             self_->network_status.param.change_mask |= 0x0002U;
183         }
184         if(self_->network_status.param.avail_info != result.avail_info)
185         {
186             self_->network_status.param.change_mask |= 0x0004U;
187         }
188         if(self_->network_status.param.avail_trans_cause != result.avail_trans_cause)
189         {
190             self_->network_status.param.change_mask |= 0x0008U;
191         }
192         if(self_->network_status.param.node_address != result.node_address)
193         {
194             self_->network_status.param.change_mask |= 0x0010U;
195         }
196         if(self_->network_status.param.node_position != result.node_position)
197         {
198             self_->network_status.param.change_mask |= 0x0020U;
199         }
200         if(self_->network_status.param.max_position != result.max_position)
201         {
202             self_->network_status.param.change_mask |= 0x0040U;
203         }
204         if(self_->network_status.param.packet_bw != result.packet_bw)
205         {
206             self_->network_status.param.change_mask |= 0x0080U;
207         }
208
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;
218
219         /* Notify observer? */
220         Msub_Notify(&self_->network_status.subject,
221                     &self_->network_status.param,
222                     (uint32_t)self_->network_status.param.change_mask);
223
224         /* Clear change-mask */
225         self_->network_status.param.change_mask = 0U;
226     }
227 }
228
229 /*! \brief Observer callback used for the MOST Network Configuration
230  *  \param self        Instance pointer
231  *  \param data_ptr    Reference to the data structure
232  */
233 static void Net_UpdateNetworkConfiguration(void *self, void *data_ptr)
234 {
235     Inic_StdResult_t *data_ptr_ = (Inic_StdResult_t *)data_ptr;
236
237     if(data_ptr_->result.code == UCS_RES_SUCCESS)
238     {
239         CNetworkManagement *self_ = (CNetworkManagement *)self;
240         Inic_NetworkConfig_t result = *((Inic_NetworkConfig_t *)data_ptr_->data_info);
241
242         /* Check for changes */
243         if(self_->network_configuration.param.node_address != result.node_address)
244         {
245             self_->network_configuration.param.change_mask |= 0x0001U;
246         }
247         if(self_->network_configuration.param.group_address != result.group_address)
248         {
249             self_->network_configuration.param.change_mask |= 0x0002U;
250         }
251         if(self_->network_configuration.param.llrbc != result.llrbc)
252         {
253             self_->network_configuration.param.change_mask |= 0x0004U;
254         }
255
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;
260
261         /* Notify observer? */
262         Msub_Notify(&self_->network_configuration.subject,
263                     &self_->network_configuration.param,
264                     (uint32_t)self_->network_configuration.param.change_mask);
265
266         /* Clear change-mask */
267         self_->network_configuration.param.change_mask = 0U;
268     }
269 }
270
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
280  */
281 Net_IsOwnAddrResult_t Net_IsOwnAddress(CNetworkManagement *self, uint16_t address)
282 {
283     Net_IsOwnAddrResult_t ret_val;
284
285     if((self->network_status.param.node_address == address) ||
286        (((uint16_t)self->network_status.param.node_position + (uint16_t)0x400) == address))
287     {
288         ret_val = NET_IS_OWN_ADDR_NODE;
289     }
290     else if(self->network_configuration.param.group_address == address)
291     {
292         ret_val = NET_IS_OWN_ADDR_GROUP;
293     }
294     else
295     {
296         ret_val = NET_IS_OWN_ADDR_NONE; 
297     }
298
299     return ret_val;
300 }
301
302 /*!
303  * @}
304  * \endcond
305  */
306
307 /*------------------------------------------------------------------------------------------------*/
308 /* End of file                                                                                    */
309 /*------------------------------------------------------------------------------------------------*/
310