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 (*pDataType == visible_string && *pExpectedSize < szData)) {
143 allow to fetch a shorter string than expected */
145 # ifdef CANOPEN_BIG_ENDIAN
146 if(endianize && *pDataType > boolean && *pDataType < visible_string) {
147 /* data must be transmited with low byte first */
149 MSG_WAR(boolean, "data type ", *pDataType);
150 MSG_WAR(visible_string, "data type ", *pDataType);
151 for ( i = szData ; i > 0 ; i--) {
153 ((UNS8*)pDestData)[j++] =
154 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
157 else /* no endianisation change */
159 if(*pDataType < visible_string) {
160 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
161 *pExpectedSize = szData;
163 /* TODO : CONFORM TO DS-301 :
164 * - stop using NULL terminated strings
165 * - store string size in td_subindex
167 /* Copy null terminated string to user, and return discovered size */
168 UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
169 UNS8 *ptr_start = ptr;
170 UNS8 *ptr_end = ptr + *pExpectedSize; /* *pExpectedSize IS < szData */
171 while( *ptr && ptr < ptr_end){
172 *((UNS8*)pDestData++) = *(ptr++);
174 *pExpectedSize = ptr - ptr_start;
177 return OD_SUCCESSFUL;
180 *pExpectedSize = szData;
181 accessDictionaryError(wIndex, bSubindex, szData,
182 *pExpectedSize, OD_LENGTH_DATA_INVALID);
183 return OD_LENGTH_DATA_INVALID;
194 ** @param pExpectedSize
196 ** @param checkAccess
200 UNS32 getODentry( CO_Data* d,
204 UNS8 * pExpectedSize,
208 return _getODentry( d,
225 ** @param pExpectedSize
227 ** @param checkAccess
231 UNS32 readLocalDict( CO_Data* d,
235 UNS8 * pExpectedSize,
239 return _getODentry( d,
246 0);//do not endianize
255 ** @param pSourceData
256 ** @param pExpectedSize
257 ** @param checkAccess
262 UNS32 _setODentry( CO_Data* d,
266 UNS8 * pExpectedSize,
273 const indextable *ptrTable;
274 ODCallback_t *Callback;
276 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
277 if (errorCode != OD_SUCCESSFUL)
280 if( ptrTable->bSubCount <= bSubindex ) {
281 /* Subindex not found */
282 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
283 return OD_NO_SUCH_SUBINDEX;
285 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
286 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
287 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
288 return OD_WRITE_NOT_ALLOWED;
292 dataType = ptrTable->pSubindex[bSubindex].bDataType;
293 szData = ptrTable->pSubindex[bSubindex].size;
295 if( *pExpectedSize == 0 ||
296 *pExpectedSize == szData ||
297 (dataType == visible_string && *pExpectedSize < szData)) /* We
298 allow to store a shorter string than entry size */
300 #ifdef CANOPEN_BIG_ENDIAN
301 if(endianize && dataType > boolean && dataType < visible_string)
303 /* we invert the data source directly. This let us do range
305 /* additional temp variable */
307 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
309 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
310 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
311 ((UNS8 *)pSourceData)[i] = tmp;
315 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
317 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
320 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
321 *pExpectedSize = szData;
324 if(Callback && Callback[bSubindex]){
325 (*Callback[bSubindex])(d, ptrTable, bSubindex);
328 /* TODO : Store dans NVRAM */
329 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
330 (*d->storeODSubIndex)(d, wIndex, bSubindex);
332 return OD_SUCCESSFUL;
334 *pExpectedSize = szData;
335 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
336 return OD_LENGTH_DATA_INVALID;
346 ** @param pSourceData
347 ** @param pExpectedSize
348 ** @param checkAccess
352 UNS32 setODentry( CO_Data* d,
356 UNS8 * pExpectedSize,
359 return _setODentry( d,
374 ** @param pSourceData
375 ** @param pExpectedSize
376 ** @param checkAccess
380 UNS32 writeLocalDict( CO_Data* d,
384 UNS8 * pExpectedSize,
387 return _setODentry( d,
393 0);//do not endianize
406 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
408 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
421 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
424 ODCallback_t *CallbackList;
426 scanIndexOD (d, wIndex, &errorCode, &CallbackList);
427 if(errorCode == OD_SUCCESSFUL && CallbackList)
428 CallbackList[bSubindex] = Callback;
438 void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}