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, UNS8 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 = (UNS8)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, UNS8 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 = (UNS8)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, UNS8 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 = (UNS8)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;
298 UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
299 UNS8 subIndex, UNS32 abortCode)
303 err = getSDOlineOnUse( d, nodeId, whoami, &line );
304 if (!err) /* If a line on use have been found.*/
305 MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
306 if ((! err) && (whoami == SDO_SERVER)) {
307 resetSDOline( d, line );
308 MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
310 if ((! err) && (whoami == SDO_CLIENT)) {
312 d->transfers[line].state = SDO_ABORTED_INTERNAL;
314 MSG_WAR(0x3A22, "Sending SDO abort ", 0);
315 err = sendSDOabort(d, whoami, nodeId, index, subIndex, abortCode);
317 MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
329 void resetSDOline ( CO_Data* d, UNS8 line )
332 MSG_WAR(0x3A25, "reset SDO line nb : ", line);
333 initSDOline(d, line, 0, 0, 0, SDO_RESET);
334 for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
335 d->transfers[line].data[i] = 0;
336 d->transfers[line].whoami = 0;
337 d->transfers[line].abortCode = 0;
352 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
354 MSG_WAR(0x3A25, "init SDO line nb : ", line);
355 if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
360 d->transfers[line].nodeId = nodeId;
361 d->transfers[line].index = index;
362 d->transfers[line].subIndex = subIndex;
363 d->transfers[line].state = state;
364 d->transfers[line].toggle = 0;
365 d->transfers[line].count = 0;
366 d->transfers[line].offset = 0;
367 d->transfers[line].dataType = 0;
368 d->transfers[line].Callback = NULL;
381 UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
386 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
387 if ( d->transfers[i].state == SDO_RESET ) {
389 d->transfers[i].whoami = whoami;
393 MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
407 UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
412 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
413 if ( (d->transfers[i].state != SDO_RESET) &&
414 (d->transfers[i].nodeId == nodeId) &&
415 (d->transfers[i].whoami == whoami) ) {
432 UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
436 err = getSDOlineOnUse(d, nodeId, whoami, &line);
438 MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
441 resetSDOline(d, line);
454 UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes)
456 if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
459 * nbBytes = (UNS8)d->transfers[line].count - (UNS8)d->transfers[line].offset;
472 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes)
474 if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
475 MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
478 d->transfers[line].count = nbBytes;
491 UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
498 UNS32 * pwCobId = NULL;
499 UNS8 * pwNodeId = NULL;
501 MSG_WAR(0x3A38, "sendSDO",0);
502 if( !((d->nodeState == Operational) || (d->nodeState == Pre_operational ))) {
503 MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
507 /*get the server->client cobid*/
508 if ( whoami == SDO_SERVER ) {/*case server. only one SDO server*/
509 offset = d->firstIndex->SDO_SVR;
511 MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
514 pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
515 MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
517 else { /*case client*/
518 /* Get the client->server cobid.*/
520 offset = d->firstIndex->SDO_CLT;
521 lastIndex = d->lastIndex->SDO_CLT;
523 MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
526 /* find index for communication server node */
527 while (offset <= lastIndex){
528 MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
529 if (d->objdict[offset].bSubCount <= 3) {
530 MSG_ERR(0x1A28, "Subindex 3 not found at index ", 0x1280 + sdoNum);
533 pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
534 MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
535 if(*pwNodeId == sdo.nodeId) {
543 MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
546 /* read the client->server cobid */
547 pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
549 /* message copy for sending */
550 m.cob_id = UNS16_LE(*pwCobId);
551 m.rtr = NOT_A_REQUEST;
552 /* the length of SDO must be 8 */
554 for (i = 0 ; i < 8 ; i++) {
555 m.data[i] = sdo.body.data[i];
557 return canSend(d->canHandle,&m);
571 UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeID, UNS16 index, UNS8 subIndex, UNS32 abortCode)
579 MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
580 if(whoami == SDO_SERVER)
582 sdo.nodeId = *d->bDeviceNodeId;
588 sdo.body.data[0] = 0x80;
590 sdo.body.data[1] = index & 0xFF; /* LSB */
591 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
593 sdo.body.data[3] = subIndex;
595 sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
596 sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
597 sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
598 sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
599 ret = sendSDO(d, whoami, sdo);
612 UNS8 proceedSDO (CO_Data* d, Message *m)
616 UNS8 nbBytes; /* received or to be transmited. */
617 UNS8 nodeId = 0; /* The node from which the SDO is received */
618 UNS8 *pNodeId = NULL;
619 UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
620 UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
621 s_SDO sdo; /* SDO to transmit */
626 UNS32 *pCobId = NULL;
630 MSG_WAR(0x3A60, "proceedSDO ", 0);
631 whoami = SDO_UNKNOWN;
632 /* Looking for the cobId in the object dictionary. */
633 /* Am-I a server ? */
634 offset = d->firstIndex->SDO_SVR;
635 lastIndex = d->lastIndex->SDO_SVR;
637 if(offset) while (offset <= lastIndex) {
638 if (d->objdict[offset].bSubCount <= 1) {
639 MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);
642 pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
643 if ( *pCobId == UNS16_LE(m->cob_id) ) {
645 MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
646 /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
647 /* 0x1200 where the cobid received is defined. */
654 if (whoami == SDO_UNKNOWN) {
656 offset = d->firstIndex->SDO_CLT;
657 lastIndex = d->lastIndex->SDO_CLT;
659 if(offset) while (offset <= lastIndex) {
660 if (d->objdict[offset].bSubCount <= 3) {
661 MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
664 /* a) Looking for the cobid received. */
665 pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
666 if (*pCobId == UNS16_LE(m->cob_id) ) {
667 /* b) cobid found, so reading the node id of the server. */
668 pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
671 MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
672 MSG_WAR(0x3A65, " Server nodeId : ", nodeId);
679 if (whoami == SDO_UNKNOWN) {
680 return 0xFF;/* This SDO was not for us ! */
683 /* Test if the size of the SDO is ok */
684 if ( (*m).len != 8) {
685 MSG_ERR(0x1A67, "Error size SDO. CobId : ", UNS16_LE(m->cob_id));
686 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
690 if (whoami == SDO_CLIENT) {
691 MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
694 MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", UNS16_LE(m->cob_id));
697 /* Testing the command specifier */
698 /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
699 /* cs = other : Not allowed -> abort. */
700 switch (getSDOcs(m->data[0])) {
704 if (whoami == SDO_SERVER) {
705 /* Receiving a download segment data. */
706 /* A SDO transfert should have been yet initiated. */
707 err = getSDOlineOnUse( d, nodeId, whoami, &line );
709 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
711 MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
713 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
716 /* Reset the wathdog */
717 RestartSDO_TIMER(line)
718 MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
719 index = d->transfers[line].index;
720 subIndex = d->transfers[line].subIndex;
722 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
723 MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
724 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
727 /* Nb of data to be downloaded */
728 nbBytes = 7 - getSDOn3(m->data[0]);
729 /* Store the data in the transfert structure. */
730 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
732 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
735 /* Sending the SDO response, CS = 1 */
736 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
737 sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
738 for (i = 1 ; i < 8 ; i++)
739 sdo.body.data[i] = 0;
740 MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
741 sendSDO(d, whoami, sdo);
742 /* Inverting the toggle for the next segment. */
743 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
744 /* If it was the last segment, */
745 if (getSDOc(m->data[0])) {
746 /* Transfering line data to object dictionary. */
747 /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
748 errorCode = SDOlineToObjdict(d, line);
750 MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
751 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
754 /* Release of the line */
755 resetSDOline(d, line);
756 MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
758 } /* end if SERVER */
759 else { /* if CLIENT */
761 /* It is a request for a previous upload segment. We should find a line opened for this.*/
762 err = getSDOlineOnUse( d, nodeId, whoami, &line);
764 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
766 MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
767 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
770 /* Reset the wathdog */
771 RestartSDO_TIMER(line)
772 index = d->transfers[line].index;
773 subIndex = d->transfers[line].subIndex;
774 /* test of the toggle; */
775 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
776 MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
777 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
780 /* nb of data to be uploaded */
781 nbBytes = 7 - getSDOn3(m->data[0]);
782 /* Storing the data in the line structure. */
783 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
785 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
788 /* Inverting the toggle for the next segment. */
789 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
790 /* If it was the last segment,*/
791 if ( getSDOc(m->data[0])) {
792 /* Put in state finished */
793 /* The code is safe for the case e=s=0 in initiate frame. */
795 d->transfers[line].state = SDO_FINISHED;
796 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
798 MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
800 else { /* more segments to receive */
801 /* Sending the request for the next segment. */
803 sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
804 for (i = 1 ; i < 8 ; i++)
805 sdo.body.data[i] = 0;
806 sendSDO(d, whoami, sdo);
807 MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
809 } /* End if CLIENT */
814 /* Receive of an initiate download */
815 if (whoami == SDO_SERVER) {
816 index = getSDOindex(m->data[1],m->data[2]);
817 subIndex = getSDOsubIndex(m->data[3]);
818 MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
820 MSG_WAR(0x3A80, "Writing at index : ", index);
821 MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
823 /* Search if a SDO transfert have been yet initiated */
824 err = getSDOlineOnUse( d, nodeId, whoami, &line );
826 MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
827 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
830 /* No line on use. Great ! */
831 /* Try to open a new line. */
832 err = getSDOfreeLine( d, whoami, &line );
834 MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
835 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
838 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
840 if (getSDOe(m->data[0])) { /* If SDO expedited */
841 /* nb of data to be downloaded */
842 nbBytes = 4 - getSDOn2(m->data[0]);
843 /* Storing the data in the line structure. */
844 d->transfers[line].count = nbBytes;
845 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
848 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
852 /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
853 /*The line will be reseted when it is downloading in the dictionary. */
854 MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
855 /* Transfering line data to object dictionary. */
856 errorCode = SDOlineToObjdict(d, line);
858 MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
859 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
862 /* Release of the line. */
863 resetSDOline(d, line);
865 else {/* So, if it is not an expedited transfert */
866 if (getSDOs(m->data[0])) {
867 /* TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
868 nbBytes = m->data[4]; /* Transfert limited to 255 bytes. */
869 err = setSDOlineRestBytes(d, nodeId, nbBytes);
871 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
876 /*Sending a SDO, cs=3*/
877 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
878 sdo.body.data[0] = 3 << 5;
879 sdo.body.data[1] = index & 0xFF; /* LSB */
880 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
881 sdo.body.data[3] = subIndex;
882 for (i = 4 ; i < 8 ; i++)
883 sdo.body.data[i] = 0;
884 sendSDO(d, whoami, sdo);
885 } /* end if I am SERVER */
888 /* It is a response for a previous download segment. We should find a line opened for this. */
889 err = getSDOlineOnUse( d, nodeId, whoami, &line);
891 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
893 MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
894 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
897 /* Reset the wathdog */
898 RestartSDO_TIMER(line)
899 index = d->transfers[line].index;
900 subIndex = d->transfers[line].subIndex;
901 /* test of the toggle; */
902 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
903 MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
904 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
908 /* End transmission or downloading next segment. We need to know if it will be the last one. */
909 getSDOlineRestBytes(d, line, &nbBytes);
911 MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
913 d->transfers[line].state = SDO_FINISHED;
914 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
917 /* At least one transfer to send. */
919 /* several segments to download.*/
920 /* code to send the next segment. (cs = 0; c = 0) */
921 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
922 sdo.nodeId = nodeId; /* The server node Id; */
923 sdo.body.data[0] = (d->transfers[line].toggle << 4);
924 err = lineToSDO(d, line, 7, sdo.body.data + 1);
926 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
932 /* code to send the last segment. (cs = 0; c = 1)*/
933 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
934 sdo.nodeId = nodeId; /* The server node Id; */
935 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
936 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
938 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
941 for (i = nbBytes + 1 ; i < 8 ; i++)
942 sdo.body.data[i] = 0;
944 MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
945 sendSDO(d, whoami, sdo);
946 } /* end if I am a CLIENT */
951 /* Receive of an initiate upload.*/
952 if (whoami == SDO_SERVER) {
953 index = getSDOindex(m->data[1],m->data[2]);
954 subIndex = getSDOsubIndex(m->data[3]);
955 MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
957 MSG_WAR(0x3A90, "Reading at index : ", index);
958 MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
959 /* Search if a SDO transfert have been yet initiated*/
960 err = getSDOlineOnUse( d, nodeId, whoami, &line );
962 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
963 MSG_WAR(0x3A93, "nodeId = ", nodeId);
964 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
967 /* No line on use. Great !*/
968 /* Try to open a new line.*/
969 err = getSDOfreeLine( d, whoami, &line );
971 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
972 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
975 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
976 /* Transfer data from dictionary to the line structure. */
977 errorCode = objdictToSDOline(d, line);
980 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
982 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
985 /* Preparing the response.*/
986 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
987 sdo.nodeId = nodeId; /* The server node Id; */
989 /* normal transfert. (segmented). */
990 /* code to send the initiate upload response. (cs = 2) */
991 sdo.body.data[0] = (2 << 5) | 1;
992 sdo.body.data[1] = index & 0xFF; /* LSB */
993 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
994 sdo.body.data[3] = subIndex;
995 sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
996 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
997 /* in the object dictionary, at every index and subindex. */
998 for (i = 5 ; i < 8 ; i++)
999 sdo.body.data[i] = 0;
1000 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
1001 sendSDO(d, whoami, sdo);
1004 /* Expedited upload. (cs = 2 ; e = 1) */
1005 sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;
1006 sdo.body.data[1] = index & 0xFF; /* LSB */
1007 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1008 sdo.body.data[3] = subIndex;
1009 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
1011 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1014 for (i = 4 + nbBytes ; i < 8 ; i++)
1015 sdo.body.data[i] = 0;
1016 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1018 sendSDO(d, whoami, sdo);
1019 /* Release the line.*/
1020 resetSDOline(d, line);
1022 } /* end if I am SERVER*/
1025 /* It is the response for the previous initiate upload request.*/
1026 /* We should find a line opened for this. */
1027 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1029 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1031 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1032 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1035 /* Reset the wathdog */
1036 RestartSDO_TIMER(line)
1037 index = d->transfers[line].index;
1038 subIndex = d->transfers[line].subIndex;
1040 if (getSDOe(m->data[0])) { /* If SDO expedited */
1041 /* nb of data to be uploaded */
1042 nbBytes = 4 - getSDOn2(m->data[0]);
1043 /* Storing the data in the line structure. */
1044 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1046 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1049 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1050 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1052 d->transfers[line].count = nbBytes;
1053 d->transfers[line].state = SDO_FINISHED;
1054 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1057 else { /* So, if it is not an expedited transfert */
1058 /* Storing the nb of data to receive. */
1059 if (getSDOs(m->data[0])) {
1060 nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
1061 err = setSDOlineRestBytes(d, line, nbBytes);
1063 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1067 /* Requesting next segment. (cs = 3) */
1068 sdo.nodeId = nodeId;
1069 sdo.body.data[0] = 3 << 5;
1070 for (i = 1 ; i < 8 ; i++)
1071 sdo.body.data[i] = 0;
1072 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1073 sendSDO(d, whoami, sdo);
1075 } /* End if CLIENT */
1080 if (whoami == SDO_SERVER) {
1081 /* Receiving a upload segment. */
1082 /* A SDO transfert should have been yet initiated. */
1083 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1085 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1087 MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
1089 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1092 /* Reset the wathdog */
1093 RestartSDO_TIMER(line)
1094 MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
1095 index = d->transfers[line].index;
1096 subIndex = d->transfers[line].subIndex;
1098 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
1099 MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
1100 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
1103 /* Uploading next segment. We need to know if it will be the last one. */
1104 getSDOlineRestBytes(d, line, &nbBytes);
1106 /* The segment to transfer is not the last one.*/
1107 /* code to send the next segment. (cs = 0; c = 0) */
1108 sdo.nodeId = nodeId; /* The server node Id; */
1109 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1110 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1112 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1115 /* Inverting the toggle for the next tranfert. */
1116 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
1117 MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
1118 sendSDO(d, whoami, sdo);
1122 /* code to send the last segment. (cs = 0; c = 1) */
1123 sdo.nodeId = nodeId; /** The server node Id; */
1124 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1125 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1127 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1130 for (i = nbBytes + 1 ; i < 8 ; i++)
1131 sdo.body.data[i] = 0;
1132 MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
1133 sendSDO(d, whoami, sdo);
1134 /* Release the line */
1135 resetSDOline(d, line);
1137 } /* end if SERVER*/
1140 /* It is the response for the previous initiate download request. */
1141 /* We should find a line opened for this. */
1142 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1144 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
1146 MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
1147 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1150 /* Reset the watchdog */
1151 RestartSDO_TIMER(line)
1152 index = d->transfers[line].index;
1153 subIndex = d->transfers[line].subIndex;
1154 /* End transmission or requesting next segment. */
1155 getSDOlineRestBytes(d, line, &nbBytes);
1157 MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
1159 d->transfers[line].state = SDO_FINISHED;
1160 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1164 /* more than one request to send */
1165 /* code to send the next segment. (cs = 0; c = 0) */
1166 sdo.nodeId = nodeId; /** The server node Id; */
1167 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1168 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1170 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1176 /* code to send the last segment. (cs = 0; c = 1) */
1177 sdo.nodeId = nodeId; /* The server node Id; */
1178 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1179 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1181 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1184 for (i = nbBytes + 1 ; i < 8 ; i++)
1185 sdo.body.data[i] = 0;
1187 MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
1188 sendSDO(d, whoami, sdo);
1190 } /* end if I am a CLIENT */
1196 ((UNS32)m->data[5] << 8) |
1197 ((UNS32)m->data[6] << 16) |
1198 ((UNS32)m->data[7] << 24);
1199 /* Received SDO abort. */
1200 /* Looking for the line concerned. */
1201 if (whoami == SDO_SERVER) {
1202 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1204 resetSDOline( d, line );
1205 MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
1208 MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1209 /* Tips : The end user has no way to know that the server node has received an abort SDO. */
1210 /* Its is ok, I think.*/
1212 else { /* If I am CLIENT */
1213 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1215 /* The line *must* be released by the core program. */
1217 d->transfers[line].state = SDO_ABORTED_RCV;
1218 d->transfers[line].abortCode = abortCode;
1219 MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
1220 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1223 MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1227 /* Error : Unknown cs */
1228 MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
1250 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1251 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1256 s_SDO sdo; /* SDO to transmit */
1260 UNS8 *pNodeIdServer;
1263 MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
1264 MSG_WAR(0x3AC1, " At index : ", index);
1265 MSG_WAR(0x3AC2, " subIndex : ", subIndex);
1266 MSG_WAR(0x3AC3, " nb bytes : ", count);
1268 /* Verify that there is no SDO communication yet. */
1269 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1271 MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
1274 /* Taking the line ... */
1275 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1277 MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1280 /* Check which SDO to use to communicate with the node */
1281 offset = d->firstIndex->SDO_CLT;
1282 lastIndex = d->lastIndex->SDO_CLT;
1284 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1288 while (offset <= lastIndex) {
1289 if (d->objdict[offset].bSubCount <= 3) {
1290 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1293 /* looking for the nodeId server */
1294 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1295 nodeIdServer = *pNodeIdServer;
1296 MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
1297 MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
1299 if(nodeIdServer == nodeId) {
1307 MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
1310 MSG_WAR(0x3AD0," SDO client defined at index : ", 0x1280 + i);
1311 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
1312 d->transfers[line].count = count;
1313 d->transfers[line].dataType = dataType;
1315 /* Copy data to transfers structure. */
1316 for (j = 0 ; j < count ; j++) {
1317 # ifdef CANOPEN_BIG_ENDIAN
1318 if (dataType == 0 && endianize)
1319 d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
1320 else /* String of bytes. */
1321 d->transfers[line].data[j] = ((char *)data)[j];
1323 d->transfers[line].data[j] = ((char *)data)[j];
1326 /* Send the SDO to the server. Initiate download, cs=1. */
1327 sdo.nodeId = nodeId;
1328 if (count <= 4) { /* Expedited transfert */
1329 sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
1330 for (i = 4 ; i < 8 ; i++)
1331 sdo.body.data[i] = d->transfers[line].data[i - 4];
1332 d->transfers[line].offset = count;
1334 else { /** Normal transfert */
1335 sdo.body.data[0] = (1 << 5) | 1;
1336 sdo.body.data[4] = count; /* nb of byte to transmit. Max = 255. (canfestival2 limitation). */
1337 for (i = 5 ; i < 8 ; i++)
1338 sdo.body.data[i] = 0;
1340 sdo.body.data[1] = index & 0xFF; /* LSB */
1341 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1342 sdo.body.data[3] = subIndex;
1344 d->transfers[line].Callback = Callback;
1346 err = sendSDO(d, SDO_CLIENT, sdo);
1348 MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
1349 /* release the line */
1350 resetSDOline(d, line);
1371 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1372 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data)
1374 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
1391 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
1392 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback)
1394 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1409 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1415 s_SDO sdo; /* SDO to transmit */
1416 UNS8 *pNodeIdServer;
1420 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1421 MSG_WAR(0x3AD6, " At index : ", index);
1422 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1425 /* Verify that there is no SDO communication yet. */
1426 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1428 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1431 /* Taking the line ... */
1432 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1434 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1438 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1440 /* Check which SDO to use to communicate with the node */
1441 offset = d->firstIndex->SDO_CLT;
1442 lastIndex = d->lastIndex->SDO_CLT;
1444 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1448 while (offset <= lastIndex) {
1449 if (d->objdict[offset].bSubCount <= 3) {
1450 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1453 /* looking for the nodeId server */
1454 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1455 nodeIdServer = *pNodeIdServer;
1457 if(nodeIdServer == nodeId) {
1465 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1468 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1469 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1470 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1471 sdo.nodeId = nodeId;
1472 /* Send the SDO to the server. Initiate upload, cs=2. */
1473 d->transfers[line].dataType = dataType;
1474 sdo.body.data[0] = (2 << 5);
1475 sdo.body.data[1] = index & 0xFF; /* LSB */
1476 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1477 sdo.body.data[3] = subIndex;
1478 for (i = 4 ; i < 8 ; i++)
1479 sdo.body.data[i] = 0;
1480 d->transfers[line].Callback = Callback;
1481 err = sendSDO(d, SDO_CLIENT, sdo);
1483 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1484 /* release the line */
1485 resetSDOline(d, line);
1502 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
1504 return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
1519 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1521 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1530 ** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
1535 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS8 *size,
1544 /* Looking for the line tranfert. */
1545 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1547 MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
1548 return SDO_ABORTED_INTERNAL;
1550 * abortCode = d->transfers[line].abortCode;
1551 if (d->transfers[line].state != SDO_FINISHED)
1552 return d->transfers[line].state;
1554 /* Transfert is finished. Put the value in the data. */
1555 /* use transfers[line].count as max size */
1556 if( (UNS8)d->transfers[line].count < *size )
1557 *size = (UNS8)d->transfers[line].count;
1558 for ( i = 0 ; i < *size ; i++) {
1559 # ifdef CANOPEN_BIG_ENDIAN
1560 if (d->transfers[line].dataType != visible_string)
1561 ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
1562 else /* String of bytes. */
1563 ( (char *) data)[i] = d->transfers[line].data[i];
1565 ( (char *) data)[i] = d->transfers[line].data[i];
1568 return SDO_FINISHED;
1580 UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
1586 /* Looking for the line tranfert. */
1587 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1589 MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
1590 return SDO_ABORTED_INTERNAL;
1592 * abortCode = d->transfers[line].abortCode;
1593 return d->transfers[line].state;