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