]> rtime.felk.cvut.cz Git - CanFestival-3.git/blobdiff - src/objacces.c
Applied edward's patch for OD acces macros (optimization) and boudaries check (safety).
[CanFestival-3.git] / src / objacces.c
index eef3530ea1e963476f93431b405f19824e63f53c..1ab03bd7ce908cab227b99019e2473741206dd7e 100644 (file)
 /*
-This file is part of CanFestival, a library implementing CanOpen Stack. 
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
 
-Copyright (C): Edouard TISSERANT and Francis DUPIN
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
 
-See COPYING file for copyrights details.
+  See COPYING file for copyrights details.
 
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
 
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
 
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
 */
+/*!
+** @file   objacces.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 08:55:23 2007
+**
+** @brief
+**
+**
+*/
+
+
+
 
 /* #define DEBUG_WAR_CONSOLE_ON */
 /* #define DEBUG_ERR_CONSOLE_ON */
 
 
-#include "objacces.h"
+#include "data.h"
 
 
+/*!
+**
+**
+** @param index
+** @param subIndex
+** @param sizeDataDict
+** @param sizeDataGiven
+** @param code
+**
+** @return
+**/
 #ifdef DEBUG_WAR_CONSOLE_ON
-UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, 
-                            UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
+UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
+                           UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
 {
   MSG_WAR(0x2B09,"Dictionary index : ", index);
   MSG_WAR(0X2B10,"           subindex : ", subIndex);
   switch (code) {
-    case  OD_NO_SUCH_OBJECT: 
-      MSG_WAR(0x2B11,"Index not found ", index);
-      break;
-    case OD_NO_SUCH_SUBINDEX :
-      MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
-      break;   
-    case OD_WRITE_NOT_ALLOWED :
-      MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
-      break;         
-    case OD_LENGTH_DATA_INVALID :    
-      MSG_WAR(0x2B14,"Conflict size data. Should be (bytes)  : ", sizeDataDict);
-      MSG_WAR(0x2B15,"But you have given the size  : ", sizeDataGiven);
-      break;
-    case OD_NOT_MAPPABLE :
-      MSG_WAR(0x2B16,"Not mappable data in a PDO at index    : ", index);
-      break;
-    case OD_VALUE_TOO_LOW :
-      MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
-      break;
-    case OD_VALUE_TOO_HIGH :
-      MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
-      break;
+  case  OD_NO_SUCH_OBJECT:
+    MSG_WAR(0x2B11,"Index not found ", index);
+    break;
+  case OD_NO_SUCH_SUBINDEX :
+    MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
+    break;
+  case OD_WRITE_NOT_ALLOWED :
+    MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
+    break;
+  case OD_LENGTH_DATA_INVALID :
+    MSG_WAR(0x2B14,"Conflict size data. Should be (bytes)  : ", sizeDataDict);
+    MSG_WAR(0x2B15,"But you have given the size  : ", sizeDataGiven);
+    break;
+  case OD_NOT_MAPPABLE :
+    MSG_WAR(0x2B16,"Not mappable data in a PDO at index    : ", index);
+    break;
+  case OD_VALUE_TOO_LOW :
+    MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
+    break;
+  case OD_VALUE_TOO_HIGH :
+    MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
+    break;
   default :
     MSG_WAR(0x2B20, "Unknown error code : ", code);
   }
-  return 0; 
-}      
+  return 0;
+}
+#else
+#define accessDictionaryError(index, subIndex, sizeDataDict, sizeDataGiven, code)
 #endif
 
