CHANGE: SDO block mode added, without CRC support
authorfbeaulier
Mon, 29 Aug 2011 16:59:55 +0200
changeset 664 a03f0aa7d219
parent 663 70fc3603e36f
child 665 90e6cf84a0d7
CHANGE: SDO block mode added, without CRC support
WARNING : API change in client functions
configure
examples/CANOpenShell/CANOpenShell.c
examples/TestMasterMicroMod/TestMasterMicroMod.c
examples/TestMasterSlave/Master.c
include/data.h
include/def.h
include/sdo.h
src/sdo.c
--- a/configure	Tue Aug 16 14:15:52 2011 +0200
+++ b/configure	Mon Aug 29 16:59:55 2011 +0200
@@ -32,6 +32,10 @@
 #For a normal transfert, (usually for a string), put the maximum string size to transfer.
 SDO_MAX_LENGTH_TRANSFERT=32
 
+# For block transfert, number of segments transmitted at once.
+# SDO_BLOCK_SIZE CAN frames must fit into the CAN Tx buffer
+SDO_BLOCK_SIZE=16
+
 # Number of SDO from differents nodes that the node can manage concurrently.
 #for a slave node, usually put 1.
 SDO_MAX_SIMULTANEOUS_TRANSFERTS=4
@@ -122,6 +126,7 @@
 	--debug=*)	DEBUG=$optarg;;
 	--MAX_CAN_BUS_ID=*)	MAX_CAN_BUS_ID=$optarg;;
 	--SDO_MAX_LENGTH_TRANSFERT=*)	SDO_MAX_LENGTH_TRANSFERT=$optarg;;
+	--SDO_BLOCK_SIZE=*)	SDO_BLOCK_SIZE=$optarg;;
 	--SDO_MAX_SIMULTANEOUS_TRANSFERTS=*)	SDO_MAX_SIMULTANEOUS_TRANSFERTS=$optarg;;
 	--NMT_MAX_NODE_ID=*)	NMT_MAX_NODE_ID=$optarg;;
 	--SDO_TIMEOUT_MS=*)	SDO_TIMEOUT_MS=$optarg;;
@@ -179,6 +184,7 @@
 		echo	"Stack compilation constants"
 		echo	" --MAX_CAN_BUS_ID [=1] Number of can bus to use"
 		echo	" --SDO_MAX_LENGTH_TRANSFERT [=32] max bytes to transmit by SDO"
+		echo	" --SDO_BLOCK_SIZE [=16] max CAN frames transmitted at once for block transfert"
 		echo	" --SDO_MAX_SIMULTANEOUS_TRANSFERTS [=4] Number of SDO that the node can manage concurrently"
 		echo	" --NMT_MAX_NODE_ID [=128] can be reduced to gain memory on small network"
 		echo	" --SDO_TIMEOUT_MS [=3000] Timeout in milliseconds for SDO (None to disable the feature)"
@@ -657,6 +663,7 @@
 for i in \
  MAX_CAN_BUS_ID\
  SDO_MAX_LENGTH_TRANSFERT\
+ SDO_BLOCK_SIZE\
  SDO_MAX_SIMULTANEOUS_TRANSFERTS\
  NMT_MAX_NODE_ID\
  SDO_TIMEOUT_MS\
--- a/examples/CANOpenShell/CANOpenShell.c	Tue Aug 16 14:15:52 2011 +0200
+++ b/examples/CANOpenShell/CANOpenShell.c	Mon Aug 29 16:59:55 2011 +0200
@@ -136,19 +136,19 @@
 				printf("##################################\n");
 				printf("#### Informations for node %x ####\n", nodeid);
 				printf("##################################\n");
-				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1000, 0x00, 0, CheckReadInfoSDO);
+				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1000, 0x00, 0, CheckReadInfoSDO, 0);
 				break;
 
 			case 2: /* Get Vendor ID */
-				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x01, 0, CheckReadInfoSDO);
+				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x01, 0, CheckReadInfoSDO, 0);
 				break;
 
 			case 3: /* Get Product Code */
-				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x02, 0, CheckReadInfoSDO);
+				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x02, 0, CheckReadInfoSDO, 0);
 				break;
 
 			case 4: /* Get Revision Number */
-				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x03, 0, CheckReadInfoSDO);
+				readNetworkDictCallback(CANOpenShellOD_Data, nodeid, 0x1018, 0x03, 0, CheckReadInfoSDO, 0);
 				break;
 
 			case 5: /* Print node info */
@@ -192,7 +192,7 @@
 		printf("Index    : %4.4x\n", index);
 		printf("SubIndex : %2.2x\n", subindex);
 
-		readNetworkDictCallback(CANOpenShellOD_Data, (UNS8)nodeid, (UNS16)index, (UNS8)subindex, (UNS8)datatype, CheckReadSDO);
+		readNetworkDictCallback(CANOpenShellOD_Data, (UNS8)nodeid, (UNS16)index, (UNS8)subindex, (UNS8)datatype, CheckReadSDO, 0);
 	}
 	else
 		printf("Wrong command  : %s\n", sdo);
@@ -234,7 +234,7 @@
 		printf("Size     : %2.2x\n", size);
 		printf("Data     : %x\n", data);
 
-		writeNetworkDictCallBack(CANOpenShellOD_Data, nodeid, index, subindex, size, 0, &data, CheckWriteSDO);
+		writeNetworkDictCallBack(CANOpenShellOD_Data, nodeid, index, subindex, size, 0, &data, CheckWriteSDO, 0);
 	}
 	else
 		printf("Wrong command  : %s\n", sdo);
--- a/examples/TestMasterMicroMod/TestMasterMicroMod.c	Tue Aug 16 14:15:52 2011 +0200
+++ b/examples/TestMasterMicroMod/TestMasterMicroMod.c	Mon Aug 29 16:59:55 2011 +0200
@@ -135,7 +135,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 
@@ -152,7 +153,8 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&Transmission_Type,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 
@@ -169,7 +171,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 					
@@ -186,7 +189,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 
@@ -204,7 +208,8 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&Transmission_Type,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}	
 		break;
 
@@ -221,7 +226,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 		
@@ -238,7 +244,8 @@
 					2, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&Heartbeat_Producer_Time,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 
@@ -255,7 +262,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;
 
@@ -272,7 +280,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}
 		break;			
 
@@ -289,7 +298,8 @@
 					4, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&TPDO_COBId,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 		}			
 		break;			
 		
--- a/examples/TestMasterSlave/Master.c	Tue Aug 16 14:15:52 2011 +0200
+++ b/examples/TestMasterSlave/Master.c	Mon Aug 29 16:59:55 2011 +0200
@@ -119,7 +119,8 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&Transmission_Type,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 					break;
 		
 		case 2:	/*Second step*/
@@ -131,7 +132,8 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&Transmission_Type,/*void *data*/
-					CheckSDOAndContinue); /*SDOCallback_t Callback*/
+					CheckSDOAndContinue, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 					break;
 		case 3: 
 		
