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