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 #ifdef DEBUG_WAR_CONSOLE_ON
56 UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
57 UNS8 sizeDataDict, UNS8 sizeDataGiven, UNS32 code)
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);
90 #define accessDictionaryError(index, subIndex, sizeDataDict, sizeDataGiven, code)
100 ** @param pExpectedSize
102 ** @param checkAccess
107 UNS32 _getODentry( CO_Data* d,
111 UNS8 * pExpectedSize,
115 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
119 const indextable *ptrTable;
120 ODCallback_t *Callback;
122 ptrTable = (*d->scanIndexOD)(wIndex, &errorCode, &Callback);
124 if (errorCode != OD_SUCCESSFUL)
126 if( ptrTable->bSubCount <= bSubindex ) {
127 /* Subindex not found */
128 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
129 return OD_NO_SUCH_SUBINDEX;
132 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
133 MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
134 accessDictionaryError(wIndex, bSubindex, 0, 0, OD_READ_NOT_ALLOWED);
135 return OD_READ_NOT_ALLOWED;
138 *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
139 szData = ptrTable->pSubindex[bSubindex].size;
141 if(*pExpectedSize == 0 ||
142 *pExpectedSize == szData ||
143 /* allow to fetch a shorter string than expected */
144 (*pDataType >= visible_string && *pExpectedSize < szData)) {
146 # ifdef CANOPEN_BIG_ENDIAN
147 if(endianize && *pDataType > boolean && !(
148 *pDataType >= visible_string &&
149 *pDataType <= domain)) {
150 /* data must be transmited with low byte first */
152 MSG_WAR(boolean, "data type ", *pDataType);
153 MSG_WAR(visible_string, "data type ", *pDataType);
154 for ( i = szData ; i > 0 ; i--) {
156 ((UNS8*)pDestData)[j++] =
157 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
159 *pExpectedSize = szData;
161 else /* no endianisation change */
163 if(*pDataType != visible_string) {
164 memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
165 *pExpectedSize = szData;
167 /* TODO : CONFORM TO DS-301 :
168 * - stop using NULL terminated strings
169 * - store string size in td_subindex
171 /* Copy null terminated string to user, and return discovered size */
172 UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
173 UNS8 *ptr_start = ptr;
174 /* *pExpectedSize IS < szData . if null, use szData */
175 UNS8 *ptr_end = ptr + (*pExpectedSize ? *pExpectedSize : szData) ;
176 UNS8 *ptr_dest = (UNS8*)pDestData;
177 while( *ptr && ptr < ptr_end){
178 *(ptr_dest++) = *(ptr++);
181 *pExpectedSize = ptr - ptr_start;
182 /* terminate string if not maximum length */
183 if (*pExpectedSize < szData)
187 return OD_SUCCESSFUL;
190 *pExpectedSize = szData;
191 accessDictionaryError(wIndex, bSubindex, szData,
192 *pExpectedSize, OD_LENGTH_DATA_INVALID);
193 return OD_LENGTH_DATA_INVALID;
203 ** @param pSourceData
204 ** @param pExpectedSize
205 ** @param checkAccess
210 UNS32 _setODentry( CO_Data* d,
214 UNS8 * pExpectedSize,
221 const indextable *ptrTable;
222 ODCallback_t *Callback;
224 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
225 if (errorCode != OD_SUCCESSFUL)
228 if( ptrTable->bSubCount <= bSubindex ) {
229 /* Subindex not found */
230 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
231 return OD_NO_SUCH_SUBINDEX;
233 if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
234 MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
235 accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
236 return OD_WRITE_NOT_ALLOWED;
240 dataType = ptrTable->pSubindex[bSubindex].bDataType;
241 szData = ptrTable->pSubindex[bSubindex].size;
243 if( *pExpectedSize == 0 ||
244 *pExpectedSize == szData ||
245 /* allow to store a shorter string than entry size */
246 (dataType == visible_string && *pExpectedSize < szData))
248 #ifdef CANOPEN_BIG_ENDIAN
249 /* re-endianize do not occur for bool, strings time and domains */
250 if(endianize && dataType > boolean && !(
251 dataType >= visible_string &&
254 /* we invert the data source directly. This let us do range
256 /* additional temp variable */
258 for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1) ; i++)
260 UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
261 ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
262 ((UNS8 *)pSourceData)[i] = tmp;
266 errorCode = (*d->valueRangeTest)(dataType, pSourceData);
268 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
271 memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
272 /* TODO : CONFORM TO DS-301 :
273 * - stop using NULL terminated strings
274 * - store string size in td_subindex
276 /* terminate visible_string with '\0' */
277 if(dataType == visible_string && *pExpectedSize < szData)
278 ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[*pExpectedSize] = 0;
280 *pExpectedSize = szData;
283 if(Callback && Callback[bSubindex]){
284 errorCode = (Callback[bSubindex])(d, ptrTable, bSubindex);
285 if(errorCode != OD_SUCCESSFUL)
291 /* TODO : Store dans NVRAM */
292 if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
293 (*d->storeODSubIndex)(d, wIndex, bSubindex);
295 return OD_SUCCESSFUL;
297 *pExpectedSize = szData;
298 accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
299 return OD_LENGTH_DATA_INVALID;
313 const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
315 return (*d->scanIndexOD)(wIndex, errorCode, Callback);
328 UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
331 ODCallback_t *CallbackList;
332 const indextable *odentry;
334 odentry = scanIndexOD (d, wIndex, &errorCode, &CallbackList);
335 if(errorCode == OD_SUCCESSFUL && CallbackList && bSubindex < odentry->bSubCount)
336 CallbackList[bSubindex] = Callback;
346 void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}