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)
98 //---------------------------------------------------------------------------
100 //---------------------------------------------------------------------------
102 // struct for instance table
105 EPL_MCO_DECL_INSTANCE_MEMBER ()
107 STATIC tEplObdInitParam INST_FAR m_ObdInitParam;
108 STATIC tEplObdStoreLoadObjCallback INST_NEAR m_fpStoreLoadObjCallback;
112 // decomposition of float
115 tEplObdReal32 m_flRealPart;
121 //---------------------------------------------------------------------------
122 // modul globale vars
123 //---------------------------------------------------------------------------
125 // This macro replace the unspecific pointer to an instance through
126 // the modul specific type for the local instance table. This macro
127 // must defined in each modul.
128 //#define tEplPtrInstance tEplInstanceInfo MEM*
130 EPL_MCO_DECL_INSTANCE_VAR ()
132 BYTE MEM abEplObdTrashObject_g[8];
135 //---------------------------------------------------------------------------
136 // local function prototypes
137 //---------------------------------------------------------------------------
139 EPL_MCO_DEFINE_INSTANCE_FCT ()
141 static tEplKernel EplObdCallObjectCallback (EPL_MCO_DECL_INSTANCE_PTR_
142 tEplObdCallback fpCallback_p,
143 tEplObdCbParam MEM* pCbParam_p);
145 static tEplObdSize EplObdGetDataSizeIntern (tEplObdSubEntryPtr pSubIndexEntry_p);
147 static tEplObdSize EplObdGetStrLen (void* pObjData_p,
148 tEplObdSize ObjLen_p,
149 tEplObdType ObjType_p);
151 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
152 static tEplKernel EplObdCheckObjectRange (
153 tEplObdSubEntryPtr pSubindexEntry_p,
157 static tEplKernel EplObdGetVarEntry (
158 tEplObdSubEntryPtr pSubindexEntry_p,
159 tEplObdVarEntry MEM** ppVarEntry_p);
161 static tEplKernel EplObdGetEntry (EPL_MCO_DECL_INSTANCE_PTR_
162 unsigned int uiIndex_p,
163 unsigned int uiSubindex_p,
164 tEplObdEntryPtr* ppObdEntry_p,
165 tEplObdSubEntryPtr* ppObdSubEntry_p);
167 static tEplObdSize EplObdGetObjectSize (tEplObdSubEntryPtr pSubIndexEntry_p);
169 static tEplKernel EplObdGetIndexIntern (
170 tEplObdInitParam MEM* pInitParam_p,
171 unsigned int uiIndex_p,
172 tEplObdEntryPtr* ppObdEntry_p);
174 static tEplKernel EplObdGetSubindexIntern (
175 tEplObdEntryPtr pObdEntry_p,
176 unsigned int uiSubIndex_p,
177 tEplObdSubEntryPtr* ppObdSubEntry_p);
179 static tEplKernel EplObdAccessOdPartIntern (EPL_MCO_DECL_INSTANCE_PTR_
180 tEplObdPart CurrentOdPart_p,
181 tEplObdEntryPtr pObdEnty_p,
182 tEplObdDir Direction_p);
184 static void * EplObdGetObjectDefaultPtr (tEplObdSubEntryPtr pSubIndexEntry_p);
185 static void MEM* EplObdGetObjectCurrentPtr (tEplObdSubEntryPtr pSubIndexEntry_p);
187 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
189 static tEplKernel EplObdCallStoreCallback (EPL_MCO_DECL_INSTANCE_PTR_
190 tEplObdCbStoreParam MEM* pCbStoreParam_p);
192 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
194 static void EplObdCopyObjectData (
195 void MEM* pDstData_p,
197 tEplObdSize ObjSize_p,
198 tEplObdType ObjType_p);
200 void * EplObdGetObjectDataPtrIntern (tEplObdSubEntryPtr pSubindexEntry_p);
202 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
203 BOOL* pfEntryNumerical_p);
205 static tEplKernel PUBLIC EplObdWriteEntryPre (EPL_MCO_DECL_INSTANCE_PTR_
206 unsigned int uiIndex_p,
207 unsigned int uiSubIndex_p,
211 tEplObdEntryPtr* ppObdEntry_p,
212 tEplObdSubEntryPtr* ppSubEntry_p,
213 tEplObdCbParam MEM* pCbParam_p,
214 tEplObdSize* pObdSize_p);
216 static tEplKernel PUBLIC EplObdWriteEntryPost (EPL_MCO_DECL_INSTANCE_PTR_
217 tEplObdEntryPtr pObdEntry_p,
218 tEplObdSubEntryPtr pSubEntry_p,
219 tEplObdCbParam MEM* pCbParam_p,
222 tEplObdSize ObdSize_p);
226 //=========================================================================//
228 // P U B L I C F U N C T I O N S //
230 //=========================================================================//
232 //---------------------------------------------------------------------------
234 // Function: EplObdInit()
236 // Description: initializes the first instance
238 // Parameters: pInitParam_p = init parameter
240 // Return: tEplKernel = errorcode
244 //---------------------------------------------------------------------------
246 EPLDLLEXPORT tEplKernel PUBLIC EplObdInit (EPL_MCO_DECL_PTR_INSTANCE_PTR_
247 tEplObdInitParam MEM* pInitParam_p)
251 EPL_MCO_DELETE_INSTANCE_TABLE ();
253 if (pInitParam_p == NULL)
255 Ret = kEplSuccessful;
259 Ret = EplObdAddInstance (EPL_MCO_PTR_INSTANCE_PTR_
268 //---------------------------------------------------------------------------
270 // Function: EplObdAddInstance()
272 // Description: adds a new instance
274 // Parameters: pInitParam_p
276 // Return: tEplKernel
280 //---------------------------------------------------------------------------
282 EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance (EPL_MCO_DECL_PTR_INSTANCE_PTR_
283 tEplObdInitParam MEM* pInitParam_p)
286 EPL_MCO_DECL_INSTANCE_PTR_LOCAL
289 // check if pointer to instance pointer valid
290 // get free instance and set the globale instance pointer
291 // set also the instance addr to parameterlist
292 EPL_MCO_CHECK_PTR_INSTANCE_PTR ();
293 EPL_MCO_GET_FREE_INSTANCE_PTR ();
294 EPL_MCO_SET_PTR_INSTANCE_PTR ();
296 // save init parameters
297 EPL_MEMCPY (&EPL_MCO_GLB_VAR (m_ObdInitParam), pInitParam_p, sizeof (tEplObdInitParam));
299 // clear callback function for command LOAD and STORE
300 EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) = NULL;
302 // sign instance as used
303 EPL_MCO_WRITE_INSTANCE_STATE (kStateUsed);
305 // initialize object dictionary
306 // so all all VarEntries will be initialized to trash object and default values will be set to current data
307 Ret = EplObdAccessOdPart (EPL_MCO_INSTANCE_PTR_
308 kEplObdPartAll, kEplObdDirInit);
315 //---------------------------------------------------------------------------
317 // Function: EplObdDeleteInstance()
319 // Description: delete instance
321 // Parameters: EPL_MCO_DECL_INSTANCE_PTR
323 // Return: tEplKernel
327 //---------------------------------------------------------------------------
328 #if (EPL_USE_DELETEINST_FUNC != FALSE)
329 EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance (EPL_MCO_DECL_INSTANCE_PTR)
331 // check for all API function if instance is valid
332 EPL_MCO_CHECK_INSTANCE_STATE ();
334 // sign instance as unused
335 EPL_MCO_WRITE_INSTANCE_STATE (kStateUnused);
337 return kEplSuccessful;
340 #endif // (EPL_USE_DELETEINST_FUNC != FALSE)
343 //---------------------------------------------------------------------------
345 // Function: EplObdWriteEntry()
347 // Description: Function writes data to an OBD entry. Strings
348 // are stored with added '\0' character.
350 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
351 // uiIndex_p = Index of the OD entry
352 // uiSubIndex_p = Subindex of the OD Entry
353 // pSrcData_p = Pointer to the data to write
354 // Size_p = Size of the data in Byte
356 // Return: tEplKernel = Errorcode
361 //---------------------------------------------------------------------------
363 EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry (EPL_MCO_DECL_INSTANCE_PTR_
364 unsigned int uiIndex_p,
365 unsigned int uiSubIndex_p,
371 tEplObdEntryPtr pObdEntry;
372 tEplObdSubEntryPtr pSubEntry;
373 tEplObdCbParam MEM CbParam;
378 Ret = EplObdWriteEntryPre (EPL_MCO_INSTANCE_PTR_
388 if (Ret != kEplSuccessful)
393 Ret = EplObdWriteEntryPost (EPL_MCO_INSTANCE_PTR_
400 if (Ret != kEplSuccessful)
412 //---------------------------------------------------------------------------
414 // Function: EplObdReadEntry()
416 // Description: The function reads an object entry. The application
417 // can always read the data even if attrib kEplObdAccRead
418 // is not set. The attrib is only checked up for SDO transfer.
420 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
421 // uiIndex_p = Index oof the OD entry to read
422 // uiSubIndex_p = Subindex to read
423 // pDstData_p = pointer to the buffer for data
424 // Offset_p = offset in data for read access
425 // pSize_p = IN: Size of the buffer
426 // OUT: number of readed Bytes
428 // Return: tEplKernel
432 //---------------------------------------------------------------------------
434 EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry (EPL_MCO_DECL_INSTANCE_PTR_
435 unsigned int uiIndex_p,
436 unsigned int uiSubIndex_p,
438 tEplObdSize * pSize_p)
442 tEplObdEntryPtr pObdEntry;
443 tEplObdSubEntryPtr pSubEntry;
444 tEplObdCbParam MEM CbParam;
448 // check for all API function if instance is valid
449 EPL_MCO_CHECK_INSTANCE_STATE ();
451 ASSERT (pDstData_p != NULL);
452 ASSERT (pSize_p != NULL);
454 // get address of index and subindex entry
455 Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_
456 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
457 if (Ret != kEplSuccessful)
462 // get pointer to object data
463 pSrcData = EplObdGetObjectDataPtrIntern (pSubEntry);
465 // check source pointer
466 if (pSrcData == NULL)
468 Ret = kEplObdReadViolation;
472 //------------------------------------------------------------------------
473 // address of source data to structure of callback parameters
474 // so callback function can change this data before reading
475 CbParam.m_uiIndex = uiIndex_p;
476 CbParam.m_uiSubIndex= uiSubIndex_p;
477 CbParam.m_pArg = pSrcData;
478 CbParam.m_ObdEvent = kEplObdEvPreRead;
479 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
480 pObdEntry->m_fpCallback, &CbParam);
481 if (Ret != kEplSuccessful)
486 // get size of data and check if application has reserved enough memory
487 ObdSize = EplObdGetDataSizeIntern (pSubEntry);
488 // check if offset given and calc correct number of bytes to read
489 if (*pSize_p < ObdSize)
491 Ret = kEplObdValueLengthError;
495 // read value from object
496 EPL_MEMCPY (pDstData_p, pSrcData, ObdSize);
499 // write address of destination data to structure of callback parameters
500 // so callback function can change this data after reading
501 CbParam.m_pArg = pDstData_p;
502 CbParam.m_ObdEvent = kEplObdEvPostRead;
503 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
504 pObdEntry->m_fpCallback, &CbParam);
512 //---------------------------------------------------------------------------
514 // Function: EplObdAccessOdPart()
516 // Description: restores default values of one part of OD
518 // Parameters: ObdPart_p
521 // Return: tEplKernel
525 //---------------------------------------------------------------------------
527 EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart (EPL_MCO_DECL_INSTANCE_PTR_
528 tEplObdPart ObdPart_p,
529 tEplObdDir Direction_p)
532 tEplKernel Ret = kEplSuccessful;
534 tEplObdEntryPtr pObdEntry;
536 // check for all API function if instance is valid
537 EPL_MCO_CHECK_INSTANCE_STATE ();
539 // part always has to be unequal to NULL
540 pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pPart);
541 ASSERTMSG (pObdEntry != NULL, "EplObdAccessOdPart(): no OD part is defined!\n");
543 // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
547 if ((ObdPart_p & kEplObdPartGen) != 0)
551 Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_
552 kEplObdPartGen, pObdEntry, Direction_p);
553 if (Ret != kEplSuccessful)
559 // access to manufacturer part
560 pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pManufacturerPart);
562 if ( ((ObdPart_p & kEplObdPartMan) != 0) &&
563 (pObdEntry != NULL) )
567 Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_
568 kEplObdPartMan, pObdEntry, Direction_p);
569 if (Ret != kEplSuccessful)
575 // access to device part
576 pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pDevicePart);
578 if ( ((ObdPart_p & kEplObdPartDev) != 0) &&
579 (pObdEntry != NULL) )
583 Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_
584 kEplObdPartDev, pObdEntry, Direction_p);
585 if (Ret != kEplSuccessful)
591 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
593 // access to user part
594 pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pUserPart);
596 if ( ((ObdPart_p & kEplObdPartUsr) != 0) &&
597 (pObdEntry != NULL) )
601 Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_
602 kEplObdPartUsr, pObdEntry, Direction_p);
603 if (Ret != kEplSuccessful)
611 // no access to an OD part was done? illegal OD part was specified!
612 if (fPartFount == FALSE)
614 Ret = kEplObdIllegalPart;
624 //---------------------------------------------------------------------------
626 // Function: EplObdDefineVar()
628 // Description: defines a variable in OD
630 // Parameters: pEplVarParam_p
632 // Return: tEplKernel
636 //---------------------------------------------------------------------------
638 EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar (EPL_MCO_DECL_INSTANCE_PTR_
639 tEplVarParam MEM* pVarParam_p)
643 tEplObdVarEntry MEM* pVarEntry;
644 tEplVarParamValid VarValid;
645 tEplObdSubEntryPtr pSubindexEntry;
647 // check for all API function if instance is valid
648 EPL_MCO_CHECK_INSTANCE_STATE ();
650 ASSERT (pVarParam_p != NULL); // is not allowed to be NULL
652 // get address of subindex entry
653 Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_
654 pVarParam_p->m_uiIndex,
655 pVarParam_p->m_uiSubindex,
656 NULL, &pSubindexEntry);
657 if (Ret != kEplSuccessful)
663 Ret = EplObdGetVarEntry (pSubindexEntry, &pVarEntry);
664 if (Ret != kEplSuccessful)
669 VarValid = pVarParam_p->m_ValidFlag;
671 // copy only this values, which valid flag is set
672 if ((VarValid & kVarValidSize) != 0)
674 if (pSubindexEntry->m_Type != kEplObdTypDomain)
676 tEplObdSize DataSize;
678 // check passed size parameter
679 DataSize = EplObdGetObjectSize(pSubindexEntry);
680 if (DataSize != pVarParam_p->m_Size)
681 { // size of variable does not match
682 Ret = kEplObdValueLengthError;
687 { // size can be set only for objects of type DOMAIN
688 pVarEntry->m_Size = pVarParam_p->m_Size;
692 if ((VarValid & kVarValidData) != 0)
694 pVarEntry->m_pData = pVarParam_p->m_pData;
697 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
699 if ((VarValid & kVarValidCallback) != 0)
701 pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
704 if ((VarValid & kVarValidArg) != 0)
706 pVarEntry->m_pArg = pVarParam_p->m_pArg;
711 // Ret is already set to kEplSuccessful from ObdGetVarIntern()
720 //---------------------------------------------------------------------------
722 // Function: EplObdGetObjectDataPtr()
724 // Description: It returnes the current data pointer. But if object is an
725 // constant object it returnes the default pointer.
727 // Parameters: uiIndex_p = Index of the entry
728 // uiSubindex_p = Subindex of the entry
730 // Return: void * = pointer to object data
734 //---------------------------------------------------------------------------
736 EPLDLLEXPORT void * PUBLIC EplObdGetObjectDataPtr (EPL_MCO_DECL_INSTANCE_PTR_
737 unsigned int uiIndex_p,
738 unsigned int uiSubIndex_p)
742 tEplObdEntryPtr pObdEntry;
743 tEplObdSubEntryPtr pObdSubEntry;
746 // get pointer to index structure
747 Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam),
750 if(Ret != kEplSuccessful)
756 // get pointer to subindex structure
757 Ret = EplObdGetSubindexIntern (pObdEntry,
760 if(Ret != kEplSuccessful)
766 pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
774 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
776 //---------------------------------------------------------------------------
778 // Function: EplObdRegisterUserOd()
780 // Description: function registers the user OD
782 // Parameters: pUserOd_p =pointer to user ODd
784 // Return: tEplKernel = errorcode
788 //---------------------------------------------------------------------------
789 EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd (EPL_MCO_DECL_INSTANCE_PTR_
790 tEplObdEntryPtr pUserOd_p)
793 EPL_MCO_CHECK_INSTANCE_STATE ();
795 EPL_MCO_GLB_VAR (m_ObdInitParam.m_pUserPart) = pUserOd_p;
797 return kEplSuccessful;
804 //---------------------------------------------------------------------------
806 // Function: EplObdInitVarEntry()
808 // Description: function to initialize VarEntry dependened on object type
810 // Parameters: pVarEntry_p = pointer to var entry structure
811 // Type_p = object type
812 // ObdSize_p = size of object data
818 //---------------------------------------------------------------------------
820 EPLDLLEXPORT void PUBLIC EplObdInitVarEntry (EPL_MCO_DECL_INSTANCE_PTR_
821 tEplObdVarEntry MEM* pVarEntry_p,
822 tEplObdType Type_p, tEplObdSize ObdSize_p)
825 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
827 // reset pointer to VAR callback and argument
828 pVarEntry_p->m_fpCallback = NULL;
829 pVarEntry_p->m_pArg = NULL;
834 // 10-dec-2004 r.d.: this function will not be used for strings
835 if ((Type_p == kEplObdTypDomain))
836 // (bType_p == kEplObdTypVString) /* ||
837 // (bType_p == kEplObdTypOString) ||
838 // (bType_p == kEplObdTypUString) */ )
840 // variables which are defined as DOMAIN or VSTRING should not point to
841 // trash object, because this trash object contains only 8 bytes. DOMAINS or
842 // STRINGS can be longer.
843 pVarEntry_p->m_pData = NULL;
844 pVarEntry_p->m_Size = 0;
848 // set address to variable data to trash object
849 // This prevents an access violation if user forgets to call EplObdDefineVar()
850 // for this variable but mappes it in a PDO.
851 pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
852 pVarEntry_p->m_Size = ObdSize_p;
858 //---------------------------------------------------------------------------
860 // Function: EplObdGetDataSize()
862 // Description: function to initialize VarEntry dependened on object type
864 // gets the data size of an object
865 // for string objects it returnes the string length
867 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
869 // uiSubIndex_p= Subindex
871 // Return: tEplObdSize
875 //---------------------------------------------------------------------------
876 EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_
877 unsigned int uiIndex_p,
878 unsigned int uiSubIndex_p)
882 tEplObdEntryPtr pObdEntry;
883 tEplObdSubEntryPtr pObdSubEntry;
886 // get pointer to index structure
887 Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam),
890 if(Ret != kEplSuccessful)
896 // get pointer to subindex structure
897 Ret = EplObdGetSubindexIntern (pObdEntry,
900 if(Ret != kEplSuccessful)
907 ObdSize = EplObdGetDataSizeIntern (pObdSubEntry);
911 //---------------------------------------------------------------------------
913 // Function: EplObdGetNodeId()
915 // Description: function returns nodeid from entry 0x1F93
918 // Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
920 // Return: unsigned int = Node Id
924 //---------------------------------------------------------------------------
925 EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
932 ObdSize = sizeof(bNodeId);
933 Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
934 EPL_OBD_NODE_ID_INDEX,
935 EPL_OBD_NODE_ID_SUBINDEX,
938 if(Ret != kEplSuccessful)
940 bNodeId = EPL_C_ADR_INVALID;
945 return (unsigned int) bNodeId;
950 //---------------------------------------------------------------------------
952 // Function: EplObdSetNodeId()
954 // Description: function sets nodeid in entry 0x1F93
957 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
958 // uiNodeId_p = Node Id to set
959 // NodeIdType_p= Type on which way the Node Id was set
961 // Return: tEplKernel = Errorcode
965 //---------------------------------------------------------------------------
966 EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_
967 unsigned int uiNodeId_p,
968 tEplObdNodeIdType NodeIdType_p)
976 if(uiNodeId_p == EPL_C_ADR_INVALID)
978 Ret = kEplInvalidNodeId;
981 bNodeId = (BYTE)uiNodeId_p;
982 ObdSize = sizeof(BYTE);
983 // write NodeId to OD entry
984 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
985 EPL_OBD_NODE_ID_INDEX,
986 EPL_OBD_NODE_ID_SUBINDEX,
989 if(Ret != kEplSuccessful)
994 // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
995 switch (NodeIdType_p)
998 case kEplObdNodeIdUnknown:
1000 fHwBool = OBD_FALSE;
1004 case kEplObdNodeIdSoftware:
1006 fHwBool = OBD_FALSE;
1010 case kEplObdNodeIdHardware:
1018 fHwBool = OBD_FALSE;
1021 } // end of switch (NodeIdType_p)
1024 ObdSize = sizeof(fHwBool);
1025 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
1026 EPL_OBD_NODE_ID_INDEX,
1027 EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
1030 if(Ret != kEplSuccessful)
1039 //---------------------------------------------------------------------------
1041 // Function: EplObdIsNumerical()
1043 // Description: function checks if a entry is numerical or not
1046 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
1047 // uiIndex_p = Index
1048 // uiSubIndex_p = Subindex
1049 // pfEntryNumerical_p = pointer to BOOL for returnvalue
1050 // -> TRUE if entry a numerical value
1051 // -> FALSE if entry not a numerical value
1053 // Return: tEplKernel = Errorcode
1057 //---------------------------------------------------------------------------
1058 EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_
1059 unsigned int uiIndex_p,
1060 unsigned int uiSubIndex_p,
1061 BOOL* pfEntryNumerical_p)
1064 tEplObdEntryPtr pObdEntry;
1065 tEplObdSubEntryPtr pObdSubEntry;
1068 // get pointer to index structure
1069 Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam),
1072 if(Ret != kEplSuccessful)
1077 // get pointer to subindex structure
1078 Ret = EplObdGetSubindexIntern (pObdEntry,
1081 if(Ret != kEplSuccessful)
1086 Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
1094 //---------------------------------------------------------------------------
1096 // Function: EplObdReadEntryToLe()
1098 // Description: The function reads an object entry from the byteoder
1099 // of the system to the little endian byteorder for numerical values.
1100 // For other types a normal read will be processed. This is usefull for
1101 // the PDO and SDO module. The application
1102 // can always read the data even if attrib kEplObdAccRead
1103 // is not set. The attrib is only checked up for SDO transfer.
1105 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1106 // uiIndex_p = Index of the OD entry to read
1107 // uiSubIndex_p = Subindex to read
1108 // pDstData_p = pointer to the buffer for data
1109 // Offset_p = offset in data for read access
1110 // pSize_p = IN: Size of the buffer
1111 // OUT: number of readed Bytes
1113 // Return: tEplKernel
1117 //---------------------------------------------------------------------------
1118 EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe (EPL_MCO_DECL_INSTANCE_PTR_
1119 unsigned int uiIndex_p,
1120 unsigned int uiSubIndex_p,
1122 tEplObdSize * pSize_p)
1125 tEplObdEntryPtr pObdEntry;
1126 tEplObdSubEntryPtr pSubEntry;
1127 tEplObdCbParam MEM CbParam;
1129 tEplObdSize ObdSize;
1131 // check for all API function if instance is valid
1132 EPL_MCO_CHECK_INSTANCE_STATE ();
1134 ASSERT (pDstData_p != NULL);
1135 ASSERT (pSize_p != NULL);
1137 // get address of index and subindex entry
1138 Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_
1139 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1140 if (Ret != kEplSuccessful)
1145 // get pointer to object data
1146 pSrcData = EplObdGetObjectDataPtrIntern (pSubEntry);
1148 // check source pointer
1149 if (pSrcData == NULL)
1151 Ret = kEplObdReadViolation;
1155 //------------------------------------------------------------------------
1156 // address of source data to structure of callback parameters
1157 // so callback function can change this data before reading
1158 CbParam.m_uiIndex = uiIndex_p;
1159 CbParam.m_uiSubIndex= uiSubIndex_p;
1160 CbParam.m_pArg = pSrcData;
1161 CbParam.m_ObdEvent = kEplObdEvPreRead;
1162 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
1163 pObdEntry->m_fpCallback, &CbParam);
1164 if (Ret != kEplSuccessful)
1169 // get size of data and check if application has reserved enough memory
1170 ObdSize = EplObdGetDataSizeIntern (pSubEntry);
1171 // check if offset given and calc correct number of bytes to read
1172 if (*pSize_p < ObdSize)
1174 Ret = kEplObdValueLengthError;
1178 // check if numerical type
1179 switch(pSubEntry->m_Type)
1181 //-----------------------------------------------
1182 // types without ami
1183 case kEplObdTypVString:
1184 case kEplObdTypOString:
1185 case kEplObdTypDomain:
1188 // read value from object
1189 EPL_MEMCPY (pDstData_p, pSrcData, ObdSize);
1193 //-----------------------------------------------
1194 // numerical type which needs ami-write
1195 // 8 bit or smaller values
1196 case kEplObdTypBool:
1197 case kEplObdTypInt8:
1198 case kEplObdTypUInt8:
1200 AmiSetByteToLe(pDstData_p, *((BYTE*)pSrcData));
1205 case kEplObdTypInt16:
1206 case kEplObdTypUInt16:
1208 AmiSetWordToLe(pDstData_p, *((WORD*)pSrcData));
1213 case kEplObdTypInt24:
1214 case kEplObdTypUInt24:
1216 AmiSetDword24ToLe(pDstData_p, *((DWORD*)pSrcData));
1221 case kEplObdTypInt32:
1222 case kEplObdTypUInt32:
1223 case kEplObdTypReal32:
1225 AmiSetDwordToLe(pDstData_p, *((DWORD*)pSrcData));
1230 case kEplObdTypInt40:
1231 case kEplObdTypUInt40:
1233 AmiSetQword40ToLe(pDstData_p, *((QWORD*)pSrcData));
1238 case kEplObdTypInt48:
1239 case kEplObdTypUInt48:
1241 AmiSetQword48ToLe(pDstData_p, *((QWORD*)pSrcData));
1246 case kEplObdTypInt56:
1247 case kEplObdTypUInt56:
1249 AmiSetQword56ToLe(pDstData_p, *((QWORD*)pSrcData));
1254 case kEplObdTypInt64:
1255 case kEplObdTypUInt64:
1256 case kEplObdTypReal64:
1258 AmiSetQword64ToLe(pDstData_p, *((QWORD*)pSrcData));
1263 case kEplObdTypTimeOfDay:
1264 case kEplObdTypTimeDiff:
1266 AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay*)pSrcData));
1270 }// end of switch(pSubEntry->m_Type)
1275 // write address of destination data to structure of callback parameters
1276 // so callback function can change this data after reading
1277 CbParam.m_pArg = pDstData_p;
1278 CbParam.m_ObdEvent = kEplObdEvPostRead;
1279 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
1280 pObdEntry->m_fpCallback, &CbParam);
1288 //---------------------------------------------------------------------------
1290 // Function: EplObdWriteEntryFromLe()
1292 // Description: Function writes data to an OBD entry from a source with
1293 // little endian byteorder to the od with system specuific
1294 // byteorder. Not numerical values will only by copied. Strings
1295 // are stored with added '\0' character.
1297 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1298 // uiIndex_p = Index of the OD entry
1299 // uiSubIndex_p = Subindex of the OD Entry
1300 // pSrcData_p = Pointer to the data to write
1301 // Size_p = Size of the data in Byte
1303 // Return: tEplKernel = Errorcode
1308 //---------------------------------------------------------------------------
1309 EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe (EPL_MCO_DECL_INSTANCE_PTR_
1310 unsigned int uiIndex_p,
1311 unsigned int uiSubIndex_p,
1316 tEplObdEntryPtr pObdEntry;
1317 tEplObdSubEntryPtr pSubEntry;
1318 tEplObdCbParam MEM CbParam;
1320 tEplObdSize ObdSize;
1322 void* pBuffer = &qwBuffer;
1325 Ret = EplObdWriteEntryPre (EPL_MCO_INSTANCE_PTR_
1335 if (Ret != kEplSuccessful)
1341 // check if numerical type
1342 switch(pSubEntry->m_Type)
1344 //-----------------------------------------------
1345 // types without ami
1347 { // do nothing, i.e. use the given source pointer
1348 pBuffer = pSrcData_p;
1352 //-----------------------------------------------
1353 // numerical type which needs ami-write
1354 // 8 bit or smaller values
1355 case kEplObdTypBool:
1356 case kEplObdTypInt8:
1357 case kEplObdTypUInt8:
1359 *((BYTE*)pBuffer) = AmiGetByteFromLe(pSrcData_p);
1364 case kEplObdTypInt16:
1365 case kEplObdTypUInt16:
1367 *((WORD*)pBuffer) = AmiGetWordFromLe(pSrcData_p);
1372 case kEplObdTypInt24:
1373 case kEplObdTypUInt24:
1375 *((DWORD*)pBuffer) = AmiGetDword24FromLe(pSrcData_p);
1380 case kEplObdTypInt32:
1381 case kEplObdTypUInt32:
1382 case kEplObdTypReal32:
1384 *((DWORD*)pBuffer) = AmiGetDwordFromLe(pSrcData_p);
1389 case kEplObdTypInt40:
1390 case kEplObdTypUInt40:
1392 *((QWORD*)pBuffer) = AmiGetQword40FromLe(pSrcData_p);
1397 case kEplObdTypInt48:
1398 case kEplObdTypUInt48:
1400 *((QWORD*)pBuffer) = AmiGetQword48FromLe(pSrcData_p);
1405 case kEplObdTypInt56:
1406 case kEplObdTypUInt56:
1408 *((QWORD*)pBuffer) = AmiGetQword56FromLe(pSrcData_p);
1413 case kEplObdTypInt64:
1414 case kEplObdTypUInt64:
1415 case kEplObdTypReal64:
1417 *((QWORD*)pBuffer) = AmiGetQword64FromLe(pSrcData_p);
1422 case kEplObdTypTimeOfDay:
1423 case kEplObdTypTimeDiff:
1425 AmiGetTimeOfDay(pBuffer, ((tTimeOfDay*)pSrcData_p));
1429 }// end of switch(pSubEntry->m_Type)
1432 Ret = EplObdWriteEntryPost (EPL_MCO_INSTANCE_PTR_
1439 if (Ret != kEplSuccessful)
1450 //---------------------------------------------------------------------------
1452 // Function: EplObdGetAccessType()
1454 // Description: Function returns accesstype of the entry
1456 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1457 // uiIndex_p = Index of the OD entry
1458 // uiSubIndex_p = Subindex of the OD Entry
1459 // pAccessTyp_p = pointer to buffer to store accesstype
1461 // Return: tEplKernel = errorcode
1466 //---------------------------------------------------------------------------
1467 EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_
1468 unsigned int uiIndex_p,
1469 unsigned int uiSubIndex_p,
1470 tEplObdAccess* pAccessTyp_p)
1474 tEplObdEntryPtr pObdEntry;
1475 tEplObdSubEntryPtr pObdSubEntry;
1478 // get pointer to index structure
1479 Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam),
1482 if(Ret != kEplSuccessful)
1487 // get pointer to subindex structure
1488 Ret = EplObdGetSubindexIntern (pObdEntry,
1491 if(Ret != kEplSuccessful)
1497 *pAccessTyp_p = pObdSubEntry->m_Access;
1504 //---------------------------------------------------------------------------
1506 // Function: EplObdSearchVarEntry()
1508 // Description: gets variable from OD
1510 // Parameters: uiIndex_p = index of the var entry to search
1511 // uiSubindex_p = subindex of var entry to search
1512 // ppVarEntry_p = pointer to the pointer to the varentry
1514 // Return: tEplKernel
1518 //---------------------------------------------------------------------------
1520 tEplKernel PUBLIC EplObdSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_
1521 unsigned int uiIndex_p,
1522 unsigned int uiSubindex_p,
1523 tEplObdVarEntry MEM** ppVarEntry_p)
1527 tEplObdSubEntryPtr pSubindexEntry;
1529 // check for all API function if instance is valid
1530 EPL_MCO_CHECK_INSTANCE_STATE ();
1532 // get address of subindex entry
1533 Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_
1534 uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
1535 if (Ret == kEplSuccessful)
1538 Ret = EplObdGetVarEntry (pSubindexEntry, ppVarEntry_p);
1544 //=========================================================================//
1546 // P R I V A T E D E F I N I T I O N S //
1548 //=========================================================================//
1550 EPL_MCO_DECL_INSTANCE_FCT ()
1551 //---------------------------------------------------------------------------
1553 // Function: EplObdCallObjectCallback()
1555 // Description: calls callback function of an object or of a variable
1557 // Parameters: fpCallback_p
1560 // Return: tEplKernel
1564 //---------------------------------------------------------------------------
1566 static tEplKernel EplObdCallObjectCallback (EPL_MCO_DECL_INSTANCE_PTR_
1567 tEplObdCallback fpCallback_p,
1568 tEplObdCbParam MEM* pCbParam_p)
1572 tEplObdCallback MEM fpCallback;
1574 // check for all API function if instance is valid
1575 EPL_MCO_CHECK_INSTANCE_STATE ();
1577 ASSERT (pCbParam_p != NULL);
1579 Ret = kEplSuccessful;
1581 // check address of callback function before calling it
1582 if (fpCallback_p != NULL)
1584 // KEIL C51 V6.01 has a bug.
1585 // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
1586 fpCallback = fpCallback_p;
1588 // call callback function for this object
1589 Ret = fpCallback (EPL_MCO_INSTANCE_PARAM_IDX_()
1596 //---------------------------------------------------------------------------
1598 // Function: EplObdGetDataSizeIntern()
1600 // Description: gets the data size of an object
1601 // for string objects it returnes the string length
1603 // Parameters: pSubIndexEntry_p
1605 // Return: tEplObdSize
1609 //---------------------------------------------------------------------------
1611 static tEplObdSize EplObdGetDataSizeIntern (tEplObdSubEntryPtr pSubIndexEntry_p)
1614 tEplObdSize DataSize;
1617 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
1618 // then the current pointer is always NULL. The function
1619 // returns the length of default string.
1620 DataSize = EplObdGetObjectSize (pSubIndexEntry_p);
1622 if (pSubIndexEntry_p->m_Type == kEplObdTypVString)
1624 // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
1625 pData = ((void MEM*) EplObdGetObjectCurrentPtr (pSubIndexEntry_p));
1628 DataSize = EplObdGetStrLen ((void *) pData, DataSize, pSubIndexEntry_p->m_Type);
1638 //---------------------------------------------------------------------------
1640 // Function: EplObdGetStrLen()
1642 // Description: The function calculates the length of string. The '\0'
1643 // character is included!!
1645 // Parameters: pObjData_p = pointer to string
1646 // ObjLen_p = max. length of objectr entry
1647 // bObjType_p = object type (VSTRING, ...)
1649 // Returns: string length + 1
1653 //---------------------------------------------------------------------------
1655 static tEplObdSize EplObdGetStrLen (void * pObjData_p,
1656 tEplObdSize ObjLen_p,
1657 tEplObdType ObjType_p)
1660 tEplObdSize StrLen = 0;
1663 if (pObjData_p == NULL)
1668 //----------------------------------------
1669 // Visible String: data format byte
1670 if (ObjType_p == kEplObdTypVString)
1672 pbString = pObjData_p;
1674 for (StrLen = 0; StrLen < ObjLen_p; StrLen++)
1676 if (*pbString == '\0')
1686 //----------------------------------------
1687 // other string types ...
1696 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1698 //---------------------------------------------------------------------------
1700 // Function: EplObdCheckObjectRange()
1702 // Description: function to check value range of object data
1704 // NOTICE: The pointer of data (pData_p) must point out to an even address,
1705 // if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
1706 // always realiced because pointer m_pDefault points always to an
1707 // array of the SPECIFIED type.
1709 // Parameters: pSubindexEntry_p
1712 // Return: tEplKernel
1716 //---------------------------------------------------------------------------
1718 static tEplKernel EplObdCheckObjectRange (
1719 tEplObdSubEntryPtr pSubindexEntry_p,
1726 ASSERTMSG (pSubindexEntry_p != NULL,
1727 "EplObdCheckObjectRange(): no address to subindex struct!\n");
1729 Ret = kEplSuccessful;
1731 // check if data range has to be checked
1732 if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0)
1737 // get address of default data
1738 pRangeData = pSubindexEntry_p->m_pDefault;
1740 // jump to called object type
1741 switch ((tEplObdType) pSubindexEntry_p->m_Type)
1743 // -----------------------------------------------------------------
1744 // ObdType kEplObdTypBool will not be checked because there are only
1745 // two possible values 0 or 1.
1747 // -----------------------------------------------------------------
1748 // ObdTypes which has to be check up because numerical values
1749 case kEplObdTypInt8:
1751 // switch to lower limit
1752 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1754 // check if value is to low
1755 if (*((tEplObdInteger8 *) pData_p) < *((tEplObdInteger8 *) pRangeData))
1757 Ret = kEplObdValueTooLow;
1761 // switch to higher limit
1762 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1764 // check if value is to high
1765 if (*((tEplObdInteger8 *) pData_p) > *((tEplObdInteger8 *) pRangeData))
1767 Ret = kEplObdValueTooHigh;
1772 case kEplObdTypUInt8:
1774 // switch to lower limit
1775 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1777 // check if value is to low
1778 if (*((tEplObdUnsigned8 *) pData_p) < *((tEplObdUnsigned8 *) pRangeData))
1780 Ret = kEplObdValueTooLow;
1784 // switch to higher limit
1785 pRangeData = ((tEplObdUnsigned8*) pRangeData) + 1;
1787 // check if value is to high
1788 if (*((tEplObdUnsigned8 *) pData_p) > *((tEplObdUnsigned8 *) pRangeData))
1790 Ret = kEplObdValueTooHigh;
1795 case kEplObdTypInt16:
1797 // switch to lower limit
1798 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1800 // check if value is to low
1801 if (*((tEplObdInteger16 *) pData_p) < *((tEplObdInteger16 *) pRangeData))
1803 Ret = kEplObdValueTooLow;
1807 // switch to higher limit
1808 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1810 // check if value is to high
1811 if (*((tEplObdInteger16 *) pData_p) > *((tEplObdInteger16 *) pRangeData))
1813 Ret = kEplObdValueTooHigh;
1818 case kEplObdTypUInt16:
1820 // switch to lower limit
1821 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1823 // check if value is to low
1824 if (*((tEplObdUnsigned16 *) pData_p) < *((tEplObdUnsigned16 *) pRangeData))
1826 Ret = kEplObdValueTooLow;
1830 // switch to higher limit
1831 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1833 // check if value is to high
1834 if (*((tEplObdUnsigned16 *) pData_p) > *((tEplObdUnsigned16 *) pRangeData))
1836 Ret = kEplObdValueTooHigh;
1841 case kEplObdTypInt32:
1843 // switch to lower limit
1844 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1846 // check if value is to low
1847 if (*((tEplObdInteger32 *) pData_p) < *((tEplObdInteger32 *) pRangeData))
1849 Ret = kEplObdValueTooLow;
1853 // switch to higher limit
1854 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1856 // check if value is to high
1857 if (*((tEplObdInteger32 *) pData_p) > *((tEplObdInteger32 *) pRangeData))
1859 Ret = kEplObdValueTooHigh;
1864 case kEplObdTypUInt32:
1866 // switch to lower limit
1867 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1869 // check if value is to low
1870 if (*((tEplObdUnsigned32 *) pData_p) < *((tEplObdUnsigned32 *) pRangeData))
1872 Ret = kEplObdValueTooLow;
1876 // switch to higher limit
1877 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1879 // check if value is to high
1880 if (*((tEplObdUnsigned32 *) pData_p) > *((tEplObdUnsigned32 *) pRangeData))
1882 Ret = kEplObdValueTooHigh;
1887 case kEplObdTypReal32:
1889 // switch to lower limit
1890 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1892 // check if value is to low
1893 if (*((tEplObdReal32 *) pData_p) < *((tEplObdReal32 *) pRangeData))
1895 Ret = kEplObdValueTooLow;
1899 // switch to higher limit
1900 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1902 // check if value is to high
1903 if (*((tEplObdReal32 *) pData_p) > *((tEplObdReal32 *) pRangeData))
1905 Ret = kEplObdValueTooHigh;
1910 // -----------------------------------------------------------------
1911 case kEplObdTypInt40:
1912 case kEplObdTypInt48:
1913 case kEplObdTypInt56:
1914 case kEplObdTypInt64:
1916 // switch to lower limit
1917 pRangeData = ((signed QWORD *) pRangeData) + 1;
1919 // check if value is to low
1920 if (*((signed QWORD *) pData_p) < *((signed QWORD *) pRangeData))
1922 Ret = kEplObdValueTooLow;
1926 // switch to higher limit
1927 pRangeData = ((signed QWORD *) pRangeData) + 1;
1929 // check if value is to high
1930 if (*((signed QWORD *) pData_p) > *((signed QWORD *) pRangeData))
1932 Ret = kEplObdValueTooHigh;
1937 // -----------------------------------------------------------------
1938 case kEplObdTypUInt40:
1939 case kEplObdTypUInt48:
1940 case kEplObdTypUInt56:
1941 case kEplObdTypUInt64:
1943 // switch to lower limit
1944 pRangeData = ((unsigned QWORD *) pRangeData) + 1;
1946 // check if value is to low
1947 if (*((unsigned QWORD *) pData_p) < *((unsigned QWORD *) pRangeData))
1949 Ret = kEplObdValueTooLow;
1953 // switch to higher limit
1954 pRangeData = ((unsigned QWORD *) pRangeData) + 1;
1956 // check if value is to high
1957 if (*((unsigned QWORD *) pData_p) > *((unsigned QWORD *) pRangeData))
1959 Ret = kEplObdValueTooHigh;
1964 // -----------------------------------------------------------------
1965 case kEplObdTypReal64:
1967 // switch to lower limit
1968 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1970 // check if value is to low
1971 if (*((tEplObdReal64 *) pData_p) < *((tEplObdReal64 *) pRangeData))
1973 Ret = kEplObdValueTooLow;
1977 // switch to higher limit
1978 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1980 // check if value is to high
1981 if (*((tEplObdReal64 *) pData_p) > *((tEplObdReal64 *) pRangeData))
1983 Ret = kEplObdValueTooHigh;
1988 // -----------------------------------------------------------------
1989 case kEplObdTypTimeOfDay:
1990 case kEplObdTypTimeDiff:
1993 // -----------------------------------------------------------------
1994 // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
1995 // they have no numerical value.
1998 Ret = kEplObdUnknownObjectType;
2007 #endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2009 //---------------------------------------------------------------------------
2011 // Function: EplObdWriteEntryPre()
2013 // Description: Function prepares write of data to an OBD entry. Strings
2014 // are stored with added '\0' character.
2016 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
2017 // uiIndex_p = Index of the OD entry
2018 // uiSubIndex_p = Subindex of the OD Entry
2019 // pSrcData_p = Pointer to the data to write
2020 // Size_p = Size of the data in Byte
2022 // Return: tEplKernel = Errorcode
2027 //---------------------------------------------------------------------------
2029 static tEplKernel PUBLIC EplObdWriteEntryPre (EPL_MCO_DECL_INSTANCE_PTR_
2030 unsigned int uiIndex_p,
2031 unsigned int uiSubIndex_p,
2035 tEplObdEntryPtr* ppObdEntry_p,
2036 tEplObdSubEntryPtr* ppSubEntry_p,
2037 tEplObdCbParam MEM* pCbParam_p,
2038 tEplObdSize* pObdSize_p)
2042 tEplObdEntryPtr pObdEntry;
2043 tEplObdSubEntryPtr pSubEntry;
2044 tEplObdAccess Access;
2046 tEplObdSize ObdSize;
2047 BOOL fEntryNumerical;
2049 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
2050 tEplObdVStringDomain MEM MemVStringDomain;
2051 void MEM* pCurrData;
2054 // check for all API function if instance is valid
2055 EPL_MCO_CHECK_INSTANCE_STATE ();
2057 ASSERT (pSrcData_p != NULL); // should never be NULL
2059 //------------------------------------------------------------------------
2060 // get address of index and subindex entry
2061 Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_
2062 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
2063 if (Ret != kEplSuccessful)
2068 // get pointer to object data
2069 pDstData = (void MEM*) EplObdGetObjectDataPtrIntern (pSubEntry);
2071 Access = (tEplObdAccess) pSubEntry->m_Access;
2073 // check access for write
2074 // access violation if adress to current value is NULL
2075 if ( ((Access & kEplObdAccConst) != 0) ||
2076 (pDstData == NULL) )
2078 Ret = kEplObdAccessViolation;
2082 //------------------------------------------------------------------------
2083 // get size of object
2084 // -as ObdSize = ObdGetObjectSize (pSubEntry);
2086 //------------------------------------------------------------------------
2087 // To use the same callback function for ObdWriteEntry as well as for
2088 // an SDO download call at first (kEplObdEvPre...) the callback function
2089 // with the argument pointer to object size.
2090 pCbParam_p->m_uiIndex = uiIndex_p;
2091 pCbParam_p->m_uiSubIndex = uiSubIndex_p;
2093 // Because object size and object pointer are
2094 // adapted by user callback function, re-read
2096 ObdSize = EplObdGetObjectSize (pSubEntry);
2097 pDstData = (void MEM*) EplObdGetObjectDataPtrIntern (pSubEntry);
2099 // 09-dec-2004 r.d.:
2100 // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
2101 // for String or Domain which lets called module directly change
2102 // the data pointer or size. This prevents a recursive call to
2103 // the callback function if it calls EplObdGetEntry().
2104 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
2105 if ( (pSubEntry->m_Type == kEplObdTypVString) ||
2106 (pSubEntry->m_Type == kEplObdTypDomain) ||
2107 (pSubEntry->m_Type == kEplObdTypOString))
2109 if (pSubEntry->m_Type == kEplObdTypVString)
2111 // reserve one byte for 0-termination
2112 // -as ObdSize -= 1;
2116 // fill out new arg-struct
2117 MemVStringDomain.m_DownloadSize = Size_p;
2118 MemVStringDomain.m_ObjSize = ObdSize;
2119 MemVStringDomain.m_pData = pDstData;
2121 pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
2122 pCbParam_p->m_pArg = &MemVStringDomain;
2123 // call user callback
2124 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
2125 pObdEntry->m_fpCallback, pCbParam_p);
2126 if (Ret != kEplSuccessful)
2131 // write back new settings
2132 pCurrData = pSubEntry->m_pCurrent;
2133 if ((pSubEntry->m_Type == kEplObdTypVString)
2134 ||(pSubEntry->m_Type == kEplObdTypOString))
2136 ((tEplObdVString MEM*) pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
2137 ((tEplObdVString MEM*) pCurrData)->m_pString = MemVStringDomain.m_pData;
2139 else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
2141 ((tEplObdVarEntry MEM*) pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
2142 ((tEplObdVarEntry MEM*) pCurrData)->m_pData = (void MEM*) MemVStringDomain.m_pData;
2145 // Because object size and object pointer are
2146 // adapted by user callback function, re-read
2148 ObdSize = MemVStringDomain.m_ObjSize;
2149 pDstData = (void MEM*) MemVStringDomain.m_pData;
2151 #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
2153 // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
2154 // -as 16.11.04 CbParam.m_pArg = &ObdSize;
2155 // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p;
2156 pCbParam_p->m_pArg = &ObdSize;
2157 pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
2158 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
2159 pObdEntry->m_fpCallback, pCbParam_p);
2160 if (Ret != kEplSuccessful)
2165 if (Size_p > ObdSize)
2167 Ret = kEplObdValueLengthError;
2171 if (pSubEntry->m_Type == kEplObdTypVString)
2173 if (((char MEM*) pSrcData_p)[Size_p - 1] == '\0')
2174 { // last byte of source string contains null character
2176 // reserve one byte in destination for 0-termination
2179 else if (Size_p >= ObdSize)
2180 { // source string is not 0-terminated
2181 // and destination buffer is too short
2182 Ret = kEplObdValueLengthError;
2187 Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
2188 if (Ret != kEplSuccessful)
2193 if ((fEntryNumerical != FALSE)
2194 && (Size_p != ObdSize))
2196 // type is numerical, therefor size has to fit, but it does not.
2197 Ret = kEplObdValueLengthError;
2201 // use given size, because non-numerical objects can be written with shorter values
2204 // set output parameters
2205 *pObdSize_p = ObdSize;
2206 *ppObdEntry_p = pObdEntry;
2207 *ppSubEntry_p = pSubEntry;
2208 *ppDstData_p = pDstData;
2210 // all checks are done
2211 // the caller may now convert the numerial source value to platform byte order in a temporary buffer
2220 //---------------------------------------------------------------------------
2222 // Function: EplObdWriteEntryPost()
2224 // Description: Function finishes write of data to an OBD entry. Strings
2225 // are stored with added '\0' character.
2227 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
2228 // uiIndex_p = Index of the OD entry
2229 // uiSubIndex_p = Subindex of the OD Entry
2230 // pSrcData_p = Pointer to the data to write
2231 // Size_p = Size of the data in Byte
2233 // Return: tEplKernel = Errorcode
2238 //---------------------------------------------------------------------------
2240 static tEplKernel PUBLIC EplObdWriteEntryPost (EPL_MCO_DECL_INSTANCE_PTR_
2241 tEplObdEntryPtr pObdEntry_p,
2242 tEplObdSubEntryPtr pSubEntry_p,
2243 tEplObdCbParam MEM* pCbParam_p,
2246 tEplObdSize ObdSize_p)
2252 // caller converted the source value to platform byte order
2253 // now the range of the value may be checked
2255 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2258 Ret = EplObdCheckObjectRange (pSubEntry_p, pSrcData_p);
2259 if (Ret != kEplSuccessful)
2266 // now call user callback function to check value
2267 // write address of source data to structure of callback parameters
2268 // so callback function can check this data
2269 pCbParam_p->m_pArg = pSrcData_p;
2270 pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
2271 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
2272 pObdEntry_p->m_fpCallback, pCbParam_p);
2273 if (Ret != kEplSuccessful)
2278 // copy object data to OBD
2279 EPL_MEMCPY (pDstData_p, pSrcData_p, ObdSize_p);
2281 // terminate string with 0
2282 if (pSubEntry_p->m_Type == kEplObdTypVString)
2284 ((char MEM*) pDstData_p)[ObdSize_p] = '\0';
2287 // write address of destination to structure of callback parameters
2288 // so callback function can change data subsequently
2289 pCbParam_p->m_pArg = pDstData_p;
2290 pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
2291 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
2292 pObdEntry_p->m_fpCallback, pCbParam_p);
2301 //---------------------------------------------------------------------------
2303 // Function: EplObdGetObjectSize()
2305 // Description: function to get size of object
2306 // The function determines if an object type an fixed data type (BYTE, WORD, ...)
2307 // or non fixed object (string, domain). This information is used to decide
2308 // if download data are stored temporary or not. For objects with fixed data length
2309 // and types a value range checking can process.
2310 // For strings the function returns the whole object size not the
2311 // length of string.
2313 // Parameters: pSubIndexEntry_p
2315 // Return: tEplObdSize
2319 //---------------------------------------------------------------------------
2321 static tEplObdSize EplObdGetObjectSize (tEplObdSubEntryPtr pSubIndexEntry_p)
2324 tEplObdSize DataSize = 0;
2327 switch (pSubIndexEntry_p->m_Type)
2329 // -----------------------------------------------------------------
2330 case kEplObdTypBool:
2335 // -----------------------------------------------------------------
2336 // ObdTypes which has to be check because numerical values
2337 case kEplObdTypInt8:
2338 DataSize = sizeof (tEplObdInteger8);
2341 // -----------------------------------------------------------------
2342 case kEplObdTypUInt8:
2343 DataSize = sizeof (tEplObdUnsigned8);
2346 // -----------------------------------------------------------------
2347 case kEplObdTypInt16:
2348 DataSize = sizeof (tEplObdInteger16);
2351 // -----------------------------------------------------------------
2352 case kEplObdTypUInt16:
2353 DataSize = sizeof (tEplObdUnsigned16);
2356 // -----------------------------------------------------------------
2357 case kEplObdTypInt32:
2358 DataSize = sizeof (tEplObdInteger32);
2361 // -----------------------------------------------------------------
2362 case kEplObdTypUInt32:
2363 DataSize = sizeof (tEplObdUnsigned32);
2366 // -----------------------------------------------------------------
2367 case kEplObdTypReal32:
2368 DataSize = sizeof (tEplObdReal32);
2371 // -----------------------------------------------------------------
2372 // ObdTypes which has to be not checked because not NUM values
2373 case kEplObdTypDomain:
2375 pData = (void *) pSubIndexEntry_p->m_pCurrent;
2376 if ((void MEM*) pData != (void MEM*) NULL)
2378 DataSize = ((tEplObdVarEntry MEM*) pData)->m_Size;
2382 // -----------------------------------------------------------------
2383 case kEplObdTypVString:
2384 //case kEplObdTypUString:
2386 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
2387 // then the current pointer is always NULL. The function
2388 // returns the length of default string.
2389 pData = (void *) pSubIndexEntry_p->m_pCurrent;
2390 if ((void MEM*) pData != (void MEM*) NULL)
2392 // The max. size of strings defined by STRING-Macro is stored in
2393 // tEplObdVString of current value.
2394 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2395 DataSize = ((tEplObdVString MEM*) pData)->m_Size;
2399 // The current position is not decleared. The string
2400 // is located in ROM, therefor use default pointer.
2401 pData = (void *) pSubIndexEntry_p->m_pDefault;
2402 if ((CONST void ROM*) pData != (CONST void ROM*) NULL)
2404 // The max. size of strings defined by STRING-Macro is stored in
2405 // tEplObdVString of default value.
2406 DataSize = ((CONST tEplObdVString ROM*) pData)->m_Size;
2412 // -----------------------------------------------------------------
2413 case kEplObdTypOString:
2415 pData = (void *) pSubIndexEntry_p->m_pCurrent;
2416 if ((void MEM*) pData != (void MEM*) NULL)
2418 // The max. size of strings defined by STRING-Macro is stored in
2419 // tEplObdVString of current value.
2420 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2421 DataSize = ((tEplObdOString MEM*) pData)->m_Size;
2425 // The current position is not decleared. The string
2426 // is located in ROM, therefor use default pointer.
2427 pData = (void *) pSubIndexEntry_p->m_pDefault;
2428 if ((CONST void ROM*) pData != (CONST void ROM*) NULL)
2430 // The max. size of strings defined by STRING-Macro is stored in
2431 // tEplObdVString of default value.
2432 DataSize = ((CONST tEplObdOString ROM*) pData)->m_Size;
2437 // -----------------------------------------------------------------
2438 case kEplObdTypInt24:
2439 case kEplObdTypUInt24:
2445 // -----------------------------------------------------------------
2446 case kEplObdTypInt40:
2447 case kEplObdTypUInt40:
2452 // -----------------------------------------------------------------
2453 case kEplObdTypInt48:
2454 case kEplObdTypUInt48:
2459 // -----------------------------------------------------------------
2460 case kEplObdTypInt56:
2461 case kEplObdTypUInt56:
2466 // -----------------------------------------------------------------
2467 case kEplObdTypInt64:
2468 case kEplObdTypUInt64:
2469 case kEplObdTypReal64:
2474 // -----------------------------------------------------------------
2475 case kEplObdTypTimeOfDay:
2476 case kEplObdTypTimeDiff:
2481 // -----------------------------------------------------------------
2489 //---------------------------------------------------------------------------
2491 // Function: EplObdGetObjectDefaultPtr()
2493 // Description: function to get the default pointer (type specific)
2495 // Parameters: pSubIndexEntry_p = pointer to subindex structure
2497 // Returns: (void *) = pointer to default value
2501 //---------------------------------------------------------------------------
2503 static void * EplObdGetObjectDefaultPtr (tEplObdSubEntryPtr pSubIndexEntry_p)
2509 ASSERTMSG (pSubIndexEntry_p != NULL, "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
2511 // get address to default data from default pointer
2512 pDefault = pSubIndexEntry_p->m_pDefault;
2513 if (pDefault != NULL)
2515 // there are some special types, whose default pointer always is NULL or has to get from other structure
2516 // get type from subindex structure
2517 Type = pSubIndexEntry_p->m_Type;
2519 // check if object type is a string value
2520 if ((Type == kEplObdTypVString) /* ||
2521 (Type == kEplObdTypUString) */ )
2524 // EPL_OBD_SUBINDEX_RAM_VSTRING
2525 // tEplObdSize m_Size; --> size of default string
2526 // char * m_pDefString; --> pointer to default string
2527 // char * m_pString; --> pointer to string in RAM
2529 pDefault = (void *) ((tEplObdVString *) pDefault)->m_pString;
2531 else if(Type == kEplObdTypOString)
2533 pDefault = (void *) ((tEplObdOString *) pDefault)->m_pString;
2542 //---------------------------------------------------------------------------
2544 // Function: EplObdGetVarEntry()
2546 // Description: gets a variable entry of an object
2548 // Parameters: pSubindexEntry_p
2551 // Return: tCopKernel
2555 //---------------------------------------------------------------------------
2557 static tEplKernel EplObdGetVarEntry (
2558 tEplObdSubEntryPtr pSubindexEntry_p,
2559 tEplObdVarEntry MEM** ppVarEntry_p)
2562 tEplKernel Ret = kEplObdVarEntryNotExist;
2564 ASSERT (ppVarEntry_p != NULL); // is not allowed to be NULL
2565 ASSERT (pSubindexEntry_p != NULL);
2567 // check VAR-Flag - only this object points to variables
2568 if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0)
2570 // check if object is an array
2571 if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0)
2573 *ppVarEntry_p = &((tEplObdVarEntry MEM*) pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
2577 *ppVarEntry_p = (tEplObdVarEntry MEM*) pSubindexEntry_p->m_pCurrent;
2580 Ret = kEplSuccessful;
2587 //---------------------------------------------------------------------------
2589 // Function: EplObdGetEntry()
2591 // Description: gets a index entry from OD
2593 // Parameters: uiIndex_p = Index number
2594 // uiSubindex_p = Subindex number
2595 // ppObdEntry_p = pointer to the pointer to the entry
2596 // ppObdSubEntry_p = pointer to the pointer to the subentry
2598 // Return: tEplKernel
2603 //---------------------------------------------------------------------------
2605 static tEplKernel EplObdGetEntry (EPL_MCO_DECL_INSTANCE_PTR_
2606 unsigned int uiIndex_p,
2607 unsigned int uiSubindex_p,
2608 tEplObdEntryPtr* ppObdEntry_p,
2609 tEplObdSubEntryPtr* ppObdSubEntry_p)
2612 tEplObdEntryPtr pObdEntry;
2613 tEplObdCbParam MEM CbParam;
2616 // check for all API function if instance is valid
2617 EPL_MCO_CHECK_INSTANCE_STATE ();
2619 //------------------------------------------------------------------------
2620 // get address of entry of index
2621 Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), uiIndex_p, &pObdEntry);
2622 if (Ret != kEplSuccessful)
2627 //------------------------------------------------------------------------
2628 // get address of entry of subindex
2629 Ret = EplObdGetSubindexIntern (pObdEntry, uiSubindex_p, ppObdSubEntry_p);
2630 if (Ret != kEplSuccessful)
2635 //------------------------------------------------------------------------
2636 // call callback function to inform user/stack that an object will be searched
2637 // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
2638 CbParam.m_uiIndex = uiIndex_p;
2639 CbParam.m_uiSubIndex = uiSubindex_p;
2640 CbParam.m_pArg = NULL;
2641 CbParam.m_ObdEvent = kEplObdEvCheckExist;
2642 Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_
2643 pObdEntry->m_fpCallback, &CbParam);
2644 if (Ret != kEplSuccessful)
2646 Ret = kEplObdIndexNotExist;
2650 //------------------------------------------------------------------------
2651 // it is allowed to set ppObdEntry_p to NULL
2652 // if so, no address will be written to calling function
2653 if (ppObdEntry_p != NULL)
2655 *ppObdEntry_p = pObdEntry;
2663 //---------------------------------------------------------------------------
2665 // Function: EplObdGetObjectCurrentPtr()
2667 // Description: function to get Current pointer (type specific)
2669 // Parameters: pSubIndexEntry_p
2671 // Return: void MEM*
2675 //---------------------------------------------------------------------------
2677 static void MEM* EplObdGetObjectCurrentPtr (tEplObdSubEntryPtr pSubIndexEntry_p)
2681 unsigned int uiArrayIndex;
2684 pData = pSubIndexEntry_p->m_pCurrent;
2686 // check if constant object
2689 // check if object is an array
2690 if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0)
2692 // calculate correct data pointer
2693 uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
2694 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0)
2696 Size = sizeof (tEplObdVarEntry);
2700 Size = EplObdGetObjectSize (pSubIndexEntry_p);
2702 pData = ((BYTE MEM*) pData) + (Size * uiArrayIndex);
2705 // check if VarEntry
2706 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0)
2708 // The data pointer is stored in VarEntry->pData
2709 pData = ((tEplObdVarEntry MEM*) pData)->m_pData;
2712 // the default pointer is stored for strings in tEplObdVString
2713 else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* ||
2714 (pSubIndexEntry_p->m_Type == kEplObdTypUString) */ )
2716 pData = (void MEM*) ((tEplObdVString MEM*) pData)->m_pString;
2718 else if (pSubIndexEntry_p->m_Type == kEplObdTypOString)
2720 pData = (void MEM*) ((tEplObdOString MEM*) pData)->m_pString;
2729 //---------------------------------------------------------------------------
2731 // Function: EplObdGetIndexIntern()
2733 // Description: gets a index entry from OD
2735 // Parameters: pInitParam_p
2739 // Return: tEplKernel
2743 //---------------------------------------------------------------------------
2745 static tEplKernel EplObdGetIndexIntern (
2746 tEplObdInitParam MEM* pInitParam_p,
2747 unsigned int uiIndex_p,
2748 tEplObdEntryPtr* ppObdEntry_p)
2751 tEplObdEntryPtr pObdEntry;
2753 unsigned int uiIndex;
2755 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2759 // if user OD is used then objekts also has to be searched in user OD
2760 // there is less code need if we do this in a loop
2765 ASSERTMSG (ppObdEntry_p != NULL, "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
2767 Ret = kEplObdIndexNotExist;
2769 // get start address of OD part
2770 // start address depends on object index because
2771 // object dictionary is divided in 3 parts
2772 if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000))
2774 pObdEntry = pInitParam_p->m_pPart;
2776 else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000))
2778 pObdEntry = pInitParam_p->m_pManufacturerPart;
2781 // index range 0xA000 to 0xFFFF is reserved for DSP-405
2782 // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
2783 // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
2784 // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
2785 // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
2787 #if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
2788 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
2790 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
2793 pObdEntry = pInitParam_p->m_pDevicePart;
2797 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2799 // if index does not match in static OD then index only has to be searched in user OD
2802 // begin from first entry of user OD part
2803 pObdEntry = pInitParam_p->m_pUserPart;
2805 // no user OD is available
2806 if (pObdEntry == NULL)
2811 // loop must only run once
2820 // no user OD is available
2821 // so other object can be found in OD
2824 Ret = kEplObdIllegalPart;
2831 // The end of Index table is marked with m_uiIndex = 0xFFFF.
2832 // If this function will be called with wIndex_p = 0xFFFF, entry
2833 // should not be found. Therefor it is important to use
2834 // while{} instead of do{}while !!!
2836 // get first index of index table
2837 uiIndex = pObdEntry->m_uiIndex;
2839 // search Index in OD part
2840 while (uiIndex != EPL_OBD_TABLE_INDEX_END)
2842 // go to the end of this function if index is found
2843 if (uiIndex_p == uiIndex)
2845 // write address of OD entry to calling function
2846 *ppObdEntry_p = pObdEntry;
2847 Ret = kEplSuccessful;
2851 // objects are sorted in OD
2852 // if the current index in OD is greater than the index which is to search then break loop
2853 // in this case user OD has to be search too
2854 if (uiIndex_p < uiIndex)
2859 // next entry in index table
2862 // get next index of index table
2863 uiIndex = pObdEntry->m_uiIndex;
2866 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2868 // begin from first entry of user OD part
2869 pObdEntry = pInitParam_p->m_pUserPart;
2871 // no user OD is available
2872 if (pObdEntry == NULL)
2877 // switch next loop for user OD
2880 } while (nLoop > 0);
2884 // in this line Index was not found
2893 //---------------------------------------------------------------------------
2895 // Function: EplObdGetSubindexIntern()
2897 // Description: gets a subindex entry from a index entry
2899 // Parameters: pObdEntry_p
2903 // Return: tEplKernel
2907 //---------------------------------------------------------------------------
2909 static tEplKernel EplObdGetSubindexIntern (
2910 tEplObdEntryPtr pObdEntry_p,
2911 unsigned int uiSubIndex_p,
2912 tEplObdSubEntryPtr* ppObdSubEntry_p)
2915 tEplObdSubEntryPtr pSubEntry;
2916 unsigned int nSubIndexCount;
2919 ASSERTMSG (pObdEntry_p != NULL, "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
2920 ASSERTMSG (ppObdSubEntry_p != NULL, "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
2922 Ret = kEplObdSubindexNotExist;
2924 // get start address of subindex table and count of subindices
2925 pSubEntry = pObdEntry_p->m_pSubIndex;
2926 nSubIndexCount = pObdEntry_p->m_uiCount;
2927 ASSERTMSG ((pSubEntry != NULL) && (nSubIndexCount > 0),
2928 "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
2930 // search subindex in subindex table
2931 while (nSubIndexCount > 0)
2933 // check if array is found
2934 if ((pSubEntry->m_Access & kEplObdAccArray) != 0)
2936 // check if subindex is in range
2937 if (uiSubIndex_p < pObdEntry_p->m_uiCount)
2939 // update subindex number (subindex entry of an array is always in RAM !!!)
2940 pSubEntry->m_uiSubIndex = uiSubIndex_p;
2941 *ppObdSubEntry_p = pSubEntry;
2942 Ret = kEplSuccessful;
2947 // go to the end of this function if subindex is found
2948 else if (uiSubIndex_p == pSubEntry->m_uiSubIndex)
2950 *ppObdSubEntry_p = pSubEntry;
2951 Ret = kEplSuccessful;
2955 // objects are sorted in OD
2956 // if the current subindex in OD is greater than the subindex which is to search then break loop
2957 // in this case user OD has to be search too
2958 if (uiSubIndex_p < pSubEntry->m_uiSubIndex)
2967 // in this line SubIndex was not fount
2976 //---------------------------------------------------------------------------
2978 // Function: EplObdSetStoreLoadObjCallback()
2980 // Description: function set address to callbackfunction for command Store and Load
2982 // Parameters: fpCallback_p
2984 // Return: tEplKernel
2988 //---------------------------------------------------------------------------
2989 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2990 EPLDLLEXPORT tEplKernel PUBLIC EplObdSetStoreLoadObjCallback (EPL_MCO_DECL_INSTANCE_PTR_
2991 tEplObdStoreLoadObjCallback fpCallback_p)
2994 EPL_MCO_CHECK_INSTANCE_STATE ();
2996 // set new address of callback function
2997 EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) = fpCallback_p;
2999 return kEplSuccessful;
3002 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3005 //---------------------------------------------------------------------------
3007 // Function: EplObdAccessOdPartIntern()
3009 // Description: runs through OD and executes a job
3011 // Parameters: CurrentOdPart_p
3013 // Direction_p = what is to do (load values from flash or EEPROM, store, ...)
3015 // Return: tEplKernel
3019 //---------------------------------------------------------------------------
3021 static tEplKernel EplObdAccessOdPartIntern (EPL_MCO_DECL_INSTANCE_PTR_
3022 tEplObdPart CurrentOdPart_p,
3023 tEplObdEntryPtr pObdEnty_p,
3024 tEplObdDir Direction_p)
3027 tEplObdSubEntryPtr pSubIndex;
3028 unsigned int nSubIndexCount;
3029 tEplObdAccess Access;
3032 tEplObdSize ObjSize;
3034 tEplObdCbStoreParam MEM CbStore;
3035 tEplObdVarEntry MEM* pVarEntry;
3037 ASSERT (pObdEnty_p != NULL);
3039 Ret = kEplSuccessful;
3041 // prepare structure for STORE RESTORE callback function
3042 CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p;
3043 CbStore.m_pData = NULL;
3044 CbStore.m_ObjSize = 0;
3046 // command of first action depends on direction to access
3047 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3048 if (Direction_p == kEplObdDirLoad)
3050 CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead;
3052 // call callback function for previous command
3053 Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_
3055 if (Ret != kEplSuccessful)
3060 // set command for index and subindex loop
3061 CbStore.m_bCommand = (BYTE) kEplObdCommReadObj;
3063 else if (Direction_p == kEplObdDirStore)
3065 CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite;
3067 // call callback function for previous command
3068 Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_
3070 if (Ret != kEplSuccessful)
3075 // set command for index and subindex loop
3076 CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj;
3078 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3080 // we should not restore the OD values here
3081 // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
3082 if (Direction_p != kEplObdDirRestore)
3084 // walk through OD part till end is found
3085 while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END)
3087 // get address to subindex table and count of subindices
3088 pSubIndex = pObdEnty_p->m_pSubIndex;
3089 nSubIndexCount = pObdEnty_p->m_uiCount;
3090 ASSERT ((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL
3092 // walk through subindex table till all subinices were restored
3093 while (nSubIndexCount != 0)
3095 Access = (tEplObdAccess) pSubIndex->m_Access;
3097 // get pointer to current and default data
3098 pDefault = EplObdGetObjectDefaultPtr (pSubIndex);
3099 pDstData = EplObdGetObjectCurrentPtr (pSubIndex);
3101 // NOTE (for kEplObdTypVString):
3102 // The function returnes the max. number of bytes for a
3104 // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
3105 ObjSize = EplObdGetObjectSize (pSubIndex);
3107 // switch direction of OD access
3108 switch (Direction_p)
3110 // --------------------------------------------------------------------------
3111 // VarEntry structures has to be initialized
3112 case kEplObdDirInit:
3114 // If VAR-Flag is set, m_pCurrent means not address of data
3115 // but address of tEplObdVarEntry. Address of data has to be get from
3117 if ((Access & kEplObdAccVar) != 0)
3119 EplObdGetVarEntry (pSubIndex, &pVarEntry);
3120 EplObdInitVarEntry (pVarEntry, pSubIndex->m_Type, ObjSize);
3122 if ((Access & kEplObdAccArray) == 0)
3124 EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
3128 EplObdInitVarEntry ((tEplObdVarEntry MEM*) (((BYTE MEM*) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
3129 pSubIndex->m_Type, ObjSize);
3132 // at this time no application variable is defined !!!
3133 // therefore data can not be copied.
3136 else if (pSubIndex->m_Type == kEplObdTypVString)
3138 // If pointer m_pCurrent is not equal to NULL then the
3139 // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
3140 // pointer points to struct tEplObdVString located in MEM.
3141 // The element size includes the max. number of
3142 // bytes. The element m_pString includes the pointer
3143 // to string in MEM. The memory location of default string
3144 // must be copied to memory location of current string.
3146 pDstData = pSubIndex->m_pCurrent;
3147 if (pDstData != NULL)
3149 // 08-dec-2004: code optimization !!!
3150 // entries ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString
3151 // and ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
3152 // twice. thats not necessary!
3154 // For copying data we have to set the destination pointer to the real RAM string. This
3155 // pointer to RAM string is located in default string info structure. (translated r.d.)
3156 pDstData = (void MEM*) ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString;
3157 ObjSize = ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size;
3160 ((tEplObdVString MEM*) pSubIndex->m_pCurrent)->m_pString = pDstData;
3161 ((tEplObdVString MEM*) pSubIndex->m_pCurrent)->m_Size = ObjSize;
3165 else if(pSubIndex->m_Type == kEplObdTypOString)
3167 pDstData = pSubIndex->m_pCurrent;
3168 if (pDstData != NULL)
3170 // 08-dec-2004: code optimization !!!
3171 // entries ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString
3172 // and ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
3173 // twice. thats not necessary!
3175 // For copying data we have to set the destination pointer to the real RAM string. This
3176 // pointer to RAM string is located in default string info structure. (translated r.d.)
3177 pDstData = (void MEM*) ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString;
3178 ObjSize = ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size;
3181 ((tEplObdOString MEM*) pSubIndex->m_pCurrent)->m_pString = pDstData;
3182 ((tEplObdOString MEM*) pSubIndex->m_pCurrent)->m_Size = ObjSize;
3188 // no break !! because copy of data has to done too.
3190 // --------------------------------------------------------------------------
3191 // all objects has to be restored with default values
3192 case kEplObdDirRestore:
3194 // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
3195 // is replaced to function ObdCopyObjectData() with a new parameter.
3198 // restore object data for init phase
3199 EplObdCopyObjectData (pDstData, pDefault, ObjSize, pSubIndex->m_Type);
3202 // --------------------------------------------------------------------------
3203 // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
3204 case kEplObdDirLoad:
3206 // restore object data for init phase
3207 EplObdCopyObjectData (pDstData, pDefault, ObjSize, pSubIndex->m_Type);
3209 // no break !! because callback function has to be called too.
3211 // --------------------------------------------------------------------------
3212 // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
3213 case kEplObdDirStore:
3215 // when attribute kEplObdAccStore is set, then call callback function
3216 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3217 if ((Access & kEplObdAccStore) != 0)
3219 // fill out data pointer and size of data
3220 CbStore.m_pData = pDstData;
3221 CbStore.m_ObjSize = ObjSize;
3223 // call callback function for read or write object
3224 Ret = ObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_
3226 if (Ret != kEplSuccessful)
3231 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3235 // --------------------------------------------------------------------------
3236 // if OD Builder key has to be checked no access to subindex and data should be made
3237 case kEplObdDirOBKCheck:
3239 // no break !! because we want to break the second loop too.
3242 // --------------------------------------------------------------------------
3243 // unknown Direction
3246 // so we can break the second loop earler
3253 // next subindex entry
3254 if ((Access & kEplObdAccArray) == 0)
3257 if ((nSubIndexCount > 0)
3258 && ((pSubIndex->m_Access & kEplObdAccArray) != 0))
3260 // next subindex points to an array
3261 // reset subindex number
3262 pSubIndex->m_uiSubIndex = 1;
3267 if (nSubIndexCount > 0)
3269 // next subindex points to an array
3270 // increment subindex number
3271 pSubIndex->m_uiSubIndex++;
3281 // -----------------------------------------------------------------------------------------
3282 // command of last action depends on direction to access
3283 if (Direction_p == kEplObdDirOBKCheck)
3288 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3291 if (Direction_p == kEplObdDirLoad)
3293 CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead;
3295 else if (Direction_p == kEplObdDirStore)
3297 CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite;
3299 else if (Direction_p == kEplObdDirRestore)
3301 CbStore.m_bCommand = (BYTE) kEplObdCommClear;
3308 // call callback function for last command
3309 Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_
3312 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3323 // ----------------------------------------------------------------------------
3324 // Function: EplObdCopyObjectData()
3326 // Description: checks pointers to object data and copy them from source to destination
3328 // Parameters: pDstData_p = destination pointer
3329 // pSrcData_p = source pointer
3330 // ObjSize_p = size of object
3333 // Returns: tEplKernel = error code
3334 // ----------------------------------------------------------------------------
3336 static void EplObdCopyObjectData (
3337 void MEM* pDstData_p,
3339 tEplObdSize ObjSize_p,
3340 tEplObdType ObjType_p)
3344 tEplObdSize StrSize = 0;
3347 // it is allowed to set default and current address to NULL (nothing to copy)
3348 if (pDstData_p != NULL)
3351 if (ObjType_p == kEplObdTypVString)
3353 // The function calculates the really number of characters of string. The
3354 // object entry size can be bigger as string size of default string.
3355 // The '\0'-termination is included. A string with no characters has a
3357 StrSize = EplObdGetStrLen ((void *) pSrcData_p, ObjSize_p, kEplObdTypVString);
3359 // If the string length is greater than or equal to the entry size in OD then only copy
3360 // entry size - 1 and always set the '\0'-termination.
3361 if (StrSize >= ObjSize_p)
3363 StrSize = ObjSize_p - 1;
3367 if (pSrcData_p != NULL)
3370 EPL_MEMCPY (pDstData_p, pSrcData_p, ObjSize_p);
3372 if (ObjType_p == kEplObdTypVString)
3374 ((char MEM*) pDstData_p)[StrSize] = '\0';
3382 //---------------------------------------------------------------------------
3384 // Function: EplObdIsNumericalIntern()
3386 // Description: function checks if a entry is numerical or not
3389 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
3390 // uiIndex_p = Index
3391 // uiSubIndex_p = Subindex
3392 // pfEntryNumerical_p = pointer to BOOL for returnvalue
3393 // -> TRUE if entry a numerical value
3394 // -> FALSE if entry not a numerical value
3396 // Return: tEplKernel = Errorcode
3400 //---------------------------------------------------------------------------
3401 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
3402 BOOL* pfEntryNumerical_p)
3404 tEplKernel Ret = kEplSuccessful;
3408 if((pObdSubEntry_p->m_Type == kEplObdTypVString)
3409 || (pObdSubEntry_p->m_Type == kEplObdTypOString)
3410 || (pObdSubEntry_p->m_Type == kEplObdTypDomain))
3411 { // not numerical types
3412 *pfEntryNumerical_p = FALSE;
3415 { // numerical types
3416 *pfEntryNumerical_p = TRUE;
3424 // -------------------------------------------------------------------------
3425 // function to classify object type (fixed/non fixed)
3426 // -------------------------------------------------------------------------
3428 // ----------------------------------------------------------------------------
3429 // Function: EplObdCallStoreCallback()
3431 // Description: checks address to callback function and calles it when unequal
3434 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
3435 // pCbStoreParam_p = address to callback parameters
3437 // Returns: tEplKernel = error code
3438 // ----------------------------------------------------------------------------
3439 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3440 static tEplKernel EplObdCallStoreCallback (EPL_MCO_DECL_INSTANCE_PTR_
3441 tEplObdCbStoreParam MEM* pCbStoreParam_p)
3444 tEplKernel Ret = kEplSuccessful;
3446 ASSERT (pCbStoreParam_p != NULL);
3448 // check if function pointer is NULL - if so, no callback should be called
3449 if (EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) != NULL)
3451 Ret = EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) (EPL_MCO_INSTANCE_PARAM_IDX_()
3458 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3459 //---------------------------------------------------------------------------
3461 // Function: EplObdGetObjectDataPtrIntern()
3463 // Description: Function gets the data pointer of an object.
3464 // It returnes the current data pointer. But if object is an
3465 // constant object it returnes the default pointer.
3467 // Parameters: pSubindexEntry_p = pointer to subindex entry
3469 // Return: void * = pointer to object data
3473 //---------------------------------------------------------------------------
3475 void * EplObdGetObjectDataPtrIntern (tEplObdSubEntryPtr pSubindexEntry_p)
3479 tEplObdAccess Access;
3481 ASSERTMSG (pSubindexEntry_p != NULL, "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
3483 // there are are some objects whose data pointer has to get from other structure
3484 // get access type for this object
3485 Access = pSubindexEntry_p->m_Access;
3487 // If object has access type = const,
3488 // for data only exists default values.
3489 if ((Access & kEplObdAccConst) != 0)
3491 // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
3492 pData = ((void *) EplObdGetObjectDefaultPtr (pSubindexEntry_p));
3496 // The pointer to current value can be received from ObdGetObjectCurrentPtr()
3497 pData = ((void *) EplObdGetObjectCurrentPtr (pSubindexEntry_p));
3503 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)