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