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 INST_FAR m_ObdInitParam;
105 STATIC tEplObdStoreLoadObjCallback INST_NEAR 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 MEM*
124 EPL_MCO_DECL_INSTANCE_VAR()
126 BYTE MEM 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 MEM * 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 MEM ** 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 MEM * 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 MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
175 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
177 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
178 tEplObdCbStoreParam MEM *
181 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
183 static void EplObdCopyObjectData(void MEM * pDstData_p,
185 tEplObdSize ObjSize_p, tEplObdType ObjType_p);
187 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p);
189 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
190 BOOL * pfEntryNumerical_p);
192 static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_
193 unsigned int uiIndex_p,
194 unsigned int uiSubIndex_p,
198 tEplObdEntryPtr * ppObdEntry_p,
199 tEplObdSubEntryPtr * ppSubEntry_p,
200 tEplObdCbParam MEM * pCbParam_p,
201 tEplObdSize * pObdSize_p);
203 static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_
204 tEplObdEntryPtr pObdEntry_p,
205 tEplObdSubEntryPtr pSubEntry_p,
206 tEplObdCbParam MEM * pCbParam_p,
209 tEplObdSize ObdSize_p);
211 //=========================================================================//
213 // P U B L I C F U N C T I O N S //
215 //=========================================================================//
217 //---------------------------------------------------------------------------
219 // Function: EplObdInit()
221 // Description: initializes the first instance
223 // Parameters: pInitParam_p = init parameter
225 // Return: tEplKernel = errorcode
229 //---------------------------------------------------------------------------
231 EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_
232 tEplObdInitParam MEM * pInitParam_p)
236 EPL_MCO_DELETE_INSTANCE_TABLE();
238 if (pInitParam_p == NULL) {
239 Ret = kEplSuccessful;
243 Ret = EplObdAddInstance(EPL_MCO_PTR_INSTANCE_PTR_ pInitParam_p);
250 //---------------------------------------------------------------------------
252 // Function: EplObdAddInstance()
254 // Description: adds a new instance
256 // Parameters: pInitParam_p
258 // Return: tEplKernel
262 //---------------------------------------------------------------------------
264 EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_
265 tEplObdInitParam MEM *
269 EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret;
271 // check if pointer to instance pointer valid
272 // get free instance and set the globale instance pointer
273 // set also the instance addr to parameterlist
274 EPL_MCO_CHECK_PTR_INSTANCE_PTR();
275 EPL_MCO_GET_FREE_INSTANCE_PTR();
276 EPL_MCO_SET_PTR_INSTANCE_PTR();
278 // save init parameters
279 EPL_MEMCPY(&EPL_MCO_GLB_VAR(m_ObdInitParam), pInitParam_p,
280 sizeof(tEplObdInitParam));
282 // clear callback function for command LOAD and STORE
283 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = NULL;
285 // sign instance as used
286 EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed);
288 // initialize object dictionary
289 // so all all VarEntries will be initialized to trash object and default values will be set to current data
290 Ret = EplObdAccessOdPart(EPL_MCO_INSTANCE_PTR_
291 kEplObdPartAll, kEplObdDirInit);
297 //---------------------------------------------------------------------------
299 // Function: EplObdDeleteInstance()
301 // Description: delete instance
303 // Parameters: EPL_MCO_DECL_INSTANCE_PTR
305 // Return: tEplKernel
309 //---------------------------------------------------------------------------
310 #if (EPL_USE_DELETEINST_FUNC != FALSE)
311 EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR)
313 // check for all API function if instance is valid
314 EPL_MCO_CHECK_INSTANCE_STATE();
316 // sign instance as unused
317 EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused);
319 return kEplSuccessful;
322 #endif // (EPL_USE_DELETEINST_FUNC != FALSE)
324 //---------------------------------------------------------------------------
326 // Function: EplObdWriteEntry()
328 // Description: Function writes data to an OBD entry. Strings
329 // are stored with added '\0' character.
331 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
332 // uiIndex_p = Index of the OD entry
333 // uiSubIndex_p = Subindex of the OD Entry
334 // pSrcData_p = Pointer to the data to write
335 // Size_p = Size of the data in Byte
337 // Return: tEplKernel = Errorcode
342 //---------------------------------------------------------------------------
344 EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_
345 unsigned int uiIndex_p,
346 unsigned int uiSubIndex_p,
352 tEplObdEntryPtr pObdEntry;
353 tEplObdSubEntryPtr pSubEntry;
354 tEplObdCbParam MEM CbParam;
358 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
364 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
365 if (Ret != kEplSuccessful) {
369 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
372 &CbParam, pSrcData_p, pDstData, ObdSize);
373 if (Ret != kEplSuccessful) {
383 //---------------------------------------------------------------------------
385 // Function: EplObdReadEntry()
387 // Description: The function reads an object entry. The application
388 // can always read the data even if attrib kEplObdAccRead
389 // is not set. The attrib is only checked up for SDO transfer.
391 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
392 // uiIndex_p = Index oof the OD entry to read
393 // uiSubIndex_p = Subindex to read
394 // pDstData_p = pointer to the buffer for data
395 // Offset_p = offset in data for read access
396 // pSize_p = IN: Size of the buffer
397 // OUT: number of readed Bytes
399 // Return: tEplKernel
403 //---------------------------------------------------------------------------
405 EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_
406 unsigned int uiIndex_p,
407 unsigned int uiSubIndex_p,
409 tEplObdSize * pSize_p)
413 tEplObdEntryPtr pObdEntry;
414 tEplObdSubEntryPtr pSubEntry;
415 tEplObdCbParam MEM CbParam;
419 // check for all API function if instance is valid
420 EPL_MCO_CHECK_INSTANCE_STATE();
422 ASSERT(pDstData_p != NULL);
423 ASSERT(pSize_p != NULL);
425 // get address of index and subindex entry
426 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
427 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
428 if (Ret != kEplSuccessful) {
431 // get pointer to object data
432 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
434 // check source pointer
435 if (pSrcData == NULL) {
436 Ret = kEplObdReadViolation;
439 //------------------------------------------------------------------------
440 // address of source data to structure of callback parameters
441 // so callback function can change this data before reading
442 CbParam.m_uiIndex = uiIndex_p;
443 CbParam.m_uiSubIndex = uiSubIndex_p;
444 CbParam.m_pArg = pSrcData;
445 CbParam.m_ObdEvent = kEplObdEvPreRead;
446 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
447 pObdEntry->m_fpCallback, &CbParam);
448 if (Ret != kEplSuccessful) {
451 // get size of data and check if application has reserved enough memory
452 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
453 // check if offset given and calc correct number of bytes to read
454 if (*pSize_p < ObdSize) {
455 Ret = kEplObdValueLengthError;
458 // read value from object
459 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
462 // write address of destination data to structure of callback parameters
463 // so callback function can change this data after reading
464 CbParam.m_pArg = pDstData_p;
465 CbParam.m_ObdEvent = kEplObdEvPostRead;
466 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
467 pObdEntry->m_fpCallback, &CbParam);
475 //---------------------------------------------------------------------------
477 // Function: EplObdAccessOdPart()
479 // Description: restores default values of one part of OD
481 // Parameters: ObdPart_p
484 // Return: tEplKernel
488 //---------------------------------------------------------------------------
490 EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_
491 tEplObdPart ObdPart_p,
492 tEplObdDir Direction_p)
495 tEplKernel Ret = kEplSuccessful;
497 tEplObdEntryPtr pObdEntry;
499 // check for all API function if instance is valid
500 EPL_MCO_CHECK_INSTANCE_STATE();
502 // part always has to be unequal to NULL
503 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pPart);
504 ASSERTMSG(pObdEntry != NULL,
505 "EplObdAccessOdPart(): no OD part is defined!\n");
507 // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
511 if ((ObdPart_p & kEplObdPartGen) != 0) {
514 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
515 kEplObdPartGen, pObdEntry,
517 if (Ret != kEplSuccessful) {
521 // access to manufacturer part
522 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pManufacturerPart);
524 if (((ObdPart_p & kEplObdPartMan) != 0) && (pObdEntry != NULL)) {
527 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
528 kEplObdPartMan, pObdEntry,
530 if (Ret != kEplSuccessful) {
534 // access to device part
535 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pDevicePart);
537 if (((ObdPart_p & kEplObdPartDev) != 0) && (pObdEntry != NULL)) {
540 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
541 kEplObdPartDev, pObdEntry,
543 if (Ret != kEplSuccessful) {
547 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
549 // access to user part
550 pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart);
552 if (((ObdPart_p & kEplObdPartUsr) != 0) && (pObdEntry != NULL)) {
555 Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
557 pObdEntry, Direction_p);
558 if (Ret != kEplSuccessful) {
565 // no access to an OD part was done? illegal OD part was specified!
566 if (fPartFount == FALSE) {
567 Ret = kEplObdIllegalPart;
576 //---------------------------------------------------------------------------
578 // Function: EplObdDefineVar()
580 // Description: defines a variable in OD
582 // Parameters: pEplVarParam_p
584 // Return: tEplKernel
588 //---------------------------------------------------------------------------
590 EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_
591 tEplVarParam MEM * pVarParam_p)
595 tEplObdVarEntry MEM *pVarEntry;
596 tEplVarParamValid VarValid;
597 tEplObdSubEntryPtr pSubindexEntry;
599 // check for all API function if instance is valid
600 EPL_MCO_CHECK_INSTANCE_STATE();
602 ASSERT(pVarParam_p != NULL); // is not allowed to be NULL
604 // get address of subindex entry
605 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
606 pVarParam_p->m_uiIndex,
607 pVarParam_p->m_uiSubindex, NULL, &pSubindexEntry);
608 if (Ret != kEplSuccessful) {
612 Ret = EplObdGetVarEntry(pSubindexEntry, &pVarEntry);
613 if (Ret != kEplSuccessful) {
617 VarValid = pVarParam_p->m_ValidFlag;
619 // copy only this values, which valid flag is set
620 if ((VarValid & kVarValidSize) != 0) {
621 if (pSubindexEntry->m_Type != kEplObdTypDomain) {
622 tEplObdSize DataSize;
624 // check passed size parameter
625 DataSize = EplObdGetObjectSize(pSubindexEntry);
626 if (DataSize != pVarParam_p->m_Size) { // size of variable does not match
627 Ret = kEplObdValueLengthError;
630 } else { // size can be set only for objects of type DOMAIN
631 pVarEntry->m_Size = pVarParam_p->m_Size;
635 if ((VarValid & kVarValidData) != 0) {
636 pVarEntry->m_pData = pVarParam_p->m_pData;
639 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
641 if ((VarValid & kVarValidCallback) != 0)
643 pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
646 if ((VarValid & kVarValidArg) != 0)
648 pVarEntry->m_pArg = pVarParam_p->m_pArg;
653 // Ret is already set to kEplSuccessful from ObdGetVarIntern()
661 //---------------------------------------------------------------------------
663 // Function: EplObdGetObjectDataPtr()
665 // Description: It returnes the current data pointer. But if object is an
666 // constant object it returnes the default pointer.
668 // Parameters: uiIndex_p = Index of the entry
669 // uiSubindex_p = Subindex of the entry
671 // Return: void * = pointer to object data
675 //---------------------------------------------------------------------------
677 EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_
678 unsigned int uiIndex_p,
679 unsigned int uiSubIndex_p)
683 tEplObdEntryPtr pObdEntry;
684 tEplObdSubEntryPtr pObdSubEntry;
686 // get pointer to index structure
687 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
688 uiIndex_p, &pObdEntry);
689 if (Ret != kEplSuccessful) {
693 // get pointer to subindex structure
694 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
695 if (Ret != kEplSuccessful) {
700 pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
707 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
709 //---------------------------------------------------------------------------
711 // Function: EplObdRegisterUserOd()
713 // Description: function registers the user OD
715 // Parameters: pUserOd_p =pointer to user ODd
717 // Return: tEplKernel = errorcode
721 //---------------------------------------------------------------------------
722 EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_
723 tEplObdEntryPtr pUserOd_p)
726 EPL_MCO_CHECK_INSTANCE_STATE();
728 EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart) = pUserOd_p;
730 return kEplSuccessful;
736 //---------------------------------------------------------------------------
738 // Function: EplObdInitVarEntry()
740 // Description: function to initialize VarEntry dependened on object type
742 // Parameters: pVarEntry_p = pointer to var entry structure
743 // Type_p = object type
744 // ObdSize_p = size of object data
750 //---------------------------------------------------------------------------
752 EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
753 tEplObdVarEntry MEM * pVarEntry_p,
755 tEplObdSize ObdSize_p)
758 #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
760 // reset pointer to VAR callback and argument
761 pVarEntry_p->m_fpCallback = NULL;
762 pVarEntry_p->m_pArg = NULL;
767 // 10-dec-2004 r.d.: this function will not be used for strings
768 if ((Type_p == kEplObdTypDomain))
769 // (bType_p == kEplObdTypVString) /* ||
770 // (bType_p == kEplObdTypOString) ||
771 // (bType_p == kEplObdTypUString) */ )
773 // variables which are defined as DOMAIN or VSTRING should not point to
774 // trash object, because this trash object contains only 8 bytes. DOMAINS or
775 // STRINGS can be longer.
776 pVarEntry_p->m_pData = NULL;
777 pVarEntry_p->m_Size = 0;
779 // set address to variable data to trash object
780 // This prevents an access violation if user forgets to call EplObdDefineVar()
781 // for this variable but mappes it in a PDO.
782 pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
783 pVarEntry_p->m_Size = ObdSize_p;
788 //---------------------------------------------------------------------------
790 // Function: EplObdGetDataSize()
792 // Description: function to initialize VarEntry dependened on object type
794 // gets the data size of an object
795 // for string objects it returnes the string length
797 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
799 // uiSubIndex_p= Subindex
801 // Return: tEplObdSize
805 //---------------------------------------------------------------------------
806 EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_
807 unsigned int uiIndex_p,
808 unsigned int uiSubIndex_p)
812 tEplObdEntryPtr pObdEntry;
813 tEplObdSubEntryPtr pObdSubEntry;
815 // get pointer to index structure
816 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
817 uiIndex_p, &pObdEntry);
818 if (Ret != kEplSuccessful) {
822 // get pointer to subindex structure
823 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
824 if (Ret != kEplSuccessful) {
829 ObdSize = EplObdGetDataSizeIntern(pObdSubEntry);
834 //---------------------------------------------------------------------------
836 // Function: EplObdGetNodeId()
838 // Description: function returns nodeid from entry 0x1F93
841 // Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
843 // Return: unsigned int = Node Id
847 //---------------------------------------------------------------------------
848 EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
855 ObdSize = sizeof(bNodeId);
856 Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
857 EPL_OBD_NODE_ID_INDEX,
858 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, &ObdSize);
859 if (Ret != kEplSuccessful) {
860 bNodeId = EPL_C_ADR_INVALID;
865 return (unsigned int)bNodeId;
869 //---------------------------------------------------------------------------
871 // Function: EplObdSetNodeId()
873 // Description: function sets nodeid in entry 0x1F93
876 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
877 // uiNodeId_p = Node Id to set
878 // NodeIdType_p= Type on which way the Node Id was set
880 // Return: tEplKernel = Errorcode
884 //---------------------------------------------------------------------------
885 EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_
886 unsigned int uiNodeId_p,
887 tEplObdNodeIdType NodeIdType_p)
895 if (uiNodeId_p == EPL_C_ADR_INVALID) {
896 Ret = kEplInvalidNodeId;
899 bNodeId = (BYTE) uiNodeId_p;
900 ObdSize = sizeof(BYTE);
901 // write NodeId to OD entry
902 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
903 EPL_OBD_NODE_ID_INDEX,
904 EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, ObdSize);
905 if (Ret != kEplSuccessful) {
908 // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
909 switch (NodeIdType_p) {
911 case kEplObdNodeIdUnknown:
917 case kEplObdNodeIdSoftware:
923 case kEplObdNodeIdHardware:
934 } // end of switch (NodeIdType_p)
937 ObdSize = sizeof(fHwBool);
938 Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
939 EPL_OBD_NODE_ID_INDEX,
940 EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
942 if (Ret != kEplSuccessful) {
950 //---------------------------------------------------------------------------
952 // Function: EplObdIsNumerical()
954 // Description: function checks if a entry is numerical or not
957 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
959 // uiSubIndex_p = Subindex
960 // pfEntryNumerical_p = pointer to BOOL for returnvalue
961 // -> TRUE if entry a numerical value
962 // -> FALSE if entry not a numerical value
964 // Return: tEplKernel = Errorcode
968 //---------------------------------------------------------------------------
969 EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_
970 unsigned int uiIndex_p,
971 unsigned int uiSubIndex_p,
972 BOOL * pfEntryNumerical_p)
975 tEplObdEntryPtr pObdEntry;
976 tEplObdSubEntryPtr pObdSubEntry;
978 // get pointer to index structure
979 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
980 uiIndex_p, &pObdEntry);
981 if (Ret != kEplSuccessful) {
984 // get pointer to subindex structure
985 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
986 if (Ret != kEplSuccessful) {
990 Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
997 //---------------------------------------------------------------------------
999 // Function: EplObdReadEntryToLe()
1001 // Description: The function reads an object entry from the byteoder
1002 // of the system to the little endian byteorder for numerical values.
1003 // For other types a normal read will be processed. This is usefull for
1004 // the PDO and SDO module. The application
1005 // can always read the data even if attrib kEplObdAccRead
1006 // is not set. The attrib is only checked up for SDO transfer.
1008 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1009 // uiIndex_p = Index of the OD entry to read
1010 // uiSubIndex_p = Subindex to read
1011 // pDstData_p = pointer to the buffer for data
1012 // Offset_p = offset in data for read access
1013 // pSize_p = IN: Size of the buffer
1014 // OUT: number of readed Bytes
1016 // Return: tEplKernel
1020 //---------------------------------------------------------------------------
1021 EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_
1022 unsigned int uiIndex_p,
1023 unsigned int uiSubIndex_p,
1025 tEplObdSize * pSize_p)
1028 tEplObdEntryPtr pObdEntry;
1029 tEplObdSubEntryPtr pSubEntry;
1030 tEplObdCbParam MEM CbParam;
1032 tEplObdSize ObdSize;
1034 // check for all API function if instance is valid
1035 EPL_MCO_CHECK_INSTANCE_STATE();
1037 ASSERT(pDstData_p != NULL);
1038 ASSERT(pSize_p != NULL);
1040 // get address of index and subindex entry
1041 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1042 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1043 if (Ret != kEplSuccessful) {
1046 // get pointer to object data
1047 pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
1049 // check source pointer
1050 if (pSrcData == NULL) {
1051 Ret = kEplObdReadViolation;
1054 //------------------------------------------------------------------------
1055 // address of source data to structure of callback parameters
1056 // so callback function can change this data before reading
1057 CbParam.m_uiIndex = uiIndex_p;
1058 CbParam.m_uiSubIndex = uiSubIndex_p;
1059 CbParam.m_pArg = pSrcData;
1060 CbParam.m_ObdEvent = kEplObdEvPreRead;
1061 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1062 pObdEntry->m_fpCallback, &CbParam);
1063 if (Ret != kEplSuccessful) {
1066 // get size of data and check if application has reserved enough memory
1067 ObdSize = EplObdGetDataSizeIntern(pSubEntry);
1068 // check if offset given and calc correct number of bytes to read
1069 if (*pSize_p < ObdSize) {
1070 Ret = kEplObdValueLengthError;
1073 // check if numerical type
1074 switch (pSubEntry->m_Type) {
1075 //-----------------------------------------------
1076 // types without ami
1077 case kEplObdTypVString:
1078 case kEplObdTypOString:
1079 case kEplObdTypDomain:
1082 // read value from object
1083 EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
1087 //-----------------------------------------------
1088 // numerical type which needs ami-write
1089 // 8 bit or smaller values
1090 case kEplObdTypBool:
1091 case kEplObdTypInt8:
1092 case kEplObdTypUInt8:
1094 AmiSetByteToLe(pDstData_p, *((BYTE *) pSrcData));
1099 case kEplObdTypInt16:
1100 case kEplObdTypUInt16:
1102 AmiSetWordToLe(pDstData_p, *((WORD *) pSrcData));
1107 case kEplObdTypInt24:
1108 case kEplObdTypUInt24:
1110 AmiSetDword24ToLe(pDstData_p, *((DWORD *) pSrcData));
1115 case kEplObdTypInt32:
1116 case kEplObdTypUInt32:
1117 case kEplObdTypReal32:
1119 AmiSetDwordToLe(pDstData_p, *((DWORD *) pSrcData));
1124 case kEplObdTypInt40:
1125 case kEplObdTypUInt40:
1127 AmiSetQword40ToLe(pDstData_p, *((QWORD *) pSrcData));
1132 case kEplObdTypInt48:
1133 case kEplObdTypUInt48:
1135 AmiSetQword48ToLe(pDstData_p, *((QWORD *) pSrcData));
1140 case kEplObdTypInt56:
1141 case kEplObdTypUInt56:
1143 AmiSetQword56ToLe(pDstData_p, *((QWORD *) pSrcData));
1148 case kEplObdTypInt64:
1149 case kEplObdTypUInt64:
1150 case kEplObdTypReal64:
1152 AmiSetQword64ToLe(pDstData_p, *((QWORD *) pSrcData));
1157 case kEplObdTypTimeOfDay:
1158 case kEplObdTypTimeDiff:
1160 AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay *) pSrcData));
1164 } // end of switch(pSubEntry->m_Type)
1168 // write address of destination data to structure of callback parameters
1169 // so callback function can change this data after reading
1170 CbParam.m_pArg = pDstData_p;
1171 CbParam.m_ObdEvent = kEplObdEvPostRead;
1172 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1173 pObdEntry->m_fpCallback, &CbParam);
1181 //---------------------------------------------------------------------------
1183 // Function: EplObdWriteEntryFromLe()
1185 // Description: Function writes data to an OBD entry from a source with
1186 // little endian byteorder to the od with system specuific
1187 // byteorder. Not numerical values will only by copied. Strings
1188 // are stored with added '\0' character.
1190 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1191 // uiIndex_p = Index of the OD entry
1192 // uiSubIndex_p = Subindex of the OD Entry
1193 // pSrcData_p = Pointer to the data to write
1194 // Size_p = Size of the data in Byte
1196 // Return: tEplKernel = Errorcode
1201 //---------------------------------------------------------------------------
1202 EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_
1203 unsigned int uiIndex_p,
1204 unsigned int uiSubIndex_p,
1209 tEplObdEntryPtr pObdEntry;
1210 tEplObdSubEntryPtr pSubEntry;
1211 tEplObdCbParam MEM CbParam;
1213 tEplObdSize ObdSize;
1215 void *pBuffer = &qwBuffer;
1217 Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
1223 &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
1224 if (Ret != kEplSuccessful) {
1228 // check if numerical type
1229 switch (pSubEntry->m_Type) {
1230 //-----------------------------------------------
1231 // types without ami
1233 { // do nothing, i.e. use the given source pointer
1234 pBuffer = pSrcData_p;
1238 //-----------------------------------------------
1239 // numerical type which needs ami-write
1240 // 8 bit or smaller values
1241 case kEplObdTypBool:
1242 case kEplObdTypInt8:
1243 case kEplObdTypUInt8:
1245 *((BYTE *) pBuffer) = AmiGetByteFromLe(pSrcData_p);
1250 case kEplObdTypInt16:
1251 case kEplObdTypUInt16:
1253 *((WORD *) pBuffer) = AmiGetWordFromLe(pSrcData_p);
1258 case kEplObdTypInt24:
1259 case kEplObdTypUInt24:
1261 *((DWORD *) pBuffer) = AmiGetDword24FromLe(pSrcData_p);
1266 case kEplObdTypInt32:
1267 case kEplObdTypUInt32:
1268 case kEplObdTypReal32:
1270 *((DWORD *) pBuffer) = AmiGetDwordFromLe(pSrcData_p);
1275 case kEplObdTypInt40:
1276 case kEplObdTypUInt40:
1278 *((QWORD *) pBuffer) = AmiGetQword40FromLe(pSrcData_p);
1283 case kEplObdTypInt48:
1284 case kEplObdTypUInt48:
1286 *((QWORD *) pBuffer) = AmiGetQword48FromLe(pSrcData_p);
1291 case kEplObdTypInt56:
1292 case kEplObdTypUInt56:
1294 *((QWORD *) pBuffer) = AmiGetQword56FromLe(pSrcData_p);
1299 case kEplObdTypInt64:
1300 case kEplObdTypUInt64:
1301 case kEplObdTypReal64:
1303 *((QWORD *) pBuffer) = AmiGetQword64FromLe(pSrcData_p);
1308 case kEplObdTypTimeOfDay:
1309 case kEplObdTypTimeDiff:
1311 AmiGetTimeOfDay(pBuffer, ((tTimeOfDay *) pSrcData_p));
1315 } // end of switch(pSubEntry->m_Type)
1317 Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
1320 &CbParam, pBuffer, pDstData, ObdSize);
1321 if (Ret != kEplSuccessful) {
1331 //---------------------------------------------------------------------------
1333 // Function: EplObdGetAccessType()
1335 // Description: Function returns accesstype of the entry
1337 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1338 // uiIndex_p = Index of the OD entry
1339 // uiSubIndex_p = Subindex of the OD Entry
1340 // pAccessTyp_p = pointer to buffer to store accesstype
1342 // Return: tEplKernel = errorcode
1347 //---------------------------------------------------------------------------
1348 EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_
1349 unsigned int uiIndex_p,
1350 unsigned int uiSubIndex_p,
1351 tEplObdAccess * pAccessTyp_p)
1354 tEplObdEntryPtr pObdEntry;
1355 tEplObdSubEntryPtr pObdSubEntry;
1357 // get pointer to index structure
1358 Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
1359 uiIndex_p, &pObdEntry);
1360 if (Ret != kEplSuccessful) {
1363 // get pointer to subindex structure
1364 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
1365 if (Ret != kEplSuccessful) {
1369 *pAccessTyp_p = pObdSubEntry->m_Access;
1375 //---------------------------------------------------------------------------
1377 // Function: EplObdSearchVarEntry()
1379 // Description: gets variable from OD
1381 // Parameters: uiIndex_p = index of the var entry to search
1382 // uiSubindex_p = subindex of var entry to search
1383 // ppVarEntry_p = pointer to the pointer to the varentry
1385 // Return: tEplKernel
1389 //---------------------------------------------------------------------------
1391 tEplKernel PUBLIC EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
1392 unsigned int uiIndex_p,
1393 unsigned int uiSubindex_p,
1394 tEplObdVarEntry MEM ** ppVarEntry_p)
1398 tEplObdSubEntryPtr pSubindexEntry;
1400 // check for all API function if instance is valid
1401 EPL_MCO_CHECK_INSTANCE_STATE();
1403 // get address of subindex entry
1404 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1405 uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
1406 if (Ret == kEplSuccessful) {
1408 Ret = EplObdGetVarEntry(pSubindexEntry, ppVarEntry_p);
1415 //=========================================================================//
1417 // P R I V A T E D E F I N I T I O N S //
1419 //=========================================================================//
1421 EPL_MCO_DECL_INSTANCE_FCT()
1422 //---------------------------------------------------------------------------
1424 // Function: EplObdCallObjectCallback()
1426 // Description: calls callback function of an object or of a variable
1428 // Parameters: fpCallback_p
1431 // Return: tEplKernel
1435 //---------------------------------------------------------------------------
1436 static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
1437 tEplObdCallback fpCallback_p,
1438 tEplObdCbParam MEM * pCbParam_p)
1442 tEplObdCallback MEM fpCallback;
1444 // check for all API function if instance is valid
1445 EPL_MCO_CHECK_INSTANCE_STATE();
1447 ASSERT(pCbParam_p != NULL);
1449 Ret = kEplSuccessful;
1451 // check address of callback function before calling it
1452 if (fpCallback_p != NULL) {
1453 // KEIL C51 V6.01 has a bug.
1454 // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
1455 fpCallback = fpCallback_p;
1457 // call callback function for this object
1458 Ret = fpCallback(EPL_MCO_INSTANCE_PARAM_IDX_()
1465 //---------------------------------------------------------------------------
1467 // Function: EplObdGetDataSizeIntern()
1469 // Description: gets the data size of an object
1470 // for string objects it returnes the string length
1472 // Parameters: pSubIndexEntry_p
1474 // Return: tEplObdSize
1478 //---------------------------------------------------------------------------
1480 static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p)
1483 tEplObdSize DataSize;
1486 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
1487 // then the current pointer is always NULL. The function
1488 // returns the length of default string.
1489 DataSize = EplObdGetObjectSize(pSubIndexEntry_p);
1491 if (pSubIndexEntry_p->m_Type == kEplObdTypVString) {
1492 // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
1494 ((void MEM *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p));
1495 if (pData != NULL) {
1497 EplObdGetStrLen((void *)pData, DataSize,
1498 pSubIndexEntry_p->m_Type);
1507 //---------------------------------------------------------------------------
1509 // Function: EplObdGetStrLen()
1511 // Description: The function calculates the length of string. The '\0'
1512 // character is included!!
1514 // Parameters: pObjData_p = pointer to string
1515 // ObjLen_p = max. length of objectr entry
1516 // bObjType_p = object type (VSTRING, ...)
1518 // Returns: string length + 1
1522 //---------------------------------------------------------------------------
1524 static tEplObdSize EplObdGetStrLen(void *pObjData_p,
1525 tEplObdSize ObjLen_p, tEplObdType ObjType_p)
1528 tEplObdSize StrLen = 0;
1531 if (pObjData_p == NULL) {
1534 //----------------------------------------
1535 // Visible String: data format byte
1536 if (ObjType_p == kEplObdTypVString) {
1537 pbString = pObjData_p;
1539 for (StrLen = 0; StrLen < ObjLen_p; StrLen++) {
1540 if (*pbString == '\0') {
1548 //----------------------------------------
1549 // other string types ...
1556 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1558 //---------------------------------------------------------------------------
1560 // Function: EplObdCheckObjectRange()
1562 // Description: function to check value range of object data
1564 // NOTICE: The pointer of data (pData_p) must point out to an even address,
1565 // if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
1566 // always realiced because pointer m_pDefault points always to an
1567 // array of the SPECIFIED type.
1569 // Parameters: pSubindexEntry_p
1572 // Return: tEplKernel
1576 //---------------------------------------------------------------------------
1578 static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
1585 ASSERTMSG(pSubindexEntry_p != NULL,
1586 "EplObdCheckObjectRange(): no address to subindex struct!\n");
1588 Ret = kEplSuccessful;
1590 // check if data range has to be checked
1591 if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) {
1594 // get address of default data
1595 pRangeData = pSubindexEntry_p->m_pDefault;
1597 // jump to called object type
1598 switch ((tEplObdType) pSubindexEntry_p->m_Type) {
1599 // -----------------------------------------------------------------
1600 // ObdType kEplObdTypBool will not be checked because there are only
1601 // two possible values 0 or 1.
1603 // -----------------------------------------------------------------
1604 // ObdTypes which has to be check up because numerical values
1605 case kEplObdTypInt8:
1607 // switch to lower limit
1608 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1610 // check if value is to low
1611 if (*((tEplObdInteger8 *) pData_p) <
1612 *((tEplObdInteger8 *) pRangeData)) {
1613 Ret = kEplObdValueTooLow;
1616 // switch to higher limit
1617 pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
1619 // check if value is to high
1620 if (*((tEplObdInteger8 *) pData_p) >
1621 *((tEplObdInteger8 *) pRangeData)) {
1622 Ret = kEplObdValueTooHigh;
1627 case kEplObdTypUInt8:
1629 // switch to lower limit
1630 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1632 // check if value is to low
1633 if (*((tEplObdUnsigned8 *) pData_p) <
1634 *((tEplObdUnsigned8 *) pRangeData)) {
1635 Ret = kEplObdValueTooLow;
1638 // switch to higher limit
1639 pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
1641 // check if value is to high
1642 if (*((tEplObdUnsigned8 *) pData_p) >
1643 *((tEplObdUnsigned8 *) pRangeData)) {
1644 Ret = kEplObdValueTooHigh;
1649 case kEplObdTypInt16:
1651 // switch to lower limit
1652 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1654 // check if value is to low
1655 if (*((tEplObdInteger16 *) pData_p) <
1656 *((tEplObdInteger16 *) pRangeData)) {
1657 Ret = kEplObdValueTooLow;
1660 // switch to higher limit
1661 pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
1663 // check if value is to high
1664 if (*((tEplObdInteger16 *) pData_p) >
1665 *((tEplObdInteger16 *) pRangeData)) {
1666 Ret = kEplObdValueTooHigh;
1671 case kEplObdTypUInt16:
1673 // switch to lower limit
1674 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1676 // check if value is to low
1677 if (*((tEplObdUnsigned16 *) pData_p) <
1678 *((tEplObdUnsigned16 *) pRangeData)) {
1679 Ret = kEplObdValueTooLow;
1682 // switch to higher limit
1683 pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
1685 // check if value is to high
1686 if (*((tEplObdUnsigned16 *) pData_p) >
1687 *((tEplObdUnsigned16 *) pRangeData)) {
1688 Ret = kEplObdValueTooHigh;
1693 case kEplObdTypInt32:
1695 // switch to lower limit
1696 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1698 // check if value is to low
1699 if (*((tEplObdInteger32 *) pData_p) <
1700 *((tEplObdInteger32 *) pRangeData)) {
1701 Ret = kEplObdValueTooLow;
1704 // switch to higher limit
1705 pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
1707 // check if value is to high
1708 if (*((tEplObdInteger32 *) pData_p) >
1709 *((tEplObdInteger32 *) pRangeData)) {
1710 Ret = kEplObdValueTooHigh;
1715 case kEplObdTypUInt32:
1717 // switch to lower limit
1718 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1720 // check if value is to low
1721 if (*((tEplObdUnsigned32 *) pData_p) <
1722 *((tEplObdUnsigned32 *) pRangeData)) {
1723 Ret = kEplObdValueTooLow;
1726 // switch to higher limit
1727 pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
1729 // check if value is to high
1730 if (*((tEplObdUnsigned32 *) pData_p) >
1731 *((tEplObdUnsigned32 *) pRangeData)) {
1732 Ret = kEplObdValueTooHigh;
1737 case kEplObdTypReal32:
1739 // switch to lower limit
1740 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1742 // check if value is to low
1743 if (*((tEplObdReal32 *) pData_p) <
1744 *((tEplObdReal32 *) pRangeData)) {
1745 Ret = kEplObdValueTooLow;
1748 // switch to higher limit
1749 pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
1751 // check if value is to high
1752 if (*((tEplObdReal32 *) pData_p) >
1753 *((tEplObdReal32 *) pRangeData)) {
1754 Ret = kEplObdValueTooHigh;
1759 // -----------------------------------------------------------------
1760 case kEplObdTypInt40:
1761 case kEplObdTypInt48:
1762 case kEplObdTypInt56:
1763 case kEplObdTypInt64:
1765 // switch to lower limit
1766 pRangeData = ((signed QWORD *)pRangeData) + 1;
1768 // check if value is to low
1769 if (*((signed QWORD *)pData_p) < *((signed QWORD *)pRangeData)) {
1770 Ret = kEplObdValueTooLow;
1773 // switch to higher limit
1774 pRangeData = ((signed QWORD *)pRangeData) + 1;
1776 // check if value is to high
1777 if (*((signed QWORD *)pData_p) > *((signed QWORD *)pRangeData)) {
1778 Ret = kEplObdValueTooHigh;
1783 // -----------------------------------------------------------------
1784 case kEplObdTypUInt40:
1785 case kEplObdTypUInt48:
1786 case kEplObdTypUInt56:
1787 case kEplObdTypUInt64:
1789 // switch to lower limit
1790 pRangeData = ((unsigned QWORD *)pRangeData) + 1;
1792 // check if value is to low
1793 if (*((unsigned QWORD *)pData_p) <
1794 *((unsigned QWORD *)pRangeData)) {
1795 Ret = kEplObdValueTooLow;
1798 // switch to higher limit
1799 pRangeData = ((unsigned QWORD *)pRangeData) + 1;
1801 // check if value is to high
1802 if (*((unsigned QWORD *)pData_p) >
1803 *((unsigned QWORD *)pRangeData)) {
1804 Ret = kEplObdValueTooHigh;
1809 // -----------------------------------------------------------------
1810 case kEplObdTypReal64:
1812 // switch to lower limit
1813 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1815 // check if value is to low
1816 if (*((tEplObdReal64 *) pData_p) <
1817 *((tEplObdReal64 *) pRangeData)) {
1818 Ret = kEplObdValueTooLow;
1821 // switch to higher limit
1822 pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
1824 // check if value is to high
1825 if (*((tEplObdReal64 *) pData_p) >
1826 *((tEplObdReal64 *) pRangeData)) {
1827 Ret = kEplObdValueTooHigh;
1832 // -----------------------------------------------------------------
1833 case kEplObdTypTimeOfDay:
1834 case kEplObdTypTimeDiff:
1837 // -----------------------------------------------------------------
1838 // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
1839 // they have no numerical value.
1842 Ret = kEplObdUnknownObjectType;
1851 #endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
1853 //---------------------------------------------------------------------------
1855 // Function: EplObdWriteEntryPre()
1857 // Description: Function prepares write of data to an OBD entry. Strings
1858 // are stored with added '\0' character.
1860 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
1861 // uiIndex_p = Index of the OD entry
1862 // uiSubIndex_p = Subindex of the OD Entry
1863 // pSrcData_p = Pointer to the data to write
1864 // Size_p = Size of the data in Byte
1866 // Return: tEplKernel = Errorcode
1871 //---------------------------------------------------------------------------
1873 static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_
1874 unsigned int uiIndex_p,
1875 unsigned int uiSubIndex_p,
1879 tEplObdEntryPtr * ppObdEntry_p,
1880 tEplObdSubEntryPtr * ppSubEntry_p,
1881 tEplObdCbParam MEM * pCbParam_p,
1882 tEplObdSize * pObdSize_p)
1886 tEplObdEntryPtr pObdEntry;
1887 tEplObdSubEntryPtr pSubEntry;
1888 tEplObdAccess Access;
1890 tEplObdSize ObdSize;
1891 BOOL fEntryNumerical;
1893 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1894 tEplObdVStringDomain MEM MemVStringDomain;
1895 void MEM *pCurrData;
1898 // check for all API function if instance is valid
1899 EPL_MCO_CHECK_INSTANCE_STATE();
1901 ASSERT(pSrcData_p != NULL); // should never be NULL
1903 //------------------------------------------------------------------------
1904 // get address of index and subindex entry
1905 Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
1906 uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
1907 if (Ret != kEplSuccessful) {
1910 // get pointer to object data
1911 pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry);
1913 Access = (tEplObdAccess) pSubEntry->m_Access;
1915 // check access for write
1916 // access violation if adress to current value is NULL
1917 if (((Access & kEplObdAccConst) != 0) || (pDstData == NULL)) {
1918 Ret = kEplObdAccessViolation;
1921 //------------------------------------------------------------------------
1922 // get size of object
1923 // -as ObdSize = ObdGetObjectSize (pSubEntry);
1925 //------------------------------------------------------------------------
1926 // To use the same callback function for ObdWriteEntry as well as for
1927 // an SDO download call at first (kEplObdEvPre...) the callback function
1928 // with the argument pointer to object size.
1929 pCbParam_p->m_uiIndex = uiIndex_p;
1930 pCbParam_p->m_uiSubIndex = uiSubIndex_p;
1932 // Because object size and object pointer are
1933 // adapted by user callback function, re-read
1935 ObdSize = EplObdGetObjectSize(pSubEntry);
1936 pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry);
1938 // 09-dec-2004 r.d.:
1939 // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
1940 // for String or Domain which lets called module directly change
1941 // the data pointer or size. This prevents a recursive call to
1942 // the callback function if it calls EplObdGetEntry().
1943 #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1944 if ((pSubEntry->m_Type == kEplObdTypVString) ||
1945 (pSubEntry->m_Type == kEplObdTypDomain) ||
1946 (pSubEntry->m_Type == kEplObdTypOString)) {
1947 if (pSubEntry->m_Type == kEplObdTypVString) {
1948 // reserve one byte for 0-termination
1949 // -as ObdSize -= 1;
1952 // fill out new arg-struct
1953 MemVStringDomain.m_DownloadSize = Size_p;
1954 MemVStringDomain.m_ObjSize = ObdSize;
1955 MemVStringDomain.m_pData = pDstData;
1957 pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
1958 pCbParam_p->m_pArg = &MemVStringDomain;
1959 // call user callback
1960 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1961 pObdEntry->m_fpCallback,
1963 if (Ret != kEplSuccessful) {
1966 // write back new settings
1967 pCurrData = pSubEntry->m_pCurrent;
1968 if ((pSubEntry->m_Type == kEplObdTypVString)
1969 || (pSubEntry->m_Type == kEplObdTypOString)) {
1970 ((tEplObdVString MEM *) pCurrData)->m_Size =
1971 MemVStringDomain.m_ObjSize;
1972 ((tEplObdVString MEM *) pCurrData)->m_pString =
1973 MemVStringDomain.m_pData;
1974 } else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
1976 ((tEplObdVarEntry MEM *) pCurrData)->m_Size =
1977 MemVStringDomain.m_ObjSize;
1978 ((tEplObdVarEntry MEM *) pCurrData)->m_pData =
1979 (void MEM *)MemVStringDomain.m_pData;
1982 // Because object size and object pointer are
1983 // adapted by user callback function, re-read
1985 ObdSize = MemVStringDomain.m_ObjSize;
1986 pDstData = (void MEM *)MemVStringDomain.m_pData;
1988 #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
1990 // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
1991 // -as 16.11.04 CbParam.m_pArg = &ObdSize;
1992 // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p;
1993 pCbParam_p->m_pArg = &ObdSize;
1994 pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
1995 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
1996 pObdEntry->m_fpCallback, pCbParam_p);
1997 if (Ret != kEplSuccessful) {
2001 if (Size_p > ObdSize) {
2002 Ret = kEplObdValueLengthError;
2006 if (pSubEntry->m_Type == kEplObdTypVString) {
2007 if (((char MEM *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character
2009 // reserve one byte in destination for 0-termination
2011 } else if (Size_p >= ObdSize) { // source string is not 0-terminated
2012 // and destination buffer is too short
2013 Ret = kEplObdValueLengthError;
2018 Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
2019 if (Ret != kEplSuccessful) {
2023 if ((fEntryNumerical != FALSE)
2024 && (Size_p != ObdSize)) {
2025 // type is numerical, therefor size has to fit, but it does not.
2026 Ret = kEplObdValueLengthError;
2029 // use given size, because non-numerical objects can be written with shorter values
2032 // set output parameters
2033 *pObdSize_p = ObdSize;
2034 *ppObdEntry_p = pObdEntry;
2035 *ppSubEntry_p = pSubEntry;
2036 *ppDstData_p = pDstData;
2038 // all checks are done
2039 // the caller may now convert the numerial source value to platform byte order in a temporary buffer
2047 //---------------------------------------------------------------------------
2049 // Function: EplObdWriteEntryPost()
2051 // Description: Function finishes write of data to an OBD entry. Strings
2052 // are stored with added '\0' character.
2054 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_
2055 // uiIndex_p = Index of the OD entry
2056 // uiSubIndex_p = Subindex of the OD Entry
2057 // pSrcData_p = Pointer to the data to write
2058 // Size_p = Size of the data in Byte
2060 // Return: tEplKernel = Errorcode
2065 //---------------------------------------------------------------------------
2067 static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_
2068 tEplObdEntryPtr pObdEntry_p,
2069 tEplObdSubEntryPtr pSubEntry_p,
2070 tEplObdCbParam MEM * pCbParam_p,
2073 tEplObdSize ObdSize_p)
2078 // caller converted the source value to platform byte order
2079 // now the range of the value may be checked
2081 #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
2084 Ret = EplObdCheckObjectRange(pSubEntry_p, pSrcData_p);
2085 if (Ret != kEplSuccessful) {
2091 // now call user callback function to check value
2092 // write address of source data to structure of callback parameters
2093 // so callback function can check this data
2094 pCbParam_p->m_pArg = pSrcData_p;
2095 pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
2096 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2097 pObdEntry_p->m_fpCallback, pCbParam_p);
2098 if (Ret != kEplSuccessful) {
2101 // copy object data to OBD
2102 EPL_MEMCPY(pDstData_p, pSrcData_p, ObdSize_p);
2104 // terminate string with 0
2105 if (pSubEntry_p->m_Type == kEplObdTypVString) {
2106 ((char MEM *)pDstData_p)[ObdSize_p] = '\0';
2108 // write address of destination to structure of callback parameters
2109 // so callback function can change data subsequently
2110 pCbParam_p->m_pArg = pDstData_p;
2111 pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
2112 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2113 pObdEntry_p->m_fpCallback, pCbParam_p);
2121 //---------------------------------------------------------------------------
2123 // Function: EplObdGetObjectSize()
2125 // Description: function to get size of object
2126 // The function determines if an object type an fixed data type (BYTE, WORD, ...)
2127 // or non fixed object (string, domain). This information is used to decide
2128 // if download data are stored temporary or not. For objects with fixed data length
2129 // and types a value range checking can process.
2130 // For strings the function returns the whole object size not the
2131 // length of string.
2133 // Parameters: pSubIndexEntry_p
2135 // Return: tEplObdSize
2139 //---------------------------------------------------------------------------
2141 static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p)
2144 tEplObdSize DataSize = 0;
2147 switch (pSubIndexEntry_p->m_Type) {
2148 // -----------------------------------------------------------------
2149 case kEplObdTypBool:
2154 // -----------------------------------------------------------------
2155 // ObdTypes which has to be check because numerical values
2156 case kEplObdTypInt8:
2157 DataSize = sizeof(tEplObdInteger8);
2160 // -----------------------------------------------------------------
2161 case kEplObdTypUInt8:
2162 DataSize = sizeof(tEplObdUnsigned8);
2165 // -----------------------------------------------------------------
2166 case kEplObdTypInt16:
2167 DataSize = sizeof(tEplObdInteger16);
2170 // -----------------------------------------------------------------
2171 case kEplObdTypUInt16:
2172 DataSize = sizeof(tEplObdUnsigned16);
2175 // -----------------------------------------------------------------
2176 case kEplObdTypInt32:
2177 DataSize = sizeof(tEplObdInteger32);
2180 // -----------------------------------------------------------------
2181 case kEplObdTypUInt32:
2182 DataSize = sizeof(tEplObdUnsigned32);
2185 // -----------------------------------------------------------------
2186 case kEplObdTypReal32:
2187 DataSize = sizeof(tEplObdReal32);
2190 // -----------------------------------------------------------------
2191 // ObdTypes which has to be not checked because not NUM values
2192 case kEplObdTypDomain:
2194 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2195 if ((void MEM *)pData != (void MEM *)NULL) {
2196 DataSize = ((tEplObdVarEntry MEM *) pData)->m_Size;
2200 // -----------------------------------------------------------------
2201 case kEplObdTypVString:
2202 //case kEplObdTypUString:
2204 // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
2205 // then the current pointer is always NULL. The function
2206 // returns the length of default string.
2207 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2208 if ((void MEM *)pData != (void MEM *)NULL) {
2209 // The max. size of strings defined by STRING-Macro is stored in
2210 // tEplObdVString of current value.
2211 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2212 DataSize = ((tEplObdVString MEM *) pData)->m_Size;
2214 // The current position is not decleared. The string
2215 // is located in ROM, therefor use default pointer.
2216 pData = (void *)pSubIndexEntry_p->m_pDefault;
2217 if ((CONST void ROM *)pData != (CONST void ROM *)NULL) {
2218 // The max. size of strings defined by STRING-Macro is stored in
2219 // tEplObdVString of default value.
2221 ((CONST tEplObdVString ROM *) pData)->
2228 // -----------------------------------------------------------------
2229 case kEplObdTypOString:
2231 pData = (void *)pSubIndexEntry_p->m_pCurrent;
2232 if ((void MEM *)pData != (void MEM *)NULL) {
2233 // The max. size of strings defined by STRING-Macro is stored in
2234 // tEplObdVString of current value.
2235 // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
2236 DataSize = ((tEplObdOString MEM *) pData)->m_Size;
2238 // The current position is not decleared. The string
2239 // is located in ROM, therefor use default pointer.
2240 pData = (void *)pSubIndexEntry_p->m_pDefault;
2241 if ((CONST void ROM *)pData != (CONST void ROM *)NULL) {
2242 // The max. size of strings defined by STRING-Macro is stored in
2243 // tEplObdVString of default value.
2245 ((CONST tEplObdOString ROM *) pData)->
2251 // -----------------------------------------------------------------
2252 case kEplObdTypInt24:
2253 case kEplObdTypUInt24:
2258 // -----------------------------------------------------------------
2259 case kEplObdTypInt40:
2260 case kEplObdTypUInt40:
2265 // -----------------------------------------------------------------
2266 case kEplObdTypInt48:
2267 case kEplObdTypUInt48:
2272 // -----------------------------------------------------------------
2273 case kEplObdTypInt56:
2274 case kEplObdTypUInt56:
2279 // -----------------------------------------------------------------
2280 case kEplObdTypInt64:
2281 case kEplObdTypUInt64:
2282 case kEplObdTypReal64:
2287 // -----------------------------------------------------------------
2288 case kEplObdTypTimeOfDay:
2289 case kEplObdTypTimeDiff:
2294 // -----------------------------------------------------------------
2302 //---------------------------------------------------------------------------
2304 // Function: EplObdGetObjectDefaultPtr()
2306 // Description: function to get the default pointer (type specific)
2308 // Parameters: pSubIndexEntry_p = pointer to subindex structure
2310 // Returns: (void *) = pointer to default value
2314 //---------------------------------------------------------------------------
2316 static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2322 ASSERTMSG(pSubIndexEntry_p != NULL,
2323 "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
2325 // get address to default data from default pointer
2326 pDefault = pSubIndexEntry_p->m_pDefault;
2327 if (pDefault != NULL) {
2328 // there are some special types, whose default pointer always is NULL or has to get from other structure
2329 // get type from subindex structure
2330 Type = pSubIndexEntry_p->m_Type;
2332 // check if object type is a string value
2333 if ((Type == kEplObdTypVString) /* ||
2334 (Type == kEplObdTypUString) */ ) {
2336 // EPL_OBD_SUBINDEX_RAM_VSTRING
2337 // tEplObdSize m_Size; --> size of default string
2338 // char * m_pDefString; --> pointer to default string
2339 // char * m_pString; --> pointer to string in RAM
2342 (void *)((tEplObdVString *) pDefault)->m_pString;
2343 } else if (Type == kEplObdTypOString) {
2345 (void *)((tEplObdOString *) pDefault)->m_pString;
2353 //---------------------------------------------------------------------------
2355 // Function: EplObdGetVarEntry()
2357 // Description: gets a variable entry of an object
2359 // Parameters: pSubindexEntry_p
2362 // Return: tCopKernel
2366 //---------------------------------------------------------------------------
2368 static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
2369 tEplObdVarEntry MEM ** ppVarEntry_p)
2372 tEplKernel Ret = kEplObdVarEntryNotExist;
2374 ASSERT(ppVarEntry_p != NULL); // is not allowed to be NULL
2375 ASSERT(pSubindexEntry_p != NULL);
2377 // check VAR-Flag - only this object points to variables
2378 if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) {
2379 // check if object is an array
2380 if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) {
2382 &((tEplObdVarEntry MEM *) pSubindexEntry_p->
2383 m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
2386 (tEplObdVarEntry MEM *) pSubindexEntry_p->
2390 Ret = kEplSuccessful;
2397 //---------------------------------------------------------------------------
2399 // Function: EplObdGetEntry()
2401 // Description: gets a index entry from OD
2403 // Parameters: uiIndex_p = Index number
2404 // uiSubindex_p = Subindex number
2405 // ppObdEntry_p = pointer to the pointer to the entry
2406 // ppObdSubEntry_p = pointer to the pointer to the subentry
2408 // Return: tEplKernel
2413 //---------------------------------------------------------------------------
2415 static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
2416 unsigned int uiIndex_p,
2417 unsigned int uiSubindex_p,
2418 tEplObdEntryPtr * ppObdEntry_p,
2419 tEplObdSubEntryPtr * ppObdSubEntry_p)
2422 tEplObdEntryPtr pObdEntry;
2423 tEplObdCbParam MEM CbParam;
2426 // check for all API function if instance is valid
2427 EPL_MCO_CHECK_INSTANCE_STATE();
2429 //------------------------------------------------------------------------
2430 // get address of entry of index
2432 EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam), uiIndex_p,
2434 if (Ret != kEplSuccessful) {
2437 //------------------------------------------------------------------------
2438 // get address of entry of subindex
2439 Ret = EplObdGetSubindexIntern(pObdEntry, uiSubindex_p, ppObdSubEntry_p);
2440 if (Ret != kEplSuccessful) {
2443 //------------------------------------------------------------------------
2444 // call callback function to inform user/stack that an object will be searched
2445 // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
2446 CbParam.m_uiIndex = uiIndex_p;
2447 CbParam.m_uiSubIndex = uiSubindex_p;
2448 CbParam.m_pArg = NULL;
2449 CbParam.m_ObdEvent = kEplObdEvCheckExist;
2450 Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
2451 pObdEntry->m_fpCallback, &CbParam);
2452 if (Ret != kEplSuccessful) {
2453 Ret = kEplObdIndexNotExist;
2456 //------------------------------------------------------------------------
2457 // it is allowed to set ppObdEntry_p to NULL
2458 // if so, no address will be written to calling function
2459 if (ppObdEntry_p != NULL) {
2460 *ppObdEntry_p = pObdEntry;
2469 //---------------------------------------------------------------------------
2471 // Function: EplObdGetObjectCurrentPtr()
2473 // Description: function to get Current pointer (type specific)
2475 // Parameters: pSubIndexEntry_p
2477 // Return: void MEM*
2481 //---------------------------------------------------------------------------
2483 static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
2487 unsigned int uiArrayIndex;
2490 pData = pSubIndexEntry_p->m_pCurrent;
2492 // check if constant object
2493 if (pData != NULL) {
2494 // check if object is an array
2495 if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) {
2496 // calculate correct data pointer
2497 uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
2498 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2499 Size = sizeof(tEplObdVarEntry);
2501 Size = EplObdGetObjectSize(pSubIndexEntry_p);
2503 pData = ((BYTE MEM *) pData) + (Size * uiArrayIndex);
2505 // check if VarEntry
2506 if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
2507 // The data pointer is stored in VarEntry->pData
2508 pData = ((tEplObdVarEntry MEM *) pData)->m_pData;
2510 // the default pointer is stored for strings in tEplObdVString
2511 else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* ||
2512 (pSubIndexEntry_p->m_Type == kEplObdTypUString) */
2515 (void MEM *)((tEplObdVString MEM *) pData)->
2517 } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) {
2519 (void MEM *)((tEplObdOString MEM *) pData)->
2528 //---------------------------------------------------------------------------
2530 // Function: EplObdGetIndexIntern()
2532 // Description: gets a index entry from OD
2534 // Parameters: pInitParam_p
2538 // Return: tEplKernel
2542 //---------------------------------------------------------------------------
2544 static tEplKernel EplObdGetIndexIntern(tEplObdInitParam MEM * pInitParam_p,
2545 unsigned int uiIndex_p,
2546 tEplObdEntryPtr * ppObdEntry_p)
2549 tEplObdEntryPtr pObdEntry;
2551 unsigned int uiIndex;
2553 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2557 // if user OD is used then objekts also has to be searched in user OD
2558 // there is less code need if we do this in a loop
2563 ASSERTMSG(ppObdEntry_p != NULL,
2564 "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
2566 Ret = kEplObdIndexNotExist;
2568 // get start address of OD part
2569 // start address depends on object index because
2570 // object dictionary is divided in 3 parts
2571 if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) {
2572 pObdEntry = pInitParam_p->m_pPart;
2573 } else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) {
2574 pObdEntry = pInitParam_p->m_pManufacturerPart;
2576 // index range 0xA000 to 0xFFFF is reserved for DSP-405
2577 // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
2578 // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
2579 // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
2580 // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
2582 #if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
2583 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
2585 else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
2588 pObdEntry = pInitParam_p->m_pDevicePart;
2591 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2593 // if index does not match in static OD then index only has to be searched in user OD
2595 // begin from first entry of user OD part
2596 pObdEntry = pInitParam_p->m_pUserPart;
2598 // no user OD is available
2599 if (pObdEntry == NULL) {
2602 // loop must only run once
2610 // no user OD is available
2611 // so other object can be found in OD
2613 Ret = kEplObdIllegalPart;
2620 // The end of Index table is marked with m_uiIndex = 0xFFFF.
2621 // If this function will be called with wIndex_p = 0xFFFF, entry
2622 // should not be found. Therefor it is important to use
2623 // while{} instead of do{}while !!!
2625 // get first index of index table
2626 uiIndex = pObdEntry->m_uiIndex;
2628 // search Index in OD part
2629 while (uiIndex != EPL_OBD_TABLE_INDEX_END) {
2630 // go to the end of this function if index is found
2631 if (uiIndex_p == uiIndex) {
2632 // write address of OD entry to calling function
2633 *ppObdEntry_p = pObdEntry;
2634 Ret = kEplSuccessful;
2637 // objects are sorted in OD
2638 // if the current index in OD is greater than the index which is to search then break loop
2639 // in this case user OD has to be search too
2640 if (uiIndex_p < uiIndex) {
2643 // next entry in index table
2646 // get next index of index table
2647 uiIndex = pObdEntry->m_uiIndex;
2650 #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
2652 // begin from first entry of user OD part
2653 pObdEntry = pInitParam_p->m_pUserPart;
2655 // no user OD is available
2656 if (pObdEntry == NULL) {
2659 // switch next loop for user OD
2668 // in this line Index was not found
2676 //---------------------------------------------------------------------------
2678 // Function: EplObdGetSubindexIntern()
2680 // Description: gets a subindex entry from a index entry
2682 // Parameters: pObdEntry_p
2686 // Return: tEplKernel
2690 //---------------------------------------------------------------------------
2692 static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
2693 unsigned int uiSubIndex_p,
2694 tEplObdSubEntryPtr * ppObdSubEntry_p)
2697 tEplObdSubEntryPtr pSubEntry;
2698 unsigned int nSubIndexCount;
2701 ASSERTMSG(pObdEntry_p != NULL,
2702 "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
2703 ASSERTMSG(ppObdSubEntry_p != NULL,
2704 "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
2706 Ret = kEplObdSubindexNotExist;
2708 // get start address of subindex table and count of subindices
2709 pSubEntry = pObdEntry_p->m_pSubIndex;
2710 nSubIndexCount = pObdEntry_p->m_uiCount;
2711 ASSERTMSG((pSubEntry != NULL) && (nSubIndexCount > 0), "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
2713 // search subindex in subindex table
2714 while (nSubIndexCount > 0) {
2715 // check if array is found
2716 if ((pSubEntry->m_Access & kEplObdAccArray) != 0) {
2717 // check if subindex is in range
2718 if (uiSubIndex_p < pObdEntry_p->m_uiCount) {
2719 // update subindex number (subindex entry of an array is always in RAM !!!)
2720 pSubEntry->m_uiSubIndex = uiSubIndex_p;
2721 *ppObdSubEntry_p = pSubEntry;
2722 Ret = kEplSuccessful;
2726 // go to the end of this function if subindex is found
2727 else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) {
2728 *ppObdSubEntry_p = pSubEntry;
2729 Ret = kEplSuccessful;
2732 // objects are sorted in OD
2733 // if the current subindex in OD is greater than the subindex which is to search then break loop
2734 // in this case user OD has to be search too
2735 if (uiSubIndex_p < pSubEntry->m_uiSubIndex) {
2743 // in this line SubIndex was not fount
2751 //---------------------------------------------------------------------------
2753 // Function: EplObdSetStoreLoadObjCallback()
2755 // Description: function set address to callbackfunction for command Store and Load
2757 // Parameters: fpCallback_p
2759 // Return: tEplKernel
2763 //---------------------------------------------------------------------------
2764 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2765 EPLDLLEXPORT tEplKernel PUBLIC
2766 EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_
2767 tEplObdStoreLoadObjCallback fpCallback_p)
2770 EPL_MCO_CHECK_INSTANCE_STATE();
2772 // set new address of callback function
2773 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = fpCallback_p;
2775 return kEplSuccessful;
2778 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2780 //---------------------------------------------------------------------------
2782 // Function: EplObdAccessOdPartIntern()
2784 // Description: runs through OD and executes a job
2786 // Parameters: CurrentOdPart_p
2788 // Direction_p = what is to do (load values from flash or EEPROM, store, ...)
2790 // Return: tEplKernel
2794 //---------------------------------------------------------------------------
2796 static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
2797 tEplObdPart CurrentOdPart_p,
2798 tEplObdEntryPtr pObdEnty_p,
2799 tEplObdDir Direction_p)
2802 tEplObdSubEntryPtr pSubIndex;
2803 unsigned int nSubIndexCount;
2804 tEplObdAccess Access;
2807 tEplObdSize ObjSize;
2809 tEplObdCbStoreParam MEM CbStore;
2810 tEplObdVarEntry MEM *pVarEntry;
2812 ASSERT(pObdEnty_p != NULL);
2814 Ret = kEplSuccessful;
2816 // prepare structure for STORE RESTORE callback function
2817 CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p;
2818 CbStore.m_pData = NULL;
2819 CbStore.m_ObjSize = 0;
2821 // command of first action depends on direction to access
2822 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
2823 if (Direction_p == kEplObdDirLoad) {
2824 CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead;
2826 // call callback function for previous command
2827 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2828 if (Ret != kEplSuccessful) {
2831 // set command for index and subindex loop
2832 CbStore.m_bCommand = (BYTE) kEplObdCommReadObj;
2833 } else if (Direction_p == kEplObdDirStore) {
2834 CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite;
2836 // call callback function for previous command
2837 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
2838 if (Ret != kEplSuccessful) {
2841 // set command for index and subindex loop
2842 CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj;
2844 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
2846 // we should not restore the OD values here
2847 // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
2848 if (Direction_p != kEplObdDirRestore) {
2849 // walk through OD part till end is found
2850 while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) {
2851 // get address to subindex table and count of subindices
2852 pSubIndex = pObdEnty_p->m_pSubIndex;
2853 nSubIndexCount = pObdEnty_p->m_uiCount;
2854 ASSERT((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL
2856 // walk through subindex table till all subinices were restored
2857 while (nSubIndexCount != 0) {
2858 Access = (tEplObdAccess) pSubIndex->m_Access;
2860 // get pointer to current and default data
2861 pDefault = EplObdGetObjectDefaultPtr(pSubIndex);
2862 pDstData = EplObdGetObjectCurrentPtr(pSubIndex);
2864 // NOTE (for kEplObdTypVString):
2865 // The function returnes the max. number of bytes for a
2867 // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
2868 ObjSize = EplObdGetObjectSize(pSubIndex);
2870 // switch direction of OD access
2871 switch (Direction_p) {
2872 // --------------------------------------------------------------------------
2873 // VarEntry structures has to be initialized
2874 case kEplObdDirInit:
2876 // If VAR-Flag is set, m_pCurrent means not address of data
2877 // but address of tEplObdVarEntry. Address of data has to be get from
2879 if ((Access & kEplObdAccVar) != 0) {
2880 EplObdGetVarEntry(pSubIndex,
2882 EplObdInitVarEntry(pVarEntry,
2887 if ((Access & kEplObdAccArray) == 0)
2889 EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
2893 EplObdInitVarEntry ((tEplObdVarEntry MEM*) (((BYTE MEM*) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
2894 pSubIndex->m_Type, ObjSize);
2897 // at this time no application variable is defined !!!
2898 // therefore data can not be copied.
2900 } else if (pSubIndex->m_Type ==
2901 kEplObdTypVString) {
2902 // If pointer m_pCurrent is not equal to NULL then the
2903 // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
2904 // pointer points to struct tEplObdVString located in MEM.
2905 // The element size includes the max. number of
2906 // bytes. The element m_pString includes the pointer
2907 // to string in MEM. The memory location of default string
2908 // must be copied to memory location of current string.
2911 pSubIndex->m_pCurrent;
2912 if (pDstData != NULL) {
2913 // 08-dec-2004: code optimization !!!
2914 // entries ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString
2915 // and ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
2916 // twice. thats not necessary!
2918 // For copying data we have to set the destination pointer to the real RAM string. This
2919 // pointer to RAM string is located in default string info structure. (translated r.d.)
2922 *)((tEplObdVStringDef ROM *) pSubIndex->m_pDefault)->m_pString;
2929 ((tEplObdVString MEM *)
2932 m_pString = pDstData;
2933 ((tEplObdVString MEM *)
2935 m_pCurrent)->m_Size =
2939 } else if (pSubIndex->m_Type ==
2940 kEplObdTypOString) {
2942 pSubIndex->m_pCurrent;
2943 if (pDstData != NULL) {
2944 // 08-dec-2004: code optimization !!!
2945 // entries ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString
2946 // and ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
2947 // twice. thats not necessary!
2949 // For copying data we have to set the destination pointer to the real RAM string. This
2950 // pointer to RAM string is located in default string info structure. (translated r.d.)
2953 *)((tEplObdOStringDef ROM *) pSubIndex->m_pDefault)->m_pString;
2960 ((tEplObdOString MEM *)
2963 m_pString = pDstData;
2964 ((tEplObdOString MEM *)
2966 m_pCurrent)->m_Size =
2972 // no break !! because copy of data has to done too.
2974 // --------------------------------------------------------------------------
2975 // all objects has to be restored with default values
2976 case kEplObdDirRestore:
2978 // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
2979 // is replaced to function ObdCopyObjectData() with a new parameter.
2981 // restore object data for init phase
2982 EplObdCopyObjectData(pDstData, pDefault,
2987 // --------------------------------------------------------------------------
2988 // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
2989 case kEplObdDirLoad:
2991 // restore object data for init phase
2992 EplObdCopyObjectData(pDstData, pDefault,
2996 // no break !! because callback function has to be called too.
2998 // --------------------------------------------------------------------------
2999 // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
3000 case kEplObdDirStore:
3002 // when attribute kEplObdAccStore is set, then call callback function
3003 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3004 if ((Access & kEplObdAccStore) != 0) {
3005 // fill out data pointer and size of data
3006 CbStore.m_pData = pDstData;
3007 CbStore.m_ObjSize = ObjSize;
3009 // call callback function for read or write object
3011 ObdCallStoreCallback
3012 (EPL_MCO_INSTANCE_PTR_ &
3014 if (Ret != kEplSuccessful) {
3018 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3021 // --------------------------------------------------------------------------
3022 // if OD Builder key has to be checked no access to subindex and data should be made
3023 case kEplObdDirOBKCheck:
3025 // no break !! because we want to break the second loop too.
3027 // --------------------------------------------------------------------------
3028 // unknown Direction
3031 // so we can break the second loop earler
3038 // next subindex entry
3039 if ((Access & kEplObdAccArray) == 0) {
3041 if ((nSubIndexCount > 0)
3044 m_Access & kEplObdAccArray) !=
3046 // next subindex points to an array
3047 // reset subindex number
3048 pSubIndex->m_uiSubIndex = 1;
3051 if (nSubIndexCount > 0) {
3052 // next subindex points to an array
3053 // increment subindex number
3054 pSubIndex->m_uiSubIndex++;
3063 // -----------------------------------------------------------------------------------------
3064 // command of last action depends on direction to access
3065 if (Direction_p == kEplObdDirOBKCheck) {
3069 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3071 if (Direction_p == kEplObdDirLoad) {
3072 CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead;
3073 } else if (Direction_p == kEplObdDirStore) {
3074 CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite;
3075 } else if (Direction_p == kEplObdDirRestore) {
3076 CbStore.m_bCommand = (BYTE) kEplObdCommClear;
3081 // call callback function for last command
3082 Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
3084 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3094 // ----------------------------------------------------------------------------
3095 // Function: EplObdCopyObjectData()
3097 // Description: checks pointers to object data and copy them from source to destination
3099 // Parameters: pDstData_p = destination pointer
3100 // pSrcData_p = source pointer
3101 // ObjSize_p = size of object
3104 // Returns: tEplKernel = error code
3105 // ----------------------------------------------------------------------------
3107 static void EplObdCopyObjectData(void MEM * pDstData_p,
3109 tEplObdSize ObjSize_p, tEplObdType ObjType_p)
3112 tEplObdSize StrSize = 0;
3114 // it is allowed to set default and current address to NULL (nothing to copy)
3115 if (pDstData_p != NULL) {
3117 if (ObjType_p == kEplObdTypVString) {
3118 // The function calculates the really number of characters of string. The
3119 // object entry size can be bigger as string size of default string.
3120 // The '\0'-termination is included. A string with no characters has a
3123 EplObdGetStrLen((void *)pSrcData_p, ObjSize_p,
3126 // If the string length is greater than or equal to the entry size in OD then only copy
3127 // entry size - 1 and always set the '\0'-termination.
3128 if (StrSize >= ObjSize_p) {
3129 StrSize = ObjSize_p - 1;
3133 if (pSrcData_p != NULL) {
3135 EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p);
3137 if (ObjType_p == kEplObdTypVString) {
3138 ((char MEM *)pDstData_p)[StrSize] = '\0';
3145 //---------------------------------------------------------------------------
3147 // Function: EplObdIsNumericalIntern()
3149 // Description: function checks if a entry is numerical or not
3152 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
3153 // uiIndex_p = Index
3154 // uiSubIndex_p = Subindex
3155 // pfEntryNumerical_p = pointer to BOOL for returnvalue
3156 // -> TRUE if entry a numerical value
3157 // -> FALSE if entry not a numerical value
3159 // Return: tEplKernel = Errorcode
3163 //---------------------------------------------------------------------------
3164 static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
3165 BOOL * pfEntryNumerical_p)
3167 tEplKernel Ret = kEplSuccessful;
3170 if ((pObdSubEntry_p->m_Type == kEplObdTypVString)
3171 || (pObdSubEntry_p->m_Type == kEplObdTypOString)
3172 || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) { // not numerical types
3173 *pfEntryNumerical_p = FALSE;
3174 } else { // numerical types
3175 *pfEntryNumerical_p = TRUE;
3182 // -------------------------------------------------------------------------
3183 // function to classify object type (fixed/non fixed)
3184 // -------------------------------------------------------------------------
3186 // ----------------------------------------------------------------------------
3187 // Function: EplObdCallStoreCallback()
3189 // Description: checks address to callback function and calles it when unequal
3192 // Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
3193 // pCbStoreParam_p = address to callback parameters
3195 // Returns: tEplKernel = error code
3196 // ----------------------------------------------------------------------------
3197 #if (EPL_OBD_USE_STORE_RESTORE != FALSE)
3198 static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
3199 tEplObdCbStoreParam MEM *
3203 tEplKernel Ret = kEplSuccessful;
3205 ASSERT(pCbStoreParam_p != NULL);
3207 // check if function pointer is NULL - if so, no callback should be called
3208 if (EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) != NULL) {
3210 EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback)
3211 (EPL_MCO_INSTANCE_PARAM_IDX_()
3218 #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
3219 //---------------------------------------------------------------------------
3221 // Function: EplObdGetObjectDataPtrIntern()
3223 // Description: Function gets the data pointer of an object.
3224 // It returnes the current data pointer. But if object is an
3225 // constant object it returnes the default pointer.
3227 // Parameters: pSubindexEntry_p = pointer to subindex entry
3229 // Return: void * = pointer to object data
3233 //---------------------------------------------------------------------------
3235 void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p)
3239 tEplObdAccess Access;
3241 ASSERTMSG(pSubindexEntry_p != NULL,
3242 "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
3244 // there are are some objects whose data pointer has to get from other structure
3245 // get access type for this object
3246 Access = pSubindexEntry_p->m_Access;
3248 // If object has access type = const,
3249 // for data only exists default values.
3250 if ((Access & kEplObdAccConst) != 0) {
3251 // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
3252 pData = ((void *)EplObdGetObjectDefaultPtr(pSubindexEntry_p));
3254 // The pointer to current value can be received from ObdGetObjectCurrentPtr()
3255 pData = ((void *)EplObdGetObjectCurrentPtr(pSubindexEntry_p));
3261 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)