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 BYTE 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 EPLDLLEXPORT 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 EPLDLLEXPORT 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 EPLDLLEXPORT 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 EPLDLLEXPORT tEplKernel EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
338 unsigned int uiSubIndex_p,
344 tEplObdEntryPtr pObdEntry;
345 tEplObdSubEntryPtr pSubEntry;
346 tEplObdCbParam CbParam;
350 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
356 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
357 if (Ret != kEplSuccessful) {
361 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
364 &CbParam, pSrcData_p, pDstData, ObdSize);
365 if (Ret != kEplSuccessful) {
375 //---------------------------------------------------------------------------
377 // Function: EplObdReadEntry()
379 // Description: The function reads an object entry. The application
380 // can always read the data even if attrib kEplObdAccRead
381 // is not set. The attrib is only checked up for SDO transfer.
383 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
384 // uiIndex_p = Index oof the OD entry to read
385 // uiSubIndex_p = Subindex to read
386 // pDstData_p = pointer to the buffer for data
387 // Offset_p = offset in data for read access
388 // pSize_p = IN: Size of the buffer
389 // OUT: number of readed Bytes
391 // Return: tEplKernel
395 //---------------------------------------------------------------------------
397 EPLDLLEXPORT tEplKernel EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
398 unsigned int uiSubIndex_p,
400 tEplObdSize *pSize_p)
404 tEplObdEntryPtr pObdEntry;
405 tEplObdSubEntryPtr pSubEntry;
406 tEplObdCbParam CbParam;
410 // check for all API function if instance is valid
411 EPL_MCO_CHECK_INSTANCE_STATE();
413 ASSERT(pDstData_p != NULL);
414 ASSERT(pSize_p != NULL);
416 // get address of index and subindex entry
417 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
418 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
419 if (Ret != kEplSuccessful) {
422 // get pointer to object data
423 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
425 // check source pointer
426 if (pSrcData == NULL) {
427 Ret = kEplObdReadViolation;
430 //------------------------------------------------------------------------
431 // address of source data to structure of callback parameters
432 // so callback function can change this data before reading
433 CbParam.m_uiIndex = uiIndex_p;
434 CbParam.m_uiSubIndex = uiSubIndex_p;
435 CbParam.m_pArg = pSrcData;
436 CbParam.m_ObdEvent = kEplObdEvPreRead;
437 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
438 pObdEntry->m_fpCallback, &CbParam);
439 if (Ret != kEplSuccessful) {
442 // get size of data and check if application has reserved enough memory
443 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
444 // check if offset given and calc correct number of bytes to read
445 if (*pSize_p < ObdSize) {
446 Ret = kEplObdValueLengthError;
449 // read value from object
450 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
453 // write address of destination data to structure of callback parameters
454 // so callback function can change this data after reading
455 CbParam.m_pArg = pDstData_p;
456 CbParam.m_ObdEvent = kEplObdEvPostRead;
457 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
458 pObdEntry->m_fpCallback, &CbParam);
466 //---------------------------------------------------------------------------
468 // Function: EplObdAccessOdPart()
470 // Description: restores default values of one part of OD
472 // Parameters: ObdPart_p
475 // Return: tEplKernel
479 //---------------------------------------------------------------------------
481 EPLDLLEXPORT tEplKernel EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdPart ObdPart_p,
482 tEplObdDir Direction_p)
485 tEplKernel Ret = kEplSuccessful;
487 tEplObdEntryPtr pObdEntry;
489 // check for all API function if instance is valid
490 EPL_MCO_CHECK_INSTANCE_STATE();
492 // part always has to be unequal to NULL
493 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pPart);
494 ASSERTMSG(pObdEntry != NULL,
495 "EplObdAccessOdPart(): no OD part is defined!\n");
497 // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
501 if ((ObdPart_p & kEplObdPartGen) != 0) {
504 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
505 kEplObdPartGen, pObdEntry,
507 if (Ret != kEplSuccessful) {
511 // access to manufacturer part
512 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pManufacturerPart);
514 if (((ObdPart_p & kEplObdPartMan) != 0) && (pObdEntry != NULL)) {
517 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
518 kEplObdPartMan, pObdEntry,
520 if (Ret != kEplSuccessful) {
524 // access to device part
525 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pDevicePart);
527 if (((ObdPart_p & kEplObdPartDev) != 0) && (pObdEntry != NULL)) {
530 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
531 kEplObdPartDev, pObdEntry,
533 if (Ret != kEplSuccessful) {
537 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
539 // access to user part
540 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart);
542 if (((ObdPart_p & kEplObdPartUsr) != 0) && (pObdEntry != NULL)) {
545 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
547 pObdEntry, Direction_p);
548 if (Ret != kEplSuccessful) {
555 // no access to an OD part was done? illegal OD part was specified!
556 if (fPartFount == FALSE) {
557 Ret = kEplObdIllegalPart;
566 //---------------------------------------------------------------------------
568 // Function: EplObdDefineVar()
570 // Description: defines a variable in OD
572 // Parameters: pEplVarParam_p
574 // Return: tEplKernel
578 //---------------------------------------------------------------------------
580 EPLDLLEXPORT tEplKernel EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ tEplVarParam *pVarParam_p)
584 tEplObdVarEntry *pVarEntry;
585 tEplVarParamValid VarValid;
586 tEplObdSubEntryPtr pSubindexEntry;
588 // check for all API function if instance is valid
589 EPL_MCO_CHECK_INSTANCE_STATE();
591 ASSERT(pVarParam_p != NULL); // is not allowed to be NULL
593 // get address of subindex entry
594 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
595 pVarParam_p->m_uiIndex,
596 pVarParam_p->m_uiSubindex, NULL, &pSubindexEntry);
597 if (Ret != kEplSuccessful) {
601 Ret = EplObdGetVarEntry(pSubindexEntry, &pVarEntry);
602 if (Ret != kEplSuccessful) {
606 VarValid = pVarParam_p->m_ValidFlag;
608 // copy only this values, which valid flag is set
609 if ((VarValid & kVarValidSize) != 0) {
610 if (pSubindexEntry->m_Type != kEplObdTypDomain) {
611 tEplObdSize DataSize;
613 // check passed size parameter
614 DataSize = EplObdGetObjectSize(pSubindexEntry);
615 if (DataSize != pVarParam_p->m_Size) { // size of variable does not match
616 Ret = kEplObdValueLengthError;
619 } else { // size can be set only for objects of type DOMAIN
620 pVarEntry->m_Size = pVarParam_p->m_Size;
624 if ((VarValid & kVarValidData) != 0) {
625 pVarEntry->m_pData = pVarParam_p->m_pData;
628 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
630 if ((VarValid & kVarValidCallback) != 0)
632 pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
635 if ((VarValid & kVarValidArg) != 0)
637 pVarEntry->m_pArg = pVarParam_p->m_pArg;
642 // Ret is already set to kEplSuccessful from ObdGetVarIntern()
650 //---------------------------------------------------------------------------
652 // Function: EplObdGetObjectDataPtr()
654 // Description: It returnes the current data pointer. But if object is an
655 // constant object it returnes the default pointer.
657 // Parameters: uiIndex_p = Index of the entry
658 // uiSubindex_p = Subindex of the entry
660 // Return: void * = pointer to object data
664 //---------------------------------------------------------------------------
666 EPLDLLEXPORT void *EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
667 unsigned int uiSubIndex_p)
671 tEplObdEntryPtr pObdEntry;
672 tEplObdSubEntryPtr pObdSubEntry;
674 // get pointer to index structure
675 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
676 uiIndex_p, &pObdEntry);
677 if (Ret != kEplSuccessful) {
681 // get pointer to subindex structure
682 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
683 if (Ret != kEplSuccessful) {
688 pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
695 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
697 //---------------------------------------------------------------------------
699 // Function: EplObdRegisterUserOd()
701 // Description: function registers the user OD
703 // Parameters: pUserOd_p =pointer to user ODd
705 // Return: tEplKernel = errorcode
709 //---------------------------------------------------------------------------
710 EPLDLLEXPORT tEplKernel EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pUserOd_p)
713 EPL_MCO_CHECK_INSTANCE_STATE();
715 EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart) = pUserOd_p;
717 return kEplSuccessful;
723 //---------------------------------------------------------------------------
725 // Function: EplObdInitVarEntry()
727 // Description: function to initialize VarEntry dependened on object type
729 // Parameters: pVarEntry_p = pointer to var entry structure
730 // Type_p = object type
731 // ObdSize_p = size of object data
737 //---------------------------------------------------------------------------
739 EPLDLLEXPORT void EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdVarEntry *pVarEntry_p,
740 tEplObdType Type_p, tEplObdSize ObdSize_p)
743 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
745 // reset pointer to VAR callback and argument
746 pVarEntry_p->m_fpCallback = NULL;
747 pVarEntry_p->m_pArg = NULL;
752 // 10-dec-2004 r.d.: this function will not be used for strings
753 if ((Type_p == kEplObdTypDomain))
754 // (bType_p == kEplObdTypVString) /* ||
755 // (bType_p == kEplObdTypOString) ||
756 // (bType_p == kEplObdTypUString) */ )
758 // variables which are defined as DOMAIN or VSTRING should not point to
759 // trash object, because this trash object contains only 8 bytes. DOMAINS or
760 // STRINGS can be longer.
761 pVarEntry_p->m_pData = NULL;
762 pVarEntry_p->m_Size = 0;
764 // set address to variable data to trash object
765 // This prevents an access violation if user forgets to call EplObdDefineVar()
766 // for this variable but mappes it in a PDO.
767 pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
768 pVarEntry_p->m_Size = ObdSize_p;
773 //---------------------------------------------------------------------------
775 // Function: EplObdGetDataSize()
777 // Description: function to initialize VarEntry dependened on object type
779 // gets the data size of an object
780 // for string objects it returnes the string length
782 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
784 // uiSubIndex_p= Subindex
786 // Return: tEplObdSize
790 //---------------------------------------------------------------------------
791 EPLDLLEXPORT tEplObdSize EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
792 unsigned int uiSubIndex_p)
796 tEplObdEntryPtr pObdEntry;
797 tEplObdSubEntryPtr pObdSubEntry;
799 // get pointer to index structure
800 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
801 uiIndex_p, &pObdEntry);
802 if (Ret != kEplSuccessful) {
806 // get pointer to subindex structure
807 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
808 if (Ret != kEplSuccessful) {
813 ObdSize = EplObdGetDataSizeIntern(pObdSubEntry);
818 //---------------------------------------------------------------------------
820 // Function: EplObdGetNodeId()
822 // Description: function returns nodeid from entry 0x1F93
825 // Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
827 // Return: unsigned int = Node Id
831 //---------------------------------------------------------------------------
832 EPLDLLEXPORT unsigned int EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
839 ObdSize = sizeof(bNodeId);
840 Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
841 EPL_OBD_NODE_ID_INDEX,
842 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, &ObdSize);
843 if (Ret != kEplSuccessful) {
844 bNodeId = EPL_C_ADR_INVALID;
849 return (unsigned int)bNodeId;
853 //---------------------------------------------------------------------------
855 // Function: EplObdSetNodeId()
857 // Description: function sets nodeid in entry 0x1F93
860 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
861 // uiNodeId_p = Node Id to set
862 // NodeIdType_p= Type on which way the Node Id was set
864 // Return: tEplKernel = Errorcode
868 //---------------------------------------------------------------------------
869 EPLDLLEXPORT tEplKernel EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ unsigned int uiNodeId_p,
870 tEplObdNodeIdType NodeIdType_p)
878 if (uiNodeId_p == EPL_C_ADR_INVALID) {
879 Ret = kEplInvalidNodeId;
882 bNodeId = (BYTE) uiNodeId_p;
883 ObdSize = sizeof(BYTE);
884 // write NodeId to OD entry
885 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
886 EPL_OBD_NODE_ID_INDEX,
887 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, ObdSize);
888 if (Ret != kEplSuccessful) {
891 // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
892 switch (NodeIdType_p) {
894 case kEplObdNodeIdUnknown:
900 case kEplObdNodeIdSoftware:
906 case kEplObdNodeIdHardware:
917 } // end of switch (NodeIdType_p)
920 ObdSize = sizeof(fHwBool);
921 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
922 EPL_OBD_NODE_ID_INDEX,
923 EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
925 if (Ret != kEplSuccessful) {
933 //---------------------------------------------------------------------------
935 // Function: EplObdIsNumerical()
937 // Description: function checks if a entry is numerical or not
940 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
942 // uiSubIndex_p = Subindex
943 // pfEntryNumerical_p = pointer to BOOL for returnvalue
944 // -> TRUE if entry a numerical value
945 // -> FALSE if entry not a numerical value
947 // Return: tEplKernel = Errorcode
951 //---------------------------------------------------------------------------
952 EPLDLLEXPORT tEplKernel EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
953 unsigned int uiSubIndex_p,
954 BOOL *pfEntryNumerical_p)
957 tEplObdEntryPtr pObdEntry;
958 tEplObdSubEntryPtr pObdSubEntry;
960 // get pointer to index structure
961 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
962 uiIndex_p, &pObdEntry);
963 if (Ret != kEplSuccessful) {
966 // get pointer to subindex structure
967 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
968 if (Ret != kEplSuccessful) {
972 Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
979 //---------------------------------------------------------------------------
981 // Function: EplObdReadEntryToLe()
983 // Description: The function reads an object entry from the byteoder
984 // of the system to the little endian byteorder for numerical values.
985 // For other types a normal read will be processed. This is usefull for
986 // the PDO and SDO module. The application
987 // can always read the data even if attrib kEplObdAccRead
988 // is not set. The attrib is only checked up for SDO transfer.
990 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
991 // uiIndex_p = Index of the OD entry to read
992 // uiSubIndex_p = Subindex to read
993 // pDstData_p = pointer to the buffer for data
994 // Offset_p = offset in data for read access
995 // pSize_p = IN: Size of the buffer
996 // OUT: number of readed Bytes
998 // Return: tEplKernel
1002 //---------------------------------------------------------------------------
1003 EPLDLLEXPORT tEplKernel EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1004 unsigned int uiSubIndex_p,
1006 tEplObdSize *pSize_p)
1009 tEplObdEntryPtr pObdEntry;
1010 tEplObdSubEntryPtr pSubEntry;
1011 tEplObdCbParam CbParam;
1013 tEplObdSize ObdSize;
1015 // check for all API function if instance is valid
1016 EPL_MCO_CHECK_INSTANCE_STATE();
1018 ASSERT(pDstData_p != NULL);
1019 ASSERT(pSize_p != NULL);
1021 // get address of index and subindex entry
1022 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1023 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1024 if (Ret != kEplSuccessful) {
1027 // get pointer to object data
1028 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
1030 // check source pointer
1031 if (pSrcData == NULL) {
1032 Ret = kEplObdReadViolation;
1035 //------------------------------------------------------------------------
1036 // address of source data to structure of callback parameters
1037 // so callback function can change this data before reading
1038 CbParam.m_uiIndex = uiIndex_p;
1039 CbParam.m_uiSubIndex = uiSubIndex_p;
1040 CbParam.m_pArg = pSrcData;
1041 CbParam.m_ObdEvent = kEplObdEvPreRead;
1042 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1043 pObdEntry->m_fpCallback, &CbParam);
1044 if (Ret != kEplSuccessful) {
1047 // get size of data and check if application has reserved enough memory
1048 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
1049 // check if offset given and calc correct number of bytes to read
1050 if (*pSize_p < ObdSize) {
1051 Ret = kEplObdValueLengthError;
1054 // check if numerical type
1055 switch (pSubEntry->m_Type) {
1056 //-----------------------------------------------
1057 // types without ami
1058 case kEplObdTypVString:
1059 case kEplObdTypOString:
1060 case kEplObdTypDomain:
1063 // read value from object
1064 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
1068 //-----------------------------------------------
1069 // numerical type which needs ami-write
1070 // 8 bit or smaller values
1071 case kEplObdTypBool:
1072 case kEplObdTypInt8:
1073 case kEplObdTypUInt8:
1075 AmiSetByteToLe(pDstData_p, *((BYTE *) pSrcData));
1080 case kEplObdTypInt16:
1081 case kEplObdTypUInt16:
1083 AmiSetWordToLe(pDstData_p, *((WORD *) pSrcData));
1088 case kEplObdTypInt24:
1089 case kEplObdTypUInt24:
1091 AmiSetDword24ToLe(pDstData_p, *((DWORD *) pSrcData));
1096 case kEplObdTypInt32:
1097 case kEplObdTypUInt32:
1098 case kEplObdTypReal32:
1100 AmiSetDwordToLe(pDstData_p, *((DWORD *) pSrcData));
1105 case kEplObdTypInt40:
1106 case kEplObdTypUInt40:
1108 AmiSetQword40ToLe(pDstData_p, *((QWORD *) pSrcData));
1113 case kEplObdTypInt48:
1114 case kEplObdTypUInt48:
1116 AmiSetQword48ToLe(pDstData_p, *((QWORD *) pSrcData));
1121 case kEplObdTypInt56:
1122 case kEplObdTypUInt56:
1124 AmiSetQword56ToLe(pDstData_p, *((QWORD *) pSrcData));
1129 case kEplObdTypInt64:
1130 case kEplObdTypUInt64:
1131 case kEplObdTypReal64:
1133 AmiSetQword64ToLe(pDstData_p, *((QWORD *) pSrcData));
1138 case kEplObdTypTimeOfDay:
1139 case kEplObdTypTimeDiff:
1141 AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay *) pSrcData));
1145 } // end of switch(pSubEntry->m_Type)
1149 // write address of destination data to structure of callback parameters
1150 // so callback function can change this data after reading
1151 CbParam.m_pArg = pDstData_p;
1152 CbParam.m_ObdEvent = kEplObdEvPostRead;
1153 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1154 pObdEntry->m_fpCallback, &CbParam);
1162 //---------------------------------------------------------------------------
1164 // Function: EplObdWriteEntryFromLe()
1166 // Description: Function writes data to an OBD entry from a source with
1167 // little endian byteorder to the od with system specuific
1168 // byteorder. Not numerical values will only by copied. Strings
1169 // are stored with added '\0' character.
1171 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1172 // uiIndex_p = Index of the OD entry
1173 // uiSubIndex_p = Subindex of the OD Entry
1174 // pSrcData_p = Pointer to the data to write
1175 // Size_p = Size of the data in Byte
1177 // Return: tEplKernel = Errorcode
1182 //---------------------------------------------------------------------------
1183 EPLDLLEXPORT tEplKernel EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1184 unsigned int uiSubIndex_p,
1189 tEplObdEntryPtr pObdEntry;
1190 tEplObdSubEntryPtr pSubEntry;
1191 tEplObdCbParam CbParam;
1193 tEplObdSize ObdSize;
1195 void *pBuffer = &qwBuffer;
1197 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
1203 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
1204 if (Ret != kEplSuccessful) {
1208 // check if numerical type
1209 switch (pSubEntry->m_Type) {
1210 //-----------------------------------------------
1211 // types without ami
1213 { // do nothing, i.e. use the given source pointer
1214 pBuffer = pSrcData_p;
1218 //-----------------------------------------------
1219 // numerical type which needs ami-write
1220 // 8 bit or smaller values
1221 case kEplObdTypBool:
1222 case kEplObdTypInt8:
1223 case kEplObdTypUInt8:
1225 *((BYTE *) pBuffer) = AmiGetByteFromLe(pSrcData_p);
1230 case kEplObdTypInt16:
1231 case kEplObdTypUInt16:
1233 *((WORD *) pBuffer) = AmiGetWordFromLe(pSrcData_p);
1238 case kEplObdTypInt24:
1239 case kEplObdTypUInt24:
1241 *((DWORD *) pBuffer) = AmiGetDword24FromLe(pSrcData_p);
1246 case kEplObdTypInt32:
1247 case kEplObdTypUInt32:
1248 case kEplObdTypReal32:
1250 *((DWORD *) pBuffer) = AmiGetDwordFromLe(pSrcData_p);
1255 case kEplObdTypInt40:
1256 case kEplObdTypUInt40:
1258 *((QWORD *) pBuffer) = AmiGetQword40FromLe(pSrcData_p);
1263 case kEplObdTypInt48:
1264 case kEplObdTypUInt48:
1266 *((QWORD *) pBuffer) = AmiGetQword48FromLe(pSrcData_p);
1271 case kEplObdTypInt56:
1272 case kEplObdTypUInt56:
1274 *((QWORD *) pBuffer) = AmiGetQword56FromLe(pSrcData_p);
1279 case kEplObdTypInt64:
1280 case kEplObdTypUInt64:
1281 case kEplObdTypReal64:
1283 *((QWORD *) pBuffer) = AmiGetQword64FromLe(pSrcData_p);
1288 case kEplObdTypTimeOfDay:
1289 case kEplObdTypTimeDiff:
1291 AmiGetTimeOfDay(pBuffer, ((tTimeOfDay *) pSrcData_p));
1295 } // end of switch(pSubEntry->m_Type)
1297 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
1300 &CbParam, pBuffer, pDstData, ObdSize);
1301 if (Ret != kEplSuccessful) {
1311 //---------------------------------------------------------------------------
1313 // Function: EplObdGetAccessType()
1315 // Description: Function returns accesstype of the entry
1317 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1318 // uiIndex_p = Index of the OD entry
1319 // uiSubIndex_p = Subindex of the OD Entry
1320 // pAccessTyp_p = pointer to buffer to store accesstype
1322 // Return: tEplKernel = errorcode
1327 //---------------------------------------------------------------------------
1328 EPLDLLEXPORT tEplKernel EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1329 unsigned int uiSubIndex_p,
1330 tEplObdAccess *pAccessTyp_p)
1333 tEplObdEntryPtr pObdEntry;
1334 tEplObdSubEntryPtr pObdSubEntry;
1336 // get pointer to index structure
1337 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
1338 uiIndex_p, &pObdEntry);
1339 if (Ret != kEplSuccessful) {
1342 // get pointer to subindex structure
1343 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
1344 if (Ret != kEplSuccessful) {
1348 *pAccessTyp_p = pObdSubEntry->m_Access;
1354 //---------------------------------------------------------------------------
1356 // Function: EplObdSearchVarEntry()
1358 // Description: gets variable from OD
1360 // Parameters: uiIndex_p = index of the var entry to search
1361 // uiSubindex_p = subindex of var entry to search
1362 // ppVarEntry_p = pointer to the pointer to the varentry
1364 // Return: tEplKernel
1368 //---------------------------------------------------------------------------
1370 tEplKernel EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1371 unsigned int uiSubindex_p,
1372 tEplObdVarEntry **ppVarEntry_p)
1376 tEplObdSubEntryPtr pSubindexEntry;
1378 // check for all API function if instance is valid
1379 EPL_MCO_CHECK_INSTANCE_STATE();
1381 // get address of subindex entry
1382 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1383 uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
1384 if (Ret == kEplSuccessful) {
1386 Ret = EplObdGetVarEntry(pSubindexEntry, ppVarEntry_p);
1393 //=========================================================================//
1395 // P R I V A T E D E F I N I T I O N S //
1397 //=========================================================================//
1399 EPL_MCO_DECL_INSTANCE_FCT()
1400 //---------------------------------------------------------------------------
1402 // Function: EplObdCallObjectCallback()
1404 // Description: calls callback function of an object or of a variable
1406 // Parameters: fpCallback_p
1409 // Return: tEplKernel
1413 //---------------------------------------------------------------------------
1414 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
1415 tEplObdCallback fpCallback_p,
1416 tEplObdCbParam *pCbParam_p)
1420 tEplObdCallback fpCallback;
1422 // check for all API function if instance is valid
1423 EPL_MCO_CHECK_INSTANCE_STATE();
1425 ASSERT(pCbParam_p != NULL);
1427 Ret = kEplSuccessful;
1429 // check address of callback function before calling it
1430 if (fpCallback_p != NULL) {
1431 // KEIL C51 V6.01 has a bug.
1432 // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
1433 fpCallback = fpCallback_p;
1435 // call callback function for this object
1436 Ret = fpCallback(EPL_MCO_INSTANCE_PARAM_IDX_()
1443 //---------------------------------------------------------------------------
1445 // Function: EplObdGetDataSizeIntern()
1447 // Description: gets the data size of an object
1448 // for string objects it returnes the string length
1450 // Parameters: pSubIndexEntry_p
1452 // Return: tEplObdSize
1456 //---------------------------------------------------------------------------
1458 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p)
1461 tEplObdSize DataSize;
1464 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
1465 // then the current pointer is always NULL. The function
1466 // returns the length of default string.
1467 DataSize = EplObdGetObjectSize(pSubIndexEntry_p);
1469 if (pSubIndexEntry_p->m_Type == kEplObdTypVString) {
1470 // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
1471 pData = ((void *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p));
1472 if (pData != NULL) {
1474 EplObdGetStrLen((void *)pData, DataSize,
1475 pSubIndexEntry_p->m_Type);
1484 //---------------------------------------------------------------------------
1486 // Function: EplObdGetStrLen()
1488 // Description: The function calculates the length of string. The '\0'
1489 // character is included!!
1491 // Parameters: pObjData_p = pointer to string
1492 // ObjLen_p = max. length of objectr entry
1493 // bObjType_p = object type (VSTRING, ...)
1495 // Returns: string length + 1
1499 //---------------------------------------------------------------------------
1501 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
1502 tEplObdSize ObjLen_p, tEplObdType ObjType_p)
1505 tEplObdSize StrLen = 0;
1508 if (pObjData_p == NULL) {
1511 //----------------------------------------
1512 // Visible String: data format byte
1513 if (ObjType_p == kEplObdTypVString) {
1514 pbString = pObjData_p;
1516 for (StrLen = 0; StrLen < ObjLen_p; StrLen++) {
1517 if (*pbString == '\0') {
1525 //----------------------------------------
1526 // other string types ...
1533 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1535 //---------------------------------------------------------------------------
1537 // Function: EplObdCheckObjectRange()
1539 // Description: function to check value range of object data
1541 // NOTICE: The pointer of data (pData_p) must point out to an even address,
1542 // if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
1543 // always realiced because pointer m_pDefault points always to an
1544 // array of the SPECIFIED type.
1546 // Parameters: pSubindexEntry_p
1549 // Return: tEplKernel
1553 //---------------------------------------------------------------------------
1555 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
1562 ASSERTMSG(pSubindexEntry_p != NULL,
1563 "EplObdCheckObjectRange(): no address to subindex struct!\n");
1565 Ret = kEplSuccessful;
1567 // check if data range has to be checked
1568 if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) {
1571 // get address of default data
1572 pRangeData = pSubindexEntry_p->m_pDefault;
1574 // jump to called object type
1575 switch ((tEplObdType) pSubindexEntry_p->m_Type) {
1576 // -----------------------------------------------------------------
1577 // ObdType kEplObdTypBool will not be checked because there are only
1578 // two possible values 0 or 1.
1580 // -----------------------------------------------------------------
1581 // ObdTypes which has to be check up because numerical values
1582 case kEplObdTypInt8:
1584 // switch to lower limit
1585 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1587 // check if value is to low
1588 if (*((tEplObdInteger8 *) pData_p) <
1589 *((tEplObdInteger8 *) pRangeData)) {
1590 Ret = kEplObdValueTooLow;
1593 // switch to higher limit
1594 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1596 // check if value is to high
1597 if (*((tEplObdInteger8 *) pData_p) >
1598 *((tEplObdInteger8 *) pRangeData)) {
1599 Ret = kEplObdValueTooHigh;
1604 case kEplObdTypUInt8:
1606 // switch to lower limit
1607 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1609 // check if value is to low
1610 if (*((tEplObdUnsigned8 *) pData_p) <
1611 *((tEplObdUnsigned8 *) pRangeData)) {
1612 Ret = kEplObdValueTooLow;
1615 // switch to higher limit
1616 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1618 // check if value is to high
1619 if (*((tEplObdUnsigned8 *) pData_p) >
1620 *((tEplObdUnsigned8 *) pRangeData)) {
1621 Ret = kEplObdValueTooHigh;
1626 case kEplObdTypInt16:
1628 // switch to lower limit
1629 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1631 // check if value is to low
1632 if (*((tEplObdInteger16 *) pData_p) <
1633 *((tEplObdInteger16 *) pRangeData)) {
1634 Ret = kEplObdValueTooLow;
1637 // switch to higher limit
1638 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1640 // check if value is to high
1641 if (*((tEplObdInteger16 *) pData_p) >
1642 *((tEplObdInteger16 *) pRangeData)) {
1643 Ret = kEplObdValueTooHigh;
1648 case kEplObdTypUInt16:
1650 // switch to lower limit
1651 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1653 // check if value is to low
1654 if (*((tEplObdUnsigned16 *) pData_p) <
1655 *((tEplObdUnsigned16 *) pRangeData)) {
1656 Ret = kEplObdValueTooLow;
1659 // switch to higher limit
1660 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1662 // check if value is to high
1663 if (*((tEplObdUnsigned16 *) pData_p) >
1664 *((tEplObdUnsigned16 *) pRangeData)) {
1665 Ret = kEplObdValueTooHigh;
1670 case kEplObdTypInt32:
1672 // switch to lower limit
1673 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1675 // check if value is to low
1676 if (*((tEplObdInteger32 *) pData_p) <
1677 *((tEplObdInteger32 *) pRangeData)) {
1678 Ret = kEplObdValueTooLow;
1681 // switch to higher limit
1682 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1684 // check if value is to high
1685 if (*((tEplObdInteger32 *) pData_p) >
1686 *((tEplObdInteger32 *) pRangeData)) {
1687 Ret = kEplObdValueTooHigh;
1692 case kEplObdTypUInt32:
1694 // switch to lower limit
1695 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1697 // check if value is to low
1698 if (*((tEplObdUnsigned32 *) pData_p) <
1699 *((tEplObdUnsigned32 *) pRangeData)) {
1700 Ret = kEplObdValueTooLow;
1703 // switch to higher limit
1704 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1706 // check if value is to high
1707 if (*((tEplObdUnsigned32 *) pData_p) >
1708 *((tEplObdUnsigned32 *) pRangeData)) {
1709 Ret = kEplObdValueTooHigh;
1714 case kEplObdTypReal32:
1716 // switch to lower limit
1717 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1719 // check if value is to low
1720 if (*((tEplObdReal32 *) pData_p) <
1721 *((tEplObdReal32 *) pRangeData)) {
1722 Ret = kEplObdValueTooLow;
1725 // switch to higher limit
1726 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1728 // check if value is to high
1729 if (*((tEplObdReal32 *) pData_p) >
1730 *((tEplObdReal32 *) pRangeData)) {
1731 Ret = kEplObdValueTooHigh;
1736 // -----------------------------------------------------------------
1737 case kEplObdTypInt40:
1738 case kEplObdTypInt48:
1739 case kEplObdTypInt56:
1740 case kEplObdTypInt64:
1742 // switch to lower limit
1743 pRangeData = ((signed QWORD *)pRangeData) + 1;
1745 // check if value is to low
1746 if (*((signed QWORD *)pData_p) < *((signed QWORD *)pRangeData)) {
1747 Ret = kEplObdValueTooLow;
1750 // switch to higher limit
1751 pRangeData = ((signed QWORD *)pRangeData) + 1;
1753 // check if value is to high
1754 if (*((signed QWORD *)pData_p) > *((signed QWORD *)pRangeData)) {
1755 Ret = kEplObdValueTooHigh;
1760 // -----------------------------------------------------------------
1761 case kEplObdTypUInt40:
1762 case kEplObdTypUInt48:
1763 case kEplObdTypUInt56:
1764 case kEplObdTypUInt64:
1766 // switch to lower limit
1767 pRangeData = ((unsigned QWORD *)pRangeData) + 1;
1769 // check if value is to low
1770 if (*((unsigned QWORD *)pData_p) <
1771 *((unsigned QWORD *)pRangeData)) {
1772 Ret = kEplObdValueTooLow;
1775 // switch to higher limit
1776 pRangeData = ((unsigned QWORD *)pRangeData) + 1;
1778 // check if value is to high
1779 if (*((unsigned QWORD *)pData_p) >
1780 *((unsigned QWORD *)pRangeData)) {
1781 Ret = kEplObdValueTooHigh;
1786 // -----------------------------------------------------------------
1787 case kEplObdTypReal64:
1789 // switch to lower limit
1790 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1792 // check if value is to low
1793 if (*((tEplObdReal64 *) pData_p) <
1794 *((tEplObdReal64 *) pRangeData)) {
1795 Ret = kEplObdValueTooLow;
1798 // switch to higher limit
1799 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1801 // check if value is to high
1802 if (*((tEplObdReal64 *) pData_p) >
1803 *((tEplObdReal64 *) pRangeData)) {
1804 Ret = kEplObdValueTooHigh;
1809 // -----------------------------------------------------------------
1810 case kEplObdTypTimeOfDay:
1811 case kEplObdTypTimeDiff:
1814 // -----------------------------------------------------------------
1815 // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
1816 // they have no numerical value.
1819 Ret = kEplObdUnknownObjectType;
1828 #endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1830 //---------------------------------------------------------------------------
1832 // Function: EplObdWriteEntryPre()
1834 // Description: Function prepares write of data to an OBD entry. Strings
1835 // are stored with added '\0' character.
1837 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1838 // uiIndex_p = Index of the OD entry
1839 // uiSubIndex_p = Subindex of the OD Entry
1840 // pSrcData_p = Pointer to the data to write
1841 // Size_p = Size of the data in Byte
1843 // Return: tEplKernel = Errorcode
1848 //---------------------------------------------------------------------------
1850 static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
1851 unsigned int uiSubIndex_p,
1855 tEplObdEntryPtr *ppObdEntry_p,
1856 tEplObdSubEntryPtr *ppSubEntry_p,
1857 tEplObdCbParam *pCbParam_p,
1858 tEplObdSize *pObdSize_p)
1862 tEplObdEntryPtr pObdEntry;
1863 tEplObdSubEntryPtr pSubEntry;
1864 tEplObdAccess Access;
1866 tEplObdSize ObdSize;
1867 BOOL fEntryNumerical;
1869 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1870 tEplObdVStringDomain MemVStringDomain;
1874 // check for all API function if instance is valid
1875 EPL_MCO_CHECK_INSTANCE_STATE();
1877 ASSERT(pSrcData_p != NULL); // should never be NULL
1879 //------------------------------------------------------------------------
1880 // get address of index and subindex entry
1881 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1882 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1883 if (Ret != kEplSuccessful) {
1886 // get pointer to object data
1887 pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1889 Access = (tEplObdAccess) pSubEntry->m_Access;
1891 // check access for write
1892 // access violation if adress to current value is NULL
1893 if (((Access & kEplObdAccConst) != 0) || (pDstData == NULL)) {
1894 Ret = kEplObdAccessViolation;
1897 //------------------------------------------------------------------------
1898 // get size of object
1899 // -as ObdSize = ObdGetObjectSize (pSubEntry);
1901 //------------------------------------------------------------------------
1902 // To use the same callback function for ObdWriteEntry as well as for
1903 // an SDO download call at first (kEplObdEvPre...) the callback function
1904 // with the argument pointer to object size.
1905 pCbParam_p->m_uiIndex = uiIndex_p;
1906 pCbParam_p->m_uiSubIndex = uiSubIndex_p;
1908 // Because object size and object pointer are
1909 // adapted by user callback function, re-read
1911 ObdSize = EplObdGetObjectSize(pSubEntry);
1912 pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry);
1914 // 09-dec-2004 r.d.:
1915 // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
1916 // for String or Domain which lets called module directly change
1917 // the data pointer or size. This prevents a recursive call to
1918 // the callback function if it calls EplObdGetEntry().
1919 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1920 if ((pSubEntry->m_Type == kEplObdTypVString) ||
1921 (pSubEntry->m_Type == kEplObdTypDomain) ||
1922 (pSubEntry->m_Type == kEplObdTypOString)) {
1923 if (pSubEntry->m_Type == kEplObdTypVString) {
1924 // reserve one byte for 0-termination
1925 // -as ObdSize -= 1;
1928 // fill out new arg-struct
1929 MemVStringDomain.m_DownloadSize = Size_p;
1930 MemVStringDomain.m_ObjSize = ObdSize;
1931 MemVStringDomain.m_pData = pDstData;
1933 pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
1934 pCbParam_p->m_pArg = &MemVStringDomain;
1935 // call user callback
1936 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1937 pObdEntry->m_fpCallback,
1939 if (Ret != kEplSuccessful) {
1942 // write back new settings
1943 pCurrData = pSubEntry->m_pCurrent;
1944 if ((pSubEntry->m_Type == kEplObdTypVString)
1945 || (pSubEntry->m_Type == kEplObdTypOString)) {
1946 ((tEplObdVString *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1947 ((tEplObdVString *)pCurrData)->m_pString = MemVStringDomain.m_pData;
1948 } else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
1950 ((tEplObdVarEntry *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize;
1951 ((tEplObdVarEntry *)pCurrData)->m_pData = (void *)MemVStringDomain.m_pData;
1954 // Because object size and object pointer are
1955 // adapted by user callback function, re-read
1957 ObdSize = MemVStringDomain.m_ObjSize;
1958 pDstData = (void *)MemVStringDomain.m_pData;
1960 #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1962 // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
1963 // -as 16.11.04 CbParam.m_pArg = &ObdSize;
1964 // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p;
1965 pCbParam_p->m_pArg = &ObdSize;
1966 pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
1967 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1968 pObdEntry->m_fpCallback, pCbParam_p);
1969 if (Ret != kEplSuccessful) {
1973 if (Size_p > ObdSize) {
1974 Ret = kEplObdValueLengthError;
1978 if (pSubEntry->m_Type == kEplObdTypVString) {
1979 if (((char *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character
1981 // reserve one byte in destination for 0-termination
1983 } else if (Size_p >= ObdSize) { // source string is not 0-terminated
1984 // and destination buffer is too short
1985 Ret = kEplObdValueLengthError;
1990 Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
1991 if (Ret != kEplSuccessful) {
1995 if ((fEntryNumerical != FALSE)
1996 && (Size_p != ObdSize)) {
1997 // type is numerical, therefor size has to fit, but it does not.
1998 Ret = kEplObdValueLengthError;
2001 // use given size, because non-numerical objects can be written with shorter values
2004 // set output parameters
2005 *pObdSize_p = ObdSize;
2006 *ppObdEntry_p = pObdEntry;
2007 *ppSubEntry_p = pSubEntry;
2008 *ppDstData_p = pDstData;
2010 // all checks are done
2011 // the caller may now convert the numerial source value to platform byte order in a temporary buffer
2019 //---------------------------------------------------------------------------
2021 // Function: EplObdWriteEntryPost()
2023 // Description: Function finishes write of data to an OBD entry. Strings
2024 // are stored with added '\0' character.
2026 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
2027 // uiIndex_p = Index of the OD entry
2028 // uiSubIndex_p = Subindex of the OD Entry
2029 // pSrcData_p = Pointer to the data to write
2030 // Size_p = Size of the data in Byte
2032 // Return: tEplKernel = Errorcode
2037 //---------------------------------------------------------------------------
2039 static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p,
2040 tEplObdSubEntryPtr pSubEntry_p,
2041 tEplObdCbParam *pCbParam_p,
2044 tEplObdSize ObdSize_p)
2049 // caller converted the source value to platform byte order
2050 // now the range of the value may be checked
2052 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2055 Ret = EplObdCheckObjectRange(pSubEntry_p, pSrcData_p);
2056 if (Ret != kEplSuccessful) {
2062 // now call user callback function to check value
2063 // write address of source data to structure of callback parameters
2064 // so callback function can check this data
2065 pCbParam_p->m_pArg = pSrcData_p;
2066 pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
2067 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2068 pObdEntry_p->m_fpCallback, pCbParam_p);
2069 if (Ret != kEplSuccessful) {
2072 // copy object data to OBD
2073 EPL_MEMCPY(pDstData_p, pSrcData_p, ObdSize_p);
2075 // terminate string with 0
2076 if (pSubEntry_p->m_Type == kEplObdTypVString) {
2077 ((char *)pDstData_p)[ObdSize_p] = '\0';
2079 // write address of destination to structure of callback parameters
2080 // so callback function can change data subsequently
2081 pCbParam_p->m_pArg = pDstData_p;
2082 pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
2083 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2084 pObdEntry_p->m_fpCallback, pCbParam_p);
2092 //---------------------------------------------------------------------------
2094 // Function: EplObdGetObjectSize()
2096 // Description: function to get size of object
2097 // The function determines if an object type an fixed data type (BYTE, WORD, ...)
2098 // or non fixed object (string, domain). This information is used to decide
2099 // if download data are stored temporary or not. For objects with fixed data length
2100 // and types a value range checking can process.
2101 // For strings the function returns the whole object size not the
2102 // length of string.
2104 // Parameters: pSubIndexEntry_p
2106 // Return: tEplObdSize
2110 //---------------------------------------------------------------------------
2112 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p)
2115 tEplObdSize DataSize = 0;
2118 switch (pSubIndexEntry_p->m_Type) {
2119 // -----------------------------------------------------------------
2120 case kEplObdTypBool:
2125 // -----------------------------------------------------------------
2126 // ObdTypes which has to be check because numerical values
2127 case kEplObdTypInt8:
2128 DataSize = sizeof(tEplObdInteger8);
2131 // -----------------------------------------------------------------
2132 case kEplObdTypUInt8:
2133 DataSize = sizeof(tEplObdUnsigned8);
2136 // -----------------------------------------------------------------
2137 case kEplObdTypInt16:
2138 DataSize = sizeof(tEplObdInteger16);
2141 // -----------------------------------------------------------------
2142 case kEplObdTypUInt16:
2143 DataSize = sizeof(tEplObdUnsigned16);
2146 // -----------------------------------------------------------------
2147 case kEplObdTypInt32:
2148 DataSize = sizeof(tEplObdInteger32);
2151 // -----------------------------------------------------------------
2152 case kEplObdTypUInt32:
2153 DataSize = sizeof(tEplObdUnsigned32);
2156 // -----------------------------------------------------------------
2157 case kEplObdTypReal32:
2158 DataSize = sizeof(tEplObdReal32);
2161 // -----------------------------------------------------------------
2162 // ObdTypes which has to be not checked because not NUM values
2163 case kEplObdTypDomain:
2165 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2166 if ((void *)pData != (void *)NULL) {
2167 DataSize = ((tEplObdVarEntry *) pData)->m_Size;
2171 // -----------------------------------------------------------------
2172 case kEplObdTypVString:
2173 //case kEplObdTypUString:
2175 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
2176 // then the current pointer is always NULL. The function
2177 // returns the length of default string.
2178 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2179 if ((void *)pData != (void *)NULL) {
2180 // The max. size of strings defined by STRING-Macro is stored in
2181 // tEplObdVString of current value.
2182 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2183 DataSize = ((tEplObdVString *) pData)->m_Size;
2185 // The current position is not decleared. The string
2186 // is located in ROM, therefor use default pointer.
2187 pData = (void *)pSubIndexEntry_p->m_pDefault;
2188 if ((CONST void *)pData != (CONST void *)NULL) {
2189 // The max. size of strings defined by STRING-Macro is stored in
2190 // tEplObdVString of default value.
2192 ((CONST tEplObdVString *) pData)->
2199 // -----------------------------------------------------------------
2200 case kEplObdTypOString:
2202 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2203 if ((void *)pData != (void *)NULL) {
2204 // The max. size of strings defined by STRING-Macro is stored in
2205 // tEplObdVString of current value.
2206 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2207 DataSize = ((tEplObdOString *) pData)->m_Size;
2209 // The current position is not decleared. The string
2210 // is located in ROM, therefor use default pointer.
2211 pData = (void *)pSubIndexEntry_p->m_pDefault;
2212 if ((CONST void *)pData != (CONST void *)NULL) {
2213 // The max. size of strings defined by STRING-Macro is stored in
2214 // tEplObdVString of default value.
2216 ((CONST tEplObdOString *) pData)->
2222 // -----------------------------------------------------------------
2223 case kEplObdTypInt24:
2224 case kEplObdTypUInt24:
2229 // -----------------------------------------------------------------
2230 case kEplObdTypInt40:
2231 case kEplObdTypUInt40:
2236 // -----------------------------------------------------------------
2237 case kEplObdTypInt48:
2238 case kEplObdTypUInt48:
2243 // -----------------------------------------------------------------
2244 case kEplObdTypInt56:
2245 case kEplObdTypUInt56:
2250 // -----------------------------------------------------------------
2251 case kEplObdTypInt64:
2252 case kEplObdTypUInt64:
2253 case kEplObdTypReal64:
2258 // -----------------------------------------------------------------
2259 case kEplObdTypTimeOfDay:
2260 case kEplObdTypTimeDiff:
2265 // -----------------------------------------------------------------
2273 //---------------------------------------------------------------------------
2275 // Function: EplObdGetObjectDefaultPtr()
2277 // Description: function to get the default pointer (type specific)
2279 // Parameters: pSubIndexEntry_p = pointer to subindex structure
2281 // Returns: (void *) = pointer to default value
2285 //---------------------------------------------------------------------------
2287 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2293 ASSERTMSG(pSubIndexEntry_p != NULL,
2294 "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
2296 // get address to default data from default pointer
2297 pDefault = pSubIndexEntry_p->m_pDefault;
2298 if (pDefault != NULL) {
2299 // there are some special types, whose default pointer always is NULL or has to get from other structure
2300 // get type from subindex structure
2301 Type = pSubIndexEntry_p->m_Type;
2303 // check if object type is a string value
2304 if ((Type == kEplObdTypVString) /* ||
2305 (Type == kEplObdTypUString) */ ) {
2307 // EPL_OBD_SUBINDEX_RAM_VSTRING
2308 // tEplObdSize m_Size; --> size of default string
2309 // char * m_pDefString; --> pointer to default string
2310 // char * m_pString; --> pointer to string in RAM
2313 (void *)((tEplObdVString *) pDefault)->m_pString;
2314 } else if (Type == kEplObdTypOString) {
2316 (void *)((tEplObdOString *) pDefault)->m_pString;
2324 //---------------------------------------------------------------------------
2326 // Function: EplObdGetVarEntry()
2328 // Description: gets a variable entry of an object
2330 // Parameters: pSubindexEntry_p
2333 // Return: tCopKernel
2337 //---------------------------------------------------------------------------
2339 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
2340 tEplObdVarEntry **ppVarEntry_p)
2343 tEplKernel Ret = kEplObdVarEntryNotExist;
2345 ASSERT(ppVarEntry_p != NULL); // is not allowed to be NULL
2346 ASSERT(pSubindexEntry_p != NULL);
2348 // check VAR-Flag - only this object points to variables
2349 if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) {
2350 // check if object is an array
2351 if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) {
2352 *ppVarEntry_p = &((tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
2354 *ppVarEntry_p = (tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent;
2357 Ret = kEplSuccessful;
2364 //---------------------------------------------------------------------------
2366 // Function: EplObdGetEntry()
2368 // Description: gets a index entry from OD
2370 // Parameters: uiIndex_p = Index number
2371 // uiSubindex_p = Subindex number
2372 // ppObdEntry_p = pointer to the pointer to the entry
2373 // ppObdSubEntry_p = pointer to the pointer to the subentry
2375 // Return: tEplKernel
2380 //---------------------------------------------------------------------------
2382 static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
2383 unsigned int uiIndex_p,
2384 unsigned int uiSubindex_p,
2385 tEplObdEntryPtr * ppObdEntry_p,
2386 tEplObdSubEntryPtr * ppObdSubEntry_p)
2389 tEplObdEntryPtr pObdEntry;
2390 tEplObdCbParam CbParam;
2393 // check for all API function if instance is valid
2394 EPL_MCO_CHECK_INSTANCE_STATE();
2396 //------------------------------------------------------------------------
2397 // get address of entry of index
2399 EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam), uiIndex_p,
2401 if (Ret != kEplSuccessful) {
2404 //------------------------------------------------------------------------
2405 // get address of entry of subindex
2406 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubindex_p, ppObdSubEntry_p);
2407 if (Ret != kEplSuccessful) {
2410 //------------------------------------------------------------------------
2411 // call callback function to inform user/stack that an object will be searched
2412 // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
2413 CbParam.m_uiIndex = uiIndex_p;
2414 CbParam.m_uiSubIndex = uiSubindex_p;
2415 CbParam.m_pArg = NULL;
2416 CbParam.m_ObdEvent = kEplObdEvCheckExist;
2417 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2418 pObdEntry->m_fpCallback, &CbParam);
2419 if (Ret != kEplSuccessful) {
2420 Ret = kEplObdIndexNotExist;
2423 //------------------------------------------------------------------------
2424 // it is allowed to set ppObdEntry_p to NULL
2425 // if so, no address will be written to calling function
2426 if (ppObdEntry_p != NULL) {
2427 *ppObdEntry_p = pObdEntry;
2436 //---------------------------------------------------------------------------
2438 // Function: EplObdGetObjectCurrentPtr()
2440 // Description: function to get Current pointer (type specific)
2442 // Parameters: pSubIndexEntry_p
2448 //---------------------------------------------------------------------------
2450 static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2454 unsigned int uiArrayIndex;
2457 pData = pSubIndexEntry_p->m_pCurrent;
2459 // check if constant object
2460 if (pData != NULL) {
2461 // check if object is an array
2462 if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) {
2463 // calculate correct data pointer
2464 uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
2465 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2466 Size = sizeof(tEplObdVarEntry);
2468 Size = EplObdGetObjectSize(pSubIndexEntry_p);
2470 pData = ((BYTE *) pData) + (Size * uiArrayIndex);
2472 // check if VarEntry
2473 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2474 // The data pointer is stored in VarEntry->pData
2475 pData = ((tEplObdVarEntry *) pData)->m_pData;
2477 // the default pointer is stored for strings in tEplObdVString
2478 else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* ||
2479 (pSubIndexEntry_p->m_Type == kEplObdTypUString) */
2481 pData = (void *)((tEplObdVString *)pData)->m_pString;
2482 } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) {
2484 (void *)((tEplObdOString *)pData)->m_pString;
2492 //---------------------------------------------------------------------------
2494 // Function: EplObdGetIndexIntern()
2496 // Description: gets a index entry from OD
2498 // Parameters: pInitParam_p
2502 // Return: tEplKernel
2506 //---------------------------------------------------------------------------
2508 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p,
2509 unsigned int uiIndex_p,
2510 tEplObdEntryPtr * ppObdEntry_p)
2513 tEplObdEntryPtr pObdEntry;
2515 unsigned int uiIndex;
2517 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2521 // if user OD is used then objekts also has to be searched in user OD
2522 // there is less code need if we do this in a loop
2527 ASSERTMSG(ppObdEntry_p != NULL,
2528 "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
2530 Ret = kEplObdIndexNotExist;
2532 // get start address of OD part
2533 // start address depends on object index because
2534 // object dictionary is divided in 3 parts
2535 if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) {
2536 pObdEntry = pInitParam_p->m_pPart;
2537 } else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) {
2538 pObdEntry = pInitParam_p->m_pManufacturerPart;
2540 // index range 0xA000 to 0xFFFF is reserved for DSP-405
2541 // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
2542 // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
2543 // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
2544 // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
2546 #if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
2547 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
2549 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
2552 pObdEntry = pInitParam_p->m_pDevicePart;
2555 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2557 // if index does not match in static OD then index only has to be searched in user OD
2559 // begin from first entry of user OD part
2560 pObdEntry = pInitParam_p->m_pUserPart;
2562 // no user OD is available
2563 if (pObdEntry == NULL) {
2566 // loop must only run once
2574 // no user OD is available
2575 // so other object can be found in OD
2577 Ret = kEplObdIllegalPart;
2584 // The end of Index table is marked with m_uiIndex = 0xFFFF.
2585 // If this function will be called with wIndex_p = 0xFFFF, entry
2586 // should not be found. Therefor it is important to use
2587 // while{} instead of do{}while !!!
2589 // get first index of index table
2590 uiIndex = pObdEntry->m_uiIndex;
2592 // search Index in OD part
2593 while (uiIndex != EPL_OBD_TABLE_INDEX_END) {
2594 // go to the end of this function if index is found
2595 if (uiIndex_p == uiIndex) {
2596 // write address of OD entry to calling function
2597 *ppObdEntry_p = pObdEntry;
2598 Ret = kEplSuccessful;
2601 // objects are sorted in OD
2602 // if the current index in OD is greater than the index which is to search then break loop
2603 // in this case user OD has to be search too
2604 if (uiIndex_p < uiIndex) {
2607 // next entry in index table
2610 // get next index of index table
2611 uiIndex = pObdEntry->m_uiIndex;
2614 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2616 // begin from first entry of user OD part
2617 pObdEntry = pInitParam_p->m_pUserPart;
2619 // no user OD is available
2620 if (pObdEntry == NULL) {
2623 // switch next loop for user OD
2632 // in this line Index was not found
2640 //---------------------------------------------------------------------------
2642 // Function: EplObdGetSubindexIntern()
2644 // Description: gets a subindex entry from a index entry
2646 // Parameters: pObdEntry_p
2650 // Return: tEplKernel
2654 //---------------------------------------------------------------------------
2656 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
2657 unsigned int uiSubIndex_p,
2658 tEplObdSubEntryPtr * ppObdSubEntry_p)
2661 tEplObdSubEntryPtr pSubEntry;
2662 unsigned int nSubIndexCount;
2665 ASSERTMSG(pObdEntry_p != NULL,
2666 "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
2667 ASSERTMSG(ppObdSubEntry_p != NULL,
2668 "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
2670 Ret = kEplObdSubindexNotExist;
2672 // get start address of subindex table and count of subindices
2673 pSubEntry = pObdEntry_p->m_pSubIndex;
2674 nSubIndexCount = pObdEntry_p->m_uiCount;
2675 ASSERTMSG((pSubEntry != NULL) && (nSubIndexCount > 0), "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
2677 // search subindex in subindex table
2678 while (nSubIndexCount > 0) {
2679 // check if array is found
2680 if ((pSubEntry->m_Access & kEplObdAccArray) != 0) {
2681 // check if subindex is in range
2682 if (uiSubIndex_p < pObdEntry_p->m_uiCount) {
2683 // update subindex number (subindex entry of an array is always in RAM !!!)
2684 pSubEntry->m_uiSubIndex = uiSubIndex_p;
2685 *ppObdSubEntry_p = pSubEntry;
2686 Ret = kEplSuccessful;
2690 // go to the end of this function if subindex is found
2691 else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) {
2692 *ppObdSubEntry_p = pSubEntry;
2693 Ret = kEplSuccessful;
2696 // objects are sorted in OD
2697 // if the current subindex in OD is greater than the subindex which is to search then break loop
2698 // in this case user OD has to be search too
2699 if (uiSubIndex_p < pSubEntry->m_uiSubIndex) {
2707 // in this line SubIndex was not fount
2715 //---------------------------------------------------------------------------
2717 // Function: EplObdSetStoreLoadObjCallback()
2719 // Description: function set address to callbackfunction for command Store and Load
2721 // Parameters: fpCallback_p
2723 // Return: tEplKernel
2727 //---------------------------------------------------------------------------
2728 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2729 EPLDLLEXPORT tEplKernel EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdStoreLoadObjCallback fpCallback_p)
2732 EPL_MCO_CHECK_INSTANCE_STATE();
2734 // set new address of callback function
2735 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = fpCallback_p;
2737 return kEplSuccessful;
2740 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2742 //---------------------------------------------------------------------------
2744 // Function: EplObdAccessOdPartIntern()
2746 // Description: runs through OD and executes a job
2748 // Parameters: CurrentOdPart_p
2750 // Direction_p = what is to do (load values from flash or EEPROM, store, ...)
2752 // Return: tEplKernel
2756 //---------------------------------------------------------------------------
2758 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
2759 tEplObdPart CurrentOdPart_p,
2760 tEplObdEntryPtr pObdEnty_p,
2761 tEplObdDir Direction_p)
2764 tEplObdSubEntryPtr pSubIndex;
2765 unsigned int nSubIndexCount;
2766 tEplObdAccess Access;
2769 tEplObdSize ObjSize;
2771 tEplObdCbStoreParam CbStore;
2772 tEplObdVarEntry *pVarEntry;
2774 ASSERT(pObdEnty_p != NULL);
2776 Ret = kEplSuccessful;
2778 // prepare structure for STORE RESTORE callback function
2779 CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p;
2780 CbStore.m_pData = NULL;
2781 CbStore.m_ObjSize = 0;
2783 // command of first action depends on direction to access
2784 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2785 if (Direction_p == kEplObdDirLoad) {
2786 CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead;
2788 // call callback function for previous command
2789 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2790 if (Ret != kEplSuccessful) {
2793 // set command for index and subindex loop
2794 CbStore.m_bCommand = (BYTE) kEplObdCommReadObj;
2795 } else if (Direction_p == kEplObdDirStore) {
2796 CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite;
2798 // call callback function for previous command
2799 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2800 if (Ret != kEplSuccessful) {
2803 // set command for index and subindex loop
2804 CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj;
2806 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2808 // we should not restore the OD values here
2809 // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
2810 if (Direction_p != kEplObdDirRestore) {
2811 // walk through OD part till end is found
2812 while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) {
2813 // get address to subindex table and count of subindices
2814 pSubIndex = pObdEnty_p->m_pSubIndex;
2815 nSubIndexCount = pObdEnty_p->m_uiCount;
2816 ASSERT((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL
2818 // walk through subindex table till all subinices were restored
2819 while (nSubIndexCount != 0) {
2820 Access = (tEplObdAccess) pSubIndex->m_Access;
2822 // get pointer to current and default data
2823 pDefault = EplObdGetObjectDefaultPtr(pSubIndex);
2824 pDstData = EplObdGetObjectCurrentPtr(pSubIndex);
2826 // NOTE (for kEplObdTypVString):
2827 // The function returnes the max. number of bytes for a
2829 // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
2830 ObjSize = EplObdGetObjectSize(pSubIndex);
2832 // switch direction of OD access
2833 switch (Direction_p) {
2834 // --------------------------------------------------------------------------
2835 // VarEntry structures has to be initialized
2836 case kEplObdDirInit:
2838 // If VAR-Flag is set, m_pCurrent means not address of data
2839 // but address of tEplObdVarEntry. Address of data has to be get from
2841 if ((Access & kEplObdAccVar) != 0) {
2842 EplObdGetVarEntry(pSubIndex,
2844 EplObdInitVarEntry(pVarEntry,
2849 if ((Access & kEplObdAccArray) == 0)
2851 EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
2855 EplObdInitVarEntry ((tEplObdVarEntry *) (((BYTE *) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
2856 pSubIndex->m_Type, ObjSize);
2859 // at this time no application variable is defined !!!
2860 // therefore data can not be copied.
2862 } else if (pSubIndex->m_Type ==
2863 kEplObdTypVString) {
2864 // If pointer m_pCurrent is not equal to NULL then the
2865 // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
2866 // pointer points to struct tEplObdVString located in MEM.
2867 // The element size includes the max. number of
2868 // bytes. The element m_pString includes the pointer
2869 // to string in MEM. The memory location of default string
2870 // must be copied to memory location of current string.
2873 pSubIndex->m_pCurrent;
2874 if (pDstData != NULL) {
2875 // 08-dec-2004: code optimization !!!
2876 // entries ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString
2877 // and ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_Size were read
2878 // twice. thats not necessary!
2880 // For copying data we have to set the destination pointer to the real RAM string. This
2881 // pointer to RAM string is located in default string info structure. (translated r.d.)
2882 pDstData = (void *)((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString;
2883 ObjSize = ((tEplObdVStringDef *)pSubIndex->m_pDefault)->m_Size;
2885 ((tEplObdVString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2886 ((tEplObdVString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2889 } else if (pSubIndex->m_Type ==
2890 kEplObdTypOString) {
2892 pSubIndex->m_pCurrent;
2893 if (pDstData != NULL) {
2894 // 08-dec-2004: code optimization !!!
2895 // entries ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_pString
2896 // and ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_Size were read
2897 // twice. thats not necessary!
2899 // For copying data we have to set the destination pointer to the real RAM string. This
2900 // pointer to RAM string is located in default string info structure. (translated r.d.)
2901 pDstData = (void *)((tEplObdOStringDef *) pSubIndex->m_pDefault)->m_pString;
2902 ObjSize = ((tEplObdOStringDef *)pSubIndex->m_pDefault)->m_Size;
2904 ((tEplObdOString *)pSubIndex->m_pCurrent)->m_pString = pDstData;
2905 ((tEplObdOString *)pSubIndex->m_pCurrent)->m_Size = ObjSize;
2910 // no break !! because copy of data has to done too.
2912 // --------------------------------------------------------------------------
2913 // all objects has to be restored with default values
2914 case kEplObdDirRestore:
2916 // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
2917 // is replaced to function ObdCopyObjectData() with a new parameter.
2919 // restore object data for init phase
2920 EplObdCopyObjectData(pDstData, pDefault,
2925 // --------------------------------------------------------------------------
2926 // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
2927 case kEplObdDirLoad:
2929 // restore object data for init phase
2930 EplObdCopyObjectData(pDstData, pDefault,
2934 // no break !! because callback function has to be called too.
2936 // --------------------------------------------------------------------------
2937 // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
2938 case kEplObdDirStore:
2940 // when attribute kEplObdAccStore is set, then call callback function
2941 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2942 if ((Access & kEplObdAccStore) != 0) {
2943 // fill out data pointer and size of data
2944 CbStore.m_pData = pDstData;
2945 CbStore.m_ObjSize = ObjSize;
2947 // call callback function for read or write object
2949 ObdCallStoreCallback
2950 (EPL_MCO_INSTANCE_PTR_ &
2952 if (Ret != kEplSuccessful) {
2956 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2959 // --------------------------------------------------------------------------
2960 // if OD Builder key has to be checked no access to subindex and data should be made
2961 case kEplObdDirOBKCheck:
2963 // no break !! because we want to break the second loop too.
2965 // --------------------------------------------------------------------------
2966 // unknown Direction
2969 // so we can break the second loop earler
2976 // next subindex entry
2977 if ((Access & kEplObdAccArray) == 0) {
2979 if ((nSubIndexCount > 0)
2982 m_Access & kEplObdAccArray) !=
2984 // next subindex points to an array
2985 // reset subindex number
2986 pSubIndex->m_uiSubIndex = 1;
2989 if (nSubIndexCount > 0) {
2990 // next subindex points to an array
2991 // increment subindex number
2992 pSubIndex->m_uiSubIndex++;
3001 // -----------------------------------------------------------------------------------------
3002 // command of last action depends on direction to access
3003 if (Direction_p == kEplObdDirOBKCheck) {
3007 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3009 if (Direction_p == kEplObdDirLoad) {
3010 CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead;
3011 } else if (Direction_p == kEplObdDirStore) {
3012 CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite;
3013 } else if (Direction_p == kEplObdDirRestore) {
3014 CbStore.m_bCommand = (BYTE) kEplObdCommClear;
3019 // call callback function for last command
3020 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
3022 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3032 // ----------------------------------------------------------------------------
3033 // Function: EplObdCopyObjectData()
3035 // Description: checks pointers to object data and copy them from source to destination
3037 // Parameters: pDstData_p = destination pointer
3038 // pSrcData_p = source pointer
3039 // ObjSize_p = size of object
3042 // Returns: tEplKernel = error code
3043 // ----------------------------------------------------------------------------
3045 static void EplObdCopyObjectData(void *pDstData_p,
3047 tEplObdSize ObjSize_p, tEplObdType ObjType_p)
3050 tEplObdSize StrSize = 0;
3052 // it is allowed to set default and current address to NULL (nothing to copy)
3053 if (pDstData_p != NULL) {
3055 if (ObjType_p == kEplObdTypVString) {
3056 // The function calculates the really number of characters of string. The
3057 // object entry size can be bigger as string size of default string.
3058 // The '\0'-termination is included. A string with no characters has a
3061 EplObdGetStrLen((void *)pSrcData_p, ObjSize_p,
3064 // If the string length is greater than or equal to the entry size in OD then only copy
3065 // entry size - 1 and always set the '\0'-termination.
3066 if (StrSize >= ObjSize_p) {
3067 StrSize = ObjSize_p - 1;
3071 if (pSrcData_p != NULL) {
3073 EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p);
3075 if (ObjType_p == kEplObdTypVString) {
3076 ((char *)pDstData_p)[StrSize] = '\0';
3083 //---------------------------------------------------------------------------
3085 // Function: EplObdIsNumericalIntern()
3087 // Description: function checks if a entry is numerical or not
3090 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
3091 // uiIndex_p = Index
3092 // uiSubIndex_p = Subindex
3093 // pfEntryNumerical_p = pointer to BOOL for returnvalue
3094 // -> TRUE if entry a numerical value
3095 // -> FALSE if entry not a numerical value
3097 // Return: tEplKernel = Errorcode
3101 //---------------------------------------------------------------------------
3102 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
3103 BOOL * pfEntryNumerical_p)
3105 tEplKernel Ret = kEplSuccessful;
3108 if ((pObdSubEntry_p->m_Type == kEplObdTypVString)
3109 || (pObdSubEntry_p->m_Type == kEplObdTypOString)
3110 || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) { // not numerical types
3111 *pfEntryNumerical_p = FALSE;
3112 } else { // numerical types
3113 *pfEntryNumerical_p = TRUE;
3120 // -------------------------------------------------------------------------
3121 // function to classify object type (fixed/non fixed)
3122 // -------------------------------------------------------------------------
3124 // ----------------------------------------------------------------------------
3125 // Function: EplObdCallStoreCallback()
3127 // Description: checks address to callback function and calles it when unequal
3130 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
3131 // pCbStoreParam_p = address to callback parameters
3133 // Returns: tEplKernel = error code
3134 // ----------------------------------------------------------------------------
3135 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3136 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
3137 tEplObdCbStoreParam *
3141 tEplKernel Ret = kEplSuccessful;
3143 ASSERT(pCbStoreParam_p != NULL);
3145 // check if function pointer is NULL - if so, no callback should be called
3146 if (EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) != NULL) {
3148 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback)
3149 (EPL_MCO_INSTANCE_PARAM_IDX_()
3156 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3157 //---------------------------------------------------------------------------
3159 // Function: EplObdGetObjectDataPtrIntern()
3161 // Description: Function gets the data pointer of an object.
3162 // It returnes the current data pointer. But if object is an
3163 // constant object it returnes the default pointer.
3165 // Parameters: pSubindexEntry_p = pointer to subindex entry
3167 // Return: void * = pointer to object data
3171 //---------------------------------------------------------------------------
3173 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p)
3177 tEplObdAccess Access;
3179 ASSERTMSG(pSubindexEntry_p != NULL,
3180 "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
3182 // there are are some objects whose data pointer has to get from other structure
3183 // get access type for this object
3184 Access = pSubindexEntry_p->m_Access;
3186 // If object has access type = const,
3187 // for data only exists default values.
3188 if ((Access & kEplObdAccConst) != 0) {
3189 // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
3190 pData = ((void *)EplObdGetObjectDefaultPtr(pSubindexEntry_p));
3192 // The pointer to current value can be received from ObdGetObjectCurrentPtr()
3193 pData = ((void *)EplObdGetObjectCurrentPtr(pSubindexEntry_p));
3199 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)