nilfs2: segment usage file
[linux-2.6] / drivers / staging / epl / EplObd.c
1 /****************************************************************************
2
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5
6   Project:      openPOWERLINK
7
8   Description:  source file for api function of EplOBD-Module
9
10   License:
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40
41     Severability Clause:
42
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49
50   -------------------------------------------------------------------------
51
52                 $RCSfile: EplObd.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.12 $  $Date: 2008/10/17 15:32:32 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                 Microsoft VC7
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/06/02 k.t.:   start of the implementation, version 1.00
68                      ->based on CANopen OBD-Modul
69
70 ****************************************************************************/
71
72 #include "EplInc.h"
73 #include "kernel/EplObdk.h"     // function prototyps of the EplOBD-Modul
74
75 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
76
77 /***************************************************************************/
78 /*                                                                         */
79 /*                                                                         */
80 /*          G L O B A L   D E F I N I T I O N S                            */
81 /*                                                                         */
82 /*                                                                         */
83 /***************************************************************************/
84
85 //---------------------------------------------------------------------------
86 // const defines
87 //---------------------------------------------------------------------------
88
89 // float definitions and macros
90 #define _SHIFTED_EXPONENT_MASK_SP   0xff
91 #define _BIAS_SP                    126
92 #define T_SP                        23
93 #define EXPONENT_DENORM_SP          (-_BIAS_SP)
94 #define BASE_TO_THE_T_SP            ((float) 8388608.0)
95 #define GET_EXPONENT_SP(x)          ((((x) >> T_SP) & _SHIFTED_EXPONENT_MASK_SP) - _BIAS_SP)
96
97 //---------------------------------------------------------------------------
98 // local types
99 //---------------------------------------------------------------------------
100
101 // struct for instance table
102 INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER()
103
104 STATIC tEplObdInitParam m_ObdInitParam;
105 STATIC tEplObdStoreLoadObjCallback m_fpStoreLoadObjCallback;
106
107 INSTANCE_TYPE_END
108 // decomposition of float
109 typedef union {
110         tEplObdReal32 m_flRealPart;
111         int m_nIntegerPart;
112
113 } tEplObdRealParts;
114
115 //---------------------------------------------------------------------------
116 // modul globale vars
117 //---------------------------------------------------------------------------
118
119 // This macro replace the unspecific pointer to an instance through
120 // the modul specific type for the local instance table. This macro
121 // must defined in each modul.
122 //#define tEplPtrInstance             tEplInstanceInfo *
123
124 EPL_MCO_DECL_INSTANCE_VAR()
125
126 u8 abEplObdTrashObject_g[8];
127
128 //---------------------------------------------------------------------------
129 // local function prototypes
130 //---------------------------------------------------------------------------
131
132 EPL_MCO_DEFINE_INSTANCE_FCT()
133
134 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
135                                            tEplObdCallback fpCallback_p,
136                                            tEplObdCbParam *pCbParam_p);
137
138 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p);
139
140 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
141                                    tEplObdSize ObjLen_p, tEplObdType ObjType_p);
142
143 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
144 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
145                                          void *pData_p);
146 #endif
147
148 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
149                                     tEplObdVarEntry **ppVarEntry_p);
150
151 static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
152                                  unsigned int uiIndex_p,
153                                  unsigned int uiSubindex_p,
154                                  tEplObdEntryPtr * ppObdEntry_p,
155                                  tEplObdSubEntryPtr * ppObdSubEntry_p);
156
157 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p);
158
159 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p,
160                                        unsigned int uiIndex_p,
161                                        tEplObdEntryPtr * ppObdEntry_p);
162
163 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
164                                           unsigned int uiSubIndex_p,
165                                           tEplObdSubEntryPtr * ppObdSubEntry_p);
166
167 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
168                                            tEplObdPart CurrentOdPart_p,
169                                            tEplObdEntryPtr pObdEnty_p,
170                                            tEplObdDir Direction_p);
171
172 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
173 static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
174
175 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
176
177 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdCbStoreParam *pCbStoreParam_p);
178
179 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
180
181 static void EplObdCopyObjectData(void *pDstData_p,
182                                  void *pSrcData_p,
183                                  tEplObdSize ObjSize_p, tEplObdType ObjType_p);
184
185 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p);
186
187 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
188                                           BOOL * pfEntryNumerical_p);
189
190 static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
191                                       unsigned int uiSubIndex_p,
192                                       void *pSrcData_p,
193                                       void **ppDstData_p,
194                                       tEplObdSize Size_p,
195                                       tEplObdEntryPtr *ppObdEntry_p,
196                                       tEplObdSubEntryPtr *ppSubEntry_p,
197                                       tEplObdCbParam *pCbParam_p,
198                                       tEplObdSize *pObdSize_p);
199
200 static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p,
201                                        tEplObdSubEntryPtr pSubEntry_p,
202                                        tEplObdCbParam *pCbParam_p,
203                                        void *pSrcData_p,
204                                        void *pDstData_p,
205                                        tEplObdSize ObdSize_p);
206
207 //=========================================================================//
208 //                                                                         //
209 //          P U B L I C   F U N C T I O N S                                //
210 //                                                                         //
211 //=========================================================================//
212
213 //---------------------------------------------------------------------------
214 //
215 // Function:    EplObdInit()
216 //
217 // Description: initializes the first instance
218 //
219 // Parameters:  pInitParam_p    = init parameter
220 //
221 // Return:      tEplKernel      =   errorcode
222 //
223 // State:
224 //
225 //---------------------------------------------------------------------------
226
227 tEplKernel EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p)
228 {
229
230         tEplKernel Ret;
231         EPL_MCO_DELETE_INSTANCE_TABLE();
232
233         if (pInitParam_p == NULL) {
234                 Ret = kEplSuccessful;
235                 goto Exit;
236         }
237
238         Ret = EplObdAddInstance(EPL_MCO_PTR_INSTANCE_PTR_ pInitParam_p);
239
240       Exit:
241         return Ret;
242
243 }
244
245 //---------------------------------------------------------------------------
246 //
247 // Function:    EplObdAddInstance()
248 //
249 // Description: adds a new instance
250 //
251 // Parameters:  pInitParam_p
252 //
253 // Return:      tEplKernel
254 //
255 // State:
256 //
257 //---------------------------------------------------------------------------
258
259 tEplKernel EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p)
260 {
261
262         EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret;
263
264         // check if pointer to instance pointer valid
265         // get free instance and set the globale instance pointer
266         // set also the instance addr to parameterlist
267         EPL_MCO_CHECK_PTR_INSTANCE_PTR();
268         EPL_MCO_GET_FREE_INSTANCE_PTR();
269         EPL_MCO_SET_PTR_INSTANCE_PTR();
270
271         // save init parameters
272         EPL_MEMCPY(&EPL_MCO_GLB_VAR(m_ObdInitParam), pInitParam_p,
273                    sizeof(tEplObdInitParam));
274
275         // clear callback function for command LOAD and STORE
276         EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = NULL;
277
278         // sign instance as used
279         EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed);
280
281         // initialize object dictionary
282         // so all all VarEntries will be initialized to trash object and default values will be set to current data
283         Ret = EplObdAccessOdPart(EPL_MCO_INSTANCE_PTR_
284                                  kEplObdPartAll, kEplObdDirInit);
285
286         return Ret;
287
288 }
289
290 //---------------------------------------------------------------------------
291 //
292 // Function:    EplObdDeleteInstance()
293 //
294 // Description: delete instance
295 //
296 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR
297 //
298 // Return:      tEplKernel
299 //
300 // State:
301 //
302 //---------------------------------------------------------------------------
303 #if (EPL_USE_DELETEINST_FUNC != FALSE)
304 tEplKernel EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR)
305 {
306         // check for all API function if instance is valid
307         EPL_MCO_CHECK_INSTANCE_STATE();
308
309         // sign instance as unused
310         EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused);
311
312         return kEplSuccessful;
313
314 }
315 #endif // (EPL_USE_DELETEINST_FUNC != FALSE)
316
317 //---------------------------------------------------------------------------
318 //
319 // Function:    EplObdWriteEntry()
320 //
321 // Description: Function writes data to an OBD entry. Strings
322 //              are stored with added '\0' character.
323 //
324 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
325 //              uiIndex_p       =   Index of the OD entry
326 //              uiSubIndex_p    =   Subindex of the OD Entry
327 //              pSrcData_p      =   Pointer to the data to write
328 //              Size_p          =   Size of the data in Byte
329 //
330 // Return:      tEplKernel      =   Errorcode
331 //
332 //
333 // State:
334 //
335 //---------------------------------------------------------------------------
336
337 tEplKernel EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
338                             unsigned int uiSubIndex_p,
339                             void *pSrcData_p, tEplObdSize Size_p)
340 {
341
342         tEplKernel Ret;
343         tEplObdEntryPtr pObdEntry;
344         tEplObdSubEntryPtr pSubEntry;
345         tEplObdCbParam CbParam;
346         void *pDstData;
347         tEplObdSize ObdSize;
348
349         Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
350                                   uiIndex_p,
351                                   uiSubIndex_p,
352                                   pSrcData_p,
353                                   &pDstData,
354                                   Size_p,
355                                   &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
356         if (Ret != kEplSuccessful) {
357                 goto Exit;
358         }
359
360         Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
361                                    pObdEntry,
362                                    pSubEntry,
363                                    &CbParam, pSrcData_p, pDstData, ObdSize);
364         if (Ret != kEplSuccessful) {
365                 goto Exit;
366         }
367
368       Exit:
369
370         return Ret;
371
372 }
373
374 //---------------------------------------------------------------------------
375 //
376 // Function:    EplObdReadEntry()
377 //
378 // Description: The function reads an object entry. The application
379 //              can always read the data even if attrib kEplObdAccRead
380 //              is not set. The attrib is only checked up for SDO transfer.
381 //
382 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
383 //              uiIndex_p       = Index oof the OD entry to read
384 //              uiSubIndex_p    = Subindex to read
385 //              pDstData_p      = pointer to the buffer for data
386 //              Offset_p        = offset in data for read access
387 //              pSize_p         = IN: Size of the buffer
388 //                                OUT: number of readed Bytes
389 //
390 // Return:      tEplKernel
391 //
392 // State:
393 //
394 //---------------------------------------------------------------------------
395
396 tEplKernel EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
397                            unsigned int uiSubIndex_p,
398                            void *pDstData_p, tEplObdSize *pSize_p)
399 {
400
401         tEplKernel Ret;
402         tEplObdEntryPtr pObdEntry;
403         tEplObdSubEntryPtr pSubEntry;
404         tEplObdCbParam CbParam;
405         void *pSrcData;
406         tEplObdSize ObdSize;
407
408         // check for all API function if instance is valid
409         EPL_MCO_CHECK_INSTANCE_STATE();
410
411         ASSERT(pDstData_p != NULL);
412         ASSERT(pSize_p != NULL);
413
414         // get address of index and subindex entry
415         Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
416                              uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
417         if (Ret != kEplSuccessful) {
418                 goto Exit;
419         }
420         // get pointer to object data
421         pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
422
423         // check source pointer
424         if (pSrcData == NULL) {
425                 Ret = kEplObdReadViolation;
426                 goto Exit;
427         }
428         //------------------------------------------------------------------------
429         // address of source data to structure of callback parameters
430         // so callback function can change this data before reading
431         CbParam.m_uiIndex = uiIndex_p;
432         CbParam.m_uiSubIndex = uiSubIndex_p;
433         CbParam.m_pArg = pSrcData;
434         CbParam.m_ObdEvent = kEplObdEvPreRead;
435         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
436                                        pObdEntry->m_fpCallback, &CbParam);
437         if (Ret != kEplSuccessful) {
438                 goto Exit;
439         }
440         // get size of data and check if application has reserved enough memory
441         ObdSize = EplObdGetDataSizeIntern(pSubEntry);
442         // check if offset given and calc correct number of bytes to read
443         if (*pSize_p < ObdSize) {
444                 Ret = kEplObdValueLengthError;
445                 goto Exit;
446         }
447         // read value from object
448         EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
449         *pSize_p = ObdSize;
450
451         // write address of destination data to structure of callback parameters
452         // so callback function can change this data after reading
453         CbParam.m_pArg = pDstData_p;
454         CbParam.m_ObdEvent = kEplObdEvPostRead;
455         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
456                                        pObdEntry->m_fpCallback, &CbParam);
457
458       Exit:
459
460         return Ret;
461
462 }
463
464 //---------------------------------------------------------------------------
465 //
466 // Function:    EplObdAccessOdPart()
467 //
468 // Description: restores default values of one part of OD
469 //
470 // Parameters:  ObdPart_p
471 //              Direction_p
472 //
473 // Return:      tEplKernel
474 //
475 // State:
476 //
477 //---------------------------------------------------------------------------
478
479 tEplKernel EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdPart ObdPart_p,
480                               tEplObdDir Direction_p)
481 {
482
483         tEplKernel Ret = kEplSuccessful;
484         BOOL fPartFount;
485         tEplObdEntryPtr pObdEntry;
486
487         // check for all API function if instance is valid
488         EPL_MCO_CHECK_INSTANCE_STATE();
489
490         //  part always has to be unequal to NULL
491         pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pPart);
492         ASSERTMSG(pObdEntry != NULL,
493                   "EplObdAccessOdPart(): no  OD part is defined!\n");
494
495         // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
496         fPartFount = FALSE;
497
498         // access to  part
499         if ((ObdPart_p & kEplObdPartGen) != 0) {
500                 fPartFount = TRUE;
501
502                 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
503                                                kEplObdPartGen, pObdEntry,
504                                                Direction_p);
505                 if (Ret != kEplSuccessful) {
506                         goto Exit;
507                 }
508         }
509         // access to manufacturer part
510         pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pManufacturerPart);
511
512         if (((ObdPart_p & kEplObdPartMan) != 0) && (pObdEntry != NULL)) {
513                 fPartFount = TRUE;
514
515                 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
516                                                kEplObdPartMan, pObdEntry,
517                                                Direction_p);
518                 if (Ret != kEplSuccessful) {
519                         goto Exit;
520                 }
521         }
522         // access to device part
523         pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pDevicePart);
524
525         if (((ObdPart_p & kEplObdPartDev) != 0) && (pObdEntry != NULL)) {
526                 fPartFount = TRUE;
527
528                 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
529                                                kEplObdPartDev, pObdEntry,
530                                                Direction_p);
531                 if (Ret != kEplSuccessful) {
532                         goto Exit;
533                 }
534         }
535 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
536         {
537                 // access to user part
538                 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart);
539
540                 if (((ObdPart_p & kEplObdPartUsr) != 0) && (pObdEntry != NULL)) {
541                         fPartFount = TRUE;
542
543                         Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
544                                                        kEplObdPartUsr,
545                                                        pObdEntry, Direction_p);
546                         if (Ret != kEplSuccessful) {
547                                 goto Exit;
548                         }
549                 }
550         }
551 #endif
552
553         // no access to an OD part was done? illegal OD part was specified!
554         if (fPartFount == FALSE) {
555                 Ret = kEplObdIllegalPart;
556         }
557
558       Exit:
559
560         return Ret;
561
562 }
563
564 //---------------------------------------------------------------------------
565 //
566 // Function:    EplObdDefineVar()
567 //
568 // Description: defines a variable in OD
569 //
570 // Parameters:  pEplVarParam_p
571 //
572 // Return:      tEplKernel
573 //
574 // State:
575 //
576 //---------------------------------------------------------------------------
577
578 tEplKernel EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ tEplVarParam *pVarParam_p)
579 {
580
581         tEplKernel Ret;
582         tEplObdVarEntry *pVarEntry;
583         tEplVarParamValid VarValid;
584         tEplObdSubEntryPtr pSubindexEntry;
585
586         // check for all API function if instance is valid
587         EPL_MCO_CHECK_INSTANCE_STATE();
588
589         ASSERT(pVarParam_p != NULL);    // is not allowed to be NULL
590
591         // get address of subindex entry
592         Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
593                              pVarParam_p->m_uiIndex,
594                              pVarParam_p->m_uiSubindex, NULL, &pSubindexEntry);
595         if (Ret != kEplSuccessful) {
596                 goto Exit;
597         }
598         // get var entry
599         Ret = EplObdGetVarEntry(pSubindexEntry, &pVarEntry);
600         if (Ret != kEplSuccessful) {
601                 goto Exit;
602         }
603
604         VarValid = pVarParam_p->m_ValidFlag;
605
606         // copy only this values, which valid flag is set
607         if ((VarValid & kVarValidSize) != 0) {
608                 if (pSubindexEntry->m_Type != kEplObdTypDomain) {
609                         tEplObdSize DataSize;
610
611                         // check passed size parameter
612                         DataSize = EplObdGetObjectSize(pSubindexEntry);
613                         if (DataSize != pVarParam_p->m_Size) {  // size of variable does not match
614                                 Ret = kEplObdValueLengthError;
615                                 goto Exit;
616                         }
617                 } else {        // size can be set only for objects of type DOMAIN
618                         pVarEntry->m_Size = pVarParam_p->m_Size;
619                 }
620         }
621
622         if ((VarValid & kVarValidData) != 0) {
623                 pVarEntry->m_pData = pVarParam_p->m_pData;
624         }
625 /*
626     #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
627     {
628         if ((VarValid & kVarValidCallback) != 0)
629         {
630            pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
631         }
632
633         if ((VarValid & kVarValidArg) != 0)
634         {
635            pVarEntry->m_pArg = pVarParam_p->m_pArg;
636         }
637     }
638     #endif
639 */
640         // Ret is already set to kEplSuccessful from ObdGetVarIntern()
641
642       Exit:
643
644         return Ret;
645
646 }
647
648 //---------------------------------------------------------------------------
649 //
650 // Function:    EplObdGetObjectDataPtr()
651 //
652 // Description: It returnes the current data pointer. But if object is an
653 //              constant object it returnes the default pointer.
654 //
655 // Parameters:  uiIndex_p    =   Index of the entry
656 //              uiSubindex_p =   Subindex of the entry
657 //
658 // Return:      void *    = pointer to object data
659 //
660 // State:
661 //
662 //---------------------------------------------------------------------------
663
664 void *EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
665                              unsigned int uiSubIndex_p)
666 {
667         tEplKernel Ret;
668         void *pData;
669         tEplObdEntryPtr pObdEntry;
670         tEplObdSubEntryPtr pObdSubEntry;
671
672         // get pointer to index structure
673         Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
674                                    uiIndex_p, &pObdEntry);
675         if (Ret != kEplSuccessful) {
676                 pData = NULL;
677                 goto Exit;
678         }
679         // get pointer to subindex structure
680         Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
681         if (Ret != kEplSuccessful) {
682                 pData = NULL;
683                 goto Exit;
684         }
685         // get Datapointer
686         pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
687
688       Exit:
689         return pData;
690
691 }
692
693 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
694
695 //---------------------------------------------------------------------------
696 //
697 // Function:    EplObdRegisterUserOd()
698 //
699 // Description: function registers the user OD
700 //
701 // Parameters:  pUserOd_p   =pointer to user ODd
702 //
703 // Return:     tEplKernel = errorcode
704 //
705 // State:
706 //
707 //---------------------------------------------------------------------------
708 tEplKernel EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pUserOd_p)
709 {
710
711         EPL_MCO_CHECK_INSTANCE_STATE();
712
713         EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart) = pUserOd_p;
714
715         return kEplSuccessful;
716
717 }
718
719 #endif
720
721 //---------------------------------------------------------------------------
722 //
723 // Function:    EplObdInitVarEntry()
724 //
725 // Description: function to initialize VarEntry dependened on object type
726 //
727 // Parameters:  pVarEntry_p = pointer to var entry structure
728 //              Type_p      = object type
729 //              ObdSize_p   = size of object data
730 //
731 // Returns:     none
732 //
733 // State:
734 //
735 //---------------------------------------------------------------------------
736
737 void EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdVarEntry *pVarEntry_p,
738                         tEplObdType Type_p, tEplObdSize ObdSize_p)
739 {
740 /*
741     #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
742     {
743         // reset pointer to VAR callback and argument
744         pVarEntry_p->m_fpCallback  = NULL;
745         pVarEntry_p->m_pArg = NULL;
746     }
747     #endif
748 */
749
750 // 10-dec-2004 r.d.: this function will not be used for strings
751         if ((Type_p == kEplObdTypDomain))
752 //         (bType_p == kEplObdTypVString) /* ||
753 //         (bType_p == kEplObdTypOString) ||
754 //         (bType_p == kEplObdTypUString)    */ )
755         {
756                 // variables which are defined as DOMAIN or VSTRING should not point to
757                 // trash object, because this trash object contains only 8 bytes. DOMAINS or
758                 // STRINGS can be longer.
759                 pVarEntry_p->m_pData = NULL;
760                 pVarEntry_p->m_Size = 0;
761         } else {
762                 // set address to variable data to trash object
763                 // This prevents an access violation if user forgets to call EplObdDefineVar()
764                 // for this variable but mappes it in a PDO.
765                 pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
766                 pVarEntry_p->m_Size = ObdSize_p;
767         }
768
769 }
770
771 //---------------------------------------------------------------------------
772 //
773 // Function:    EplObdGetDataSize()
774 //
775 // Description: function to initialize VarEntry dependened on object type
776 //
777 //              gets the data size of an object
778 //              for string objects it returnes the string length
779 //
780 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
781 //              uiIndex_p   =   Index
782 //              uiSubIndex_p=   Subindex
783 //
784 // Return:      tEplObdSize
785 //
786 // State:
787 //
788 //---------------------------------------------------------------------------
789 tEplObdSize EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
790                               unsigned int uiSubIndex_p)
791 {
792         tEplKernel Ret;
793         tEplObdSize ObdSize;
794         tEplObdEntryPtr pObdEntry;
795         tEplObdSubEntryPtr pObdSubEntry;
796
797         // get pointer to index structure
798         Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
799                                    uiIndex_p, &pObdEntry);
800         if (Ret != kEplSuccessful) {
801                 ObdSize = 0;
802                 goto Exit;
803         }
804         // get pointer to subindex structure
805         Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
806         if (Ret != kEplSuccessful) {
807                 ObdSize = 0;
808                 goto Exit;
809         }
810         // get size
811         ObdSize = EplObdGetDataSizeIntern(pObdSubEntry);
812       Exit:
813         return ObdSize;
814 }
815
816 //---------------------------------------------------------------------------
817 //
818 // Function:    EplObdGetNodeId()
819 //
820 // Description: function returns nodeid from entry 0x1F93
821 //
822 //
823 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
824 //
825 // Return:      unsigned int = Node Id
826 //
827 // State:
828 //
829 //---------------------------------------------------------------------------
830 unsigned int EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
831 {
832         tEplKernel Ret;
833         tEplObdSize ObdSize;
834         u8 bNodeId;
835
836         bNodeId = 0;
837         ObdSize = sizeof(bNodeId);
838         Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
839                               EPL_OBD_NODE_ID_INDEX,
840                               EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, &ObdSize);
841         if (Ret != kEplSuccessful) {
842                 bNodeId = EPL_C_ADR_INVALID;
843                 goto Exit;
844         }
845
846       Exit:
847         return (unsigned int)bNodeId;
848
849 }
850
851 //---------------------------------------------------------------------------
852 //
853 // Function:    EplObdSetNodeId()
854 //
855 // Description: function sets nodeid in entry 0x1F93
856 //
857 //
858 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
859 //              uiNodeId_p  =   Node Id to set
860 //              NodeIdType_p=   Type on which way the Node Id was set
861 //
862 // Return:      tEplKernel = Errorcode
863 //
864 // State:
865 //
866 //---------------------------------------------------------------------------
867 tEplKernel EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ unsigned int uiNodeId_p,
868                            tEplObdNodeIdType NodeIdType_p)
869 {
870         tEplKernel Ret;
871         tEplObdSize ObdSize;
872         u8 fHwBool;
873         u8 bNodeId;
874
875         // check Node Id
876         if (uiNodeId_p == EPL_C_ADR_INVALID) {
877                 Ret = kEplInvalidNodeId;
878                 goto Exit;
879         }
880         bNodeId = (u8) uiNodeId_p;
881         ObdSize = sizeof(u8);
882         // write NodeId to OD entry
883         Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
884                                EPL_OBD_NODE_ID_INDEX,
885                                EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, ObdSize);
886         if (Ret != kEplSuccessful) {
887                 goto Exit;
888         }
889         // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
890         switch (NodeIdType_p) {
891                 // type unknown
892         case kEplObdNodeIdUnknown:
893                 {
894                         fHwBool = OBD_FALSE;
895                         break;
896                 }
897
898         case kEplObdNodeIdSoftware:
899                 {
900                         fHwBool = OBD_FALSE;
901                         break;
902                 }
903
904         case kEplObdNodeIdHardware:
905                 {
906                         fHwBool = OBD_TRUE;
907                         break;
908                 }
909
910         default:
911                 {
912                         fHwBool = OBD_FALSE;
913                 }
914
915         }                       // end of switch (NodeIdType_p)
916
917         // write flag
918         ObdSize = sizeof(fHwBool);
919         Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
920                                EPL_OBD_NODE_ID_INDEX,
921                                EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
922                                &fHwBool, ObdSize);
923         if (Ret != kEplSuccessful) {
924                 goto Exit;
925         }
926
927       Exit:
928         return Ret;
929 }
930
931 //---------------------------------------------------------------------------
932 //
933 // Function:    EplObdIsNumerical()
934 //
935 // Description: function checks if a entry is numerical or not
936 //
937 //
938 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
939 //              uiIndex_p           = Index
940 //              uiSubIndex_p        = Subindex
941 //              pfEntryNumerical_p  = pointer to BOOL for returnvalue
942 //                                  -> TRUE if entry a numerical value
943 //                                  -> FALSE if entry not a numerical value
944 //
945 // Return:      tEplKernel = Errorcode
946 //
947 // State:
948 //
949 //---------------------------------------------------------------------------
950 tEplKernel EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
951                              unsigned int uiSubIndex_p,
952                              BOOL *pfEntryNumerical_p)
953 {
954         tEplKernel Ret;
955         tEplObdEntryPtr pObdEntry;
956         tEplObdSubEntryPtr pObdSubEntry;
957
958         // get pointer to index structure
959         Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
960                                    uiIndex_p, &pObdEntry);
961         if (Ret != kEplSuccessful) {
962                 goto Exit;
963         }
964         // get pointer to subindex structure
965         Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
966         if (Ret != kEplSuccessful) {
967                 goto Exit;
968         }
969
970         Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
971
972       Exit:
973         return Ret;
974
975 }
976
977 //---------------------------------------------------------------------------
978 //
979 // Function:    EplObdReadEntryToLe()
980 //
981 // Description: The function reads an object entry from the byteoder
982 //              of the system to the little endian byteorder for numerical values.
983 //              For other types a normal read will be processed. This is usefull for
984 //              the PDO and SDO module. The application
985 //              can always read the data even if attrib kEplObdAccRead
986 //              is not set. The attrib is only checked up for SDO transfer.
987 //
988 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
989 //              uiIndex_p       = Index of the OD entry to read
990 //              uiSubIndex_p    = Subindex to read
991 //              pDstData_p      = pointer to the buffer for data
992 //              Offset_p        = offset in data for read access
993 //              pSize_p         = IN: Size of the buffer
994 //                                OUT: number of readed Bytes
995 //
996 // Return:      tEplKernel
997 //
998 // State:
999 //
1000 //---------------------------------------------------------------------------
1001 tEplKernel EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1002                                unsigned int uiSubIndex_p,
1003                                void *pDstData_p, tEplObdSize *pSize_p)
1004 {
1005         tEplKernel Ret;
1006         tEplObdEntryPtr pObdEntry;
1007         tEplObdSubEntryPtr pSubEntry;
1008         tEplObdCbParam CbParam;
1009         void *pSrcData;
1010         tEplObdSize ObdSize;
1011
1012         // check for all API function if instance is valid
1013         EPL_MCO_CHECK_INSTANCE_STATE();
1014
1015         ASSERT(pDstData_p != NULL);
1016         ASSERT(pSize_p != NULL);
1017
1018         // get address of index and subindex entry
1019         Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1020                              uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1021         if (Ret != kEplSuccessful) {
1022                 goto Exit;
1023         }
1024         // get pointer to object data
1025         pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
1026
1027         // check source pointer
1028         if (pSrcData == NULL) {
1029                 Ret = kEplObdReadViolation;
1030                 goto Exit;
1031         }
1032         //------------------------------------------------------------------------
1033         // address of source data to structure of callback parameters
1034         // so callback function can change this data before reading
1035         CbParam.m_uiIndex = uiIndex_p;
1036         CbParam.m_uiSubIndex = uiSubIndex_p;
1037         CbParam.m_pArg = pSrcData;
1038         CbParam.m_ObdEvent = kEplObdEvPreRead;
1039         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1040                                        pObdEntry->m_fpCallback, &CbParam);
1041         if (Ret != kEplSuccessful) {
1042                 goto Exit;
1043         }
1044         // get size of data and check if application has reserved enough memory
1045         ObdSize = EplObdGetDataSizeIntern(pSubEntry);
1046         // check if offset given and calc correct number of bytes to read
1047         if (*pSize_p < ObdSize) {
1048                 Ret = kEplObdValueLengthError;
1049                 goto Exit;
1050         }
1051         // check if numerical type
1052         switch (pSubEntry->m_Type) {
1053                 //-----------------------------------------------
1054                 // types without ami
1055         case kEplObdTypVString:
1056         case kEplObdTypOString:
1057         case kEplObdTypDomain:
1058         default:
1059                 {
1060                         // read value from object
1061                         EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
1062                         break;
1063                 }
1064
1065                 //-----------------------------------------------
1066                 // numerical type which needs ami-write
1067                 // 8 bit or smaller values
1068         case kEplObdTypBool:
1069         case kEplObdTypInt8:
1070         case kEplObdTypUInt8:
1071                 {
1072                         AmiSetByteToLe(pDstData_p, *((u8 *) pSrcData));
1073                         break;
1074                 }
1075
1076                 // 16 bit values
1077         case kEplObdTypInt16:
1078         case kEplObdTypUInt16:
1079                 {
1080                         AmiSetWordToLe(pDstData_p, *((u16 *) pSrcData));
1081                         break;
1082                 }
1083
1084                 // 24 bit values
1085         case kEplObdTypInt24:
1086         case kEplObdTypUInt24:
1087                 {
1088                         AmiSetDword24ToLe(pDstData_p, *((u32 *) pSrcData));
1089                         break;
1090                 }
1091
1092                 // 32 bit values
1093         case kEplObdTypInt32:
1094         case kEplObdTypUInt32:
1095         case kEplObdTypReal32:
1096                 {
1097                         AmiSetDwordToLe(pDstData_p, *((u32 *) pSrcData));
1098                         break;
1099                 }
1100
1101                 // 40 bit values
1102         case kEplObdTypInt40:
1103         case kEplObdTypUInt40:
1104                 {
1105                         AmiSetQword40ToLe(pDstData_p, *((u64 *) pSrcData));
1106                         break;
1107                 }
1108
1109                 // 48 bit values
1110         case kEplObdTypInt48:
1111         case kEplObdTypUInt48:
1112                 {
1113                         AmiSetQword48ToLe(pDstData_p, *((u64 *) pSrcData));
1114                         break;
1115                 }
1116
1117                 // 56 bit values
1118         case kEplObdTypInt56:
1119         case kEplObdTypUInt56:
1120                 {
1121                         AmiSetQword56ToLe(pDstData_p, *((u64 *) pSrcData));
1122                         break;
1123                 }
1124
1125                 // 64 bit values
1126         case kEplObdTypInt64:
1127         case kEplObdTypUInt64:
1128         case kEplObdTypReal64:
1129                 {
1130                         AmiSetQword64ToLe(pDstData_p, *((u64 *) pSrcData));
1131                         break;
1132                 }
1133
1134                 // time of day
1135         case kEplObdTypTimeOfDay:
1136         case kEplObdTypTimeDiff:
1137                 {
1138                         AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay *) pSrcData));
1139                         break;
1140                 }
1141
1142         }                       // end of switch(pSubEntry->m_Type)
1143
1144         *pSize_p = ObdSize;
1145
1146         // write address of destination data to structure of callback parameters
1147         // so callback function can change this data after reading
1148         CbParam.m_pArg = pDstData_p;
1149         CbParam.m_ObdEvent = kEplObdEvPostRead;
1150         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1151                                        pObdEntry->m_fpCallback, &CbParam);
1152
1153       Exit:
1154
1155         return Ret;
1156
1157 }
1158
1159 //---------------------------------------------------------------------------
1160 //
1161 // Function:    EplObdWriteEntryFromLe()
1162 //
1163 // Description: Function writes data to an OBD entry from a source with
1164 //              little endian byteorder to the od with system specuific
1165 //              byteorder. Not numerical values will only by copied. Strings
1166 //              are stored with added '\0' character.
1167 //
1168 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
1169 //              uiIndex_p       =   Index of the OD entry
1170 //              uiSubIndex_p    =   Subindex of the OD Entry
1171 //              pSrcData_p      =   Pointer to the data to write
1172 //              Size_p          =   Size of the data in Byte
1173 //
1174 // Return:      tEplKernel      =   Errorcode
1175 //
1176 //
1177 // State:
1178 //
1179 //---------------------------------------------------------------------------
1180 tEplKernel EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1181                                   unsigned int uiSubIndex_p,
1182                                   void *pSrcData_p, tEplObdSize Size_p)
1183 {
1184         tEplKernel Ret;
1185         tEplObdEntryPtr pObdEntry;
1186         tEplObdSubEntryPtr pSubEntry;
1187         tEplObdCbParam CbParam;
1188         void *pDstData;
1189         tEplObdSize ObdSize;
1190         u64 qwBuffer;
1191         void *pBuffer = &qwBuffer;
1192
1193         Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
1194                                   uiIndex_p,
1195                                   uiSubIndex_p,
1196                                   pSrcData_p,
1197                                   &pDstData,
1198                                   Size_p,
1199                                   &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
1200         if (Ret != kEplSuccessful) {
1201                 goto Exit;
1202         }
1203
1204         // check if numerical type
1205         switch (pSubEntry->m_Type) {
1206                 //-----------------------------------------------
1207                 // types without ami
1208         default:
1209                 {               // do nothing, i.e. use the given source pointer
1210                         pBuffer = pSrcData_p;
1211                         break;
1212                 }
1213
1214                 //-----------------------------------------------
1215                 // numerical type which needs ami-write
1216                 // 8 bit or smaller values
1217         case kEplObdTypBool:
1218         case kEplObdTypInt8:
1219         case kEplObdTypUInt8:
1220                 {
1221                         *((u8 *) pBuffer) = AmiGetByteFromLe(pSrcData_p);
1222                         break;
1223                 }
1224
1225                 // 16 bit values
1226         case kEplObdTypInt16:
1227         case kEplObdTypUInt16:
1228                 {
1229                         *((u16 *) pBuffer) = AmiGetWordFromLe(pSrcData_p);
1230                         break;
1231                 }
1232
1233                 // 24 bit values
1234         case kEplObdTypInt24:
1235         case kEplObdTypUInt24:
1236                 {
1237                         *((u32 *) pBuffer) = AmiGetDword24FromLe(pSrcData_p);
1238                         break;
1239                 }
1240
1241                 // 32 bit values
1242         case kEplObdTypInt32:
1243         case kEplObdTypUInt32:
1244         case kEplObdTypReal32:
1245                 {
1246                         *((u32 *) pBuffer) = AmiGetDwordFromLe(pSrcData_p);
1247                         break;
1248                 }
1249
1250                 // 40 bit values
1251         case kEplObdTypInt40:
1252         case kEplObdTypUInt40:
1253                 {
1254                         *((u64 *) pBuffer) = AmiGetQword40FromLe(pSrcData_p);
1255                         break;
1256                 }
1257
1258                 // 48 bit values
1259         case kEplObdTypInt48:
1260         case kEplObdTypUInt48:
1261                 {
1262                         *((u64 *) pBuffer) = AmiGetQword48FromLe(pSrcData_p);
1263                         break;
1264                 }
1265
1266                 // 56 bit values
1267         case kEplObdTypInt56:
1268         case kEplObdTypUInt56:
1269                 {
1270                         *((u64 *) pBuffer) = AmiGetQword56FromLe(pSrcData_p);
1271                         break;
1272                 }
1273
1274                 // 64 bit values
1275         case kEplObdTypInt64:
1276         case kEplObdTypUInt64:
1277         case kEplObdTypReal64:
1278                 {
1279                         *((u64 *) pBuffer) = AmiGetQword64FromLe(pSrcData_p);
1280                         break;
1281                 }
1282
1283                 // time of day
1284         case kEplObdTypTimeOfDay:
1285         case kEplObdTypTimeDiff:
1286                 {
1287                         AmiGetTimeOfDay(pBuffer, ((tTimeOfDay *) pSrcData_p));
1288                         break;
1289                 }
1290
1291         }                       // end of switch(pSubEntry->m_Type)
1292
1293         Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
1294                                    pObdEntry,
1295                                    pSubEntry,
1296                                    &CbParam, pBuffer, pDstData, ObdSize);
1297         if (Ret != kEplSuccessful) {
1298                 goto Exit;
1299         }
1300
1301       Exit:
1302
1303         return Ret;
1304
1305 }
1306
1307 //---------------------------------------------------------------------------
1308 //
1309 // Function:    EplObdGetAccessType()
1310 //
1311 // Description: Function returns accesstype of the entry
1312 //
1313 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
1314 //              uiIndex_p       =   Index of the OD entry
1315 //              uiSubIndex_p    =   Subindex of the OD Entry
1316 //              pAccessTyp_p    =   pointer to buffer to store accesstype
1317 //
1318 // Return:      tEplKernel     =   errorcode
1319 //
1320 //
1321 // State:
1322 //
1323 //---------------------------------------------------------------------------
1324 tEplKernel EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1325                                unsigned int uiSubIndex_p,
1326                                tEplObdAccess *pAccessTyp_p)
1327 {
1328         tEplKernel Ret;
1329         tEplObdEntryPtr pObdEntry;
1330         tEplObdSubEntryPtr pObdSubEntry;
1331
1332         // get pointer to index structure
1333         Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
1334                                    uiIndex_p, &pObdEntry);
1335         if (Ret != kEplSuccessful) {
1336                 goto Exit;
1337         }
1338         // get pointer to subindex structure
1339         Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
1340         if (Ret != kEplSuccessful) {
1341                 goto Exit;
1342         }
1343         // get accessType
1344         *pAccessTyp_p = pObdSubEntry->m_Access;
1345
1346       Exit:
1347         return Ret;
1348 }
1349
1350 //---------------------------------------------------------------------------
1351 //
1352 // Function:    EplObdSearchVarEntry()
1353 //
1354 // Description: gets variable from OD
1355 //
1356 // Parameters:  uiIndex_p       =   index of the var entry to search
1357 //              uiSubindex_p    =   subindex of var entry to search
1358 //              ppVarEntry_p    =   pointer to the pointer to the varentry
1359 //
1360 // Return:      tEplKernel
1361 //
1362 // State:
1363 //
1364 //---------------------------------------------------------------------------
1365
1366 tEplKernel EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1367                                 unsigned int uiSubindex_p,
1368                                 tEplObdVarEntry **ppVarEntry_p)
1369 {
1370
1371         tEplKernel Ret;
1372         tEplObdSubEntryPtr pSubindexEntry;
1373
1374         // check for all API function if instance is valid
1375         EPL_MCO_CHECK_INSTANCE_STATE();
1376
1377         // get address of subindex entry
1378         Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1379                              uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
1380         if (Ret == kEplSuccessful) {
1381                 // get var entry
1382                 Ret = EplObdGetVarEntry(pSubindexEntry, ppVarEntry_p);
1383         }
1384
1385         return Ret;
1386
1387 }
1388
1389 //=========================================================================//
1390 //                                                                         //
1391 //          P R I V A T E   D E F I N I T I O N S                          //
1392 //                                                                         //
1393 //=========================================================================//
1394
1395 EPL_MCO_DECL_INSTANCE_FCT()
1396 //---------------------------------------------------------------------------
1397 //
1398 // Function:    EplObdCallObjectCallback()
1399 //
1400 // Description: calls callback function of an object or of a variable
1401 //
1402 // Parameters:  fpCallback_p
1403 //              pCbParam_p
1404 //
1405 // Return:      tEplKernel
1406 //
1407 // State:
1408 //
1409 //---------------------------------------------------------------------------
1410 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
1411                                            tEplObdCallback fpCallback_p,
1412                                            tEplObdCbParam *pCbParam_p)
1413 {
1414
1415         tEplKernel Ret;
1416         tEplObdCallback fpCallback;
1417
1418         // check for all API function if instance is valid
1419         EPL_MCO_CHECK_INSTANCE_STATE();
1420
1421         ASSERT(pCbParam_p != NULL);
1422
1423         Ret = kEplSuccessful;
1424
1425         // check address of callback function before calling it
1426         if (fpCallback_p != NULL) {
1427                 // KEIL C51 V6.01 has a bug.
1428                 // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
1429                 fpCallback = fpCallback_p;
1430
1431                 // call callback function for this object
1432                 Ret = fpCallback(EPL_MCO_INSTANCE_PARAM_IDX_()
1433                                  pCbParam_p);
1434         }
1435
1436         return Ret;
1437 }
1438
1439 //---------------------------------------------------------------------------
1440 //
1441 // Function:    EplObdGetDataSizeIntern()
1442 //
1443 // Description: gets the data size of an object
1444 //              for string objects it returnes the string length
1445 //
1446 // Parameters:  pSubIndexEntry_p
1447 //
1448 // Return:      tEplObdSize
1449 //
1450 // State:
1451 //
1452 //---------------------------------------------------------------------------
1453
1454 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p)
1455 {
1456
1457         tEplObdSize DataSize;
1458         void *pData;
1459
1460         // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
1461         // then the current pointer is always NULL. The function
1462         // returns the length of default string.
1463         DataSize = EplObdGetObjectSize(pSubIndexEntry_p);
1464
1465         if (pSubIndexEntry_p->m_Type == kEplObdTypVString) {
1466                 // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
1467                 pData = ((void *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p));
1468                 if (pData != NULL) {
1469                         DataSize =
1470                             EplObdGetStrLen((void *)pData, DataSize,
1471                                             pSubIndexEntry_p->m_Type);
1472                 }
1473
1474         }
1475
1476         return DataSize;
1477
1478 }
1479
1480 //---------------------------------------------------------------------------
1481 //
1482 // Function:    EplObdGetStrLen()
1483 //
1484 // Description: The function calculates the length of string. The '\0'
1485 //              character is included!!
1486 //
1487 // Parameters:  pObjData_p          = pointer to string
1488 //              ObjLen_p            = max. length of objectr entry
1489 //              bObjType_p          = object type (VSTRING, ...)
1490 //
1491 // Returns:     string length + 1
1492 //
1493 // State:
1494 //
1495 //---------------------------------------------------------------------------
1496
1497 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
1498                                    tEplObdSize ObjLen_p, tEplObdType ObjType_p)
1499 {
1500
1501         tEplObdSize StrLen = 0;
1502         u8 *pbString;
1503
1504         if (pObjData_p == NULL) {
1505                 goto Exit;
1506         }
1507         //----------------------------------------
1508         // Visible String: data format byte
1509         if (ObjType_p == kEplObdTypVString) {
1510                 pbString = pObjData_p;
1511
1512                 for (StrLen = 0; StrLen < ObjLen_p; StrLen++) {
1513                         if (*pbString == '\0') {
1514                                 StrLen++;
1515                                 break;
1516                         }
1517
1518                         pbString++;
1519                 }
1520         }
1521         //----------------------------------------
1522         // other string types ...
1523
1524       Exit:
1525         return (StrLen);
1526
1527 }
1528
1529 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1530
1531 //---------------------------------------------------------------------------
1532 //
1533 // Function:    EplObdCheckObjectRange()
1534 //
1535 // Description: function to check value range of object data
1536 //
1537 // NOTICE: The pointer of data (pData_p) must point out to an even address,
1538 //         if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
1539 //         always realiced because pointer m_pDefault points always to an
1540 //         array of the SPECIFIED type.
1541 //
1542 // Parameters:  pSubindexEntry_p
1543 //              pData_p
1544 //
1545 // Return:      tEplKernel
1546 //
1547 // State:
1548 //
1549 //---------------------------------------------------------------------------
1550
1551 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
1552                                          void *pData_p)
1553 {
1554
1555         tEplKernel Ret;
1556         void *pRangeData;
1557
1558         ASSERTMSG(pSubindexEntry_p != NULL,
1559                   "EplObdCheckObjectRange(): no address to subindex struct!\n");
1560
1561         Ret = kEplSuccessful;
1562
1563         // check if data range has to be checked
1564         if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) {
1565                 goto Exit;
1566         }
1567         // get address of default data
1568         pRangeData = pSubindexEntry_p->m_pDefault;
1569
1570         // jump to called object type
1571         switch ((tEplObdType) pSubindexEntry_p->m_Type) {
1572                 // -----------------------------------------------------------------
1573                 // ObdType kEplObdTypBool will not be checked because there are only
1574                 // two possible values 0 or 1.
1575
1576                 // -----------------------------------------------------------------
1577                 // ObdTypes which has to be check up because numerical values
1578         case kEplObdTypInt8:
1579
1580                 // switch to lower limit
1581                 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1582
1583                 // check if value is to low
1584                 if (*((tEplObdInteger8 *) pData_p) <
1585                     *((tEplObdInteger8 *) pRangeData)) {
1586                         Ret = kEplObdValueTooLow;
1587                         break;
1588                 }
1589                 // switch to higher limit
1590                 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1591
1592                 // check if value is to high
1593                 if (*((tEplObdInteger8 *) pData_p) >
1594                     *((tEplObdInteger8 *) pRangeData)) {
1595                         Ret = kEplObdValueTooHigh;
1596                 }
1597
1598                 break;
1599
1600         case kEplObdTypUInt8:
1601
1602                 // switch to lower limit
1603                 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1604
1605                 // check if value is to low
1606                 if (*((tEplObdUnsigned8 *) pData_p) <
1607                     *((tEplObdUnsigned8 *) pRangeData)) {
1608                         Ret = kEplObdValueTooLow;
1609                         break;
1610                 }
1611                 // switch to higher limit
1612                 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1613
1614                 // check if value is to high
1615                 if (*((tEplObdUnsigned8 *) pData_p) >
1616                     *((tEplObdUnsigned8 *) pRangeData)) {
1617                         Ret = kEplObdValueTooHigh;
1618                 }
1619
1620                 break;
1621
1622         case kEplObdTypInt16:
1623
1624                 // switch to lower limit
1625                 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1626
1627                 // check if value is to low
1628                 if (*((tEplObdInteger16 *) pData_p) <
1629                     *((tEplObdInteger16 *) pRangeData)) {
1630                         Ret = kEplObdValueTooLow;
1631                         break;
1632                 }
1633                 // switch to higher limit
1634                 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1635
1636                 // check if value is to high
1637                 if (*((tEplObdInteger16 *) pData_p) >
1638                     *((tEplObdInteger16 *) pRangeData)) {
1639                         Ret = kEplObdValueTooHigh;
1640                 }
1641
1642                 break;
1643
1644         case kEplObdTypUInt16:
1645
1646                 // switch to lower limit
1647                 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1648
1649                 // check if value is to low
1650                 if (*((tEplObdUnsigned16 *) pData_p) <
1651                     *((tEplObdUnsigned16 *) pRangeData)) {
1652                         Ret = kEplObdValueTooLow;
1653                         break;
1654                 }
1655                 // switch to higher limit
1656                 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1657
1658                 // check if value is to high
1659                 if (*((tEplObdUnsigned16 *) pData_p) >
1660                     *((tEplObdUnsigned16 *) pRangeData)) {
1661                         Ret = kEplObdValueTooHigh;
1662                 }
1663
1664                 break;
1665
1666         case kEplObdTypInt32:
1667
1668                 // switch to lower limit
1669                 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1670
1671                 // check if value is to low
1672                 if (*((tEplObdInteger32 *) pData_p) <
1673                     *((tEplObdInteger32 *) pRangeData)) {
1674                         Ret = kEplObdValueTooLow;
1675                         break;
1676                 }
1677                 // switch to higher limit
1678                 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1679
1680                 // check if value is to high
1681                 if (*((tEplObdInteger32 *) pData_p) >
1682                     *((tEplObdInteger32 *) pRangeData)) {
1683                         Ret = kEplObdValueTooHigh;
1684                 }
1685
1686                 break;
1687
1688         case kEplObdTypUInt32:
1689
1690                 // switch to lower limit
1691                 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1692
1693                 // check if value is to low
1694                 if (*((tEplObdUnsigned32 *) pData_p) <
1695                     *((tEplObdUnsigned32 *) pRangeData)) {
1696                         Ret = kEplObdValueTooLow;
1697                         break;
1698                 }
1699                 // switch to higher limit
1700                 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1701
1702                 // check if value is to high
1703                 if (*((tEplObdUnsigned32 *) pData_p) >
1704                     *((tEplObdUnsigned32 *) pRangeData)) {
1705                         Ret = kEplObdValueTooHigh;
1706                 }
1707
1708                 break;
1709
1710         case kEplObdTypReal32:
1711
1712                 // switch to lower limit
1713                 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1714
1715                 // check if value is to low
1716                 if (*((tEplObdReal32 *) pData_p) <
1717                     *((tEplObdReal32 *) pRangeData)) {
1718                         Ret = kEplObdValueTooLow;
1719                         break;
1720                 }
1721                 // switch to higher limit
1722                 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1723
1724                 // check if value is to high
1725                 if (*((tEplObdReal32 *) pData_p) >
1726                     *((tEplObdReal32 *) pRangeData)) {
1727                         Ret = kEplObdValueTooHigh;
1728                 }
1729
1730                 break;
1731
1732                 // -----------------------------------------------------------------
1733         case kEplObdTypInt40:
1734         case kEplObdTypInt48:
1735         case kEplObdTypInt56:
1736         case kEplObdTypInt64:
1737
1738                 // switch to lower limit
1739                 pRangeData = ((signed u64 *)pRangeData) + 1;
1740
1741                 // check if value is to low
1742                 if (*((signed u64 *)pData_p) < *((signed u64 *)pRangeData)) {
1743                         Ret = kEplObdValueTooLow;
1744                         break;
1745                 }
1746                 // switch to higher limit
1747                 pRangeData = ((signed u64 *)pRangeData) + 1;
1748
1749                 // check if value is to high
1750                 if (*((signed u64 *)pData_p) > *((signed u64 *)pRangeData)) {
1751                         Ret = kEplObdValueTooHigh;
1752                 }
1753
1754                 break;
1755
1756                 // -----------------------------------------------------------------
1757         case kEplObdTypUInt40:
1758         case kEplObdTypUInt48:
1759         case kEplObdTypUInt56:
1760         case kEplObdTypUInt64:
1761
1762                 // switch to lower limit
1763                 pRangeData = ((unsigned u64 *)pRangeData) + 1;
1764
1765                 // check if value is to low
1766                 if (*((unsigned u64 *)pData_p) <
1767                     *((unsigned u64 *)pRangeData)) {
1768                         Ret = kEplObdValueTooLow;
1769                         break;
1770                 }
1771                 // switch to higher limit
1772                 pRangeData = ((unsigned u64 *)pRangeData) + 1;
1773
1774                 // check if value is to high
1775                 if (*((unsigned u64 *)pData_p) >
1776                     *((unsigned u64 *)pRangeData)) {
1777                         Ret = kEplObdValueTooHigh;
1778                 }
1779
1780                 break;
1781
1782                 // -----------------------------------------------------------------
1783         case kEplObdTypReal64:
1784
1785                 // switch to lower limit
1786                 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1787
1788                 // check if value is to low
1789                 if (*((tEplObdReal64 *) pData_p) <
1790                     *((tEplObdReal64 *) pRangeData)) {
1791                         Ret = kEplObdValueTooLow;
1792                         break;
1793                 }
1794                 // switch to higher limit
1795                 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1796
1797                 // check if value is to high
1798                 if (*((tEplObdReal64 *) pData_p) >
1799                     *((tEplObdReal64 *) pRangeData)) {
1800                         Ret = kEplObdValueTooHigh;
1801                 }
1802
1803                 break;
1804
1805                 // -----------------------------------------------------------------
1806         case kEplObdTypTimeOfDay:
1807         case kEplObdTypTimeDiff:
1808                 break;
1809
1810                 // -----------------------------------------------------------------
1811                 // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
1812                 // they have no numerical value.
1813         default:
1814
1815                 Ret = kEplObdUnknownObjectType;
1816                 break;
1817         }
1818
1819       Exit:
1820
1821         return Ret;
1822
1823 }
1824 #endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1825
1826 //---------------------------------------------------------------------------
1827 //
1828 // Function:    EplObdWriteEntryPre()
1829 //
1830 // Description: Function prepares write of data to an OBD entry. Strings
1831 //              are stored with added '\0' character.
1832 //
1833 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
1834 //              uiIndex_p       =   Index of the OD entry
1835 //              uiSubIndex_p    =   Subindex of the OD Entry
1836 //              pSrcData_p      =   Pointer to the data to write
1837 //              Size_p          =   Size of the data in Byte
1838 //
1839 // Return:      tEplKernel      =   Errorcode
1840 //
1841 //
1842 // State:
1843 //
1844 //---------------------------------------------------------------------------
1845
1846 static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1847                                       unsigned int uiSubIndex_p,
1848                                       void *pSrcData_p,
1849                                       void **ppDstData_p,
1850                                       tEplObdSize Size_p,
1851                                       tEplObdEntryPtr *ppObdEntry_p,
1852                                       tEplObdSubEntryPtr *ppSubEntry_p,
1853                                       tEplObdCbParam *pCbParam_p,
1854                                       tEplObdSize *pObdSize_p)
1855 {
1856
1857         tEplKernel Ret;
1858         tEplObdEntryPtr pObdEntry;
1859         tEplObdSubEntryPtr pSubEntry;
1860         tEplObdAccess Access;
1861         void *pDstData;
1862         tEplObdSize ObdSize;
1863         BOOL fEntryNumerical;
1864
1865 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1866         tEplObdVStringDomain MemVStringDomain;
1867         void *pCurrData;
1868 #endif
1869
1870         // check for all API function if instance is valid
1871         EPL_MCO_CHECK_INSTANCE_STATE();
1872
1873         ASSERT(pSrcData_p != NULL);     // should never be NULL
1874
1875         //------------------------------------------------------------------------
1876         // get address of index and subindex entry
1877         Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1878                              uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1879         if (Ret != kEplSuccessful) {
1880                 goto Exit;
1881         }
1882         // get pointer to object data
1883         pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1884
1885         Access = (tEplObdAccess) pSubEntry->m_Access;
1886
1887         // check access for write
1888         // access violation if adress to current value is NULL
1889         if (((Access & kEplObdAccConst) != 0) || (pDstData == NULL)) {
1890                 Ret = kEplObdAccessViolation;
1891                 goto Exit;
1892         }
1893         //------------------------------------------------------------------------
1894         // get size of object
1895         // -as ObdSize = ObdGetObjectSize (pSubEntry);
1896
1897         //------------------------------------------------------------------------
1898         // To use the same callback function for ObdWriteEntry as well as for
1899         // an SDO download call at first (kEplObdEvPre...) the callback function
1900         // with the argument pointer to object size.
1901         pCbParam_p->m_uiIndex = uiIndex_p;
1902         pCbParam_p->m_uiSubIndex = uiSubIndex_p;
1903
1904         // Because object size and object pointer are
1905         // adapted by user callback function, re-read
1906         // this values.
1907         ObdSize = EplObdGetObjectSize(pSubEntry);
1908         pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1909
1910         // 09-dec-2004 r.d.:
1911         //      Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
1912         //      for String or Domain which lets called module directly change
1913         //      the data pointer or size. This prevents a recursive call to
1914         //      the callback function if it calls EplObdGetEntry().
1915 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1916         if ((pSubEntry->m_Type == kEplObdTypVString) ||
1917             (pSubEntry->m_Type == kEplObdTypDomain) ||
1918             (pSubEntry->m_Type == kEplObdTypOString)) {
1919                 if (pSubEntry->m_Type == kEplObdTypVString) {
1920                         // reserve one byte for 0-termination
1921                         // -as ObdSize -= 1;
1922                         Size_p += 1;
1923                 }
1924                 // fill out new arg-struct
1925                 MemVStringDomain.m_DownloadSize = Size_p;
1926                 MemVStringDomain.m_ObjSize = ObdSize;
1927                 MemVStringDomain.m_pData = pDstData;
1928
1929                 pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
1930                 pCbParam_p->m_pArg = &MemVStringDomain;
1931                 //  call user callback
1932                 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1933                                                pObdEntry->m_fpCallback,
1934                                                pCbParam_p);
1935                 if (Ret != kEplSuccessful) {
1936                         goto Exit;
1937                 }
1938                 // write back new settings
1939                 pCurrData = pSubEntry->m_pCurrent;
1940                 if ((pSubEntry->m_Type == kEplObdTypVString)
1941                     || (pSubEntry->m_Type == kEplObdTypOString)) {
1942                         ((tEplObdVString *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1943                         ((tEplObdVString *)pCurrData)->m_pString = MemVStringDomain.m_pData;
1944                 } else          // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
1945                 {
1946                         ((tEplObdVarEntry *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1947                         ((tEplObdVarEntry *)pCurrData)->m_pData = (void *)MemVStringDomain.m_pData;
1948                 }
1949
1950                 // Because object size and object pointer are
1951                 // adapted by user callback function, re-read
1952                 // this values.
1953                 ObdSize = MemVStringDomain.m_ObjSize;
1954                 pDstData = (void *)MemVStringDomain.m_pData;
1955         }
1956 #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1957
1958         // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
1959         // -as 16.11.04 CbParam.m_pArg     = &ObdSize;
1960         // 09-dec-2004 r.d.: CbParam.m_pArg     = &Size_p;
1961         pCbParam_p->m_pArg = &ObdSize;
1962         pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
1963         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1964                                        pObdEntry->m_fpCallback, pCbParam_p);
1965         if (Ret != kEplSuccessful) {
1966                 goto Exit;
1967         }
1968
1969         if (Size_p > ObdSize) {
1970                 Ret = kEplObdValueLengthError;
1971                 goto Exit;
1972         }
1973
1974         if (pSubEntry->m_Type == kEplObdTypVString) {
1975                 if (((char *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character
1976
1977                         // reserve one byte in destination for 0-termination
1978                         Size_p -= 1;
1979                 } else if (Size_p >= ObdSize) { // source string is not 0-terminated
1980                         // and destination buffer is too short
1981                         Ret = kEplObdValueLengthError;
1982                         goto Exit;
1983                 }
1984         }
1985
1986         Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
1987         if (Ret != kEplSuccessful) {
1988                 goto Exit;
1989         }
1990
1991         if ((fEntryNumerical != FALSE)
1992             && (Size_p != ObdSize)) {
1993                 // type is numerical, therefor size has to fit, but it does not.
1994                 Ret = kEplObdValueLengthError;
1995                 goto Exit;
1996         }
1997         // use given size, because non-numerical objects can be written with shorter values
1998         ObdSize = Size_p;
1999
2000         // set output parameters
2001         *pObdSize_p = ObdSize;
2002         *ppObdEntry_p = pObdEntry;
2003         *ppSubEntry_p = pSubEntry;
2004         *ppDstData_p = pDstData;
2005
2006         // all checks are done
2007         // the caller may now convert the numerial source value to platform byte order in a temporary buffer
2008
2009       Exit:
2010
2011         return Ret;
2012
2013 }
2014
2015 //---------------------------------------------------------------------------
2016 //
2017 // Function:    EplObdWriteEntryPost()
2018 //
2019 // Description: Function finishes write of data to an OBD entry. Strings
2020 //              are stored with added '\0' character.
2021 //
2022 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_
2023 //              uiIndex_p       =   Index of the OD entry
2024 //              uiSubIndex_p    =   Subindex of the OD Entry
2025 //              pSrcData_p      =   Pointer to the data to write
2026 //              Size_p          =   Size of the data in Byte
2027 //
2028 // Return:      tEplKernel      =   Errorcode
2029 //
2030 //
2031 // State:
2032 //
2033 //---------------------------------------------------------------------------
2034
2035 static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p,
2036                                        tEplObdSubEntryPtr pSubEntry_p,
2037                                        tEplObdCbParam *pCbParam_p,
2038                                        void *pSrcData_p,
2039                                        void *pDstData_p,
2040                                        tEplObdSize ObdSize_p)
2041 {
2042
2043         tEplKernel Ret;
2044
2045         // caller converted the source value to platform byte order
2046         // now the range of the value may be checked
2047
2048 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2049         {
2050                 // check data range
2051                 Ret = EplObdCheckObjectRange(pSubEntry_p, pSrcData_p);
2052                 if (Ret != kEplSuccessful) {
2053                         goto Exit;
2054                 }
2055         }
2056 #endif
2057
2058         // now call user callback function to check value
2059         // write address of source data to structure of callback parameters
2060         // so callback function can check this data
2061         pCbParam_p->m_pArg = pSrcData_p;
2062         pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
2063         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2064                                        pObdEntry_p->m_fpCallback, pCbParam_p);
2065         if (Ret != kEplSuccessful) {
2066                 goto Exit;
2067         }
2068         // copy object data to OBD
2069         EPL_MEMCPY(pDstData_p, pSrcData_p, ObdSize_p);
2070
2071         // terminate string with 0
2072         if (pSubEntry_p->m_Type == kEplObdTypVString) {
2073                 ((char *)pDstData_p)[ObdSize_p] = '\0';
2074         }
2075         // write address of destination to structure of callback parameters
2076         // so callback function can change data subsequently
2077         pCbParam_p->m_pArg = pDstData_p;
2078         pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
2079         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2080                                        pObdEntry_p->m_fpCallback, pCbParam_p);
2081
2082       Exit:
2083
2084         return Ret;
2085
2086 }
2087
2088 //---------------------------------------------------------------------------
2089 //
2090 // Function:    EplObdGetObjectSize()
2091 //
2092 // Description: function to get size of object
2093 //              The function determines if an object type an fixed data type (u8, u16, ...)
2094 //              or non fixed object (string, domain). This information is used to decide
2095 //              if download data are stored temporary or not. For objects with fixed data length
2096 //              and types a value range checking can process.
2097 //              For strings the function returns the whole object size not the
2098 //              length of string.
2099 //
2100 // Parameters:  pSubIndexEntry_p
2101 //
2102 // Return:      tEplObdSize
2103 //
2104 // State:
2105 //
2106 //---------------------------------------------------------------------------
2107
2108 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p)
2109 {
2110
2111         tEplObdSize DataSize = 0;
2112         void *pData;
2113
2114         switch (pSubIndexEntry_p->m_Type) {
2115                 // -----------------------------------------------------------------
2116         case kEplObdTypBool:
2117
2118                 DataSize = 1;
2119                 break;
2120
2121                 // -----------------------------------------------------------------
2122                 // ObdTypes which has to be check because numerical values
2123         case kEplObdTypInt8:
2124                 DataSize = sizeof(tEplObdInteger8);
2125                 break;
2126
2127                 // -----------------------------------------------------------------
2128         case kEplObdTypUInt8:
2129                 DataSize = sizeof(tEplObdUnsigned8);
2130                 break;
2131
2132                 // -----------------------------------------------------------------
2133         case kEplObdTypInt16:
2134                 DataSize = sizeof(tEplObdInteger16);
2135                 break;
2136
2137                 // -----------------------------------------------------------------
2138         case kEplObdTypUInt16:
2139                 DataSize = sizeof(tEplObdUnsigned16);
2140                 break;
2141
2142                 // -----------------------------------------------------------------
2143         case kEplObdTypInt32:
2144                 DataSize = sizeof(tEplObdInteger32);
2145                 break;
2146
2147                 // -----------------------------------------------------------------
2148         case kEplObdTypUInt32:
2149                 DataSize = sizeof(tEplObdUnsigned32);
2150                 break;
2151
2152                 // -----------------------------------------------------------------
2153         case kEplObdTypReal32:
2154                 DataSize = sizeof(tEplObdReal32);
2155                 break;
2156
2157                 // -----------------------------------------------------------------
2158                 // ObdTypes which has to be not checked because not NUM values
2159         case kEplObdTypDomain:
2160
2161                 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2162                 if ((void *)pData != (void *)NULL) {
2163                         DataSize = ((tEplObdVarEntry *) pData)->m_Size;
2164                 }
2165                 break;
2166
2167                 // -----------------------------------------------------------------
2168         case kEplObdTypVString:
2169                 //case kEplObdTypUString:
2170
2171                 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
2172                 // then the current pointer is always NULL. The function
2173                 // returns the length of default string.
2174                 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2175                 if ((void *)pData != (void *)NULL) {
2176                         // The max. size of strings defined by STRING-Macro is stored in
2177                         // tEplObdVString of current value.
2178                         // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2179                         DataSize = ((tEplObdVString *) pData)->m_Size;
2180                 } else {
2181                         // The current position is not decleared. The string
2182                         // is located in ROM, therefor use default pointer.
2183                         pData = (void *)pSubIndexEntry_p->m_pDefault;
2184                         if ((const void *)pData != (const void *)NULL) {
2185                                 // The max. size of strings defined by STRING-Macro is stored in
2186                                 // tEplObdVString of default value.
2187                                 DataSize = ((const tEplObdVString *)pData)->m_Size;
2188                         }
2189                 }
2190
2191                 break;
2192
2193                 // -----------------------------------------------------------------
2194         case kEplObdTypOString:
2195
2196                 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2197                 if ((void *)pData != (void *)NULL) {
2198                         // The max. size of strings defined by STRING-Macro is stored in
2199                         // tEplObdVString of current value.
2200                         // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2201                         DataSize = ((tEplObdOString *) pData)->m_Size;
2202                 } else {
2203                         // The current position is not decleared. The string
2204                         // is located in ROM, therefor use default pointer.
2205                         pData = (void *)pSubIndexEntry_p->m_pDefault;
2206                         if ((const void *)pData != (const void *)NULL) {
2207                                 // The max. size of strings defined by STRING-Macro is stored in
2208                                 // tEplObdVString of default value.
2209                                 DataSize = ((const tEplObdOString *)pData)->m_Size;
2210                         }
2211                 }
2212                 break;
2213
2214                 // -----------------------------------------------------------------
2215         case kEplObdTypInt24:
2216         case kEplObdTypUInt24:
2217
2218                 DataSize = 3;
2219                 break;
2220
2221                 // -----------------------------------------------------------------
2222         case kEplObdTypInt40:
2223         case kEplObdTypUInt40:
2224
2225                 DataSize = 5;
2226                 break;
2227
2228                 // -----------------------------------------------------------------
2229         case kEplObdTypInt48:
2230         case kEplObdTypUInt48:
2231
2232                 DataSize = 6;
2233                 break;
2234
2235                 // -----------------------------------------------------------------
2236         case kEplObdTypInt56:
2237         case kEplObdTypUInt56:
2238
2239                 DataSize = 7;
2240                 break;
2241
2242                 // -----------------------------------------------------------------
2243         case kEplObdTypInt64:
2244         case kEplObdTypUInt64:
2245         case kEplObdTypReal64:
2246
2247                 DataSize = 8;
2248                 break;
2249
2250                 // -----------------------------------------------------------------
2251         case kEplObdTypTimeOfDay:
2252         case kEplObdTypTimeDiff:
2253
2254                 DataSize = 6;
2255                 break;
2256
2257                 // -----------------------------------------------------------------
2258         default:
2259                 break;
2260         }
2261
2262         return DataSize;
2263 }
2264
2265 //---------------------------------------------------------------------------
2266 //
2267 // Function:    EplObdGetObjectDefaultPtr()
2268 //
2269 // Description: function to get the default pointer (type specific)
2270 //
2271 // Parameters:  pSubIndexEntry_p    = pointer to subindex structure
2272 //
2273 // Returns:     (void *)   = pointer to default value
2274 //
2275 // State:
2276 //
2277 //---------------------------------------------------------------------------
2278
2279 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2280 {
2281
2282         void *pDefault;
2283         tEplObdType Type;
2284
2285         ASSERTMSG(pSubIndexEntry_p != NULL,
2286                   "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
2287
2288         // get address to default data from default pointer
2289         pDefault = pSubIndexEntry_p->m_pDefault;
2290         if (pDefault != NULL) {
2291                 // there are some special types, whose default pointer always is NULL or has to get from other structure
2292                 // get type from subindex structure
2293                 Type = pSubIndexEntry_p->m_Type;
2294
2295                 // check if object type is a string value
2296                 if ((Type == kEplObdTypVString) /* ||
2297                                                    (Type == kEplObdTypUString) */ ) {
2298
2299                         // EPL_OBD_SUBINDEX_RAM_VSTRING
2300                         //    tEplObdSize         m_Size;       --> size of default string
2301                         //    char *    m_pDefString; --> pointer to  default string
2302                         //    char *    m_pString;    --> pointer to string in RAM
2303                         //
2304                         pDefault =
2305                             (void *)((tEplObdVString *) pDefault)->m_pString;
2306                 } else if (Type == kEplObdTypOString) {
2307                         pDefault =
2308                             (void *)((tEplObdOString *) pDefault)->m_pString;
2309                 }
2310         }
2311
2312         return pDefault;
2313
2314 }
2315
2316 //---------------------------------------------------------------------------
2317 //
2318 // Function:    EplObdGetVarEntry()
2319 //
2320 // Description: gets a variable entry of an object
2321 //
2322 // Parameters:  pSubindexEntry_p
2323 //              ppVarEntry_p
2324 //
2325 // Return:      tCopKernel
2326 //
2327 // State:
2328 //
2329 //---------------------------------------------------------------------------
2330
2331 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
2332                                     tEplObdVarEntry **ppVarEntry_p)
2333 {
2334
2335         tEplKernel Ret = kEplObdVarEntryNotExist;
2336
2337         ASSERT(ppVarEntry_p != NULL);   // is not allowed to be NULL
2338         ASSERT(pSubindexEntry_p != NULL);
2339
2340         // check VAR-Flag - only this object points to variables
2341         if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) {
2342                 // check if object is an array
2343                 if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) {
2344                         *ppVarEntry_p = &((tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
2345                 } else {
2346                         *ppVarEntry_p = (tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent;
2347                 }
2348
2349                 Ret = kEplSuccessful;
2350         }
2351
2352         return Ret;
2353
2354 }
2355
2356 //---------------------------------------------------------------------------
2357 //
2358 // Function:    EplObdGetEntry()
2359 //
2360 // Description: gets a index entry from OD
2361 //
2362 // Parameters:  uiIndex_p       =   Index number
2363 //              uiSubindex_p    =   Subindex number
2364 //              ppObdEntry_p    =   pointer to the pointer to the entry
2365 //              ppObdSubEntry_p =   pointer to the pointer to the subentry
2366 //
2367 // Return:      tEplKernel
2368
2369 //
2370 // State:
2371 //
2372 //---------------------------------------------------------------------------
2373
2374 static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
2375                                  unsigned int uiIndex_p,
2376                                  unsigned int uiSubindex_p,
2377                                  tEplObdEntryPtr * ppObdEntry_p,
2378                                  tEplObdSubEntryPtr * ppObdSubEntry_p)
2379 {
2380
2381         tEplObdEntryPtr pObdEntry;
2382         tEplObdCbParam CbParam;
2383         tEplKernel Ret;
2384
2385         // check for all API function if instance is valid
2386         EPL_MCO_CHECK_INSTANCE_STATE();
2387
2388         //------------------------------------------------------------------------
2389         // get address of entry of index
2390         Ret =
2391             EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam), uiIndex_p,
2392                                  &pObdEntry);
2393         if (Ret != kEplSuccessful) {
2394                 goto Exit;
2395         }
2396         //------------------------------------------------------------------------
2397         // get address of entry of subindex
2398         Ret = EplObdGetSubindexIntern(pObdEntry, uiSubindex_p, ppObdSubEntry_p);
2399         if (Ret != kEplSuccessful) {
2400                 goto Exit;
2401         }
2402         //------------------------------------------------------------------------
2403         // call callback function to inform user/stack that an object will be searched
2404         // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
2405         CbParam.m_uiIndex = uiIndex_p;
2406         CbParam.m_uiSubIndex = uiSubindex_p;
2407         CbParam.m_pArg = NULL;
2408         CbParam.m_ObdEvent = kEplObdEvCheckExist;
2409         Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2410                                        pObdEntry->m_fpCallback, &CbParam);
2411         if (Ret != kEplSuccessful) {
2412                 Ret = kEplObdIndexNotExist;
2413                 goto Exit;
2414         }
2415         //------------------------------------------------------------------------
2416         // it is allowed to set ppObdEntry_p to NULL
2417         // if so, no address will be written to calling function
2418         if (ppObdEntry_p != NULL) {
2419                 *ppObdEntry_p = pObdEntry;
2420         }
2421
2422       Exit:
2423
2424         return Ret;
2425
2426 }
2427
2428 //---------------------------------------------------------------------------
2429 //
2430 // Function:    EplObdGetObjectCurrentPtr()
2431 //
2432 // Description: function to get Current pointer (type specific)
2433 //
2434 // Parameters:  pSubIndexEntry_p
2435 //
2436 // Return:      void *
2437 //
2438 // State:
2439 //
2440 //---------------------------------------------------------------------------
2441
2442 static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2443 {
2444
2445         void *pData;
2446         unsigned int uiArrayIndex;
2447         tEplObdSize Size;
2448
2449         pData = pSubIndexEntry_p->m_pCurrent;
2450
2451         // check if constant object
2452         if (pData != NULL) {
2453                 // check if object is an array
2454                 if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) {
2455                         // calculate correct data pointer
2456                         uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
2457                         if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2458                                 Size = sizeof(tEplObdVarEntry);
2459                         } else {
2460                                 Size = EplObdGetObjectSize(pSubIndexEntry_p);
2461                         }
2462                         pData = ((u8 *) pData) + (Size * uiArrayIndex);
2463                 }
2464                 // check if VarEntry
2465                 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2466                         // The data pointer is stored in VarEntry->pData
2467                         pData = ((tEplObdVarEntry *) pData)->m_pData;
2468                 }
2469                 // the default pointer is stored for strings in tEplObdVString
2470                 else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString)        /* ||
2471                                                                                    (pSubIndexEntry_p->m_Type == kEplObdTypUString)    */
2472                          ) {
2473                         pData = (void *)((tEplObdVString *)pData)->m_pString;
2474                 } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) {
2475                         pData =
2476                             (void *)((tEplObdOString *)pData)->m_pString;
2477                 }
2478         }
2479
2480         return pData;
2481
2482 }
2483
2484 //---------------------------------------------------------------------------
2485 //
2486 // Function:    EplObdGetIndexIntern()
2487 //
2488 // Description: gets a index entry from OD
2489 //
2490 // Parameters:  pInitParam_p
2491 //              uiIndex_p
2492 //              ppObdEntry_p
2493 //
2494 // Return:      tEplKernel
2495 //
2496 // State:
2497 //
2498 //---------------------------------------------------------------------------
2499
2500 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p,
2501                                        unsigned int uiIndex_p,
2502                                        tEplObdEntryPtr * ppObdEntry_p)
2503 {
2504
2505         tEplObdEntryPtr pObdEntry;
2506         tEplKernel Ret;
2507         unsigned int uiIndex;
2508
2509 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2510
2511         unsigned int nLoop;
2512
2513         // if user OD is used then objekts also has to be searched in user OD
2514         // there is less code need if we do this in a loop
2515         nLoop = 2;
2516
2517 #endif
2518
2519         ASSERTMSG(ppObdEntry_p != NULL,
2520                   "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
2521
2522         Ret = kEplObdIndexNotExist;
2523
2524         // get start address of OD part
2525         // start address depends on object index because
2526         // object dictionary is divided in 3 parts
2527         if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) {
2528                 pObdEntry = pInitParam_p->m_pPart;
2529         } else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) {
2530                 pObdEntry = pInitParam_p->m_pManufacturerPart;
2531         }
2532         // index range 0xA000 to 0xFFFF is reserved for DSP-405
2533         // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
2534         // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
2535         // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
2536         // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
2537
2538 #if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
2539         else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
2540 #else
2541         else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
2542 #endif
2543         {
2544                 pObdEntry = pInitParam_p->m_pDevicePart;
2545         }
2546
2547 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2548
2549         // if index does not match in static OD then index only has to be searched in user OD
2550         else {
2551                 // begin from first entry of user OD part
2552                 pObdEntry = pInitParam_p->m_pUserPart;
2553
2554                 // no user OD is available
2555                 if (pObdEntry == NULL) {
2556                         goto Exit;
2557                 }
2558                 // loop must only run once
2559                 nLoop = 1;
2560         }
2561
2562         do {
2563
2564 #else
2565
2566         // no user OD is available
2567         // so other object can be found in OD
2568         else {
2569                 Ret = kEplObdIllegalPart;
2570                 goto Exit;
2571         }
2572
2573 #endif
2574
2575         // note:
2576         // The end of Index table is marked with m_uiIndex = 0xFFFF.
2577         // If this function will be called with wIndex_p = 0xFFFF, entry
2578         // should not be found. Therefor it is important to use
2579         // while{} instead of do{}while !!!
2580
2581         // get first index of index table
2582         uiIndex = pObdEntry->m_uiIndex;
2583
2584         // search Index in OD part
2585         while (uiIndex != EPL_OBD_TABLE_INDEX_END) {
2586                 // go to the end of this function if index is found
2587                 if (uiIndex_p == uiIndex) {
2588                         // write address of OD entry to calling function
2589                         *ppObdEntry_p = pObdEntry;
2590                         Ret = kEplSuccessful;
2591                         goto Exit;
2592                 }
2593                 // objects are sorted in OD
2594                 // if the current index in OD is greater than the index which is to search then break loop
2595                 // in this case user OD has to be search too
2596                 if (uiIndex_p < uiIndex) {
2597                         break;
2598                 }
2599                 // next entry in index table
2600                 pObdEntry++;
2601
2602                 // get next index of index table
2603                 uiIndex = pObdEntry->m_uiIndex;
2604         }
2605
2606 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2607
2608         // begin from first entry of user OD part
2609         pObdEntry = pInitParam_p->m_pUserPart;
2610
2611         // no user OD is available
2612         if (pObdEntry == NULL) {
2613                 goto Exit;
2614         }
2615         // switch next loop for user OD
2616         nLoop--;
2617
2618 }
2619
2620 while (nLoop > 0) ;
2621
2622 #endif
2623
2624     // in this line Index was not found
2625
2626 Exit:
2627
2628 return Ret;
2629
2630 }
2631
2632 //---------------------------------------------------------------------------
2633 //
2634 // Function:    EplObdGetSubindexIntern()
2635 //
2636 // Description: gets a subindex entry from a index entry
2637 //
2638 // Parameters:  pObdEntry_p
2639 //              bSubIndex_p
2640 //              ppObdSubEntry_p
2641 //
2642 // Return:      tEplKernel
2643 //
2644 // State:
2645 //
2646 //---------------------------------------------------------------------------
2647
2648 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
2649                                           unsigned int uiSubIndex_p,
2650                                           tEplObdSubEntryPtr * ppObdSubEntry_p)
2651 {
2652
2653         tEplObdSubEntryPtr pSubEntry;
2654         unsigned int nSubIndexCount;
2655         tEplKernel Ret;
2656
2657         ASSERTMSG(pObdEntry_p != NULL,
2658                   "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
2659         ASSERTMSG(ppObdSubEntry_p != NULL,
2660                   "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
2661
2662         Ret = kEplObdSubindexNotExist;
2663
2664         // get start address of subindex table and count of subindices
2665         pSubEntry = pObdEntry_p->m_pSubIndex;
2666         nSubIndexCount = pObdEntry_p->m_uiCount;
2667         ASSERTMSG((pSubEntry != NULL) && (nSubIndexCount > 0), "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
2668
2669         // search subindex in subindex table
2670         while (nSubIndexCount > 0) {
2671                 // check if array is found
2672                 if ((pSubEntry->m_Access & kEplObdAccArray) != 0) {
2673                         // check if subindex is in range
2674                         if (uiSubIndex_p < pObdEntry_p->m_uiCount) {
2675                                 // update subindex number (subindex entry of an array is always in RAM !!!)
2676                                 pSubEntry->m_uiSubIndex = uiSubIndex_p;
2677                                 *ppObdSubEntry_p = pSubEntry;
2678                                 Ret = kEplSuccessful;
2679                                 goto Exit;
2680                         }
2681                 }
2682                 // go to the end of this function if subindex is found
2683                 else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) {
2684                         *ppObdSubEntry_p = pSubEntry;
2685                         Ret = kEplSuccessful;
2686                         goto Exit;
2687                 }
2688                 // objects are sorted in OD
2689                 // if the current subindex in OD is greater than the subindex which is to search then break loop
2690                 // in this case user OD has to be search too
2691                 if (uiSubIndex_p < pSubEntry->m_uiSubIndex) {
2692                         break;
2693                 }
2694
2695                 pSubEntry++;
2696                 nSubIndexCount--;
2697         }
2698
2699         // in this line SubIndex was not fount
2700
2701       Exit:
2702
2703         return Ret;
2704
2705 }
2706
2707 //---------------------------------------------------------------------------
2708 //
2709 // Function:    EplObdSetStoreLoadObjCallback()
2710 //
2711 // Description: function set address to callbackfunction for command Store and Load
2712 //
2713 // Parameters:  fpCallback_p
2714 //
2715 // Return:      tEplKernel
2716 //
2717 // State:
2718 //
2719 //---------------------------------------------------------------------------
2720 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2721 tEplKernel EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdStoreLoadObjCallback fpCallback_p)
2722 {
2723
2724         EPL_MCO_CHECK_INSTANCE_STATE();
2725
2726         // set new address of callback function
2727         EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = fpCallback_p;
2728
2729         return kEplSuccessful;
2730
2731 }
2732 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2733
2734 //---------------------------------------------------------------------------
2735 //
2736 // Function:    EplObdAccessOdPartIntern()
2737 //
2738 // Description: runs through OD and executes a job
2739 //
2740 // Parameters:  CurrentOdPart_p
2741 //              pObdEnty_p
2742 //              Direction_p     = what is to do (load values from flash or EEPROM, store, ...)
2743 //
2744 // Return:      tEplKernel
2745 //
2746 // State:
2747 //
2748 //---------------------------------------------------------------------------
2749
2750 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
2751                                            tEplObdPart CurrentOdPart_p,
2752                                            tEplObdEntryPtr pObdEnty_p,
2753                                            tEplObdDir Direction_p)
2754 {
2755
2756         tEplObdSubEntryPtr pSubIndex;
2757         unsigned int nSubIndexCount;
2758         tEplObdAccess Access;
2759         void *pDstData;
2760         void *pDefault;
2761         tEplObdSize ObjSize;
2762         tEplKernel Ret;
2763         tEplObdCbStoreParam CbStore;
2764         tEplObdVarEntry *pVarEntry;
2765
2766         ASSERT(pObdEnty_p != NULL);
2767
2768         Ret = kEplSuccessful;
2769
2770         // prepare structure for STORE RESTORE callback function
2771         CbStore.m_bCurrentOdPart = (u8) CurrentOdPart_p;
2772         CbStore.m_pData = NULL;
2773         CbStore.m_ObjSize = 0;
2774
2775         // command of first action depends on direction to access
2776 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2777         if (Direction_p == kEplObdDirLoad) {
2778                 CbStore.m_bCommand = (u8) kEplObdCommOpenRead;
2779
2780                 // call callback function for previous command
2781                 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2782                 if (Ret != kEplSuccessful) {
2783                         goto Exit;
2784                 }
2785                 // set command for index and subindex loop
2786                 CbStore.m_bCommand = (u8) kEplObdCommReadObj;
2787         } else if (Direction_p == kEplObdDirStore) {
2788                 CbStore.m_bCommand = (u8) kEplObdCommOpenWrite;
2789
2790                 // call callback function for previous command
2791                 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2792                 if (Ret != kEplSuccessful) {
2793                         goto Exit;
2794                 }
2795                 // set command for index and subindex loop
2796                 CbStore.m_bCommand = (u8) kEplObdCommWriteObj;
2797         }
2798 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2799
2800         // we should not restore the OD values here
2801         // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
2802         if (Direction_p != kEplObdDirRestore) {
2803                 // walk through OD part till end is found
2804                 while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) {
2805                         // get address to subindex table and count of subindices
2806                         pSubIndex = pObdEnty_p->m_pSubIndex;
2807                         nSubIndexCount = pObdEnty_p->m_uiCount;
2808                         ASSERT((pSubIndex != NULL) && (nSubIndexCount > 0));    // should never be NULL
2809
2810                         // walk through subindex table till all subinices were restored
2811                         while (nSubIndexCount != 0) {
2812                                 Access = (tEplObdAccess) pSubIndex->m_Access;
2813
2814                                 // get pointer to current and default data
2815                                 pDefault = EplObdGetObjectDefaultPtr(pSubIndex);
2816                                 pDstData = EplObdGetObjectCurrentPtr(pSubIndex);
2817
2818                                 // NOTE (for kEplObdTypVString):
2819                                 //      The function returnes the max. number of bytes for a
2820                                 //      current string.
2821                                 //      r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
2822                                 ObjSize = EplObdGetObjectSize(pSubIndex);
2823
2824                                 // switch direction of OD access
2825                                 switch (Direction_p) {
2826                                         // --------------------------------------------------------------------------
2827                                         // VarEntry structures has to be initialized
2828                                 case kEplObdDirInit:
2829
2830                                         // If VAR-Flag is set, m_pCurrent means not address of data
2831                                         // but address of tEplObdVarEntry. Address of data has to be get from
2832                                         // this structure.
2833                                         if ((Access & kEplObdAccVar) != 0) {
2834                                                 EplObdGetVarEntry(pSubIndex,
2835                                                                   &pVarEntry);
2836                                                 EplObdInitVarEntry(pVarEntry,
2837                                                                    pSubIndex->
2838                                                                    m_Type,
2839                                                                    ObjSize);
2840 /*
2841                             if ((Access & kEplObdAccArray) == 0)
2842                             {
2843                                 EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
2844                             }
2845                             else
2846                             {
2847                                 EplObdInitVarEntry ((tEplObdVarEntry *) (((u8 *) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
2848                                     pSubIndex->m_Type, ObjSize);
2849                             }
2850 */
2851                                                 // at this time no application variable is defined !!!
2852                                                 // therefore data can not be copied.
2853                                                 break;
2854                                         } else if (pSubIndex->m_Type ==
2855                                                    kEplObdTypVString) {
2856                                                 // If pointer m_pCurrent is not equal to NULL then the
2857                                                 // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
2858                                                 // pointer points to struct tEplObdVString located in MEM.
2859                                                 // The element size includes the max. number of
2860                                                 // bytes. The element m_pString includes the pointer
2861                                                 // to string in MEM. The memory location of default string
2862                                                 // must be copied to memory location of current string.
2863
2864                                                 pDstData =
2865                                                     pSubIndex->m_pCurrent;
2866                                                 if (pDstData != NULL) {
2867                                                         // 08-dec-2004: code optimization !!!
2868                                                         //              entries ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString
2869                                                         //              and ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_Size were read
2870                                                         //              twice. thats not necessary!
2871
2872                                                         // For copying data we have to set the destination pointer to the real RAM string. This
2873                                                         // pointer to RAM string is located in default string info structure. (translated r.d.)
2874                                                         pDstData = (void *)((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString;
2875                                                         ObjSize = ((tEplObdVStringDef *)pSubIndex->m_pDefault)->m_Size;
2876
2877                                                         ((tEplObdVString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2878                                                         ((tEplObdVString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2879                                                 }
2880
2881                                         } else if (pSubIndex->m_Type ==
2882                                                    kEplObdTypOString) {
2883                                                 pDstData =
2884                                                     pSubIndex->m_pCurrent;
2885                                                 if (pDstData != NULL) {
2886                                                         // 08-dec-2004: code optimization !!!
2887                                                         //              entries ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_pString
2888                                                         //              and ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_Size were read
2889                                                         //              twice. thats not necessary!
2890
2891                                                         // For copying data we have to set the destination pointer to the real RAM string. This
2892                                                         // pointer to RAM string is located in default string info structure. (translated r.d.)
2893                                                         pDstData = (void *)((tEplObdOStringDef *) pSubIndex->m_pDefault)->m_pString;
2894                                                         ObjSize = ((tEplObdOStringDef *)pSubIndex->m_pDefault)->m_Size;
2895
2896                                                         ((tEplObdOString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2897                                                         ((tEplObdOString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2898                                                 }
2899
2900                                         }
2901
2902                                         // no break !! because copy of data has to done too.
2903
2904                                         // --------------------------------------------------------------------------
2905                                         // all objects has to be restored with default values
2906                                 case kEplObdDirRestore:
2907
2908                                         // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
2909                                         //                   is replaced to function ObdCopyObjectData() with a new parameter.
2910
2911                                         // restore object data for init phase
2912                                         EplObdCopyObjectData(pDstData, pDefault,
2913                                                              ObjSize,
2914                                                              pSubIndex->m_Type);
2915                                         break;
2916
2917                                         // --------------------------------------------------------------------------
2918                                         // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
2919                                 case kEplObdDirLoad:
2920
2921                                         // restore object data for init phase
2922                                         EplObdCopyObjectData(pDstData, pDefault,
2923                                                              ObjSize,
2924                                                              pSubIndex->m_Type);
2925
2926                                         // no break !! because callback function has to be called too.
2927
2928                                         // --------------------------------------------------------------------------
2929                                         // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
2930                                 case kEplObdDirStore:
2931
2932                                         // when attribute kEplObdAccStore is set, then call callback function
2933 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2934                                         if ((Access & kEplObdAccStore) != 0) {
2935                                                 // fill out data pointer and size of data
2936                                                 CbStore.m_pData = pDstData;
2937                                                 CbStore.m_ObjSize = ObjSize;
2938
2939                                                 // call callback function for read or write object
2940                                                 Ret =
2941                                                     ObdCallStoreCallback
2942                                                     (EPL_MCO_INSTANCE_PTR_ &
2943                                                      CbStore);
2944                                                 if (Ret != kEplSuccessful) {
2945                                                         goto Exit;
2946                                                 }
2947                                         }
2948 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2949                                         break;
2950
2951                                         // --------------------------------------------------------------------------
2952                                         // if OD Builder key has to be checked no access to subindex and data should be made
2953                                 case kEplObdDirOBKCheck:
2954
2955                                         // no break !! because we want to break the second loop too.
2956
2957                                         // --------------------------------------------------------------------------
2958                                         // unknown Direction
2959                                 default:
2960
2961                                         // so we can break the second loop earler
2962                                         nSubIndexCount = 1;
2963                                         break;
2964                                 }
2965
2966                                 nSubIndexCount--;
2967
2968                                 // next subindex entry
2969                                 if ((Access & kEplObdAccArray) == 0) {
2970                                         pSubIndex++;
2971                                         if ((nSubIndexCount > 0)
2972                                             &&
2973                                             ((pSubIndex->
2974                                               m_Access & kEplObdAccArray) !=
2975                                              0)) {
2976                                                 // next subindex points to an array
2977                                                 // reset subindex number
2978                                                 pSubIndex->m_uiSubIndex = 1;
2979                                         }
2980                                 } else {
2981                                         if (nSubIndexCount > 0) {
2982                                                 // next subindex points to an array
2983                                                 // increment subindex number
2984                                                 pSubIndex->m_uiSubIndex++;
2985                                         }
2986                                 }
2987                         }
2988
2989                         // next index entry
2990                         pObdEnty_p++;
2991                 }
2992         }
2993         // -----------------------------------------------------------------------------------------
2994         // command of last action depends on direction to access
2995         if (Direction_p == kEplObdDirOBKCheck) {
2996
2997                 goto Exit;
2998         }
2999 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3000         else {
3001                 if (Direction_p == kEplObdDirLoad) {
3002                         CbStore.m_bCommand = (u8) kEplObdCommCloseRead;
3003                 } else if (Direction_p == kEplObdDirStore) {
3004                         CbStore.m_bCommand = (u8) kEplObdCommCloseWrite;
3005                 } else if (Direction_p == kEplObdDirRestore) {
3006                         CbStore.m_bCommand = (u8) kEplObdCommClear;
3007                 } else {
3008                         goto Exit;
3009                 }
3010
3011                 // call callback function for last command
3012                 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
3013         }
3014 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3015
3016 //    goto Exit;
3017
3018       Exit:
3019
3020         return Ret;
3021
3022 }
3023
3024 // ----------------------------------------------------------------------------
3025 // Function:    EplObdCopyObjectData()
3026 //
3027 // Description: checks pointers to object data and copy them from source to destination
3028 //
3029 // Parameters:  pDstData_p              = destination pointer
3030 //              pSrcData_p              = source pointer
3031 //              ObjSize_p               = size of object
3032 //              ObjType_p               =
3033 //
3034 // Returns:     tEplKernel              = error code
3035 // ----------------------------------------------------------------------------
3036
3037 static void EplObdCopyObjectData(void *pDstData_p,
3038                                  void *pSrcData_p,
3039                                  tEplObdSize ObjSize_p, tEplObdType ObjType_p)
3040 {
3041
3042         tEplObdSize StrSize = 0;
3043
3044         // it is allowed to set default and current address to NULL (nothing to copy)
3045         if (pDstData_p != NULL) {
3046
3047                 if (ObjType_p == kEplObdTypVString) {
3048                         // The function calculates the really number of characters of string. The
3049                         // object entry size can be bigger as string size of default string.
3050                         // The '\0'-termination is included. A string with no characters has a
3051                         // size of 1.
3052                         StrSize =
3053                             EplObdGetStrLen((void *)pSrcData_p, ObjSize_p,
3054                                             kEplObdTypVString);
3055
3056                         // If the string length is greater than or equal to the entry size in OD then only copy
3057                         // entry size - 1 and always set the '\0'-termination.
3058                         if (StrSize >= ObjSize_p) {
3059                                 StrSize = ObjSize_p - 1;
3060                         }
3061                 }
3062
3063                 if (pSrcData_p != NULL) {
3064                         // copy data
3065                         EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p);
3066
3067                         if (ObjType_p == kEplObdTypVString) {
3068                                 ((char *)pDstData_p)[StrSize] = '\0';
3069                         }
3070                 }
3071         }
3072
3073 }
3074
3075 //---------------------------------------------------------------------------
3076 //
3077 // Function:    EplObdIsNumericalIntern()
3078 //
3079 // Description: function checks if a entry is numerical or not
3080 //
3081 //
3082 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
3083 //              uiIndex_p           = Index
3084 //              uiSubIndex_p        = Subindex
3085 //              pfEntryNumerical_p  = pointer to BOOL for returnvalue
3086 //                                  -> TRUE if entry a numerical value
3087 //                                  -> FALSE if entry not a numerical value
3088 //
3089 // Return:      tEplKernel = Errorcode
3090 //
3091 // State:
3092 //
3093 //---------------------------------------------------------------------------
3094 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
3095                                           BOOL * pfEntryNumerical_p)
3096 {
3097         tEplKernel Ret = kEplSuccessful;
3098
3099         // get Type
3100         if ((pObdSubEntry_p->m_Type == kEplObdTypVString)
3101             || (pObdSubEntry_p->m_Type == kEplObdTypOString)
3102             || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) {  // not numerical types
3103                 *pfEntryNumerical_p = FALSE;
3104         } else {                // numerical types
3105                 *pfEntryNumerical_p = TRUE;
3106         }
3107
3108         return Ret;
3109
3110 }
3111
3112 // -------------------------------------------------------------------------
3113 // function to classify object type (fixed/non fixed)
3114 // -------------------------------------------------------------------------
3115
3116 // ----------------------------------------------------------------------------
3117 // Function:    EplObdCallStoreCallback()
3118 //
3119 // Description: checks address to callback function and calles it when unequal
3120 //              to NULL
3121 //
3122 // Parameters:  EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
3123 //              pCbStoreParam_p        = address to callback parameters
3124 //
3125 // Returns:     tEplKernel             = error code
3126 // ----------------------------------------------------------------------------
3127 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3128 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
3129                                           tEplObdCbStoreParam *
3130                                           pCbStoreParam_p)
3131 {
3132
3133         tEplKernel Ret = kEplSuccessful;
3134
3135         ASSERT(pCbStoreParam_p != NULL);
3136
3137         // check if function pointer is NULL - if so, no callback should be called
3138         if (EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) != NULL) {
3139                 Ret =
3140                     EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback)
3141                     (EPL_MCO_INSTANCE_PARAM_IDX_()
3142                      pCbStoreParam_p);
3143         }
3144
3145         return Ret;
3146
3147 }
3148 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3149 //---------------------------------------------------------------------------
3150 //
3151 // Function:    EplObdGetObjectDataPtrIntern()
3152 //
3153 // Description: Function gets the data pointer of an object.
3154 //              It returnes the current data pointer. But if object is an
3155 //              constant object it returnes the default pointer.
3156 //
3157 // Parameters:  pSubindexEntry_p = pointer to subindex entry
3158 //
3159 // Return:      void *    = pointer to object data
3160 //
3161 // State:
3162 //
3163 //---------------------------------------------------------------------------
3164
3165 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p)
3166 {
3167
3168         void *pData;
3169         tEplObdAccess Access;
3170
3171         ASSERTMSG(pSubindexEntry_p != NULL,
3172                   "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
3173
3174         // there are are some objects whose data pointer has to get from other structure
3175         // get access type for this object
3176         Access = pSubindexEntry_p->m_Access;
3177
3178         // If object has access type = const,
3179         // for data only exists default values.
3180         if ((Access & kEplObdAccConst) != 0) {
3181                 // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
3182                 pData = ((void *)EplObdGetObjectDefaultPtr(pSubindexEntry_p));
3183         } else {
3184                 // The pointer to current value can be received from ObdGetObjectCurrentPtr()
3185                 pData = ((void *)EplObdGetObjectCurrentPtr(pSubindexEntry_p));
3186         }
3187
3188         return pData;
3189
3190 }
3191 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
3192 // EOF