c932c900fdcc07c3e966a4d6a6d6e9d86d0df532
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_bc_diag.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 BackChannel Diagnosis.
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup G_BACKCHANNEL_DIAG
28  * @{
29
30  */
31
32 /*------------------------------------------------------------------------------------------------*/
33 /* Includes                                                                                       */
34 /*------------------------------------------------------------------------------------------------*/
35 #include "ucs_inic_pb.h"
36 #include "ucs_bc_diag.h"
37 #include "ucs_misc.h"
38
39
40 /*------------------------------------------------------------------------------------------------*/
41 /* Internal constants                                                                             */
42 /*------------------------------------------------------------------------------------------------*/
43 #define BCD_NUM_STATES               7U     /*!< \brief Number of state machine states */
44 #define BCD_NUM_EVENTS              12U     /*!< \brief Number of state machine events */
45
46 #define BCD_TIMEOUT_COMMAND        100U     /*!< \brief supervise EXC commands */
47
48 #define BCD_SIGNATURE_VERSION        1U     /*!< \brief signature version used for BackChannel Diagnosis */
49
50 #define BCD_T_SEND              0x0100U
51 #define BCD_T_WAIT4DUT          0x1000U
52 #define BCD_T_SWITCH            0x0100U
53 #define BCD_T_BACK              0x2000U
54 #define BCD_TIMEOUT2            0x3000U
55 #define BCD_T_SIGNAL_ON         100U
56 #define BCD_T_LOCK              100U
57 #define BCD_T_LIGHT_PROGRESS    20U
58 #define BCD_AUTOBACK            (true)
59 #define ADMIN_BASE_ADDR         0x0F00U
60
61 /*------------------------------------------------------------------------------------------------*/
62 /* Service parameters                                                                             */
63 /*------------------------------------------------------------------------------------------------*/
64 /*! Priority of the BackChannel Diagnosis used by scheduler */
65 static const uint8_t BCD_SRV_PRIO = 248U;   /* parasoft-suppress  MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
66 /*! Main event for the BackChannel Diagnosis */
67 static const Srv_Event_t BCD_EVENT_SERVICE = 1U;
68
69
70 /*------------------------------------------------------------------------------------------------*/
71 /* Internal enumerators                                                                           */
72 /*------------------------------------------------------------------------------------------------*/
73 /*! \brief Possible events of the BackChannel Diagnosis state machine */
74 typedef enum Bcd_Events_
75 {
76     BCD_E_NIL                = 0U,      /*!< \brief NIL Event */
77     BCD_E_START              = 1U,      /*!< \brief API start command was called. */
78     BCD_E_DIAGMODE_END       = 2U,      /*!< \brief INIC.BCDiagEnd.Result successful. */
79     BCD_E_DIAG_MODE_STARTED  = 3U,      /*!< \brief INIC.BCDiag.Result successful. */
80     BCD_E_DIAG_MODE_FAILED   = 4U,      /*!< \brief INIC.BCDiag.Error received. */
81     BCD_E_TX_ENABLE_SUCCESS  = 5U,      /*!< \brief EXC.BCEnableTx successful */
82     BCD_E_TX_ENABLE_FAILED   = 6U,      /*!< \brief EXC.BCEnableTx failed. */
83     BCD_E_DIAG_RESULT_OK     = 7U,      /*!< \brief EXC.BCDIAG.Result Ok received. */
84     BCD_E_DIAG_RESULT_NOTOK  = 8U,      /*!< \brief EXC.BCDIAG.Result NotOk received. */
85     BCD_E_NET_OFF            = 9U,      /*!< \brief NetOff occurred. */
86     BCD_E_TIMEOUT            = 10U,     /*!< \brief Timeout occurred. */
87     BCD_E_ERROR              = 11U      /*!< \brief An unexpected error occurred. */
88
89 } Bcd_Events_t;
90
91
92 /*! \brief States of the BackChannel Diagnosis state machine */
93 typedef enum Bcd_State_
94 {
95     BCD_S_IDLE            =  0U,     /*!< \brief Idle state */
96     BCD_S_STARTED         =  1U,     /*!< \brief BackChannel Diagnosis started */
97     BCD_S_WAIT_ENABLED    =  2U,     /*!< \brief Wait for BCEnableTx.Result */
98     BCD_S_WAIT_SIG_PROP   =  3U,     /*!< \brief Wait for signal propagating through the following nodes */    
99     BCD_S_WAIT_SIGNAL_ON  =  4U,     /*!< \brief Wait for t_SignalOn to expire. */
100     BCD_S_WAIT_RESULT     =  5U,     /*!< \brief Wait for ENC.BCDiag.Result */
101     BCD_S_END             =  6U      /*!< \brief BackChannel Diagnosis ends. */
102 } Bcd_State_t;
103
104
105 /*------------------------------------------------------------------------------------------------*/
106 /* Internal prototypes                                                                            */
107 /*------------------------------------------------------------------------------------------------*/
108 static void Bcd_Service(void *self);
109
110 static void Bcd_InicBcdStartCb(void *self, void *result_ptr);
111 static void Bcd_EnableTxResultCb(void *self, void *result_ptr);
112 static void Bcd_DiagnosisResultCb(void *self, void *result_ptr);
113 static void Bcd_InicBcdEndCb(void *self, void *result_ptr);
114
115 static void Bcd_OnTerminateEventCb(void *self, void *result_ptr);
116 static void Bcd_NetworkStatusCb(void *self, void *result_ptr);
117
118 static void Bcd_A_Start(void *self);
119 static void Bcd_A_EnableTx(void *self);
120 static void Bcd_A_DiagStart(void *self);
121 static void Bcd_A_NextSeg(void *self);
122 static void Bcd_A_StopDiag(void *self);
123 static void Bcd_A_Error(void *self);
124 static void Bcd_A_EndDiag(void *self);
125 static void Bcd_A_Timeout2(void *self);
126 static void Bcd_A_WaitLight(void *self);
127
128
129 static Ucs_Return_t Bcd_EnableTx(void *self, uint8_t port);
130
131 static void Bcd_TimerCb(void *self);
132
133 /*------------------------------------------------------------------------------------------------*/
134 /* State transition table (used by finite state machine)                                          */
135 /*------------------------------------------------------------------------------------------------*/
136 /*! \brief State transition table */
137 static const Fsm_StateElem_t bcd_trans_tab[BCD_NUM_STATES][BCD_NUM_EVENTS] =    /* parasoft-suppress  MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
138 {
139     { /* State BCD_S_IDLE */
140         /* BCD_E_NIL                */ {NULL,                   BCD_S_IDLE              },
141         /* BCD_E_START              */ {Bcd_A_Start,            BCD_S_STARTED           },
142         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_IDLE              },
143         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_IDLE              },
144         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_IDLE              },
145         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_IDLE              },
146         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_IDLE              },
147         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_IDLE              },
148         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_IDLE              },
149         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_IDLE              },
150         /* BCD_E_TIMEOUT            */ {NULL,                   BCD_S_IDLE              },
151         /* BCD_E_ERROR              */ {NULL,                   BCD_S_IDLE              }
152     },
153     { /* State BCD_S_STARTED */
154         /* BCD_E_NIL                */ {NULL,                   BCD_S_STARTED           },
155         /* BCD_E_START              */ {NULL,                   BCD_S_STARTED           },
156         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_STARTED           },
157         /* BCD_E_DIAG_MODE_STARTED  */ {Bcd_A_EnableTx,         BCD_S_WAIT_ENABLED      },
158         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_STARTED           },
159         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_STARTED           },
160         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_STARTED           },
161         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_STARTED           },
162         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_STARTED           },
163         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_STARTED           },
164         /* BCD_E_TIMEOUT            */ {Bcd_A_Timeout2,         BCD_S_IDLE              },
165         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
166     },
167     { /* State BCD_S_WAIT_ENABLED */
168         /* BCD_E_NIL                */ {NULL,                   BCD_S_WAIT_ENABLED      },
169         /* BCD_E_START              */ {NULL,                   BCD_S_WAIT_ENABLED      },
170         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_WAIT_ENABLED      },
171         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_WAIT_ENABLED      },
172         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_WAIT_ENABLED      },
173         /* BCD_E_TX_ENABLE_SUCCESS  */ {Bcd_A_WaitLight,        BCD_S_WAIT_SIG_PROP     },
174         /* BCD_E_TX_ENABLE_FAILED   */ {Bcd_A_Error,            BCD_S_IDLE              },
175         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_WAIT_ENABLED      },
176         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_WAIT_ENABLED      },
177         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_WAIT_ENABLED      },
178         /* BCD_E_TIMEOUT            */ {Bcd_A_Timeout2,         BCD_S_IDLE              },
179         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
180     },
181     { /* State BCD_S_WAIT_SIG_PROP */
182         /* BCD_E_NIL                */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
183         /* BCD_E_START              */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
184         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
185         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
186         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
187         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
188         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
189         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
190         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
191         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_WAIT_SIG_PROP     },
192         /* BCD_E_TIMEOUT            */ {Bcd_A_DiagStart,        BCD_S_WAIT_RESULT       },
193         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
194     },
195     { /* State BCD_S_WAIT_SIGNAL_ON */
196         /* BCD_E_NIL                */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
197         /* BCD_E_START              */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
198         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
199         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
200         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
201         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
202         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
203         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
204         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
205         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_WAIT_SIGNAL_ON    },
206         /* BCD_E_TIMEOUT            */ {Bcd_A_EnableTx,         BCD_S_WAIT_ENABLED      },
207         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
208     },
209     { /* State BCD_S_WAIT_RESULT */
210         /* BCD_E_NIL                */ {NULL,                   BCD_S_WAIT_RESULT       },
211         /* BCD_E_START              */ {NULL,                   BCD_S_WAIT_RESULT       },
212         /* BCD_E_DIAGMODE_END       */ {NULL,                   BCD_S_WAIT_RESULT       },
213         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_WAIT_RESULT       },
214         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_WAIT_RESULT       },
215         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_WAIT_RESULT       },
216         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_WAIT_RESULT       },
217         /* BCD_E_DIAG_RESULT_OK     */ {Bcd_A_NextSeg,          BCD_S_WAIT_SIGNAL_ON    },
218         /* BCD_E_DIAG_RESULT_NOTOK  */ {Bcd_A_StopDiag,         BCD_S_END               },
219         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_WAIT_RESULT       },
220         /* BCD_E_TIMEOUT            */ {Bcd_A_Timeout2,         BCD_S_IDLE              },
221         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
222     },
223     { /* State BCD_S_END    */
224         /* BCD_E_NIL                */ {NULL,                   BCD_S_END               },
225         /* BCD_E_START              */ {NULL,                   BCD_S_END               },
226         /* BCD_E_DIAGMODE_END       */ {Bcd_A_EndDiag,          BCD_S_IDLE              },
227         /* BCD_E_DIAG_MODE_STARTED  */ {NULL,                   BCD_S_END               },
228         /* BCD_E_DIAG_MODE_FAILED   */ {NULL,                   BCD_S_END               },
229         /* BCD_E_TX_ENABLE_SUCCESS  */ {NULL,                   BCD_S_END               },
230         /* BCD_E_TX_ENABLE_FAILED   */ {NULL,                   BCD_S_END               },
231         /* BCD_E_DIAG_RESULT_OK     */ {NULL,                   BCD_S_END               },
232         /* BCD_E_DIAG_RESULT_NOTOK  */ {NULL,                   BCD_S_END               },
233         /* BCD_E_NET_OFF            */ {NULL,                   BCD_S_END               },
234         /* BCD_E_TIMEOUT            */ {Bcd_A_Timeout2,         BCD_S_IDLE              },
235         /* BCD_E_ERROR              */ {Bcd_A_Error,            BCD_S_IDLE              }
236     }
237 };
238
239
240 /*! \brief Constructor of class CBackChannelDiag.
241  *  \param self         Reference to CBackChannelDiag instance
242  *  \param inic         Reference to CInic instance
243  *  \param base         Reference to CBase instance
244  *  \param exc          Reference to CExc instance
245  */
246  /*  \param init_ptr    Report callback function*/
247 void Bcd_Ctor(CBackChannelDiag *self, CInic *inic, CBase *base, CExc *exc)
248 {
249     MISC_MEM_SET((void *)self, 0, sizeof(*self));
250
251     self->inic       = inic;
252     self->exc        = exc;
253     self->base       = base;
254
255     Fsm_Ctor(&self->fsm, self, &(bcd_trans_tab[0][0]), BCD_NUM_EVENTS, BCD_E_NIL);
256
257
258     Sobs_Ctor(&self->bcd_inic_bcd_start, self, &Bcd_InicBcdStartCb);
259     Sobs_Ctor(&self->bcd_inic_bcd_end,   self, &Bcd_InicBcdEndCb);
260     Sobs_Ctor(&self->bcd_enabletx,       self, &Bcd_EnableTxResultCb);
261     Sobs_Ctor(&self->bcd_diagnosis,      self, &Bcd_DiagnosisResultCb);
262
263
264     /* register termination events */
265     Mobs_Ctor(&self->bcd_terminate, self, EH_M_TERMINATION_EVENTS, &Bcd_OnTerminateEventCb);
266     Eh_AddObsrvInternalEvent(&self->base->eh, &self->bcd_terminate);
267
268     /* Register NetOn and MPR events */
269     Obs_Ctor(&self->bcd_nwstatus, self, &Bcd_NetworkStatusCb);
270     Inic_AddObsrvNwStatus(self->inic,  &self->bcd_nwstatus);
271     self->neton = false;
272
273     /* Initialize Node Discovery service */
274     Srv_Ctor(&self->service, BCD_SRV_PRIO, self, &Bcd_Service);
275     /* Add Node Discovery service to scheduler */
276     (void)Scd_AddService(&self->base->scd, &self->service);
277
278 }
279
280
281 /*! \brief Service function of the Node Discovery service.
282  *  \param self    Reference to Node Discovery object
283  */
284 static void Bcd_Service(void *self)
285 {
286     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
287     Srv_Event_t event_mask;
288     Srv_GetEvent(&self_->service, &event_mask);
289     if(BCD_EVENT_SERVICE == (event_mask & BCD_EVENT_SERVICE))   /* Is event pending? */
290     {
291         Fsm_State_t result;
292         Srv_ClearEvent(&self_->service, BCD_EVENT_SERVICE);
293         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured));
294         result = Fsm_Service(&self_->fsm);
295         TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", (result != FSM_STATE_ERROR));
296         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "FSM -> %d", 1U, self_->fsm.current_state));
297         MISC_UNUSED(result);
298     }
299 }
300
301
302 /**************************************************************************************************/
303 /* API functions                                                                                  */
304 /**************************************************************************************************/
305 /*! \brief Program a node
306  *
307  *  \param *self        Reference to BackChannel Diagnosis object
308  *  \param *report_fptr Reference to result callback used by BackChannel Diagnosis
309 */
310 void Bcd_Start(CBackChannelDiag *self, Ucs_Bcd_ReportCb_t report_fptr)
311 {
312     self->report_fptr = report_fptr;
313
314     Fsm_SetEvent(&self->fsm, BCD_E_START);
315     Srv_SetEvent(&self->service, BCD_EVENT_SERVICE);
316
317     TR_INFO((self->base->ucs_user_ptr, "[BCD]", "Bcd_Start", 0U));
318
319 }
320
321
322
323 /**************************************************************************************************/
324 /*  FSM Actions                                                                                   */
325 /**************************************************************************************************/
326 static void Bcd_A_Start(void *self)
327 {
328     Ucs_Return_t ret_val;
329     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
330
331     /* send INIC.BCDiag.StartResult */
332     ret_val = Inic_BCDiagnosis(self_->inic,  &self_->bcd_inic_bcd_start);
333
334     if (ret_val == UCS_RET_SUCCESS)
335     {
336         Tm_SetTimer(&self_->base->tm,
337                     &self_->timer,
338                     &Bcd_TimerCb,
339                     self_,
340                     BCD_TIMEOUT_COMMAND,
341                     0U);
342     }
343     else
344     {
345         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
346         Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
347     }
348
349     self_->current_segment = 0U;
350
351     TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS);
352     MISC_UNUSED(ret_val);
353 }
354
355 static void Bcd_A_EnableTx(void *self)
356 {
357     Ucs_Return_t ret_val;
358     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
359
360     /* send ENC.EnableTx */
361     ret_val = Bcd_EnableTx(self, 0U);
362
363     if (ret_val == UCS_RET_SUCCESS)
364     {
365         Tm_SetTimer(&self_->base->tm,
366                     &self_->timer,
367                     &Bcd_TimerCb,
368                     self_,
369                     BCD_TIMEOUT_COMMAND,
370                     0U);
371     }
372     else
373     {
374         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
375         Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
376     }
377
378     TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS);
379     MISC_UNUSED(ret_val);
380 }
381
382 /*! Starts the diagnosis command for one certain segment.
383  *
384  * \param *self The instance
385  */
386 static void Bcd_A_DiagStart(void *self)
387 {
388     Ucs_Return_t ret_val;
389     uint16_t t_send     = BCD_T_SEND;
390     uint16_t t_wait4dut = BCD_T_WAIT4DUT;
391     uint16_t t_switch   = BCD_T_SWITCH;
392     uint16_t t_back     = BCD_T_BACK;
393     bool     autoback   = BCD_AUTOBACK; 
394
395     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
396
397     ret_val = Exc_BCDiag_Start(self_->exc,
398                                self_->current_segment,
399                                ADMIN_BASE_ADDR + self_->current_segment,
400                                t_send,
401                                t_wait4dut,
402                                t_switch,
403                                t_back,
404                                autoback,
405                                &self_->bcd_diagnosis);
406
407     if (ret_val == UCS_RET_SUCCESS)
408     {
409         Tm_SetTimer(&self_->base->tm,
410                     &self_->timer,
411                     &Bcd_TimerCb,
412                     self_,
413                     BCD_TIMEOUT2,
414                     0U);
415
416     }
417     else
418     {
419         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
420         Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
421     }
422
423
424     MISC_UNUSED(ret_val);
425 }
426
427
428 static void Bcd_A_NextSeg(void *self)
429 {
430     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
431
432     self_->report_fptr(UCS_BCD_RES_SUCCESS, 
433                        (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), 
434                        self_->base->ucs_user_ptr);
435     self_->current_segment += 1U;       /* switch to next segment. */
436
437     Tm_SetTimer(&self_->base->tm,
438                 &self_->timer,
439                 &Bcd_TimerCb,
440                 self_,
441                 BCD_T_SIGNAL_ON,
442                 0U);
443 }
444
445 static void Bcd_A_StopDiag(void *self)
446 {
447     Ucs_Return_t ret_val;
448     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
449
450     switch(self_->bcd_result.diag_result)
451     {
452     case DUT_MASTER:
453         self_->report_fptr(UCS_BCD_RES_NO_RING_BREAK, 
454                            (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), 
455                            self_->base->ucs_user_ptr);
456         break;
457
458     case DUT_NO_ANSWER:
459         self_->report_fptr(UCS_BCD_RES_RING_BREAK, 
460                            (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), 
461                            self_->base->ucs_user_ptr);
462         break;
463
464     case DUT_TIMEOUT:
465         self_->report_fptr(UCS_BCD_RES_TIMEOUT1,  
466                            (uint8_t)(self_->bcd_result.admin_addr - ADMIN_BASE_ADDR), 
467                            self_->base->ucs_user_ptr);
468         break;
469
470     default:
471         break;
472     }
473
474     /* finish Back Channel Diagnosis Mode: send INIC.BCDiagEnd.StartResult */
475     ret_val = Inic_BCDiagEnd(self_->inic,  &self_->bcd_inic_bcd_end);
476
477     if (ret_val == UCS_RET_SUCCESS)
478     {
479         Tm_SetTimer(&self_->base->tm,
480                     &self_->timer,
481                     &Bcd_TimerCb,
482                     self_,
483                     BCD_TIMEOUT_COMMAND,
484                     0U);
485     }
486     else
487     {
488         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
489         Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
490     }
491
492     MISC_UNUSED(ret_val);
493 }
494
495
496 static void Bcd_A_EndDiag(void *self)
497 {
498     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
499
500     if (self_->report_fptr != NULL)
501     {
502         self_->report_fptr(UCS_BCD_RES_END, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr);
503     }
504 }
505
506 static void Bcd_A_Timeout2(void *self)
507 {
508     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
509
510     if (self_->report_fptr != NULL)
511     {
512         self_->report_fptr(UCS_BCD_RES_TIMEOUT2, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr);
513     }
514 }
515
516 static void Bcd_A_WaitLight(void *self)
517 {
518     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
519
520     Tm_SetTimer(&self_->base->tm,
521                 &self_->timer,
522                 &Bcd_TimerCb,
523                 self_,
524                 BCD_T_LOCK + (BCD_T_LIGHT_PROGRESS * (self_->current_segment + 1U)),
525                 0U);
526 }
527
528
529
530
531 /*! \brief An unecpected error occurred
532  *
533  * \param *self Reference to BackChannelDiagnosis object
534  */
535 static void Bcd_A_Error(void *self)
536 {
537     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
538
539     if (self_->report_fptr != NULL)
540     {
541         self_->report_fptr(UCS_BCD_RES_ERROR, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr);
542     }
543
544 }
545
546
547 /**************************************************************************************************/
548 /*  Callback functions                                                                            */
549 /**************************************************************************************************/
550
551 /*! \brief  Function is called on reception of the Welcome.Result messsage
552  *  \param  self        Reference to BackChannelDiagnosis object
553  *  \param  result_ptr  Pointer to the result of the Welcome message
554  */
555 static void Bcd_InicBcdStartCb(void *self, void *result_ptr)
556 {
557     CBackChannelDiag *self_        = (CBackChannelDiag *)self;
558     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
559
560     Tm_ClearTimer(&self_->base->tm, &self_->timer);
561
562     if (result_ptr_->result.code == UCS_RES_SUCCESS)
563     {
564         Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_MODE_STARTED);
565         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb BCD_E_DIAG_MODE_STARTED", 0U));
566     }
567     else
568     {
569         uint8_t i;
570
571         Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_MODE_FAILED);
572         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb Error (code) 0x%x", 1U, result_ptr_->result.code));
573         for (i=0U; i< result_ptr_->result.info_size; ++i)
574         {
575             TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdStartCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i]));
576         }
577     }
578
579     Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
580 }
581
582
583
584 /*! \brief  Function is called on reception of the BCEnableTx.Result messsage
585  *  \param  self        Reference to BackChannelDiagnosis object
586  *  \param  result_ptr  Pointer to the result of the BCEnableTx message
587  */
588 static void Bcd_EnableTxResultCb(void *self, void *result_ptr)
589 {
590     CBackChannelDiag *self_        = (CBackChannelDiag *)self;
591     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
592
593     Tm_ClearTimer(&self_->base->tm, &self_->timer);
594
595     if (result_ptr_->result.code == UCS_RES_SUCCESS)
596     {
597         /*        self_->signature_status = *(Exc_SignatureStatus_t *)(result_ptr_->data_info);*/
598         Fsm_SetEvent(&self_->fsm, BCD_E_TX_ENABLE_SUCCESS);
599         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_EnableTxResultCb BCD_E_TX_ENABLE_SUCCESS", 0U));
600     }
601     else
602     {
603         Fsm_SetEvent(&self_->fsm, BCD_E_TX_ENABLE_FAILED);
604         TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_EnableTxResultCb Error  0x%x", 1U, result_ptr_->result.code));
605     }
606
607     Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
608 }
609
610
611 /*! \brief  Function is called on reception of the ENC.BCDiag.Result messsage
612  *  \param  self        Reference to BackChannelDiagnosis object
613  *  \param  result_ptr  Pointer to the result of the BCDiag message
614  */
615 static void Bcd_DiagnosisResultCb(void *self, void *result_ptr)
616 {
617     CBackChannelDiag *self_      = (CBackChannelDiag *)self;
618     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
619
620     Tm_ClearTimer(&self_->base->tm, &self_->timer);
621
622     if (result_ptr_->result.code == UCS_RES_SUCCESS)
623     {
624         self_->bcd_result = *((Exc_BCDiagResult *)(result_ptr_->data_info));
625         switch (self_->bcd_result.diag_result)
626         {
627         case DUT_SLAVE:
628             /* node reported working segment */
629             Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_RESULT_OK);
630             TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_DiagnosisResultCb DUT_SLAVE", 0U));
631             break;
632
633         case DUT_MASTER:        /* all segments are ok */
634         case DUT_NO_ANSWER:     /* ring break found */
635         case DUT_TIMEOUT:       /* no communication on back channel */
636             Fsm_SetEvent(&self_->fsm, BCD_E_DIAG_RESULT_NOTOK);
637             TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_DiagnosisResultCb others", 0U));
638             break;
639
640         default:
641             /* report error */
642             break;
643         }
644     }
645     else
646     {
647         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
648         TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_DiagnosisResultCb Error  0x%x", 1U, result_ptr_->result.code));
649     }
650
651     Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
652 }
653
654
655 /*! \brief  Function is called on reception of the INIC.BCDiagEnd.Result messsage
656  *  \param  self        Reference to BackChannel Diagnosis object
657  *  \param  result_ptr  Pointer to the result of the Welcome message
658  */
659 static void Bcd_InicBcdEndCb(void *self, void *result_ptr)
660 {
661     CBackChannelDiag *self_        = (CBackChannelDiag *)self;
662     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
663
664     Tm_ClearTimer(&self_->base->tm, &self_->timer);
665
666     if (result_ptr_->result.code == UCS_RES_SUCCESS)
667     {
668         Fsm_SetEvent(&self_->fsm, BCD_E_DIAGMODE_END);
669         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_InicBcdEndCb BCD_E_DIAGMODE_END", 0U));
670     }
671     else
672     {
673         Fsm_SetEvent(&self_->fsm, BCD_E_ERROR);
674         TR_INFO((self_->base->ucs_user_ptr, "[ND]", "Bcd_InicBcdEndCb Error  0x%x", 1U, result_ptr_->result.code));
675     }
676
677     Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
678 }
679
680
681 /*!  Function is called on severe internal errors
682  *
683  * \param *self         Reference to Node Discovery object
684  * \param *result_ptr   Reference to data
685  */
686 static void Bcd_OnTerminateEventCb(void *self, void *result_ptr)
687 {
688     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
689
690     MISC_UNUSED(result_ptr);
691
692     if (self_->fsm.current_state != BCD_S_IDLE)
693     {
694         Tm_ClearTimer(&self_->base->tm, &self_->timer);
695         if (self_->report_fptr != NULL)
696         {
697             self_->report_fptr(UCS_BCD_RES_ERROR, UCS_BCD_DUMMY_SEGMENT, self_->base->ucs_user_ptr);
698         }
699     }
700 }
701
702
703 /*! \brief Callback function for the INIC.NetworkStatus status and error messages
704  *
705  * \param *self         Reference to Node Discovery object
706  * \param *result_ptr   Pointer to the result of the INIC.NetworkStatus message
707  */
708 static void Bcd_NetworkStatusCb(void *self, void *result_ptr)
709 {
710     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
711     Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
712
713     if (result_ptr_->result.code == UCS_RES_SUCCESS)
714     {
715         TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_NetworkStatusCb  0x%x", 1U, result_ptr_->result.code));
716         /* check for NetOn/NetOff events */
717         if (    (self_->neton == true)
718              && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) )
719         {
720             self_->neton = false;
721             Fsm_SetEvent(&self_->fsm, BCD_E_NET_OFF);
722             Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
723         }
724         /* check for NetOn/NetOff events */
725         else if (    (self_->neton == false)
726              && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) )
727         {
728 /*            self_->neton = true;
729             self_->hello_neton_request = true;
730             Fsm_SetEvent(&self_->fsm, BCD_E_CHECK);*/
731         }
732         /* check for MPR event */
733         else if (   (((Inic_NetworkStatus_t *)(result_ptr_->data_info))->events & UCS_NETWORK_EVENT_NCE)
734             == UCS_NETWORK_EVENT_NCE)
735         {
736 /*            self_->hello_mpr_request = true;
737             Fsm_SetEvent(&self_->fsm, BCD_E_CHECK);*/
738         }
739     }
740
741 }
742
743
744 /*! \brief Timer callback used for supervising INIC command timeouts.
745  *  \param self    Reference to Node Discovery object
746  */
747 static void Bcd_TimerCb(void *self)
748 {
749     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
750
751     Fsm_SetEvent(&self_->fsm, BCD_E_TIMEOUT);
752     TR_INFO((self_->base->ucs_user_ptr, "[BCD]", "Bcd_TimerCb BCD_E_TIMEOUT", 0U));
753
754     Srv_SetEvent(&self_->service, BCD_EVENT_SERVICE);
755 }
756
757
758 /**************************************************************************************************/
759 /*  Helper functions                                                                              */
760 /**************************************************************************************************/
761 static Ucs_Return_t Bcd_EnableTx(void *self, uint8_t port)
762 {
763     Ucs_Return_t ret_val;
764     CBackChannelDiag *self_ = (CBackChannelDiag *)self;
765
766     /* send INIC.BCDiag.StartResult */
767     ret_val = Exc_BCEnableTx_StartResult(self_->exc, port, &self_->bcd_enabletx);
768
769     TR_ASSERT(self_->base->ucs_user_ptr, "[BCD]", ret_val == UCS_RET_SUCCESS);
770     return ret_val;
771 }
772
773
774
775
776 /*!
777  * @}
778  * \endcond
779  */
780
781 /*------------------------------------------------------------------------------------------------*/
782 /* End of file                                                                                    */
783 /*------------------------------------------------------------------------------------------------*/
784