-UNS32 getODentry( CO_Data* d, 
-                  UNS16 wIndex,
-                 UNS8 bSubindex,
-                 void * pDestData,
-                 UNS8 * pExpectedSize,
-                 UNS8 * pDataType,
-                 UNS8 checkAccess)
-{ /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pDestData
+** @param pExpectedSize
+** @param pDataType
+** @param checkAccess
+** @param endianize
+**
+** @return
+**/
+UNS32 _getODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pDestData,
+                   UNS8 * pExpectedSize,
+                   UNS8 * pDataType,
+                   UNS8 checkAccess,
+                   UNS8 endianize)
+{ /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
+    loop if it fails. */
   UNS32 errorCode;
   UNS8 szData;
   const indextable *ptrTable;
@@ -85,66 +128,92 @@ UNS32 getODentry( CO_Data* d,
     accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
     return OD_NO_SUCH_SUBINDEX;
   }
-  
-  if (checkAccess && !(ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
-       MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
-    accessDictionaryError(wIndex, bSubindex, 0, 0, OD_WRITE_NOT_ALLOWED);
+
+  if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
+    MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+    accessDictionaryError(wIndex, bSubindex, 0, 0, OD_READ_NOT_ALLOWED);
     return OD_READ_NOT_ALLOWED;
   }
 
   *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
-   szData = ptrTable->pSubindex[bSubindex].size;
+  szData = ptrTable->pSubindex[bSubindex].size;
+
+  if(*pExpectedSize == 0 ||
+     *pExpectedSize == szData ||
+     /* allow to fetch a shorter string than expected */
+     (*pDataType >= visible_string && *pExpectedSize < szData)) { 
 
-   if( *pExpectedSize == 0 ||
-       *pExpectedSize == szData ||
-       (*pDataType == visible_string && *pExpectedSize < szData)) {/* We allow to fetch a shorter string than expected */
-     
 #  ifdef CANOPEN_BIG_ENDIAN
-     if(*pDataType > boolean && *pDataType < visible_string) {
-       /* data must be transmited with low byte first */
-       UNS8 i, j = 0;
-       MSG_WAR(boolean, "data type ", *pDataType);
-       MSG_WAR(visible_string, "data type ", *pDataType);
-       for ( i = szData ; i > 0 ; i--) {
-         MSG_WAR(i," ", j);
-        ((UNS8*)pDestData)[j++] = 
-          ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
-       }
-     }
-     else /* It it is a visible string no endianisation to perform */
-       memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
-#  else
-     memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
+     if(endianize && *pDataType > boolean && !(
+            *pDataType >= visible_string && 
+            *pDataType <= domain)) {
+      /* data must be transmited with low byte first */
+      UNS8 i, j = 0;
+      MSG_WAR(boolean, "data type ", *pDataType);
+      MSG_WAR(visible_string, "data type ", *pDataType);
+      for ( i = szData ; i > 0 ; i--) {
+        MSG_WAR(i," ", j);
+        ((UNS8*)pDestData)[j++] =
+          ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
+      }
+      *pExpectedSize = szData;
+    }
+    else /* no endianisation change */
 #  endif
-     
-     *pExpectedSize = szData;
-#if 0
-     /* Me laisser ça, please ! (FD) */
-     {
-       UNS8 i;
-       for (i = 0 ; i < 10 ; i++) {
-        MSG_WAR(*pExpectedSize, "dic data= ",
-                *(UNS8 *)(ptrTable->pSubindex[bSubindex].pObject + i));
-       }
-      
-     }
-#endif
-     return OD_SUCCESSFUL;
-   }
-   else { /* Error ! */
-     *pExpectedSize = szData;
-     accessDictionaryError(wIndex, bSubindex, szData, 
-                          *pExpectedSize, OD_LENGTH_DATA_INVALID);
-     return OD_LENGTH_DATA_INVALID;
-   }
+    if(*pDataType != visible_string) {
+        memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
+        *pExpectedSize = szData;
+    }else{
+        /* TODO : CONFORM TO DS-301 : 
+         *  - stop using NULL terminated strings
+         *  - store string size in td_subindex 
+         * */
+        /* Copy null terminated string to user, and return discovered size */
+        UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
+        UNS8 *ptr_start = ptr;
+        /* *pExpectedSize IS < szData . if null, use szData */
+        UNS8 *ptr_end = ptr + (*pExpectedSize ? *pExpectedSize : szData) ; 
+        UNS8 *ptr_dest = (UNS8*)pDestData;
+        while( *ptr && ptr < ptr_end){
+            *(ptr_dest++) = *(ptr++);
+        } 
+         
+        *pExpectedSize = ptr - ptr_start;
+        /* terminate string if not maximum length */
+        if (*pExpectedSize < szData) 
+            *(ptr) = 0; 
+    }
+
+    return OD_SUCCESSFUL;
+  }
+  else { /* Error ! */
+    *pExpectedSize = szData;
+    accessDictionaryError(wIndex, bSubindex, szData,
+                          *pExpectedSize, OD_LENGTH_DATA_INVALID);
+    return OD_LENGTH_DATA_INVALID;
+  }
 }
 
-UNS32 setODentry( CO_Data* d, 
-                  UNS16 wIndex,
-                 UNS8 bSubindex, 
-                 void * pSourceData, 
-                 UNS8 * pExpectedSize, 
-                 UNS8 checkAccess)
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param pSourceData
+** @param pExpectedSize
+** @param checkAccess
+** @param endianize
+**
+** @return
+**/
+UNS32 _setODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pSourceData,
+                   UNS8 * pExpectedSize,
+                   UNS8 checkAccess,
+                   UNS8 endianize)
 {
   UNS8 szData;
   UNS8 dataType;
@@ -162,71 +231,116 @@ UNS32 setODentry( CO_Data* d,
     return OD_NO_SUCH_SUBINDEX;
   }
   if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
-       MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+    MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
     accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
     return OD_WRITE_NOT_ALLOWED;
   }
 
 