@@ -220,8 +222,9 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&transmitiontype,/*void *data*/
-					CheckSDO); /*SDOCallback_t Callback*/
-	}
+					CheckSDO, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
+	}   
 	if(MasterSyncCount % 50 == 25){
 		UNS8 transmitiontype = 0x00;
 		eprintf("Master : Change slave's transmit type to 0x00\n");
@@ -232,7 +235,8 @@
 					1, /*UNS8 count*/
 					0, /*UNS8 dataType*/
 					&transmitiontype,/*void *data*/
-					CheckSDO); /*SDOCallback_t Callback*/
+					CheckSDO, /*SDOCallback_t Callback*/
+                    0); /* use block mode */
 	}
 	MasterSyncCount++;
 }
--- a/include/data.h	Tue Aug 16 14:15:52 2011 +0200
+++ b/include/data.h	Mon Aug 29 16:59:55 2011 +0200
@@ -95,7 +95,7 @@
 	post_sync_t post_sync;
 	post_TPDO_t post_TPDO;
 	post_SlaveBootup_t post_SlaveBootup;
-  post_SlaveStateChange_t post_SlaveStateChange;
+    post_SlaveStateChange_t post_SlaveStateChange;
 	
 	/* General */
 	UNS8 toggle;
@@ -130,7 +130,7 @@
 
 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
 #define s_transfer_Initializer {\
-		0,          /* nodeId */\
+		0,          /* CliServNbr */\
 		0,          /* wohami */\
 		SDO_RESET,  /* state */\
 		0,          /* toggle */\
@@ -142,6 +142,15 @@
 		{0},        /* data (static use, so that all the table is initialize at 0)*/\
     NULL,       /* dynamicData */ \
     0,          /* dynamicDataSize */ \
+		0,          /* peerCRCsupport */\
+		0,          /* blksize */\
+		0,          /* ackseq */\
+		0,          /* objsize */\
+		0,          /* lastblockoffset */\
+		0,          /* seqno */\
+		0,          /* endfield */\
+		RXSTEP_INIT,/* rxstep */\
+		{0},        /* tmpData */\
 		0,          /* dataType */\
 		-1,         /* timer */\
 		NULL        /* Callback */\
@@ -158,9 +167,18 @@
 		0,          /* count */\
 		0,          /* offset */\
 		{0},        /* data (static use, so that all the table is initialize at 0)*/\
-		0,          /* dataType */\
-		-1,         /* timer */\
-		NULL        /* Callback */\
+		0,          /* peerCRCsupport */\
+		0,          /* blksize */\
+		0,          /* ackseq */\
+		0,          /* objsize */\
+		0,          /* lastblockoffset */\
+		0,          /* seqno */\
+		0,          /* endfield */\
+		RXSTEP_INIT,/* rxstep */\
+		{0},        /* tmpData */\
+		0,          /*  */\
+		-1,         /*  */\
+		NULL        /*  */\
 	  },
 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 
--- a/include/def.h	Tue Aug 16 14:15:52 2011 +0200
+++ b/include/def.h	Mon Aug 29 16:59:55 2011 +0200
@@ -75,6 +75,12 @@
 #define	SDO_ABORTED_INTERNAL     0x85     /* Aborted but not because of an abort message. */
 #define	SDO_DOWNLOAD_IN_PROGRESS 0x2 
 #define	SDO_UPLOAD_IN_PROGRESS   0x3   
+#define	SDO_BLOCK_DOWNLOAD_IN_PROGRESS 0x4 
+#define	SDO_BLOCK_UPLOAD_IN_PROGRESS   0x5
+
+/** getReadResultNetworkDict may return any of above status value or this one
+ */
+#define SDO_PROVIDED_BUFFER_TOO_SMALL   0x8A
 
 /* Status of the node during the SDO transfert : */
 #define SDO_SERVER  0x1
@@ -87,6 +93,8 @@
 #define INITIATE_UPLOAD_REQUEST      2
 #define UPLOAD_SEGMENT_REQUEST       3
 #define ABORT_TRANSFER_REQUEST       4
+#define BLOCK_UPLOAD_REQUEST         5
+#define BLOCK_DOWNLOAD_REQUEST       6
 
 /* SDOtx scs: server command specifier */
 #define UPLOAD_SEGMENT_RESPONSE      0
@@ -94,7 +102,27 @@
 #define INITIATE_DOWNLOAD_RESPONSE   3
 #define INITIATE_UPLOAD_RESPONSE     2
 #define ABORT_TRANSFER_REQUEST       4
+#define BLOCK_DOWNLOAD_RESPONSE    	 5
+#define BLOCK_UPLOAD_RESPONSE        6
 
+/* SDO block upload client subcommand */
+#define SDO_BCS_INITIATE_UPLOAD_REQUEST 0
+#define SDO_BCS_END_UPLOAD_REQUEST      1
+#define SDO_BCS_UPLOAD_RESPONSE         2
+#define SDO_BCS_START_UPLOAD            3
+
+/* SDO block upload server subcommand */
+#define SDO_BSS_INITIATE_UPLOAD_RESPONSE 0
+#define SDO_BSS_END_UPLOAD_RESPONSE      1
+
+/* SDO block download client subcommand */
+#define SDO_BCS_INITIATE_DOWNLOAD_REQUEST 0
+#define SDO_BCS_END_DOWNLOAD_REQUEST      1
+
+/* SDO block download server subcommand */
+#define SDO_BSS_INITIATE_DOWNLOAD_RESPONSE 0
+#define SDO_BSS_END_DOWNLOAD_RESPONSE      1
+#define SDO_BSS_DOWNLOAD_RESPONSE          2
 
 /*  Function Codes 
    ---------------
--- a/include/sdo.h	Tue Aug 16 14:15:52 2011 +0200
+++ b/include/sdo.h	Mon Aug 29 16:59:55 2011 +0200
@@ -38,12 +38,19 @@
 
 #include "timer.h"
 
+/* Block mode : Data consumer receive step 
+ * - set to RXSTEP_STARTED when client receive initiate upload response 
+ * - set to RXSTEP_END when last segment of a block received 
+ */
+typedef enum {RXSTEP_INIT, RXSTEP_STARTED, RXSTEP_END } rxStep_t;
+
 typedef void (*SDOCallback_t)(CO_Data* d, UNS8 nodeId);
 
 /* The Transfer structure
 Used to store the different segments of
  - a SDO received before writing in the dictionary
  - the reading of the dictionary to put on a SDO to transmit
+WARNING : after a change in this structure check the macro s_transfer_Initializer in data.h
 */
 
 struct struct_s_transfer {
@@ -69,6 +76,17 @@
   UNS8           *dynamicData;
   UNS32          dynamicDataSize;
 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+                                    
+  UNS8           peerCRCsupport;    /**< True if peer supports CRC */
+  UNS8           blksize;           /**< Number of segments per block with 0 < blksize < 128 */
+  UNS8           ackseq;            /**< sequence number of last segment that was received successfully */
+  UNS32          objsize;           /**< Size in bytes of the object provided by data producer */
+  UNS8           lastblockoffset;   /**< Value of offset before last block */
+  UNS8           seqno;             /**< Last sequence number received OK or transmitted */   
+  UNS8           endfield;          /**< nbr of bytes in last segment of last block that do not contain data */
+  rxStep_t       rxstep;            /**< data consumer receive step - set to true when last segment of a block received */
+  UNS8           tmpData[8];        /**< temporary segment storage */
+
   UNS8           dataType;   /**< Defined in objdictdef.h Value is visible_string
                               * if it is a string, any other value if it is not a string,
                               * like 0. In fact, it is used only if client.
@@ -86,22 +104,6 @@
 
 #include "data.h"
 
-#if 0
-struct BODY{
-    UNS8 data[8]; /**< The 8 bytes data of the SDO */
-};
-
-/* The SDO structure ...*/
-struct struct_s_SDO {
-  UNS8 nodeId;		/**< In any case, Node ID of the server (case sender or receiver).*/
-  struct BODY body;
-};
-
-
-typedef struct struct_s_SDO s_SDO;
-
-#endif
-
 /** 
  * @brief Reset of a SDO exchange on timeout.
  * Send a SDO abort.
@@ -307,7 +309,7 @@
  * - 0xFF is returned when error occurs.
  */
 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
