2 This file is part of CanFestival, a library implementing CanOpen Stack.
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
6 See COPYING file for copyrights details.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ** @author Edouard TISSERANT and Francis DUPIN
25 ** @date Tue Jun 5 09:32:32 2007
32 /* #define DEBUG_WAR_CONSOLE_ON */
33 /* #define DEBUG_ERR_CONSOLE_ON */
35 #include "canfestival.h"
38 /* Uncomment if your compiler does not support inline functions */
47 /*Internals prototypes*/
50 ** Called by writeNetworkDict
64 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
65 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
68 ** Called by readNetworkDict
79 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
80 UNS8 dataType, SDOCallback_t Callback);
83 /***************************************************************************/
84 /* SDO (un)packing macros */
86 /** Returns the command specifier (cs, ccs, scs) from the first byte of the SDO
88 #define getSDOcs(byte) (byte >> 5)
90 /** Returns the number of bytes without data from the first byte of the SDO. Coded in 2 bits
92 #define getSDOn2(byte) ((byte >> 2) & 3)
94 /** Returns the number of bytes without data from the first byte of the SDO. Coded in 3 bits
96 #define getSDOn3(byte) ((byte >> 1) & 7)
98 /** Returns the transfer type from the first byte of the SDO
100 #define getSDOe(byte) ((byte >> 1) & 1)
102 /** Returns the size indicator from the first byte of the SDO
104 #define getSDOs(byte) (byte & 1)
106 /** Returns the indicator of end transmission from the first byte of the SDO
108 #define getSDOc(byte) (byte & 1)
110 /** Returns the toggle from the first byte of the SDO
112 #define getSDOt(byte) ((byte >> 4) & 1)
114 /** Returns the index from the bytes 1 and 2 of the SDO
116 #define getSDOindex(byte1, byte2) ((byte2 << 8) | (byte1))
118 /** Returns the subIndex from the byte 3 of the SDO
120 #define getSDOsubIndex(byte3) (byte3)
128 void SDOTimeoutAlarm(CO_Data* d, UNS32 id)
130 MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
131 MSG_WAR(0x2A02, "server node : ", d->transfers[id].nodeId);
132 MSG_WAR(0x2A02, " index : ", d->transfers[id].index);
133 MSG_WAR(0x2A02, " subIndex : ", d->transfers[id].subIndex);
134 /* Reset timer handler */
135 d->transfers[id].timer = TIMER_NONE;
136 /*Set aborted state*/
137 d->transfers[id].state = SDO_ABORTED_INTERNAL;
138 /* Sending a SDO abort */
139 sendSDOabort(d, d->transfers[id].whoami, d->transfers[id].nodeId,
140 d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);
141 d->transfers[id].abortCode = SDOABT_TIMED_OUT;
142 /* Call the user function to inform of the problem.*/
143 if(d->transfers[id].Callback)
144 /*If ther is a callback, it is responsible to close SDO transfer (client)*/
145 (*d->transfers[id].Callback)(d,d->transfers[id].nodeId);
146 else if(d->transfers[id].whoami == SDO_SERVER)
147 /*Else, if server, reset the line*/
148 resetSDOline(d, (UNS8)id);
151 #define StopSDO_TIMER(id) \
152 MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\
153 d->transfers[id].timer = DelAlarm(d->transfers[id].timer);
155 #define StartSDO_TIMER(id) \
156 MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\
157 d->transfers[id].timer = SetAlarm(d,id,&SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);
159 #define RestartSDO_TIMER(id) \
160 MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
161 if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
164 ** Reset all sdo buffers
168 void resetSDO (CO_Data* d)
172 /* transfer structure initialization */
173 for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++)
185 UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line)
189 MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);
190 size = d->transfers[line].count;
191 errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
192 (void *) d->transfers[line].data, &size, 1);
193 if (errorCode != OD_SUCCESSFUL)
195 MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
208 UNS32 objdictToSDOline (CO_Data* d, UNS8 line)
214 MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
215 MSG_WAR(0x3A06, " subIndex : ", d->transfers[line].subIndex);
217 errorCode = getODentry(d, d->transfers[line].index,
218 d->transfers[line].subIndex,
219 (void *)d->transfers[line].data,
220 &size, &dataType, 1);
222 if (errorCode != OD_SUCCESSFUL)
225 d->transfers[line].count = size;
226 d->transfers[line].offset = 0;
241 UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data) {
245 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
246 MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
249 if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
250 MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
253 offset = d->transfers[line].offset;
254 for (i = 0 ; i < nbBytes ; i++)
255 * (data + i) = d->transfers[line].data[offset + i];
256 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
270 UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data)
275 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
276 MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
279 offset = d->transfers[line].offset;
280 for (i = 0 ; i < nbBytes ; i++)
281 d->transfers[line].data[offset + i] = * (data + i);
282 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
283 d->transfers[line].count = d->transfers[line].offset;
300 UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
301 UNS8 subIndex, UNS32 abortCode)
305 err = getSDOlineOnUse( d, nodeId, whoami, &line );
306 if (!err) /* If a line on use have been found.*/
307 MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
308 if ((! err) && (whoami == SDO_SERVER)) {
309 resetSDOline( d, line );
310 MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
312 if ((! err) && (whoami == SDO_CLIENT)) {
314 d->transfers[line].state = SDO_ABORTED_INTERNAL;
316 MSG_WAR(0x3A22, "Sending SDO abort ", 0);
317 err = sendSDOabort(d, whoami, nodeId, index, subIndex, abortCode);
319 MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
331 void resetSDOline ( CO_Data* d, UNS8 line )
334 MSG_WAR(0x3A25, "reset SDO line nb : ", line);
335 initSDOline(d, line, 0, 0, 0, SDO_RESET);
336 for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
337 d->transfers[line].data[i] = 0;
338 d->transfers[line].whoami = 0;
339 d->transfers[line].abortCode = 0;
354 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
356 MSG_WAR(0x3A25, "init SDO line nb : ", line);
357 if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
362 d->transfers[line].nodeId = nodeId;
363 d->transfers[line].index = index;
364 d->transfers[line].subIndex = subIndex;
365 d->transfers[line].state = state;
366 d->transfers[line].toggle = 0;
367 d->transfers[line].count = 0;
368 d->transfers[line].offset = 0;
369 d->transfers[line].dataType = 0;
370 d->transfers[line].Callback = NULL;
383 UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
388 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
389 if ( d->transfers[i].state == SDO_RESET ) {
391 d->transfers[i].whoami = whoami;
395 MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
409 UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
414 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
415 if ( (d->transfers[i].state != SDO_RESET) &&
416 (d->transfers[i].nodeId == nodeId) &&
417 (d->transfers[i].whoami == whoami) ) {
434 UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
438 err = getSDOlineOnUse(d, nodeId, whoami, &line);
440 MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
443 resetSDOline(d, line);
456 UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 * nbBytes)
458 if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
461 * nbBytes = d->transfers[line].count - d->transfers[line].offset;
475 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 nbBytes)
477 if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
478 MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
481 d->transfers[line].count = nbBytes;
494 UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
501 UNS32 * pwCobId = NULL;
502 UNS8 * pwNodeId = NULL;
504 MSG_WAR(0x3A38, "sendSDO",0);
505 if( !((d->nodeState == Operational) || (d->nodeState == Pre_operational ))) {
506 MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
510 /*get the server->client cobid*/
511 if ( whoami == SDO_SERVER ) {/*case server. only one SDO server*/
512 offset = d->firstIndex->SDO_SVR;
514 MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
517 pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
518 MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
520 else { /*case client*/
521 /* Get the client->server cobid.*/
523 offset = d->firstIndex->SDO_CLT;
524 lastIndex = d->lastIndex->SDO_CLT;
526 MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
529 /* find index for communication server node */
530 while (offset <= lastIndex){
531 MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
532 if (d->objdict[offset].bSubCount <= 3) {
533 MSG_ERR(0x1A28, "Subindex 3 not found at index ", 0x1280 + sdoNum);
536 pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
537 MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
538 if(*pwNodeId == sdo.nodeId) {
546 MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
549 /* read the client->server cobid */
550 pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
552 /* message copy for sending */
553 m.cob_id = UNS16_LE(*pwCobId);
554 m.rtr = NOT_A_REQUEST;
555 /* the length of SDO must be 8 */
557 for (i = 0 ; i < 8 ; i++) {
558 m.data[i] = sdo.body.data[i];
560 return canSend(d->canHandle,&m);
574 UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeID, UNS16 index, UNS8 subIndex, UNS32 abortCode)
582 MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
583 if(whoami == SDO_SERVER)
585 sdo.nodeId = *d->bDeviceNodeId;
591 sdo.body.data[0] = 0x80;
593 sdo.body.data[1] = index & 0xFF; /* LSB */
594 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
596 sdo.body.data[3] = subIndex;
598 sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
599 sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
600 sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
601 sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
602 ret = sendSDO(d, whoami, sdo);
615 UNS8 proceedSDO (CO_Data* d, Message *m)
619 UNS32 nbBytes; /* received or to be transmited. */
620 UNS8 nodeId = 0; /* The node from which the SDO is received */
621 UNS8 *pNodeId = NULL;
622 UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
623 UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
624 s_SDO sdo; /* SDO to transmit */
629 UNS32 *pCobId = NULL;
633 MSG_WAR(0x3A60, "proceedSDO ", 0);
634 whoami = SDO_UNKNOWN;
635 /* Looking for the cobId in the object dictionary. */
636 /* Am-I a server ? */
637 offset = d->firstIndex->SDO_SVR;
638 lastIndex = d->lastIndex->SDO_SVR;
640 if(offset) while (offset <= lastIndex) {
641 if (d->objdict[offset].bSubCount <= 1) {
642 MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);
645 pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
646 if ( *pCobId == UNS16_LE(m->cob_id) ) {
648 MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
649 /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
650 /* 0x1200 where the cobid received is defined. */
657 if (whoami == SDO_UNKNOWN) {
659 offset = d->firstIndex->SDO_CLT;
660 lastIndex = d->lastIndex->SDO_CLT;
662 if(offset) while (offset <= lastIndex) {
663 if (d->objdict[offset].bSubCount <= 3) {
664 MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
667 /* a) Looking for the cobid received. */
668 pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
669 if (*pCobId == UNS16_LE(m->cob_id) ) {
670 /* b) cobid found, so reading the node id of the server. */
671 pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
674 MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
675 MSG_WAR(0x3A65, " Server nodeId : ", nodeId);
682 if (whoami == SDO_UNKNOWN) {
683 return 0xFF;/* This SDO was not for us ! */
686 /* Test if the size of the SDO is ok */
687 if ( (*m).len != 8) {
688 MSG_ERR(0x1A67, "Error size SDO. CobId : ", UNS16_LE(m->cob_id));
689 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
693 if (whoami == SDO_CLIENT) {
694 MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
697 MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", UNS16_LE(m->cob_id));
700 /* Testing the command specifier */
701 /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
702 /* cs = other : Not allowed -> abort. */
703 switch (getSDOcs(m->data[0])) {
707 if (whoami == SDO_SERVER) {
708 /* Receiving a download segment data. */
709 /* A SDO transfert should have been yet initiated. */
710 err = getSDOlineOnUse( d, nodeId, whoami, &line );
712 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
714 MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
716 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
719 /* Reset the wathdog */
720 RestartSDO_TIMER(line)
721 MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
722 index = d->transfers[line].index;
723 subIndex = d->transfers[line].subIndex;
725 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
726 MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
727 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
730 /* Nb of data to be downloaded */
731 nbBytes = 7 - getSDOn3(m->data[0]);
732 /* Store the data in the transfert structure. */
733 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
735 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
738 /* Sending the SDO response, CS = 1 */
739 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
740 sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
741 for (i = 1 ; i < 8 ; i++)
742 sdo.body.data[i] = 0;
743 MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
744 sendSDO(d, whoami, sdo);
745 /* Inverting the toggle for the next segment. */
746 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
747 /* If it was the last segment, */
748 if (getSDOc(m->data[0])) {
749 /* Transfering line data to object dictionary. */
750 /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
751 errorCode = SDOlineToObjdict(d, line);
753 MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
754 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
757 /* Release of the line */
758 resetSDOline(d, line);
759 MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
761 } /* end if SERVER */
762 else { /* if CLIENT */
764 /* It is a request for a previous upload segment. We should find a line opened for this.*/
765 err = getSDOlineOnUse( d, nodeId, whoami, &line);
767 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
769 MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
770 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
773 /* Reset the wathdog */
774 RestartSDO_TIMER(line)
775 index = d->transfers[line].index;
776 subIndex = d->transfers[line].subIndex;
777 /* test of the toggle; */
778 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
779 MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
780 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
783 /* nb of data to be uploaded */
784 nbBytes = 7 - getSDOn3(m->data[0]);
785 /* Storing the data in the line structure. */
786 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
788 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
791 /* Inverting the toggle for the next segment. */
792 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
793 /* If it was the last segment,*/
794 if ( getSDOc(m->data[0])) {
795 /* Put in state finished */
796 /* The code is safe for the case e=s=0 in initiate frame. */
798 d->transfers[line].state = SDO_FINISHED;
799 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
801 MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
803 else { /* more segments to receive */
804 /* Sending the request for the next segment. */
806 sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
807 for (i = 1 ; i < 8 ; i++)
808 sdo.body.data[i] = 0;
809 sendSDO(d, whoami, sdo);
810 MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
812 } /* End if CLIENT */
817 /* Receive of an initiate download */
818 if (whoami == SDO_SERVER) {
819 index = getSDOindex(m->data[1],m->data[2]);
820 subIndex = getSDOsubIndex(m->data[3]);
821 MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
823 MSG_WAR(0x3A80, "Writing at index : ", index);
824 MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
826 /* Search if a SDO transfert have been yet initiated */
827 err = getSDOlineOnUse( d, nodeId, whoami, &line );
829 MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
830 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
833 /* No line on use. Great ! */
834 /* Try to open a new line. */
835 err = getSDOfreeLine( d, whoami, &line );
837 MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
838 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
841 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
843 if (getSDOe(m->data[0])) { /* If SDO expedited */
844 /* nb of data to be downloaded */
845 nbBytes = 4 - getSDOn2(m->data[0]);
846 /* Storing the data in the line structure. */
847 d->transfers[line].count = nbBytes;
848 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
851 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
855 /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
856 /*The line will be reseted when it is downloading in the dictionary. */
857 MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
858 /* Transfering line data to object dictionary. */
859 errorCode = SDOlineToObjdict(d, line);
861 MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
862 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
865 /* Release of the line. */
866 resetSDOline(d, line);
868 else {/* So, if it is not an expedited transfert */
869 if (getSDOs(m->data[0])) {
871 err = setSDOlineRestBytes(d, nodeId, nbBytes);
873 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
878 /*Sending a SDO, cs=3*/
879 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
880 sdo.body.data[0] = 3 << 5;
881 sdo.body.data[1] = index & 0xFF; /* LSB */
882 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
883 sdo.body.data[3] = subIndex;
884 for (i = 4 ; i < 8 ; i++)
885 sdo.body.data[i] = 0;
886 sendSDO(d, whoami, sdo);
887 } /* end if I am SERVER */
890 /* It is a response for a previous download segment. We should find a line opened for this. */
891 err = getSDOlineOnUse( d, nodeId, whoami, &line);
893 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
895 MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
896 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
899 /* Reset the wathdog */
900 RestartSDO_TIMER(line)
901 index = d->transfers[line].index;
902 subIndex = d->transfers[line].subIndex;
903 /* test of the toggle; */
904 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
905 MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
906 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
910 /* End transmission or downloading next segment. We need to know if it will be the last one. */
911 getSDOlineRestBytes(d, line, &nbBytes);
913 MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
915 d->transfers[line].state = SDO_FINISHED;
916 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
919 /* At least one transfer to send. */
921 /* several segments to download.*/
922 /* code to send the next segment. (cs = 0; c = 0) */
923 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
924 sdo.nodeId = nodeId; /* The server node Id; */
925 sdo.body.data[0] = (d->transfers[line].toggle << 4);
926 err = lineToSDO(d, line, 7, sdo.body.data + 1);
928 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
934 /* code to send the last segment. (cs = 0; c = 1)*/
935 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
936 sdo.nodeId = nodeId; /* The server node Id; */
937 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
938 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
940 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
943 for (i = nbBytes + 1 ; i < 8 ; i++)
944 sdo.body.data[i] = 0;
946 MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
947 sendSDO(d, whoami, sdo);
948 } /* end if I am a CLIENT */
953 /* Receive of an initiate upload.*/
954 if (whoami == SDO_SERVER) {
955 index = getSDOindex(m->data[1],m->data[2]);
956 subIndex = getSDOsubIndex(m->data[3]);
957 MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
959 MSG_WAR(0x3A90, "Reading at index : ", index);
960 MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
961 /* Search if a SDO transfert have been yet initiated*/
962 err = getSDOlineOnUse( d, nodeId, whoami, &line );
964 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
965 MSG_WAR(0x3A93, "nodeId = ", nodeId);
966 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
969 /* No line on use. Great !*/
970 /* Try to open a new line.*/
971 err = getSDOfreeLine( d, whoami, &line );
973 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
974 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
977 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
978 /* Transfer data from dictionary to the line structure. */
979 errorCode = objdictToSDOline(d, line);
982 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
984 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
987 /* Preparing the response.*/
988 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
989 sdo.nodeId = nodeId; /* The server node Id; */
991 /* normal transfert. (segmented). */
992 /* code to send the initiate upload response. (cs = 2) */
993 sdo.body.data[0] = (2 << 5) | 1;
994 sdo.body.data[1] = index & 0xFF; /* LSB */
995 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
996 sdo.body.data[3] = subIndex;
997 sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
998 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
999 /* in the object dictionary, at every index and subindex. */
1000 for (i = 5 ; i < 8 ; i++)
1001 sdo.body.data[i] = 0;
1002 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
1003 sendSDO(d, whoami, sdo);
1006 /* Expedited upload. (cs = 2 ; e = 1) */
1007 sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;
1008 sdo.body.data[1] = index & 0xFF; /* LSB */
1009 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1010 sdo.body.data[3] = subIndex;
1011 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
1013 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1016 for (i = 4 + nbBytes ; i < 8 ; i++)
1017 sdo.body.data[i] = 0;
1018 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1020 sendSDO(d, whoami, sdo);
1021 /* Release the line.*/
1022 resetSDOline(d, line);
1024 } /* end if I am SERVER*/
1027 /* It is the response for the previous initiate upload request.*/
1028 /* We should find a line opened for this. */
1029 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1031 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1033 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1034 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1037 /* Reset the wathdog */
1038 RestartSDO_TIMER(line)
1039 index = d->transfers[line].index;
1040 subIndex = d->transfers[line].subIndex;
1042 if (getSDOe(m->data[0])) { /* If SDO expedited */
1043 /* nb of data to be uploaded */
1044 nbBytes = 4 - getSDOn2(m->data[0]);
1045 /* Storing the data in the line structure. */
1046 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1048 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1051 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1052 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1054 d->transfers[line].count = nbBytes;
1055 d->transfers[line].state = SDO_FINISHED;
1056 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1059 else { /* So, if it is not an expedited transfert */
1060 /* Storing the nb of data to receive. */
1061 if (getSDOs(m->data[0])) {
1062 nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
1063 err = setSDOlineRestBytes(d, line, nbBytes);
1065 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1069 /* Requesting next segment. (cs = 3) */
1070 sdo.nodeId = nodeId;
1071 sdo.body.data[0] = 3 << 5;
1072 for (i = 1 ; i < 8 ; i++)
1073 sdo.body.data[i] = 0;
1074 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1075 sendSDO(d, whoami, sdo);
1077 } /* End if CLIENT */
1082 if (whoami == SDO_SERVER) {
1083 /* Receiving a upload segment. */
1084 /* A SDO transfert should have been yet initiated. */
1085 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1087 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1089 MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
1091 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1094 /* Reset the wathdog */
1095 RestartSDO_TIMER(line)
1096 MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
1097 index = d->transfers[line].index;
1098 subIndex = d->transfers[line].subIndex;
1100 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
1101 MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
1102 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
1105 /* Uploading next segment. We need to know if it will be the last one. */
1106 getSDOlineRestBytes(d, line, &nbBytes);
1108 /* The segment to transfer is not the last one.*/
1109 /* code to send the next segment. (cs = 0; c = 0) */
1110 sdo.nodeId = nodeId; /* The server node Id; */
1111 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1112 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1114 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1117 /* Inverting the toggle for the next tranfert. */
1118 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
1119 MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
1120 sendSDO(d, whoami, sdo);
1124 /* code to send the last segment. (cs = 0; c = 1) */
1125 sdo.nodeId = nodeId; /** The server node Id; */
1126 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1127 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1129 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1132 for (i = nbBytes + 1 ; i < 8 ; i++)
1133 sdo.body.data[i] = 0;
1134 MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
1135 sendSDO(d, whoami, sdo);
1136 /* Release the line */
1137 resetSDOline(d, line);
1139 } /* end if SERVER*/
1142 /* It is the response for the previous initiate download request. */
1143 /* We should find a line opened for this. */
1144 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1146 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
1148 MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
1149 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1152 /* Reset the watchdog */
1153 RestartSDO_TIMER(line)
1154 index = d->transfers[line].index;
1155 subIndex = d->transfers[line].subIndex;
1156 /* End transmission or requesting next segment. */
1157 getSDOlineRestBytes(d, line, &nbBytes);
1159 MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
1161 d->transfers[line].state = SDO_FINISHED;
1162 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1166 /* more than one request to send */
1167 /* code to send the next segment. (cs = 0; c = 0) */
1168 sdo.nodeId = nodeId; /** The server node Id; */
1169 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1170 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1172 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1178 /* code to send the last segment. (cs = 0; c = 1) */
1179 sdo.nodeId = nodeId; /* The server node Id; */
1180 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1181 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1183 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1186 for (i = nbBytes + 1 ; i < 8 ; i++)
1187 sdo.body.data[i] = 0;
1189 MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
1190 sendSDO(d, whoami, sdo);
1192 } /* end if I am a CLIENT */
1198 ((UNS32)m->data[5] << 8) |
1199 ((UNS32)m->data[6] << 16) |
1200 ((UNS32)m->data[7] << 24);
1201 /* Received SDO abort. */
1202 /* Looking for the line concerned. */
1203 if (whoami == SDO_SERVER) {
1204 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1206 resetSDOline( d, line );
1207 MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
1210 MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1211 /* Tips : The end user has no way to know that the server node has received an abort SDO. */
1212 /* Its is ok, I think.*/
1214 else { /* If I am CLIENT */
1215 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1217 /* The line *must* be released by the core program. */
1219 d->transfers[line].state = SDO_ABORTED_RCV;
1220 d->transfers[line].abortCode = abortCode;
1221 MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
1222 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1225 MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1229 /* Error : Unknown cs */
1230 MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
1252 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1253 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1258 s_SDO sdo; /* SDO to transmit */
1263 UNS8 *pNodeIdServer;
1266 MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
1267 MSG_WAR(0x3AC1, " At index : ", index);
1268 MSG_WAR(0x3AC2, " subIndex : ", subIndex);
1269 MSG_WAR(0x3AC3, " nb bytes : ", count);
1271 /* Verify that there is no SDO communication yet. */
1272 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1274 MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
1277 /* Taking the line ... */
1278 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1280 MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1283 /* Check which SDO to use to communicate with the node */
1284 offset = d->firstIndex->SDO_CLT;
1285 lastIndex = d->lastIndex->SDO_CLT;
1287 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1291 while (offset <= lastIndex) {
1292 if (d->objdict[offset].bSubCount <= 3) {
1293 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1296 /* looking for the nodeId server */
1297 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1298 nodeIdServer = *pNodeIdServer;
1299 MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
1300 MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
1302 if(nodeIdServer == nodeId) {
1310 MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
1313 MSG_WAR(0x3AD0," SDO client defined at index : ", 0x1280 + i);
1314 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
1315 d->transfers[line].count = count;
1316 d->transfers[line].dataType = dataType;
1318 /* Copy data to transfers structure. */
1319 for (j = 0 ; j < count ; j++) {
1320 # ifdef CANOPEN_BIG_ENDIAN
1321 if (dataType == 0 && endianize)
1322 d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
1323 else /* String of bytes. */
1324 d->transfers[line].data[j] = ((char *)data)[j];
1326 d->transfers[line].data[j] = ((char *)data)[j];
1329 /* Send the SDO to the server. Initiate download, cs=1. */
1330 sdo.nodeId = nodeId;
1331 if (count <= 4) { /* Expedited transfert */
1332 sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
1333 for (i = 4 ; i < 8 ; i++)
1334 sdo.body.data[i] = d->transfers[line].data[i - 4];
1335 d->transfers[line].offset = count;
1337 else { /** Normal transfert */
1338 sdo.body.data[0] = (1 << 5) | 1;
1339 for (i = 4 ; i < 8 ; i++)
1340 sdo.body.data[i] = 0;
1342 sdo.body.data[1] = index & 0xFF; /* LSB */
1343 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1344 sdo.body.data[3] = subIndex;
1346 d->transfers[line].Callback = Callback;
1348 err = sendSDO(d, SDO_CLIENT, sdo);
1350 MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
1351 /* release the line */
1352 resetSDOline(d, line);
1373 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1374 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
1376 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
1393 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
1394 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
1396 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1399 UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
1400 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1408 ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize);
1411 offset = d->firstIndex->SDO_CLT;
1412 lastIndex = d->lastIndex->SDO_CLT;
1415 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1419 while (offset <= lastIndex)
1421 if (d->objdict[offset].bSubCount <= 3)
1423 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1426 nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
1427 if(nodeIdServer == 0)
1429 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
1430 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
1431 *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
1432 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1460 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1466 s_SDO sdo; /* SDO to transmit */
1467 UNS8 *pNodeIdServer;
1471 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1472 MSG_WAR(0x3AD6, " At index : ", index);
1473 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1476 /* Verify that there is no SDO communication yet. */
1477 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1479 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1482 /* Taking the line ... */
1483 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1485 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1489 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1491 /* Check which SDO to use to communicate with the node */
1492 offset = d->firstIndex->SDO_CLT;
1493 lastIndex = d->lastIndex->SDO_CLT;
1495 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1499 while (offset <= lastIndex) {
1500 if (d->objdict[offset].bSubCount <= 3) {
1501 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1504 /* looking for the nodeId server */
1505 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1506 nodeIdServer = *pNodeIdServer;
1508 if(nodeIdServer == nodeId) {
1516 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1519 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1520 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1521 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1522 sdo.nodeId = nodeId;
1523 /* Send the SDO to the server. Initiate upload, cs=2. */
1524 d->transfers[line].dataType = dataType;
1525 sdo.body.data[0] = (2 << 5);
1526 sdo.body.data[1] = index & 0xFF; /* LSB */
1527 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1528 sdo.body.data[3] = subIndex;
1529 for (i = 4 ; i < 8 ; i++)
1530 sdo.body.data[i] = 0;
1531 d->transfers[line].Callback = Callback;
1532 err = sendSDO(d, SDO_CLIENT, sdo);
1534 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1535 /* release the line */
1536 resetSDOline(d, line);
1553 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
1555 return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
1570 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1572 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1575 UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1583 ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1586 offset = d->firstIndex->SDO_CLT;
1587 lastIndex = d->lastIndex->SDO_CLT;
1590 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1594 while (offset <= lastIndex)
1596 if (d->objdict[offset].bSubCount <= 3)
1598 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1601 nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
1602 if(nodeIdServer == 0)
1604 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
1605 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
1606 *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
1607 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1629 ** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
1634 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
1642 /* Looking for the line tranfert. */
1643 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1645 MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
1646 return SDO_ABORTED_INTERNAL;
1648 * abortCode = d->transfers[line].abortCode;
1649 if (d->transfers[line].state != SDO_FINISHED)
1650 return d->transfers[line].state;
1652 /* Transfert is finished. Put the value in the data. */
1653 /* use transfers[line].count as max size */
1654 if( d->transfers[line].count < *size )
1655 *size = d->transfers[line].count;
1656 for ( i = 0 ; i < *size ; i++) {
1657 # ifdef CANOPEN_BIG_ENDIAN
1658 if (d->transfers[line].dataType != visible_string)
1659 ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
1660 else /* String of bytes. */
1661 ( (char *) data)[i] = d->transfers[line].data[i];
1663 ( (char *) data)[i] = d->transfers[line].data[i];
1666 return SDO_FINISHED;
1678 UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
1684 /* Looking for the line tranfert. */
1685 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1687 MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
1688 return SDO_ABORTED_INTERNAL;
1690 * abortCode = d->transfers[line].abortCode;
1691 return d->transfers[line].state;