2 This file is part of CanFestival, a library implementing CanOpen
5 Copyright (C): Edouard TISSERANT and Francis DUPIN
7 See COPYING file for copyrights details.
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 ** @author Edouard TISSERANT and Francis DUPIN
27 ** @date Tue Jun 5 08:55:23 2007
37 /* #define DEBUG_WAR_CONSOLE_ON */
38 /* #define DEBUG_ERR_CONSOLE_ON */
49 ** @param sizeDataDict
50 ** @param sizeDataGiven
55 UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
56 UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
58 #ifdef DEBUG_WAR_CONSOLE_ON
59 MSG_WAR(0x2B09,"Dictionary index : ", index);
60 MSG_WAR(0X2B10," subindex : ", subIndex);
62 case OD_NO_SUCH_OBJECT:
63 MSG_WAR(0x2B11,"Index not found ", index);
65 case OD_NO_SUCH_SUBINDEX :
66 MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
68 case OD_WRITE_NOT_ALLOWED :
69 MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
71 case OD_LENGTH_DATA_INVALID :
72 MSG_WAR(0x2B14,"Conflict size data. Should be (bytes) : ", sizeDataDict);
73 MSG_WAR(0x2B15,"But you have given the size : ", sizeDataGiven);
75 case OD_NOT_MAPPABLE :
76 MSG_WAR(0x2B16,"Not mappable data in a PDO at index : ", index);
78 case OD_VALUE_TOO_LOW :
79 MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
81 case OD_VALUE_TOO_HIGH :
82 MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
85 MSG_WAR(0x2B20, "Unknown error code : ", code);
98 ** @param pExpectedSize
100 ** @param checkAccess
105 UNS32 _getODentry( CO_Data* d,
109 UNS8 * pExpectedSize,
113 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
117 const indextable *ptrTable;
118 ODCallback_t *Callback;
120 ptrTable = (*d->scanIndexOD)(wIndex, &errorCode, &Callback);
122 if (errorCode != OD_SUCCESSFUL)
124 if( ptrTable->bSubCount <= bSubindex ) {
125 /* Subindex not found */
126 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
127 return OD_NO_SUCH_SUBINDEX;
130 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
131 MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
132 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_WRITE_NOT_ALLOWED);
133 return OD_READ_NOT_ALLOWED;
136 *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
137 szData = ptrTable->pSubindex[bSubindex].size;
139 if(*pExpectedSize == 0 ||
140 *pExpectedSize == szData ||
141 /* allow to fetch a shorter string than expected */
142 (*pDataType >= visible_string && *pExpectedSize < szData)) {
144 # ifdef CANOPEN_BIG_ENDIAN
145 if(endianize && dataType > boolean && !(
146 dataType >= visible_string &&
147 domain <= dataType)) {
148 /* data must be transmited with low byte first */
150 MSG_WAR(boolean, "data type ", *pDataType);
151 MSG_WAR(visible_string, "data type ", *pDataType);
152 for ( i = szData ; i > 0 ; i--) {
154 ((UNS8*)pDestData)[j++] =
155 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
158 else /* no endianisation change */
160 if(*pDataType != visible_string) {
161 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
162 *pExpectedSize = szData;
164 /* TODO : CONFORM TO DS-301 :
165 * - stop using NULL terminated strings
166 * - store string size in td_subindex
168 /* Copy null terminated string to user, and return discovered size */
169 UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
170 UNS8 *ptr_start = ptr;
171 UNS8 *ptr_end = ptr + *pExpectedSize; /* *pExpectedSize IS < szData */
172 UNS8 *ptr_dest = (UNS8*)pDestData;
173 while( *ptr && ptr < ptr_end){
174 *(ptr_dest++) = *(ptr++);
177 *pExpectedSize = ptr - ptr_start;
178 /* terminate string if not maximum length */
179 if (*pExpectedSize < szData)
183 return OD_SUCCESSFUL;
186 *pExpectedSize = szData;
187 accessDictionaryError(wIndex, bSubindex, szData,
188 *pExpectedSize, OD_LENGTH_DATA_INVALID);
189 return OD_LENGTH_DATA_INVALID;
200 ** @param pExpectedSize
202 ** @param checkAccess
206 UNS32 getODentry( CO_Data* d,
210 UNS8 * pExpectedSize,
214 return _getODentry( d,
231 ** @param pExpectedSize
233 ** @param checkAccess
237 UNS32 readLocalDict( CO_Data* d,
241 UNS8 * pExpectedSize,
245 return _getODentry( d,
252 0);//do not endianize
261 ** @param pSourceData
262 ** @param pExpectedSize
263 ** @param checkAccess
268 UNS32 _setODentry( CO_Data* d,
272 UNS8 * pExpectedSize,
279 const indextable *ptrTable;
280 ODCallback_t *Callback;
282 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
283 if (errorCode != OD_SUCCESSFUL)
286 if( ptrTable->bSubCount <= bSubindex ) {
287 /* Subindex not found */
288 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
289 return OD_NO_SUCH_SUBINDEX;
291 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
292 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
293 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
294 return OD_WRITE_NOT_ALLOWED;
298 dataType = ptrTable->pSubindex[bSubindex].bDataType;
299 szData = ptrTable->pSubindex[bSubindex].size;
301 if( *pExpectedSize == 0 ||
302 *pExpectedSize == szData ||
303 /* allow to store a shorter string than entry size */
304 (dataType == visible_string && *pExpectedSize < szData))
306 #ifdef CANOPEN_BIG_ENDIAN
307 /* re-endianize do not occur for bool, strings time and domains */
308 if(endianize && dataType > boolean && !(
309 dataType >= visible_string &&
312 /* we invert the data source directly. This let us do range
314 /* additional temp variable */
316 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
318 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
319 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
320 ((UNS8 *)pSourceData)[i] = tmp;
324 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
326 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
329 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
330 /* TODO : CONFORM TO DS-301 :
331 * - stop using NULL terminated strings
332 * - store string size in td_subindex
334 /* terminate visible_string with '\0' */
335 if(dataType == visible_string && *pExpectedSize < szData)
336 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[*pExpectedSize] = 0;
338 *pExpectedSize = szData;
341 if(Callback && Callback[bSubindex]){
342 (*Callback[bSubindex])(d, ptrTable, bSubindex);
345 /* TODO : Store dans NVRAM */
346 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
347 (*d->storeODSubIndex)(d, wIndex, bSubindex);
349 return OD_SUCCESSFUL;
351 *pExpectedSize = szData;
352 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
353 return OD_LENGTH_DATA_INVALID;
363 ** @param pSourceData
364 ** @param pExpectedSize
365 ** @param checkAccess
369 UNS32 setODentry( CO_Data* d,
373 UNS8 * pExpectedSize,
376 return _setODentry( d,
391 ** @param pSourceData
392 ** @param pExpectedSize
393 ** @param checkAccess
397 UNS32 writeLocalDict( CO_Data* d,
401 UNS8 * pExpectedSize,
404 return _setODentry( d,
410 0);//do not endianize
423 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
425 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
438 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
441 ODCallback_t *CallbackList;
443 scanIndexOD (d, wIndex, &errorCode, &CallbackList);
444 if(errorCode == OD_SUCCESSFUL && CallbackList)
445 CallbackList[bSubindex] = Callback;
455 void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}