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_READ_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 && *pDataType > boolean && !(
146 *pDataType >= visible_string &&
147 *pDataType <= domain)) {
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];
157 *pExpectedSize = szData;
159 else /* no endianisation change */
161 if(*pDataType != visible_string) {
162 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
163 *pExpectedSize = szData;
165 /* TODO : CONFORM TO DS-301 :
166 * - stop using NULL terminated strings
167 * - store string size in td_subindex
169 /* Copy null terminated string to user, and return discovered size */
170 UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
171 UNS8 *ptr_start = ptr;
172 /* *pExpectedSize IS < szData . if null, use szData */
173 UNS8 *ptr_end = ptr + (*pExpectedSize ? *pExpectedSize : szData) ;
174 UNS8 *ptr_dest = (UNS8*)pDestData;
175 while( *ptr && ptr < ptr_end){
176 *(ptr_dest++) = *(ptr++);
179 *pExpectedSize = ptr - ptr_start;
180 /* terminate string if not maximum length */
181 if (*pExpectedSize < szData)
185 return OD_SUCCESSFUL;
188 *pExpectedSize = szData;
189 accessDictionaryError(wIndex, bSubindex, szData,
190 *pExpectedSize, OD_LENGTH_DATA_INVALID);
191 return OD_LENGTH_DATA_INVALID;
202 ** @param pExpectedSize
204 ** @param checkAccess
208 UNS32 getODentry( CO_Data* d,
212 UNS8 * pExpectedSize,
216 return _getODentry( d,
233 ** @param pExpectedSize
235 ** @param checkAccess
239 UNS32 readLocalDict( CO_Data* d,
243 UNS8 * pExpectedSize,
247 return _getODentry( d,
254 0);//do not endianize
263 ** @param pSourceData
264 ** @param pExpectedSize
265 ** @param checkAccess
270 UNS32 _setODentry( CO_Data* d,
274 UNS8 * pExpectedSize,
281 const indextable *ptrTable;
282 ODCallback_t *Callback;
284 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
285 if (errorCode != OD_SUCCESSFUL)
288 if( ptrTable->bSubCount <= bSubindex ) {
289 /* Subindex not found */
290 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
291 return OD_NO_SUCH_SUBINDEX;
293 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
294 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
295 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
296 return OD_WRITE_NOT_ALLOWED;
300 dataType = ptrTable->pSubindex[bSubindex].bDataType;
301 szData = ptrTable->pSubindex[bSubindex].size;
303 if( *pExpectedSize == 0 ||
304 *pExpectedSize == szData ||
305 /* allow to store a shorter string than entry size */
306 (dataType == visible_string && *pExpectedSize < szData))
308 #ifdef CANOPEN_BIG_ENDIAN
309 /* re-endianize do not occur for bool, strings time and domains */
310 if(endianize && dataType > boolean && !(
311 dataType >= visible_string &&
314 /* we invert the data source directly. This let us do range
316 /* additional temp variable */
318 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
320 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
321 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
322 ((UNS8 *)pSourceData)[i] = tmp;
326 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
328 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
331 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
332 /* TODO : CONFORM TO DS-301 :
333 * - stop using NULL terminated strings
334 * - store string size in td_subindex
336 /* terminate visible_string with '\0' */
337 if(dataType == visible_string && *pExpectedSize < szData)
338 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[*pExpectedSize] = 0;
340 *pExpectedSize = szData;
343 if(Callback && Callback[bSubindex]){
344 errorCode = (Callback[bSubindex])(d, ptrTable, bSubindex);
345 if(errorCode != OD_SUCCESSFUL)
351 /* TODO : Store dans NVRAM */
352 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
353 (*d->storeODSubIndex)(d, wIndex, bSubindex);
355 return OD_SUCCESSFUL;
357 *pExpectedSize = szData;
358 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
359 return OD_LENGTH_DATA_INVALID;
369 ** @param pSourceData
370 ** @param pExpectedSize
371 ** @param checkAccess
375 UNS32 setODentry( CO_Data* d,
379 UNS8 * pExpectedSize,
382 return _setODentry( d,
397 ** @param pSourceData
398 ** @param pExpectedSize
399 ** @param checkAccess
403 UNS32 writeLocalDict( CO_Data* d,
407 UNS8 * pExpectedSize,
410 return _setODentry( d,
416 0);//do not endianize
429 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
431 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
444 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
447 ODCallback_t *CallbackList;
449 scanIndexOD (d, wIndex, &errorCode, &CallbackList);
450 if(errorCode == OD_SUCCESSFUL && CallbackList)
451 CallbackList[bSubindex] = Callback;
461 void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}