-		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data);
+		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode);
 
 /** 
  * @ingroup sdo
@@ -328,7 +330,7 @@
  * - 0xFF is returned when error occurs.
  */
 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
-		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback);
+		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 useBlockMode);
 
 /**
  * @ingroup sdo 
@@ -352,7 +354,7 @@
  * - 0xFF is returned when error occurs.
  */
 UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
-		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+		       UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode);
 
 /**
  * @ingroup sdo 
@@ -367,7 +369,7 @@
  * - 0xFE is returned when no sdo client to communicate with node.
  * - 0xFF is returned when error occurs.
  */
-UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType);
+UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, UNS8 useBlockMode);
 
 /** 
  * @ingroup sdo
@@ -385,7 +387,7 @@
  * - 0xFE is returned when no sdo client to communicate with node.
  * - 0xFF is returned when error occurs.
  */
-UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback);
+UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
 
 /** 
  * @ingroup sdo
@@ -403,7 +405,7 @@
  * - 0 is returned upon success.
  * - 0xFF is returned when error occurs.
  */
-UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback);
+UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
 
 /** 
  * @ingroup sdo
@@ -411,8 +413,9 @@
  * 
  * @param *d Pointer to a CAN object data structure
  * @param nodeId Node Id of the slave
- * @param *data Pointer to the datas
- * @param *size Pointer to the size
+ * @param *data Pointer to the buffer to get the data
+ * @param *size Pointer to the size : MUST contain the size of the buffer before calling
+ *                                    The function set it to the actual number of written bytes
  * @param *abortCode Pointer to the abortcode. (0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV)
  * 
  * 
@@ -422,6 +425,7 @@
  *           - SDO_ABORTED_INTERNAL     // Transfert failed (internal abort)
  *           - SDO_UPLOAD_IN_PROGRESS   // Datas are not yet available
  *           - SDO_DOWNLOAD_IN_PROGRESS // Download is in progress
+ *           - SDO_PROVIDED_BUFFER_TOO_SMALL //The value *size is not enough to store the received data
  * \n\n
  * example :
  * @code
--- a/src/sdo.c	Tue Aug 16 14:15:52 2011 +0200
+++ b/src/sdo.c	Mon Aug 29 16:59:55 2011 +0200
@@ -62,7 +62,7 @@
  ** @return
  **/
 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
-		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode);
 
 /*!
  ** Called by readNetworkDict
@@ -77,7 +77,7 @@
  ** @return
  **/
 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
-		UNS8 dataType, SDOCallback_t Callback);
+		UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
 
 
 /***************************************************************************/
@@ -119,6 +119,11 @@
 */
 #define getSDOsubIndex(byte3) (byte3)
 
+/** Returns the subcommand in SDO block transfert
+*/
+#define getSDOblockSC(byte) (byte & 3)
+
+
 /*!
  **
  **
@@ -136,9 +141,9 @@
 	}
 	nodeId = *((UNS32*) d->objdict[offset+d->transfers[id].CliServNbr].pSubindex[3].pObject);
 	MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
-	MSG_WAR(0x2A02, "server node : ", NodeId);
-	MSG_WAR(0x2A02, "      index : ", d->transfers[id].index);
-	MSG_WAR(0x2A02, "   subIndex : ", d->transfers[id].subIndex);
+	MSG_WAR(0x2A02, "server node id : ", nodeId);
+	MSG_WAR(0x2A02, "         index : ", d->transfers[id].index);
+	MSG_WAR(0x2A02, "      subIndex : ", d->transfers[id].subIndex);
 	/* Reset timer handler */
 	d->transfers[id].timer = TIMER_NONE;
 	/*Set aborted state*/
@@ -402,6 +407,7 @@
 	if ((! err) && (whoami == SDO_CLIENT)) {
 		StopSDO_TIMER(line);
 		d->transfers[line].state = SDO_ABORTED_INTERNAL;
+		d->transfers[line].abortCode = abortCode;
 	}
 	MSG_WAR(0x3A22, "Sending SDO abort ", 0);
 	err = sendSDOabort(d, whoami, CliServNbr, index, subIndex, abortCode);
@@ -427,11 +433,6 @@
 		d->transfers[line].data[i] = 0;
 	d->transfers[line].whoami = 0;
 	d->transfers[line].abortCode = 0;
-#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
-	free(d->transfers[line].dynamicData);
-	d->transfers[line].dynamicData = 0;
-	d->transfers[line].dynamicDataSize = 0;
-#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 }
 
 /*!
@@ -449,7 +450,8 @@
 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS8 state)
 {
 	MSG_WAR(0x3A25, "init SDO line nb : ", line);
-	if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
+	if (state == SDO_DOWNLOAD_IN_PROGRESS       || state == SDO_UPLOAD_IN_PROGRESS ||
+        state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS || state == SDO_BLOCK_UPLOAD_IN_PROGRESS){
 		StartSDO_TIMER(line)
 	}else{
 		StopSDO_TIMER(line)
@@ -461,6 +463,14 @@
 	d->transfers[line].toggle = 0;
 	d->transfers[line].count = 0;
 	d->transfers[line].offset = 0;
+    d->transfers[line].peerCRCsupport = 0;
+    d->transfers[line].blksize = 0;
+    d->transfers[line].ackseq = 0;
+    d->transfers[line].objsize = 0;
+    d->transfers[line].lastblockoffset = 0;
+    d->transfers[line].seqno = 0;
+    d->transfers[line].endfield = 0;
+    d->transfers[line].rxstep = RXSTEP_INIT;
 	d->transfers[line].dataType = 0;
 	d->transfers[line].Callback = NULL;
 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
@@ -643,7 +653,7 @@
 			return 0xFF;
 		}
 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[2].pObject);
-		MSG_WAR(0x3A41, "I am server cobId : ", m.cob_id);
+		MSG_WAR(0x3A41, "I am server Tx cobId : ", m.cob_id);
 	}
 	else {			/*case client*/
 		/* Get the client->server cobid.*/
@@ -653,7 +663,7 @@
 			return 0xFF;
 		}
 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[1].pObject);
-		MSG_WAR(0x3A41, "I am client cobId : ", m.cob_id);
+		MSG_WAR(0x3A41, "I am client Tx cobId : ", m.cob_id);
 	}
 	/* message copy for sending */
 	m.rtr = NOT_A_REQUEST;
