nico@207: nico@207: nico@215: CanFestival: src/sdo.c Source File nico@207: nico@207: nico@207: nico@207: nico@207:
nico@207:
nico@207:
nico@207:
nico@215: nico@215:

sdo.c

Go to the documentation of this file.
00001 /*
nico@207: 00002 This file is part of CanFestival, a library implementing CanOpen Stack. 
nico@207: 00003 
nico@207: 00004 Copyright (C): Edouard TISSERANT and Francis DUPIN
nico@207: 00005 
nico@207: 00006 See COPYING file for copyrights details.
nico@207: 00007 
nico@207: 00008 This library is free software; you can redistribute it and/or
nico@207: 00009 modify it under the terms of the GNU Lesser General Public
nico@207: 00010 License as published by the Free Software Foundation; either
nico@207: 00011 version 2.1 of the License, or (at your option) any later version.
nico@207: 00012 
nico@207: 00013 This library is distributed in the hope that it will be useful,
nico@207: 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
nico@207: 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
nico@207: 00016 Lesser General Public License for more details.
nico@207: 00017 
nico@207: 00018 You should have received a copy of the GNU Lesser General Public
nico@207: 00019 License along with this library; if not, write to the Free Software
nico@207: 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
nico@207: 00021 */
nico@210: 00032 /* #define DEBUG_WAR_CONSOLE_ON */
nico@210: 00033 /* #define DEBUG_ERR_CONSOLE_ON */
nico@210: 00034 
nico@215: 00035 #include "objacces.h"
nico@215: 00036 #include "sdo.h"
nico@215: 00037 #include "canfestival.h"
nico@210: 00038 
nico@210: 00039 /* Uncomment if your compiler does not support inline functions */
etisserant@240: 00040 #define NO_INLINE 
nico@210: 00041 
nico@210: 00042 #ifdef NO_INLINE
etisserant@240: 00043   #define INLINE 
nico@210: 00044 #else
nico@210: 00045   #define INLINE inline
nico@210: 00046 #endif
nico@210: 00047 
nico@210: 00048 /*Internals prototypes*/
nico@207: 00049 
etisserant@240: 00065 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, 
etisserant@240: 00066                        UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
nico@210: 00067 
etisserant@240: 00080 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, 
etisserant@240: 00081         UNS8 dataType, SDOCallback_t Callback);
nico@210: 00082         
nico@210: 00083 
nico@210: 00084 /***************************************************************************/
nico@210: 00085 /* SDO (un)packing macros */
nico@210: 00086 
etisserant@240: 00089 #define getSDOcs(byte) (byte >> 5)
nico@210: 00090 
etisserant@240: 00093 #define getSDOn2(byte) ((byte >> 2) & 3)
nico@210: 00094 
etisserant@240: 00097 #define getSDOn3(byte) ((byte >> 1) & 7)
nico@210: 00098 
etisserant@240: 00101 #define getSDOe(byte) ((byte >> 1) & 1)
nico@210: 00102 
etisserant@240: 00105 #define getSDOs(byte) (byte & 1)
nico@210: 00106 
etisserant@240: 00109 #define getSDOc(byte) (byte & 1)
nico@210: 00110 
etisserant@240: 00113 #define getSDOt(byte) ((byte >> 4) & 1)
nico@210: 00114 
etisserant@240: 00117 #define getSDOindex(byte1, byte2) ((byte2 << 8) | (byte1))
nico@210: 00118 
etisserant@240: 00121 #define getSDOsubIndex(byte3) (byte3)
nico@210: 00122 
etisserant@240: 00129 void SDOTimeoutAlarm(CO_Data* d, UNS32 id)
nico@210: 00130 {
etisserant@240: 00131     MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
etisserant@240: 00132     MSG_WAR(0x2A02, "server node : ", d->transfers[id].nodeId);
etisserant@240: 00133     MSG_WAR(0x2A02, "      index : ", d->transfers[id].index);
etisserant@240: 00134     MSG_WAR(0x2A02, "   subIndex : ", d->transfers[id].subIndex); 
nico@210: 00135     /* Reset timer handler */
etisserant@240: 00136     d->transfers[id].timer = TIMER_NONE;
nico@210: 00137     /*Set aborted state*/
etisserant@240: 00138     d->transfers[id].state = SDO_ABORTED_INTERNAL;
nico@210: 00139     /* Sending a SDO abort */
etisserant@240: 00140     sendSDOabort(d, d->transfers[id].whoami, 
etisserant@240: 00141                  d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);
etisserant@240: 00142     d->transfers[id].abortCode = SDOABT_TIMED_OUT;
nico@210: 00143     /* Call the user function to inform of the problem.*/
etisserant@240: 00144     if(d->transfers[id].Callback)
nico@210: 00145         /*If ther is a callback, it is responsible to close SDO transfer (client)*/
etisserant@240: 00146         (*d->transfers[id].Callback)(d,d->transfers[id].nodeId);
etisserant@240: 00147     else if(d->transfers[id].whoami == SDO_SERVER)
nico@210: 00148         /*Else, if server, reset the line*/
etisserant@240: 00149         resetSDOline(d, (UNS8)id);
nico@210: 00150 }
nico@210: 00151 
etisserant@240: 00152 #define StopSDO_TIMER(id) \
nico@210: 00153 MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\
nico@210: 00154 d->transfers[id].timer = DelAlarm(d->transfers[id].timer);
nico@210: 00155 
etisserant@240: 00156 #define StartSDO_TIMER(id) \
nico@210: 00157 MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\
nico@210: 00158 d->transfers[id].timer = SetAlarm(d,id,&SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);
nico@210: 00159 
etisserant@240: 00160 #define RestartSDO_TIMER(id) \
nico@210: 00161 MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
nico@210: 00162 if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
nico@210: 00163 
etisserant@240: 00169 void resetSDO (CO_Data* d)
nico@210: 00170 {
etisserant@240: 00171   UNS8 j;
nico@210: 00172 
nico@215: 00173   /* transfer structure initialization */
etisserant@240: 00174     for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++) 
etisserant@240: 00175       resetSDOline(d, j);
nico@210: 00176 }
nico@210: 00177 
etisserant@240: 00186 UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line)
nico@210: 00187 {
etisserant@240: 00188   UNS8      size;
etisserant@240: 00189   UNS32 errorCode;
etisserant@240: 00190   MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);
etisserant@240: 00191   size = (UNS8)d->transfers[line].count;
etisserant@240: 00192   errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex, 
etisserant@240: 00193                          (void *) d->transfers[line].data, &size, 1);
etisserant@240: 00194   if (errorCode != OD_SUCCESSFUL)
nico@210: 00195     return errorCode;
etisserant@240: 00196   MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
nico@210: 00197   return 0;
nico@210: 00198 
nico@210: 00199 }
nico@210: 00200 
etisserant@240: 00209 UNS32 objdictToSDOline (CO_Data* d, UNS8 line)
nico@210: 00210 {
etisserant@240: 00211   UNS8  size = 0;
etisserant@240: 00212   UNS8  dataType;
etisserant@240: 00213   UNS32 errorCode;
nico@210: 00214 
etisserant@240: 00215   MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
etisserant@240: 00216   MSG_WAR(0x3A06, "  subIndex : ", d->transfers[line].subIndex);
nico@210: 00217 
etisserant@240: 00218   errorCode = getODentry(d,     d->transfers[line].index,
etisserant@240: 00219                                 d->transfers[line].subIndex,
etisserant@240: 00220                                 (void *)d->transfers[line].data,
nico@210: 00221                                 &size, &dataType, 0);
nico@210: 00222   
etisserant@240: 00223   if (errorCode != OD_SUCCESSFUL)
nico@210: 00224     return errorCode;
nico@207: 00225 
etisserant@240: 00226   d->transfers[line].count = size;
etisserant@240: 00227   d->transfers[line].offset = 0;
nico@210: 00228 #if 0
nico@210: 00229    /*Me laisser a, please ! (FD)*/
nico@210: 00230   {
etisserant@240: 00231     UNS8 i;
nico@210: 00232     for (i = 0 ; i < 10 ; i++) {
etisserant@240: 00233       MSG_WAR(i, "data= ", d->transfers[line].data[i]);
nico@210: 00234     }     
nico@210: 00235   }
nico@210: 00236 #endif
nico@210: 00237   return 0;
nico@210: 00238 }
nico@210: 00239 
etisserant@240: 00250 UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data) {
etisserant@240: 00251   UNS8 i;
etisserant@240: 00252   UNS8 offset;
nico@210: 00253 
etisserant@240: 00254   if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
etisserant@240: 00255     MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
nico@210: 00256     return 0xFF;
nico@210: 00257   }
etisserant@240: 00258     if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
etisserant@240: 00259     MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
nico@210: 00260     return 0xFF;
nico@210: 00261   }
etisserant@240: 00262   offset = (UNS8)d->transfers[line].offset;
nico@210: 00263   for (i = 0 ; i < nbBytes ; i++) 
etisserant@240: 00264     * (data + i) = d->transfers[line].data[offset + i];
etisserant@240: 00265   d->transfers[line].offset = d->transfers[line].offset + nbBytes;
nico@210: 00266   return 0;
nico@210: 00267 }
nico@210: 00268 
etisserant@240: 00279 UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data)
nico@210: 00280 {
etisserant@240: 00281   UNS8 i;
etisserant@240: 00282   UNS8 offset;
nico@210: 00283   
etisserant@240: 00284   if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
etisserant@240: 00285     MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
nico@210: 00286     return 0xFF;
nico@210: 00287   }
etisserant@240: 00288   offset = (UNS8)d->transfers[line].offset;
nico@210: 00289   for (i = 0 ; i < nbBytes ; i++) 
etisserant@240: 00290     d->transfers[line].data[offset + i] = * (data + i);
etisserant@240: 00291   d->transfers[line].offset = d->transfers[line].offset + nbBytes;
nico@210: 00292   return 0;
nico@210: 00293 }
nico@210: 00294 
etisserant@240: 00307 UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index, 
etisserant@240: 00308                 UNS8 subIndex, UNS32 abortCode)
nico@210: 00309 {
etisserant@240: 00310   UNS8 err;
etisserant@240: 00311   UNS8 line;
etisserant@240: 00312   err = getSDOlineOnUse( d, nodeId, whoami, &line );
nico@210: 00313   if (!err) /* If a line on use have been found.*/
etisserant@240: 00314     MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
etisserant@240: 00315   if ((! err) && (whoami == SDO_SERVER)) {
etisserant@240: 00316     resetSDOline( d, line );
etisserant@240: 00317     MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
nico@210: 00318   }
etisserant@240: 00319   if ((! err) && (whoami == SDO_CLIENT)) {
etisserant@240: 00320     StopSDO_TIMER(line);
etisserant@240: 00321     d->transfers[line].state = SDO_ABORTED_INTERNAL;
nico@210: 00322   }
etisserant@240: 00323   MSG_WAR(0x3A22, "Sending SDO abort ", 0);
etisserant@240: 00324   err = sendSDOabort(d, whoami, index, subIndex, abortCode);
nico@210: 00325   if (err) {
etisserant@240: 00326     MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
nico@210: 00327     return 0xFF;
nico@210: 00328   }
nico@210: 00329   return 0;
nico@210: 00330 }
nico@210: 00331 
etisserant@240: 00338 void resetSDOline ( CO_Data* d, UNS8 line )
nico@210: 00339 {
etisserant@240: 00340   UNS8 i; 
etisserant@240: 00341   MSG_WAR(0x3A25, "reset SDO line nb : ", line); 
etisserant@240: 00342   initSDOline(d, line, 0, 0, 0, SDO_RESET);
etisserant@240: 00343   for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
etisserant@240: 00344     d->transfers[line].data[i] = 0;
nico@210: 00345 }
nico@210: 00346 
etisserant@240: 00359 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
nico@210: 00360 {
etisserant@240: 00361   MSG_WAR(0x3A25, "init SDO line nb : ", line); 
etisserant@240: 00362   if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
etisserant@240: 00363         StartSDO_TIMER(line)
nico@210: 00364   }else{
etisserant@240: 00365         StopSDO_TIMER(line)
nico@210: 00366   }
etisserant@240: 00367   d->transfers[line].nodeId = nodeId; 
etisserant@240: 00368   d->transfers[line].index = index;
etisserant@240: 00369   d->transfers[line].subIndex = subIndex;
etisserant@240: 00370   d->transfers[line].state = state;
etisserant@240: 00371   d->transfers[line].toggle = 0;
etisserant@240: 00372   d->transfers[line].count = 0;
etisserant@240: 00373   d->transfers[line].offset = 0;
etisserant@240: 00374   d->transfers[line].dataType = 0;
etisserant@240: 00375   d->transfers[line].Callback = NULL;  
nico@210: 00376   return 0;
nico@210: 00377 }
nico@210: 00378 
etisserant@240: 00388 UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
nico@210: 00389 {
nico@210: 00390         
etisserant@240: 00391   UNS8 i;
nico@210: 00392     
etisserant@240: 00393   for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
etisserant@240: 00394     if ( d->transfers[i].state == SDO_RESET ) {
nico@210: 00395       *line = i;
etisserant@240: 00396       d->transfers[i].whoami = whoami;
nico@210: 00397       return 0;
nico@210: 00398     } /* end if */
nico@210: 00399   } /* end for */
etisserant@240: 00400   MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
nico@210: 00401   return 0xFF;
nico@210: 00402 }
nico@210: 00403 
etisserant@240: 00414 UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
nico@210: 00415 {
nico@210: 00416         
etisserant@240: 00417   UNS8 i;
nico@210: 00418     
etisserant@240: 00419   for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
etisserant@240: 00420     if ( (d->transfers[i].state != SDO_RESET) &&
etisserant@240: 00421          (d->transfers[i].nodeId == nodeId) && 
etisserant@240: 00422          (d->transfers[i].whoami == whoami) ) {
nico@210: 00423       *line = i;
nico@210: 00424       return 0;
nico@210: 00425     }
nico@210: 00426   } 
nico@210: 00427   return 0xFF;
nico@210: 00428 }
nico@210: 00429 
etisserant@240: 00439 UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
nico@210: 00440 {
etisserant@240: 00441   UNS8 err;
etisserant@240: 00442   UNS8 line;
etisserant@240: 00443   err = getSDOlineOnUse(d, nodeId, whoami, &line);
nico@210: 00444   if (err) {
etisserant@240: 00445     MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId); 
nico@210: 00446     return 0xFF;
nico@210: 00447   }
etisserant@240: 00448   resetSDOline(d, line);  
nico@210: 00449   return 0;
nico@210: 00450 }
nico@210: 00451 
etisserant@240: 00461 UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes)
nico@210: 00462 {
etisserant@240: 00463   if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
nico@210: 00464     * nbBytes = 0;
nico@210: 00465   else
etisserant@240: 00466     * nbBytes = (UNS8)d->transfers[line].count - (UNS8)d->transfers[line].offset;
nico@210: 00467   return 0;
nico@210: 00468 }
nico@210: 00469 
etisserant@240: 00479 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes)
nico@210: 00480 {
etisserant@240: 00481   if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
etisserant@240: 00482     MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
nico@210: 00483     return 0xFF;
nico@210: 00484   }
etisserant@240: 00485   d->transfers[line].count = nbBytes;
nico@210: 00486   return 0;
nico@210: 00487 }
nico@210: 00488 
etisserant@240: 00498 UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
nico@210: 00499 {       
etisserant@240: 00500   UNS16 offset;
etisserant@240: 00501   UNS16 lastIndex;
etisserant@240: 00502   UNS8 found = 0;
nico@215: 00503   Message m;
etisserant@240: 00504   UNS8 i;
etisserant@240: 00505   UNS32 * pwCobId = NULL;
etisserant@240: 00506   UNS32 * pwNodeId = NULL;
nico@210: 00507 
etisserant@240: 00508   MSG_WAR(0x3A38, "sendSDO",0);
etisserant@240: 00509   if( !((d->nodeState == Operational) ||  (d->nodeState == Pre_operational ))) {
etisserant@240: 00510     MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
nico@210: 00511     return 0xFF;
nico@210: 00512   }                             
nico@210: 00513 
nico@215: 00514   /*get the server->client cobid*/
etisserant@240: 00515   if ( whoami == SDO_SERVER )   {/*case server. Easy because today only one server SDO is authorized in CanFestival*/
etisserant@240: 00516     offset = d->firstIndex->SDO_SVR;
nico@210: 00517     if (offset == 0) {
etisserant@240: 00518       MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0); 
nico@210: 00519       return 0xFF;
nico@210: 00520     }
etisserant@240: 00521     pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
etisserant@240: 00522     MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId); 
nico@210: 00523   }
nico@215: 00524   else {                        /*case client*/
nico@215: 00525     /* Get the client->server cobid.*/
etisserant@240: 00526     UNS16 sdoNum = 0;
etisserant@240: 00527     offset = d->firstIndex->SDO_CLT;
etisserant@240: 00528     lastIndex = d->lastIndex->SDO_CLT;
nico@210: 00529     if (offset == 0) {
etisserant@240: 00530       MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0); 
nico@210: 00531       return 0xFF;
nico@210: 00532     }
nico@215: 00533     /* First, have to find at the index where is defined the communication with the server node */
nico@210: 00534     while (offset <= lastIndex){
etisserant@240: 00535       MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
etisserant@240: 00536       if (d->objdict[offset].bSubCount <= 3) {
etisserant@240: 00537         MSG_ERR(0x1A28, "Subindex 3  not found at index ", 0x1280 + sdoNum);
nico@210: 00538         return 0xFF;
nico@210: 00539       }
etisserant@240: 00540       pwNodeId = (UNS32*) d->objdict[offset].pSubindex[3].pObject;
etisserant@240: 00541       MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);     
etisserant@240: 00542       if(*pwNodeId == sdo.nodeId) {
nico@210: 00543         found = 1;
nico@210: 00544         break;          
nico@210: 00545       }      
nico@210: 00546       offset ++;
nico@210: 00547       sdoNum ++;
nico@210: 00548     }
nico@210: 00549     if (! found){
etisserant@240: 00550       MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
nico@210: 00551       return 0xFF;
nico@210: 00552     }
nico@215: 00553     /* Second, read the cobid client->server */
etisserant@240: 00554     pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
nico@210: 00555   }
nico@215: 00556   /* message copy for sending */
etisserant@240: 00557   m.cob_id.w = *pwCobId;
etisserant@240: 00558   m.rtr = NOT_A_REQUEST; 
nico@215: 00559   /* the length of SDO must be 8 */
etisserant@240: 00560   m.len = 8;
nico@210: 00561   for (i = 0 ; i < 8 ; i++) {
etisserant@240: 00562     m.data[i] =  sdo.body.data[i];
nico@210: 00563   }
etisserant@240: 00564   return canSend(d->canHandle,&m);
nico@210: 00565 }
nico@210: 00566 
etisserant@240: 00578 UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode)
nico@210: 00579 {
nico@215: 00580   s_SDO sdo;
etisserant@240: 00581   UNS8 ret;
etisserant@240: 00582   MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
etisserant@240: 00583   sdo.nodeId = *d->bDeviceNodeId;
etisserant@240: 00584   sdo.body.data[0] = 0x80;
nico@210: 00585   /* Index */
etisserant@240: 00586   sdo.body.data[1] = index & 0xFF; /* LSB */
etisserant@240: 00587   sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
nico@210: 00588   /* Subindex */
etisserant@240: 00589   sdo.body.data[3] = subIndex;
nico@210: 00590   /* Data */
etisserant@240: 00591   sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
etisserant@240: 00592   sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
etisserant@240: 00593   sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
etisserant@240: 00594   sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
etisserant@240: 00595   ret = sendSDO(d, whoami, sdo);
nico@210: 00596 
nico@210: 00597   return ret;
nico@210: 00598 }
nico@210: 00599 
etisserant@240: 00608 UNS8 proceedSDO (CO_Data* d, Message *m)
nico@210: 00609 {
etisserant@240: 00610   UNS8 err;
etisserant@240: 00611   UNS8 line;
etisserant@240: 00612   UNS8 nbBytes; /* received or to be transmited. */
etisserant@240: 00613   UNS8 nodeId = 0;  /* The node from which the SDO is received */
etisserant@240: 00614   UNS32 nodeId_32; /* node id in 32 bits, for temporary use */
etisserant@240: 00615   UNS32 *pNodeId = NULL;
etisserant@240: 00616   UNS8 whoami = SDO_UNKNOWN;  /* SDO_SERVER or SDO_CLIENT.*/
etisserant@240: 00617   UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
nico@215: 00618   s_SDO sdo;    /* SDO to transmit */
etisserant@240: 00619   UNS16 index;
etisserant@240: 00620   UNS8 subIndex;
etisserant@240: 00621   UNS32 abortCode;
etisserant@240: 00622   UNS8 i,j;
etisserant@240: 00623   UNS32 *     pCobId = NULL;
etisserant@240: 00624   UNS16 offset;
etisserant@240: 00625   UNS16 lastIndex;
nico@210: 00626 
etisserant@240: 00627   MSG_WAR(0x3A60, "proceedSDO ", 0);
etisserant@240: 00628   whoami = SDO_UNKNOWN;
nico@215: 00629   /* Looking for the cobId in the object dictionary. */
nico@215: 00630   /* Am-I a server ? */
etisserant@240: 00631   offset = d->firstIndex->SDO_SVR;
etisserant@240: 00632   lastIndex = d->lastIndex->SDO_SVR;
nico@210: 00633   j = 0;
nico@210: 00634   if(offset) while (offset <= lastIndex) {
etisserant@240: 00635      if (d->objdict[offset].bSubCount <= 1) {
etisserant@240: 00636           MSG_ERR(0x1A61, "Subindex 1  not found at index ", 0x1200 + j);
nico@210: 00637           return 0xFF;
nico@210: 00638         }
etisserant@240: 00639       pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
etisserant@240: 00640       if ( *pCobId == (*m).cob_id.w ) {
etisserant@240: 00641         whoami = SDO_SERVER;
etisserant@240: 00642         MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
nico@215: 00643         /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
nico@215: 00644         /* 0x1200 where the cobid received is defined. */
nico@210: 00645         nodeId = j;
nico@210: 00646         break;
nico@210: 00647       }
nico@210: 00648       j++;
nico@210: 00649       offset++;
nico@215: 00650   } /* end while */
etisserant@240: 00651   if (whoami == SDO_UNKNOWN) {
nico@215: 00652     /* Am-I client ? */
etisserant@240: 00653     offset = d->firstIndex->SDO_CLT;
etisserant@240: 00654     lastIndex = d->lastIndex->SDO_CLT;
nico@210: 00655     j = 0;
nico@210: 00656     if(offset) while (offset <= lastIndex) {
etisserant@240: 00657        if (d->objdict[offset].bSubCount <= 3) {
etisserant@240: 00658          MSG_ERR(0x1A63, "Subindex 3  not found at index ", 0x1280 + j);
nico@210: 00659          return 0xFF;
nico@210: 00660        }
nico@215: 00661        /* a) Looking for the cobid received. */
etisserant@240: 00662        pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
etisserant@240: 00663        if (*pCobId == (*m).cob_id.w ) {
nico@215: 00664          /* b) cobid found, so reading the node id of the server. */
etisserant@240: 00665          pNodeId = (UNS32*) d->objdict[offset].pSubindex[3].pObject;
etisserant@240: 00666          whoami = SDO_CLIENT;
nico@210: 00667          nodeId_32 = *pNodeId;
etisserant@240: 00668          nodeId = (UNS8)nodeId_32;
etisserant@240: 00669          MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
etisserant@240: 00670          MSG_WAR(0x3A65, "                 Server nodeId : ", nodeId);
nico@210: 00671          break;
nico@210: 00672         }
nico@210: 00673        j++;
nico@210: 00674        offset++;
nico@210: 00675     } /* end while */
nico@210: 00676   }
etisserant@240: 00677   if (whoami == SDO_UNKNOWN) {
nico@215: 00678     return 0xFF;/* This SDO was not for us ! */
nico@210: 00679   }
nico@210: 00680 
nico@215: 00681   /* Test if the size of the SDO is ok */
nico@210: 00682   if ( (*m).len != 8) {
etisserant@240: 00683     MSG_ERR(0x1A67, "Error size SDO. CobId  : ", (*m).cob_id.w);
etisserant@240: 00684     failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
nico@210: 00685     return 0xFF;
nico@210: 00686   }
nico@210: 00687   
etisserant@240: 00688   if (whoami == SDO_CLIENT) {
etisserant@240: 00689     MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
nico@210: 00690   }
nico@210: 00691   else {
etisserant@240: 00692     MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", (*m).cob_id.w);
nico@210: 00693   }
nico@210: 00694     
nico@215: 00695   /* Testing the command specifier */
nico@215: 00696   /* Allowed : cs = 0, 1, 2, 3, 4. (=  all except those for block tranfert). */
nico@215: 00697   /* cs = other : Not allowed -> abort. */
etisserant@240: 00698   switch (getSDOcs(m->data[0])) {
nico@210: 00699 
nico@210: 00700   case 0:
nico@215: 00701     /* I am SERVER */
etisserant@240: 00702     if (whoami == SDO_SERVER) {
nico@215: 00703       /* Receiving a download segment data. */
nico@215: 00704       /* A SDO transfert should have been yet initiated. */
etisserant@240: 00705       err = getSDOlineOnUse( d, nodeId, whoami, &line ); 
nico@210: 00706       if (!err)
etisserant@240: 00707         err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
nico@210: 00708       if (err) {
etisserant@240: 00709         MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ", 
nico@210: 00710                 nodeId); 
etisserant@240: 00711         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00712         return 0xFF;
nico@210: 00713       }
nico@215: 00714       /* Reset the wathdog */
etisserant@240: 00715       RestartSDO_TIMER(line)
etisserant@240: 00716       MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId); 
etisserant@240: 00717       index = d->transfers[line].index;
etisserant@240: 00718       subIndex = d->transfers[line].subIndex;
nico@215: 00719       /* Toggle test. */
etisserant@240: 00720       if (d->transfers[line].toggle != getSDOt(m->data[0])) {
etisserant@240: 00721         MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0])); 
etisserant@240: 00722         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
nico@210: 00723         return 0xFF;
nico@210: 00724       }
nico@215: 00725       /* Nb of data to be downloaded */
etisserant@240: 00726       nbBytes = 7 - getSDOn3(m->data[0]);
nico@215: 00727       /* Store the data in the transfert structure. */
etisserant@240: 00728       err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
nico@207: 00729       if (err) {
etisserant@240: 00730         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00731         return 0xFF;
nico@210: 00732       }
nico@215: 00733       /* Sending the SDO response, CS = 1 */
etisserant@240: 00734       sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
etisserant@240: 00735       sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
nico@210: 00736       for (i = 1 ; i < 8 ; i++)
etisserant@240: 00737         sdo.body.data[i] = 0;
etisserant@240: 00738       MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId); 
etisserant@240: 00739       sendSDO(d, whoami, sdo);
nico@215: 00740       /* Inverting the toggle for the next segment. */
nico@210: 00741       d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
nico@215: 00742       /* If it was the last segment, */
etisserant@240: 00743       if (getSDOc(m->data[0])) {
nico@215: 00744         /* Transfering line data to object dictionary. */
nico@215: 00745         /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
etisserant@240: 00746         errorCode = SDOlineToObjdict(d, line);
nico@210: 00747         if (errorCode) {
etisserant@240: 00748           MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0); 
etisserant@240: 00749           failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
nico@210: 00750           return 0xFF;    
nico@210: 00751         }
nico@215: 00752         /* Release of the line */
etisserant@240: 00753         resetSDOline(d, line);
etisserant@240: 00754         MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId); 
nico@210: 00755       }
nico@210: 00756     } /* end if SERVER */
nico@210: 00757     else { /* if CLIENT */
nico@215: 00758       /* I am CLIENT */
nico@215: 00759       /* It is a request for a previous upload segment. We should find a line opened for this.*/
etisserant@240: 00760       err = getSDOlineOnUse( d, nodeId, whoami, &line);
nico@210: 00761       if (!err)
etisserant@240: 00762         err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
nico@210: 00763       if (err) {
etisserant@240: 00764         MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId); 
etisserant@240: 00765         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00766         return 0xFF;
nico@210: 00767       }
nico@215: 00768       /* Reset the wathdog */
etisserant@240: 00769       RestartSDO_TIMER(line)
etisserant@240: 00770       index = d->transfers[line].index;
etisserant@240: 00771       subIndex = d->transfers[line].subIndex;
nico@215: 00772       /* test of the toggle; */
etisserant@240: 00773       if (d->transfers[line].toggle != getSDOt(m->data[0])) {
etisserant@240: 00774         MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId); 
etisserant@240: 00775         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
nico@210: 00776         return 0xFF;
nico@210: 00777       }
nico@215: 00778       /* nb of data to be uploaded */
etisserant@240: 00779       nbBytes = 7 - getSDOn3(m->data[0]);
nico@215: 00780       /* Storing the data in the line structure. */
etisserant@240: 00781       err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
nico@210: 00782       if (err) {
etisserant@240: 00783         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00784         return 0xFF;
nico@210: 00785       }
nico@215: 00786       /* Inverting the toggle for the next segment. */
etisserant@240: 00787       d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
nico@215: 00788       /* If it was the last segment,*/
etisserant@240: 00789       if ( getSDOc(m->data[0])) {
nico@215: 00790         /* Put in state finished */
nico@215: 00791         /* The code is safe for the case e=s=0 in initiate frame. */
etisserant@240: 00792         StopSDO_TIMER(line)
etisserant@240: 00793         d->transfers[line].state = SDO_FINISHED;
etisserant@240: 00794         if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
nico@210: 00795         
etisserant@240: 00796         MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
nico@210: 00797       }
nico@215: 00798       else { /* more segments to receive */
nico@215: 00799              /* Sending the request for the next segment. */
etisserant@240: 00800         sdo.nodeId = nodeId;
etisserant@240: 00801         sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
nico@210: 00802         for (i = 1 ; i < 8 ; i++)
etisserant@240: 00803           sdo.body.data[i] = 0;
etisserant@240: 00804         sendSDO(d, whoami, sdo);
etisserant@240: 00805         MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
nico@210: 00806       }            
nico@210: 00807     } /* End if CLIENT */
nico@210: 00808     break;
nico@210: 00809 
nico@210: 00810   case 1:
nico@215: 00811     /* I am SERVER */
nico@215: 00812     /* Receive of an initiate download */
etisserant@240: 00813     if (whoami == SDO_SERVER) {
etisserant@240: 00814       index = getSDOindex(m->data[1],m->data[2]);
etisserant@240: 00815       subIndex = getSDOsubIndex(m->data[3]);
etisserant@240: 00816       MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ", 
nico@210: 00817               nodeId); 
etisserant@240: 00818       MSG_WAR(0x3A80, "Writing at index : ", index);
etisserant@240: 00819       MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
nico@210: 00820       
nico@215: 00821       /* Search if a SDO transfert have been yet initiated */
etisserant@240: 00822       err = getSDOlineOnUse( d, nodeId, whoami, &line );
nico@210: 00823       if (! err) {
etisserant@240: 00824         MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0); 
etisserant@240: 00825         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00826         return 0xFF;
nico@210: 00827       }
nico@215: 00828       /* No line on use. Great ! */
nico@215: 00829       /* Try to open a new line. */
etisserant@240: 00830       err = getSDOfreeLine( d, whoami, &line );
nico@210: 00831       if (err) {
etisserant@240: 00832         MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
etisserant@240: 00833         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00834         return 0xFF;
nico@210: 00835       }
etisserant@240: 00836       initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);      
nico@210: 00837 
etisserant@240: 00838       if (getSDOe(m->data[0])) { /* If SDO expedited */
nico@215: 00839         /* nb of data to be downloaded */
etisserant@240: 00840         nbBytes = 4 - getSDOn2(m->data[0]);
nico@215: 00841         /* Storing the data in the line structure. */
etisserant@240: 00842         d->transfers[line].count = nbBytes;
etisserant@240: 00843         err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
nico@210: 00844         
nico@210: 00845         if (err) {
etisserant@240: 00846           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00847           return 0xFF;
nico@210: 00848         }         
nico@210: 00849 
nico@215: 00850         /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
nico@215: 00851         /*The line will be reseted when it is downloading in the dictionary. */
etisserant@240: 00852         MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
nico@215: 00853         /* Transfering line data to object dictionary. */
etisserant@240: 00854         errorCode = SDOlineToObjdict(d, line);
nico@210: 00855         if (errorCode) {
etisserant@240: 00856           MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0); 
etisserant@240: 00857           failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
nico@210: 00858           return 0xFF;
nico@210: 00859         }
nico@215: 00860         /* Release of the line. */
etisserant@240: 00861         resetSDOline(d, line);
nico@210: 00862       }
nico@215: 00863       else {/* So, if it is not an expedited transfert */
etisserant@240: 00864         if (getSDOs(m->data[0])) {
nico@215: 00865           /* TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
etisserant@240: 00866           nbBytes = m->data[4]; /* Transfert limited to 255 bytes. */
etisserant@240: 00867           err = setSDOlineRestBytes(d, nodeId, nbBytes);
nico@210: 00868           if (err) {
etisserant@240: 00869             failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00870             return 0xFF;
nico@210: 00871           }     
nico@210: 00872         }
nico@210: 00873       }
nico@215: 00874       /*Sending a SDO, cs=3*/
etisserant@240: 00875       sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
etisserant@240: 00876       sdo.body.data[0] = 3 << 5;
etisserant@240: 00877       sdo.body.data[1] = index & 0xFF;        /* LSB */
etisserant@240: 00878       sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
etisserant@240: 00879       sdo.body.data[3] = subIndex;
nico@210: 00880       for (i = 4 ; i < 8 ; i++)
etisserant@240: 00881                 sdo.body.data[i] = 0;
etisserant@240: 00882       sendSDO(d, whoami, sdo);
nico@210: 00883     } /* end if I am SERVER */
nico@210: 00884     else {
nico@215: 00885       /* I am CLIENT */
nico@215: 00886       /* It is a response for a previous download segment. We should find a line opened for this. */
etisserant@240: 00887       err = getSDOlineOnUse( d, nodeId, whoami, &line);
nico@210: 00888       if (!err)
etisserant@240: 00889         err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
nico@210: 00890       if (err) {
etisserant@240: 00891         MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId); 
etisserant@240: 00892         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00893         return 0xFF;
nico@210: 00894       }
nico@215: 00895       /* Reset the wathdog */
etisserant@240: 00896       RestartSDO_TIMER(line)
etisserant@240: 00897       index = d->transfers[line].index;
etisserant@240: 00898       subIndex = d->transfers[line].subIndex;
nico@215: 00899       /* test of the toggle; */
etisserant@240: 00900       if (d->transfers[line].toggle != getSDOt(m->data[0])) {
etisserant@240: 00901         MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId); 
etisserant@240: 00902         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
nico@210: 00903         return 0xFF;
nico@210: 00904       }
nico@210: 00905 
nico@215: 00906       /* End transmission or downloading next segment. We need to know if it will be the last one. */
etisserant@240: 00907       getSDOlineRestBytes(d, line, &nbBytes);
nico@210: 00908       if (nbBytes == 0) {
etisserant@240: 00909         MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId); 
etisserant@240: 00910         StopSDO_TIMER(line)
etisserant@240: 00911         d->transfers[line].state = SDO_FINISHED;
etisserant@240: 00912         if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
nico@210: 00913         return 0x00;
nico@210: 00914       }
nico@215: 00915       /* At least one transfer to send. */
nico@210: 00916       if (nbBytes > 7) {
nico@215: 00917         /* several segments to download.*/
nico@215: 00918         /* code to send the next segment. (cs = 0; c = 0) */
etisserant@240: 00919         d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
etisserant@240: 00920         sdo.nodeId = nodeId; /* The server node Id; */
etisserant@240: 00921         sdo.body.data[0] = (d->transfers[line].toggle << 4);
etisserant@240: 00922         err = lineToSDO(d, line, 7, sdo.body.data + 1);  
nico@210: 00923         if (err) {
etisserant@240: 00924           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00925           return 0xFF;
nico@210: 00926         }
nico@210: 00927       } 
nico@210: 00928       else {
nico@215: 00929         /* Last segment. */
nico@215: 00930         /* code to send the last segment. (cs = 0; c = 1)*/
etisserant@240: 00931         d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
etisserant@240: 00932         sdo.nodeId = nodeId; /* The server node Id; */
etisserant@240: 00933         sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
etisserant@240: 00934         err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);    
nico@210: 00935         if (err) {
etisserant@240: 00936           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 00937           return 0xFF;
nico@210: 00938         }
nico@210: 00939         for (i = nbBytes + 1 ; i < 8 ; i++)
etisserant@240: 00940           sdo.body.data[i] = 0;
nico@210: 00941       }
etisserant@240: 00942       MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId); 
etisserant@240: 00943       sendSDO(d, whoami, sdo); 
nico@215: 00944     } /* end if I am a CLIENT */                          
nico@210: 00945     break;
nico@210: 00946 
nico@210: 00947   case 2:
nico@215: 00948     /* I am SERVER */
nico@215: 00949     /* Receive of an initiate upload.*/
etisserant@240: 00950     if (whoami == SDO_SERVER) {
etisserant@240: 00951       index = getSDOindex(m->data[1],m->data[2]);
etisserant@240: 00952       subIndex = getSDOsubIndex(m->data[3]);
etisserant@240: 00953       MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ", 
nico@210: 00954               nodeId); 
etisserant@240: 00955       MSG_WAR(0x3A90, "Reading at index : ", index);
etisserant@240: 00956       MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
nico@215: 00957       /* Search if a SDO transfert have been yet initiated*/
etisserant@240: 00958       err = getSDOlineOnUse( d, nodeId, whoami, &line );
nico@210: 00959       if (! err) {
etisserant@240: 00960             MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line); 
etisserant@240: 00961         MSG_WAR(0x3A93, "nodeId = ", nodeId); 
etisserant@240: 00962             failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00963             return 0xFF;
nico@210: 00964       }
nico@215: 00965       /* No line on use. Great !*/
nico@215: 00966       /* Try to open a new line.*/
etisserant@240: 00967       err = getSDOfreeLine( d, whoami, &line );
nico@210: 00968       if (err) {
etisserant@240: 00969         MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
etisserant@240: 00970         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 00971         return 0xFF;
nico@210: 00972       }
etisserant@240: 00973       initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
nico@215: 00974       /* Transfer data from dictionary to the line structure. */
etisserant@240: 00975       errorCode = objdictToSDOline(d, line);
nico@210: 00976      
nico@210: 00977       if (errorCode) {
etisserant@240: 00978         MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ", 
nico@210: 00979                 errorCode); 
etisserant@240: 00980         failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
nico@210: 00981         return 0xFF;
nico@210: 00982         }
nico@215: 00983       /* Preparing the response.*/
etisserant@240: 00984       getSDOlineRestBytes(d, line, &nbBytes);   /* Nb bytes to transfer ? */
etisserant@240: 00985       sdo.nodeId = nodeId; /* The server node Id; */
nico@210: 00986       if (nbBytes > 4) {
nico@215: 00987         /* normal transfert. (segmented). */
nico@215: 00988         /* code to send the initiate upload response. (cs = 2) */
etisserant@240: 00989         sdo.body.data[0] = (2 << 5) | 1;
etisserant@240: 00990         sdo.body.data[1] = index & 0xFF;        /* LSB */
etisserant@240: 00991         sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
etisserant@240: 00992         sdo.body.data[3] = subIndex;
etisserant@240: 00993         sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
nico@215: 00994         /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
nico@215: 00995         /* in the object dictionary, at every index and subindex. */
nico@210: 00996         for (i = 5 ; i < 8 ; i++)
etisserant@240: 00997           sdo.body.data[i] = 0;
etisserant@240: 00998         MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId); 
etisserant@240: 00999         sendSDO(d, whoami, sdo); 
nico@210: 01000       }
nico@210: 01001       else {
nico@215: 01002         /* Expedited upload. (cs = 2 ; e = 1) */
etisserant@240: 01003         sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;  
etisserant@240: 01004         sdo.body.data[1] = index & 0xFF;        /* LSB */
etisserant@240: 01005         sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
etisserant@240: 01006         sdo.body.data[3] = subIndex;
etisserant@240: 01007         err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);    
nico@210: 01008         if (err) {
etisserant@240: 01009           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01010           return 0xFF;
nico@210: 01011         }
nico@210: 01012         for (i = 4 + nbBytes ; i < 8 ; i++)
etisserant@240: 01013           sdo.body.data[i] = 0;
etisserant@240: 01014         MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ", 
nico@210: 01015                 nodeId); 
etisserant@240: 01016         sendSDO(d, whoami, sdo); 
nico@215: 01017         /* Release the line.*/
etisserant@240: 01018         resetSDOline(d, line);
nico@210: 01019       }
nico@215: 01020     } /* end if I am SERVER*/
nico@210: 01021     else {
nico@215: 01022       /* I am CLIENT */
nico@215: 01023       /* It is the response for the previous initiate upload request.*/
nico@215: 01024       /* We should find a line opened for this. */
etisserant@240: 01025       err = getSDOlineOnUse( d, nodeId, whoami, &line);
nico@210: 01026       if (!err)
etisserant@240: 01027         err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
nico@210: 01028       if (err) {
etisserant@240: 01029         MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId); 
etisserant@240: 01030         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 01031         return 0xFF;
nico@210: 01032       }
nico@215: 01033       /* Reset the wathdog */
etisserant@240: 01034       RestartSDO_TIMER(line)
etisserant@240: 01035       index = d->transfers[line].index;
etisserant@240: 01036       subIndex = d->transfers[line].subIndex;
nico@210: 01037       
etisserant@240: 01038       if (getSDOe(m->data[0])) { /* If SDO expedited */
nico@215: 01039         /* nb of data to be uploaded */
etisserant@240: 01040           nbBytes = 4 - getSDOn2(m->data[0]);
nico@215: 01041         /* Storing the data in the line structure. */
etisserant@240: 01042         err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
nico@210: 01043         if (err) {
etisserant@240: 01044           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01045           return 0xFF;
nico@210: 01046         }
nico@215: 01047         /* SDO expedited -> transfert finished. data are available via  getReadResultNetworkDict(). */
etisserant@240: 01048         MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
etisserant@240: 01049         StopSDO_TIMER(line)
etisserant@240: 01050         d->transfers[line].count = nbBytes;
etisserant@240: 01051         d->transfers[line].state = SDO_FINISHED;
etisserant@240: 01052         if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
nico@210: 01053         return 0;
nico@210: 01054       }
nico@215: 01055       else { /* So, if it is not an expedited transfert */
nico@215: 01056         /* Storing the nb of data to receive. */
etisserant@240: 01057         if (getSDOs(m->data[0])) {
etisserant@240: 01058           nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
etisserant@240: 01059           err = setSDOlineRestBytes(d, line, nbBytes);
nico@210: 01060           if (err) {
etisserant@240: 01061             failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01062             return 0xFF;
nico@210: 01063           }     
nico@210: 01064         }
nico@215: 01065         /* Requesting next segment. (cs = 3) */
etisserant@240: 01066         sdo.nodeId = nodeId;
etisserant@240: 01067         sdo.body.data[0] = 3 << 5;
nico@210: 01068         for (i = 1 ; i < 8 ; i++)
etisserant@240: 01069           sdo.body.data[i] = 0;
etisserant@240: 01070         MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId); 
etisserant@240: 01071         sendSDO(d, whoami, sdo);  
nico@210: 01072       }
nico@215: 01073     } /* End if CLIENT */
nico@210: 01074     break;
nico@210: 01075 
nico@210: 01076   case 3:
nico@215: 01077     /* I am SERVER */
etisserant@240: 01078     if (whoami == SDO_SERVER) {
nico@215: 01079       /* Receiving a upload segment. */
nico@215: 01080       /* A SDO transfert should have been yet initiated. */
etisserant@240: 01081       err = getSDOlineOnUse( d, nodeId, whoami, &line ); 
nico@210: 01082       if (!err)
etisserant@240: 01083         err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
nico@210: 01084       if (err) {
etisserant@240: 01085         MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ", 
nico@210: 01086                 nodeId); 
etisserant@240: 01087         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 01088         return 0xFF;
nico@210: 01089       }
nico@215: 01090       /* Reset the wathdog */
etisserant@240: 01091       RestartSDO_TIMER(line)
etisserant@240: 01092       MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId); 
etisserant@240: 01093       index = d->transfers[line].index;
etisserant@240: 01094       subIndex = d->transfers[line].subIndex;
nico@215: 01095       /* Toggle test.*/
etisserant@240: 01096       if (d->transfers[line].toggle != getSDOt(m->data[0])) {
etisserant@240: 01097         MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0])); 
etisserant@240: 01098         failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
nico@210: 01099         return 0xFF;
nico@210: 01100       }
nico@215: 01101       /* Uploading next segment. We need to know if it will be the last one. */
etisserant@240: 01102       getSDOlineRestBytes(d, line, &nbBytes);             
nico@210: 01103       if (nbBytes > 7) {
nico@215: 01104         /* The segment to transfer is not the last one.*/
nico@215: 01105         /* code to send the next segment. (cs = 0; c = 0) */
etisserant@240: 01106         sdo.nodeId = nodeId; /* The server node Id; */
etisserant@240: 01107         sdo.body.data[0] = (d->transfers[line].toggle << 4);
etisserant@240: 01108         err = lineToSDO(d, line, 7, sdo.body.data + 1);  
nico@210: 01109         if (err) {
etisserant@240: 01110           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01111           return 0xFF;
nico@210: 01112         }
nico@215: 01113         /* Inverting the toggle for the next tranfert. */
etisserant@240: 01114         d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
etisserant@240: 01115         MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId); 
etisserant@240: 01116         sendSDO(d, whoami, sdo); 
nico@210: 01117       } 
nico@210: 01118       else {
nico@215: 01119         /* Last segment. */
nico@215: 01120         /* code to send the last segment. (cs = 0; c = 1) */        
etisserant@240: 01121         sdo.nodeId = nodeId; 
etisserant@240: 01122         sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
etisserant@240: 01123         err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);    
nico@210: 01124         if (err) {
etisserant@240: 01125           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01126           return 0xFF;
nico@210: 01127         }
nico@210: 01128         for (i = nbBytes + 1 ; i < 8 ; i++)
etisserant@240: 01129           sdo.body.data[i] = 0;
etisserant@240: 01130         MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);      
etisserant@240: 01131         sendSDO(d, whoami, sdo);
nico@215: 01132         /* Release the line */
etisserant@240: 01133         resetSDOline(d, line);
nico@210: 01134       }
nico@210: 01135     } /* end if SERVER*/
nico@210: 01136     else {
nico@215: 01137       /* I am CLIENT */
nico@215: 01138       /* It is the response for the previous initiate download request. */
nico@215: 01139       /* We should find a line opened for this. */
etisserant@240: 01140       err = getSDOlineOnUse( d, nodeId, whoami, &line);
nico@210: 01141       if (!err)
etisserant@240: 01142         err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
nico@210: 01143       if (err) {
etisserant@240: 01144         MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId); 
etisserant@240: 01145         failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
nico@210: 01146         return 0xFF;
nico@210: 01147       }
nico@215: 01148       /* Reset the watchdog */
etisserant@240: 01149       RestartSDO_TIMER(line)
etisserant@240: 01150       index = d->transfers[line].index;
etisserant@240: 01151       subIndex = d->transfers[line].subIndex;
nico@210: 01152       /* End transmission or requesting  next segment. */
etisserant@240: 01153       getSDOlineRestBytes(d, line, &nbBytes);
nico@210: 01154       if (nbBytes == 0) {
etisserant@240: 01155         MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId); 
etisserant@240: 01156         StopSDO_TIMER(line)
etisserant@240: 01157         d->transfers[line].state = SDO_FINISHED;
etisserant@240: 01158         if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
nico@210: 01159         return 0x00;
nico@210: 01160       }   
nico@210: 01161       if (nbBytes > 7) {
nico@215: 01162         /* more than one request to send */
nico@215: 01163         /* code to send the next segment. (cs = 0; c = 0)       */    
etisserant@240: 01164         sdo.nodeId = nodeId; 
etisserant@240: 01165         sdo.body.data[0] = (d->transfers[line].toggle << 4);
etisserant@240: 01166         err = lineToSDO(d, line, 7, sdo.body.data + 1);  
nico@210: 01167         if (err) {
etisserant@240: 01168           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01169           return 0xFF;
nico@210: 01170         }
nico@210: 01171       } 
nico@210: 01172       else {
nico@215: 01173         /* Last segment.*/
nico@215: 01174         /* code to send the last segment. (cs = 0; c = 1)       */   
etisserant@240: 01175         sdo.nodeId = nodeId; /* The server node Id; */
etisserant@240: 01176         sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
etisserant@240: 01177         err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);    
nico@210: 01178         if (err) {
etisserant@240: 01179           failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
nico@210: 01180           return 0xFF;
nico@210: 01181         }
nico@210: 01182         for (i = nbBytes + 1 ; i < 8 ; i++)
etisserant@240: 01183           sdo.body.data[i] = 0;
nico@210: 01184       }
etisserant@240: 01185       MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId); 
etisserant@240: 01186       sendSDO(d, whoami, sdo); 
nico@207: 01187 
nico@210: 01188     } /* end if I am a CLIENT           */        
nico@210: 01189     break;  
nico@210: 01190 
nico@210: 01191    case 4:
nico@210: 01192      abortCode = (*m).data[3] |
etisserant@240: 01193       ((UNS32)m->data[5] << 8) |
etisserant@240: 01194       ((UNS32)m->data[6] << 16) |
etisserant@240: 01195       ((UNS32)m->data[7] << 24);
nico@215: 01196     /* Received SDO abort. */
nico@215: 01197     /* Looking for the line concerned. */
etisserant@240: 01198     if (whoami == SDO_SERVER) {
etisserant@240: 01199       err = getSDOlineOnUse( d, nodeId, whoami, &line );
nico@210: 01200       if (!err) {
etisserant@240: 01201         resetSDOline( d, line );
etisserant@240: 01202         MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
nico@210: 01203       }
nico@210: 01204       else
etisserant@240: 01205         MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
nico@215: 01206       /* Tips : The end user has no way to know that the server node has received an abort SDO. */
nico@215: 01207       /* Its is ok, I think.*/
nico@210: 01208     }
nico@215: 01209     else { /* If I am CLIENT */
etisserant@240: 01210       err = getSDOlineOnUse( d, nodeId, whoami, &line );
nico@210: 01211       if (!err) {
nico@215: 01212         /* The line *must* be released by the core program. */
etisserant@240: 01213         StopSDO_TIMER(line)
etisserant@240: 01214         d->transfers[line].state = SDO_ABORTED_RCV;
etisserant@240: 01215         d->transfers[line].abortCode = abortCode;
etisserant@240: 01216         MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
etisserant@240: 01217         if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
nico@210: 01218       }
nico@210: 01219       else
etisserant@240: 01220         MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
nico@210: 01221     } 
nico@210: 01222     break;
nico@210: 01223   default:
nico@215: 01224     /* Error : Unknown cs */
etisserant@240: 01225     MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
nico@210: 01226     return 0xFF;
nico@210: 01227 
nico@210: 01228   } /* End switch */
nico@210: 01229   return 0;     
nico@210: 01230 }
nico@210: 01231 
etisserant@240: 01247 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, 
etisserant@240: 01248                        UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
nico@210: 01249 {
etisserant@240: 01250   UNS8 err;
etisserant@240: 01251   UNS8 SDOfound = 0;
etisserant@240: 01252   UNS8 line;
nico@215: 01253   s_SDO sdo;    /* SDO to transmit */
etisserant@240: 01254   UNS8 i, j;
etisserant@240: 01255   UNS16     lastIndex;
etisserant@240: 01256   UNS16     offset;
etisserant@240: 01257   UNS32      *pNodeIdServer;
etisserant@240: 01258   UNS32      nodeIdServer;
nico@210: 01259 
etisserant@240: 01260   MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
etisserant@240: 01261   MSG_WAR(0x3AC1, "                                   At index : ", index);
etisserant@240: 01262   MSG_WAR(0x3AC2, "                                   subIndex : ", subIndex);
etisserant@240: 01263   MSG_WAR(0x3AC3, "                                   nb bytes : ", count);
nico@210: 01264 
nico@215: 01265   /* Verify that there is no SDO communication yet. */
etisserant@240: 01266   err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
nico@210: 01267   if (!err) {
etisserant@240: 01268     MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId); 
nico@210: 01269     return 0xFF;
nico@210: 01270   }
nico@215: 01271   /* Taking the line ... */
etisserant@240: 01272   err = getSDOfreeLine( d, SDO_CLIENT, &line );
nico@210: 01273   if (err) {
etisserant@240: 01274     MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId); 
nico@210: 01275     return (0xFF);
nico@210: 01276   }
nico@215: 01277   /* Check which SDO to use to communicate with the node */
etisserant@240: 01278   offset = d->firstIndex->SDO_CLT;
etisserant@240: 01279   lastIndex = d->lastIndex->SDO_CLT;
nico@210: 01280   if (offset == 0) {
etisserant@240: 01281     MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0); 
nico@210: 01282     return 0xFF;
nico@210: 01283   }
nico@210: 01284   i = 0;
nico@210: 01285    while (offset <= lastIndex) {
etisserant@240: 01286      if (d->objdict[offset].bSubCount <= 3) {
etisserant@240: 01287          MSG_ERR(0x1AC8, "Subindex 3  not found at index ", 0x1280 + i);
nico@210: 01288          return 0xFF;
nico@210: 01289      }
nico@215: 01290      /* looking for the nodeId server */
etisserant@240: 01291      pNodeIdServer = (UNS32*) d->objdict[offset].pSubindex[3].pObject;
nico@210: 01292      nodeIdServer = *pNodeIdServer;
etisserant@240: 01293      MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
etisserant@240: 01294      MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
nico@210: 01295    
etisserant@240: 01296     if(nodeIdServer == (UNS32)nodeId) {
nico@210: 01297       SDOfound = 1;
nico@210: 01298       break;
nico@210: 01299     }
nico@210: 01300     offset++;
nico@210: 01301     i++;
nico@210: 01302   } /* end while */
nico@210: 01303   if (!SDOfound) {
etisserant@240: 01304     MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
nico@210: 01305     return 0xFF;
nico@210: 01306   }
etisserant@240: 01307   MSG_WAR(0x3AD0,"        SDO client defined at index  : ", 0x1280 + i);
etisserant@240: 01308   initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
etisserant@240: 01309   d->transfers[line].count = count;
etisserant@240: 01310   d->transfers[line].dataType = dataType;
nico@210: 01311   
nico@215: 01312   /* Copy data to transfers structure. */
nico@210: 01313   for (j = 0 ; j < count ; j++) {
etisserant@240: 01314 # ifdef CANOPEN_BIG_ENDIAN
nico@210: 01315     if (dataType == 0 && endianize)
etisserant@240: 01316       d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
nico@210: 01317     else /* String of bytes. */
etisserant@240: 01318       d->transfers[line].data[j] = ((char *)data)[j];
nico@210: 01319 #  else 
etisserant@240: 01320     d->transfers[line].data[j] = ((char *)data)[j];
nico@210: 01321 #  endif
nico@210: 01322   }
nico@215: 01323   /* Send the SDO to the server. Initiate download, cs=1. */
etisserant@240: 01324   sdo.nodeId = nodeId;
nico@215: 01325   if (count <= 4) { /* Expedited transfert */
etisserant@240: 01326     sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
nico@210: 01327     for (i = 4 ; i < 8 ; i++)
etisserant@240: 01328       sdo.body.data[i] = d->transfers[line].data[i - 4];
etisserant@240: 01329     d->transfers[line].offset = count;
nico@210: 01330   }     
nico@210: 01331   else { 
etisserant@240: 01332     sdo.body.data[0] = (1 << 5) | 1;
etisserant@240: 01333     sdo.body.data[4] = count; /* nb of byte to transmit. Max = 255. (canfestival2 limitation). */
nico@210: 01334     for (i = 5 ; i < 8 ; i++)
etisserant@240: 01335       sdo.body.data[i] = 0;
nico@210: 01336   }
etisserant@240: 01337   sdo.body.data[1] = index & 0xFF;        /* LSB */
etisserant@240: 01338   sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
etisserant@240: 01339   sdo.body.data[3] = subIndex;
nico@210: 01340 
etisserant@240: 01341   d->transfers[line].Callback = Callback;
nico@210: 01342     
etisserant@240: 01343   err = sendSDO(d, SDO_CLIENT, sdo);
nico@210: 01344   if (err) {
etisserant@240: 01345     MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
nico@215: 01346     /* release the line */
etisserant@240: 01347     resetSDOline(d, line);
nico@210: 01348     return 0xFF;
nico@210: 01349   }
nico@210: 01350 
nico@210: 01351   
nico@210: 01352   return 0;
nico@210: 01353 }
nico@210: 01354 
etisserant@240: 01368 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, 
etisserant@240: 01369                        UNS8 subIndex, UNS8 count, UNS8 dataType, void *data)
nico@210: 01370 {
etisserant@240: 01371         return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
nico@210: 01372 }
nico@210: 01373 
etisserant@240: 01388 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index, 
etisserant@240: 01389                        UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback)
nico@210: 01390 {
etisserant@240: 01391         return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);      
nico@210: 01392 }
nico@210: 01393 
etisserant@240: 01406 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
nico@210: 01407 {
etisserant@240: 01408   UNS8 err;
etisserant@240: 01409   UNS8 SDOfound = 0;
etisserant@240: 01410   UNS8 i;
etisserant@240: 01411   UNS8 line;
nico@215: 01412   s_SDO sdo;    /* SDO to transmit */
etisserant@240: 01413   UNS32      *pNodeIdServer;
etisserant@240: 01414   UNS32      nodeIdServer;
etisserant@240: 01415   UNS16     offset;
etisserant@240: 01416   UNS16     lastIndex;
etisserant@240: 01417   MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
etisserant@240: 01418   MSG_WAR(0x3AD6, "                                  At index : ", index);
etisserant@240: 01419   MSG_WAR(0x3AD7, "                                  subIndex : ", subIndex);
nico@210: 01420 
nico@210: 01421 
nico@215: 01422   /* Verify that there is no SDO communication yet. */
etisserant@240: 01423   err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
nico@210: 01424   if (!err) {
etisserant@240: 01425     MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId); 
nico@210: 01426     return 0xFF;
nico@210: 01427   }
nico@215: 01428   /* Taking the line ... */
etisserant@240: 01429   err = getSDOfreeLine( d, SDO_CLIENT, &line );
nico@210: 01430   if (err) {
etisserant@240: 01431     MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId); 
nico@210: 01432     return (0xFF);
nico@210: 01433   }
nico@210: 01434   else
etisserant@240: 01435     MSG_WAR(0x3AE0, "Transmission on line : ", line);
nico@210: 01436 
nico@215: 01437   /* Check which SDO to use to communicate with the node */
etisserant@240: 01438   offset = d->firstIndex->SDO_CLT;
etisserant@240: 01439   lastIndex = d->lastIndex->SDO_CLT;
nico@210: 01440   if (offset == 0) {
etisserant@240: 01441     MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0); 
nico@210: 01442     return 0xFF;
nico@210: 01443   }
nico@210: 01444   i = 0;
nico@210: 01445   while (offset <= lastIndex) {
etisserant@240: 01446      if (d->objdict[offset].bSubCount <= 3) {
etisserant@240: 01447          MSG_ERR(0x1AE2, "Subindex 3  not found at index ", 0x1280 + i);
nico@210: 01448          return 0xFF;
nico@210: 01449      }
nico@215: 01450      /* looking for the nodeId server */
etisserant@240: 01451      pNodeIdServer = (UNS32*) d->objdict[offset].pSubindex[3].pObject;
nico@210: 01452      nodeIdServer = *pNodeIdServer;
nico@210: 01453    
etisserant@240: 01454     if(nodeIdServer == (UNS32)nodeId) {
nico@210: 01455       SDOfound = 1;
nico@210: 01456       break;
nico@210: 01457     }
nico@210: 01458     offset++;
nico@210: 01459     i++;
nico@210: 01460   } /* end while */
nico@210: 01461   if (!SDOfound) {
etisserant@240: 01462     MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
nico@210: 01463     return 0xFF;
nico@210: 01464   }
etisserant@240: 01465   MSG_WAR(0x3AE4,"        SDO client defined at index  : ", 0x1280 + i);
etisserant@240: 01466   initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
etisserant@240: 01467   getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
etisserant@240: 01468   sdo.nodeId = nodeId;
nico@215: 01469   /* Send the SDO to the server. Initiate upload, cs=2. */
etisserant@240: 01470   d->transfers[line].dataType = dataType;                               
etisserant@240: 01471   sdo.body.data[0] = (2 << 5);  
etisserant@240: 01472   sdo.body.data[1] = index & 0xFF;        /* LSB */
etisserant@240: 01473   sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
etisserant@240: 01474   sdo.body.data[3] = subIndex;
nico@210: 01475   for (i = 4 ; i < 8 ; i++)
etisserant@240: 01476     sdo.body.data[i] = 0;
etisserant@240: 01477   d->transfers[line].Callback = Callback;
etisserant@240: 01478   err = sendSDO(d, SDO_CLIENT, sdo);
nico@210: 01479   if (err) {
etisserant@240: 01480     MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
nico@210: 01481     /* release the line */
etisserant@240: 01482     resetSDOline(d, line);
nico@210: 01483     return 0xFF;
nico@210: 01484   }             
nico@210: 01485   return 0;
nico@210: 01486 }
nico@210: 01487 
etisserant@240: 01499 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
nico@210: 01500 {
etisserant@240: 01501         return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
nico@210: 01502 }
nico@210: 01503 
etisserant@240: 01516 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
nico@210: 01517 {
etisserant@240: 01518         return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
nico@210: 01519 }
nico@210: 01520 
etisserant@240: 01532 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS8 *size, 
etisserant@240: 01533                                UNS32 * abortCode)
nico@210: 01534 {
etisserant@240: 01535   UNS8 i;
etisserant@240: 01536   UNS8 err;
etisserant@240: 01537   UNS8 line;
nico@210: 01538   * size = 0;
nico@210: 01539 
nico@215: 01540   /* Looking for the line tranfert. */
etisserant@240: 01541   err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
nico@210: 01542   if (err) {
etisserant@240: 01543     MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId); 
etisserant@240: 01544     return SDO_ABORTED_INTERNAL;
nico@210: 01545   }
etisserant@240: 01546   if (d->transfers[line].state != SDO_FINISHED)
etisserant@240: 01547     return d->transfers[line].state;
nico@210: 01548 
nico@215: 01549   /* Transfert is finished. Put the value in the data. */
etisserant@240: 01550   * size = (UNS8)d->transfers[line].count;
nico@210: 01551   for  ( i = 0 ; i < *size ; i++) {
etisserant@240: 01552 # ifdef CANOPEN_BIG_ENDIAN
etisserant@240: 01553     if (d->transfers[line].dataType != visible_string)
etisserant@240: 01554       ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
nico@215: 01555     else /* String of bytes. */
etisserant@240: 01556       ( (char *) data)[i] = d->transfers[line].data[i];
nico@210: 01557 # else 
etisserant@240: 01558     ( (char *) data)[i] = d->transfers[line].data[i];
nico@210: 01559 # endif
nico@210: 01560   } 
etisserant@240: 01561   return SDO_FINISHED;
nico@210: 01562 }
nico@210: 01563 
etisserant@240: 01573 UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
nico@210: 01574 {
etisserant@240: 01575   UNS8 line = 0;
etisserant@240: 01576   UNS8 err;
nico@210: 01577 
nico@210: 01578   * abortCode = 0;
nico@215: 01579   /* Looking for the line tranfert. */
etisserant@240: 01580   err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
nico@210: 01581   if (err) {
etisserant@240: 01582     MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId); 
etisserant@240: 01583     return SDO_ABORTED_INTERNAL;
nico@210: 01584   }
etisserant@240: 01585   * abortCode = d->transfers[line].abortCode;
etisserant@240: 01586   return d->transfers[line].state;
nico@210: 01587 }
etisserant@240: 

Generated on Mon Jul 2 19:10:16 2007 for CanFestival by  nico@207: nico@207: doxygen 1.5.1
nico@207: nico@207: