Use latest version of conf.d/templates submodule.
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_xrm.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 Extended Resource Manager. This file contains the implementation of 
25  *        the basic functions of the class CExtendedResourceManager.
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup G_UCS_XRM_INT
28  * @{
29  */
30
31 /*------------------------------------------------------------------------------------------------*/
32 /* Includes                                                                                       */
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_xrm.h"
35 #include "ucs_xrm_pv.h"
36 #include "ucs_misc.h"
37
38 /*------------------------------------------------------------------------------------------------*/
39 /* Service parameters                                                                             */
40 /*------------------------------------------------------------------------------------------------*/
41 /*! Priority of the XRM service used by scheduler */
42 const uint8_t XRM_SRV_PRIO = 250U;   /* parasoft-suppress  MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
43 /*! \brief Event to trigger Extended Resource Manager service */
44 const Srv_Event_t XRM_EVENT_PROCESS              = 0x01U;
45 /*! \brief Event to trigger error handling */
46 const Srv_Event_t XRM_EVENT_ERROR                = 0x02U;
47 /*! \brief Event to trigger request list of invalid resource handles */
48 const Srv_Event_t XRM_EVENT_REQ_INV_RES_LST      = 0x04U;
49 /*! \brief Event to trigger destruction of invalid resources */
50 const Srv_Event_t XRM_EVENT_DESTROY_INV_RES      = 0x08U;
51 /*! \brief Event to resume the destruction of resources */
52 const Srv_Event_t XRM_EVENT_RESUME_JOB_DESTRUCT  = 0x10U;
53 /*! \brief Event to reset INIC's Resource Monitor */
54 const Srv_Event_t XRM_EVENT_RESET_RES_MONITOR    = 0x20U;
55 /*! \brief Event to trigger notification for automatically destroyed resources */
56 const Srv_Event_t XRM_EVENT_NOTIFY_AUTO_DEST_RES = 0x40U;
57 /*! \brief Event to trigger notification for destroyed resources */
58 const Srv_Event_t XRM_EVENT_NOTIFY_DESTROYED_JOB = 0x80U;
59 /*! \brief Event to trigger notification for automatically destroyed resources on remote devices */
60 const Srv_Event_t XRM_EVENT_NOTIFY_AUTO_DEST_RESR   = 0x100U;
61 /*! \brief Event to trigger configuration of a stream port */
62 const Srv_Event_t XRM_EVENT_STREAMPORT_CONFIG_SET   = 0x200U;
63 /*! \brief Event to read configuration of a stream port */
64 const Srv_Event_t XRM_EVENT_STREAMPORT_CONFIG_GET   = 0x400U;
65
66 /*------------------------------------------------------------------------------------------------*/
67 /* Internal Constants                                                                             */
68 /*------------------------------------------------------------------------------------------------*/
69 /*! \brief Invalid resource handle */
70 const uint16_t XRM_INVALID_RESOURCE_HANDLE  = 0xFFFFU;
71 /*! \brief Invalid MOST connection label */
72 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." */
73 /*! \brief Default value used for INIC sender handles */
74 const uint16_t XRM_DEFAULT_SENDER_HANDLE    = 0x0001U;
75 /*! \brief Invalid device node address */
76 const uint16_t XRM_INVALID_NODE_ADDRESS     = 0x0000U; 
77 /*! \brief Mask for network availability info */
78 const uint16_t XRM_MASK_NETWORK_AVAILABILITY  = 0x0002U;
79 /*! \brief Mask for node address update info */
80 const uint16_t XRM_MASK_NETWORK_NODE_ADDRESS  = 0x0010U; 
81
82 /*------------------------------------------------------------------------------------------------*/
83 /* Implementation of class CExtendedResourceManager                                               */
84 /*------------------------------------------------------------------------------------------------*/
85 /*! \brief Constructor of the Extended Resource Manager class.
86  *  \param self     Instance pointer
87  *  \param data_ptr Data pointer (receive reference to MNS instance)
88  */
89 void Xrm_Ctor(CExtendedResourceManager *self, Xrm_InitData_t *data_ptr)
90 {
91     MISC_MEM_SET(self, 0, sizeof(CExtendedResourceManager));
92
93     /* Retrieve the initialization data */
94     self->net_ptr  = data_ptr->net_ptr;
95     self->base_ptr = data_ptr->base_ptr;
96     self->rsm_ptr  = data_ptr->rsm_ptr;
97     self->inic_ptr = data_ptr->inic_ptr;
98     self->xrmp_ptr = data_ptr->xrmp_ptr;
99     self->res_debugging_fptr = data_ptr->res_debugging_fptr;
100
101     /* Set the flag that indicates the run mode of the instance */
102     self->IsInRemoteControlMode = (UCS_ADDR_LOCAL_DEV != Inic_GetTargetAddress(self->inic_ptr)) ? true:false;
103
104     /* Initialize observers */
105     Obs_Ctor(&self->obs.tx_msg_obj_obs, self, &Xrm_MsgObjAvailCb);
106     Obs_Ctor(&self->obs.resource_monitor_obs, self, &Xrm_ResourceMonitorCb);
107     Sobs_Ctor(&self->obs.std_result_obs, self, &Xrm_StdResultCb);
108     Sobs_Ctor(&self->obs.resource_invalid_list_obs, self, &Xrm_RequestResourceListResultCb);
109     Sobs_Ctor(&self->obs.resource_destroy_obs, self, &Xrm_DestroyResourcesResultCb);
110     Sobs_Ctor(&self->obs.stream_port_config_obs, self, &Xrm_Stream_PortConfigResult);
111     Sobs_Ctor(&self->obs.most_port_enable_obs, self, &Xrm_Most_PortEnableResult);
112     Sobs_Ctor(&self->obs.most_port_en_full_str_obs, self, &Xrm_Most_PortEnFullStrResult);
113     Obs_Ctor(&self->obs.rsm_sync_lost_obs, self, &Xrm_RmtDevSyncLostCb);
114
115     /* Add observer to resource monitor subject */
116     Inic_AddObsrvResMonitor(self->inic_ptr, &self->obs.resource_monitor_obs);
117     /* Initialize callback pointer for unmute callback */
118     self->obs.check_unmute_fptr = data_ptr->check_unmute_fptr;
119
120     /* Add observer to the MNS termination event */
121     Mobs_Ctor(&self->obs.internal_error_obs, self, EH_M_TERMINATION_EVENTS, &Xrm_UninitializeService);
122     Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->obs.internal_error_obs);
123     /* Add observer to the MNS network event */
124     Mobs_Ctor(&self->obs.nw_status_obs, self, (XRM_MASK_NETWORK_AVAILABILITY | XRM_MASK_NETWORK_NODE_ADDRESS), &Xrm_MnsNwStatusInfosCb);
125     Net_AddObserverNetworkStatus(self->net_ptr, &self->obs.nw_status_obs);
126     /* Add observer to the MNS RSM event */
127     Rsm_AddObserver(self->rsm_ptr, &self->obs.rsm_sync_lost_obs);
128
129     /* Initialize the Jobs list queue */
130     Dl_Ctor(&self->job_list, self->base_ptr->ucs_user_ptr);
131
132     /* Initialize XRM service */
133     Srv_Ctor(&self->xrm_srv, XRM_SRV_PRIO, self, &Xrm_Service);
134     /* Add XRM service to scheduler */
135     (void)Scd_AddService(&self->base_ptr->scd, &self->xrm_srv);
136 }
137
138 /*! \brief Service function of the Extended Resource Manager.
139  *  \param self    Instance pointer
140  */
141 void Xrm_Service(void *self)
142 {
143     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
144     Srv_Event_t event_mask;
145     Srv_GetEvent(&self_->xrm_srv, &event_mask);
146
147     /* Handle event to process a XRM job */
148     if((event_mask & XRM_EVENT_PROCESS) == XRM_EVENT_PROCESS)
149     {
150         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_PROCESS);
151         Xrm_ProcessJob(self_);
152     }
153     /* Handle event to request the list of invalid resource handles */
154     if((event_mask & XRM_EVENT_REQ_INV_RES_LST) == XRM_EVENT_REQ_INV_RES_LST)
155     {
156         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_REQ_INV_RES_LST);
157         Xrm_RequestResourceList(self_);
158     }
159     /* Handle event to destroy invalid INIC resources */
160     if((event_mask & XRM_EVENT_DESTROY_INV_RES) == XRM_EVENT_DESTROY_INV_RES)
161     {
162         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_DESTROY_INV_RES);
163         Xrm_DestroyResources(self_, &Xrm_DestroyResourcesResultCb);
164     }
165     /* Handle event to resume the destruction of all INIC resources of a job */
166     if((event_mask & XRM_EVENT_RESUME_JOB_DESTRUCT) == XRM_EVENT_RESUME_JOB_DESTRUCT)
167     {
168         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_RESUME_JOB_DESTRUCT);
169         Xrm_ResumeJobDestruction(self_);
170     }
171     /* Handle event to resume the destruction of all INIC resources of a job */
172     if((event_mask & XRM_EVENT_RESET_RES_MONITOR) == XRM_EVENT_RESET_RES_MONITOR)
173     {
174         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_RESET_RES_MONITOR);
175         Xrm_ResetResourceMonitor(self_);
176     }
177     /* Handle error event */
178     if((event_mask & XRM_EVENT_ERROR) == XRM_EVENT_ERROR)
179     {
180         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_ERROR);
181         Xrm_HandleError(self_);
182     }
183     /* Handle event to notify application of automatically destroyed resources */
184     if((event_mask & XRM_EVENT_NOTIFY_AUTO_DEST_RES) == XRM_EVENT_NOTIFY_AUTO_DEST_RES)
185     {
186         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RES);
187         Xrm_ReportAutoDestructionResult(self_);
188     }
189     /* Handle event to report result of resource destruction of a specific XRM job */
190     if((event_mask & XRM_EVENT_NOTIFY_DESTROYED_JOB) == XRM_EVENT_NOTIFY_DESTROYED_JOB)
191     {
192         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_DESTROYED_JOB);
193         Xrm_ReportJobDestructionResult(self_);
194     }
195     /* Handle event to notify application that resources on remote devices have been automatically destroyed */
196     if ((event_mask & XRM_EVENT_NOTIFY_AUTO_DEST_RESR) == XRM_EVENT_NOTIFY_AUTO_DEST_RESR)
197     {
198         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR);
199         Xrm_ReleaseResrcHandles(self_);
200     }
201     /* Handle event to set streaming port configuration */
202     if ((event_mask & XRM_EVENT_STREAMPORT_CONFIG_SET) == XRM_EVENT_STREAMPORT_CONFIG_SET)
203     {
204         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_STREAMPORT_CONFIG_SET);
205         (void)Xrm_SetStreamPortConfiguration(self_);
206     }
207     /* Handle event to get streaming port configuration */
208     if ((event_mask & XRM_EVENT_STREAMPORT_CONFIG_GET) == XRM_EVENT_STREAMPORT_CONFIG_GET)
209     {
210         Srv_ClearEvent(&self_->xrm_srv, XRM_EVENT_STREAMPORT_CONFIG_GET);
211         (void)Xrm_GetStreamPortConfiguration(self_);
212     }
213 }
214
215 /*! \brief Checks if the API is locked and the MNS are initialized.
216  *  \param self     Instance pointer
217  *  \return \c true if the API is not locked and the MNS are initialized, otherwise \c false.
218  */
219 bool Xrm_IsApiFree(CExtendedResourceManager *self)
220 {
221     return (self->lock_api == false);
222 }
223
224 /*! \brief Locks/Unlocks the XRM API.
225  *  \param self     Instance pointer
226  *  \param status   Locking status. \c true = Lock, \c false = Unlock
227  */
228 void Xrm_ApiLocking(CExtendedResourceManager *self, bool status)
229 {
230     self->lock_api = status;
231 }
232
233 /*! \brief  Add observer to be notified if ICM TX message object is available. Store pending events.
234  *  \param  self        Instance pointer
235  *  \param  event_mask  Event to be queued
236  */
237 void Xrm_WaitForTxMsgObj(CExtendedResourceManager *self, Srv_Event_t event_mask)
238 {
239     Inic_AddObsrvOnTxMsgObjAvail(self->inic_ptr, &self->obs.tx_msg_obj_obs);
240     self->queued_event_mask |= event_mask;
241 }
242
243 /*! \brief  Checks whether the given resource object list is part of the given Job
244  *  \param  job_ptr    Reference to a job list
245  *  \param  ud_ptr     Reference to the user data. Not used !
246  *  \return \c true if it's part of my job list, otherwise \c false.
247  */
248 bool Xrm_SetNtfForThisJob(void * job_ptr, void * ud_ptr)
249 {
250     Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr;
251     MISC_UNUSED(ud_ptr);
252
253     if(job_ptr_->valid != false)
254     {
255         job_ptr_->notify = true;
256     }
257
258     return false;
259 }
260
261 /*! \brief  Handle internal errors and un-initialize XRM service.
262  *  \param  self            Instance pointer
263  *  \param  error_code_ptr  Reference to internal error code
264  */
265 void Xrm_UninitializeService(void *self, void *error_code_ptr)
266 {
267     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
268     MISC_UNUSED(error_code_ptr);
269
270     Xrm_ApiLocking(self_, true);
271
272     MISC_MEM_SET(&self_->report_result, 0x00, sizeof(Ucs_Xrm_Result_t));
273     self_->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED;
274
275     (void)Dl_Foreach(&self_->job_list, &Xrm_SetNtfForThisJob, NULL);
276
277     /* Notify destruction of current connections */
278     Xrm_NotifyInvalidJobs(self_);
279     /* Remove XRM service from schedulers list */
280     (void)Scd_RemoveService(&self_->base_ptr->scd, &self_->xrm_srv);
281     /* Remove error/event observers */
282     Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->obs.internal_error_obs);
283     /* Remove rsm observers */
284     Rsm_DelObserver(self_->rsm_ptr, &self_->obs.rsm_sync_lost_obs);
285 }
286
287
288 /*! \brief  Handle the network status information mask "Availability" and "NodeAddress".
289  *  \param  self            Instance pointer
290  *  \param  result_ptr      Reference to the results
291  */
292 void Xrm_MnsNwStatusInfosCb(void *self, void *result_ptr)
293 {
294     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
295     Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)result_ptr;
296
297     if ((XRM_MASK_NETWORK_AVAILABILITY & result_ptr_->change_mask) == XRM_MASK_NETWORK_AVAILABILITY)
298     {
299         if ((result_ptr_->availability == UCS_NW_NOT_AVAILABLE)  &&
300             (self_->IsInRemoteControlMode))
301         {
302             /* Release all resources */
303             Xrm_ReleaseResrcHandles(self_);
304         }
305     }
306 }
307
308 /*! \brief  Whenever this function is called, a message object (ICM or MCM) is available.
309  *  \param  self        Instance pointer
310  *  \param  result_ptr  Not used!
311  */
312 void Xrm_MsgObjAvailCb(void *self, void *result_ptr)
313 {
314     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
315     MISC_UNUSED(result_ptr);
316     Srv_SetEvent(&self_->xrm_srv, self_->queued_event_mask);
317     self_->queued_event_mask = 0U;
318     Inic_DelObsrvOnTxMsgObjAvail(self_->inic_ptr, &self_->obs.tx_msg_obj_obs);
319 }
320
321 /*! \brief  Whenever this function is called, all remote devices have lost the synchronization.
322  *  \param  self        instance pointer 
323  *  \param  result_ptr  Not Used !
324  */
325 void Xrm_RmtDevSyncLostCb(void *self, void *result_ptr)
326 {
327     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
328     MISC_UNUSED(result_ptr);
329
330     Srv_SetEvent(&self_->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR);
331 }
332
333 /*! \brief Processes the XRM job that is specified by the given resource object list.
334  *  \param self                             Instance pointer
335  *  \param resource_object_list[]           Reference to array of references to INIC resource objects
336  *  \param most_network_connection_label    MOST network connection label
337  *  \param user_arg                         User argument
338  *  \param report_fptr                      Report function pointer
339  *  \return  Possible return values are shown in the table below.
340  *           Value                     | Description 
341  *           ------------------------- | ------------------------------------
342  *           UCS_RET_SUCCESS           | No error 
343  *           UCS_RET_ERR_NOT_AVAILABLE | Associated job not found
344  *           UCS_RET_ERR_PARAM         | Null pointer detected
345  *           UCS_RET_ERR_API_LOCKED    | API is currently locked
346  */
347 Ucs_Return_t Xrm_Process(CExtendedResourceManager *self, 
348                          UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[],
349                          uint16_t most_network_connection_label,
350                          void * user_arg,
351                          Ucs_Xrm_ReportCb_t report_fptr)
352 {
353     Ucs_Return_t ret_val = UCS_RET_SUCCESS;
354
355     if (self != NULL)
356     {
357         if(Xrm_IsApiFree(self) != false)
358         {
359             if((resource_object_list != NULL) && (report_fptr != NULL))
360             {
361                 Xrm_ApiLocking(self, true);
362                 self->current_job_ptr = Xrm_GetJob(self, resource_object_list);
363                 if(self->current_job_ptr != NULL)
364                 {
365                     bool job_is_mine = Dl_IsNodeInList(&self->job_list, &self->current_job_ptr->node);
366                     if (job_is_mine)
367                     {
368                         if(self->current_job_ptr->valid == false)
369                         {
370                             self->current_job_ptr->user_arg = user_arg;
371                             self->current_job_ptr->valid = true;
372                             self->current_job_ptr->notify = false;
373                             self->current_job_ptr->report_fptr = report_fptr;
374                             self->current_job_ptr->most_network_connection_label = most_network_connection_label;
375                             self->current_job_ptr->resource_object_list_ptr = resource_object_list;
376                             self->current_obj_pptr = &self->current_job_ptr->resource_object_list_ptr[0];
377                             Xrm_ProcessJob(self);
378                         }
379                         else
380                         {
381                             ret_val = UCS_RET_ERR_ALREADY_SET;
382                             Xrm_ApiLocking(self, false);
383                         }
384                     }
385                     else
386                     {
387                         ret_val = UCS_RET_ERR_PARAM;
388                         Xrm_ApiLocking(self, false);
389                     }
390                 }
391                 else
392                 {
393                     Xrm_ApiLocking(self, false);
394                     ret_val = UCS_RET_ERR_NOT_AVAILABLE;
395                 }
396             }
397             else
398             {
399                 ret_val = UCS_RET_ERR_PARAM;
400             }
401         }
402         else
403         {
404             ret_val = UCS_RET_ERR_API_LOCKED;
405         }
406     }
407     else
408     {
409         ret_val = UCS_RET_ERR_PARAM;
410     }
411
412     return ret_val;
413 }
414
415 /*! \brief   Destroys all resources that are specified by the given resource object list.
416  *  \details This function triggers the destruction of all resources which are used by the given
417  *           job. A resource will be destroyed only if it is not used by other valid resources.
418  *  \param   self                     Instance pointer
419  *  \param   resource_object_list[]   Reference to array of references to INIC resource objects
420  *  \return  Possible return values are shown in the table below.
421  *           Value                     | Description 
422  *           ------------------------- | ------------------------------------------------------
423  *           UCS_RET_SUCCESS           | No error
424  *           UCS_RET_ERR_ALREADY_SET   | Connection is already destroyed
425  *           UCS_RET_ERR_NOT_AVAILABLE | Associated job not found
426  *           UCS_RET_ERR_PARAM         | Null pointer detected
427  *           UCS_RET_ERR_API_LOCKED    | API is currently locked
428  */
429 Ucs_Return_t Xrm_Destroy(CExtendedResourceManager *self,
430                          UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[])
431 {
432     Ucs_Return_t ret_val = UCS_RET_SUCCESS;
433
434     if (self != NULL)
435     {
436         if(Xrm_IsApiFree(self) != false)
437         {
438             if(resource_object_list != NULL)
439             {
440                 Xrm_ApiLocking(self, true);
441                 self->current_job_ptr = Xrm_GetJob(self, resource_object_list);
442                 if((self->current_job_ptr != NULL) &&
443                    (self->current_job_ptr->resource_object_list_ptr != NULL))
444                 {
445                     Xrm_PreJobDestrResult_t result;
446
447                     result = Xrm_PrepareJobDestruction(self);
448                     if(result == XRM_PRE_JOB_DEST_TASKS_EXIST)
449                     {
450                         Xrm_DestroyResources(self, &Xrm_DestroyJobResourcesResultCb);
451                     }
452                     else if(result == XRM_PRE_JOB_DEST_DONE)
453                     {
454                         Srv_SetEvent(&self->xrm_srv, XRM_EVENT_NOTIFY_DESTROYED_JOB);
455                     }
456                     else if (result == XRM_PRE_JOB_DEST_BUSY)
457                     {
458                         Xrm_ApiLocking(self, false);
459                         ret_val = UCS_RET_ERR_API_LOCKED;
460                     }
461                     else
462                     {
463                         Xrm_ApiLocking(self, false);
464                         ret_val = UCS_RET_ERR_ALREADY_SET;
465                     }
466                 }
467                 else
468                 {
469                     Xrm_ApiLocking(self, false);
470                     ret_val = UCS_RET_ERR_NOT_AVAILABLE;
471                 }
472             }
473             else
474             {
475                 ret_val = UCS_RET_ERR_PARAM;
476             }
477         }
478         else
479         {
480             ret_val = UCS_RET_ERR_API_LOCKED;
481         }
482     }
483     else
484     {
485         /* This means that there is no instance associated to this job,
486          * what in turn means that the job is not available. 
487          */
488         ret_val = UCS_RET_ERR_NOT_AVAILABLE;
489     }
490
491     return ret_val;
492 }
493
494 /*! \brief  Prepares the destruction of INIC resources of the current job.
495  *  \param  self    Instance pointer
496  *  \return  Possible return values are shown in the table below.
497  *           Value                           | Description 
498  *           ------------------------------- | ------------------------------------
499  *           XRM_PRE_JOB_DEST_TASKS_EXIST    | There are resources to destroy
500  *           XRM_PRE_JOB_DEST_NO_TASKS_EXIST | All resources already destroyed
501  *           XRM_PRE_JOB_DEST_DONE           | Only shared resources affected. Invoke result callback immediately
502  *           XRM_PRE_JOB_DEST_BUSY           | Preparation of JobDestruction is currently not possible. Other resources are currently being destroyed
503  */
504 Xrm_PreJobDestrResult_t Xrm_PrepareJobDestruction(CExtendedResourceManager *self)
505 {
506     Xrm_PreJobDestrResult_t ret_val = XRM_PRE_JOB_DEST_BUSY;
507     if (self->inv_resource_handle_list_size == 0U)
508     {
509         ret_val = Xrm_UnsafePrepareJobDestruction(self);
510     }
511     return ret_val;
512 }
513
514 /*! \brief  Prepares precariously the destruction of INIC resources of the current job (This was legacy code and is unsafe).
515  *  \param  self    Instance pointer
516  *  \return  Possible return values are shown in the table below.
517  *           Value                           | Description 
518  *           ------------------------------- | ------------------------------------
519  *           XRM_PRE_JOB_DEST_TASKS_EXIST    | There are resources to destroy
520  *           XRM_PRE_JOB_DEST_NO_TASKS_EXIST | All resources already destroyed
521  *           XRM_PRE_JOB_DEST_DONE           | Only shared resources affected. Invoke result callback immediately
522  */
523 Xrm_PreJobDestrResult_t Xrm_UnsafePrepareJobDestruction(CExtendedResourceManager *self)
524 {
525     uint8_t i;
526     uint16_t resource_handle;
527     Xrm_PreJobDestrResult_t ret_val = XRM_PRE_JOB_DEST_NO_TASKS_EXIST;
528     self->inv_resource_handle_index     = 0U;
529     self->inv_resource_handle_list_size = 0U;
530     for(i=Xrm_CountResourceObjects(self, self->current_job_ptr); (i>0U) && (self->inv_resource_handle_list_size < XRM_NUM_RES_HDL_PER_ICM); i--)
531     {
532         uint8_t count = Xrm_CountResourceHandleEntries(self, self->current_job_ptr->resource_object_list_ptr[i - 1U]);
533         if(count == 1U)
534         {
535             resource_handle = Xrm_GetResourceHandle(self, self->current_job_ptr, self->current_job_ptr->resource_object_list_ptr[i - 1U], NULL);
536             if(resource_handle != XRM_INVALID_RESOURCE_HANDLE)
537             {
538                 self->inv_resource_handle_list[self->inv_resource_handle_list_size] = resource_handle;
539                 self->inv_resource_handle_list_size++;
540                 ret_val = XRM_PRE_JOB_DEST_TASKS_EXIST;
541             }
542         }
543         else if(count > 0U)
544         {
545             Xrm_ReleaseResourceHandle(self, self->current_job_ptr, self->current_job_ptr->resource_object_list_ptr[i - 1U]);
546             ret_val = (ret_val == XRM_PRE_JOB_DEST_NO_TASKS_EXIST) ? XRM_PRE_JOB_DEST_DONE : ret_val;
547         }
548     }
549     return ret_val;
550 }
551
552
553 /*! \brief  Resumes the destruction of all resources of the current job.
554  *  \param  self    Instance pointer
555  */
556 void Xrm_ResumeJobDestruction(CExtendedResourceManager *self)
557 {
558     if(Xrm_UnsafePrepareJobDestruction(self) == XRM_PRE_JOB_DEST_TASKS_EXIST)
559     {
560         Xrm_DestroyResources(self, &Xrm_DestroyJobResourcesResultCb);
561     }
562     else
563     {
564         MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t));
565         self->report_result.code = UCS_XRM_RES_SUCCESS_DESTROY;
566         Xrm_NotifyInvalidJobs(self);
567         Xrm_ApiLocking(self, false);
568     }
569 }
570
571 /*! \brief  Returns the number of resource objects for the job that is identified by the given job
572  *          reference.
573  *  \param  self        Instance pointer
574  *  \param  job_ptr     Reference to job
575  *  \return Number of INIC resource objects of the desired job
576  */
577 uint8_t Xrm_CountResourceObjects(CExtendedResourceManager *self, Xrm_Job_t *job_ptr)
578 {
579     uint8_t num_resource_objects = 0U;
580     MISC_UNUSED(self);
581     while(job_ptr->resource_object_list_ptr[num_resource_objects] != NULL)
582     {
583         num_resource_objects++;
584     }
585
586     return num_resource_objects;
587 }
588
589 /*! \brief  Returns the reference of the job that is identified by the given resource object list.
590  *  \param  self                        Instance pointer
591  *  \param  resource_object_list[]      Reference to array of references to INIC resource objects
592  *  \return Reference to the desired job if the job was found, otherwise NULL.
593  */
594 Xrm_Job_t * Xrm_GetJob(CExtendedResourceManager *self,
595                        UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[])
596 {
597     Xrm_Job_t *ret_ptr = NULL;
598
599     ret_ptr = Xrmp_GetJob(self->xrmp_ptr, resource_object_list);
600     if (ret_ptr != NULL)
601     {
602         if ((!Dl_IsNodeInList(&self->job_list, &ret_ptr->node)) && 
603             (!Dln_IsNodePartOfAList(&ret_ptr->node)))
604         {
605             Dln_SetData(&ret_ptr->node, ret_ptr);
606             Dl_InsertTail(&self->job_list, &ret_ptr->node);
607         }
608     }
609
610     return ret_ptr;
611 }
612
613 /*! \brief  Checks whether the given resource object list is part of the given Job
614  *  \param  job_ptr           Reference to a job list
615  *  \param  resrc_obj_ptr     Reference to array of references to INIC resource objects
616  *  \return \c true if it's part of my job list, otherwise \c false.
617  */
618 bool Xrm_IsPartOfJobList (void * job_ptr, void * resrc_obj_ptr)
619 {
620     Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr;
621     bool ret_val = false;
622
623     if(job_ptr_->resource_object_list_ptr == (UCS_XRM_CONST Ucs_Xrm_ResObject_t **)resrc_obj_ptr)
624     {
625         ret_val = true;
626     }
627
628     return ret_val;
629 }
630
631 /*! \brief  Checks whether the given resource object list is part of my Job list
632  *  \param  self                        Instance pointer
633  *  \param  resource_object_list[]      Reference to array of references to INIC resource objects
634  *  \return \c true if it's part of my job list, otherwise \c false.
635  */
636 bool Xrm_IsInMyJobList(CExtendedResourceManager *self, UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_list[])
637 {
638     return (NULL != Dl_Foreach(&self->job_list, &Xrm_IsPartOfJobList, (void *)resource_object_list));
639 }
640
641 /*! \brief  Returns the table index of the given resource object.
642  *  \param  self        Instance pointer
643  *  \param  job_ptr     Reference to job
644  *  \param  obj_pptr    Reference to array of references to INIC resource objects
645  *  \return Table index of the given resource object. If entry is not found 0xFF is returned.
646  */
647 uint8_t Xrm_GetResourceObjectIndex(CExtendedResourceManager *self,
648                                    Xrm_Job_t *job_ptr,
649                                    UCS_XRM_CONST Ucs_Xrm_ResObject_t **obj_pptr)
650 {
651     return Xrmp_GetResourceHandleIdx(self->xrmp_ptr, job_ptr, obj_pptr);
652 }
653
654 /*! \brief  Check if the current device is already attached respectively sync'ed.
655  *  \param  self    Instance pointer
656  *  \return \c true if no error occurred, otherwise \c false.
657  */
658 bool Xrm_IsCurrDeviceAlreadyAttached(CExtendedResourceManager *self)
659 {
660     bool ret_val = true;
661
662     if (Rsm_GetDevState(self->rsm_ptr) == RSM_DEV_UNSYNCED)
663     {
664         ret_val = false;
665     }
666
667     return ret_val;
668 }
669
670 /*! \brief  Check if the current device is already attached respectively sync'ed.
671  *  \param  self    XRM Instance pointer
672  *  \param  job_ptr Reference to the XRM job to be looked for
673  *  \return \c true if the given job is part of my jobs_list, otherwise \c false.
674  */
675 bool Xrm_IsInMyJobsList (void * self, void * job_ptr)
676 {
677     CExtendedResourceManager *self_ = (CExtendedResourceManager *)self;
678     Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr;
679     bool ret_val = false;
680
681     if ((self_ != NULL) && (job_ptr_ != NULL) && 
682         (Dl_IsNodeInList(&self_->job_list, &job_ptr_->node)))
683     {
684         ret_val = true;
685     }
686
687     return ret_val;
688 }
689
690 /*! \brief  Search for the next resource object to process.
691  *  \param  self    Instance pointer
692  *  \return \c true if no error occurred, otherwise \c false.
693  */
694 bool Xrm_SearchNextResourceObject(CExtendedResourceManager *self)
695 {
696     uint16_t tmp_resource_handle;
697     bool ret_val = true;
698
699     while(*self->current_obj_pptr != NULL)
700     {
701         if(Xrm_IsDefaultCreatedPort(self, *self->current_obj_pptr) != false)
702         {
703             self->current_obj_pptr++;
704         }
705         else
706         {
707             tmp_resource_handle = Xrm_GetResourceHandle(self, NULL, *self->current_obj_pptr, &Xrm_IsInMyJobsList);
708             if(tmp_resource_handle == XRM_INVALID_RESOURCE_HANDLE)
709             {
710                 break;
711             }
712             else
713             {
714                 if(Xrm_GetResourceHandle(self, self->current_job_ptr, *self->current_obj_pptr, NULL) == XRM_INVALID_RESOURCE_HANDLE)
715                 {
716                     if(Xrm_StoreResourceHandle(self, tmp_resource_handle, self->current_job_ptr, *self->current_obj_pptr) == false)
717                     {
718                         self->report_result.code = UCS_XRM_RES_ERR_CONFIG;
719                         Xrm_HandleError(self);
720                         TR_ERROR((self->base_ptr->ucs_user_ptr, "[XRM]", "Misconfiguration. Resource handle list is too small.", 0U));
721                         ret_val = false;
722                     }
723                 }
724                 self->current_obj_pptr++;
725             }
726         }
727     }
728
729     return ret_val;
730 }
731
732 /*! \brief  Process the next INIC resource object in the resource object list of the current job.
733  *  \param  self    Instance pointer
734  */
735 void Xrm_ProcessJob(CExtendedResourceManager *self)
736 {
737     if(Xrm_SearchNextResourceObject(self) != false)
738     {
739         if(*self->current_obj_pptr != NULL)
740         {
741             if (Xrm_IsCurrDeviceAlreadyAttached(self) == false)
742             {
743                 (void)Xrm_RemoteDeviceAttach(self, XRM_EVENT_PROCESS);
744             }
745             else
746             {
747                 switch(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(*self->current_obj_pptr))
748                 {
749                     case UCS_XRM_RC_TYPE_MOST_SOCKET:
750                         Xrm_CreateMostSocket(self);
751                         break;
752                     case UCS_XRM_RC_TYPE_MLB_PORT:
753                         Xrm_CreateMlbPort(self);
754                         break;
755                     case UCS_XRM_RC_TYPE_MLB_SOCKET:
756                         Xrm_CreateMlbSocket(self);
757                         break;
758                     case UCS_XRM_RC_TYPE_USB_PORT:
759                         Xrm_CreateUsbPort(self);
760                         break;
761                     case UCS_XRM_RC_TYPE_USB_SOCKET:
762                         Xrm_CreateUsbSocket(self);
763                         break;
764                     case UCS_XRM_RC_TYPE_RMCK_PORT:
765                         Xrm_CreateRmckPort(self);
766                         break;
767                     case UCS_XRM_RC_TYPE_STRM_PORT:
768                         Xrm_CreateStreamPort(self);
769                         break;
770                     case UCS_XRM_RC_TYPE_STRM_SOCKET:
771                         Xrm_CreateStreamSocket(self);
772                         break;
773                     case UCS_XRM_RC_TYPE_SYNC_CON:
774                         Xrm_CreateSyncCon(self);
775                         break;
776                     case UCS_XRM_RC_TYPE_DFIPHASE_CON:
777                         Xrm_CreateDfiPhaseCon(self);
778                         break;
779                     case UCS_XRM_RC_TYPE_COMBINER:
780                         Xrm_CreateCombiner(self);
781                         break;
782                     case UCS_XRM_RC_TYPE_SPLITTER:
783                         Xrm_CreateSplitter(self);
784                         break;
785                     case UCS_XRM_RC_TYPE_AVP_CON:
786                         Xrm_CreateAvpCon(self);
787                         break;
788                     case UCS_XRM_RC_TYPE_QOS_CON:
789                         Xrm_CreateQoSCon(self);
790                         break;
791                     default:
792                         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)));
793                         self->report_result.code = UCS_XRM_RES_ERR_CONFIG;
794                         Xrm_HandleError(self);
795                         break;
796                 }
797             }
798         }
799         else
800         {
801             Xrm_FinishJob(self);
802         }
803     }
804 }
805
806 /*! \brief  Checks if the given resource object is from type "Default Created Port".
807  *  \param  self                    Instance pointer
808  *  \param  resource_object_ptr     Reference to the resource object
809  *  \return Returns \c true if resource object is from type "Default Created Port", otherwise \c false.
810  */
811 bool Xrm_IsDefaultCreatedPort(CExtendedResourceManager *self, UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr)
812 {
813     MISC_UNUSED(self);
814     return (*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resource_object_ptr) == UCS_XRM_RC_TYPE_DC_PORT);
815 }
816
817 /*! \brief  Stores the given resource handle in the resource handle list.
818  *  \param  self                Instance pointer
819  *  \param  resource_handle     Resource handle to save
820  *  \param  job_ptr             Reference to job
821  *  \param  resource_object_ptr Reference to resource object
822  *  \return \c true if free slot in handle list was found, otherwise \c false
823  */
824 bool Xrm_StoreResourceHandle(CExtendedResourceManager *self,
825                              uint16_t resource_handle,
826                              Xrm_Job_t *job_ptr,
827                              UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr)
828 {
829     return Xrmp_StoreResourceHandle(self->xrmp_ptr, resource_handle, job_ptr, resource_object_ptr);
830 }
831
832 /*! \brief  Retrieves the resource handle identified by the given job reference and the given
833  *          resource object reference.
834  *  \param  self                    Instance pointer
835  *  \param  job_ptr                 Reference to the job. Use NULL as wildcard.
836  *  \param  resource_object_ptr     Reference to the resource object
837  *  \param  func_ptr                Reference to a function that checks if found jobs by XRMP belongs to our own job list
838  *  \return Resource handle if handle was found, otherwise XRM_INVALID_RESOURCE_HANDLE.
839  */
840 uint16_t Xrm_GetResourceHandle(CExtendedResourceManager *self,
841                                Xrm_Job_t *job_ptr,
842                                UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr, Xrmp_CheckJobListFunc_t func_ptr)
843 {
844     return Xrmp_GetResourceHandle(self->xrmp_ptr, job_ptr, resource_object_ptr, func_ptr, self);
845 }
846
847 /*! \brief  Checks for the resource handle in the given resource handle list and counts It if found.
848  *  \param  resrc_ptr       Reference to the resource handle list to be looked for.
849  *  \param  job_ptr         Reference to the job list to be looked for.
850  *  \param  param_ptr       Reference to the user parameter.
851  *  \param  user_arg        Reference to the user argument.
852  *  \return \c false to continue the for-each-loop of the resources list queue.
853  */
854 bool Xrm_IncrResHandleEntryCnt (void *resrc_ptr, void *job_ptr, void *param_ptr, void * user_arg)
855 {
856     Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr;
857     Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr;
858     Xrm_CntEntriesResHandle_t * param_ptr_ = (Xrm_CntEntriesResHandle_t *)param_ptr;
859     MISC_UNUSED(user_arg);
860
861     if((resrc_ptr_->resource_handle != XRM_INVALID_RESOURCE_HANDLE) &&
862        (resrc_ptr_->job_ptr == job_ptr_) &&
863        (resrc_ptr_->resource_object_ptr == param_ptr_->resource_object_ptr))
864     {
865         (*param_ptr_->cnt_res)++;
866     }
867
868     return false;
869 }
870
871 /*! \brief  Finds the resource handle to be counted in my job list and pass it to the record callback function .
872  *  \param  job_ptr                 Reference to the job to be looked for.
873  *  \param  param_ptr               Reference to the user parameter.
874  *  \return \c false to continue the for-each-loop of the job_list queue
875  */
876 bool Xrm_CntResHandleEntries(void * job_ptr, void * param_ptr)
877 {
878     Xrm_CntEntriesResHandle_t * param_ptr_ = (Xrm_CntEntriesResHandle_t *)param_ptr;
879
880     Xrmp_Foreach(param_ptr_->xrm_inst->xrmp_ptr, &Xrm_IncrResHandleEntryCnt, job_ptr, param_ptr_, NULL);
881
882     return false;
883 }
884
885 /*! \brief  Retrieves the number of list entries that uses the given resource handle.
886  *  \param  self                    Instance pointer
887  *  \param  resource_object_ptr     Reference to the current resource object
888  *  \return Number of list entries
889  */
890 uint8_t Xrm_CountResourceHandleEntries(CExtendedResourceManager *self,
891                                        UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr)
892 {
893     uint8_t ret_val = 0U;
894     Xrm_CntEntriesResHandle_t cnt_entry_param;
895     cnt_entry_param.xrm_inst = self;
896     cnt_entry_param.cnt_res = &ret_val;
897     cnt_entry_param.resource_object_ptr = resource_object_ptr;
898
899     (void)Dl_Foreach(&self->job_list, &Xrm_CntResHandleEntries, &cnt_entry_param);
900
901     return ret_val;
902 }
903
904 /*! \brief  Releases the given resource handle.
905  *  \param  resrc_ptr       Reference to the resource handle list to be looked for.
906  *  \param  job_ptr         Reference to the job list to be looked for.
907  *  \param  resrc_obj_pptr  Reference to the resource object to be looked for.
908  *  \param  user_arg         Reference to the user argument
909  *  \return \c true to stop the foreach loop when the resource handle has been found, otherwise \c false
910  */
911 bool Xrm_ReleaseResrcHandle(void *resrc_ptr, void *job_ptr, void *resrc_obj_pptr, void * user_arg)
912 {
913     bool ret_val = false;
914     Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr;
915     Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr;
916     UCS_XRM_CONST Ucs_Xrm_ResObject_t *resrc_obj_ptr_ = *(UCS_XRM_CONST Ucs_Xrm_ResObject_t **)resrc_obj_pptr;
917     MISC_UNUSED(user_arg);
918
919     if((resrc_ptr_->job_ptr == job_ptr_) &&
920         (resrc_ptr_->resource_object_ptr == resrc_obj_ptr_))
921     {
922         resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE;
923         resrc_ptr_->job_ptr = NULL;
924         resrc_ptr_->resource_object_ptr = NULL;
925         ret_val = true;
926     }
927
928     return ret_val;
929 }
930
931 /*! \brief  Releases the given resource handle. Frees the corresponding table row.
932  *  \param  self                    Instance pointer
933  *  \param  job_ptr                 Reference to the job
934  *  \param  resource_object_ptr     Reference to the resource object
935  */
936 void Xrm_ReleaseResourceHandle(CExtendedResourceManager *self,
937                                Xrm_Job_t *job_ptr,
938                                UCS_XRM_CONST Ucs_Xrm_ResObject_t *resource_object_ptr)
939 {
940     void * resource_object_pptr = (void *)&resource_object_ptr;
941     Xrmp_Foreach(self->xrmp_ptr, &Xrm_ReleaseResrcHandle, job_ptr, resource_object_pptr, NULL);
942 }
943
944 /*! \brief  Releases the given resource and sets the notification to \c true.
945  *  \param  resrc_ptr       Reference to the resource handle list to be looked for.
946  *  \param  resrc_handle    Reference to the resource handle to be found.
947  *  \param  job_ptr         Reference to the job to be looked for.
948  *  \param  user_arg        Reference to a user argument.
949  *  \return \c false to continue the for-each-loop of the resources list table
950  */
951 bool Xrm_FreeResrcHandleAndNtf(void *resrc_ptr, void *resrc_handle, void *job_ptr, void * user_arg)
952 {
953     Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr;
954     uint16_t * resrc_handle_ = (uint16_t *)resrc_handle;
955     Xrm_Job_t * job_ptr_ = (Xrm_Job_t *)job_ptr;
956     CExtendedResourceManager *self = (CExtendedResourceManager *) user_arg;
957
958     if((resrc_ptr_->resource_handle == *resrc_handle_) &&
959        (*resrc_handle_ != XRM_INVALID_RESOURCE_HANDLE) &&
960        ((resrc_ptr_->job_ptr == job_ptr_) || 
961        (Dl_IsNodeInList(&self->job_list, &resrc_ptr_->job_ptr->node))))
962     {
963         resrc_ptr_->job_ptr->notify = true;
964         resrc_ptr_->job_ptr->valid = false;
965         resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE;
966         resrc_ptr_->job_ptr = NULL;
967
968         if (self->res_debugging_fptr != NULL)
969         {
970             self->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resrc_ptr_->resource_object_ptr),
971                 resrc_ptr_->resource_object_ptr, UCS_XRM_INFOS_DESTROYED, self->current_job_ptr->user_arg, self->base_ptr->ucs_user_ptr);
972         }
973
974         resrc_ptr_->resource_object_ptr = NULL;
975     }
976
977     return false;
978 }
979
980 /*! \brief  Releases all given resource handles. Frees the corresponding table rows. Marks the
981  *          corresponding job(s) as invalid and sets the notification flag.
982  *  \param  self                        Instance pointer
983  *  \param  job_ptr                     Reference to the job. Use NULL as wildcard.
984  *  \param  resource_handle_list        Resource handle list
985  *  \param  resource_handle_list_size   Size of list resource_handle_list[]
986  *  \param  failed_resource_handle      This parameter can be used to specify where the release
987  *                                      process has to be stopped. All resource handles prior to
988  *                                      the failed handle are released. If this feature is not
989  *                                      used \c failed_resource_handle must be set to 
990  *                                      \ref XRM_INVALID_RESOURCE_HANDLE.
991  *  \return the index of the resource where the release process has stopped.
992  */
993 uint8_t Xrm_ReleaseResourceHandles(CExtendedResourceManager *self,
994                                    Xrm_Job_t *job_ptr,
995                                    uint16_t resource_handle_list[],
996                                    uint8_t resource_handle_list_size,
997                                    uint16_t failed_resource_handle)
998 {
999     uint8_t i;
1000
1001     for(i=0U; i<resource_handle_list_size; i++)
1002     {
1003         if((failed_resource_handle != XRM_INVALID_RESOURCE_HANDLE) &&
1004            (resource_handle_list[i] == failed_resource_handle))
1005         {
1006             break;
1007         }
1008
1009         Xrmp_Foreach(self->xrmp_ptr, &Xrm_FreeResrcHandleAndNtf, &resource_handle_list[i], job_ptr, self);
1010     }
1011
1012     return i;
1013 }
1014
1015 /*! \brief  Releases all resource handles created on remote devices. Frees the corresponding table rows. Marks the
1016  *          corresponding job(s) as invalid and sets the notification flag.
1017  *  \param  self                        Instance pointer
1018  */
1019 void Xrm_ReleaseResrcHandles(CExtendedResourceManager *self)
1020 {
1021     if(Xrm_IsApiFree(self) != false)
1022     {
1023         Xrm_ApiLocking(self, true);
1024
1025         Xrm_MarkResrcAndJobsAsInvalid(self);
1026         Xrm_NotifyInvalidJobs(self);
1027         Xrm_ApiLocking(self, false);
1028     }
1029     else
1030     {
1031         Srv_SetEvent(&self->xrm_srv, XRM_EVENT_NOTIFY_AUTO_DEST_RESR);
1032     }
1033 }
1034
1035 /*! \brief  Handles and reports Extended Resource Manager errors.
1036  *  \param  self    Instance pointer
1037  */
1038 void Xrm_HandleError(CExtendedResourceManager *self)
1039 {
1040     self->current_job_ptr->valid = false;
1041     self->current_job_ptr->notify = false;
1042     self->current_job_ptr->report_fptr(Inic_GetTargetAddress(self->inic_ptr), XRM_INVALID_CONNECTION_LABEL, self->report_result, self->current_job_ptr->user_arg);
1043     Xrm_ApiLocking(self, false);
1044 }
1045
1046 /*! \brief  Reports result of automatically destroyed resources
1047  *  \param  self    Instance pointer
1048  */
1049 void Xrm_ReportAutoDestructionResult(CExtendedResourceManager *self)
1050 {
1051     MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t));
1052     self->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED;
1053     Xrm_NotifyInvalidJobs(self);
1054     Xrm_ApiLocking(self, false);
1055 }
1056
1057 /*! \brief  Reports result of resource destruction for a specific XRM job
1058  *  \param  self    Instance pointer
1059  */
1060 void Xrm_ReportJobDestructionResult(CExtendedResourceManager *self)
1061 {
1062     MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t));
1063     self->report_result.code = UCS_XRM_RES_SUCCESS_DESTROY;
1064     self->current_job_ptr->notify = true;
1065     Xrm_NotifyInvalidJobs(self);
1066     Xrm_ApiLocking(self, false);
1067 }
1068
1069 /*! \brief  Reports the conclusion of Extended Resource Manager jobs.
1070  *  \param  self    Instance pointer
1071  */
1072 void Xrm_FinishJob(CExtendedResourceManager *self)
1073 {
1074     MISC_MEM_SET(&self->report_result, 0x00, sizeof(Ucs_Xrm_Result_t));
1075     self->report_result.code = UCS_XRM_RES_SUCCESS_BUILD;
1076     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);
1077     Xrm_ApiLocking(self, false);
1078 }
1079
1080 /*! \brief  Marks the given resource as invalid and sets the notification.
1081  *  \param  resrc_ptr   Reference to the resource handle list to be looked for.
1082  *  \param  xrm_inst    Reference to the XRM instance to be looked for.
1083  *  \param  ud_ptr2     Optional reference to the user data 2. Not used !
1084  *  \param  ud_ptr3     Optional reference to the user data 3. Not used !
1085  *  \return \c false to continue the for-each-loop of the job_list queue
1086  */
1087 bool Xrm_MarkThisResrcAsInvalid (void *resrc_ptr, void * xrm_inst, void *ud_ptr2, void *ud_ptr3)
1088 {
1089     Xrm_ResourceHandleListItem_t * resrc_ptr_ = (Xrm_ResourceHandleListItem_t *)resrc_ptr;
1090     CExtendedResourceManager * xrm_inst_ = (CExtendedResourceManager *)xrm_inst;
1091     MISC_UNUSED(ud_ptr2);
1092     MISC_UNUSED(ud_ptr3);
1093
1094     if (Dl_IsNodeInList(&xrm_inst_->job_list, &resrc_ptr_->job_ptr->node))
1095     {
1096         if (resrc_ptr_->job_ptr->valid == true)
1097         {
1098             resrc_ptr_->job_ptr->valid  = false;
1099             resrc_ptr_->job_ptr->notify = true;
1100         }
1101         
1102         /* Inform monitor callback function */
1103         if (xrm_inst_->res_debugging_fptr != NULL)
1104         {
1105             xrm_inst_->res_debugging_fptr(*(UCS_XRM_CONST Ucs_Xrm_ResourceType_t *)(UCS_XRM_CONST void*)(resrc_ptr_->resource_object_ptr),
1106                                  resrc_ptr_->resource_object_ptr, UCS_XRM_INFOS_DESTROYED, xrm_inst_->current_job_ptr->user_arg, xrm_inst_->base_ptr->ucs_user_ptr);
1107         }
1108
1109         resrc_ptr_->resource_handle = XRM_INVALID_RESOURCE_HANDLE;
1110         resrc_ptr_->job_ptr = NULL;
1111         resrc_ptr_->resource_object_ptr = NULL;
1112     }
1113
1114     return false;
1115 }
1116
1117 /*! \brief  Marks all jobs on remote devices as "invalid".
1118  *  \param  self    Instance pointer
1119  */
1120 void Xrm_MarkResrcAndJobsAsInvalid (CExtendedResourceManager *self)
1121 {
1122     Xrmp_Foreach(self->xrmp_ptr, &Xrm_MarkThisResrcAsInvalid, self, NULL, NULL);
1123
1124     self->report_result.code = UCS_XRM_RES_RC_AUTO_DESTROYED;
1125 }
1126
1127 /*! \brief  Calls the result callbacks of jobs that were marked as invalid.
1128  *  \param  job_ptr    Reference to the job to be looked for.
1129  *  \param  xrm_inst   XRM Instance pointer.
1130  *  \return \c false to continue the for-each-loop of the job_list queue
1131  */
1132 bool Xrm_SetJobAsInvalid(void * job_ptr, void * xrm_inst)
1133 {
1134     Xrm_Job_t *job_ptr_ = (Xrm_Job_t *)job_ptr;
1135     CExtendedResourceManager * xrm_inst_ = (CExtendedResourceManager *)xrm_inst;
1136
1137     if(job_ptr_->notify != false)
1138     {
1139         job_ptr_->report_fptr(Inic_GetTargetAddress(xrm_inst_->inic_ptr), job_ptr_->connection_label, xrm_inst_->report_result, job_ptr_->user_arg);
1140         job_ptr_->notify = false;
1141     }
1142
1143     return false;
1144 }
1145
1146 /*! \brief  Calls the result callbacks of jobs that were marked as invalid.
1147  *  \param  self    Instance pointer
1148  */
1149 void Xrm_NotifyInvalidJobs(CExtendedResourceManager *self)
1150 {
1151     (void)Dl_Foreach(&self->job_list, &Xrm_SetJobAsInvalid, self);
1152 }
1153
1154 /*! \brief  Sets the monitoring callback for XRM resources.
1155  *  \param  self        Reference to the XRM Instance to be looked for.
1156  *  \param  dbg_cb_fn   Debug callback function to set.
1157  */
1158 void Xrm_SetResourceDebugCbFn(CExtendedResourceManager *self, Ucs_Xrm_ResourceDebugCb_t dbg_cb_fn)
1159 {
1160     if ((self != NULL) && (dbg_cb_fn != NULL))
1161     {
1162         self->res_debugging_fptr = dbg_cb_fn;
1163     }
1164 }
1165
1166 /*!
1167  * @}
1168  * \endcond
1169  */
1170
1171 /*------------------------------------------------------------------------------------------------*/
1172 /* End of file                                                                                    */
1173 /*------------------------------------------------------------------------------------------------*/
1174