Initial Commit
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_jobs.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 Job classes
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup  G_MGR
28  * @{
29  */
30
31 /*------------------------------------------------------------------------------------------------*/
32 /* Includes                                                                                       */
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_jobs.h"
35 #include "ucs_misc.h"
36 /*#include "ucs_scheduler.h"
37 #include "ucs_trace.h"*/
38
39 /*------------------------------------------------------------------------------------------------*/
40 /* Internal constants                                                                             */
41 /*------------------------------------------------------------------------------------------------*/
42 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." */
43
44 /*------------------------------------------------------------------------------------------------*/
45 /* Internal prototypes                                                                            */
46 /*------------------------------------------------------------------------------------------------*/
47 static void Jbs_Service(void *self);
48 static void Jbq_OnJobResult(void *self, void *data_ptr);
49 static bool Jbs_ForEachJbq(void *d_ptr, void *ud_ptr);
50 static bool Jbq_CheckState(CJobQ *self, CJob *job_ptr);
51
52 /*------------------------------------------------------------------------------------------------*/
53 /* CJobService Methods                                                                            */
54 /*------------------------------------------------------------------------------------------------*/
55 void Jbs_Ctor(CJobService *self, CBase *base_ptr)
56 {
57     MISC_MEM_SET(self, 0, sizeof(*self));
58
59     self->base_ptr = base_ptr;
60     Dl_Ctor(&self->list, base_ptr->ucs_user_ptr);
61     Srv_Ctor(&self->service, JBS_SRV_PRIO, self, &Jbs_Service);
62     (void)Scd_AddService(&self->base_ptr->scd, &self->service);
63 }
64
65 void Jbs_RegisterJobQ(CJobService *self, CDlNode *job_q_node)
66 {
67     Dl_InsertTail(&self->list, job_q_node);
68 }
69
70 void Jbs_TriggerEvent(CJobService *self, Srv_Event_t id)
71 {
72     Srv_SetEvent(&self->service, id);
73 }
74
75 static bool Jbs_ForEachJbq(void *d_ptr, void *ud_ptr)
76 {
77     Srv_Event_t *event_ptr = (Srv_Event_t*)ud_ptr;
78     CJobQ *jobQ_ptr = (CJobQ*)d_ptr;
79
80     if ((*event_ptr & Jbq_GetEventId(jobQ_ptr)) != 0U)
81     {
82         Jbq_Service(jobQ_ptr);
83     }
84
85     return false;   /* continue loop for all jobQs */
86 }
87
88 static void Jbs_Service(void *self)
89 {
90     CJobService *self_ = (CJobService *)self; 
91     Srv_Event_t event_mask;
92
93     Srv_GetEvent(&self_->service, &event_mask);             /* save and reset current events */
94     Srv_ClearEvent(&self_->service, event_mask);
95
96     Dl_Foreach(&self_->list, &Jbs_ForEachJbq, &event_mask); /* service jobQ with the corresponding event */
97 }
98
99
100 /*------------------------------------------------------------------------------------------------*/
101 /* CJobQ Methods                                                                                  */
102 /*------------------------------------------------------------------------------------------------*/
103 void Jbq_Ctor(CJobQ *self, CJobService *job_service_ptr, Srv_Event_t event_id, CJob *job_list[])
104 {
105     MISC_MEM_SET(self, 0, sizeof(*self));
106
107     self->job_service_ptr = job_service_ptr;
108     self->event_id = event_id;
109     self->job_list = job_list;
110     
111     self->index = 0U;
112     self->state = JOB_S_STOPPED;
113     self->result = JOB_R_NA;
114     
115     Dln_Ctor(&self->node, self);
116     Ssub_Ctor(&self->q_subject, 0U /*inst id*/);
117     Sobs_Ctor(&self->result_obs, self, &Jbq_OnJobResult);
118     Jbs_RegisterJobQ(self->job_service_ptr, &self->node);
119 }
120
121 Srv_Event_t Jbq_GetEventId(CJobQ *self)
122 {
123     return self->event_id;
124 }
125
126 void Jbq_Start(CJobQ *self, CSingleObserver *result_obs_ptr)
127 {
128     if (self->state != JOB_S_STARTED)
129     {
130         if (self->job_list[self->index] != NULL)
131         {
132             TR_INFO((0U, "[JBQ]", "Jbq_Start(): Starting job queue. Id: 0x%04X", 1U, self->event_id));
133             self->index = 0U;
134             self->state = JOB_S_STARTED;
135             self->result = JOB_R_NA;
136             (void)Ssub_AddObserver(&self->q_subject, result_obs_ptr);       /* register observer for finished queue */
137             Job_Start(self->job_list[self->index], &self->result_obs);      /* pass own observer for finished job */
138         }
139         else
140         {
141             TR_ERROR((0U, "[JBQ]", "Jbq_Start(): Invalid job list. Id: 0x%04X", 1U, self->event_id));
142         }
143     }
144     else
145     {
146         TR_ERROR((0U, "[JBQ]", "Jbq_Start(): JobQ already started. Id: 0x%04X", 1U, self->event_id));
147     }
148 }
149
150 void Jbq_Stop(CJobQ *self)
151 {
152     if (self->state == JOB_S_STARTED)
153     {
154         if (self->job_list[self->index] != NULL)
155         {
156             self->index = 0U;
157             self->state = JOB_S_STOPPED;
158             self->result = JOB_R_NA;
159             (void)Ssub_RemoveObserver(&self->q_subject);
160             Job_Stop(self->job_list[self->index]);
161         }
162     }
163 }
164
165
166 static void Jbq_OnJobResult(void *self, void *data_ptr)
167 {
168     CJobQ *self_ = (CJobQ *)self;
169     Job_Result_t *result_ptr = (Job_Result_t *)data_ptr;
170     
171     if (self_->state == JOB_S_STARTED)
172     {
173         TR_INFO((0U, "[JBQ]", "Jbq_OnJobResult(): Receiving job result. event_id=0x%04X, result=0x%02X", 2U, self_->event_id, *result_ptr));
174         Jbs_TriggerEvent(self_->job_service_ptr, self_->event_id);
175     }
176     else
177     {
178         TR_INFO((0U, "[JBQ]", "Jbq_OnJobResult(): Receiving job result for stopped job. Id: 0x%04X", 1U, self_->event_id));
179     }
180
181     MISC_UNUSED(result_ptr);
182 }
183
184
185 static bool Jbq_CheckState(CJobQ *self, CJob *job_ptr)
186 {
187     bool ret = false;
188
189     if (self->state == JOB_S_STARTED)
190     {
191         if (job_ptr != NULL)
192         {
193             if ((Job_GetState(job_ptr) == JOB_S_FINISHED) && (Job_GetResult(job_ptr) != JOB_R_NA))
194             {
195                 ret = true;     /* job attributes are correct -> process */
196             }
197         }
198         else
199         {
200             TR_ERROR((0U, "[JBQ]", "Jbq_Service(): Invalid job list. Id: 0x%04X", 1U, self->event_id));
201         }
202     }
203     else
204     {
205         TR_ERROR((0U, "[JBQ]", "Jbq_Service(): JobQ not started. Id: 0x%04X", 1U, self->event_id));
206     }
207
208     return ret;
209 }
210
211 void Jbq_Service(CJobQ *self)
212 {
213     CJob *curr_job_ptr = self->job_list[self->index];
214     CJob *next_job_ptr = self->job_list[self->index + 1U];
215
216     if (Jbq_CheckState(self, curr_job_ptr))
217     {
218         if (curr_job_ptr != NULL)
219         {
220             Job_Result_t tmp_res = Job_GetResult(curr_job_ptr);
221
222             if ((next_job_ptr != NULL) && (tmp_res == JOB_R_SUCCESS))   /* job successfully and next job available */
223             {
224                 self->index += 1U;
225                 Job_Start(next_job_ptr, &self->result_obs);
226             }
227             else        /* current job not successful or last job */
228             {
229                 self->result = tmp_res;                                 /* copy status from last job and finish */
230                 self->state = JOB_S_FINISHED;
231                 Ssub_Notify(&self->q_subject, &tmp_res, true/*auto-remove*/);
232             }
233         }
234     }
235 }
236
237 /*------------------------------------------------------------------------------------------------*/
238 /* CJob Methods                                                                                   */
239 /*------------------------------------------------------------------------------------------------*/
240
241 void Job_Ctor(CJob *self, Job_StartCb_t start_fptr, void *inst_ptr)
242 {
243     MISC_MEM_SET(self, 0, sizeof(*self));
244
245     self->start_fptr = start_fptr;
246     self->inst_ptr = inst_ptr;
247
248     self->state = JOB_S_STOPPED;
249     self->result = JOB_R_NA;
250     Ssub_Ctor(&self->subject, 0U /*ucs instance*/);
251 }
252
253 void Job_Start(CJob *self, CSingleObserver *result_obs_ptr)
254 {
255     if (self->state != JOB_S_STARTED)
256     {
257         TR_ASSERT(0U, "[JOB]", (self->start_fptr != NULL));
258         (void)Ssub_AddObserver(&self->subject, result_obs_ptr);
259         self->state = JOB_S_STARTED;
260         self->result = JOB_R_NA;
261
262         TR_INFO((0U, "[JOB]", "Job_Start(): starting job", 0U));
263         self->start_fptr(self->inst_ptr);
264     }
265     else
266     {
267         TR_INFO((0U, "[JOB]", "Job_Start(): ambiguous state during job start", 0U));
268     }
269 }
270
271 void Job_Stop(CJob *self)
272 {
273     self->state = JOB_S_STOPPED;
274     self->result = JOB_R_NA;
275     Ssub_RemoveObserver(&self->subject);
276     TR_INFO((0U, "[JOB]", "Job_Stop()", 0U));
277 }
278
279 void Job_SetResult(CJob *self, Job_Result_t result)
280 {
281     TR_INFO((0U, "[JOB]", "Job_SetResult(): result=%d", 1U, result));
282
283     if (self->state == JOB_S_STARTED)
284     {
285         self->state = JOB_S_FINISHED;
286         self->result = result;
287         Ssub_Notify(&self->subject, &result, true/*auto-remove*/);
288         MISC_UNUSED(self);
289         MISC_UNUSED(result);
290     }
291     else
292     {
293         TR_ERROR((0U, "[JOB]", "Job_SetResult(): called in ambiguous state=%d", 1U, self->state));
294     }
295 }
296
297 Job_State_t Job_GetState(CJob *self)
298 {
299     return self->state;
300 }
301
302 Job_Result_t Job_GetResult(CJob *self)
303 {
304     return self->result;
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 #if 0
324
325 /*------------------------------------------------------------------------------------------------*/
326 /* Initialization Methods                                                                         */
327 /*------------------------------------------------------------------------------------------------*/
328
329 /*! \brief Constructor of Manager class 
330  *  \param self         The instance
331  *  \param base_ptr     Reference to base component
332  *  \param inic_ptr     Reference to INIC component
333  *  \param net_ptr      Reference to net component
334  *  \param packet_bw    Desired packet bandwidth
335  */
336 void Mgr_Ctor(CManager *self, CBase *base_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr, uint16_t packet_bw)
337 {
338     MISC_MEM_SET(self, 0, sizeof(*self));
339
340     self->base_ptr = base_ptr;
341     self->inic_ptr = inic_ptr;
342     self->net_ptr = net_ptr;
343     self->packet_bw = packet_bw;
344
345     Srv_Ctor(&self->service, MGR_SRV_PRIO, self, &Mgr_Service);             /* register service */
346     (void)Scd_AddService(&self->base_ptr->scd, &self->service);
347
348     Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Mgr_OnInitComplete);
349     Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer);
350
351     Sobs_Ctor(&self->startup_obs, self, &Mgr_OnNwStartupResult);
352     Sobs_Ctor(&self->shutdown_obs, self, &Mgr_OnNwShutdownResult);
353     Mobs_Ctor(&self->nwstatus_mobs, self, MGR_NWSTATUS_MASK, &Mgr_OnNwStatus);
354     Fsm_Ctor(&self->fsm, self, &(mgr_state_tbl[0][0]), (uint8_t)MGR_EV_MAX_NUM_EVENTS, MGR_EV_NIL/*init.event*/);
355 }
356
357 #endif
358
359
360
361 /*!
362  * @}
363  * \endcond
364  */
365
366 /*------------------------------------------------------------------------------------------------*/
367 /* End of file                                                                                    */
368 /*------------------------------------------------------------------------------------------------*/
369