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,
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, 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;
350 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
352 MSG_WAR(0x3A25, "init SDO line nb : ", line);
353 if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
358 d->transfers[line].nodeId = nodeId;
359 d->transfers[line].index = index;
360 d->transfers[line].subIndex = subIndex;
361 d->transfers[line].state = state;
362 d->transfers[line].toggle = 0;
363 d->transfers[line].count = 0;
364 d->transfers[line].offset = 0;
365 d->transfers[line].dataType = 0;
366 d->transfers[line].Callback = NULL;
379 UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
384 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
385 if ( d->transfers[i].state == SDO_RESET ) {
387 d->transfers[i].whoami = whoami;
391 MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
405 UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
410 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
411 if ( (d->transfers[i].state != SDO_RESET) &&
412 (d->transfers[i].nodeId == nodeId) &&
413 (d->transfers[i].whoami == whoami) ) {
430 UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
434 err = getSDOlineOnUse(d, nodeId, whoami, &line);
436 MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
439 resetSDOline(d, line);
452 UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes)
454 if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
457 * nbBytes = (UNS8)d->transfers[line].count - (UNS8)d->transfers[line].offset;
470 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes)
472 if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
473 MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
476 d->transfers[line].count = nbBytes;
489 UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
496 UNS32 * pwCobId = NULL;
497 UNS8 * pwNodeId = NULL;
499 MSG_WAR(0x3A38, "sendSDO",0);
500 if( !((d->nodeState == Operational) || (d->nodeState == Pre_operational ))) {
501 MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
505 /*get the server->client cobid*/
506 if ( whoami == SDO_SERVER ) {/*case server. only one SDO server*/
507 offset = d->firstIndex->SDO_SVR;
509 MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
512 pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
513 MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
515 else { /*case client*/
516 /* Get the client->server cobid.*/
518 offset = d->firstIndex->SDO_CLT;
519 lastIndex = d->lastIndex->SDO_CLT;
521 MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
524 /* find index for communication server node */
525 while (offset <= lastIndex){
526 MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
527 if (d->objdict[offset].bSubCount <= 3) {
528 MSG_ERR(0x1A28, "Subindex 3 not found at index ", 0x1280 + sdoNum);
531 pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
532 MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
533 if(*pwNodeId == sdo.nodeId) {
541 MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
544 /* read the client->server cobid */
545 pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
547 /* message copy for sending */
548 m.cob_id = UNS16_LE(*pwCobId);
549 m.rtr = NOT_A_REQUEST;
550 /* the length of SDO must be 8 */
552 for (i = 0 ; i < 8 ; i++) {
553 m.data[i] = sdo.body.data[i];
555 return canSend(d->canHandle,&m);
569 UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode)
573 MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
574 sdo.nodeId = *d->bDeviceNodeId;
575 sdo.body.data[0] = 0x80;
577 sdo.body.data[1] = index & 0xFF; /* LSB */
578 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
580 sdo.body.data[3] = subIndex;
582 sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
583 sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
584 sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
585 sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
586 ret = sendSDO(d, whoami, sdo);
599 UNS8 proceedSDO (CO_Data* d, Message *m)
603 UNS8 nbBytes; /* received or to be transmited. */
604 UNS8 nodeId = 0; /* The node from which the SDO is received */
605 UNS8 *pNodeId = NULL;
606 UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
607 UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
608 s_SDO sdo; /* SDO to transmit */
613 UNS32 *pCobId = NULL;
617 MSG_WAR(0x3A60, "proceedSDO ", 0);
618 whoami = SDO_UNKNOWN;
619 /* Looking for the cobId in the object dictionary. */
620 /* Am-I a server ? */
621 offset = d->firstIndex->SDO_SVR;
622 lastIndex = d->lastIndex->SDO_SVR;
624 if(offset) while (offset <= lastIndex) {
625 if (d->objdict[offset].bSubCount <= 1) {
626 MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);
629 pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
630 if ( *pCobId == UNS16_LE(m->cob_id) ) {
632 MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
633 /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
634 /* 0x1200 where the cobid received is defined. */
641 if (whoami == SDO_UNKNOWN) {
643 offset = d->firstIndex->SDO_CLT;
644 lastIndex = d->lastIndex->SDO_CLT;
646 if(offset) while (offset <= lastIndex) {
647 if (d->objdict[offset].bSubCount <= 3) {
648 MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
651 /* a) Looking for the cobid received. */
652 pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
653 if (*pCobId == UNS16_LE(m->cob_id) ) {
654 /* b) cobid found, so reading the node id of the server. */
655 pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
658 MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
659 MSG_WAR(0x3A65, " Server nodeId : ", nodeId);
666 if (whoami == SDO_UNKNOWN) {
667 return 0xFF;/* This SDO was not for us ! */
670 /* Test if the size of the SDO is ok */
671 if ( (*m).len != 8) {
672 MSG_ERR(0x1A67, "Error size SDO. CobId : ", UNS16_LE(m->cob_id));
673 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
677 if (whoami == SDO_CLIENT) {
678 MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
681 MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", UNS16_LE(m->cob_id));
684 /* Testing the command specifier */
685 /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
686 /* cs = other : Not allowed -> abort. */
687 switch (getSDOcs(m->data[0])) {
691 if (whoami == SDO_SERVER) {
692 /* Receiving a download segment data. */
693 /* A SDO transfert should have been yet initiated. */
694 err = getSDOlineOnUse( d, nodeId, whoami, &line );
696 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
698 MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
700 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
703 /* Reset the wathdog */
704 RestartSDO_TIMER(line)
705 MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
706 index = d->transfers[line].index;
707 subIndex = d->transfers[line].subIndex;
709 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
710 MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
711 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
714 /* Nb of data to be downloaded */
715 nbBytes = 7 - getSDOn3(m->data[0]);
716 /* Store the data in the transfert structure. */
717 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
719 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
722 /* Sending the SDO response, CS = 1 */
723 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
724 sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
725 for (i = 1 ; i < 8 ; i++)
726 sdo.body.data[i] = 0;
727 MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
728 sendSDO(d, whoami, sdo);
729 /* Inverting the toggle for the next segment. */
730 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
731 /* If it was the last segment, */
732 if (getSDOc(m->data[0])) {
733 /* Transfering line data to object dictionary. */
734 /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
735 errorCode = SDOlineToObjdict(d, line);
737 MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
738 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
741 /* Release of the line */
742 resetSDOline(d, line);
743 MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
745 } /* end if SERVER */
746 else { /* if CLIENT */
748 /* It is a request for a previous upload segment. We should find a line opened for this.*/
749 err = getSDOlineOnUse( d, nodeId, whoami, &line);
751 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
753 MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
754 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
757 /* Reset the wathdog */
758 RestartSDO_TIMER(line)
759 index = d->transfers[line].index;
760 subIndex = d->transfers[line].subIndex;
761 /* test of the toggle; */
762 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
763 MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
764 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
767 /* nb of data to be uploaded */
768 nbBytes = 7 - getSDOn3(m->data[0]);
769 /* Storing the data in the line structure. */
770 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
772 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
775 /* Inverting the toggle for the next segment. */
776 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
777 /* If it was the last segment,*/
778 if ( getSDOc(m->data[0])) {
779 /* Put in state finished */
780 /* The code is safe for the case e=s=0 in initiate frame. */
782 d->transfers[line].state = SDO_FINISHED;
783 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
785 MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
787 else { /* more segments to receive */
788 /* Sending the request for the next segment. */
790 sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
791 for (i = 1 ; i < 8 ; i++)
792 sdo.body.data[i] = 0;
793 sendSDO(d, whoami, sdo);
794 MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
796 } /* End if CLIENT */
801 /* Receive of an initiate download */
802 if (whoami == SDO_SERVER) {
803 index = getSDOindex(m->data[1],m->data[2]);
804 subIndex = getSDOsubIndex(m->data[3]);
805 MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
807 MSG_WAR(0x3A80, "Writing at index : ", index);
808 MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
810 /* Search if a SDO transfert have been yet initiated */
811 err = getSDOlineOnUse( d, nodeId, whoami, &line );
813 MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
814 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
817 /* No line on use. Great ! */
818 /* Try to open a new line. */
819 err = getSDOfreeLine( d, whoami, &line );
821 MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
822 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
825 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
827 if (getSDOe(m->data[0])) { /* If SDO expedited */
828 /* nb of data to be downloaded */
829 nbBytes = 4 - getSDOn2(m->data[0]);
830 /* Storing the data in the line structure. */
831 d->transfers[line].count = nbBytes;
832 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
835 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
839 /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
840 /*The line will be reseted when it is downloading in the dictionary. */
841 MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
842 /* Transfering line data to object dictionary. */
843 errorCode = SDOlineToObjdict(d, line);
845 MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
846 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
849 /* Release of the line. */
850 resetSDOline(d, line);
852 else {/* So, if it is not an expedited transfert */
853 if (getSDOs(m->data[0])) {
854 /* TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
855 nbBytes = m->data[4]; /* Transfert limited to 255 bytes. */
856 err = setSDOlineRestBytes(d, nodeId, nbBytes);
858 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
863 /*Sending a SDO, cs=3*/
864 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
865 sdo.body.data[0] = 3 << 5;
866 sdo.body.data[1] = index & 0xFF; /* LSB */
867 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
868 sdo.body.data[3] = subIndex;
869 for (i = 4 ; i < 8 ; i++)
870 sdo.body.data[i] = 0;
871 sendSDO(d, whoami, sdo);
872 } /* end if I am SERVER */
875 /* It is a response for a previous download segment. We should find a line opened for this. */
876 err = getSDOlineOnUse( d, nodeId, whoami, &line);
878 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
880 MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
881 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
884 /* Reset the wathdog */
885 RestartSDO_TIMER(line)
886 index = d->transfers[line].index;
887 subIndex = d->transfers[line].subIndex;
888 /* test of the toggle; */
889 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
890 MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
891 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
895 /* End transmission or downloading next segment. We need to know if it will be the last one. */
896 getSDOlineRestBytes(d, line, &nbBytes);
898 MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
900 d->transfers[line].state = SDO_FINISHED;
901 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
904 /* At least one transfer to send. */
906 /* several segments to download.*/
907 /* code to send the next segment. (cs = 0; c = 0) */
908 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
909 sdo.nodeId = nodeId; /* The server node Id; */
910 sdo.body.data[0] = (d->transfers[line].toggle << 4);
911 err = lineToSDO(d, line, 7, sdo.body.data + 1);
913 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
919 /* code to send the last segment. (cs = 0; c = 1)*/
920 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
921 sdo.nodeId = nodeId; /* The server node Id; */
922 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
923 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
925 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
928 for (i = nbBytes + 1 ; i < 8 ; i++)
929 sdo.body.data[i] = 0;
931 MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
932 sendSDO(d, whoami, sdo);
933 } /* end if I am a CLIENT */
938 /* Receive of an initiate upload.*/
939 if (whoami == SDO_SERVER) {
940 index = getSDOindex(m->data[1],m->data[2]);
941 subIndex = getSDOsubIndex(m->data[3]);
942 MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
944 MSG_WAR(0x3A90, "Reading at index : ", index);
945 MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
946 /* Search if a SDO transfert have been yet initiated*/
947 err = getSDOlineOnUse( d, nodeId, whoami, &line );
949 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
950 MSG_WAR(0x3A93, "nodeId = ", nodeId);
951 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
954 /* No line on use. Great !*/
955 /* Try to open a new line.*/
956 err = getSDOfreeLine( d, whoami, &line );
958 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
959 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
962 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
963 /* Transfer data from dictionary to the line structure. */
964 errorCode = objdictToSDOline(d, line);
967 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
969 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
972 /* Preparing the response.*/
973 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
974 sdo.nodeId = nodeId; /* The server node Id; */
976 /* normal transfert. (segmented). */
977 /* code to send the initiate upload response. (cs = 2) */
978 sdo.body.data[0] = (2 << 5) | 1;
979 sdo.body.data[1] = index & 0xFF; /* LSB */
980 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
981 sdo.body.data[3] = subIndex;
982 sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
983 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
984 /* in the object dictionary, at every index and subindex. */
985 for (i = 5 ; i < 8 ; i++)
986 sdo.body.data[i] = 0;
987 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
988 sendSDO(d, whoami, sdo);
991 /* Expedited upload. (cs = 2 ; e = 1) */
992 sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;
993 sdo.body.data[1] = index & 0xFF; /* LSB */
994 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
995 sdo.body.data[3] = subIndex;
996 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
998 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1001 for (i = 4 + nbBytes ; i < 8 ; i++)
1002 sdo.body.data[i] = 0;
1003 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1005 sendSDO(d, whoami, sdo);
1006 /* Release the line.*/
1007 resetSDOline(d, line);
1009 } /* end if I am SERVER*/
1012 /* It is the response for the previous initiate upload request.*/
1013 /* We should find a line opened for this. */
1014 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1016 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1018 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1019 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1022 /* Reset the wathdog */
1023 RestartSDO_TIMER(line)
1024 index = d->transfers[line].index;
1025 subIndex = d->transfers[line].subIndex;
1027 if (getSDOe(m->data[0])) { /* If SDO expedited */
1028 /* nb of data to be uploaded */
1029 nbBytes = 4 - getSDOn2(m->data[0]);
1030 /* Storing the data in the line structure. */
1031 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1033 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1036 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1037 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1039 d->transfers[line].count = nbBytes;
1040 d->transfers[line].state = SDO_FINISHED;
1041 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1044 else { /* So, if it is not an expedited transfert */
1045 /* Storing the nb of data to receive. */
1046 if (getSDOs(m->data[0])) {
1047 nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
1048 err = setSDOlineRestBytes(d, line, nbBytes);
1050 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1054 /* Requesting next segment. (cs = 3) */
1055 sdo.nodeId = nodeId;
1056 sdo.body.data[0] = 3 << 5;
1057 for (i = 1 ; i < 8 ; i++)
1058 sdo.body.data[i] = 0;
1059 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1060 sendSDO(d, whoami, sdo);
1062 } /* End if CLIENT */
1067 if (whoami == SDO_SERVER) {
1068 /* Receiving a upload segment. */
1069 /* A SDO transfert should have been yet initiated. */
1070 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1072 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1074 MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
1076 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1079 /* Reset the wathdog */
1080 RestartSDO_TIMER(line)
1081 MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
1082 index = d->transfers[line].index;
1083 subIndex = d->transfers[line].subIndex;
1085 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
1086 MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
1087 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
1090 /* Uploading next segment. We need to know if it will be the last one. */
1091 getSDOlineRestBytes(d, line, &nbBytes);
1093 /* The segment to transfer is not the last one.*/
1094 /* code to send the next segment. (cs = 0; c = 0) */
1095 sdo.nodeId = nodeId; /* The server node Id; */
1096 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1097 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1099 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1102 /* Inverting the toggle for the next tranfert. */
1103 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
1104 MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
1105 sendSDO(d, whoami, sdo);
1109 /* code to send the last segment. (cs = 0; c = 1) */
1110 sdo.nodeId = nodeId; /** The server node Id; */
1111 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1112 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1114 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1117 for (i = nbBytes + 1 ; i < 8 ; i++)
1118 sdo.body.data[i] = 0;
1119 MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
1120 sendSDO(d, whoami, sdo);
1121 /* Release the line */
1122 resetSDOline(d, line);
1124 } /* end if SERVER*/
1127 /* It is the response for the previous initiate download request. */
1128 /* We should find a line opened for this. */
1129 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1131 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
1133 MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
1134 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1137 /* Reset the watchdog */
1138 RestartSDO_TIMER(line)
1139 index = d->transfers[line].index;
1140 subIndex = d->transfers[line].subIndex;
1141 /* End transmission or requesting next segment. */
1142 getSDOlineRestBytes(d, line, &nbBytes);
1144 MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
1146 d->transfers[line].state = SDO_FINISHED;
1147 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1151 /* more than one request to send */
1152 /* code to send the next segment. (cs = 0; c = 0) */
1153 sdo.nodeId = nodeId; /** The server node Id; */
1154 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1155 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1157 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1163 /* code to send the last segment. (cs = 0; c = 1) */
1164 sdo.nodeId = nodeId; /* The server node Id; */
1165 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1166 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1168 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1171 for (i = nbBytes + 1 ; i < 8 ; i++)
1172 sdo.body.data[i] = 0;
1174 MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
1175 sendSDO(d, whoami, sdo);
1177 } /* end if I am a CLIENT */
1183 ((UNS32)m->data[5] << 8) |
1184 ((UNS32)m->data[6] << 16) |
1185 ((UNS32)m->data[7] << 24);
1186 /* Received SDO abort. */
1187 /* Looking for the line concerned. */
1188 if (whoami == SDO_SERVER) {
1189 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1191 resetSDOline( d, line );
1192 MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
1195 MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1196 /* Tips : The end user has no way to know that the server node has received an abort SDO. */
1197 /* Its is ok, I think.*/
1199 else { /* If I am CLIENT */
1200 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1202 /* The line *must* be released by the core program. */
1204 d->transfers[line].state = SDO_ABORTED_RCV;
1205 d->transfers[line].abortCode = abortCode;
1206 MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
1207 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1210 MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1214 /* Error : Unknown cs */
1215 MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
1237 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1238 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1243 s_SDO sdo; /* SDO to transmit */
1247 UNS8 *pNodeIdServer;
1250 MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
1251 MSG_WAR(0x3AC1, " At index : ", index);
1252 MSG_WAR(0x3AC2, " subIndex : ", subIndex);
1253 MSG_WAR(0x3AC3, " nb bytes : ", count);
1255 /* Verify that there is no SDO communication yet. */
1256 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1258 MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
1261 /* Taking the line ... */
1262 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1264 MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1267 /* Check which SDO to use to communicate with the node */
1268 offset = d->firstIndex->SDO_CLT;
1269 lastIndex = d->lastIndex->SDO_CLT;
1271 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1275 while (offset <= lastIndex) {
1276 if (d->objdict[offset].bSubCount <= 3) {
1277 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1280 /* looking for the nodeId server */
1281 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1282 nodeIdServer = *pNodeIdServer;
1283 MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
1284 MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
1286 if(nodeIdServer == nodeId) {
1294 MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
1297 MSG_WAR(0x3AD0," SDO client defined at index : ", 0x1280 + i);
1298 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
1299 d->transfers[line].count = count;
1300 d->transfers[line].dataType = dataType;
1302 /* Copy data to transfers structure. */
1303 for (j = 0 ; j < count ; j++) {
1304 # ifdef CANOPEN_BIG_ENDIAN
1305 if (dataType == 0 && endianize)
1306 d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
1307 else /* String of bytes. */
1308 d->transfers[line].data[j] = ((char *)data)[j];
1310 d->transfers[line].data[j] = ((char *)data)[j];
1313 /* Send the SDO to the server. Initiate download, cs=1. */
1314 sdo.nodeId = nodeId;
1315 if (count <= 4) { /* Expedited transfert */
1316 sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
1317 for (i = 4 ; i < 8 ; i++)
1318 sdo.body.data[i] = d->transfers[line].data[i - 4];
1319 d->transfers[line].offset = count;
1321 else { /** Normal transfert */
1322 sdo.body.data[0] = (1 << 5) | 1;
1323 sdo.body.data[4] = count; /* nb of byte to transmit. Max = 255. (canfestival2 limitation). */
1324 for (i = 5 ; i < 8 ; i++)
1325 sdo.body.data[i] = 0;
1327 sdo.body.data[1] = index & 0xFF; /* LSB */
1328 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1329 sdo.body.data[3] = subIndex;
1331 d->transfers[line].Callback = Callback;
1333 err = sendSDO(d, SDO_CLIENT, sdo);
1335 MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
1336 /* release the line */
1337 resetSDOline(d, line);
1358 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1359 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data)
1361 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
1378 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
1379 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback)
1381 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1396 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1402 s_SDO sdo; /* SDO to transmit */
1403 UNS8 *pNodeIdServer;
1407 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1408 MSG_WAR(0x3AD6, " At index : ", index);
1409 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1412 /* Verify that there is no SDO communication yet. */
1413 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1415 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1418 /* Taking the line ... */
1419 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1421 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1425 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1427 /* Check which SDO to use to communicate with the node */
1428 offset = d->firstIndex->SDO_CLT;
1429 lastIndex = d->lastIndex->SDO_CLT;
1431 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1435 while (offset <= lastIndex) {
1436 if (d->objdict[offset].bSubCount <= 3) {
1437 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1440 /* looking for the nodeId server */
1441 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1442 nodeIdServer = *pNodeIdServer;
1444 if(nodeIdServer == nodeId) {
1452 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1455 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1456 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1457 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1458 sdo.nodeId = nodeId;
1459 /* Send the SDO to the server. Initiate upload, cs=2. */
1460 d->transfers[line].dataType = dataType;
1461 sdo.body.data[0] = (2 << 5);
1462 sdo.body.data[1] = index & 0xFF; /* LSB */
1463 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1464 sdo.body.data[3] = subIndex;
1465 for (i = 4 ; i < 8 ; i++)
1466 sdo.body.data[i] = 0;
1467 d->transfers[line].Callback = Callback;
1468 err = sendSDO(d, SDO_CLIENT, sdo);
1470 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1471 /* release the line */
1472 resetSDOline(d, line);
1489 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
1491 return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
1506 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1508 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1517 ** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
1522 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS8 *size,
1530 /* Looking for the line tranfert. */
1531 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1533 MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
1534 return SDO_ABORTED_INTERNAL;
1536 if (d->transfers[line].state != SDO_FINISHED)
1537 return d->transfers[line].state;
1539 /* Transfert is finished. Put the value in the data. */
1540 /* use transfers[line].count as max size */
1541 if( (UNS8)d->transfers[line].count < *size )
1542 *size = (UNS8)d->transfers[line].count;
1543 for ( i = 0 ; i < *size ; i++) {
1544 # ifdef CANOPEN_BIG_ENDIAN
1545 if (d->transfers[line].dataType != visible_string)
1546 ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
1547 else /* String of bytes. */
1548 ( (char *) data)[i] = d->transfers[line].data[i];
1550 ( (char *) data)[i] = d->transfers[line].data[i];
1553 return SDO_FINISHED;
1565 UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
1571 /* Looking for the line tranfert. */
1572 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1574 MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
1575 return SDO_ABORTED_INTERNAL;
1577 * abortCode = d->transfers[line].abortCode;
1578 return d->transfers[line].state;