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,
76 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
79 const indextable *ptrTable;
80 ODCallback_t *Callback;
82 ptrTable = (*d->scanIndexOD)(wIndex, &errorCode, &Callback);
84 if (errorCode != OD_SUCCESSFUL)
86 if( ptrTable->bSubCount <= bSubindex ) {
87 /* Subindex not found */
88 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
89 return OD_NO_SUCH_SUBINDEX;
92 if (checkAccess && !(ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
93 MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
94 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_WRITE_NOT_ALLOWED);
95 return OD_READ_NOT_ALLOWED;
98 *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
99 szData = ptrTable->pSubindex[bSubindex].size;
101 if( *pExpectedSize == 0 ||
102 *pExpectedSize == szData ||
103 (*pDataType == visible_string && *pExpectedSize < szData)) {/* We allow to fetch a shorter string than expected */
105 # ifdef CANOPEN_BIG_ENDIAN
106 if(endianize && *pDataType > boolean && *pDataType < visible_string) {
107 /* data must be transmited with low byte first */
109 MSG_WAR(boolean, "data type ", *pDataType);
110 MSG_WAR(visible_string, "data type ", *pDataType);
111 for ( i = szData ; i > 0 ; i--) {
113 ((UNS8*)pDestData)[j++] =
114 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
117 else /* It it is a visible string no endianisation to perform */
118 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
120 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
123 *pExpectedSize = szData;
125 /* Me laisser ça, please ! (FD) */
128 for (i = 0 ; i < 10 ; i++) {
129 MSG_WAR(*pExpectedSize, "dic data= ",
130 *(UNS8 *)(ptrTable->pSubindex[bSubindex].pObject + i));
135 return OD_SUCCESSFUL;
138 *pExpectedSize = szData;
139 accessDictionaryError(wIndex, bSubindex, szData,
140 *pExpectedSize, OD_LENGTH_DATA_INVALID);
141 return OD_LENGTH_DATA_INVALID;
145 UNS32 getODentry( CO_Data* d,
149 UNS8 * pExpectedSize,
153 return _getODentry( d,
163 UNS32 readLocalDict( CO_Data* d,
167 UNS8 * pExpectedSize,
171 return _getODentry( d,
178 0);//do not endianize
181 UNS32 _setODentry( CO_Data* d,
185 UNS8 * pExpectedSize,
192 const indextable *ptrTable;
193 ODCallback_t *Callback;
195 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
196 if (errorCode != OD_SUCCESSFUL)
199 if( ptrTable->bSubCount <= bSubindex ) {
200 /* Subindex not found */
201 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
202 return OD_NO_SUCH_SUBINDEX;
204 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
205 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
206 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
207 return OD_WRITE_NOT_ALLOWED;
211 dataType = ptrTable->pSubindex[bSubindex].bDataType;
212 szData = ptrTable->pSubindex[bSubindex].size;
214 if( *pExpectedSize == 0 ||
215 *pExpectedSize == szData ||
216 (dataType == visible_string && *pExpectedSize < szData)) /* We allow to store a shorter string than entry size */
218 #ifdef CANOPEN_BIG_ENDIAN
219 if(endianize && dataType > boolean && dataType < visible_string)
221 /* we invert the data source directly. This let us do range testing without */
222 /* additional temp variable */
224 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
226 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
227 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
228 ((UNS8 *)pSourceData)[i] = tmp;
232 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
234 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
237 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
238 *pExpectedSize = szData;
241 if(Callback && Callback[bSubindex]){
242 (*Callback[bSubindex])(d, ptrTable, bSubindex);
245 /* TODO : Store dans NVRAM */
246 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
247 (*d->storeODSubIndex)(wIndex, bSubindex);
249 return OD_SUCCESSFUL;
251 *pExpectedSize = szData;
252 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
253 return OD_LENGTH_DATA_INVALID;
257 UNS32 setODentry( CO_Data* d,
261 UNS8 * pExpectedSize,
264 return _setODentry( d,
273 UNS32 writeLocalDict( CO_Data* d,
277 UNS8 * pExpectedSize,
280 return _setODentry( d,
286 0);//do not endianize
292 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
294 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
297 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
300 ODCallback_t *CallbackList;
302 scanIndexOD (d, wIndex, &errorCode, &CallbackList);
303 if(errorCode == OD_SUCCESSFUL && CallbackList)
304 CallbackList[bSubindex] = Callback;
308 void _storeODSubIndex (UNS16 wIndex, UNS8 bSubindex){}