1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for api function of EplOBD-Module
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
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.
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.
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.
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.
50 -------------------------------------------------------------------------
52 $RCSfile: EplObd.c,v $
56 $Revision: 1.12 $ $Date: 2008/10/17 15:32:32 $
63 -------------------------------------------------------------------------
67 2006/06/02 k.t.: start of the implementation, version 1.00
68 ->based on CANopen OBD-Modul
70 ****************************************************************************/
73 #include "kernel/EplObdk.h" // function prototyps of the EplOBD-Modul
75 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
77 /***************************************************************************/
80 /* G L O B A L D E F I N I T I O N S */
83 /***************************************************************************/
85 //---------------------------------------------------------------------------
87 //---------------------------------------------------------------------------
89 // float definitions and macros
90 #define _SHIFTED_EXPONENT_MASK_SP 0xff
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)
97 //---------------------------------------------------------------------------
99 //---------------------------------------------------------------------------
101 // struct for instance table
102 INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER()
104 STATIC tEplObdInitParam m_ObdInitParam;
105 STATIC tEplObdStoreLoadObjCallback m_fpStoreLoadObjCallback;
108 // decomposition of float
110 tEplObdReal32 m_flRealPart;
115 //---------------------------------------------------------------------------
116 // modul globale vars
117 //---------------------------------------------------------------------------
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 *
124 EPL_MCO_DECL_INSTANCE_VAR()
126 u8 abEplObdTrashObject_g[8];
128 //---------------------------------------------------------------------------
129 // local function prototypes
130 //---------------------------------------------------------------------------
132 EPL_MCO_DEFINE_INSTANCE_FCT()
134 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
135 tEplObdCallback fpCallback_p,
136 tEplObdCbParam *pCbParam_p);
138 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p);
140 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
141 tEplObdSize ObjLen_p, tEplObdType ObjType_p);
143 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
144 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
148 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
149 tEplObdVarEntry **ppVarEntry_p);
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);
157 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p);
159 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p,
160 unsigned int uiIndex_p,
161 tEplObdEntryPtr * ppObdEntry_p);
163 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
164 unsigned int uiSubIndex_p,
165 tEplObdSubEntryPtr * ppObdSubEntry_p);
167 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
168 tEplObdPart CurrentOdPart_p,
169 tEplObdEntryPtr pObdEnty_p,
170 tEplObdDir Direction_p);
172 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
173 static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
175 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
177 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdCbStoreParam *pCbStoreParam_p);
179 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
181 static void EplObdCopyObjectData(void *pDstData_p,
183 tEplObdSize ObjSize_p, tEplObdType ObjType_p);
185 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p);
187 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
188 BOOL * pfEntryNumerical_p);
190 static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
191 unsigned int uiSubIndex_p,
195 tEplObdEntryPtr *ppObdEntry_p,
196 tEplObdSubEntryPtr *ppSubEntry_p,
197 tEplObdCbParam *pCbParam_p,
198 tEplObdSize *pObdSize_p);
200 static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p,
201 tEplObdSubEntryPtr pSubEntry_p,
202 tEplObdCbParam *pCbParam_p,
205 tEplObdSize ObdSize_p);
207 //=========================================================================//
209 // P U B L I C F U N C T I O N S //
211 //=========================================================================//
213 //---------------------------------------------------------------------------
215 // Function: EplObdInit()
217 // Description: initializes the first instance
219 // Parameters: pInitParam_p = init parameter
221 // Return: tEplKernel = errorcode
225 //---------------------------------------------------------------------------
227 tEplKernel EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p)
231 EPL_MCO_DELETE_INSTANCE_TABLE();
233 if (pInitParam_p == NULL) {
234 Ret = kEplSuccessful;
238 Ret = EplObdAddInstance(EPL_MCO_PTR_INSTANCE_PTR_ pInitParam_p);
245 //---------------------------------------------------------------------------
247 // Function: EplObdAddInstance()
249 // Description: adds a new instance
251 // Parameters: pInitParam_p
253 // Return: tEplKernel
257 //---------------------------------------------------------------------------
259 tEplKernel EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p)
262 EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret;
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();
271 // save init parameters
272 EPL_MEMCPY(&EPL_MCO_GLB_VAR(m_ObdInitParam), pInitParam_p,
273 sizeof(tEplObdInitParam));
275 // clear callback function for command LOAD and STORE
276 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = NULL;
278 // sign instance as used
279 EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed);
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);
290 //---------------------------------------------------------------------------
292 // Function: EplObdDeleteInstance()
294 // Description: delete instance
296 // Parameters: EPL_MCO_DECL_INSTANCE_PTR
298 // Return: tEplKernel
302 //---------------------------------------------------------------------------
303 #if (EPL_USE_DELETEINST_FUNC != FALSE)
304 tEplKernel EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR)
306 // check for all API function if instance is valid
307 EPL_MCO_CHECK_INSTANCE_STATE();
309 // sign instance as unused
310 EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused);
312 return kEplSuccessful;
315 #endif // (EPL_USE_DELETEINST_FUNC != FALSE)
317 //---------------------------------------------------------------------------
319 // Function: EplObdWriteEntry()
321 // Description: Function writes data to an OBD entry. Strings
322 // are stored with added '\0' character.
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
330 // Return: tEplKernel = Errorcode
335 //---------------------------------------------------------------------------
337 tEplKernel EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
338 unsigned int uiSubIndex_p,
339 void *pSrcData_p, tEplObdSize Size_p)
343 tEplObdEntryPtr pObdEntry;
344 tEplObdSubEntryPtr pSubEntry;
345 tEplObdCbParam CbParam;
349 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
355 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
356 if (Ret != kEplSuccessful) {
360 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
363 &CbParam, pSrcData_p, pDstData, ObdSize);
364 if (Ret != kEplSuccessful) {
374 //---------------------------------------------------------------------------
376 // Function: EplObdReadEntry()
378 // Description: The function reads an object entry. The application
379 // can always read the data even if attrib kEplObdAccRead
380 // is not set. The attrib is only checked up for SDO transfer.
382 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
383 // uiIndex_p = Index oof the OD entry to read
384 // uiSubIndex_p = Subindex to read
385 // pDstData_p = pointer to the buffer for data
386 // Offset_p = offset in data for read access
387 // pSize_p = IN: Size of the buffer
388 // OUT: number of readed Bytes
390 // Return: tEplKernel
394 //---------------------------------------------------------------------------
396 tEplKernel EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
397 unsigned int uiSubIndex_p,
398 void *pDstData_p, tEplObdSize *pSize_p)
402 tEplObdEntryPtr pObdEntry;
403 tEplObdSubEntryPtr pSubEntry;
404 tEplObdCbParam CbParam;
408 // check for all API function if instance is valid
409 EPL_MCO_CHECK_INSTANCE_STATE();
411 ASSERT(pDstData_p != NULL);
412 ASSERT(pSize_p != NULL);
414 // get address of index and subindex entry
415 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
416 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
417 if (Ret != kEplSuccessful) {
420 // get pointer to object data
421 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
423 // check source pointer
424 if (pSrcData == NULL) {
425 Ret = kEplObdReadViolation;
428 //------------------------------------------------------------------------
429 // address of source data to structure of callback parameters
430 // so callback function can change this data before reading
431 CbParam.m_uiIndex = uiIndex_p;
432 CbParam.m_uiSubIndex = uiSubIndex_p;
433 CbParam.m_pArg = pSrcData;
434 CbParam.m_ObdEvent = kEplObdEvPreRead;
435 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
436 pObdEntry->m_fpCallback, &CbParam);
437 if (Ret != kEplSuccessful) {
440 // get size of data and check if application has reserved enough memory
441 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
442 // check if offset given and calc correct number of bytes to read
443 if (*pSize_p < ObdSize) {
444 Ret = kEplObdValueLengthError;
447 // read value from object
448 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
451 // write address of destination data to structure of callback parameters
452 // so callback function can change this data after reading
453 CbParam.m_pArg = pDstData_p;
454 CbParam.m_ObdEvent = kEplObdEvPostRead;
455 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
456 pObdEntry->m_fpCallback, &CbParam);
464 //---------------------------------------------------------------------------
466 // Function: EplObdAccessOdPart()
468 // Description: restores default values of one part of OD
470 // Parameters: ObdPart_p
473 // Return: tEplKernel
477 //---------------------------------------------------------------------------
479 tEplKernel EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdPart ObdPart_p,
480 tEplObdDir Direction_p)
483 tEplKernel Ret = kEplSuccessful;
485 tEplObdEntryPtr pObdEntry;
487 // check for all API function if instance is valid
488 EPL_MCO_CHECK_INSTANCE_STATE();
490 // part always has to be unequal to NULL
491 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pPart);
492 ASSERTMSG(pObdEntry != NULL,
493 "EplObdAccessOdPart(): no OD part is defined!\n");
495 // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
499 if ((ObdPart_p & kEplObdPartGen) != 0) {
502 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
503 kEplObdPartGen, pObdEntry,
505 if (Ret != kEplSuccessful) {
509 // access to manufacturer part
510 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pManufacturerPart);
512 if (((ObdPart_p & kEplObdPartMan) != 0) && (pObdEntry != NULL)) {
515 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
516 kEplObdPartMan, pObdEntry,
518 if (Ret != kEplSuccessful) {
522 // access to device part
523 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pDevicePart);
525 if (((ObdPart_p & kEplObdPartDev) != 0) && (pObdEntry != NULL)) {
528 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
529 kEplObdPartDev, pObdEntry,
531 if (Ret != kEplSuccessful) {
535 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
537 // access to user part
538 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart);
540 if (((ObdPart_p & kEplObdPartUsr) != 0) && (pObdEntry != NULL)) {
543 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
545 pObdEntry, Direction_p);
546 if (Ret != kEplSuccessful) {
553 // no access to an OD part was done? illegal OD part was specified!
554 if (fPartFount == FALSE) {
555 Ret = kEplObdIllegalPart;
564 //---------------------------------------------------------------------------
566 // Function: EplObdDefineVar()
568 // Description: defines a variable in OD
570 // Parameters: pEplVarParam_p
572 // Return: tEplKernel
576 //---------------------------------------------------------------------------
578 tEplKernel EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ tEplVarParam *pVarParam_p)
582 tEplObdVarEntry *pVarEntry;
583 tEplVarParamValid VarValid;
584 tEplObdSubEntryPtr pSubindexEntry;
586 // check for all API function if instance is valid
587 EPL_MCO_CHECK_INSTANCE_STATE();
589 ASSERT(pVarParam_p != NULL); // is not allowed to be NULL
591 // get address of subindex entry
592 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
593 pVarParam_p->m_uiIndex,
594 pVarParam_p->m_uiSubindex, NULL, &pSubindexEntry);
595 if (Ret != kEplSuccessful) {
599 Ret = EplObdGetVarEntry(pSubindexEntry, &pVarEntry);
600 if (Ret != kEplSuccessful) {
604 VarValid = pVarParam_p->m_ValidFlag;
606 // copy only this values, which valid flag is set
607 if ((VarValid & kVarValidSize) != 0) {
608 if (pSubindexEntry->m_Type != kEplObdTypDomain) {
609 tEplObdSize DataSize;
611 // check passed size parameter
612 DataSize = EplObdGetObjectSize(pSubindexEntry);
613 if (DataSize != pVarParam_p->m_Size) { // size of variable does not match
614 Ret = kEplObdValueLengthError;
617 } else { // size can be set only for objects of type DOMAIN
618 pVarEntry->m_Size = pVarParam_p->m_Size;
622 if ((VarValid & kVarValidData) != 0) {
623 pVarEntry->m_pData = pVarParam_p->m_pData;
626 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
628 if ((VarValid & kVarValidCallback) != 0)
630 pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
633 if ((VarValid & kVarValidArg) != 0)
635 pVarEntry->m_pArg = pVarParam_p->m_pArg;
640 // Ret is already set to kEplSuccessful from ObdGetVarIntern()
648 //---------------------------------------------------------------------------
650 // Function: EplObdGetObjectDataPtr()
652 // Description: It returnes the current data pointer. But if object is an
653 // constant object it returnes the default pointer.
655 // Parameters: uiIndex_p = Index of the entry
656 // uiSubindex_p = Subindex of the entry
658 // Return: void * = pointer to object data
662 //---------------------------------------------------------------------------
664 void *EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
665 unsigned int uiSubIndex_p)
669 tEplObdEntryPtr pObdEntry;
670 tEplObdSubEntryPtr pObdSubEntry;
672 // get pointer to index structure
673 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
674 uiIndex_p, &pObdEntry);
675 if (Ret != kEplSuccessful) {
679 // get pointer to subindex structure
680 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
681 if (Ret != kEplSuccessful) {
686 pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
693 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
695 //---------------------------------------------------------------------------
697 // Function: EplObdRegisterUserOd()
699 // Description: function registers the user OD
701 // Parameters: pUserOd_p =pointer to user ODd
703 // Return: tEplKernel = errorcode
707 //---------------------------------------------------------------------------
708 tEplKernel EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pUserOd_p)
711 EPL_MCO_CHECK_INSTANCE_STATE();
713 EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart) = pUserOd_p;
715 return kEplSuccessful;
721 //---------------------------------------------------------------------------
723 // Function: EplObdInitVarEntry()
725 // Description: function to initialize VarEntry dependened on object type
727 // Parameters: pVarEntry_p = pointer to var entry structure
728 // Type_p = object type
729 // ObdSize_p = size of object data
735 //---------------------------------------------------------------------------
737 void EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdVarEntry *pVarEntry_p,
738 tEplObdType Type_p, tEplObdSize ObdSize_p)
741 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
743 // reset pointer to VAR callback and argument
744 pVarEntry_p->m_fpCallback = NULL;
745 pVarEntry_p->m_pArg = NULL;
750 // 10-dec-2004 r.d.: this function will not be used for strings
751 if ((Type_p == kEplObdTypDomain))
752 // (bType_p == kEplObdTypVString) /* ||
753 // (bType_p == kEplObdTypOString) ||
754 // (bType_p == kEplObdTypUString) */ )
756 // variables which are defined as DOMAIN or VSTRING should not point to
757 // trash object, because this trash object contains only 8 bytes. DOMAINS or
758 // STRINGS can be longer.
759 pVarEntry_p->m_pData = NULL;
760 pVarEntry_p->m_Size = 0;
762 // set address to variable data to trash object
763 // This prevents an access violation if user forgets to call EplObdDefineVar()
764 // for this variable but mappes it in a PDO.
765 pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
766 pVarEntry_p->m_Size = ObdSize_p;
771 //---------------------------------------------------------------------------
773 // Function: EplObdGetDataSize()
775 // Description: function to initialize VarEntry dependened on object type
777 // gets the data size of an object
778 // for string objects it returnes the string length
780 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
782 // uiSubIndex_p= Subindex
784 // Return: tEplObdSize
788 //---------------------------------------------------------------------------
789 tEplObdSize EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
790 unsigned int uiSubIndex_p)
794 tEplObdEntryPtr pObdEntry;
795 tEplObdSubEntryPtr pObdSubEntry;
797 // get pointer to index structure
798 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
799 uiIndex_p, &pObdEntry);
800 if (Ret != kEplSuccessful) {
804 // get pointer to subindex structure
805 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
806 if (Ret != kEplSuccessful) {
811 ObdSize = EplObdGetDataSizeIntern(pObdSubEntry);
816 //---------------------------------------------------------------------------
818 // Function: EplObdGetNodeId()
820 // Description: function returns nodeid from entry 0x1F93
823 // Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
825 // Return: unsigned int = Node Id
829 //---------------------------------------------------------------------------
830 unsigned int EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
837 ObdSize = sizeof(bNodeId);
838 Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
839 EPL_OBD_NODE_ID_INDEX,
840 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, &ObdSize);
841 if (Ret != kEplSuccessful) {
842 bNodeId = EPL_C_ADR_INVALID;
847 return (unsigned int)bNodeId;
851 //---------------------------------------------------------------------------
853 // Function: EplObdSetNodeId()
855 // Description: function sets nodeid in entry 0x1F93
858 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
859 // uiNodeId_p = Node Id to set
860 // NodeIdType_p= Type on which way the Node Id was set
862 // Return: tEplKernel = Errorcode
866 //---------------------------------------------------------------------------
867 tEplKernel EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ unsigned int uiNodeId_p,
868 tEplObdNodeIdType NodeIdType_p)
876 if (uiNodeId_p == EPL_C_ADR_INVALID) {
877 Ret = kEplInvalidNodeId;
880 bNodeId = (u8) uiNodeId_p;
881 ObdSize = sizeof(u8);
882 // write NodeId to OD entry
883 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
884 EPL_OBD_NODE_ID_INDEX,
885 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, ObdSize);
886 if (Ret != kEplSuccessful) {
889 // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
890 switch (NodeIdType_p) {
892 case kEplObdNodeIdUnknown:
898 case kEplObdNodeIdSoftware:
904 case kEplObdNodeIdHardware:
915 } // end of switch (NodeIdType_p)
918 ObdSize = sizeof(fHwBool);
919 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
920 EPL_OBD_NODE_ID_INDEX,
921 EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
923 if (Ret != kEplSuccessful) {
931 //---------------------------------------------------------------------------
933 // Function: EplObdIsNumerical()
935 // Description: function checks if a entry is numerical or not
938 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
940 // uiSubIndex_p = Subindex
941 // pfEntryNumerical_p = pointer to BOOL for returnvalue
942 // -> TRUE if entry a numerical value
943 // -> FALSE if entry not a numerical value
945 // Return: tEplKernel = Errorcode
949 //---------------------------------------------------------------------------
950 tEplKernel EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
951 unsigned int uiSubIndex_p,
952 BOOL *pfEntryNumerical_p)
955 tEplObdEntryPtr pObdEntry;
956 tEplObdSubEntryPtr pObdSubEntry;
958 // get pointer to index structure
959 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
960 uiIndex_p, &pObdEntry);
961 if (Ret != kEplSuccessful) {
964 // get pointer to subindex structure
965 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
966 if (Ret != kEplSuccessful) {
970 Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
977 //---------------------------------------------------------------------------
979 // Function: EplObdReadEntryToLe()
981 // Description: The function reads an object entry from the byteoder
982 // of the system to the little endian byteorder for numerical values.
983 // For other types a normal read will be processed. This is usefull for
984 // the PDO and SDO module. The application
985 // can always read the data even if attrib kEplObdAccRead
986 // is not set. The attrib is only checked up for SDO transfer.
988 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
989 // uiIndex_p = Index of the OD entry to read
990 // uiSubIndex_p = Subindex to read
991 // pDstData_p = pointer to the buffer for data
992 // Offset_p = offset in data for read access
993 // pSize_p = IN: Size of the buffer
994 // OUT: number of readed Bytes
996 // Return: tEplKernel
1000 //---------------------------------------------------------------------------
1001 tEplKernel EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1002 unsigned int uiSubIndex_p,
1003 void *pDstData_p, tEplObdSize *pSize_p)
1006 tEplObdEntryPtr pObdEntry;
1007 tEplObdSubEntryPtr pSubEntry;
1008 tEplObdCbParam CbParam;
1010 tEplObdSize ObdSize;
1012 // check for all API function if instance is valid
1013 EPL_MCO_CHECK_INSTANCE_STATE();
1015 ASSERT(pDstData_p != NULL);
1016 ASSERT(pSize_p != NULL);
1018 // get address of index and subindex entry
1019 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1020 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1021 if (Ret != kEplSuccessful) {
1024 // get pointer to object data
1025 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
1027 // check source pointer
1028 if (pSrcData == NULL) {
1029 Ret = kEplObdReadViolation;
1032 //------------------------------------------------------------------------
1033 // address of source data to structure of callback parameters
1034 // so callback function can change this data before reading
1035 CbParam.m_uiIndex = uiIndex_p;
1036 CbParam.m_uiSubIndex = uiSubIndex_p;
1037 CbParam.m_pArg = pSrcData;
1038 CbParam.m_ObdEvent = kEplObdEvPreRead;
1039 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1040 pObdEntry->m_fpCallback, &CbParam);
1041 if (Ret != kEplSuccessful) {
1044 // get size of data and check if application has reserved enough memory
1045 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
1046 // check if offset given and calc correct number of bytes to read
1047 if (*pSize_p < ObdSize) {
1048 Ret = kEplObdValueLengthError;
1051 // check if numerical type
1052 switch (pSubEntry->m_Type) {
1053 //-----------------------------------------------
1054 // types without ami
1055 case kEplObdTypVString:
1056 case kEplObdTypOString:
1057 case kEplObdTypDomain:
1060 // read value from object
1061 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
1065 //-----------------------------------------------
1066 // numerical type which needs ami-write
1067 // 8 bit or smaller values
1068 case kEplObdTypBool:
1069 case kEplObdTypInt8:
1070 case kEplObdTypUInt8:
1072 AmiSetByteToLe(pDstData_p, *((u8 *) pSrcData));
1077 case kEplObdTypInt16:
1078 case kEplObdTypUInt16:
1080 AmiSetWordToLe(pDstData_p, *((u16 *) pSrcData));
1085 case kEplObdTypInt24:
1086 case kEplObdTypUInt24:
1088 AmiSetDword24ToLe(pDstData_p, *((u32 *) pSrcData));
1093 case kEplObdTypInt32:
1094 case kEplObdTypUInt32:
1095 case kEplObdTypReal32:
1097 AmiSetDwordToLe(pDstData_p, *((u32 *) pSrcData));
1102 case kEplObdTypInt40:
1103 case kEplObdTypUInt40:
1105 AmiSetQword40ToLe(pDstData_p, *((u64 *) pSrcData));
1110 case kEplObdTypInt48:
1111 case kEplObdTypUInt48:
1113 AmiSetQword48ToLe(pDstData_p, *((u64 *) pSrcData));
1118 case kEplObdTypInt56:
1119 case kEplObdTypUInt56:
1121 AmiSetQword56ToLe(pDstData_p, *((u64 *) pSrcData));
1126 case kEplObdTypInt64:
1127 case kEplObdTypUInt64:
1128 case kEplObdTypReal64:
1130 AmiSetQword64ToLe(pDstData_p, *((u64 *) pSrcData));
1135 case kEplObdTypTimeOfDay:
1136 case kEplObdTypTimeDiff:
1138 AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay *) pSrcData));
1142 } // end of switch(pSubEntry->m_Type)
1146 // write address of destination data to structure of callback parameters
1147 // so callback function can change this data after reading
1148 CbParam.m_pArg = pDstData_p;
1149 CbParam.m_ObdEvent = kEplObdEvPostRead;
1150 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1151 pObdEntry->m_fpCallback, &CbParam);
1159 //---------------------------------------------------------------------------
1161 // Function: EplObdWriteEntryFromLe()
1163 // Description: Function writes data to an OBD entry from a source with
1164 // little endian byteorder to the od with system specuific
1165 // byteorder. Not numerical values will only by copied. Strings
1166 // are stored with added '\0' character.
1168 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1169 // uiIndex_p = Index of the OD entry
1170 // uiSubIndex_p = Subindex of the OD Entry
1171 // pSrcData_p = Pointer to the data to write
1172 // Size_p = Size of the data in Byte
1174 // Return: tEplKernel = Errorcode
1179 //---------------------------------------------------------------------------
1180 tEplKernel EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1181 unsigned int uiSubIndex_p,
1182 void *pSrcData_p, tEplObdSize Size_p)
1185 tEplObdEntryPtr pObdEntry;
1186 tEplObdSubEntryPtr pSubEntry;
1187 tEplObdCbParam CbParam;
1189 tEplObdSize ObdSize;
1191 void *pBuffer = &qwBuffer;
1193 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
1199 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
1200 if (Ret != kEplSuccessful) {
1204 // check if numerical type
1205 switch (pSubEntry->m_Type) {
1206 //-----------------------------------------------
1207 // types without ami
1209 { // do nothing, i.e. use the given source pointer
1210 pBuffer = pSrcData_p;
1214 //-----------------------------------------------
1215 // numerical type which needs ami-write
1216 // 8 bit or smaller values
1217 case kEplObdTypBool:
1218 case kEplObdTypInt8:
1219 case kEplObdTypUInt8:
1221 *((u8 *) pBuffer) = AmiGetByteFromLe(pSrcData_p);
1226 case kEplObdTypInt16:
1227 case kEplObdTypUInt16:
1229 *((u16 *) pBuffer) = AmiGetWordFromLe(pSrcData_p);
1234 case kEplObdTypInt24:
1235 case kEplObdTypUInt24:
1237 *((u32 *) pBuffer) = AmiGetDword24FromLe(pSrcData_p);
1242 case kEplObdTypInt32:
1243 case kEplObdTypUInt32:
1244 case kEplObdTypReal32:
1246 *((u32 *) pBuffer) = AmiGetDwordFromLe(pSrcData_p);
1251 case kEplObdTypInt40:
1252 case kEplObdTypUInt40:
1254 *((u64 *) pBuffer) = AmiGetQword40FromLe(pSrcData_p);
1259 case kEplObdTypInt48:
1260 case kEplObdTypUInt48:
1262 *((u64 *) pBuffer) = AmiGetQword48FromLe(pSrcData_p);
1267 case kEplObdTypInt56:
1268 case kEplObdTypUInt56:
1270 *((u64 *) pBuffer) = AmiGetQword56FromLe(pSrcData_p);
1275 case kEplObdTypInt64:
1276 case kEplObdTypUInt64:
1277 case kEplObdTypReal64:
1279 *((u64 *) pBuffer) = AmiGetQword64FromLe(pSrcData_p);
1284 case kEplObdTypTimeOfDay:
1285 case kEplObdTypTimeDiff:
1287 AmiGetTimeOfDay(pBuffer, ((tTimeOfDay *) pSrcData_p));
1291 } // end of switch(pSubEntry->m_Type)
1293 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
1296 &CbParam, pBuffer, pDstData, ObdSize);
1297 if (Ret != kEplSuccessful) {
1307 //---------------------------------------------------------------------------
1309 // Function: EplObdGetAccessType()
1311 // Description: Function returns accesstype of the entry
1313 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1314 // uiIndex_p = Index of the OD entry
1315 // uiSubIndex_p = Subindex of the OD Entry
1316 // pAccessTyp_p = pointer to buffer to store accesstype
1318 // Return: tEplKernel = errorcode
1323 //---------------------------------------------------------------------------
1324 tEplKernel EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1325 unsigned int uiSubIndex_p,
1326 tEplObdAccess *pAccessTyp_p)
1329 tEplObdEntryPtr pObdEntry;
1330 tEplObdSubEntryPtr pObdSubEntry;
1332 // get pointer to index structure
1333 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
1334 uiIndex_p, &pObdEntry);
1335 if (Ret != kEplSuccessful) {
1338 // get pointer to subindex structure
1339 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
1340 if (Ret != kEplSuccessful) {
1344 *pAccessTyp_p = pObdSubEntry->m_Access;
1350 //---------------------------------------------------------------------------
1352 // Function: EplObdSearchVarEntry()
1354 // Description: gets variable from OD
1356 // Parameters: uiIndex_p = index of the var entry to search
1357 // uiSubindex_p = subindex of var entry to search
1358 // ppVarEntry_p = pointer to the pointer to the varentry
1360 // Return: tEplKernel
1364 //---------------------------------------------------------------------------
1366 tEplKernel EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1367 unsigned int uiSubindex_p,
1368 tEplObdVarEntry **ppVarEntry_p)
1372 tEplObdSubEntryPtr pSubindexEntry;
1374 // check for all API function if instance is valid
1375 EPL_MCO_CHECK_INSTANCE_STATE();
1377 // get address of subindex entry
1378 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1379 uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
1380 if (Ret == kEplSuccessful) {
1382 Ret = EplObdGetVarEntry(pSubindexEntry, ppVarEntry_p);
1389 //=========================================================================//
1391 // P R I V A T E D E F I N I T I O N S //
1393 //=========================================================================//
1395 EPL_MCO_DECL_INSTANCE_FCT()
1396 //---------------------------------------------------------------------------
1398 // Function: EplObdCallObjectCallback()
1400 // Description: calls callback function of an object or of a variable
1402 // Parameters: fpCallback_p
1405 // Return: tEplKernel
1409 //---------------------------------------------------------------------------
1410 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
1411 tEplObdCallback fpCallback_p,
1412 tEplObdCbParam *pCbParam_p)
1416 tEplObdCallback fpCallback;
1418 // check for all API function if instance is valid
1419 EPL_MCO_CHECK_INSTANCE_STATE();
1421 ASSERT(pCbParam_p != NULL);
1423 Ret = kEplSuccessful;
1425 // check address of callback function before calling it
1426 if (fpCallback_p != NULL) {
1427 // KEIL C51 V6.01 has a bug.
1428 // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
1429 fpCallback = fpCallback_p;
1431 // call callback function for this object
1432 Ret = fpCallback(EPL_MCO_INSTANCE_PARAM_IDX_()
1439 //---------------------------------------------------------------------------
1441 // Function: EplObdGetDataSizeIntern()
1443 // Description: gets the data size of an object
1444 // for string objects it returnes the string length
1446 // Parameters: pSubIndexEntry_p
1448 // Return: tEplObdSize
1452 //---------------------------------------------------------------------------
1454 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p)
1457 tEplObdSize DataSize;
1460 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
1461 // then the current pointer is always NULL. The function
1462 // returns the length of default string.
1463 DataSize = EplObdGetObjectSize(pSubIndexEntry_p);
1465 if (pSubIndexEntry_p->m_Type == kEplObdTypVString) {
1466 // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
1467 pData = ((void *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p));
1468 if (pData != NULL) {
1470 EplObdGetStrLen((void *)pData, DataSize,
1471 pSubIndexEntry_p->m_Type);
1480 //---------------------------------------------------------------------------
1482 // Function: EplObdGetStrLen()
1484 // Description: The function calculates the length of string. The '\0'
1485 // character is included!!
1487 // Parameters: pObjData_p = pointer to string
1488 // ObjLen_p = max. length of objectr entry
1489 // bObjType_p = object type (VSTRING, ...)
1491 // Returns: string length + 1
1495 //---------------------------------------------------------------------------
1497 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
1498 tEplObdSize ObjLen_p, tEplObdType ObjType_p)
1501 tEplObdSize StrLen = 0;
1504 if (pObjData_p == NULL) {
1507 //----------------------------------------
1508 // Visible String: data format byte
1509 if (ObjType_p == kEplObdTypVString) {
1510 pbString = pObjData_p;
1512 for (StrLen = 0; StrLen < ObjLen_p; StrLen++) {
1513 if (*pbString == '\0') {
1521 //----------------------------------------
1522 // other string types ...
1529 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1531 //---------------------------------------------------------------------------
1533 // Function: EplObdCheckObjectRange()
1535 // Description: function to check value range of object data
1537 // NOTICE: The pointer of data (pData_p) must point out to an even address,
1538 // if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
1539 // always realiced because pointer m_pDefault points always to an
1540 // array of the SPECIFIED type.
1542 // Parameters: pSubindexEntry_p
1545 // Return: tEplKernel
1549 //---------------------------------------------------------------------------
1551 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
1558 ASSERTMSG(pSubindexEntry_p != NULL,
1559 "EplObdCheckObjectRange(): no address to subindex struct!\n");
1561 Ret = kEplSuccessful;
1563 // check if data range has to be checked
1564 if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) {
1567 // get address of default data
1568 pRangeData = pSubindexEntry_p->m_pDefault;
1570 // jump to called object type
1571 switch ((tEplObdType) pSubindexEntry_p->m_Type) {
1572 // -----------------------------------------------------------------
1573 // ObdType kEplObdTypBool will not be checked because there are only
1574 // two possible values 0 or 1.
1576 // -----------------------------------------------------------------
1577 // ObdTypes which has to be check up because numerical values
1578 case kEplObdTypInt8:
1580 // switch to lower limit
1581 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1583 // check if value is to low
1584 if (*((tEplObdInteger8 *) pData_p) <
1585 *((tEplObdInteger8 *) pRangeData)) {
1586 Ret = kEplObdValueTooLow;
1589 // switch to higher limit
1590 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1592 // check if value is to high
1593 if (*((tEplObdInteger8 *) pData_p) >
1594 *((tEplObdInteger8 *) pRangeData)) {
1595 Ret = kEplObdValueTooHigh;
1600 case kEplObdTypUInt8:
1602 // switch to lower limit
1603 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1605 // check if value is to low
1606 if (*((tEplObdUnsigned8 *) pData_p) <
1607 *((tEplObdUnsigned8 *) pRangeData)) {
1608 Ret = kEplObdValueTooLow;
1611 // switch to higher limit
1612 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1614 // check if value is to high
1615 if (*((tEplObdUnsigned8 *) pData_p) >
1616 *((tEplObdUnsigned8 *) pRangeData)) {
1617 Ret = kEplObdValueTooHigh;
1622 case kEplObdTypInt16:
1624 // switch to lower limit
1625 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1627 // check if value is to low
1628 if (*((tEplObdInteger16 *) pData_p) <
1629 *((tEplObdInteger16 *) pRangeData)) {
1630 Ret = kEplObdValueTooLow;
1633 // switch to higher limit
1634 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1636 // check if value is to high
1637 if (*((tEplObdInteger16 *) pData_p) >
1638 *((tEplObdInteger16 *) pRangeData)) {
1639 Ret = kEplObdValueTooHigh;
1644 case kEplObdTypUInt16:
1646 // switch to lower limit
1647 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1649 // check if value is to low
1650 if (*((tEplObdUnsigned16 *) pData_p) <
1651 *((tEplObdUnsigned16 *) pRangeData)) {
1652 Ret = kEplObdValueTooLow;
1655 // switch to higher limit
1656 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1658 // check if value is to high
1659 if (*((tEplObdUnsigned16 *) pData_p) >
1660 *((tEplObdUnsigned16 *) pRangeData)) {
1661 Ret = kEplObdValueTooHigh;
1666 case kEplObdTypInt32:
1668 // switch to lower limit
1669 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1671 // check if value is to low
1672 if (*((tEplObdInteger32 *) pData_p) <
1673 *((tEplObdInteger32 *) pRangeData)) {
1674 Ret = kEplObdValueTooLow;
1677 // switch to higher limit
1678 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1680 // check if value is to high
1681 if (*((tEplObdInteger32 *) pData_p) >
1682 *((tEplObdInteger32 *) pRangeData)) {
1683 Ret = kEplObdValueTooHigh;
1688 case kEplObdTypUInt32:
1690 // switch to lower limit
1691 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1693 // check if value is to low
1694 if (*((tEplObdUnsigned32 *) pData_p) <
1695 *((tEplObdUnsigned32 *) pRangeData)) {
1696 Ret = kEplObdValueTooLow;
1699 // switch to higher limit
1700 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1702 // check if value is to high
1703 if (*((tEplObdUnsigned32 *) pData_p) >
1704 *((tEplObdUnsigned32 *) pRangeData)) {
1705 Ret = kEplObdValueTooHigh;
1710 case kEplObdTypReal32:
1712 // switch to lower limit
1713 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1715 // check if value is to low
1716 if (*((tEplObdReal32 *) pData_p) <
1717 *((tEplObdReal32 *) pRangeData)) {
1718 Ret = kEplObdValueTooLow;
1721 // switch to higher limit
1722 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1724 // check if value is to high
1725 if (*((tEplObdReal32 *) pData_p) >
1726 *((tEplObdReal32 *) pRangeData)) {
1727 Ret = kEplObdValueTooHigh;
1732 // -----------------------------------------------------------------
1733 case kEplObdTypInt40:
1734 case kEplObdTypInt48:
1735 case kEplObdTypInt56:
1736 case kEplObdTypInt64:
1738 // switch to lower limit
1739 pRangeData = ((signed u64 *)pRangeData) + 1;
1741 // check if value is to low
1742 if (*((signed u64 *)pData_p) < *((signed u64 *)pRangeData)) {
1743 Ret = kEplObdValueTooLow;
1746 // switch to higher limit
1747 pRangeData = ((signed u64 *)pRangeData) + 1;
1749 // check if value is to high
1750 if (*((signed u64 *)pData_p) > *((signed u64 *)pRangeData)) {
1751 Ret = kEplObdValueTooHigh;
1756 // -----------------------------------------------------------------
1757 case kEplObdTypUInt40:
1758 case kEplObdTypUInt48:
1759 case kEplObdTypUInt56:
1760 case kEplObdTypUInt64:
1762 // switch to lower limit
1763 pRangeData = ((unsigned u64 *)pRangeData) + 1;
1765 // check if value is to low
1766 if (*((unsigned u64 *)pData_p) <
1767 *((unsigned u64 *)pRangeData)) {
1768 Ret = kEplObdValueTooLow;
1771 // switch to higher limit
1772 pRangeData = ((unsigned u64 *)pRangeData) + 1;
1774 // check if value is to high
1775 if (*((unsigned u64 *)pData_p) >
1776 *((unsigned u64 *)pRangeData)) {
1777 Ret = kEplObdValueTooHigh;
1782 // -----------------------------------------------------------------
1783 case kEplObdTypReal64:
1785 // switch to lower limit
1786 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1788 // check if value is to low
1789 if (*((tEplObdReal64 *) pData_p) <
1790 *((tEplObdReal64 *) pRangeData)) {
1791 Ret = kEplObdValueTooLow;
1794 // switch to higher limit
1795 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1797 // check if value is to high
1798 if (*((tEplObdReal64 *) pData_p) >
1799 *((tEplObdReal64 *) pRangeData)) {
1800 Ret = kEplObdValueTooHigh;
1805 // -----------------------------------------------------------------
1806 case kEplObdTypTimeOfDay:
1807 case kEplObdTypTimeDiff:
1810 // -----------------------------------------------------------------
1811 // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
1812 // they have no numerical value.
1815 Ret = kEplObdUnknownObjectType;
1824 #endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1826 //---------------------------------------------------------------------------
1828 // Function: EplObdWriteEntryPre()
1830 // Description: Function prepares write of data to an OBD entry. Strings
1831 // are stored with added '\0' character.
1833 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1834 // uiIndex_p = Index of the OD entry
1835 // uiSubIndex_p = Subindex of the OD Entry
1836 // pSrcData_p = Pointer to the data to write
1837 // Size_p = Size of the data in Byte
1839 // Return: tEplKernel = Errorcode
1844 //---------------------------------------------------------------------------
1846 static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1847 unsigned int uiSubIndex_p,
1851 tEplObdEntryPtr *ppObdEntry_p,
1852 tEplObdSubEntryPtr *ppSubEntry_p,
1853 tEplObdCbParam *pCbParam_p,
1854 tEplObdSize *pObdSize_p)
1858 tEplObdEntryPtr pObdEntry;
1859 tEplObdSubEntryPtr pSubEntry;
1860 tEplObdAccess Access;
1862 tEplObdSize ObdSize;
1863 BOOL fEntryNumerical;
1865 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1866 tEplObdVStringDomain MemVStringDomain;
1870 // check for all API function if instance is valid
1871 EPL_MCO_CHECK_INSTANCE_STATE();
1873 ASSERT(pSrcData_p != NULL); // should never be NULL
1875 //------------------------------------------------------------------------
1876 // get address of index and subindex entry
1877 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1878 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1879 if (Ret != kEplSuccessful) {
1882 // get pointer to object data
1883 pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1885 Access = (tEplObdAccess) pSubEntry->m_Access;
1887 // check access for write
1888 // access violation if adress to current value is NULL
1889 if (((Access & kEplObdAccConst) != 0) || (pDstData == NULL)) {
1890 Ret = kEplObdAccessViolation;
1893 //------------------------------------------------------------------------
1894 // get size of object
1895 // -as ObdSize = ObdGetObjectSize (pSubEntry);
1897 //------------------------------------------------------------------------
1898 // To use the same callback function for ObdWriteEntry as well as for
1899 // an SDO download call at first (kEplObdEvPre...) the callback function
1900 // with the argument pointer to object size.
1901 pCbParam_p->m_uiIndex = uiIndex_p;
1902 pCbParam_p->m_uiSubIndex = uiSubIndex_p;
1904 // Because object size and object pointer are
1905 // adapted by user callback function, re-read
1907 ObdSize = EplObdGetObjectSize(pSubEntry);
1908 pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1910 // 09-dec-2004 r.d.:
1911 // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
1912 // for String or Domain which lets called module directly change
1913 // the data pointer or size. This prevents a recursive call to
1914 // the callback function if it calls EplObdGetEntry().
1915 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1916 if ((pSubEntry->m_Type == kEplObdTypVString) ||
1917 (pSubEntry->m_Type == kEplObdTypDomain) ||
1918 (pSubEntry->m_Type == kEplObdTypOString)) {
1919 if (pSubEntry->m_Type == kEplObdTypVString) {
1920 // reserve one byte for 0-termination
1921 // -as ObdSize -= 1;
1924 // fill out new arg-struct
1925 MemVStringDomain.m_DownloadSize = Size_p;
1926 MemVStringDomain.m_ObjSize = ObdSize;
1927 MemVStringDomain.m_pData = pDstData;
1929 pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
1930 pCbParam_p->m_pArg = &MemVStringDomain;
1931 // call user callback
1932 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1933 pObdEntry->m_fpCallback,
1935 if (Ret != kEplSuccessful) {
1938 // write back new settings
1939 pCurrData = pSubEntry->m_pCurrent;
1940 if ((pSubEntry->m_Type == kEplObdTypVString)
1941 || (pSubEntry->m_Type == kEplObdTypOString)) {
1942 ((tEplObdVString *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1943 ((tEplObdVString *)pCurrData)->m_pString = MemVStringDomain.m_pData;
1944 } else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
1946 ((tEplObdVarEntry *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1947 ((tEplObdVarEntry *)pCurrData)->m_pData = (void *)MemVStringDomain.m_pData;
1950 // Because object size and object pointer are
1951 // adapted by user callback function, re-read
1953 ObdSize = MemVStringDomain.m_ObjSize;
1954 pDstData = (void *)MemVStringDomain.m_pData;
1956 #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1958 // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
1959 // -as 16.11.04 CbParam.m_pArg = &ObdSize;
1960 // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p;
1961 pCbParam_p->m_pArg = &ObdSize;
1962 pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
1963 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1964 pObdEntry->m_fpCallback, pCbParam_p);
1965 if (Ret != kEplSuccessful) {
1969 if (Size_p > ObdSize) {
1970 Ret = kEplObdValueLengthError;
1974 if (pSubEntry->m_Type == kEplObdTypVString) {
1975 if (((char *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character
1977 // reserve one byte in destination for 0-termination
1979 } else if (Size_p >= ObdSize) { // source string is not 0-terminated
1980 // and destination buffer is too short
1981 Ret = kEplObdValueLengthError;
1986 Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
1987 if (Ret != kEplSuccessful) {
1991 if ((fEntryNumerical != FALSE)
1992 && (Size_p != ObdSize)) {
1993 // type is numerical, therefor size has to fit, but it does not.
1994 Ret = kEplObdValueLengthError;
1997 // use given size, because non-numerical objects can be written with shorter values
2000 // set output parameters
2001 *pObdSize_p = ObdSize;
2002 *ppObdEntry_p = pObdEntry;
2003 *ppSubEntry_p = pSubEntry;
2004 *ppDstData_p = pDstData;
2006 // all checks are done
2007 // the caller may now convert the numerial source value to platform byte order in a temporary buffer
2015 //---------------------------------------------------------------------------
2017 // Function: EplObdWriteEntryPost()
2019 // Description: Function finishes write of data to an OBD entry. Strings
2020 // are stored with added '\0' character.
2022 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
2023 // uiIndex_p = Index of the OD entry
2024 // uiSubIndex_p = Subindex of the OD Entry
2025 // pSrcData_p = Pointer to the data to write
2026 // Size_p = Size of the data in Byte
2028 // Return: tEplKernel = Errorcode
2033 //---------------------------------------------------------------------------
2035 static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p,
2036 tEplObdSubEntryPtr pSubEntry_p,
2037 tEplObdCbParam *pCbParam_p,
2040 tEplObdSize ObdSize_p)
2045 // caller converted the source value to platform byte order
2046 // now the range of the value may be checked
2048 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2051 Ret = EplObdCheckObjectRange(pSubEntry_p, pSrcData_p);
2052 if (Ret != kEplSuccessful) {
2058 // now call user callback function to check value
2059 // write address of source data to structure of callback parameters
2060 // so callback function can check this data
2061 pCbParam_p->m_pArg = pSrcData_p;
2062 pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
2063 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2064 pObdEntry_p->m_fpCallback, pCbParam_p);
2065 if (Ret != kEplSuccessful) {
2068 // copy object data to OBD
2069 EPL_MEMCPY(pDstData_p, pSrcData_p, ObdSize_p);
2071 // terminate string with 0
2072 if (pSubEntry_p->m_Type == kEplObdTypVString) {
2073 ((char *)pDstData_p)[ObdSize_p] = '\0';
2075 // write address of destination to structure of callback parameters
2076 // so callback function can change data subsequently
2077 pCbParam_p->m_pArg = pDstData_p;
2078 pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
2079 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2080 pObdEntry_p->m_fpCallback, pCbParam_p);
2088 //---------------------------------------------------------------------------
2090 // Function: EplObdGetObjectSize()
2092 // Description: function to get size of object
2093 // The function determines if an object type an fixed data type (u8, u16, ...)
2094 // or non fixed object (string, domain). This information is used to decide
2095 // if download data are stored temporary or not. For objects with fixed data length
2096 // and types a value range checking can process.
2097 // For strings the function returns the whole object size not the
2098 // length of string.
2100 // Parameters: pSubIndexEntry_p
2102 // Return: tEplObdSize
2106 //---------------------------------------------------------------------------
2108 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p)
2111 tEplObdSize DataSize = 0;
2114 switch (pSubIndexEntry_p->m_Type) {
2115 // -----------------------------------------------------------------
2116 case kEplObdTypBool:
2121 // -----------------------------------------------------------------
2122 // ObdTypes which has to be check because numerical values
2123 case kEplObdTypInt8:
2124 DataSize = sizeof(tEplObdInteger8);
2127 // -----------------------------------------------------------------
2128 case kEplObdTypUInt8:
2129 DataSize = sizeof(tEplObdUnsigned8);
2132 // -----------------------------------------------------------------
2133 case kEplObdTypInt16:
2134 DataSize = sizeof(tEplObdInteger16);
2137 // -----------------------------------------------------------------
2138 case kEplObdTypUInt16:
2139 DataSize = sizeof(tEplObdUnsigned16);
2142 // -----------------------------------------------------------------
2143 case kEplObdTypInt32:
2144 DataSize = sizeof(tEplObdInteger32);
2147 // -----------------------------------------------------------------
2148 case kEplObdTypUInt32:
2149 DataSize = sizeof(tEplObdUnsigned32);
2152 // -----------------------------------------------------------------
2153 case kEplObdTypReal32:
2154 DataSize = sizeof(tEplObdReal32);
2157 // -----------------------------------------------------------------
2158 // ObdTypes which has to be not checked because not NUM values
2159 case kEplObdTypDomain:
2161 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2162 if ((void *)pData != (void *)NULL) {
2163 DataSize = ((tEplObdVarEntry *) pData)->m_Size;
2167 // -----------------------------------------------------------------
2168 case kEplObdTypVString:
2169 //case kEplObdTypUString:
2171 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
2172 // then the current pointer is always NULL. The function
2173 // returns the length of default string.
2174 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2175 if ((void *)pData != (void *)NULL) {
2176 // The max. size of strings defined by STRING-Macro is stored in
2177 // tEplObdVString of current value.
2178 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2179 DataSize = ((tEplObdVString *) pData)->m_Size;
2181 // The current position is not decleared. The string
2182 // is located in ROM, therefor use default pointer.
2183 pData = (void *)pSubIndexEntry_p->m_pDefault;
2184 if ((const void *)pData != (const void *)NULL) {
2185 // The max. size of strings defined by STRING-Macro is stored in
2186 // tEplObdVString of default value.
2187 DataSize = ((const tEplObdVString *)pData)->m_Size;
2193 // -----------------------------------------------------------------
2194 case kEplObdTypOString:
2196 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2197 if ((void *)pData != (void *)NULL) {
2198 // The max. size of strings defined by STRING-Macro is stored in
2199 // tEplObdVString of current value.
2200 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2201 DataSize = ((tEplObdOString *) pData)->m_Size;
2203 // The current position is not decleared. The string
2204 // is located in ROM, therefor use default pointer.
2205 pData = (void *)pSubIndexEntry_p->m_pDefault;
2206 if ((const void *)pData != (const void *)NULL) {
2207 // The max. size of strings defined by STRING-Macro is stored in
2208 // tEplObdVString of default value.
2209 DataSize = ((const tEplObdOString *)pData)->m_Size;
2214 // -----------------------------------------------------------------
2215 case kEplObdTypInt24:
2216 case kEplObdTypUInt24:
2221 // -----------------------------------------------------------------
2222 case kEplObdTypInt40:
2223 case kEplObdTypUInt40:
2228 // -----------------------------------------------------------------
2229 case kEplObdTypInt48:
2230 case kEplObdTypUInt48:
2235 // -----------------------------------------------------------------
2236 case kEplObdTypInt56:
2237 case kEplObdTypUInt56:
2242 // -----------------------------------------------------------------
2243 case kEplObdTypInt64:
2244 case kEplObdTypUInt64:
2245 case kEplObdTypReal64:
2250 // -----------------------------------------------------------------
2251 case kEplObdTypTimeOfDay:
2252 case kEplObdTypTimeDiff:
2257 // -----------------------------------------------------------------
2265 //---------------------------------------------------------------------------
2267 // Function: EplObdGetObjectDefaultPtr()
2269 // Description: function to get the default pointer (type specific)
2271 // Parameters: pSubIndexEntry_p = pointer to subindex structure
2273 // Returns: (void *) = pointer to default value
2277 //---------------------------------------------------------------------------
2279 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2285 ASSERTMSG(pSubIndexEntry_p != NULL,
2286 "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
2288 // get address to default data from default pointer
2289 pDefault = pSubIndexEntry_p->m_pDefault;
2290 if (pDefault != NULL) {
2291 // there are some special types, whose default pointer always is NULL or has to get from other structure
2292 // get type from subindex structure
2293 Type = pSubIndexEntry_p->m_Type;
2295 // check if object type is a string value
2296 if ((Type == kEplObdTypVString) /* ||
2297 (Type == kEplObdTypUString) */ ) {
2299 // EPL_OBD_SUBINDEX_RAM_VSTRING
2300 // tEplObdSize m_Size; --> size of default string
2301 // char * m_pDefString; --> pointer to default string
2302 // char * m_pString; --> pointer to string in RAM
2305 (void *)((tEplObdVString *) pDefault)->m_pString;
2306 } else if (Type == kEplObdTypOString) {
2308 (void *)((tEplObdOString *) pDefault)->m_pString;
2316 //---------------------------------------------------------------------------
2318 // Function: EplObdGetVarEntry()
2320 // Description: gets a variable entry of an object
2322 // Parameters: pSubindexEntry_p
2325 // Return: tCopKernel
2329 //---------------------------------------------------------------------------
2331 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
2332 tEplObdVarEntry **ppVarEntry_p)
2335 tEplKernel Ret = kEplObdVarEntryNotExist;
2337 ASSERT(ppVarEntry_p != NULL); // is not allowed to be NULL
2338 ASSERT(pSubindexEntry_p != NULL);
2340 // check VAR-Flag - only this object points to variables
2341 if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) {
2342 // check if object is an array
2343 if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) {
2344 *ppVarEntry_p = &((tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
2346 *ppVarEntry_p = (tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent;
2349 Ret = kEplSuccessful;
2356 //---------------------------------------------------------------------------
2358 // Function: EplObdGetEntry()
2360 // Description: gets a index entry from OD
2362 // Parameters: uiIndex_p = Index number
2363 // uiSubindex_p = Subindex number
2364 // ppObdEntry_p = pointer to the pointer to the entry
2365 // ppObdSubEntry_p = pointer to the pointer to the subentry
2367 // Return: tEplKernel
2372 //---------------------------------------------------------------------------
2374 static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
2375 unsigned int uiIndex_p,
2376 unsigned int uiSubindex_p,
2377 tEplObdEntryPtr * ppObdEntry_p,
2378 tEplObdSubEntryPtr * ppObdSubEntry_p)
2381 tEplObdEntryPtr pObdEntry;
2382 tEplObdCbParam CbParam;
2385 // check for all API function if instance is valid
2386 EPL_MCO_CHECK_INSTANCE_STATE();
2388 //------------------------------------------------------------------------
2389 // get address of entry of index
2391 EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam), uiIndex_p,
2393 if (Ret != kEplSuccessful) {
2396 //------------------------------------------------------------------------
2397 // get address of entry of subindex
2398 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubindex_p, ppObdSubEntry_p);
2399 if (Ret != kEplSuccessful) {
2402 //------------------------------------------------------------------------
2403 // call callback function to inform user/stack that an object will be searched
2404 // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
2405 CbParam.m_uiIndex = uiIndex_p;
2406 CbParam.m_uiSubIndex = uiSubindex_p;
2407 CbParam.m_pArg = NULL;
2408 CbParam.m_ObdEvent = kEplObdEvCheckExist;
2409 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2410 pObdEntry->m_fpCallback, &CbParam);
2411 if (Ret != kEplSuccessful) {
2412 Ret = kEplObdIndexNotExist;
2415 //------------------------------------------------------------------------
2416 // it is allowed to set ppObdEntry_p to NULL
2417 // if so, no address will be written to calling function
2418 if (ppObdEntry_p != NULL) {
2419 *ppObdEntry_p = pObdEntry;
2428 //---------------------------------------------------------------------------
2430 // Function: EplObdGetObjectCurrentPtr()
2432 // Description: function to get Current pointer (type specific)
2434 // Parameters: pSubIndexEntry_p
2440 //---------------------------------------------------------------------------
2442 static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2446 unsigned int uiArrayIndex;
2449 pData = pSubIndexEntry_p->m_pCurrent;
2451 // check if constant object
2452 if (pData != NULL) {
2453 // check if object is an array
2454 if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) {
2455 // calculate correct data pointer
2456 uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
2457 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2458 Size = sizeof(tEplObdVarEntry);
2460 Size = EplObdGetObjectSize(pSubIndexEntry_p);
2462 pData = ((u8 *) pData) + (Size * uiArrayIndex);
2464 // check if VarEntry
2465 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2466 // The data pointer is stored in VarEntry->pData
2467 pData = ((tEplObdVarEntry *) pData)->m_pData;
2469 // the default pointer is stored for strings in tEplObdVString
2470 else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* ||
2471 (pSubIndexEntry_p->m_Type == kEplObdTypUString) */
2473 pData = (void *)((tEplObdVString *)pData)->m_pString;
2474 } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) {
2476 (void *)((tEplObdOString *)pData)->m_pString;
2484 //---------------------------------------------------------------------------
2486 // Function: EplObdGetIndexIntern()
2488 // Description: gets a index entry from OD
2490 // Parameters: pInitParam_p
2494 // Return: tEplKernel
2498 //---------------------------------------------------------------------------
2500 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p,
2501 unsigned int uiIndex_p,
2502 tEplObdEntryPtr * ppObdEntry_p)
2505 tEplObdEntryPtr pObdEntry;
2507 unsigned int uiIndex;
2509 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2513 // if user OD is used then objekts also has to be searched in user OD
2514 // there is less code need if we do this in a loop
2519 ASSERTMSG(ppObdEntry_p != NULL,
2520 "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
2522 Ret = kEplObdIndexNotExist;
2524 // get start address of OD part
2525 // start address depends on object index because
2526 // object dictionary is divided in 3 parts
2527 if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) {
2528 pObdEntry = pInitParam_p->m_pPart;
2529 } else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) {
2530 pObdEntry = pInitParam_p->m_pManufacturerPart;
2532 // index range 0xA000 to 0xFFFF is reserved for DSP-405
2533 // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
2534 // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
2535 // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
2536 // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
2538 #if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
2539 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
2541 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
2544 pObdEntry = pInitParam_p->m_pDevicePart;
2547 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2549 // if index does not match in static OD then index only has to be searched in user OD
2551 // begin from first entry of user OD part
2552 pObdEntry = pInitParam_p->m_pUserPart;
2554 // no user OD is available
2555 if (pObdEntry == NULL) {
2558 // loop must only run once
2566 // no user OD is available
2567 // so other object can be found in OD
2569 Ret = kEplObdIllegalPart;
2576 // The end of Index table is marked with m_uiIndex = 0xFFFF.
2577 // If this function will be called with wIndex_p = 0xFFFF, entry
2578 // should not be found. Therefor it is important to use
2579 // while{} instead of do{}while !!!
2581 // get first index of index table
2582 uiIndex = pObdEntry->m_uiIndex;
2584 // search Index in OD part
2585 while (uiIndex != EPL_OBD_TABLE_INDEX_END) {
2586 // go to the end of this function if index is found
2587 if (uiIndex_p == uiIndex) {
2588 // write address of OD entry to calling function
2589 *ppObdEntry_p = pObdEntry;
2590 Ret = kEplSuccessful;
2593 // objects are sorted in OD
2594 // if the current index in OD is greater than the index which is to search then break loop
2595 // in this case user OD has to be search too
2596 if (uiIndex_p < uiIndex) {
2599 // next entry in index table
2602 // get next index of index table
2603 uiIndex = pObdEntry->m_uiIndex;
2606 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2608 // begin from first entry of user OD part
2609 pObdEntry = pInitParam_p->m_pUserPart;
2611 // no user OD is available
2612 if (pObdEntry == NULL) {
2615 // switch next loop for user OD
2624 // in this line Index was not found
2632 //---------------------------------------------------------------------------
2634 // Function: EplObdGetSubindexIntern()
2636 // Description: gets a subindex entry from a index entry
2638 // Parameters: pObdEntry_p
2642 // Return: tEplKernel
2646 //---------------------------------------------------------------------------
2648 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
2649 unsigned int uiSubIndex_p,
2650 tEplObdSubEntryPtr * ppObdSubEntry_p)
2653 tEplObdSubEntryPtr pSubEntry;
2654 unsigned int nSubIndexCount;
2657 ASSERTMSG(pObdEntry_p != NULL,
2658 "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
2659 ASSERTMSG(ppObdSubEntry_p != NULL,
2660 "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
2662 Ret = kEplObdSubindexNotExist;
2664 // get start address of subindex table and count of subindices
2665 pSubEntry = pObdEntry_p->m_pSubIndex;
2666 nSubIndexCount = pObdEntry_p->m_uiCount;
2667 ASSERTMSG((pSubEntry != NULL) && (nSubIndexCount > 0), "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
2669 // search subindex in subindex table
2670 while (nSubIndexCount > 0) {
2671 // check if array is found
2672 if ((pSubEntry->m_Access & kEplObdAccArray) != 0) {
2673 // check if subindex is in range
2674 if (uiSubIndex_p < pObdEntry_p->m_uiCount) {
2675 // update subindex number (subindex entry of an array is always in RAM !!!)
2676 pSubEntry->m_uiSubIndex = uiSubIndex_p;
2677 *ppObdSubEntry_p = pSubEntry;
2678 Ret = kEplSuccessful;
2682 // go to the end of this function if subindex is found
2683 else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) {
2684 *ppObdSubEntry_p = pSubEntry;
2685 Ret = kEplSuccessful;
2688 // objects are sorted in OD
2689 // if the current subindex in OD is greater than the subindex which is to search then break loop
2690 // in this case user OD has to be search too
2691 if (uiSubIndex_p < pSubEntry->m_uiSubIndex) {
2699 // in this line SubIndex was not fount
2707 //---------------------------------------------------------------------------
2709 // Function: EplObdSetStoreLoadObjCallback()
2711 // Description: function set address to callbackfunction for command Store and Load
2713 // Parameters: fpCallback_p
2715 // Return: tEplKernel
2719 //---------------------------------------------------------------------------
2720 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2721 tEplKernel EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdStoreLoadObjCallback fpCallback_p)
2724 EPL_MCO_CHECK_INSTANCE_STATE();
2726 // set new address of callback function
2727 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = fpCallback_p;
2729 return kEplSuccessful;
2732 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2734 //---------------------------------------------------------------------------
2736 // Function: EplObdAccessOdPartIntern()
2738 // Description: runs through OD and executes a job
2740 // Parameters: CurrentOdPart_p
2742 // Direction_p = what is to do (load values from flash or EEPROM, store, ...)
2744 // Return: tEplKernel
2748 //---------------------------------------------------------------------------
2750 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
2751 tEplObdPart CurrentOdPart_p,
2752 tEplObdEntryPtr pObdEnty_p,
2753 tEplObdDir Direction_p)
2756 tEplObdSubEntryPtr pSubIndex;
2757 unsigned int nSubIndexCount;
2758 tEplObdAccess Access;
2761 tEplObdSize ObjSize;
2763 tEplObdCbStoreParam CbStore;
2764 tEplObdVarEntry *pVarEntry;
2766 ASSERT(pObdEnty_p != NULL);
2768 Ret = kEplSuccessful;
2770 // prepare structure for STORE RESTORE callback function
2771 CbStore.m_bCurrentOdPart = (u8) CurrentOdPart_p;
2772 CbStore.m_pData = NULL;
2773 CbStore.m_ObjSize = 0;
2775 // command of first action depends on direction to access
2776 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2777 if (Direction_p == kEplObdDirLoad) {
2778 CbStore.m_bCommand = (u8) kEplObdCommOpenRead;
2780 // call callback function for previous command
2781 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2782 if (Ret != kEplSuccessful) {
2785 // set command for index and subindex loop
2786 CbStore.m_bCommand = (u8) kEplObdCommReadObj;
2787 } else if (Direction_p == kEplObdDirStore) {
2788 CbStore.m_bCommand = (u8) kEplObdCommOpenWrite;
2790 // call callback function for previous command
2791 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2792 if (Ret != kEplSuccessful) {
2795 // set command for index and subindex loop
2796 CbStore.m_bCommand = (u8) kEplObdCommWriteObj;
2798 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2800 // we should not restore the OD values here
2801 // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
2802 if (Direction_p != kEplObdDirRestore) {
2803 // walk through OD part till end is found
2804 while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) {
2805 // get address to subindex table and count of subindices
2806 pSubIndex = pObdEnty_p->m_pSubIndex;
2807 nSubIndexCount = pObdEnty_p->m_uiCount;
2808 ASSERT((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL
2810 // walk through subindex table till all subinices were restored
2811 while (nSubIndexCount != 0) {
2812 Access = (tEplObdAccess) pSubIndex->m_Access;
2814 // get pointer to current and default data
2815 pDefault = EplObdGetObjectDefaultPtr(pSubIndex);
2816 pDstData = EplObdGetObjectCurrentPtr(pSubIndex);
2818 // NOTE (for kEplObdTypVString):
2819 // The function returnes the max. number of bytes for a
2821 // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
2822 ObjSize = EplObdGetObjectSize(pSubIndex);
2824 // switch direction of OD access
2825 switch (Direction_p) {
2826 // --------------------------------------------------------------------------
2827 // VarEntry structures has to be initialized
2828 case kEplObdDirInit:
2830 // If VAR-Flag is set, m_pCurrent means not address of data
2831 // but address of tEplObdVarEntry. Address of data has to be get from
2833 if ((Access & kEplObdAccVar) != 0) {
2834 EplObdGetVarEntry(pSubIndex,
2836 EplObdInitVarEntry(pVarEntry,
2841 if ((Access & kEplObdAccArray) == 0)
2843 EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
2847 EplObdInitVarEntry ((tEplObdVarEntry *) (((u8 *) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
2848 pSubIndex->m_Type, ObjSize);
2851 // at this time no application variable is defined !!!
2852 // therefore data can not be copied.
2854 } else if (pSubIndex->m_Type ==
2855 kEplObdTypVString) {
2856 // If pointer m_pCurrent is not equal to NULL then the
2857 // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
2858 // pointer points to struct tEplObdVString located in MEM.
2859 // The element size includes the max. number of
2860 // bytes. The element m_pString includes the pointer
2861 // to string in MEM. The memory location of default string
2862 // must be copied to memory location of current string.
2865 pSubIndex->m_pCurrent;
2866 if (pDstData != NULL) {
2867 // 08-dec-2004: code optimization !!!
2868 // entries ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString
2869 // and ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_Size were read
2870 // twice. thats not necessary!
2872 // For copying data we have to set the destination pointer to the real RAM string. This
2873 // pointer to RAM string is located in default string info structure. (translated r.d.)
2874 pDstData = (void *)((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString;
2875 ObjSize = ((tEplObdVStringDef *)pSubIndex->m_pDefault)->m_Size;
2877 ((tEplObdVString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2878 ((tEplObdVString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2881 } else if (pSubIndex->m_Type ==
2882 kEplObdTypOString) {
2884 pSubIndex->m_pCurrent;
2885 if (pDstData != NULL) {
2886 // 08-dec-2004: code optimization !!!
2887 // entries ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_pString
2888 // and ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_Size were read
2889 // twice. thats not necessary!
2891 // For copying data we have to set the destination pointer to the real RAM string. This
2892 // pointer to RAM string is located in default string info structure. (translated r.d.)
2893 pDstData = (void *)((tEplObdOStringDef *) pSubIndex->m_pDefault)->m_pString;
2894 ObjSize = ((tEplObdOStringDef *)pSubIndex->m_pDefault)->m_Size;
2896 ((tEplObdOString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2897 ((tEplObdOString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2902 // no break !! because copy of data has to done too.
2904 // --------------------------------------------------------------------------
2905 // all objects has to be restored with default values
2906 case kEplObdDirRestore:
2908 // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
2909 // is replaced to function ObdCopyObjectData() with a new parameter.
2911 // restore object data for init phase
2912 EplObdCopyObjectData(pDstData, pDefault,
2917 // --------------------------------------------------------------------------
2918 // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
2919 case kEplObdDirLoad:
2921 // restore object data for init phase
2922 EplObdCopyObjectData(pDstData, pDefault,
2926 // no break !! because callback function has to be called too.
2928 // --------------------------------------------------------------------------
2929 // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
2930 case kEplObdDirStore:
2932 // when attribute kEplObdAccStore is set, then call callback function
2933 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2934 if ((Access & kEplObdAccStore) != 0) {
2935 // fill out data pointer and size of data
2936 CbStore.m_pData = pDstData;
2937 CbStore.m_ObjSize = ObjSize;
2939 // call callback function for read or write object
2941 ObdCallStoreCallback
2942 (EPL_MCO_INSTANCE_PTR_ &
2944 if (Ret != kEplSuccessful) {
2948 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2951 // --------------------------------------------------------------------------
2952 // if OD Builder key has to be checked no access to subindex and data should be made
2953 case kEplObdDirOBKCheck:
2955 // no break !! because we want to break the second loop too.
2957 // --------------------------------------------------------------------------
2958 // unknown Direction
2961 // so we can break the second loop earler
2968 // next subindex entry
2969 if ((Access & kEplObdAccArray) == 0) {
2971 if ((nSubIndexCount > 0)
2974 m_Access & kEplObdAccArray) !=
2976 // next subindex points to an array
2977 // reset subindex number
2978 pSubIndex->m_uiSubIndex = 1;
2981 if (nSubIndexCount > 0) {
2982 // next subindex points to an array
2983 // increment subindex number
2984 pSubIndex->m_uiSubIndex++;
2993 // -----------------------------------------------------------------------------------------
2994 // command of last action depends on direction to access
2995 if (Direction_p == kEplObdDirOBKCheck) {
2999 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3001 if (Direction_p == kEplObdDirLoad) {
3002 CbStore.m_bCommand = (u8) kEplObdCommCloseRead;
3003 } else if (Direction_p == kEplObdDirStore) {
3004 CbStore.m_bCommand = (u8) kEplObdCommCloseWrite;
3005 } else if (Direction_p == kEplObdDirRestore) {
3006 CbStore.m_bCommand = (u8) kEplObdCommClear;
3011 // call callback function for last command
3012 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
3014 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3024 // ----------------------------------------------------------------------------
3025 // Function: EplObdCopyObjectData()
3027 // Description: checks pointers to object data and copy them from source to destination
3029 // Parameters: pDstData_p = destination pointer
3030 // pSrcData_p = source pointer
3031 // ObjSize_p = size of object
3034 // Returns: tEplKernel = error code
3035 // ----------------------------------------------------------------------------
3037 static void EplObdCopyObjectData(void *pDstData_p,
3039 tEplObdSize ObjSize_p, tEplObdType ObjType_p)
3042 tEplObdSize StrSize = 0;
3044 // it is allowed to set default and current address to NULL (nothing to copy)
3045 if (pDstData_p != NULL) {
3047 if (ObjType_p == kEplObdTypVString) {
3048 // The function calculates the really number of characters of string. The
3049 // object entry size can be bigger as string size of default string.
3050 // The '\0'-termination is included. A string with no characters has a
3053 EplObdGetStrLen((void *)pSrcData_p, ObjSize_p,
3056 // If the string length is greater than or equal to the entry size in OD then only copy
3057 // entry size - 1 and always set the '\0'-termination.
3058 if (StrSize >= ObjSize_p) {
3059 StrSize = ObjSize_p - 1;
3063 if (pSrcData_p != NULL) {
3065 EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p);
3067 if (ObjType_p == kEplObdTypVString) {
3068 ((char *)pDstData_p)[StrSize] = '\0';
3075 //---------------------------------------------------------------------------
3077 // Function: EplObdIsNumericalIntern()
3079 // Description: function checks if a entry is numerical or not
3082 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
3083 // uiIndex_p = Index
3084 // uiSubIndex_p = Subindex
3085 // pfEntryNumerical_p = pointer to BOOL for returnvalue
3086 // -> TRUE if entry a numerical value
3087 // -> FALSE if entry not a numerical value
3089 // Return: tEplKernel = Errorcode
3093 //---------------------------------------------------------------------------
3094 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
3095 BOOL * pfEntryNumerical_p)
3097 tEplKernel Ret = kEplSuccessful;
3100 if ((pObdSubEntry_p->m_Type == kEplObdTypVString)
3101 || (pObdSubEntry_p->m_Type == kEplObdTypOString)
3102 || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) { // not numerical types
3103 *pfEntryNumerical_p = FALSE;
3104 } else { // numerical types
3105 *pfEntryNumerical_p = TRUE;
3112 // -------------------------------------------------------------------------
3113 // function to classify object type (fixed/non fixed)
3114 // -------------------------------------------------------------------------
3116 // ----------------------------------------------------------------------------
3117 // Function: EplObdCallStoreCallback()
3119 // Description: checks address to callback function and calles it when unequal
3122 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
3123 // pCbStoreParam_p = address to callback parameters
3125 // Returns: tEplKernel = error code
3126 // ----------------------------------------------------------------------------
3127 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3128 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
3129 tEplObdCbStoreParam *
3133 tEplKernel Ret = kEplSuccessful;
3135 ASSERT(pCbStoreParam_p != NULL);
3137 // check if function pointer is NULL - if so, no callback should be called
3138 if (EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) != NULL) {
3140 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback)
3141 (EPL_MCO_INSTANCE_PARAM_IDX_()
3148 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3149 //---------------------------------------------------------------------------
3151 // Function: EplObdGetObjectDataPtrIntern()
3153 // Description: Function gets the data pointer of an object.
3154 // It returnes the current data pointer. But if object is an
3155 // constant object it returnes the default pointer.
3157 // Parameters: pSubindexEntry_p = pointer to subindex entry
3159 // Return: void * = pointer to object data
3163 //---------------------------------------------------------------------------
3165 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p)
3169 tEplObdAccess Access;
3171 ASSERTMSG(pSubindexEntry_p != NULL,
3172 "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
3174 // there are are some objects whose data pointer has to get from other structure
3175 // get access type for this object
3176 Access = pSubindexEntry_p->m_Access;
3178 // If object has access type = const,
3179 // for data only exists default values.
3180 if ((Access & kEplObdAccConst) != 0) {
3181 // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
3182 pData = ((void *)EplObdGetObjectDefaultPtr(pSubindexEntry_p));
3184 // The pointer to current value can be received from ObdGetObjectCurrentPtr()
3185 pData = ((void *)EplObdGetObjectCurrentPtr(pSubindexEntry_p));
3191 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)