--- 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;
+}