@@ -709,6 +719,7 @@
 UNS8 proceedSDO (CO_Data* d, Message *m)
 {
 	UNS8 err;
+	UNS8 cs;
 	UNS8 line;
 	UNS32 nbBytes; 		/* received or to be transmited. */
 	UNS8 nodeId = 0;  	/* The node Id of the server if client otherwise unused */
@@ -724,6 +735,10 @@
 	UNS32 *pCobId = NULL;
 	UNS16 offset;
 	UNS16 lastIndex;
+	UNS8 SubCommand;	/* Block transfert only */
+    UNS8 SeqNo;         /* Sequence number in block transfert */
+    UNS8 AckSeq;        /* Sequence number of last segment that was received successfully */
+	UNS8 NbBytesNoData; /* Number of bytes that do not contain data in last segment of block transfert */ 
 
 	MSG_WAR(0x3A60, "proceedSDO ", 0);
 	whoami = SDO_UNKNOWN;
@@ -763,7 +778,7 @@
 			pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
 			if (*pCobId == UNS16_LE(m->cob_id) ) {
 				whoami = SDO_CLIENT;
-				MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
+				MSG_WAR(0x3A64, "proceedSDO. I am client index : ", 0x1280 + j);
 				/* Defining Client number = index minus 0x1280 where the cobid received is defined. */
 				CliServNbr = j;
 				/* Reading the server node ID, if client it is mandatory in the OD */
@@ -792,17 +807,34 @@
 		MSG_WAR(0x3A69, "I am SERVER number ", CliServNbr);
 	}
 
+	/* Look for an SDO transfert already initiated. */
+	err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
+
+	/* Let's find cs value, first it is set as "not valid" */
+	cs = 0xFF; 
+	/* Special cases for block transfert : in frames with segment data cs is not spécified */
+   	if (!err) {
+		if ((whoami == SDO_SERVER) && (d->transfers[line].state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS) ||
+			(whoami == SDO_CLIENT) && (d->transfers[line].state == SDO_BLOCK_UPLOAD_IN_PROGRESS)) {		
+			if(m->data[0] == 0x80)	/* If first byte is 0x80 it is an abort frame (seqno = 0 not allowed) */
+				cs = 4;
+			else
+				cs = 6;
+		}
+	}
+	/* Other cases : cs is specified */
+	if (cs == 0xFF)
+		cs = getSDOcs(m->data[0]);
+
 	/* Testing the command specifier */
-	/* Allowed : cs = 0, 1, 2, 3, 4. (=  all except those for block tranfert). */
+	/* Allowed : cs = 0, 1, 2, 3, 4, 5, 6 */
 	/* cs = other : Not allowed -> abort. */
-	switch (getSDOcs(m->data[0])) {
+	switch (cs) {
 
 		case 0:
 			/* I am SERVER */
 			if (whoami == SDO_SERVER) {
-				/* Receiving a download segment data. */
-				/* A SDO transfert should have been yet initiated. */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
+				/* Receiving a download segment data : an SDO transfert should have been yet initiated. */
 				if (!err)
 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
 				if (err) {
@@ -856,7 +888,6 @@
 			else { /* if CLIENT */
 				/* I am CLIENT */
 				/* It is a request for a previous upload segment. We should find a line opened for this.*/
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
 				if (!err)
 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
 				if (err) {
@@ -917,7 +948,6 @@
 				MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
 
 				/* Search if a SDO transfert have been yet initiated */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
 				if (! err) {
 					MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
 					failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
@@ -980,7 +1010,6 @@
 			else {
 				/* I am CLIENT */
 				/* It is a response for a previous download segment. We should find a line opened for this. */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
 				if (!err)
 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
 				if (err) {
@@ -1049,7 +1078,6 @@
 				MSG_WAR(0x3A90, "Reading at index : ", index);
 				MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
 				/* Search if a SDO transfert have been yet initiated*/
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
 				if (! err) {
 					MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
 					MSG_WAR(0x3A93, "Server Nbr = ", CliServNbr);
@@ -1083,12 +1111,11 @@
 					data[1] = index & 0xFF;        /* LSB */
 					data[2] = (index >> 8) & 0xFF; /* MSB */
 					data[3] = subIndex;
-					data[4] = (UNS8)nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
-					/* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
-					/* in the object dictionary, at every index and subindex. */
-					for (i = 5 ; i < 8 ; i++)
-						data[i] = 0;
-					MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
+					data[4] = nbBytes; 
+					data[5] = nbBytes >> 8; 
+					data[6] = nbBytes >> 16; 
+					data[7] = nbBytes >> 24; 
+ 					MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
 					sendSDO(d, whoami, CliServNbr, data);
 				}
 				else {
@@ -1115,7 +1142,6 @@
 				/* I am CLIENT */
 				/* It is the response for the previous initiate upload request.*/
 				/* We should find a line opened for this. */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
 				if (!err)
 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
 				if (err) {
@@ -1170,7 +1196,6 @@
 			if (whoami == SDO_SERVER) {
 				/* Receiving a upload segment. */
 				/* A SDO transfert should have been yet initiated. */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
 				if (!err)
 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
 				if (err) {
@@ -1227,7 +1252,6 @@
 				/* I am CLIENT */
 				/* It is the response for the previous initiate download request. */
 				/* We should find a line opened for this. */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
 				if (!err)
 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
 				if (err) {
@@ -1283,9 +1307,7 @@
 				((UNS32)m->data[6] << 16) |
 				((UNS32)m->data[7] << 24);
 			/* Received SDO abort. */
-			/* Looking for the line concerned. */
 			if (whoami == SDO_SERVER) {
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
 				if (!err) {
 					resetSDOline( d, line );
 					MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
@@ -1296,7 +1318,6 @@
 				/* Its is ok, I think.*/
 			}
 			else { /* If I am CLIENT */
-				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
 				if (!err) {
 					/* The line *must* be released by the core program. */
 					StopSDO_TIMER(line)
@@ -1309,9 +1330,440 @@
 					MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
 			}
 			break;
+		case 5: /* Command specifier for data transmission - the client or server is the data producer */
+			SubCommand = getSDOblockSC(m->data[0]);
+			if (whoami == SDO_SERVER) { /* Server block upload */
+				if (SubCommand == SDO_BCS_INITIATE_UPLOAD_REQUEST) {
+				    index = getSDOindex(m->data[1],m->data[2]);
+				    subIndex = getSDOsubIndex(m->data[3]);
+				    MSG_WAR(0x3AB2, "Received SDO Initiate block upload defined at index 0x1200 + ",
+						CliServNbr);
+				    MSG_WAR(0x3AB3, "Reading at index : ", index);
+				    MSG_WAR(0x3AB4, "Reading at subIndex : ", subIndex);
+				    /* Search if a SDO transfert have been yet initiated */
+				    if (! err) {
+					    MSG_ERR(0x1A93, "SDO error : Transmission yet started at line : ", line);
+					    MSG_WAR(0x3AB5, "Server Nbr = ", CliServNbr);
+					    failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+					    return 0xFF;
+				    }
+				    /* No line on use. Great !*/
+				    /* Try to open a new line.*/
+				    err = getSDOfreeLine( d, whoami, &line );
+				    if (err) {
+					    MSG_ERR(0x1A73, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
+					    failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+					    return 0xFF;
+				    }
+				    initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);
+                    d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
+                    d->transfers[line].blksize = m->data[4];
+				    /* Transfer data from dictionary to the line structure. */
+				    errorCode = objdictToSDOline(d, line);
+				    if (errorCode) {
+					    MSG_ERR(0x1A95, "SDO error : Unable to copy the data from object dictionary. Err code : ",
+							errorCode);
+					    failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);
+					    return 0xFF;
+				    }
+ 				    /* Preparing the response.*/
+				    getSDOlineRestBytes(d, line, &nbBytes);	/* get Nb bytes to transfer */
+                    d->transfers[line].objsize = nbBytes;
+                    data[0] = (6 << 5) | (1 << 1) | SDO_BSS_INITIATE_UPLOAD_RESPONSE;
+					data[1] = index & 0xFF;        /* LSB */
+					data[2] = (index >> 8) & 0xFF; /* MSB */
+					data[3] = subIndex;
+					data[4] = nbBytes;
+					data[5] = nbBytes >> 8;
+					data[6] = nbBytes >> 16;
+					data[7] = nbBytes >> 24;
+					MSG_WAR(0x3A9A, "SDO. Sending normal block upload initiate response defined at index 0x1200 + ", nodeId);
+					sendSDO(d, whoami, CliServNbr, data);
+                }
+				else if (SubCommand == SDO_BCS_END_UPLOAD_REQUEST) {
+				    MSG_WAR(0x3AA2, "Received SDO block END upload request defined at index 0x1200 + ", CliServNbr);
+ 				    /* A SDO transfert should have been yet initiated. */
+				    if (!err)
+					    err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;
+				    if (err) {
+					    MSG_ERR(0x1AA1, "SDO error : Received block upload request for unstarted trans. index 0x1200 + ",
+							    CliServNbr);
+					    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+					    return 0xFF;
+				    }
+                    /* Release the line */
+					resetSDOline(d, line);
+                }
+				else if ((SubCommand == SDO_BCS_UPLOAD_RESPONSE) || (SubCommand == SDO_BCS_START_UPLOAD)) {
+ 				    /* A SDO transfert should have been yet initiated. */
+				    if (!err)
+					    err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;
+				    if (err) {
+					    MSG_ERR(0x1AA1, "SDO error : Received block upload response for unstarted trans. index 0x1200 + ",
+							    CliServNbr);
+					    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+					    return 0xFF;
+				    }
+				    /* Reset the wathdog */
+				    RestartSDO_TIMER(line);
+				    /* Uploading first or next block */
+				    index = d->transfers[line].index;
+				    subIndex = d->transfers[line].subIndex;
+                    if (SubCommand == SDO_BCS_UPLOAD_RESPONSE) {
+					    MSG_WAR(0x3AA2, "Received SDO block upload response defined at index 0x1200 + ", CliServNbr);
+                        d->transfers[line].blksize = m->data[2];
+                        AckSeq = (m->data[1]) & 0x7f;
+                        getSDOlineRestBytes(d, line, &nbBytes);
+                        if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){ /* Si tout est envoyé et confirmé reçu on envoi un block end upload response */
+                            data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BSS_END_UPLOAD_RESPONSE;
+                            for (i = 1 ; i < 8 ; i++)
+						        data[i] = 0;
+					        MSG_WAR(0x3AA5, "SDO. Sending block END upload response defined at index 0x1200 + ", CliServNbr);
+					        sendSDO(d, whoami, CliServNbr, data);
+                            break;
+                        }
+                        else
+                            d->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;
+                        if(d->transfers[line].offset > d->transfers[line].count) { /* Bad AckSeq reveived (too high) */
+					        MSG_ERR(0x1AA1, "SDO error : Received upload response with bad ackseq index 0x1200 + ",
+							    CliServNbr);
+					        failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+					        return 0xFF;
+                        }
+           			}
+                    else
+					    MSG_WAR(0x3AA2, "Received SDO block START upload defined at index 0x1200 + ", CliServNbr);
+                    d->transfers[line].lastblockoffset = d->transfers[line].offset;
+                    for(SeqNo = 1 ; SeqNo <= d->transfers[line].blksize ; SeqNo++) {
+                        d->transfers[line].seqno = SeqNo;
+				        getSDOlineRestBytes(d, line, &nbBytes);
+                        if (nbBytes > 7) {
+					        /* The segment to transfer is not the last one.*/
+ 					        data[0] = SeqNo;
+					        err = lineToSDO(d, line, 7, data + 1);
+					        if (err) {
+						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+						        return 0xFF;
+					        }
+					        MSG_WAR(0x3AA5, "SDO. Sending upload segment defined at index 0x1200 + ", CliServNbr);
+					        sendSDO(d, whoami, CliServNbr, data);
+				        }
+				        else {
+					        /* Last segment is in this block */
+					        data[0] = 0x80 | SeqNo;
+					        err = lineToSDO(d, line, nbBytes, data + 1);
+					        if (err) {
+						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+						        return 0xFF;
+					        }
+					        for (i = nbBytes + 1 ; i < 8 ; i++)
+						        data[i] = 0;
+					        MSG_WAR(0x3AA5, "SDO. Sending last upload segment defined at index 0x1200 + ", CliServNbr);
+					        sendSDO(d, whoami, CliServNbr, data);
+                            d->transfers[line].endfield = 7 - nbBytes;
+                            break;
+				        }
+                    }
+                }
+			}      /* end if SERVER */
+			else { /* if CLIENT (block download) */
+                if ((SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) || (SubCommand == SDO_BSS_DOWNLOAD_RESPONSE)) {
+                    /* We should find a line opened for this. */
+                    if (!err)
+                        err = d->transfers[line].state != SDO_BLOCK_DOWNLOAD_IN_PROGRESS;
+                    if (err) {
+                        MSG_ERR(0x1AAA, "SDO error : Received response for unknown block download request from node id", nodeId);
+                        failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+                        return 0xFF;
+                    }
+                    /* Reset the watchdog */
+                    RestartSDO_TIMER(line)
+                    if (SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) {
+                           index = d->transfers[line].index;
+                        subIndex = d->transfers[line].subIndex;
+                        d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
+                        d->transfers[line].blksize = m->data[4];
+                    }
+                    else {
+                    	d->transfers[line].blksize = m->data[2];
+                        AckSeq = (m->data[1]) & 0x7f;
+                        getSDOlineRestBytes(d, line, &nbBytes);
+                        if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){ /* Si tout est envoyé et confirmé reçu on envoi un block end download request */
+                            data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BCS_END_DOWNLOAD_REQUEST;
+                            for (i = 1 ; i < 8 ; i++)
+						        data[i] = 0;
+					        MSG_WAR(0x3AA5, "SDO. Sending block END download request defined at index 0x1200 + ", CliServNbr);
+					        sendSDO(d, whoami, CliServNbr, data);
+                            break;
+                        }
+                        else
+                            d->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;
+                        if(d->transfers[line].offset > d->transfers[line].count) { /* Bad AckSeq reveived (too high) */
+					        MSG_ERR(0x1AA1, "SDO error : Received upload segment with bad ackseq index 0x1200 + ",
+							    CliServNbr);
+					        failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+					        return 0xFF;
+                        }
+					}
+                 	d->transfers[line].lastblockoffset = d->transfers[line].offset;
+                	for(SeqNo = 1 ; SeqNo <= d->transfers[line].blksize ; SeqNo++) {
+                        d->transfers[line].seqno = SeqNo;
+				        getSDOlineRestBytes(d, line, &nbBytes);
+                        if (nbBytes > 7) {
+					        /* The segment to transfer is not the last one.*/
+ 					        data[0] = SeqNo;
+					        err = lineToSDO(d, line, 7, data + 1);
+					        if (err) {
+						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+						        return 0xFF;
+					        }
+					        MSG_WAR(0x3AAB, "SDO. Sending download segment to node id ", nodeId);
+					        sendSDO(d, whoami, CliServNbr, data);
+				        }
+				        else {
+					        /* Last segment is in this block */
+					        data[0] = 0x80 | SeqNo;
+					        err = lineToSDO(d, line, nbBytes, data + 1);
+					        if (err) {
+						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+						        return 0xFF;
+					        }
+					        for (i = nbBytes + 1 ; i < 8 ; i++)
+						        data[i] = 0;
+					        MSG_WAR(0x3AAB, "SDO. Sending last download segment to node id ", nodeId);
+					        sendSDO(d, whoami, CliServNbr, data);
+                            d->transfers[line].endfield = 7 - nbBytes;
+                            break;
+				        }
+                    }
+				}
+				else if (SubCommand == SDO_BSS_END_DOWNLOAD_RESPONSE) {
+					MSG_WAR(0x3AAC, "SDO End block download response from nodeId", nodeId);
+					StopSDO_TIMER(line)
+					d->transfers[line].state = SDO_FINISHED;
+					if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+					return 0x00;
+				}
+				else {
+			    	MSG_ERR(0x1AAB, "SDO error block download : Received wrong subcommand from nodeId", nodeId);
+    				failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+	    			return 0xFF;
+				}
+			}      /* end if CLIENT */
+			break;
+		case 6: /* Command specifier for data reception - the client or server is the data consumer */
+			if (whoami == SDO_SERVER) { /* Server block download */
+				if (err) {
+					/* Nothing already started */
+					SubCommand = (m->data[0]) & 1;
+					if (SubCommand != SDO_BCS_INITIATE_DOWNLOAD_REQUEST) {
+			    	    MSG_ERR(0x1AAC, "SDO error block download : Received wrong subcommand from node id", nodeId);
+    				    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+	    			    return 0xFF;
+				    }
+					index = getSDOindex(m->data[1],m->data[2]);
+					subIndex = getSDOsubIndex(m->data[3]);
+					MSG_WAR(0x3A9B, "Received SDO block download initiate defined at index 0x1200 + ",
+						CliServNbr);
+					MSG_WAR(0x3A9B, "Writing at index : ", index);
+					MSG_WAR(0x3A9B, "Writing at subIndex : ", subIndex);
+					/* Try to open a new line. */
+					err = getSDOfreeLine( d, whoami, &line );
+					if (err) {
+						MSG_ERR(0x1A89, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
+						failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+						return 0xFF;
+					}
+					initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);
+                    d->transfers[line].rxstep = RXSTEP_STARTED;
+                    d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
+					if ((m->data[0]) & 2)	/* if data set size is indicated */
+                    	d->transfers[line].objsize = (UNS32)m->data[4] + (UNS32)m->data[5]*256 + (UNS32)m->data[6]*256*256 + (UNS32)m->data[7]*256*256*256;
+                    data[0] = (5 << 5) | SDO_BSS_INITIATE_DOWNLOAD_RESPONSE;
+					data[1] = index;        /* LSB */
+					data[2] = index >> 8;   /* MSB */
+					data[3] = subIndex;
+					data[4] = SDO_BLOCK_SIZE;
+					data[5] = data[6] = data[7] = 0;
+					MSG_WAR(0x3AAD, "SDO. Sending block download initiate response - index 0x1200 + ", CliServNbr);
+					sendSDO(d, whoami, CliServNbr, data);
+				}
+				else if (d->transfers[line].rxstep == RXSTEP_STARTED) {
+					MSG_WAR(0x3A9B, "Received SDO block download data segment - index 0x1200 + ", CliServNbr);
+    		    	RestartSDO_TIMER(line)
+					SeqNo = m->data[0] & 0x7F;
+					if (m->data[0] & 0x80) {	/* Last segment ? */
+					    if(SeqNo == (d->transfers[line].seqno + 1)) {
+							d->transfers[line].rxstep = RXSTEP_END;
+							d->transfers[line].seqno = SeqNo;
+							/* Store the data temporary because we don't know yet how many bytes do not contain data */
+							memcpy(d->transfers[line].tmpData, m->data, 8);
+						}
+						data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;
+						data[1] = d->transfers[line].seqno;
+						data[2] = SDO_BLOCK_SIZE;
+						data[3] = data[4] = data[5] = data[6] = data[7] = 0;
+						MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);
+						sendSDO(d, whoami, CliServNbr, data);
+                        d->transfers[line].seqno = 0;
+					}
+					else {
+					   	if (SeqNo == (d->transfers[line].seqno + 1)) {	
+							d->transfers[line].seqno = SeqNo;
+							/* Store the data in the transfert structure. */
+							err = SDOtoLine(d, line, 7, (*m).data + 1);
+							if (err) {
+								failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
+								return 0xFF;
+							}
+						}
+						if (SeqNo == SDO_BLOCK_SIZE) {
+							data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;
+							data[1] = d->transfers[line].seqno;
+							data[2] = SDO_BLOCK_SIZE;
+							data[3] = data[4] = data[5] = data[6] = data[7] = 0;
+							MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);
+							sendSDO(d, whoami, CliServNbr, data);
+                            d->transfers[line].seqno = 0;
+						}
+					}
+				}
+				else if (d->transfers[line].rxstep == RXSTEP_END) { /* endphase */
+					MSG_WAR(0x3A9B, "Received SDO block download end request - index 0x1200 + ", CliServNbr);
+					/* here store remaining bytes in tmpData to line, check size and confirm or abort */
+					if ((m->data[0] & 1) != SDO_BCS_END_DOWNLOAD_REQUEST) {
+		    			MSG_ERR(0x1AAD, "SDO error block download : Received wrong subcommand - index 0x1200 + ", CliServNbr);
+    					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+	    				return 0xFF;
+					}
+    		    	RestartSDO_TIMER(line)
+					NbBytesNoData = (m->data[0]>>2) & 0x07;
+					/* Store the data in the transfert structure. */
+					err = SDOtoLine(d, line, 7-NbBytesNoData, d->transfers[line].tmpData + 1);
+					if (err) {
+						failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
+						return 0xFF;
+					}
+					if(d->transfers[line].objsize){ /* If size was indicated in the initiate request */
+						if (d->transfers[line].objsize != d->transfers[line].offset){
+		    					MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - index 0x1200 + ", CliServNbr);
+    							failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);
+	    						return 0xFF;
+						}
+					}
+					data[0] = (5 << 5) | SDO_BSS_END_DOWNLOAD_RESPONSE;
+					for (i = 1 ; i < 8 ; i++)
+						data[i] = 0;
+					MSG_WAR(0x3AAF, "SDO. Sending block download end response - index 0x1200 + ", CliServNbr);
+					sendSDO(d, whoami, CliServNbr, data);
+					/* Transfering line data to object dictionary. */
+					errorCode = SDOlineToObjdict(d, line);
+					if (errorCode) {
+						MSG_ERR(0x1AAF, "SDO error : Unable to copy the data in the object dictionary", 0);
+						failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, errorCode);
+						return 0xFF;
+					}
+					/* Release of the line */
+					resetSDOline(d, line);
+					MSG_WAR(0x3AAF, "SDO. End of block download defined at index 0x1200 + ", CliServNbr);
+				}
+		    }      /* end if SERVER */
+		    else { /* if CLIENT (block upload) */
+				if (err) {
+       				/* Nothing already started */
+			    	MSG_ERR(0x1AAD, "SDO error block upload : no transmission started", nodeId);
+    				failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+	    			return 0xFF;
+				}
+    			RestartSDO_TIMER(line)
+				if (d->transfers[line].rxstep == RXSTEP_INIT) {
+				    if ((m->data[0] & 1) == SDO_BSS_INITIATE_UPLOAD_RESPONSE) {
+					    MSG_WAR(0x3A9C, "Received SDO block upload response from node id ", nodeId);
+						d->transfers[line].rxstep = RXSTEP_STARTED;
+                        d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
+					    if ((m->data[0]) & 2)	/* if data set size is indicated */
+                    	    d->transfers[line].objsize = (UNS32)m->data[4] + (UNS32)m->data[5]*256 + (UNS32)m->data[6]*256*256 + (UNS32)m->data[7]*256*256*256;
+                        data[0] = (5 << 5) | SDO_BCS_START_UPLOAD;
+					    for (i = 1 ; i < 8 ; i++)
+						    data[i] = 0;
+                        MSG_WAR(0x3AB6, "SDO. Sending block upload start to node id ", nodeId);
+					    sendSDO(d, whoami, CliServNbr, data);
+                    }
+                }
+				else if (d->transfers[line].rxstep == RXSTEP_STARTED) {
+					SeqNo = m->data[0] & 0x7F;
+					if (m->data[0] & 0x80) {	/* Last segment ? */
+					    if(SeqNo == (d->transfers[line].seqno + 1)) {
+							d->transfers[line].rxstep = RXSTEP_END;
+							d->transfers[line].seqno = SeqNo;
+							/* Store the data temporary because we don't know yet how many bytes do not contain data */
+							memcpy(d->transfers[line].tmpData, m->data, 8);
+						}
+						data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;
+						data[1] = d->transfers[line].seqno;
+						data[2] = SDO_BLOCK_SIZE;
+						data[3] = data[4] = data[5] = data[6] = data[7] = 0;
+						MSG_WAR(0x3AB7, "SDO. Sending block upload response to node id ", nodeId);
+						sendSDO(d, whoami, CliServNbr, data);
+                        d->transfers[line].seqno = 0;
+					}
+					else {
+					   	if (SeqNo == (d->transfers[line].seqno + 1)) {	
+							d->transfers[line].seqno = SeqNo;
+							/* Store the data in the transfert structure. */
+							err = SDOtoLine(d, line, 7, (*m).data + 1);
+							if (err) {
+								failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
+								return 0xFF;
+							}
+						}
+						if (SeqNo == SDO_BLOCK_SIZE) {
+							data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;
+							data[1] = d->transfers[line].seqno;
+							data[2] = SDO_BLOCK_SIZE;
+							data[3] = data[4] = data[5] = data[6] = data[7] = 0;
+							MSG_WAR(0x3AAE, "SDO. Sending block upload response to node id ", nodeId);
+							sendSDO(d, whoami, CliServNbr, data);
+                            d->transfers[line].seqno = 0;
+						}
+					}
+				}
+				else if (d->transfers[line].rxstep == RXSTEP_END) { /* endphase */
+					/* here store remaining bytes in tmpData to line, check size and confirm or abort */
+					if ((m->data[0] & 1) != SDO_BSS_END_UPLOAD_RESPONSE) {
+			    		MSG_ERR(0x1AAD, "SDO error block upload : Received wrong subcommand from node id ", nodeId);
+    					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+	    				return 0xFF;
+					}
+					NbBytesNoData = (m->data[0]>>2) & 0x07;
+					/* Store the data in the transfert structure. */
+					err = SDOtoLine(d, line, 7-NbBytesNoData, d->transfers[line].tmpData + 1);
+					if (err) {
+						failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
+						return 0xFF;
+					}
+					if(d->transfers[line].objsize){ /* If size was indicated in the initiate request */
+						if (d->transfers[line].objsize != d->transfers[line].offset){
+			    				MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - from node id ", nodeId);
+    							failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);
+	    						return 0xFF;
+						}
+					}
+					data[0] = (5 << 5) | SDO_BCS_END_UPLOAD_REQUEST;
+					for (i = 1 ; i < 8 ; i++)
+						data[i] = 0;
+					MSG_WAR(0x3AAF, "SDO. Sending block upload end request to node id ", nodeId);
+					sendSDO(d, whoami, CliServNbr, data);
+					MSG_WAR(0x3AAF, "SDO. End of block upload request", 0);
+                    StopSDO_TIMER(line)
+					d->transfers[line].state = SDO_FINISHED;
+				    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+				}
+			}      /* end if CLIENT */
+			break;
 		default:
 			/* Error : Unknown cs */
-			MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
+			MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", cs);
 			return 0xFF;
 
 	} /* End switch */
@@ -1388,7 +1840,7 @@
  ** @return
  **/
 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
-		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
+		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode)
 {
 	UNS8 err;
 	UNS8 line;
@@ -1418,10 +1870,14 @@
 		MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
 		return (0xFF);
 	}
-	initSDOline(d, line, CliNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
+    if(useBlockMode) {
+	    initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);
+	    d->transfers[line].objsize = count;
+    }
+    else 
+	    initSDOline(d, line, CliNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
 	d->transfers[line].count = count;
 	d->transfers[line].dataType = dataType;
-
 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
 	{
 		UNS8* lineData = d->transfers[line].data;
@@ -1461,18 +1917,25 @@
 #  endif
 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 	}
-	/* Send the SDO to the server. Initiate download, cs=1. */
-	if (count <= 4) { /* Expedited transfert */
-		buf[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
-		for (i = 4 ; i < 8 ; i++)
-			buf[i] = d->transfers[line].data[i - 4];
-		d->transfers[line].offset = count;
-	}
-	else { /** Normal transfert */
-		buf[0] = (1 << 5) | 1;
-		for (i = 0 ; i < 4 ; i++)
-			buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
-	}
+    if(useBlockMode) {
+	    buf[0] = (6 << 5) | (1 << 1 );   /* CCS = 6 , CC = 0 , S = 1 , CS = 0 */
+ 	    for (i = 0 ; i < 4 ; i++)
+		    buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
+    }
+    else {
+	    /* Send the SDO to the server. Initiate download, cs=1. */
+	    if (count <= 4) { /* Expedited transfert */
+		    buf[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
+		    for (i = 4 ; i < 8 ; i++)
+			    buf[i] = d->transfers[line].data[i - 4];
+		    d->transfers[line].offset = count;
+	    }
+	    else { /** Normal transfert */
+		    buf[0] = (1 << 5) | 1;
+		    for (i = 0 ; i < 4 ; i++)
+			    buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
+	    }
+    }
 	buf[1] = index & 0xFF;        /* LSB */
 	buf[2] = (index >> 8) & 0xFF; /* MSB */
 	buf[3] = subIndex;
@@ -1505,9 +1968,9 @@
  ** @return
  **/
 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
-		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
-{
-	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
+		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode)
+{
+	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1, useBlockMode);
 }
 
 /*!
@@ -1525,13 +1988,13 @@
  ** @return
  **/
 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
-		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
-{
-	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
+		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 useBlockMode)
+{
+	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1, useBlockMode);
 }
 
 UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
-		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
+		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode)
 {
 	UNS8 ret;
 	UNS16 lastIndex;
@@ -1539,7 +2002,7 @@
 	UNS8 nodeIdServer;
 	UNS8 i;
 
-	ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize);
+	ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize, useBlockMode);
 	if(ret == 0xFE)
 	{
 		offset = d->firstIndex->SDO_CLT;
@@ -1563,7 +2026,7 @@
 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
-				return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
+				return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1, useBlockMode);
 			}
 			offset++;
 		}
@@ -1591,7 +2054,7 @@
  **
  ** @return
  **/
-INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
+INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
 {
 	UNS8 err;
 	UNS8 i;
@@ -1623,16 +2086,29 @@
 	else
 		MSG_WAR(0x3AE0, "Transmission on line : ", line);
 
-	initSDOline(d, line, CliNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
-	getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);
-	/* Send the SDO to the server. Initiate upload, cs=2. */
-	d->transfers[line].dataType = dataType;
-	data[0] = (2 << 5);
-	data[1] = index & 0xFF;        /* LSB */
-	data[2] = (index >> 8) & 0xFF; /* MSB */
-	data[3] = subIndex;
-	for (i = 4 ; i < 8 ; i++)
-		data[i] = 0;
+    if(useBlockMode) {
+	    initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);
+	    /* Send the SDO to the server. Initiate block upload, cs=0. */
+	    d->transfers[line].dataType = dataType;
+	    data[0] = (5 << 5) | SDO_BCS_INITIATE_UPLOAD_REQUEST;
+	    data[1] = index & 0xFF;        /* LSB */
+	    data[2] = (index >> 8) & 0xFF; /* MSB */
+	    data[3] = subIndex;
+	    data[4] = SDO_BLOCK_SIZE;
+	    for (i = 5 ; i < 8 ; i++)
+		    data[i] = 0;
+    }
+    else {
+	    initSDOline(d, line, CliNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
+	    /* Send the SDO to the server. Initiate upload, cs=2. */
+	    d->transfers[line].dataType = dataType;
+	    data[0] = (2 << 5);
+	    data[1] = index & 0xFF;        /* LSB */
+	    data[2] = (index >> 8) & 0xFF; /* MSB */
+	    data[3] = subIndex;
+	    for (i = 4 ; i < 8 ; i++)
+		    data[i] = 0;
+    }
 	d->transfers[line].Callback = Callback;
 	err = sendSDO(d, SDO_CLIENT, CliNbr, data);
 	if (err) {
@@ -1655,9 +2131,9 @@
  **
  ** @return
  **/
-UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
-{
-	return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
+UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, UNS8 useBlockMode)
+{
+	return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL, useBlockMode);
 }
 
 /*!
@@ -1672,12 +2148,12 @@
  **
  ** @return
  **/
-UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
-{
-	return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
-}
-
-UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
+UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
+{
+	return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
+}
+
+UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
 {
 	UNS8 ret;
 	UNS16 lastIndex;
@@ -1685,7 +2161,7 @@
 	UNS8 nodeIdServer;
 	UNS8 i;
 
-	ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
+	ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
 	if(ret == 0xFE)
 	{
 		offset = d->firstIndex->SDO_CLT;
@@ -1709,7 +2185,7 @@
 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
-				return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
+				return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
 			}
 			offset++;
 		}
@@ -1731,10 +2207,13 @@
  ** @param d
  ** @param nodeId
  ** @param data
- ** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
+ ** @param size : *size MUST contain the size of *data buffer before calling
+ **                     The function set it to the actual number of written bytes
  ** @param abortCode
  **
  ** @return
+ **    SDO_PROVIDED_BUFFER_TOO_SMALL if *data is not big enough
+ **    or any transmission status value.
  **/
 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
 		UNS32 * abortCode)
@@ -1747,25 +2226,40 @@
 
 	/* First let's find the corresponding SDO client in our OD  */
 	CliNbr = GetSDOClientFromNodeId(d, nodeId);
-	if(CliNbr >= 0xFE)
+	if(CliNbr >= 0xFE) {
+        *size = 0;
 		return SDO_ABORTED_INTERNAL;
+    }
 
 	/* Looking for the line tranfert. */
 	err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);
 	if (err) {
 		MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
-		return SDO_ABORTED_INTERNAL;
-	}
-	* abortCode = d->transfers[line].abortCode;
-	if (d->transfers[line].state != SDO_FINISHED)
+        *size = 0;
+        return SDO_ABORTED_INTERNAL;
+	}
+
+    /* If transfert not finished just return, but if aborted set abort code and size to 0 */
+    if (d->transfers[line].state != SDO_FINISHED) {
+	    if((d->transfers[line].state == SDO_ABORTED_RCV) || (d->transfers[line].state == SDO_ABORTED_INTERNAL)) {
+            *abortCode = d->transfers[line].abortCode;
+            *size = 0;
+        }
 		return d->transfers[line].state;
+    }
 
 	/* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
 	if( d->transfers[line].count == 0)
 		d->transfers[line].count = d->transfers[line].offset;
-	/* use transfers[line].count as max size */
-	if( d->transfers[line].count < *size )
-		*size = d->transfers[line].count;
+
+    /* Check if the provided buffer is big enough */
+    if(*size < d->transfers[line].count) {
+		*size = 0;
+		return SDO_PROVIDED_BUFFER_TOO_SMALL;
+    }
+	
+    /* Give back actual size */
+    *size = d->transfers[line].count;
 
 	/* Copy payload to data pointer */
 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
@@ -1799,6 +2293,7 @@
 # endif
 	}
 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+    resetSDOline(d, line);
 	return SDO_FINISHED;
 }
 
@@ -1830,5 +2325,8 @@
 		return SDO_ABORTED_INTERNAL;
 	}
 	* abortCode = d->transfers[line].abortCode;
-	return d->transfers[line].state;
-}
+    if (d->transfers[line].state != SDO_FINISHED)
+	    return d->transfers[line].state;
+    resetSDOline(d, line);
+	return SDO_FINISHED;
+}