5f5b5db3d4d8d2b6d1a3840bf503e5adf7481d90
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_exc.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 FBlock ExtendedNetworkControl
25  * \details Contains the housekeeping functions of INIC management
26  *
27  * \cond UCS_INTERNAL_DOC
28  * \addtogroup G_EXC
29  * @{
30  */
31
32 /*------------------------------------------------------------------------------------------------*/
33 /* Includes                                                                                       */
34 /*------------------------------------------------------------------------------------------------*/
35 #include "ucs_misc.h"
36 #include "ucs_ret_pb.h"
37 #include "ucs_exc.h"
38
39
40
41 /*------------------------------------------------------------------------------------------------*/
42 /* Internal definitions                                                                           */
43 /*------------------------------------------------------------------------------------------------*/
44 /*! \brief Bitmask for API method Exc_PhyTestResult_Get() used by API locking manager */
45 #define EXC_API_PHY_LAY_TEST_RESULT     0x01U
46 /*! \brief Bitmask for API method Exc_MemSessionOpen_Sr() used by API locking manager */
47 #define EXC_API_MEM_SESSION_OPEN        0x02U
48 /*! \brief Bitmask for API method Exc_MemSessionClose_Sr() used by API locking manager */
49 #define EXC_API_MEM_SESSION_CLOSE       0x04U
50 /*! \brief Bitmask for API method Exc_MemoryRead_Sr() used by API locking manager */
51 #define EXC_API_MEM_READ                0x08U
52 /*! \brief Bitmask for API method Exc_MemoryWrite_Sr() used by API locking manager */
53 #define EXC_API_MEM_WRITE               0x10U
54
55 /*! \brief max. number of elements used in MemoryWrite and MemoryWrite messages */
56 #define MAX_UNIT_LEN                    18U
57
58 /*! \brief  length of signature (V1) */
59 #define EXC_SIGNATURE_LEN_V1            26U
60
61
62 /*------------------------------------------------------------------------------------------------*/
63 /* Internal prototypes                                                                            */
64 /*------------------------------------------------------------------------------------------------*/
65 static void Exc_DecodeMsg(CExc *self, Msg_MostTel_t *msg_rx_ptr);
66 static void Exc_EnablePort_Error(void *self, Msg_MostTel_t *msg_ptr);
67 static void Exc_EnablePort_Result(void *self, Msg_MostTel_t *msg_ptr);
68 static void Exc_Hello_Status(void *self, Msg_MostTel_t *msg_ptr);
69 static void Exc_Hello_Error(void *self, Msg_MostTel_t *msg_ptr);
70 static void Exc_Welcome_Error(void *self, Msg_MostTel_t *msg_ptr);
71 static void Exc_Welcome_Result(void *self, Msg_MostTel_t *msg_ptr);
72 static void Exc_Signature_Status(void *self, Msg_MostTel_t *msg_ptr);
73 static void Exc_Signature_Error(void *self, Msg_MostTel_t *msg_ptr);
74 static void Exc_DeviceInit_Error(void *self, Msg_MostTel_t *msg_ptr);
75 static void Exc_CableLinkDiag_Error(void *self, Msg_MostTel_t *msg_ptr);
76 static void Exc_CableLinkDiag_Result(void *self, Msg_MostTel_t *msg_ptr);
77 static void Exc_NwPhyTest_Error(void *self, Msg_MostTel_t *msg_ptr);
78 static void Exc_NwPhyTestResult_Status(void *self, Msg_MostTel_t *msg_ptr);
79 static void Exc_NwPhyTestResult_Error(void *self, Msg_MostTel_t *msg_ptr);
80 static void Exc_BC_Diag_Result(void *self, Msg_MostTel_t *msg_ptr);
81 static void Exc_BC_Diag_Error(void *self, Msg_MostTel_t *msg_ptr);
82 static void Exc_BC_EnableTx_Result(void *self, Msg_MostTel_t *msg_ptr);
83 static void Exc_BC_EnableTx_Error(void *self, Msg_MostTel_t *msg_ptr);
84 static void Exc_MemoryRead_Result(void *self, Msg_MostTel_t *msg_ptr);
85 static void Exc_MemoryRead_Error(void *self, Msg_MostTel_t *msg_ptr);
86 static void Exc_MemoryWrite_Result(void *self, Msg_MostTel_t *msg_ptr);
87 static void Exc_MemoryWrite_Error(void *self, Msg_MostTel_t *msg_ptr);
88 static void Exc_MemSessionOpen_Result(void *self, Msg_MostTel_t *msg_ptr);
89 static void Exc_MemSessionOpen_Error(void *self, Msg_MostTel_t *msg_ptr);
90 static void Exc_MemSessionClose_Result(void *self, Msg_MostTel_t *msg_ptr);
91 static void Exc_MemSessionClose_Error(void *self, Msg_MostTel_t *msg_ptr);
92
93 static void Exc_HandleApiTimeout(void *self, void *method_mask_ptr);
94
95 static Ucs_StdResult_t Exc_TranslateError(CExc *self, uint8_t error_data[], uint8_t error_size);
96 static void Exc_Read_Signature(Ucs_Signature_t *dest, uint8_t source[]);
97
98
99 /*------------------------------------------------------------------------------------------------*/
100 /* Internal constants                                                                             */
101 /*------------------------------------------------------------------------------------------------*/
102 /*! \brief List of all EXC messages */
103 static const Dec_FktOpIsh_t exc_handler[] =       /* parasoft-suppress  MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
104 {
105     { DEC_FKTOP(EXC_FID_HELLO,                  UCS_OP_STATUS),  Exc_Hello_Status },
106     { DEC_FKTOP(EXC_FID_HELLO,                  UCS_OP_ERROR),   Exc_Hello_Error },
107     { DEC_FKTOP(EXC_FID_WELCOME,                UCS_OP_RESULT),  Exc_Welcome_Result },
108     { DEC_FKTOP(EXC_FID_WELCOME,                UCS_OP_ERROR),   Exc_Welcome_Error },
109     { DEC_FKTOP(EXC_FID_SIGNATURE,              UCS_OP_STATUS),  Exc_Signature_Status },
110     { DEC_FKTOP(EXC_FID_SIGNATURE,              UCS_OP_ERROR),   Exc_Signature_Error },
111     { DEC_FKTOP(EXC_FID_DEVICE_INIT,            UCS_OP_ERROR),   Exc_DeviceInit_Error },
112     { DEC_FKTOP(EXC_FID_ENABLEPORT,             UCS_OP_RESULT),  Exc_EnablePort_Result },
113     { DEC_FKTOP(EXC_FID_ENABLEPORT,             UCS_OP_ERROR),   Exc_EnablePort_Error },
114     { DEC_FKTOP(EXC_FID_CABLE_LINK_DIAG,        UCS_OP_RESULT),  Exc_CableLinkDiag_Result },
115     { DEC_FKTOP(EXC_FID_CABLE_LINK_DIAG,        UCS_OP_ERROR),   Exc_CableLinkDiag_Error },
116     { DEC_FKTOP(EXC_FID_PHY_LAY_TEST,           UCS_OP_ERROR),   Exc_NwPhyTest_Error },
117     { DEC_FKTOP(EXC_FID_PHY_LAY_TEST_RES,       UCS_OP_STATUS),  Exc_NwPhyTestResult_Status },
118     { DEC_FKTOP(EXC_FID_PHY_LAY_TEST_RES,       UCS_OP_ERROR),   Exc_NwPhyTestResult_Error },
119     { DEC_FKTOP(EXC_FID_BC_DIAG,                UCS_OP_RESULT),  Exc_BC_Diag_Result },
120     { DEC_FKTOP(EXC_FID_BC_DIAG,                UCS_OP_ERROR),   Exc_BC_Diag_Error },
121     { DEC_FKTOP(EXC_FID_BC_ENABLE_TX,           UCS_OP_RESULT),  Exc_BC_EnableTx_Result },
122     { DEC_FKTOP(EXC_FID_BC_ENABLE_TX,           UCS_OP_ERROR),   Exc_BC_EnableTx_Error },
123     { DEC_FKTOP(EXC_FID_MEM_SESSION_OPEN,       UCS_OP_RESULT),  Exc_MemSessionOpen_Result },
124     { DEC_FKTOP(EXC_FID_MEM_SESSION_OPEN,       UCS_OP_ERROR),   Exc_MemSessionOpen_Error },
125     { DEC_FKTOP(EXC_FID_MEM_SESSION_CLOSE,      UCS_OP_RESULT),  Exc_MemSessionClose_Result },
126     { DEC_FKTOP(EXC_FID_MEM_SESSION_CLOSE,      UCS_OP_ERROR),   Exc_MemSessionClose_Error },
127     { DEC_FKTOP(EXC_FID_MEMORY_READ,            UCS_OP_RESULT),  Exc_MemoryRead_Result },
128     { DEC_FKTOP(EXC_FID_MEMORY_READ,            UCS_OP_ERROR),   Exc_MemoryRead_Error },
129     { DEC_FKTOP(EXC_FID_MEMORY_WRITE,           UCS_OP_RESULT),  Exc_MemoryWrite_Result },
130     { DEC_FKTOP(EXC_FID_MEMORY_WRITE,           UCS_OP_ERROR),   Exc_MemoryWrite_Error },
131     { DEC_FKTOP_TERMINATION,                                     NULL }
132 };
133
134
135 /*------------------------------------------------------------------------------------------------*/
136 /* Implementation                                                                                 */
137 /*------------------------------------------------------------------------------------------------*/
138
139 /*! \brief Constructor of class CExc.
140  *  \param self         Reference to CExc instance
141  *  \param base_ptr     Reference to a Base instance
142  *  \param rcm_ptr      Reference to Transceiver instance
143  */
144 void Exc_Ctor(CExc *self, CBase *base_ptr, CTransceiver *rcm_ptr)
145 {
146
147     MISC_MEM_SET((void *)self, 0, sizeof(*self));
148
149     self->base_ptr = base_ptr;
150     self->xcvr_ptr = rcm_ptr;
151
152     self->fkt_op_list_ptr = &exc_handler[0];
153
154
155     /* Initialize API locking mechanism */
156     Sobs_Ctor(&self->lock.observer, self, &Exc_HandleApiTimeout);
157     Al_Ctor(&self->lock.api, &self->lock.observer, self->base_ptr->ucs_user_ptr);
158     Alm_RegisterApi(&self->base_ptr->alm, &self->lock.api);
159
160 }
161
162
163 /*! \brief   Callback function to filter RCM Rx messages
164  *  \details Do not release the message object here
165  *  \param   self     reference to INIC object
166  *  \param   tel_ptr  received message
167  */
168 void Exc_OnRcmRxFilter(void *self, Msg_MostTel_t *tel_ptr)
169 {
170     CExc *self_ = (CExc *)self;
171     Exc_DecodeMsg(self_, tel_ptr);
172
173 }
174
175
176 /*! \brief  Decode a message for FBlock EXC
177  *  \param  self        Instance pointer to FBlock EXC
178  *  \param  msg_rx_ptr  pointer to the MCM message to decode
179  */
180 static void Exc_DecodeMsg(CExc *self, Msg_MostTel_t *msg_rx_ptr)
181 {
182     Dec_Return_t result;
183     uint16_t     index;
184
185     result = Dec_SearchFktOpIsh(self->fkt_op_list_ptr, &index, msg_rx_ptr->id.function_id, msg_rx_ptr->id.op_type);
186
187     if (result == DEC_RET_SUCCESS)
188     {
189         self->fkt_op_list_ptr[index].handler_function_ptr(self, msg_rx_ptr);
190     }
191     else
192     {
193         /* no handling of decoding error for shadow OpTypes */
194     }
195 }
196
197
198
199 /*! \brief  Handles an API timeout
200  *  \param  self             Instance pointer
201  *  \param  method_mask_ptr  Bitmask to signal which API method has caused the timeout
202  */
203 static void Exc_HandleApiTimeout(void *self, void *method_mask_ptr)
204 {
205     CExc *self_ = (CExc *)self;
206     Alm_ModuleMask_t method_mask = *((Alm_ModuleMask_t *)method_mask_ptr);
207     Exc_StdResult_t res_data;
208
209     res_data.result.code      = UCS_RES_ERR_TIMEOUT;
210     res_data.result.info_ptr  = NULL;
211     res_data.result.info_size = 0U;
212     res_data.data_info        = NULL;
213
214     switch(method_mask)
215     {
216 #if 0   /* System Diagnosis supervises timeouts for these functions  */
217         case EXC_API_ENABLE_PORT:
218             Ssub_Notify(&self_->ssubs.enableport, &res_data, false);
219             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_EnablePort_Sr().", 0U));
220             break;
221         case EXC_API_HELLO:
222             Ssub_Notify(&self_->ssubs.hello, &res_data, false);
223             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_Hello_Get().", 0U));
224             break;
225         case EXC_API_WELCOME:
226             Ssub_Notify(&self_->ssubs.welcome, &res_data, false);
227             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_Welcome_Sr().", 0U));
228             break;
229         case EXC_API_CABLE_LINK_DIAG:
230             Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, false);
231             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_CableLinkDiagnosis_Start().", 0U));
232             break;
233 #endif
234         case EXC_API_PHY_LAY_TEST_RESULT:
235             Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, false);
236             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_PhyTestResult_Get().", 0U));
237             break;
238         case EXC_API_MEM_SESSION_OPEN:
239             Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, false);
240             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemSessionOpen_Sr().", 0U));
241             break;
242         case EXC_API_MEM_SESSION_CLOSE:
243             Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, false);
244             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemSessionClose_Sr().", 0U));
245             break;
246         case EXC_API_MEM_READ:
247             Ssub_Notify(&self_->ssubs.memoryread, &res_data, false);
248             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemoryRead_Sr().", 0U));
249             break;
250         case EXC_API_MEM_WRITE:
251             Ssub_Notify(&self_->ssubs.memorywrite, &res_data, false);
252             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "API locking timeout occurred for method Exc_MemoryWrite_Sr().", 0U));
253             break;
254
255         default:
256             TR_ERROR((self_->base_ptr->ucs_user_ptr, "[EXC]", "Unknown API locking bitmask detected. Mask: 0x%02X", 1U, method_mask));
257             break;
258     }
259 }
260
261
262
263
264 /*------------------------------------------------------------------------------------------------*/
265 /* Internal API                                                                                   */
266 /*------------------------------------------------------------------------------------------------*/
267 /*! \brief  This method sends the Hello.Get message
268  *  \param  self            Reference to CExc instance
269  *  \param  target_address  Target address
270  *  \param  version_limit   Signature version limit 
271  *  \param  obs_ptr         Reference to an optional observer
272  *  \return UCS_RET_SUCCESS               message was created 
273  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
274  */
275 Ucs_Return_t Exc_Hello_Get(CExc *self, 
276                            uint16_t target_address, 
277                            uint8_t version_limit,
278                            CSingleObserver *obs_ptr)
279 {
280     Ucs_Return_t result = UCS_RET_SUCCESS;
281
282     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U);
283
284     if (msg_ptr != NULL)
285     {
286         if (version_limit > UCS_EXC_SIGNATURE_VERSION_LIMIT)
287         {
288             version_limit = UCS_EXC_SIGNATURE_VERSION_LIMIT;
289         }
290
291         msg_ptr->destination_addr    = target_address;
292
293         msg_ptr->id.fblock_id        = FB_EXC;
294         msg_ptr->id.instance_id      = 0U;
295         msg_ptr->id.function_id      = EXC_FID_HELLO;
296         msg_ptr->id.op_type          = UCS_OP_GET;
297         msg_ptr->tel.tel_data_ptr[0] = version_limit;
298
299         msg_ptr->info_ptr = &self->ssubs.hello;
300         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
301
302         (void)Ssub_AddObserver(&self->ssubs.hello, obs_ptr);
303     }
304     else
305     {
306         result = UCS_RET_ERR_BUFFER_OVERFLOW;
307     }
308
309     return result;
310 }
311
312
313 /*! \brief  This method send the Welcome.StartResult message
314  *  \param  self                Reference to CExc instance
315  *  \param  target_address      Target address
316  *  \param  admin_node_address  The node address used during system diagnosis
317  *  \param  version             Signature version 
318  *  \param  signature           Signature of the device
319  *  \param  obs_ptr             Reference to an optional observer
320  *  \return UCS_RET_SUCCESS               message was created 
321  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
322  */
323 Ucs_Return_t Exc_Welcome_Sr(CExc *self, 
324                             uint16_t target_address, 
325                             uint16_t admin_node_address,
326                             uint8_t version,
327                             Ucs_Signature_t  signature,
328                             CSingleObserver *obs_ptr)
329 {
330     Ucs_Return_t result = UCS_RET_SUCCESS;
331
332     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, EXC_SIGNATURE_LEN_V1 + 3U);    /* Signature v1 */
333
334     if (msg_ptr != NULL)
335     {
336         msg_ptr->destination_addr     = target_address;
337         msg_ptr->id.fblock_id         = FB_EXC;
338         msg_ptr->id.instance_id       = 0U;
339         msg_ptr->id.function_id       = EXC_FID_WELCOME;
340         msg_ptr->id.op_type           = UCS_OP_STARTRESULT;
341         msg_ptr->tel.tel_data_ptr[0]  = MISC_HB(admin_node_address);
342         msg_ptr->tel.tel_data_ptr[1]  = MISC_LB(admin_node_address);
343         msg_ptr->tel.tel_data_ptr[2]  = version;
344         msg_ptr->tel.tel_data_ptr[3]  = MISC_HB(signature.node_address);
345         msg_ptr->tel.tel_data_ptr[4]  = MISC_LB(signature.node_address);
346         msg_ptr->tel.tel_data_ptr[5]  = MISC_HB(signature.group_address);
347         msg_ptr->tel.tel_data_ptr[6]  = MISC_LB(signature.group_address);
348         msg_ptr->tel.tel_data_ptr[7]  = MISC_HB(signature.mac_47_32);
349         msg_ptr->tel.tel_data_ptr[8]  = MISC_LB(signature.mac_47_32);
350         msg_ptr->tel.tel_data_ptr[9]  = MISC_HB(signature.mac_31_16);
351         msg_ptr->tel.tel_data_ptr[10] = MISC_LB(signature.mac_31_16);
352         msg_ptr->tel.tel_data_ptr[11] = MISC_HB(signature.mac_15_0);
353         msg_ptr->tel.tel_data_ptr[12] = MISC_LB(signature.mac_15_0);
354         msg_ptr->tel.tel_data_ptr[13] = MISC_HB(signature.node_pos_addr);
355         msg_ptr->tel.tel_data_ptr[14] = MISC_LB(signature.node_pos_addr);
356         msg_ptr->tel.tel_data_ptr[15] = MISC_HB(signature.diagnosis_id);
357         msg_ptr->tel.tel_data_ptr[16] = MISC_LB(signature.diagnosis_id);
358         msg_ptr->tel.tel_data_ptr[17] = signature.num_ports;
359         msg_ptr->tel.tel_data_ptr[18] = signature.chip_id;
360         msg_ptr->tel.tel_data_ptr[19] = signature.fw_major;
361         msg_ptr->tel.tel_data_ptr[20] = signature.fw_minor;
362         msg_ptr->tel.tel_data_ptr[21] = signature.fw_release;
363         msg_ptr->tel.tel_data_ptr[22] = MISC_HB((signature.fw_build) >>16U);
364         msg_ptr->tel.tel_data_ptr[23] = MISC_LB((signature.fw_build) >>16U);
365         msg_ptr->tel.tel_data_ptr[24] = MISC_HB(signature.fw_build);
366         msg_ptr->tel.tel_data_ptr[25] = MISC_LB(signature.fw_build);
367         msg_ptr->tel.tel_data_ptr[26] = signature.cs_major;
368         msg_ptr->tel.tel_data_ptr[27] = signature.cs_minor;
369         msg_ptr->tel.tel_data_ptr[28] = signature.cs_release;
370 /*        msg_ptr->tel.tel_data_ptr[29] = signature.uid_persistency;
371         msg_ptr->tel.tel_data_ptr[30] = MISC_HB((signature.uid) >>16U);
372         msg_ptr->tel.tel_data_ptr[31] = MISC_LB((signature.uid) >>16U);
373         msg_ptr->tel.tel_data_ptr[32] = MISC_HB(signature.uid);
374         msg_ptr->tel.tel_data_ptr[33] = MISC_LB(signature.uid);
375 */
376
377         msg_ptr->info_ptr = &self->ssubs.welcome;
378         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
379
380         (void)Ssub_AddObserver(&self->ssubs.welcome, obs_ptr);
381     }
382     else
383     {
384         result = UCS_RET_ERR_BUFFER_OVERFLOW;
385     }
386
387     return result;
388 }
389
390
391 /*! \brief  This method sends the Signature.Get message
392  *  \param  self            Reference to CExc instance
393  *  \param  target_address  Target address
394  *  \param  version_limit   Signature version limit 
395  *  \param  obs_ptr         Reference to an optional observer
396  *  \return UCS_RET_SUCCESS               message was created 
397  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
398  */
399 Ucs_Return_t Exc_Signature_Get(CExc *self, 
400                                uint16_t target_address, 
401                                uint8_t version_limit, 
402                                CSingleObserver *obs_ptr)
403 {
404     Ucs_Return_t result = UCS_RET_SUCCESS;
405
406     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U);
407
408     if (msg_ptr != NULL)
409     {
410         if (version_limit > UCS_EXC_SIGNATURE_VERSION_LIMIT)
411         {
412             version_limit = UCS_EXC_SIGNATURE_VERSION_LIMIT;
413         }
414
415         msg_ptr->destination_addr  = target_address;
416
417         msg_ptr->id.fblock_id      = FB_EXC;
418         msg_ptr->id.instance_id    = 0U;
419         msg_ptr->id.function_id    = EXC_FID_SIGNATURE;
420         msg_ptr->id.op_type        = UCS_OP_GET;
421         msg_ptr->tel.tel_data_ptr[0] = version_limit;
422
423         msg_ptr->info_ptr = &self->ssubs.signature;
424         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
425
426         (void)Ssub_AddObserver(&self->ssubs.signature, obs_ptr);
427     }
428     else
429     {
430         result = UCS_RET_ERR_BUFFER_OVERFLOW;
431     }
432
433     return result;
434 }
435
436
437 /*! \brief  This method sends the DeviceInit.Start message
438  *  \param  self            Reference to CExc instance
439  *  \param  target_address  Target address
440  *  \param  obs_ptr         Reference to an optional observer
441  *  \return UCS_RET_SUCCESS               message was created 
442  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
443  */
444 Ucs_Return_t Exc_DeviceInit_Start(CExc *self, 
445                                   uint16_t target_address, 
446                                   CSingleObserver *obs_ptr)
447 {
448     Ucs_Return_t result = UCS_RET_SUCCESS;
449
450     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U);
451
452     if (msg_ptr != NULL)
453     {
454         msg_ptr->destination_addr  = target_address;
455
456         msg_ptr->id.fblock_id      = FB_EXC;
457         msg_ptr->id.instance_id    = 0U;
458         msg_ptr->id.function_id    = EXC_FID_DEVICE_INIT;
459         msg_ptr->id.op_type        = UCS_OP_START;
460
461         msg_ptr->info_ptr = &self->ssubs.deviceinit;
462         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
463
464         (void)Ssub_AddObserver(&self->ssubs.deviceinit, obs_ptr);
465     }
466     else
467     {
468         result = UCS_RET_ERR_BUFFER_OVERFLOW;
469     }
470
471     return result;
472 }
473
474
475 /*! \brief  This method enables a port
476  *  \param  self            Reference to CExc instance
477  *  \param  target_address  Target address
478  *  \param  port_number     PortNumber 
479  *  \param  enabled         Enabled 
480  *  \param  obs_ptr         Reference to an optional observer
481  *  \return UCS_RET_SUCCESS               message was created 
482  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
483  */
484 Ucs_Return_t Exc_EnablePort_Sr(CExc *self, 
485                                uint16_t target_address, 
486                                uint8_t port_number, 
487                                bool enabled, 
488                                CSingleObserver *obs_ptr)
489 {
490     Ucs_Return_t result = UCS_RET_SUCCESS;
491
492     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U); 
493
494     if (msg_ptr != NULL)
495     {
496         msg_ptr->destination_addr    = target_address;
497
498         msg_ptr->id.fblock_id        = FB_EXC;
499         msg_ptr->id.instance_id      = 0U;
500         msg_ptr->id.function_id      = EXC_FID_ENABLEPORT;
501         msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
502         msg_ptr->tel.tel_data_ptr[0] = port_number;
503         msg_ptr->tel.tel_data_ptr[1] = (uint8_t)enabled;
504
505         msg_ptr->info_ptr = &self->ssubs.enableport;
506         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
507
508         (void)Ssub_AddObserver(&self->ssubs.enableport, obs_ptr);
509     }
510     else
511     {
512         result = UCS_RET_ERR_BUFFER_OVERFLOW;
513     }
514
515     return result;
516 }
517
518 /*! \brief  This method starts the Cable Link Diagnosis
519  *  \param  self            Reference to CExc instance
520  *  \param  target_address  Target address
521  *  \param  port_number     PortNumber 
522  *  \param  obs_ptr         Reference to an optional observer
523  *  \return UCS_RET_SUCCESS               message was created 
524  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
525  */
526 Ucs_Return_t Exc_CableLinkDiagnosis_Start(CExc *self, 
527                                           uint16_t target_address, 
528                                           uint8_t port_number, 
529                                           CSingleObserver *obs_ptr)
530 {
531     Ucs_Return_t result = UCS_RET_SUCCESS;
532
533     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U);
534
535     if (msg_ptr != NULL)
536     {
537         msg_ptr->destination_addr    = target_address;
538
539         msg_ptr->id.fblock_id        = FB_EXC;
540         msg_ptr->id.instance_id      = 0U;
541         msg_ptr->id.function_id      = EXC_FID_CABLE_LINK_DIAG;
542         msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
543         msg_ptr->tel.tel_data_ptr[0] = port_number;
544
545         msg_ptr->info_ptr = &self->ssubs.cablelinkdiag;
546         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
547
548         (void)Ssub_AddObserver(&self->ssubs.cablelinkdiag, obs_ptr);
549     }
550     else
551     {
552         result = UCS_RET_ERR_BUFFER_OVERFLOW;
553     }
554
555     return result;
556 }
557
558 /*! \brief  This method starts the Physical Layer Test
559  *  \param  self            Reference to CExc instance
560  *  \param  port_number     PortNumber 
561  *  \param  type            Type
562  *  \param  lead_in         Lead-in
563  *  \param  duration        Duration
564  *  \param  lead_out        Lead-out
565  *  \param  obs_ptr         Reference to an optional observer
566  *  \return UCS_RET_SUCCESS               message was created 
567  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
568  */
569 Ucs_Return_t Exc_PhyTest_Start(CExc *self, 
570                                uint8_t port_number, 
571                                Ucs_Diag_PhyTest_Type_t type, 
572                                uint16_t lead_in, 
573                                uint32_t duration, 
574                                uint16_t lead_out, 
575                                CSingleObserver *obs_ptr)
576 {
577     Ucs_Return_t result = UCS_RET_SUCCESS;
578
579     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 10U);
580
581     if (msg_ptr != NULL)
582     {
583         msg_ptr->destination_addr    = MSG_ADDR_INIC; 
584
585         msg_ptr->id.fblock_id        = FB_EXC;
586         msg_ptr->id.instance_id      = 0U;
587         msg_ptr->id.function_id      = EXC_FID_PHY_LAY_TEST;
588         msg_ptr->id.op_type          = UCS_OP_START;
589         msg_ptr->tel.tel_data_ptr[0] = port_number; 
590         msg_ptr->tel.tel_data_ptr[1] = (uint8_t)type;
591         msg_ptr->tel.tel_data_ptr[2] = MISC_HB(lead_in);
592         msg_ptr->tel.tel_data_ptr[3] = MISC_LB(lead_in);
593         msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((duration) >> 24);
594         msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((duration) >> 16);
595         msg_ptr->tel.tel_data_ptr[6] = (uint8_t)((duration) >> 8);
596         msg_ptr->tel.tel_data_ptr[7] = (uint8_t)(duration & (uint32_t)0xFF);
597         msg_ptr->tel.tel_data_ptr[8] = MISC_HB(lead_out);
598         msg_ptr->tel.tel_data_ptr[9] = MISC_LB(lead_out);
599
600
601         msg_ptr->info_ptr = &self->ssubs.phylaytest;
602         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
603
604         (void)Ssub_AddObserver(&self->ssubs.phylaytest, obs_ptr);
605     }
606     else
607     {
608         result = UCS_RET_ERR_BUFFER_OVERFLOW;
609     }
610
611     return result;
612 }
613
614
615 /*! \brief  Requests the EXC.PhysicalLayerTestResult.Status message
616  *  \param  self        Reference to CExc instance
617  *  \param  obs_ptr     Reference to an optional observer
618  *  \return UCS_RET_SUCCESS               message was created 
619  *  \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available 
620  *  \return UCS_RET_ERR_API_LOCKED        Resource API is already used by another command
621  */
622 Ucs_Return_t  Exc_PhyTestResult_Get(CExc *self, 
623                                     CSingleObserver *obs_ptr)
624 {
625     Ucs_Return_t result = UCS_RET_SUCCESS;
626
627     if(Al_Lock(&self->lock.api, EXC_API_PHY_LAY_TEST_RESULT) != false)
628     {
629         Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 0U);
630
631         if (msg_ptr != NULL)
632         {
633             msg_ptr->destination_addr  = MSG_ADDR_INIC;
634
635             msg_ptr->id.fblock_id      = FB_EXC;
636             msg_ptr->id.instance_id    = 0U;
637             msg_ptr->id.function_id    = EXC_FID_PHY_LAY_TEST_RES;
638             msg_ptr->id.op_type        = UCS_OP_GET;
639
640             msg_ptr->info_ptr = &self->ssubs.phylaytestresult;
641             Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
642
643             (void)Ssub_AddObserver(&self->ssubs.phylaytestresult, obs_ptr);
644         }
645         else
646         {
647             Al_Release(&self->lock.api, EXC_API_PHY_LAY_TEST_RESULT);
648             result = UCS_RET_ERR_BUFFER_OVERFLOW;
649         }
650     }
651     else
652     {
653         result = UCS_RET_ERR_API_LOCKED;
654     }
655
656     return result;
657 }
658
659
660
661 /*! Sends the BCDiag.Startresult command
662  *
663  * \param *self         Reference to CExc instance
664  * \param position      Position of the segment to be checked.
665  * \param admin_na      Admin Node Address
666  * \param t_send        Timing parameter t_Send
667  * \param t_wait4dut    Timing parameter t_WaitForDUT
668  * \param t_switch      Timing parameter t_Switch
669  * \param t_back        Timing parameter t_Back
670  * \param autoback      TBD
671  * \param *obs_ptr      Reference to an optional observer
672  * \return UCS_RET_SUCCESS               message was created 
673  * \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
674  */
675 Ucs_Return_t Exc_BCDiag_Start(CExc *self, 
676                               uint8_t position, 
677                               uint16_t admin_na,
678                               uint16_t t_send,
679                               uint16_t t_wait4dut, 
680                               uint16_t t_switch,
681                               uint16_t t_back,
682                               bool     autoback,
683                               CSingleObserver *obs_ptr)
684 {
685     Ucs_Return_t result = UCS_RET_SUCCESS;
686
687     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 12U);
688
689     if (msg_ptr != NULL)
690     {
691         msg_ptr->destination_addr    = UCS_ADDR_BROADCAST_BLOCKING; 
692         msg_ptr->id.fblock_id        = FB_EXC;
693         msg_ptr->id.instance_id      = 0U;
694         msg_ptr->id.function_id      = EXC_FID_BC_DIAG;
695         msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
696         msg_ptr->tel.tel_data_ptr[0] = position; 
697         msg_ptr->tel.tel_data_ptr[1] = MISC_HB(admin_na);
698         msg_ptr->tel.tel_data_ptr[2] = MISC_LB(admin_na);
699         msg_ptr->tel.tel_data_ptr[3] = MISC_HB(t_send);
700         msg_ptr->tel.tel_data_ptr[4] = MISC_LB(t_send);
701         msg_ptr->tel.tel_data_ptr[5] = MISC_HB(t_wait4dut);
702         msg_ptr->tel.tel_data_ptr[6] = MISC_LB(t_wait4dut);
703         msg_ptr->tel.tel_data_ptr[7] = MISC_HB(t_switch);
704         msg_ptr->tel.tel_data_ptr[8] = MISC_LB(t_switch);
705         msg_ptr->tel.tel_data_ptr[9] = MISC_HB(t_back);
706         msg_ptr->tel.tel_data_ptr[10] = MISC_LB(t_back);
707         msg_ptr->tel.tel_data_ptr[11] = (uint8_t)autoback;
708
709
710         msg_ptr->info_ptr = &self->ssubs.bcdiag;
711         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
712
713         (void)Ssub_AddObserver(&self->ssubs.bcdiag, obs_ptr);
714     }
715     else
716     {
717         result = UCS_RET_ERR_BUFFER_OVERFLOW;
718     }
719
720     return result;
721 }
722
723
724 /*! Enables the signal during backChannel Diagnosis
725  *
726  * \param *self         Reference to CExc instance
727  * \param port          Number of port which has to be enabled.
728  * \param *obs_ptr      Reference to an optional observer
729  * \return UCS_RET_SUCCESS               message was created 
730  * \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available
731  */
732 Ucs_Return_t Exc_BCEnableTx_StartResult(CExc *self, 
733                                         uint8_t port,
734                                         CSingleObserver *obs_ptr)
735 {
736     Ucs_Return_t result = UCS_RET_SUCCESS;
737
738     Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U);
739
740     if (msg_ptr != NULL)
741     {
742         msg_ptr->destination_addr    = UCS_ADDR_BROADCAST_BLOCKING; 
743         msg_ptr->id.fblock_id        = FB_EXC;
744         msg_ptr->id.instance_id      = 0U;
745         msg_ptr->id.function_id      = EXC_FID_BC_ENABLE_TX;
746         msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
747         msg_ptr->tel.tel_data_ptr[0] = port;
748
749         msg_ptr->info_ptr = &self->ssubs.enabletx;
750         Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
751
752         (void)Ssub_AddObserver(&self->ssubs.enabletx, obs_ptr);
753     }
754     else
755     {
756         result = UCS_RET_ERR_BUFFER_OVERFLOW;
757     }
758
759     return result;
760 }
761
762
763 /*! \brief This function is used to open a memory session. 
764  *
765  *  A memory session is used to control access to the memory resources. Before a memory could 
766  *  be read or written, a session of the appropriate type has to be opened.
767  *  Only a single memory session is supported. Once opened, the session must be first
768  *  closed before a new session of a different type could be used. Some session types
769  *  (0x01, 0x02 and 0x04) require a hardware reset after they were closed.
770  *  Function Exc_MemSessionOpen_Sr() also performs some preprocessing,
771  *  depending on the session_type. This includes clearing of the configuration
772  *  and identification strings before the error memory is programmed or erased.
773  *
774  * \param *self           Reference to CExc instance 
775  * \param target_address  Target address
776  * \param session_type    Defines the set of MemIDs and the memory access type(s) (read and/or write)
777  * \param *obs_ptr        Reference to an optional observer
778  *
779  * \return UCS_RET_SUCCESS message was created and sent to INIC
780  * \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available 
781  * \return UCS_RET_ERR_API_LOCKED        Resource API is already used by another command
782  */
783 Ucs_Return_t Exc_MemSessionOpen_Sr(CExc *self, 
784                                    uint16_t target_address, 
785                                    uint8_t session_type,
786                                    CSingleObserver *obs_ptr)
787 {
788     Ucs_Return_t result = UCS_RET_SUCCESS;
789
790     if(Al_Lock(&self->lock.api, EXC_API_MEM_SESSION_OPEN) != false)
791     {
792         Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 1U);
793
794         if (msg_ptr != NULL)
795         {
796             msg_ptr->destination_addr  = target_address;
797
798             msg_ptr->id.fblock_id        = FB_EXC;
799             msg_ptr->id.instance_id      = 0U;
800             msg_ptr->id.function_id      = EXC_FID_MEM_SESSION_OPEN;
801             msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
802             msg_ptr->tel.tel_data_ptr[0] = session_type; 
803
804             msg_ptr->info_ptr = &self->ssubs.memsessionopen;
805             Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
806
807             (void)Ssub_AddObserver(&self->ssubs.memsessionopen, obs_ptr);
808         }
809         else
810         {
811             Al_Release(&self->lock.api, EXC_API_MEM_SESSION_OPEN);
812             result = UCS_RET_ERR_BUFFER_OVERFLOW;
813         }
814     }
815     else
816     {
817         result = UCS_RET_ERR_API_LOCKED;
818     }
819
820     return result;
821 }
822
823
824 /*! \brief This function is used to close an active memory session that was previously opened by
825  *         function Exc_MemSessionOpen_Sr(). 
826  *
827  *  In addition, the function performs some post-processing on given session types. This includes 
828  *  validation of the newly programmed configuration and identification strings as well as 
829  *  the deactivation of the current configuration and identification strings. In these cases, 
830  *  the new configuration becomes active after a hardware reset.
831  *
832  * \param *self             Reference to CExc instance 
833  * \param target_address    Target address
834  * \param session_handle    Unique number assigned to the active memory session
835  * \param *obs_ptr          Reference to an optional observer
836  *
837  * \return UCS_RET_SUCCESS message was created and sent to INIC
838  * \return UCS_RET_ERR_BUFFER_OVERFLOW   no message buffer available 
839  * \return UCS_RET_ERR_API_LOCKED        Resource API is already used by another command
840  */
841 Ucs_Return_t Exc_MemSessionClose_Sr(CExc *self, 
842                                     uint16_t target_address, 
843                                     uint16_t session_handle,
844                                     CSingleObserver *obs_ptr)
845 {
846     Ucs_Return_t result = UCS_RET_SUCCESS;
847
848     if(Al_Lock(&self->lock.api, EXC_API_MEM_SESSION_CLOSE) != false)
849     {
850         Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 2U);
851
852         if (msg_ptr != NULL)
853         {
854             msg_ptr->destination_addr    = target_address;
855
856             msg_ptr->id.fblock_id        = FB_EXC;
857             msg_ptr->id.instance_id      = 0U;
858             msg_ptr->id.function_id      = EXC_FID_MEM_SESSION_CLOSE;
859             msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
860             msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); 
861             msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); 
862
863             msg_ptr->info_ptr = &self->ssubs.memsessionclose;
864             Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
865
866             (void)Ssub_AddObserver(&self->ssubs.memsessionclose, obs_ptr);
867         }
868         else
869         {
870             Al_Release(&self->lock.api, EXC_API_MEM_SESSION_CLOSE);
871             result = UCS_RET_ERR_BUFFER_OVERFLOW;
872         }
873     }
874     else
875     {
876         result = UCS_RET_ERR_API_LOCKED;
877     }
878
879     return result;
880 }
881
882
883 /*! \brief This function provides read access to the memories described by parameter MemID.
884  *
885  *  In addition, the function can be used to retrieve the active Configuration String and 
886  *  Identification String.
887  *  Reading the memory can only be done within an active memory session. Parameter
888  *  session_handle authorizes the access to the memory resource defined by parameter
889  *  MemID. The session_handle is provided by function Exc_MemSessionOpen_Sr(),
890  *  which must be called in advance to memory access.
891  *
892  * \param *self             Reference to CExc instance 
893  * \param target_address    Target address
894  * \param session_handle    Unique number assigned to the active memory session
895  * \param mem_id            Represents the memory resource to be read
896  * \param address           Defines the memory location at which the reading operation starts
897  * \param unit_len          Sets the number of memory units to be read. Memory units can be 
898  *                          unsigned bytes, unsigned words or unsigned masked data depending 
899  *                          on the memory type.
900  * \param *obs_ptr          Reference to an optional observer
901  *
902  * \return UCS_RET_SUCCESS              message was created and sent to INIC
903  * \return UCS_RET_ERR_BUFFER_OVERFLOW  no message buffer available 
904  * \return UCS_RET_ERR_PARAM            parameter ubit_len ist too big
905  * \return UCS_RET_ERR_API_LOCKED       Resource API is already used by another command
906  */
907 Ucs_Return_t Exc_MemoryRead_Sr(CExc *self, 
908                                uint16_t target_address, 
909                                uint16_t session_handle,
910                                uint8_t  mem_id,
911                                uint32_t address,
912                                uint8_t  unit_len,
913                                CSingleObserver *obs_ptr)
914 {
915     Ucs_Return_t result = UCS_RET_SUCCESS;
916
917     if(Al_Lock(&self->lock.api, EXC_API_MEM_READ) != false)
918     {
919         if (unit_len > MAX_UNIT_LEN)
920         {
921             result = UCS_RET_ERR_PARAM;
922         }
923
924         if (result == UCS_RET_SUCCESS)
925         {
926             Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U);
927
928             if (msg_ptr != NULL)
929             {
930                 msg_ptr->destination_addr    = target_address;
931                 msg_ptr->id.fblock_id        = FB_EXC;
932                 msg_ptr->id.instance_id      = 0U;
933                 msg_ptr->id.function_id      = EXC_FID_MEMORY_READ;
934                 msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
935                 msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); 
936                 msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); 
937                 msg_ptr->tel.tel_data_ptr[2] = mem_id; 
938                 msg_ptr->tel.tel_data_ptr[3] = (uint8_t)((address) >> 24);
939                 msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((address) >> 16);
940                 msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((address) >> 8);
941                 msg_ptr->tel.tel_data_ptr[6] = (uint8_t)(address & (uint32_t)0xFF);
942                 msg_ptr->tel.tel_data_ptr[7] = unit_len; 
943
944                 msg_ptr->info_ptr = &self->ssubs.memoryread;
945                 Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
946
947                 (void)Ssub_AddObserver(&self->ssubs.memoryread, obs_ptr);
948             }
949             else
950             {
951                 Al_Release(&self->lock.api, EXC_API_MEM_READ);
952                 result = UCS_RET_ERR_BUFFER_OVERFLOW;
953             }
954         }
955     }
956     else
957     {
958         result = UCS_RET_ERR_API_LOCKED;
959     }
960
961     return result;
962 }
963
964
965 /*! \brief This function provides write access to the memories described by parameter MemID. 
966  *
967  *  In addition, the function can be used to program a new Configuration String and Identification
968  *  String.
969  *  Writing the memory can only be done within an active memory session. Parameter
970  *  SessionHandle authorizes the access to the memory resource defined by parameter
971  *  MemID. The SessionHandle is provided by function ExtendedNetworkControl.MemorySessionOpen(),
972  *  which must be called in advance to memory access.
973  *
974  * \param *self             Reference to CExc instance 
975  * \param target_address    Target address
976  * \param session_handle    Unique number assigned to the active memory session
977  * \param mem_id            Represents the memory resource to be read
978  * \param address           Defines the memory location at which the reading operation starts
979  * \param unit_len          Sets the number of memory units to be read. Memory units can be 
980  *                          unsigned bytes, unsigned words or unsigned masked data depending 
981  *                          on the memory type.
982  * \param *unit_data        Contains the actual data written to the memory resource and formatted 
983  *                          as memory units
984  * \param *obs_ptr          Reference to an optional observer
985  *
986  * \return UCS_RET_SUCCESS              message was created and sent to INIC
987  * \return UCS_RET_ERR_BUFFER_OVERFLOW  no message buffer available 
988  * \return UCS_RET_ERR_PARAM            parameter ubit_len ist too big
989  * \return UCS_RET_ERR_API_LOCKED       Resource API is already used by another command
990  */
991 Ucs_Return_t Exc_MemoryWrite_Sr(CExc *self, 
992                                 uint16_t target_address, 
993                                 uint16_t session_handle,
994                                 uint8_t  mem_id,
995                                 uint32_t address,
996                                 uint8_t  unit_len,
997                                 uint8_t  unit_data[],
998                                 CSingleObserver *obs_ptr)
999 {
1000     Ucs_Return_t result = UCS_RET_SUCCESS;
1001
1002     if(Al_Lock(&self->lock.api, EXC_API_MEM_WRITE) != false)
1003     {
1004         if (unit_len > MAX_UNIT_LEN)
1005         {
1006             result = UCS_RET_ERR_PARAM;
1007         }
1008
1009         if (result == UCS_RET_SUCCESS)
1010         {
1011             Msg_MostTel_t *msg_ptr = Trcv_TxAllocateMsg(self->xcvr_ptr, 8U + unit_len);
1012
1013             if (msg_ptr != NULL)
1014             {
1015                 uint8_t i;
1016
1017                 msg_ptr->destination_addr    = target_address;
1018                 msg_ptr->id.fblock_id        = FB_EXC;
1019                 msg_ptr->id.instance_id      = 0U;
1020                 msg_ptr->id.function_id      = EXC_FID_MEMORY_WRITE;
1021                 msg_ptr->id.op_type          = UCS_OP_STARTRESULT;
1022                 msg_ptr->tel.tel_data_ptr[0] = MISC_HB(session_handle); 
1023                 msg_ptr->tel.tel_data_ptr[1] = MISC_LB(session_handle); 
1024                 msg_ptr->tel.tel_data_ptr[2] = mem_id; 
1025                 msg_ptr->tel.tel_data_ptr[3] = (uint8_t)((address) >> 24);
1026                 msg_ptr->tel.tel_data_ptr[4] = (uint8_t)((address) >> 16);
1027                 msg_ptr->tel.tel_data_ptr[5] = (uint8_t)((address) >> 8);
1028                 msg_ptr->tel.tel_data_ptr[6] = (uint8_t)(address & (uint32_t)0xFF);
1029                 msg_ptr->tel.tel_data_ptr[7] = unit_len; 
1030                 for (i=0U; i<unit_len; ++i)
1031                 {
1032                     msg_ptr->tel.tel_data_ptr[8U+i] = *(unit_data + i);
1033                 }
1034
1035                 msg_ptr->info_ptr = &self->ssubs.memorywrite;
1036                 Trcv_TxSendMsg(self->xcvr_ptr, msg_ptr);
1037
1038                 (void)Ssub_AddObserver(&self->ssubs.memorywrite, obs_ptr);
1039             }
1040             else
1041             {
1042                 Al_Release(&self->lock.api, EXC_API_MEM_WRITE);
1043                 result = UCS_RET_ERR_BUFFER_OVERFLOW;
1044             }
1045         }
1046     }
1047     else
1048     {
1049         result = UCS_RET_ERR_API_LOCKED;
1050     }
1051
1052     return result;
1053 }
1054
1055
1056
1057 /*------------------------------------------------------------------------------------------------*/
1058 /* Handler functions                                                                              */
1059 /*------------------------------------------------------------------------------------------------*/
1060 /*! \brief Handler function for EXC.Hello.Status
1061  *  \param  self        Reference to EXC object
1062  *  \param  msg_ptr     Received message
1063  */
1064 static void Exc_Hello_Status(void *self, Msg_MostTel_t *msg_ptr)
1065 {
1066     CExc *self_ = (CExc *)self;
1067     Exc_HelloStatus_t hello_data; 
1068     Exc_StdResult_t res_data;
1069
1070     if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1  + 1U))
1071     {
1072         hello_data.version =    msg_ptr->tel.tel_data_ptr[0];
1073         Exc_Read_Signature(&(hello_data.signature), &(msg_ptr->tel.tel_data_ptr[1]));
1074
1075         res_data.data_info        = &hello_data;
1076         res_data.result.code      = UCS_RES_SUCCESS;
1077         res_data.result.info_ptr  = NULL;
1078         res_data.result.info_size = 0U;
1079
1080         /* Node Discovery sends the Hello.Get as broadcast message. So we will need the observer
1081            several times. */ 
1082         Ssub_Notify(&self_->ssubs.hello, &res_data, false); 
1083     }
1084 }
1085
1086
1087 /*! \brief Handler function for EXC.Hello.Error
1088  * \param  self     reference to EXC object
1089  * \param  msg_ptr  received message
1090  */
1091 static void Exc_Hello_Error(void *self, Msg_MostTel_t *msg_ptr)
1092 {
1093     CExc *self_ = (CExc *)self;
1094     Exc_StdResult_t res_data;
1095
1096     if (msg_ptr->tel.tel_len > 0U)
1097     {
1098         res_data.data_info  = NULL;
1099         res_data.result = Exc_TranslateError(self_,
1100                                              &msg_ptr->tel.tel_data_ptr[0], 
1101                                              (uint8_t)(msg_ptr->tel.tel_len));
1102
1103         /* Node Discovery sends the Hello.Get as broadcast message. So we will need the observer
1104            several times. */ 
1105         Ssub_Notify(&self_->ssubs.hello, &res_data, false);
1106     }
1107 }
1108
1109
1110 /*! \brief Handler function for EXC.Welcome.Error
1111  * \param  self     reference to EXC object
1112  * \param  msg_ptr  received message
1113  */
1114 static void Exc_Welcome_Error(void *self, Msg_MostTel_t *msg_ptr)
1115 {
1116     CExc *self_ = (CExc *)self;
1117     Exc_StdResult_t res_data;
1118
1119     if (msg_ptr->tel.tel_len > 0U)
1120     {
1121         res_data.data_info  = NULL;
1122         res_data.result = Exc_TranslateError(self_,
1123                                              &msg_ptr->tel.tel_data_ptr[0], 
1124                                              (uint8_t)(msg_ptr->tel.tel_len));
1125
1126         Ssub_Notify(&self_->ssubs.welcome, &res_data, true);
1127     }
1128 }
1129
1130 /*! \brief Handler function for the EXC.Welcome.Result message
1131  * \param  self     reference to EXC object
1132  * \param  msg_ptr  received message
1133  */
1134 static void Exc_Welcome_Result(void *self, Msg_MostTel_t *msg_ptr)
1135 {
1136     CExc *self_ = (CExc *)self;
1137     Exc_WelcomeResult_t welcome_data; 
1138     Exc_StdResult_t res_data;
1139
1140     if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1  + 2U))
1141     {
1142         welcome_data.res = msg_ptr->tel.tel_data_ptr[0];
1143         welcome_data.version = msg_ptr->tel.tel_data_ptr[1];
1144         Exc_Read_Signature(&(welcome_data.signature), &(msg_ptr->tel.tel_data_ptr[2]));
1145         res_data.data_info       = &welcome_data;
1146         res_data.result.code     = UCS_RES_SUCCESS;
1147         res_data.result.info_ptr = NULL;
1148
1149         Ssub_Notify(&self_->ssubs.welcome, &res_data, true);
1150     }
1151 }
1152
1153
1154 /*! Handler function for the EXC.Signature.Status message
1155  * \param  self     reference to EXC object
1156  * \param  msg_ptr  received message
1157  */
1158 static void Exc_Signature_Status(void *self, Msg_MostTel_t *msg_ptr)
1159 {
1160     CExc *self_ = (CExc *)self;
1161     Exc_SignatureStatus_t signature_data; 
1162     Exc_StdResult_t res_data;
1163
1164     if (msg_ptr->tel.tel_len >= (EXC_SIGNATURE_LEN_V1  + 1U))
1165     {
1166         signature_data.version =    msg_ptr->tel.tel_data_ptr[0];
1167         Exc_Read_Signature(&(signature_data.signature), &(msg_ptr->tel.tel_data_ptr[1]));
1168
1169         res_data.data_info       = &signature_data;
1170         res_data.result.code     = UCS_RES_SUCCESS;
1171         res_data.result.info_ptr = NULL;
1172         res_data.result.info_size = 0U;
1173
1174         Ssub_Notify(&self_->ssubs.signature, &res_data, true);
1175     }
1176 }
1177
1178
1179 /*! Handler function for the EXC.Signature.Error message
1180  * \param  self     reference to EXC object
1181  * \param  msg_ptr  received message
1182  */
1183 static void Exc_Signature_Error(void *self, Msg_MostTel_t *msg_ptr)
1184 {
1185     CExc *self_ = (CExc *)self;
1186     Exc_StdResult_t res_data;
1187
1188     if (msg_ptr->tel.tel_len > 0U)
1189     {
1190         res_data.data_info  = NULL;
1191         res_data.result = Exc_TranslateError(self_,
1192                                              &msg_ptr->tel.tel_data_ptr[0], 
1193                                              (uint8_t)(msg_ptr->tel.tel_len));
1194
1195         Ssub_Notify(&self_->ssubs.signature, &res_data, true);
1196     }
1197 }
1198
1199
1200 /*! Handler function for the EXC.DeviceInit.Error message
1201  * \param  self     reference to EXC object
1202  * \param  msg_ptr  received message
1203  */
1204 static void Exc_DeviceInit_Error(void *self, Msg_MostTel_t *msg_ptr)
1205 {
1206     CExc *self_ = (CExc *)self;
1207     Exc_StdResult_t res_data;
1208
1209     if (msg_ptr->tel.tel_len >0U)
1210     {
1211         res_data.data_info  = NULL;
1212         res_data.result = Exc_TranslateError(self_,
1213                                              &msg_ptr->tel.tel_data_ptr[0], 
1214                                              (uint8_t)(msg_ptr->tel.tel_len));
1215
1216         Ssub_Notify(&self_->ssubs.deviceinit, &res_data, true);
1217     }
1218 }
1219
1220
1221 /*! \brief Handler function for EXC.EnablePort.Error
1222  * \param  self     reference to EXC object
1223  * \param  msg_ptr  received message
1224  */
1225 static void Exc_EnablePort_Error(void *self, Msg_MostTel_t *msg_ptr)
1226 {
1227     CExc *self_ = (CExc *)self;
1228     Exc_StdResult_t res_data;
1229
1230     if (msg_ptr->tel.tel_len > 0U)
1231     {
1232         res_data.result = Exc_TranslateError(self_, 
1233                                              &msg_ptr->tel.tel_data_ptr[0], 
1234                                              (uint8_t)(msg_ptr->tel.tel_len));
1235
1236         Ssub_Notify(&self_->ssubs.enableport, &res_data, true);
1237     }
1238 }
1239
1240 /*! \brief Handler function for EXC.EnablePort.Result
1241  * \param  self     reference to EXC object
1242  * \param  msg_ptr  received message
1243  */
1244 static void Exc_EnablePort_Result(void *self, Msg_MostTel_t *msg_ptr)
1245 {
1246     CExc *self_ = (CExc *)self;
1247     Exc_StdResult_t res_data;
1248
1249     MISC_UNUSED(msg_ptr);
1250
1251     res_data.result.code = UCS_RES_SUCCESS;
1252     res_data.result.info_ptr = NULL;
1253     Ssub_Notify(&self_->ssubs.enableport, &res_data, true);
1254 }
1255
1256
1257 /*! \brief Handler function for EXC.CableLinkDiag.Error
1258  * \param  self     reference to EXC object
1259  * \param  msg_ptr  received message
1260  */
1261 static void Exc_CableLinkDiag_Error(void *self, Msg_MostTel_t *msg_ptr)
1262 {
1263     CExc *self_ = (CExc *)self;
1264     Exc_StdResult_t res_data;
1265
1266     if (msg_ptr->tel.tel_len > 0U)   
1267     {
1268         res_data.data_info  = NULL;
1269         res_data.result = Exc_TranslateError(self_,
1270                                              &msg_ptr->tel.tel_data_ptr[0],
1271                                              (uint8_t)(msg_ptr->tel.tel_len));
1272
1273         Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, true);
1274     }
1275 }
1276
1277 /*! \brief Handler function for EXC.CableLinkDiag.Result
1278  * \param  self     reference to EXC object
1279  * \param  msg_ptr  received message
1280  */
1281 static void Exc_CableLinkDiag_Result(void *self, Msg_MostTel_t *msg_ptr)
1282 {
1283     CExc *self_ = (CExc *)self;
1284     Exc_CableLinkDiagResult_t cable_link_diag_result_data; 
1285     Exc_StdResult_t res_data;
1286
1287     if (msg_ptr->tel.tel_len > 0U)
1288     {
1289         cable_link_diag_result_data.port_number = msg_ptr->tel.tel_data_ptr[0];
1290         cable_link_diag_result_data.result      = msg_ptr->tel.tel_data_ptr[1];
1291         res_data.data_info       = &cable_link_diag_result_data;
1292         res_data.result.code     = UCS_RES_SUCCESS;
1293         res_data.result.info_ptr = NULL;
1294
1295         Ssub_Notify(&self_->ssubs.cablelinkdiag, &res_data, true);
1296     }
1297 }
1298
1299
1300 /*! \brief Handler function for EXC.PhysicalLayerTest.Error
1301  * \param  self     reference to EXC object
1302  * \param  msg_ptr  received message
1303  */static void Exc_NwPhyTest_Error(void *self, Msg_MostTel_t *msg_ptr)
1304 {
1305     CExc *self_ = (CExc *)self;
1306     Exc_StdResult_t res_data;
1307
1308     if (msg_ptr->tel.tel_len > 0U)
1309     {
1310         res_data.data_info  = NULL;
1311         res_data.result = Exc_TranslateError(self_,
1312                                              &msg_ptr->tel.tel_data_ptr[0], 
1313                                              (uint8_t)(msg_ptr->tel.tel_len));
1314
1315         Ssub_Notify(&self_->ssubs.phylaytest, &res_data, true);
1316     }
1317 }
1318
1319
1320 /*! \brief Handler function for EXC.MOSTNetworkPhysicalLayerTestResult.Status
1321  *  \param  self        Reference to EXC object
1322  *  \param  msg_ptr     Received message
1323  */
1324 static void Exc_NwPhyTestResult_Status(void *self, Msg_MostTel_t *msg_ptr)
1325 {
1326     CExc *self_ = (CExc *)self;
1327     Exc_PhyTestResult_t phy_test_result;
1328     Exc_StdResult_t res_data;
1329
1330     if (msg_ptr->tel.tel_len > 0U)
1331     {
1332         phy_test_result.port_number = msg_ptr->tel.tel_data_ptr[0];
1333         phy_test_result.lock_status = (msg_ptr->tel.tel_data_ptr[1] != 0U) ? true : false;
1334         MISC_DECODE_WORD(&(phy_test_result.err_count), &(msg_ptr->tel.tel_data_ptr[2]));
1335         res_data.data_info       = &phy_test_result;
1336         res_data.result.code     = UCS_RES_SUCCESS;
1337         res_data.result.info_ptr = NULL;
1338
1339         Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, true);
1340     }
1341     Al_Release(&self_->lock.api, EXC_API_PHY_LAY_TEST_RESULT);
1342 }
1343
1344
1345 /*! \brief Handler function for EXC.MOSTNetworkPhysicalLayerTestResult.Error
1346  * \param  self     reference to EXC object
1347  * \param  msg_ptr  received message
1348  */
1349 static void Exc_NwPhyTestResult_Error(void *self, Msg_MostTel_t *msg_ptr)
1350 {
1351     CExc *self_ = (CExc *)self;
1352     Exc_StdResult_t res_data;
1353
1354     if (msg_ptr->tel.tel_len > 0U)
1355     {
1356         res_data.data_info  = NULL;
1357         res_data.result = Exc_TranslateError(self_,
1358                                              &msg_ptr->tel.tel_data_ptr[0], 
1359                                              (uint8_t)(msg_ptr->tel.tel_len));
1360
1361         Ssub_Notify(&self_->ssubs.phylaytestresult, &res_data, true);
1362     }
1363     Al_Release(&self_->lock.api, EXC_API_PHY_LAY_TEST_RESULT);
1364 }
1365
1366
1367
1368 /*! \brief Handler function for EXC.BCDiag.Status
1369  *  \param  self        Reference to EXC object
1370  *  \param  msg_ptr     Received message
1371  */
1372 static void Exc_BC_Diag_Result(void *self, Msg_MostTel_t *msg_ptr)
1373 {
1374     CExc *self_ = (CExc *)self;
1375     Exc_BCDiagResult bcd_result;
1376     Exc_StdResult_t res_data;
1377
1378     if (msg_ptr->tel.tel_len > 1U)
1379     {
1380         bcd_result.diag_result = (Exc_BCDiagResValue)(msg_ptr->tel.tel_data_ptr[0] >> 4U);
1381         MISC_DECODE_WORD(&(bcd_result.admin_addr), &(msg_ptr->tel.tel_data_ptr[0]));
1382         bcd_result.admin_addr   &= 0x0FFFU;
1383         res_data.data_info       = &bcd_result;
1384         res_data.result.code     = UCS_RES_SUCCESS;
1385         res_data.result.info_ptr = NULL;
1386
1387         Ssub_Notify(&self_->ssubs.bcdiag, &res_data, true);
1388     }
1389 }
1390
1391
1392 /*! \brief Handler function for EXC.BCDiag.Error
1393  * \param  self     reference to EXC object
1394  * \param  msg_ptr  received message
1395  */
1396 static void Exc_BC_Diag_Error(void *self, Msg_MostTel_t *msg_ptr)
1397 {
1398     CExc *self_ = (CExc *)self;
1399     Exc_StdResult_t res_data;
1400
1401     if (msg_ptr->tel.tel_len > 0U)
1402     {
1403         res_data.data_info  = NULL;
1404         res_data.result = Exc_TranslateError(self_,
1405                                              &msg_ptr->tel.tel_data_ptr[0], 
1406                                              (uint8_t)(msg_ptr->tel.tel_len));
1407
1408         Ssub_Notify(&self_->ssubs.bcdiag, &res_data, true);
1409     }
1410 }
1411
1412
1413
1414
1415 /*! \brief Handler function for EXC.BCEnableTx.Result
1416  *  \param  self        Reference to EXC object
1417  *  \param  msg_ptr     Received message
1418  */
1419 static void Exc_BC_EnableTx_Result(void *self, Msg_MostTel_t *msg_ptr)
1420 {
1421     CExc *self_ = (CExc *)self;
1422     Exc_StdResult_t res_data;
1423
1424     res_data.data_info       = NULL;
1425     res_data.result.code     = UCS_RES_SUCCESS;
1426     res_data.result.info_ptr = NULL;
1427
1428     Ssub_Notify(&self_->ssubs.enabletx, &res_data, true);
1429
1430     MISC_UNUSED(msg_ptr);
1431 }
1432
1433
1434 /*! \brief Handler function for EXC.BCEnableTx.Error
1435  * \param  self     reference to EXC object
1436  * \param  msg_ptr  received message
1437  */
1438 static void Exc_BC_EnableTx_Error(void *self, Msg_MostTel_t *msg_ptr)
1439 {
1440     CExc *self_ = (CExc *)self;
1441     Exc_StdResult_t res_data;
1442
1443     if (msg_ptr->tel.tel_len > 0U)
1444     {
1445         res_data.data_info  = NULL;
1446         res_data.result = Exc_TranslateError(self_,
1447                                              &msg_ptr->tel.tel_data_ptr[0], 
1448                                              (uint8_t)(msg_ptr->tel.tel_len));
1449
1450         Ssub_Notify(&self_->ssubs.enabletx, &res_data, true);
1451     }
1452 }
1453
1454
1455 /*! \brief Handler function for EXC.MemorySessionOpen.Result
1456  *  \param  self     reference to EXC object
1457  *  \param  msg_ptr  received message
1458  */
1459 static void Exc_MemSessionOpen_Result(void *self, Msg_MostTel_t *msg_ptr)
1460 {
1461     CExc *self_ = (CExc *)self;
1462     uint16_t session_handle;
1463     Exc_StdResult_t res_data;
1464
1465     if (msg_ptr->tel.tel_len > 0U)
1466     {
1467         MISC_DECODE_WORD(&(session_handle),  &(msg_ptr->tel.tel_data_ptr[0]));
1468         res_data.data_info       = &session_handle;
1469         res_data.result.code     = UCS_RES_SUCCESS;
1470         res_data.result.info_ptr = NULL;
1471
1472         Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, true);
1473     }
1474     Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_OPEN);
1475 }
1476
1477
1478 /*! \brief Handler function for EXC.MemorySessionOpen.Error
1479  *  \param  self     reference to EXC object
1480  *  \param  msg_ptr  received message
1481  */
1482 static void Exc_MemSessionOpen_Error(void *self, Msg_MostTel_t *msg_ptr)
1483 {
1484     CExc *self_ = (CExc *)self;
1485     Exc_StdResult_t res_data;
1486
1487     if (msg_ptr->tel.tel_len > 0U)
1488     {
1489         res_data.data_info  = NULL;
1490         res_data.result = Exc_TranslateError(self_,
1491                                              &msg_ptr->tel.tel_data_ptr[0], 
1492                                              (uint8_t)(msg_ptr->tel.tel_len));
1493
1494         Ssub_Notify(&self_->ssubs.memsessionopen, &res_data, true);
1495     }
1496     Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_OPEN);
1497 }
1498
1499
1500 /*! \brief Handler function for EXC.MemorySessionClose.Result
1501  *  \param  self     reference to EXC object
1502  *  \param  msg_ptr  received message
1503  */
1504 static void Exc_MemSessionClose_Result(void *self, Msg_MostTel_t *msg_ptr)
1505 {
1506     CExc *self_ = (CExc *)self;
1507     uint8_t session_result;
1508     Exc_StdResult_t res_data;
1509
1510     if (msg_ptr->tel.tel_len > 0U)
1511     {
1512         session_result = msg_ptr->tel.tel_data_ptr[0];
1513         res_data.data_info       = &session_result;
1514         res_data.result.code     = UCS_RES_SUCCESS;
1515         res_data.result.info_ptr = NULL;
1516
1517         Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, true);
1518     }
1519     Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_CLOSE);
1520 }
1521
1522 /*! \brief Handler function for EXC.MemorySessionClose.Error
1523  *  \param  self     reference to EXC object
1524  *  \param  msg_ptr  received message
1525  */
1526 static void Exc_MemSessionClose_Error(void *self, Msg_MostTel_t *msg_ptr)
1527 {
1528     CExc *self_ = (CExc *)self;
1529     Exc_StdResult_t res_data;
1530
1531     if (msg_ptr->tel.tel_len > 0U)
1532     {
1533         res_data.data_info  = NULL;
1534         res_data.result = Exc_TranslateError(self_,
1535                                              &msg_ptr->tel.tel_data_ptr[0], 
1536                                              (uint8_t)(msg_ptr->tel.tel_len));
1537
1538         Ssub_Notify(&self_->ssubs.memsessionclose, &res_data, true);
1539     }
1540     Al_Release(&self_->lock.api, EXC_API_MEM_SESSION_CLOSE);
1541 }
1542
1543 /*! \brief Handler function for EXC.MemoryRead.Result
1544  *  \param  self     reference to EXC object
1545  *  \param  msg_ptr  received message
1546  */
1547 static void Exc_MemoryRead_Result(void *self, Msg_MostTel_t *msg_ptr)
1548 {
1549     CExc *self_ = (CExc *)self;
1550     Exc_MemReadResult_t mem_read_result; 
1551     Exc_StdResult_t res_data;
1552     uint8_t i;
1553
1554     if (msg_ptr->tel.tel_len > 0U)
1555     {
1556         MISC_DECODE_WORD(&(mem_read_result.session_handle), &(msg_ptr->tel.tel_data_ptr[0]));
1557         mem_read_result.mem_id = msg_ptr->tel.tel_data_ptr[2];
1558         MISC_DECODE_DWORD(&(mem_read_result.address), &(msg_ptr->tel.tel_data_ptr[3]));
1559         mem_read_result.unit_len = msg_ptr->tel.tel_data_ptr[7];
1560         for (i=0U; (i<mem_read_result.unit_len) && (i<MAX_UNIT_LEN); ++i)
1561         {
1562             mem_read_result.unit_data[i] = msg_ptr->tel.tel_data_ptr[8U+i];
1563         }
1564
1565         res_data.data_info       = &mem_read_result;
1566         res_data.result.code     = UCS_RES_SUCCESS;
1567         res_data.result.info_ptr = NULL;
1568
1569         Ssub_Notify(&self_->ssubs.memoryread, &res_data, true);
1570     }
1571     Al_Release(&self_->lock.api, EXC_API_MEM_READ);
1572 }
1573
1574
1575 /*! \brief Handler function for EXC.MemoryRead.Error
1576  *  \param  self     reference to EXC object
1577  *  \param  msg_ptr  received message
1578  */
1579 static void Exc_MemoryRead_Error(void *self, Msg_MostTel_t *msg_ptr)
1580 {
1581     CExc *self_ = (CExc *)self;
1582     Exc_StdResult_t res_data;
1583
1584     if (msg_ptr->tel.tel_len > 0U)
1585     {
1586         res_data.data_info  = NULL;
1587         res_data.result = Exc_TranslateError(self_,
1588                                              &msg_ptr->tel.tel_data_ptr[0], 
1589                                              (uint8_t)(msg_ptr->tel.tel_len));
1590
1591         Ssub_Notify(&self_->ssubs.memoryread, &res_data, true);
1592     }
1593     Al_Release(&self_->lock.api, EXC_API_MEM_READ);
1594 }
1595
1596
1597 /*! \brief Handler function for EXC.MemoryWrite.Result
1598  *  \param  self     reference to EXC object
1599  *  \param  msg_ptr  received message
1600  */
1601 static void Exc_MemoryWrite_Result(void *self, Msg_MostTel_t *msg_ptr)
1602 {
1603     CExc *self_ = (CExc *)self;
1604     Exc_MemWriteResult_t mem_write_result; 
1605     Exc_StdResult_t res_data;
1606
1607     if (msg_ptr->tel.tel_len > 0U)
1608     {
1609         MISC_DECODE_WORD(&(mem_write_result.session_handle), &(msg_ptr->tel.tel_data_ptr[0]));
1610         mem_write_result.mem_id = msg_ptr->tel.tel_data_ptr[2];
1611
1612         res_data.data_info       = &mem_write_result;
1613         res_data.result.code     = UCS_RES_SUCCESS;
1614         res_data.result.info_ptr = NULL;
1615
1616         Ssub_Notify(&self_->ssubs.memorywrite, &res_data, true);
1617     }
1618     Al_Release(&self_->lock.api, EXC_API_MEM_WRITE);
1619 }
1620
1621
1622 /*! \brief Handler function for EXC.MemoryWrite.Error
1623  *  \param  self     reference to EXC object
1624  *  \param  msg_ptr  received message
1625  */
1626 static void Exc_MemoryWrite_Error(void *self, Msg_MostTel_t *msg_ptr)
1627 {
1628     CExc *self_ = (CExc *)self;
1629     Exc_StdResult_t res_data;
1630
1631     if (msg_ptr->tel.tel_len > 0U)
1632     {
1633         res_data.data_info  = NULL;
1634         res_data.result = Exc_TranslateError(self_,
1635                                              &msg_ptr->tel.tel_data_ptr[0], 
1636                                              (uint8_t)(msg_ptr->tel.tel_len));
1637
1638         Ssub_Notify(&self_->ssubs.memorywrite, &res_data, true);
1639     }
1640     Al_Release(&self_->lock.api, EXC_API_MEM_WRITE);
1641 }
1642
1643
1644
1645 /*------------------------------------------------------------------------------------------------*/
1646 /* Helper functions                                                                               */
1647 /*------------------------------------------------------------------------------------------------*/
1648 /*! \brief Translates EXC error codes into UNICENS error codes and wraps the raw INIC
1649  *         error data to a byte stream.
1650  *  \param self         Instance of CExc
1651  *  \param error_data[] EXC error data
1652  *  \param error_size   Size of EXC error data in bytes
1653  *  \return             The formatted error
1654  */
1655 static Ucs_StdResult_t Exc_TranslateError(CExc *self, uint8_t error_data[], uint8_t error_size)
1656 {
1657     Ucs_StdResult_t ret_val;
1658     MISC_UNUSED(self);
1659
1660     if(error_data[0] != 0x20U)
1661     {
1662         ret_val.code = UCS_RES_ERR_MOST_STANDARD;
1663     }
1664     else
1665     {
1666         ret_val.code = (Ucs_Result_t)(error_data[1] + 1U);
1667     }
1668
1669     ret_val.info_ptr  = &error_data[0];
1670     ret_val.info_size = error_size;
1671
1672     return ret_val;
1673 }
1674
1675
1676 /*! \brief  Reads a signature from a message's payload 
1677  *
1678  * \param dest      Pointer to signature 
1679  * \param source    Pointer to start of signature inabyte array
1680  */
1681 static void Exc_Read_Signature(Ucs_Signature_t *dest, uint8_t source[])
1682 {
1683     MISC_DECODE_WORD(&(dest->node_address),  source);
1684     MISC_DECODE_WORD(&(dest->group_address), &(source[2]));
1685     MISC_DECODE_WORD(&(dest->mac_47_32),     &(source[4]));
1686     MISC_DECODE_WORD(&(dest->mac_31_16),     &(source[6]));
1687     MISC_DECODE_WORD(&(dest->mac_15_0),      &(source[8]));
1688     MISC_DECODE_WORD(&(dest->node_pos_addr), &(source[10]));
1689     MISC_DECODE_WORD(&(dest->diagnosis_id),  &(source[12]));
1690     dest->num_ports  = source[14];
1691     dest->chip_id    = source[15];
1692     dest->fw_major   = source[16];
1693     dest->fw_minor   = source[17];
1694     dest->fw_release = source[18];
1695     MISC_DECODE_DWORD(&(dest->fw_build),  &(source[19]));
1696     dest->cs_major   = source[23];
1697     dest->cs_minor   = source[24];
1698     dest->cs_release = source[25];
1699 /*    dest->uid_persistency = source[26];*/                 /* Signature v1 */
1700 /*    MISC_DECODE_DWORD(&(dest->uid),  &(source[27]));*/
1701
1702 }
1703 /*!
1704  * @}
1705  * \endcond
1706  */
1707
1708 /*------------------------------------------------------------------------------------------------*/
1709 /* End of file                                                                                    */
1710 /*------------------------------------------------------------------------------------------------*/
1711