2 This file is part of CanFestival, a library implementing CanOpen Stack.
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
6 See COPYING file for copyrights details.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /* #define DEBUG_WAR_CONSOLE_ON */
24 /* #define DEBUG_ERR_CONSOLE_ON */
31 UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
32 UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
34 #ifdef DEBUG_WAR_CONSOLE_ON
35 MSG_WAR(0x2B09,"Dictionary index : ", index);
36 MSG_WAR(0X2B10," subindex : ", subIndex);
38 case OD_NO_SUCH_OBJECT:
39 MSG_WAR(0x2B11,"Index not found ", index);
41 case OD_NO_SUCH_SUBINDEX :
42 MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
44 case OD_WRITE_NOT_ALLOWED :
45 MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
47 case OD_LENGTH_DATA_INVALID :
48 MSG_WAR(0x2B14,"Conflict size data. Should be (bytes) : ", sizeDataDict);
49 MSG_WAR(0x2B15,"But you have given the size : ", sizeDataGiven);
51 case OD_NOT_MAPPABLE :
52 MSG_WAR(0x2B16,"Not mappable data in a PDO at index : ", index);
54 case OD_VALUE_TOO_LOW :
55 MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
57 case OD_VALUE_TOO_HIGH :
58 MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
61 MSG_WAR(0x2B20, "Unknown error code : ", code);
68 UNS32 getODentry( CO_Data* d,
75 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
78 const indextable *ptrTable;
79 ODCallback_t *Callback;
81 ptrTable = (*d->scanIndexOD)(wIndex, &errorCode, &Callback);
83 if (errorCode != OD_SUCCESSFUL)
85 if( ptrTable->bSubCount <= bSubindex ) {
86 /* Subindex not found */
87 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
88 return OD_NO_SUCH_SUBINDEX;
91 if (checkAccess && !(ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
92 MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
93 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_WRITE_NOT_ALLOWED);
94 return OD_READ_NOT_ALLOWED;
97 *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
98 szData = ptrTable->pSubindex[bSubindex].size;
100 if( *pExpectedSize == 0 ||
101 *pExpectedSize == szData ||
102 (*pDataType == visible_string && *pExpectedSize < szData)) {/* We allow to fetch a shorter string than expected */
104 # ifdef CANOPEN_BIG_ENDIAN
105 if(*pDataType > boolean && *pDataType < visible_string) {
106 /* data must be transmited with low byte first */
108 MSG_WAR(boolean, "data type ", *pDataType);
109 MSG_WAR(visible_string, "data type ", *pDataType);
110 for ( i = szData ; i > 0 ; i--) {
112 ((UNS8*)pDestData)[j++] =
113 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
116 else /* It it is a visible string no endianisation to perform */
117 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
119 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
122 *pExpectedSize = szData;
124 /* Me laisser ça, please ! (FD) */
127 for (i = 0 ; i < 10 ; i++) {
128 MSG_WAR(*pExpectedSize, "dic data= ",
129 *(UNS8 *)(ptrTable->pSubindex[bSubindex].pObject + i));
134 return OD_SUCCESSFUL;
137 *pExpectedSize = szData;
138 accessDictionaryError(wIndex, bSubindex, szData,
139 *pExpectedSize, OD_LENGTH_DATA_INVALID);
140 return OD_LENGTH_DATA_INVALID;
144 UNS32 setODentry( CO_Data* d,
148 UNS8 * pExpectedSize,
154 const indextable *ptrTable;
155 ODCallback_t *Callback;
157 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
158 if (errorCode != OD_SUCCESSFUL)
161 if( ptrTable->bSubCount <= bSubindex ) {
162 /* Subindex not found */
163 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
164 return OD_NO_SUCH_SUBINDEX;
166 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
167 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
168 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
169 return OD_WRITE_NOT_ALLOWED;
173 dataType = ptrTable->pSubindex[bSubindex].bDataType;
174 szData = ptrTable->pSubindex[bSubindex].size;
176 if( *pExpectedSize == 0 ||
177 *pExpectedSize == szData ||
178 (dataType == visible_string && *pExpectedSize < szData)) /* We allow to store a shorter string than entry size */
180 #ifdef CANOPEN_BIG_ENDIAN
181 if(dataType > boolean && dataType < visible_string)
183 /* we invert the data source directly. This let us do range testing without */
184 /* additional temp variable */
186 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
188 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
189 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
190 ((UNS8 *)pSourceData)[i] = tmp;
194 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
196 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
199 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
200 *pExpectedSize = szData;
203 if(Callback && Callback[bSubindex]){
204 (*Callback[bSubindex])(d, ptrTable, bSubindex);
207 /* TODO : Store dans NVRAM */
208 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
209 (*d->storeODSubIndex)(wIndex, bSubindex);
211 return OD_SUCCESSFUL;
213 *pExpectedSize = szData;
214 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
215 return OD_LENGTH_DATA_INVALID;
220 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
222 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
225 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
228 ODCallback_t *CallbackList;
230 scanIndexOD (d, wIndex, &errorCode, &CallbackList);
231 if(errorCode == OD_SUCCESSFUL && CallbackList)
232 CallbackList[bSubindex] = Callback;
236 void _storeODSubIndex (UNS16 wIndex, UNS8 bSubindex){}