-   dataType = ptrTable->pSubindex[bSubindex].bDataType;
-   szData = ptrTable->pSubindex[bSubindex].size;
+  dataType = ptrTable->pSubindex[bSubindex].bDataType;
+  szData = ptrTable->pSubindex[bSubindex].size;
 
   if( *pExpectedSize == 0 ||
-       *pExpectedSize == szData ||
-       (dataType == visible_string && *pExpectedSize < szData)) /* We allow to store a shorter string than entry size */
-  {
-      #ifdef CANOPEN_BIG_ENDIAN
-             if(dataType > boolean && dataType < visible_string)
-             {
-                       /* we invert the data source directly. This let us do range testing without */
-                       /* additional temp variable */
-                       UNS8 i;
-                       for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1)  ; i++) 
-                       {
-                       UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
-                       ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
-                       ((UNS8 *)pSourceData)[i] = tmp;
-               }
-               }  
-      #endif
+      *pExpectedSize == szData ||
+      /* allow to store a shorter string than entry size */
+      (dataType == visible_string && *pExpectedSize < szData))
+    {
+#ifdef CANOPEN_BIG_ENDIAN
+      /* re-endianize do not occur for bool, strings time and domains */
+      if(endianize && dataType > boolean && !(
+            dataType >= visible_string && 
+            dataType <= domain))
+        {
+          /* we invert the data source directly. This let us do range
+            testing without */
+          /* additional temp variable */
+          UNS8 i;
+          for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1)  ; i++)
+            {
+              UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
+              ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
+              ((UNS8 *)pSourceData)[i] = tmp;
+            }
+        }
+#endif
       errorCode = (*d->valueRangeTest)(dataType, pSourceData);
       if (errorCode) {
-       accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
-       return errorCode;
+        accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
+        return errorCode;
       }
       memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
-      *pExpectedSize = szData;
+     /* TODO : CONFORM TO DS-301 : 
+      *  - stop using NULL terminated strings
+      *  - store string size in td_subindex 
+      * */
+      /* terminate visible_string with '\0' */
+      if(dataType == visible_string && *pExpectedSize < szData)
+        ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[*pExpectedSize] = 0;
       
+      *pExpectedSize = szData;
+
       /* Callbacks */
       if(Callback && Callback[bSubindex]){
-        (*Callback[bSubindex])(d, ptrTable, bSubindex);
+        errorCode = (Callback[bSubindex])(d, ptrTable, bSubindex);
+        if(errorCode != OD_SUCCESSFUL)
+        {
+            return errorCode;
+        }
+       }
+
+      /* TODO : Store dans NVRAM */
+      if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
+        (*d->storeODSubIndex)(d, wIndex, bSubindex);
       }
-      
-      /* TODO : Store dans NVRAM */     
-      /* if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVED) */
       return OD_SUCCESSFUL;
-  }else{
+    }else{
       *pExpectedSize = szData;
       accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
       return OD_LENGTH_DATA_INVALID;
-  }
+    }
 }
 
-
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param errorCode
+** @param Callback
+**
+** @return
+**/
 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
 {
   return (*d->scanIndexOD)(wIndex, errorCode, Callback);
 }
 
+/*!
+**
+**
+** @param d
+** @param wIndex
+** @param bSubindex
+** @param Callback
+**
+** @return
+**/
 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
 {
-       UNS32 errorCode;
-       ODCallback_t *CallbackList;
+UNS32 errorCode;
+ODCallback_t *CallbackList;
+const indextable *odentry;
 
-       scanIndexOD (d, wIndex, &errorCode, &CallbackList);
-       if(errorCode == OD_SUCCESSFUL && CallbackList) 
-               CallbackList[bSubindex] = Callback;
-       return errorCode;
+  odentry = scanIndexOD (d, wIndex, &errorCode, &CallbackList);
+  if(errorCode == OD_SUCCESSFUL  &&  CallbackList  &&  bSubindex < odentry->bSubCount) 
+    CallbackList[bSubindex] = Callback;
+  return errorCode;
 }
 
-
+/*!
+**
+**
+** @param wIndex
+** @param bSubindex
+**/
+void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}