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 */
37 #include "canfestival.h"
39 /* Uncomment if your compiler does not support inline functions */
48 /*Internals prototypes*/
51 ** Called by writeNetworkDict
65 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
66 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
69 ** Called by readNetworkDict
80 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
81 UNS8 dataType, SDOCallback_t Callback);
84 /***************************************************************************/
85 /* SDO (un)packing macros */
87 /** Returns the command specifier (cs, ccs, scs) from the first byte of the SDO
89 #define getSDOcs(byte) (byte >> 5)
91 /** Returns the number of bytes without data from the first byte of the SDO. Coded in 2 bits
93 #define getSDOn2(byte) ((byte >> 2) & 3)
95 /** Returns the number of bytes without data from the first byte of the SDO. Coded in 3 bits
97 #define getSDOn3(byte) ((byte >> 1) & 7)
99 /** Returns the transfer type from the first byte of the SDO
101 #define getSDOe(byte) ((byte >> 1) & 1)
103 /** Returns the size indicator from the first byte of the SDO
105 #define getSDOs(byte) (byte & 1)
107 /** Returns the indicator of end transmission from the first byte of the SDO
109 #define getSDOc(byte) (byte & 1)
111 /** Returns the toggle from the first byte of the SDO
113 #define getSDOt(byte) ((byte >> 4) & 1)
115 /** Returns the index from the bytes 1 and 2 of the SDO
117 #define getSDOindex(byte1, byte2) ((byte2 << 8) | (byte1))
119 /** Returns the subIndex from the byte 3 of the SDO
121 #define getSDOsubIndex(byte3) (byte3)
129 void SDOTimeoutAlarm(CO_Data* d, UNS32 id)
131 MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
132 MSG_WAR(0x2A02, "server node : ", d->transfers[id].nodeId);
133 MSG_WAR(0x2A02, " index : ", d->transfers[id].index);
134 MSG_WAR(0x2A02, " subIndex : ", d->transfers[id].subIndex);
135 /* Reset timer handler */
136 d->transfers[id].timer = TIMER_NONE;
137 /*Set aborted state*/
138 d->transfers[id].state = SDO_ABORTED_INTERNAL;
139 /* Sending a SDO abort */
140 sendSDOabort(d, d->transfers[id].whoami,
141 d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);
142 d->transfers[id].abortCode = SDOABT_TIMED_OUT;
143 /* Call the user function to inform of the problem.*/
144 if(d->transfers[id].Callback)
145 /*If ther is a callback, it is responsible to close SDO transfer (client)*/
146 (*d->transfers[id].Callback)(d,d->transfers[id].nodeId);
147 else if(d->transfers[id].whoami == SDO_SERVER)
148 /*Else, if server, reset the line*/
149 resetSDOline(d, (UNS8)id);
152 #define StopSDO_TIMER(id) \
153 MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\
154 d->transfers[id].timer = DelAlarm(d->transfers[id].timer);
156 #define StartSDO_TIMER(id) \
157 MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\
158 d->transfers[id].timer = SetAlarm(d,id,&SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);
160 #define RestartSDO_TIMER(id) \
161 MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
162 if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
165 ** Reset all sdo buffers
169 void resetSDO (CO_Data* d)
173 /* transfer structure initialization */
174 for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++)
186 UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line)
190 MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);
191 size = (UNS8)d->transfers[line].count;
192 errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
193 (void *) d->transfers[line].data, &size, 1);
194 if (errorCode != OD_SUCCESSFUL)
196 MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
209 UNS32 objdictToSDOline (CO_Data* d, UNS8 line)
215 MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
216 MSG_WAR(0x3A06, " subIndex : ", d->transfers[line].subIndex);
218 errorCode = getODentry(d, d->transfers[line].index,
219 d->transfers[line].subIndex,
220 (void *)d->transfers[line].data,
221 &size, &dataType, 0);
223 if (errorCode != OD_SUCCESSFUL)
226 d->transfers[line].count = size;
227 d->transfers[line].offset = 0;
229 /*Me laisser a, please ! (FD)*/
232 for (i = 0 ; i < 10 ; i++) {
233 MSG_WAR(i, "data= ", d->transfers[line].data[i]);
250 UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data) {
254 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
255 MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
258 if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
259 MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
262 offset = (UNS8)d->transfers[line].offset;
263 for (i = 0 ; i < nbBytes ; i++)
264 * (data + i) = d->transfers[line].data[offset + i];
265 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
279 UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8* data)
284 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
285 MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
288 offset = (UNS8)d->transfers[line].offset;
289 for (i = 0 ; i < nbBytes ; i++)
290 d->transfers[line].data[offset + i] = * (data + i);
291 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
307 UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
308 UNS8 subIndex, UNS32 abortCode)
312 err = getSDOlineOnUse( d, nodeId, whoami, &line );
313 if (!err) /* If a line on use have been found.*/
314 MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
315 if ((! err) && (whoami == SDO_SERVER)) {
316 resetSDOline( d, line );
317 MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
319 if ((! err) && (whoami == SDO_CLIENT)) {
321 d->transfers[line].state = SDO_ABORTED_INTERNAL;
323 MSG_WAR(0x3A22, "Sending SDO abort ", 0);
324 err = sendSDOabort(d, whoami, index, subIndex, abortCode);
326 MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
338 void resetSDOline ( CO_Data* d, UNS8 line )
341 MSG_WAR(0x3A25, "reset SDO line nb : ", line);
342 initSDOline(d, line, 0, 0, 0, SDO_RESET);
343 for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
344 d->transfers[line].data[i] = 0;
359 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
361 MSG_WAR(0x3A25, "init SDO line nb : ", line);
362 if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
367 d->transfers[line].nodeId = nodeId;
368 d->transfers[line].index = index;
369 d->transfers[line].subIndex = subIndex;
370 d->transfers[line].state = state;
371 d->transfers[line].toggle = 0;
372 d->transfers[line].count = 0;
373 d->transfers[line].offset = 0;
374 d->transfers[line].dataType = 0;
375 d->transfers[line].Callback = NULL;
388 UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
393 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
394 if ( d->transfers[i].state == SDO_RESET ) {
396 d->transfers[i].whoami = whoami;
400 MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
414 UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
419 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
420 if ( (d->transfers[i].state != SDO_RESET) &&
421 (d->transfers[i].nodeId == nodeId) &&
422 (d->transfers[i].whoami == whoami) ) {
439 UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
443 err = getSDOlineOnUse(d, nodeId, whoami, &line);
445 MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
448 resetSDOline(d, line);
461 UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes)
463 if (d->transfers[line].count == 0) /* if received initiate SDO protocol with e=0 and s=0 */
466 * nbBytes = (UNS8)d->transfers[line].count - (UNS8)d->transfers[line].offset;
479 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes)
481 if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
482 MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
485 d->transfers[line].count = nbBytes;
498 UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
505 UNS32 * pwCobId = NULL;
506 UNS8 * pwNodeId = NULL;
508 MSG_WAR(0x3A38, "sendSDO",0);
509 if( !((d->nodeState == Operational) || (d->nodeState == Pre_operational ))) {
510 MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
514 /*get the server->client cobid*/
515 if ( whoami == SDO_SERVER ) {/*case server. Easy because today only one server SDO is authorized in CanFestival*/
516 offset = d->firstIndex->SDO_SVR;
518 MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
521 pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
522 MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
524 else { /*case client*/
525 /* Get the client->server cobid.*/
527 offset = d->firstIndex->SDO_CLT;
528 lastIndex = d->lastIndex->SDO_CLT;
530 MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
533 /* First, have to find at the index where is defined the communication with the server node */
534 while (offset <= lastIndex){
535 MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
536 if (d->objdict[offset].bSubCount <= 3) {
537 MSG_ERR(0x1A28, "Subindex 3 not found at index ", 0x1280 + sdoNum);
540 pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
541 MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
542 if(*pwNodeId == sdo.nodeId) {
550 MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
553 /* Second, read the cobid client->server */
554 pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
556 /* message copy for sending */
557 m.cob_id.w = *pwCobId;
558 m.rtr = NOT_A_REQUEST;
559 /* the length of SDO must be 8 */
561 for (i = 0 ; i < 8 ; i++) {
562 m.data[i] = sdo.body.data[i];
564 return canSend(d->canHandle,&m);
578 UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode)
582 MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
583 sdo.nodeId = *d->bDeviceNodeId;
584 sdo.body.data[0] = 0x80;
586 sdo.body.data[1] = index & 0xFF; /* LSB */
587 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
589 sdo.body.data[3] = subIndex;
591 sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
592 sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
593 sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
594 sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
595 ret = sendSDO(d, whoami, sdo);
608 UNS8 proceedSDO (CO_Data* d, Message *m)
612 UNS8 nbBytes; /* received or to be transmited. */
613 UNS8 nodeId = 0; /* The node from which the SDO is received */
614 UNS8 *pNodeId = NULL;
615 UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
616 UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
617 s_SDO sdo; /* SDO to transmit */
622 UNS32 * pCobId = NULL;
626 MSG_WAR(0x3A60, "proceedSDO ", 0);
627 whoami = SDO_UNKNOWN;
628 /* Looking for the cobId in the object dictionary. */
629 /* Am-I a server ? */
630 offset = d->firstIndex->SDO_SVR;
631 lastIndex = d->lastIndex->SDO_SVR;
633 if(offset) while (offset <= lastIndex) {
634 if (d->objdict[offset].bSubCount <= 1) {
635 MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);
638 pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
639 if ( *pCobId == (*m).cob_id.w ) {
641 MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
642 /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
643 /* 0x1200 where the cobid received is defined. */
650 if (whoami == SDO_UNKNOWN) {
652 offset = d->firstIndex->SDO_CLT;
653 lastIndex = d->lastIndex->SDO_CLT;
655 if(offset) while (offset <= lastIndex) {
656 if (d->objdict[offset].bSubCount <= 3) {
657 MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
660 /* a) Looking for the cobid received. */
661 pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
662 if (*pCobId == (*m).cob_id.w ) {
663 /* b) cobid found, so reading the node id of the server. */
664 pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
667 MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
668 MSG_WAR(0x3A65, " Server nodeId : ", nodeId);
675 if (whoami == SDO_UNKNOWN) {
676 return 0xFF;/* This SDO was not for us ! */
679 /* Test if the size of the SDO is ok */
680 if ( (*m).len != 8) {
681 MSG_ERR(0x1A67, "Error size SDO. CobId : ", (*m).cob_id.w);
682 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
686 if (whoami == SDO_CLIENT) {
687 MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
690 MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", (*m).cob_id.w);
693 /* Testing the command specifier */
694 /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
695 /* cs = other : Not allowed -> abort. */
696 switch (getSDOcs(m->data[0])) {
700 if (whoami == SDO_SERVER) {
701 /* Receiving a download segment data. */
702 /* A SDO transfert should have been yet initiated. */
703 err = getSDOlineOnUse( d, nodeId, whoami, &line );
705 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
707 MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
709 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
712 /* Reset the wathdog */
713 RestartSDO_TIMER(line)
714 MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
715 index = d->transfers[line].index;
716 subIndex = d->transfers[line].subIndex;
718 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
719 MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
720 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
723 /* Nb of data to be downloaded */
724 nbBytes = 7 - getSDOn3(m->data[0]);
725 /* Store the data in the transfert structure. */
726 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
728 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
731 /* Sending the SDO response, CS = 1 */
732 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
733 sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
734 for (i = 1 ; i < 8 ; i++)
735 sdo.body.data[i] = 0;
736 MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
737 sendSDO(d, whoami, sdo);
738 /* Inverting the toggle for the next segment. */
739 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
740 /* If it was the last segment, */
741 if (getSDOc(m->data[0])) {
742 /* Transfering line data to object dictionary. */
743 /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
744 errorCode = SDOlineToObjdict(d, line);
746 MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
747 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
750 /* Release of the line */
751 resetSDOline(d, line);
752 MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
754 } /* end if SERVER */
755 else { /* if CLIENT */
757 /* It is a request for a previous upload segment. We should find a line opened for this.*/
758 err = getSDOlineOnUse( d, nodeId, whoami, &line);
760 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
762 MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
763 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
766 /* Reset the wathdog */
767 RestartSDO_TIMER(line)
768 index = d->transfers[line].index;
769 subIndex = d->transfers[line].subIndex;
770 /* test of the toggle; */
771 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
772 MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
773 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
776 /* nb of data to be uploaded */
777 nbBytes = 7 - getSDOn3(m->data[0]);
778 /* Storing the data in the line structure. */
779 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
781 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
784 /* Inverting the toggle for the next segment. */
785 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
786 /* If it was the last segment,*/
787 if ( getSDOc(m->data[0])) {
788 /* Put in state finished */
789 /* The code is safe for the case e=s=0 in initiate frame. */
791 d->transfers[line].state = SDO_FINISHED;
792 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
794 MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
796 else { /* more segments to receive */
797 /* Sending the request for the next segment. */
799 sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
800 for (i = 1 ; i < 8 ; i++)
801 sdo.body.data[i] = 0;
802 sendSDO(d, whoami, sdo);
803 MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
805 } /* End if CLIENT */
810 /* Receive of an initiate download */
811 if (whoami == SDO_SERVER) {
812 index = getSDOindex(m->data[1],m->data[2]);
813 subIndex = getSDOsubIndex(m->data[3]);
814 MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
816 MSG_WAR(0x3A80, "Writing at index : ", index);
817 MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
819 /* Search if a SDO transfert have been yet initiated */
820 err = getSDOlineOnUse( d, nodeId, whoami, &line );
822 MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
823 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
826 /* No line on use. Great ! */
827 /* Try to open a new line. */
828 err = getSDOfreeLine( d, whoami, &line );
830 MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
831 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
834 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
836 if (getSDOe(m->data[0])) { /* If SDO expedited */
837 /* nb of data to be downloaded */
838 nbBytes = 4 - getSDOn2(m->data[0]);
839 /* Storing the data in the line structure. */
840 d->transfers[line].count = nbBytes;
841 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
844 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
848 /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
849 /*The line will be reseted when it is downloading in the dictionary. */
850 MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
851 /* Transfering line data to object dictionary. */
852 errorCode = SDOlineToObjdict(d, line);
854 MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
855 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
858 /* Release of the line. */
859 resetSDOline(d, line);
861 else {/* So, if it is not an expedited transfert */
862 if (getSDOs(m->data[0])) {
863 /* TODO : if e and s = 0, not reading m->data[4] but put nbBytes = 0 */
864 nbBytes = m->data[4]; /* Transfert limited to 255 bytes. */
865 err = setSDOlineRestBytes(d, nodeId, nbBytes);
867 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
872 /*Sending a SDO, cs=3*/
873 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
874 sdo.body.data[0] = 3 << 5;
875 sdo.body.data[1] = index & 0xFF; /* LSB */
876 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
877 sdo.body.data[3] = subIndex;
878 for (i = 4 ; i < 8 ; i++)
879 sdo.body.data[i] = 0;
880 sendSDO(d, whoami, sdo);
881 } /* end if I am SERVER */
884 /* It is a response for a previous download segment. We should find a line opened for this. */
885 err = getSDOlineOnUse( d, nodeId, whoami, &line);
887 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
889 MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
890 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
893 /* Reset the wathdog */
894 RestartSDO_TIMER(line)
895 index = d->transfers[line].index;
896 subIndex = d->transfers[line].subIndex;
897 /* test of the toggle; */
898 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
899 MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
900 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
904 /* End transmission or downloading next segment. We need to know if it will be the last one. */
905 getSDOlineRestBytes(d, line, &nbBytes);
907 MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
909 d->transfers[line].state = SDO_FINISHED;
910 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
913 /* At least one transfer to send. */
915 /* several segments to download.*/
916 /* code to send the next segment. (cs = 0; c = 0) */
917 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
918 sdo.nodeId = nodeId; /* The server node Id; */
919 sdo.body.data[0] = (d->transfers[line].toggle << 4);
920 err = lineToSDO(d, line, 7, sdo.body.data + 1);
922 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
928 /* code to send the last segment. (cs = 0; c = 1)*/
929 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
930 sdo.nodeId = nodeId; /* The server node Id; */
931 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
932 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
934 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
937 for (i = nbBytes + 1 ; i < 8 ; i++)
938 sdo.body.data[i] = 0;
940 MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
941 sendSDO(d, whoami, sdo);
942 } /* end if I am a CLIENT */
947 /* Receive of an initiate upload.*/
948 if (whoami == SDO_SERVER) {
949 index = getSDOindex(m->data[1],m->data[2]);
950 subIndex = getSDOsubIndex(m->data[3]);
951 MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
953 MSG_WAR(0x3A90, "Reading at index : ", index);
954 MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
955 /* Search if a SDO transfert have been yet initiated*/
956 err = getSDOlineOnUse( d, nodeId, whoami, &line );
958 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
959 MSG_WAR(0x3A93, "nodeId = ", nodeId);
960 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
963 /* No line on use. Great !*/
964 /* Try to open a new line.*/
965 err = getSDOfreeLine( d, whoami, &line );
967 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
968 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
971 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
972 /* Transfer data from dictionary to the line structure. */
973 errorCode = objdictToSDOline(d, line);
976 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
978 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
981 /* Preparing the response.*/
982 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
983 sdo.nodeId = nodeId; /* The server node Id; */
985 /* normal transfert. (segmented). */
986 /* code to send the initiate upload response. (cs = 2) */
987 sdo.body.data[0] = (2 << 5) | 1;
988 sdo.body.data[1] = index & 0xFF; /* LSB */
989 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
990 sdo.body.data[3] = subIndex;
991 sdo.body.data[4] = nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
992 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
993 /* in the object dictionary, at every index and subindex. */
994 for (i = 5 ; i < 8 ; i++)
995 sdo.body.data[i] = 0;
996 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
997 sendSDO(d, whoami, sdo);
1000 /* Expedited upload. (cs = 2 ; e = 1) */
1001 sdo.body.data[0] = (2 << 5) | ((4 - nbBytes) << 2) | 3;
1002 sdo.body.data[1] = index & 0xFF; /* LSB */
1003 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1004 sdo.body.data[3] = subIndex;
1005 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
1007 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1010 for (i = 4 + nbBytes ; i < 8 ; i++)
1011 sdo.body.data[i] = 0;
1012 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1014 sendSDO(d, whoami, sdo);
1015 /* Release the line.*/
1016 resetSDOline(d, line);
1018 } /* end if I am SERVER*/
1021 /* It is the response for the previous initiate upload request.*/
1022 /* We should find a line opened for this. */
1023 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1025 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1027 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1028 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1031 /* Reset the wathdog */
1032 RestartSDO_TIMER(line)
1033 index = d->transfers[line].index;
1034 subIndex = d->transfers[line].subIndex;
1036 if (getSDOe(m->data[0])) { /* If SDO expedited */
1037 /* nb of data to be uploaded */
1038 nbBytes = 4 - getSDOn2(m->data[0]);
1039 /* Storing the data in the line structure. */
1040 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1042 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1045 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1046 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1048 d->transfers[line].count = nbBytes;
1049 d->transfers[line].state = SDO_FINISHED;
1050 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1053 else { /* So, if it is not an expedited transfert */
1054 /* Storing the nb of data to receive. */
1055 if (getSDOs(m->data[0])) {
1056 nbBytes = m->data[4]; /* Remember the limitation to 255 bytes to transfert */
1057 err = setSDOlineRestBytes(d, line, nbBytes);
1059 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1063 /* Requesting next segment. (cs = 3) */
1064 sdo.nodeId = nodeId;
1065 sdo.body.data[0] = 3 << 5;
1066 for (i = 1 ; i < 8 ; i++)
1067 sdo.body.data[i] = 0;
1068 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1069 sendSDO(d, whoami, sdo);
1071 } /* End if CLIENT */
1076 if (whoami == SDO_SERVER) {
1077 /* Receiving a upload segment. */
1078 /* A SDO transfert should have been yet initiated. */
1079 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1081 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1083 MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
1085 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1088 /* Reset the wathdog */
1089 RestartSDO_TIMER(line)
1090 MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
1091 index = d->transfers[line].index;
1092 subIndex = d->transfers[line].subIndex;
1094 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
1095 MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
1096 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
1099 /* Uploading next segment. We need to know if it will be the last one. */
1100 getSDOlineRestBytes(d, line, &nbBytes);
1102 /* The segment to transfer is not the last one.*/
1103 /* code to send the next segment. (cs = 0; c = 0) */
1104 sdo.nodeId = nodeId; /* The server node Id; */
1105 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1106 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1108 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1111 /* Inverting the toggle for the next tranfert. */
1112 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
1113 MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
1114 sendSDO(d, whoami, sdo);
1118 /* code to send the last segment. (cs = 0; c = 1) */
1119 sdo.nodeId = nodeId; /** The server node Id; */
1120 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1121 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1123 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1126 for (i = nbBytes + 1 ; i < 8 ; i++)
1127 sdo.body.data[i] = 0;
1128 MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
1129 sendSDO(d, whoami, sdo);
1130 /* Release the line */
1131 resetSDOline(d, line);
1133 } /* end if SERVER*/
1136 /* It is the response for the previous initiate download request. */
1137 /* We should find a line opened for this. */
1138 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1140 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
1142 MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
1143 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1146 /* Reset the watchdog */
1147 RestartSDO_TIMER(line)
1148 index = d->transfers[line].index;
1149 subIndex = d->transfers[line].subIndex;
1150 /* End transmission or requesting next segment. */
1151 getSDOlineRestBytes(d, line, &nbBytes);
1153 MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
1155 d->transfers[line].state = SDO_FINISHED;
1156 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1160 /* more than one request to send */
1161 /* code to send the next segment. (cs = 0; c = 0) */
1162 sdo.nodeId = nodeId; /** The server node Id; */
1163 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1164 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1166 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1172 /* code to send the last segment. (cs = 0; c = 1) */
1173 sdo.nodeId = nodeId; /* The server node Id; */
1174 sdo.body.data[0] = (d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1;
1175 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1177 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1180 for (i = nbBytes + 1 ; i < 8 ; i++)
1181 sdo.body.data[i] = 0;
1183 MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
1184 sendSDO(d, whoami, sdo);
1186 } /* end if I am a CLIENT */
1190 abortCode = (*m).data[3] |
1191 ((UNS32)m->data[5] << 8) |
1192 ((UNS32)m->data[6] << 16) |
1193 ((UNS32)m->data[7] << 24);
1194 /* Received SDO abort. */
1195 /* Looking for the line concerned. */
1196 if (whoami == SDO_SERVER) {
1197 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1199 resetSDOline( d, line );
1200 MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
1203 MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1204 /* Tips : The end user has no way to know that the server node has received an abort SDO. */
1205 /* Its is ok, I think.*/
1207 else { /* If I am CLIENT */
1208 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1210 /* The line *must* be released by the core program. */
1212 d->transfers[line].state = SDO_ABORTED_RCV;
1213 d->transfers[line].abortCode = abortCode;
1214 MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
1215 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1218 MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1222 /* Error : Unknown cs */
1223 MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
1245 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1246 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1251 s_SDO sdo; /* SDO to transmit */
1255 UNS8 *pNodeIdServer;
1258 MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
1259 MSG_WAR(0x3AC1, " At index : ", index);
1260 MSG_WAR(0x3AC2, " subIndex : ", subIndex);
1261 MSG_WAR(0x3AC3, " nb bytes : ", count);
1263 /* Verify that there is no SDO communication yet. */
1264 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1266 MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
1269 /* Taking the line ... */
1270 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1272 MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1275 /* Check which SDO to use to communicate with the node */
1276 offset = d->firstIndex->SDO_CLT;
1277 lastIndex = d->lastIndex->SDO_CLT;
1279 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1283 while (offset <= lastIndex) {
1284 if (d->objdict[offset].bSubCount <= 3) {
1285 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1288 /* looking for the nodeId server */
1289 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1290 nodeIdServer = *pNodeIdServer;
1291 MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
1292 MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
1294 if(nodeIdServer == nodeId) {
1302 MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
1305 MSG_WAR(0x3AD0," SDO client defined at index : ", 0x1280 + i);
1306 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
1307 d->transfers[line].count = count;
1308 d->transfers[line].dataType = dataType;
1310 /* Copy data to transfers structure. */
1311 for (j = 0 ; j < count ; j++) {
1312 # ifdef CANOPEN_BIG_ENDIAN
1313 if (dataType == 0 && endianize)
1314 d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
1315 else /* String of bytes. */
1316 d->transfers[line].data[j] = ((char *)data)[j];
1318 d->transfers[line].data[j] = ((char *)data)[j];
1321 /* Send the SDO to the server. Initiate download, cs=1. */
1322 sdo.nodeId = nodeId;
1323 if (count <= 4) { /* Expedited transfert */
1324 sdo.body.data[0] = (1 << 5) | ((4 - count) << 2) | 3;
1325 for (i = 4 ; i < 8 ; i++)
1326 sdo.body.data[i] = d->transfers[line].data[i - 4];
1327 d->transfers[line].offset = count;
1329 else { /** Normal transfert */
1330 sdo.body.data[0] = (1 << 5) | 1;
1331 sdo.body.data[4] = count; /* nb of byte to transmit. Max = 255. (canfestival2 limitation). */
1332 for (i = 5 ; i < 8 ; i++)
1333 sdo.body.data[i] = 0;
1335 sdo.body.data[1] = index & 0xFF; /* LSB */
1336 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1337 sdo.body.data[3] = subIndex;
1339 d->transfers[line].Callback = Callback;
1341 err = sendSDO(d, SDO_CLIENT, sdo);
1343 MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
1344 /* release the line */
1345 resetSDOline(d, line);
1366 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1367 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data)
1369 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
1386 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
1387 UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback)
1389 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1404 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1410 s_SDO sdo; /* SDO to transmit */
1411 UNS8 *pNodeIdServer;
1415 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1416 MSG_WAR(0x3AD6, " At index : ", index);
1417 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1420 /* Verify that there is no SDO communication yet. */
1421 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1423 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1426 /* Taking the line ... */
1427 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1429 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1433 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1435 /* Check which SDO to use to communicate with the node */
1436 offset = d->firstIndex->SDO_CLT;
1437 lastIndex = d->lastIndex->SDO_CLT;
1439 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1443 while (offset <= lastIndex) {
1444 if (d->objdict[offset].bSubCount <= 3) {
1445 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1448 /* looking for the nodeId server */
1449 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1450 nodeIdServer = *pNodeIdServer;
1452 if(nodeIdServer == nodeId) {
1460 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1463 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1464 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1465 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1466 sdo.nodeId = nodeId;
1467 /* Send the SDO to the server. Initiate upload, cs=2. */
1468 d->transfers[line].dataType = dataType;
1469 sdo.body.data[0] = (2 << 5);
1470 sdo.body.data[1] = index & 0xFF; /* LSB */
1471 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1472 sdo.body.data[3] = subIndex;
1473 for (i = 4 ; i < 8 ; i++)
1474 sdo.body.data[i] = 0;
1475 d->transfers[line].Callback = Callback;
1476 err = sendSDO(d, SDO_CLIENT, sdo);
1478 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1479 /* release the line */
1480 resetSDOline(d, line);
1497 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
1499 return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
1514 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1516 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1530 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS8 *size,
1538 /* Looking for the line tranfert. */
1539 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1541 MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
1542 return SDO_ABORTED_INTERNAL;
1544 if (d->transfers[line].state != SDO_FINISHED)
1545 return d->transfers[line].state;
1547 /* Transfert is finished. Put the value in the data. */
1548 * size = (UNS8)d->transfers[line].count;
1549 for ( i = 0 ; i < *size ; i++) {
1550 # ifdef CANOPEN_BIG_ENDIAN
1551 if (d->transfers[line].dataType != visible_string)
1552 ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
1553 else /* String of bytes. */
1554 ( (char *) data)[i] = d->transfers[line].data[i];
1556 ( (char *) data)[i] = d->transfers[line].data[i];
1559 return SDO_FINISHED;
1571 UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
1577 /* Looking for the line tranfert. */
1578 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1580 MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
1581 return SDO_ABORTED_INTERNAL;
1583 * abortCode = d->transfers[line].abortCode;
1584 return d->transfers[line].state;