src/sdo.c
changeset 664 a03f0aa7d219
parent 663 70fc3603e36f
child 665 90e6cf84a0d7
equal deleted inserted replaced
663:70fc3603e36f 664:a03f0aa7d219
    60  ** @param endianize
    60  ** @param endianize
    61  **
    61  **
    62  ** @return
    62  ** @return
    63  **/
    63  **/
    64 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
    64 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
    65 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
    65 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode);
    66 
    66 
    67 /*!
    67 /*!
    68  ** Called by readNetworkDict
    68  ** Called by readNetworkDict
    69  **
    69  **
    70  ** @param d
    70  ** @param d
    75  ** @param Callback
    75  ** @param Callback
    76  **
    76  **
    77  ** @return
    77  ** @return
    78  **/
    78  **/
    79 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
    79 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
    80 		UNS8 dataType, SDOCallback_t Callback);
    80 		UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
    81 
    81 
    82 
    82 
    83 /***************************************************************************/
    83 /***************************************************************************/
    84 /* SDO (un)packing macros */
    84 /* SDO (un)packing macros */
    85 
    85 
   116 #define getSDOindex(byte1, byte2) (((UNS16)byte2 << 8) | ((UNS16)byte1))
   116 #define getSDOindex(byte1, byte2) (((UNS16)byte2 << 8) | ((UNS16)byte1))
   117 
   117 
   118 /** Returns the subIndex from the byte 3 of the SDO
   118 /** Returns the subIndex from the byte 3 of the SDO
   119 */
   119 */
   120 #define getSDOsubIndex(byte3) (byte3)
   120 #define getSDOsubIndex(byte3) (byte3)
       
   121 
       
   122 /** Returns the subcommand in SDO block transfert
       
   123 */
       
   124 #define getSDOblockSC(byte) (byte & 3)
       
   125 
   121 
   126 
   122 /*!
   127 /*!
   123  **
   128  **
   124  **
   129  **
   125  ** @param d
   130  ** @param d
   134 	if ((offset == 0) || ((offset+d->transfers[id].CliServNbr) > d->lastIndex->SDO_CLT)) {
   139 	if ((offset == 0) || ((offset+d->transfers[id].CliServNbr) > d->lastIndex->SDO_CLT)) {
   135 		return ;
   140 		return ;
   136 	}
   141 	}
   137 	nodeId = *((UNS32*) d->objdict[offset+d->transfers[id].CliServNbr].pSubindex[3].pObject);
   142 	nodeId = *((UNS32*) d->objdict[offset+d->transfers[id].CliServNbr].pSubindex[3].pObject);
   138 	MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
   143 	MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
   139 	MSG_WAR(0x2A02, "server node : ", NodeId);
   144 	MSG_WAR(0x2A02, "server node id : ", nodeId);
   140 	MSG_WAR(0x2A02, "      index : ", d->transfers[id].index);
   145 	MSG_WAR(0x2A02, "         index : ", d->transfers[id].index);
   141 	MSG_WAR(0x2A02, "   subIndex : ", d->transfers[id].subIndex);
   146 	MSG_WAR(0x2A02, "      subIndex : ", d->transfers[id].subIndex);
   142 	/* Reset timer handler */
   147 	/* Reset timer handler */
   143 	d->transfers[id].timer = TIMER_NONE;
   148 	d->transfers[id].timer = TIMER_NONE;
   144 	/*Set aborted state*/
   149 	/*Set aborted state*/
   145 	d->transfers[id].state = SDO_ABORTED_INTERNAL;
   150 	d->transfers[id].state = SDO_ABORTED_INTERNAL;
   146 	/* Sending a SDO abort */
   151 	/* Sending a SDO abort */
   400 		MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
   405 		MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
   401 	}
   406 	}
   402 	if ((! err) && (whoami == SDO_CLIENT)) {
   407 	if ((! err) && (whoami == SDO_CLIENT)) {
   403 		StopSDO_TIMER(line);
   408 		StopSDO_TIMER(line);
   404 		d->transfers[line].state = SDO_ABORTED_INTERNAL;
   409 		d->transfers[line].state = SDO_ABORTED_INTERNAL;
       
   410 		d->transfers[line].abortCode = abortCode;
   405 	}
   411 	}
   406 	MSG_WAR(0x3A22, "Sending SDO abort ", 0);
   412 	MSG_WAR(0x3A22, "Sending SDO abort ", 0);
   407 	err = sendSDOabort(d, whoami, CliServNbr, index, subIndex, abortCode);
   413 	err = sendSDOabort(d, whoami, CliServNbr, index, subIndex, abortCode);
   408 	if (err) {
   414 	if (err) {
   409 		MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
   415 		MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
   425 	initSDOline(d, line, 0, 0, 0, SDO_RESET);
   431 	initSDOline(d, line, 0, 0, 0, SDO_RESET);
   426 	for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
   432 	for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
   427 		d->transfers[line].data[i] = 0;
   433 		d->transfers[line].data[i] = 0;
   428 	d->transfers[line].whoami = 0;
   434 	d->transfers[line].whoami = 0;
   429 	d->transfers[line].abortCode = 0;
   435 	d->transfers[line].abortCode = 0;
   430 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
       
   431 	free(d->transfers[line].dynamicData);
       
   432 	d->transfers[line].dynamicData = 0;
       
   433 	d->transfers[line].dynamicDataSize = 0;
       
   434 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
       
   435 }
   436 }
   436 
   437 
   437 /*!
   438 /*!
   438  **
   439  **
   439  **
   440  **
   447  ** @return
   448  ** @return
   448  **/
   449  **/
   449 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS8 state)
   450 UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS8 state)
   450 {
   451 {
   451 	MSG_WAR(0x3A25, "init SDO line nb : ", line);
   452 	MSG_WAR(0x3A25, "init SDO line nb : ", line);
   452 	if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
   453 	if (state == SDO_DOWNLOAD_IN_PROGRESS       || state == SDO_UPLOAD_IN_PROGRESS ||
       
   454         state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS || state == SDO_BLOCK_UPLOAD_IN_PROGRESS){
   453 		StartSDO_TIMER(line)
   455 		StartSDO_TIMER(line)
   454 	}else{
   456 	}else{
   455 		StopSDO_TIMER(line)
   457 		StopSDO_TIMER(line)
   456 	}
   458 	}
   457 	d->transfers[line].CliServNbr = CliServNbr;
   459 	d->transfers[line].CliServNbr = CliServNbr;
   459 	d->transfers[line].subIndex = subIndex;
   461 	d->transfers[line].subIndex = subIndex;
   460 	d->transfers[line].state = state;
   462 	d->transfers[line].state = state;
   461 	d->transfers[line].toggle = 0;
   463 	d->transfers[line].toggle = 0;
   462 	d->transfers[line].count = 0;
   464 	d->transfers[line].count = 0;
   463 	d->transfers[line].offset = 0;
   465 	d->transfers[line].offset = 0;
       
   466     d->transfers[line].peerCRCsupport = 0;
       
   467     d->transfers[line].blksize = 0;
       
   468     d->transfers[line].ackseq = 0;
       
   469     d->transfers[line].objsize = 0;
       
   470     d->transfers[line].lastblockoffset = 0;
       
   471     d->transfers[line].seqno = 0;
       
   472     d->transfers[line].endfield = 0;
       
   473     d->transfers[line].rxstep = RXSTEP_INIT;
   464 	d->transfers[line].dataType = 0;
   474 	d->transfers[line].dataType = 0;
   465 	d->transfers[line].Callback = NULL;
   475 	d->transfers[line].Callback = NULL;
   466 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
   476 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
   467 	free(d->transfers[line].dynamicData);
   477 	free(d->transfers[line].dynamicData);
   468 	d->transfers[line].dynamicData = 0;
   478 	d->transfers[line].dynamicData = 0;
   641 		if ((offset == 0) || ((offset+CliServNbr) > d->lastIndex->SDO_SVR)) {
   651 		if ((offset == 0) || ((offset+CliServNbr) > d->lastIndex->SDO_SVR)) {
   642 			MSG_ERR(0x1A42, "SendSDO : SDO server not found", 0);
   652 			MSG_ERR(0x1A42, "SendSDO : SDO server not found", 0);
   643 			return 0xFF;
   653 			return 0xFF;
   644 		}
   654 		}
   645 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[2].pObject);
   655 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[2].pObject);
   646 		MSG_WAR(0x3A41, "I am server cobId : ", m.cob_id);
   656 		MSG_WAR(0x3A41, "I am server Tx cobId : ", m.cob_id);
   647 	}
   657 	}
   648 	else {			/*case client*/
   658 	else {			/*case client*/
   649 		/* Get the client->server cobid.*/
   659 		/* Get the client->server cobid.*/
   650 		offset = d->firstIndex->SDO_CLT;
   660 		offset = d->firstIndex->SDO_CLT;
   651 		if ((offset == 0) || ((offset+CliServNbr) > d->lastIndex->SDO_CLT)) {
   661 		if ((offset == 0) || ((offset+CliServNbr) > d->lastIndex->SDO_CLT)) {
   652 			MSG_ERR(0x1A42, "SendSDO : SDO client not found", 0);
   662 			MSG_ERR(0x1A42, "SendSDO : SDO client not found", 0);
   653 			return 0xFF;
   663 			return 0xFF;
   654 		}
   664 		}
   655 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[1].pObject);
   665 		m.cob_id = *((UNS32*) d->objdict[offset+CliServNbr].pSubindex[1].pObject);
   656 		MSG_WAR(0x3A41, "I am client cobId : ", m.cob_id);
   666 		MSG_WAR(0x3A41, "I am client Tx cobId : ", m.cob_id);
   657 	}
   667 	}
   658 	/* message copy for sending */
   668 	/* message copy for sending */
   659 	m.rtr = NOT_A_REQUEST;
   669 	m.rtr = NOT_A_REQUEST;
   660 	/* the length of SDO must be 8 */
   670 	/* the length of SDO must be 8 */
   661 	m.len = 8;
   671 	m.len = 8;
   707  ** @return
   717  ** @return
   708  **/
   718  **/
   709 UNS8 proceedSDO (CO_Data* d, Message *m)
   719 UNS8 proceedSDO (CO_Data* d, Message *m)
   710 {
   720 {
   711 	UNS8 err;
   721 	UNS8 err;
       
   722 	UNS8 cs;
   712 	UNS8 line;
   723 	UNS8 line;
   713 	UNS32 nbBytes; 		/* received or to be transmited. */
   724 	UNS32 nbBytes; 		/* received or to be transmited. */
   714 	UNS8 nodeId = 0;  	/* The node Id of the server if client otherwise unused */
   725 	UNS8 nodeId = 0;  	/* The node Id of the server if client otherwise unused */
   715 	UNS8 CliServNbr;
   726 	UNS8 CliServNbr;
   716 	UNS8 whoami = SDO_UNKNOWN;  /* SDO_SERVER or SDO_CLIENT.*/
   727 	UNS8 whoami = SDO_UNKNOWN;  /* SDO_SERVER or SDO_CLIENT.*/
   722 	UNS32 i;
   733 	UNS32 i;
   723 	UNS8	j;
   734 	UNS8	j;
   724 	UNS32 *pCobId = NULL;
   735 	UNS32 *pCobId = NULL;
   725 	UNS16 offset;
   736 	UNS16 offset;
   726 	UNS16 lastIndex;
   737 	UNS16 lastIndex;
       
   738 	UNS8 SubCommand;	/* Block transfert only */
       
   739     UNS8 SeqNo;         /* Sequence number in block transfert */
       
   740     UNS8 AckSeq;        /* Sequence number of last segment that was received successfully */
       
   741 	UNS8 NbBytesNoData; /* Number of bytes that do not contain data in last segment of block transfert */ 
   727 
   742 
   728 	MSG_WAR(0x3A60, "proceedSDO ", 0);
   743 	MSG_WAR(0x3A60, "proceedSDO ", 0);
   729 	whoami = SDO_UNKNOWN;
   744 	whoami = SDO_UNKNOWN;
   730 	/* Looking for the cobId in the object dictionary. */
   745 	/* Looking for the cobId in the object dictionary. */
   731 	/* Am-I a server ? */
   746 	/* Am-I a server ? */
   761 			}
   776 			}
   762 			/* Looking for the cobid received. */
   777 			/* Looking for the cobid received. */
   763 			pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
   778 			pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
   764 			if (*pCobId == UNS16_LE(m->cob_id) ) {
   779 			if (*pCobId == UNS16_LE(m->cob_id) ) {
   765 				whoami = SDO_CLIENT;
   780 				whoami = SDO_CLIENT;
   766 				MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
   781 				MSG_WAR(0x3A64, "proceedSDO. I am client index : ", 0x1280 + j);
   767 				/* Defining Client number = index minus 0x1280 where the cobid received is defined. */
   782 				/* Defining Client number = index minus 0x1280 where the cobid received is defined. */
   768 				CliServNbr = j;
   783 				CliServNbr = j;
   769 				/* Reading the server node ID, if client it is mandatory in the OD */
   784 				/* Reading the server node ID, if client it is mandatory in the OD */
   770 				nodeId = *((UNS8*) d->objdict[offset].pSubindex[3].pObject);
   785 				nodeId = *((UNS8*) d->objdict[offset].pSubindex[3].pObject);
   771 				break;
   786 				break;
   790 	}
   805 	}
   791 	else {
   806 	else {
   792 		MSG_WAR(0x3A69, "I am SERVER number ", CliServNbr);
   807 		MSG_WAR(0x3A69, "I am SERVER number ", CliServNbr);
   793 	}
   808 	}
   794 
   809 
       
   810 	/* Look for an SDO transfert already initiated. */
       
   811 	err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
   812 
       
   813 	/* Let's find cs value, first it is set as "not valid" */
       
   814 	cs = 0xFF; 
       
   815 	/* Special cases for block transfert : in frames with segment data cs is not spécified */
       
   816    	if (!err) {
       
   817 		if ((whoami == SDO_SERVER) && (d->transfers[line].state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS) ||
       
   818 			(whoami == SDO_CLIENT) && (d->transfers[line].state == SDO_BLOCK_UPLOAD_IN_PROGRESS)) {		
       
   819 			if(m->data[0] == 0x80)	/* If first byte is 0x80 it is an abort frame (seqno = 0 not allowed) */
       
   820 				cs = 4;
       
   821 			else
       
   822 				cs = 6;
       
   823 		}
       
   824 	}
       
   825 	/* Other cases : cs is specified */
       
   826 	if (cs == 0xFF)
       
   827 		cs = getSDOcs(m->data[0]);
       
   828 
   795 	/* Testing the command specifier */
   829 	/* Testing the command specifier */
   796 	/* Allowed : cs = 0, 1, 2, 3, 4. (=  all except those for block tranfert). */
   830 	/* Allowed : cs = 0, 1, 2, 3, 4, 5, 6 */
   797 	/* cs = other : Not allowed -> abort. */
   831 	/* cs = other : Not allowed -> abort. */
   798 	switch (getSDOcs(m->data[0])) {
   832 	switch (cs) {
   799 
   833 
   800 		case 0:
   834 		case 0:
   801 			/* I am SERVER */
   835 			/* I am SERVER */
   802 			if (whoami == SDO_SERVER) {
   836 			if (whoami == SDO_SERVER) {
   803 				/* Receiving a download segment data. */
   837 				/* Receiving a download segment data : an SDO transfert should have been yet initiated. */
   804 				/* A SDO transfert should have been yet initiated. */
       
   805 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
   806 				if (!err)
   838 				if (!err)
   807 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
   839 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
   808 				if (err) {
   840 				if (err) {
   809 					MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
   841 					MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
   810 							CliServNbr);
   842 							CliServNbr);
   854 				}
   886 				}
   855 			} /* end if SERVER */
   887 			} /* end if SERVER */
   856 			else { /* if CLIENT */
   888 			else { /* if CLIENT */
   857 				/* I am CLIENT */
   889 				/* I am CLIENT */
   858 				/* It is a request for a previous upload segment. We should find a line opened for this.*/
   890 				/* It is a request for a previous upload segment. We should find a line opened for this.*/
   859 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
       
   860 				if (!err)
   891 				if (!err)
   861 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
   892 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
   862 				if (err) {
   893 				if (err) {
   863 					MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
   894 					MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
   864 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
   895 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
   915 						CliServNbr);
   946 						CliServNbr);
   916 				MSG_WAR(0x3A80, "Writing at index : ", index);
   947 				MSG_WAR(0x3A80, "Writing at index : ", index);
   917 				MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
   948 				MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
   918 
   949 
   919 				/* Search if a SDO transfert have been yet initiated */
   950 				/* Search if a SDO transfert have been yet initiated */
   920 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
   921 				if (! err) {
   951 				if (! err) {
   922 					MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
   952 					MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
   923 					failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
   953 					failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
   924 					return 0xFF;
   954 					return 0xFF;
   925 				}
   955 				}
   978 				sendSDO(d, whoami, CliServNbr, data);
  1008 				sendSDO(d, whoami, CliServNbr, data);
   979 			} /* end if I am SERVER */
  1009 			} /* end if I am SERVER */
   980 			else {
  1010 			else {
   981 				/* I am CLIENT */
  1011 				/* I am CLIENT */
   982 				/* It is a response for a previous download segment. We should find a line opened for this. */
  1012 				/* It is a response for a previous download segment. We should find a line opened for this. */
   983 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
       
   984 				if (!err)
  1013 				if (!err)
   985 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
  1014 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
   986 				if (err) {
  1015 				if (err) {
   987 					MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
  1016 					MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
   988 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1017 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1047 				MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
  1076 				MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
  1048 						CliServNbr);
  1077 						CliServNbr);
  1049 				MSG_WAR(0x3A90, "Reading at index : ", index);
  1078 				MSG_WAR(0x3A90, "Reading at index : ", index);
  1050 				MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
  1079 				MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
  1051 				/* Search if a SDO transfert have been yet initiated*/
  1080 				/* Search if a SDO transfert have been yet initiated*/
  1052 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
  1053 				if (! err) {
  1081 				if (! err) {
  1054 					MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
  1082 					MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
  1055 					MSG_WAR(0x3A93, "Server Nbr = ", CliServNbr);
  1083 					MSG_WAR(0x3A93, "Server Nbr = ", CliServNbr);
  1056 					failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
  1084 					failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
  1057 					return 0xFF;
  1085 					return 0xFF;
  1081 					/* code to send the initiate upload response. (cs = 2) */
  1109 					/* code to send the initiate upload response. (cs = 2) */
  1082 					data[0] = (2 << 5) | 1;
  1110 					data[0] = (2 << 5) | 1;
  1083 					data[1] = index & 0xFF;        /* LSB */
  1111 					data[1] = index & 0xFF;        /* LSB */
  1084 					data[2] = (index >> 8) & 0xFF; /* MSB */
  1112 					data[2] = (index >> 8) & 0xFF; /* MSB */
  1085 					data[3] = subIndex;
  1113 					data[3] = subIndex;
  1086 					data[4] = (UNS8)nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
  1114 					data[4] = nbBytes; 
  1087 					/* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
  1115 					data[5] = nbBytes >> 8; 
  1088 					/* in the object dictionary, at every index and subindex. */
  1116 					data[6] = nbBytes >> 16; 
  1089 					for (i = 5 ; i < 8 ; i++)
  1117 					data[7] = nbBytes >> 24; 
  1090 						data[i] = 0;
  1118  					MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
  1091 					MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
       
  1092 					sendSDO(d, whoami, CliServNbr, data);
  1119 					sendSDO(d, whoami, CliServNbr, data);
  1093 				}
  1120 				}
  1094 				else {
  1121 				else {
  1095 					/* Expedited upload. (cs = 2 ; e = 1) */
  1122 					/* Expedited upload. (cs = 2 ; e = 1) */
  1096 					data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);
  1123 					data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);
  1113 			} /* end if I am SERVER*/
  1140 			} /* end if I am SERVER*/
  1114 			else {
  1141 			else {
  1115 				/* I am CLIENT */
  1142 				/* I am CLIENT */
  1116 				/* It is the response for the previous initiate upload request.*/
  1143 				/* It is the response for the previous initiate upload request.*/
  1117 				/* We should find a line opened for this. */
  1144 				/* We should find a line opened for this. */
  1118 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
       
  1119 				if (!err)
  1145 				if (!err)
  1120 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
  1146 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
  1121 				if (err) {
  1147 				if (err) {
  1122 					MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
  1148 					MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
  1123 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1149 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1168 		case 3:
  1194 		case 3:
  1169 			/* I am SERVER */
  1195 			/* I am SERVER */
  1170 			if (whoami == SDO_SERVER) {
  1196 			if (whoami == SDO_SERVER) {
  1171 				/* Receiving a upload segment. */
  1197 				/* Receiving a upload segment. */
  1172 				/* A SDO transfert should have been yet initiated. */
  1198 				/* A SDO transfert should have been yet initiated. */
  1173 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
  1174 				if (!err)
  1199 				if (!err)
  1175 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
  1200 					err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
  1176 				if (err) {
  1201 				if (err) {
  1177 					MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
  1202 					MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
  1178 							CliServNbr);
  1203 							CliServNbr);
  1225 			} /* end if SERVER*/
  1250 			} /* end if SERVER*/
  1226 			else {
  1251 			else {
  1227 				/* I am CLIENT */
  1252 				/* I am CLIENT */
  1228 				/* It is the response for the previous initiate download request. */
  1253 				/* It is the response for the previous initiate download request. */
  1229 				/* We should find a line opened for this. */
  1254 				/* We should find a line opened for this. */
  1230 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line);
       
  1231 				if (!err)
  1255 				if (!err)
  1232 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
  1256 					err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
  1233 				if (err) {
  1257 				if (err) {
  1234 					MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
  1258 					MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
  1235 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1259 					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
  1281 				(UNS32)m->data[4] |
  1305 				(UNS32)m->data[4] |
  1282 				((UNS32)m->data[5] << 8) |
  1306 				((UNS32)m->data[5] << 8) |
  1283 				((UNS32)m->data[6] << 16) |
  1307 				((UNS32)m->data[6] << 16) |
  1284 				((UNS32)m->data[7] << 24);
  1308 				((UNS32)m->data[7] << 24);
  1285 			/* Received SDO abort. */
  1309 			/* Received SDO abort. */
  1286 			/* Looking for the line concerned. */
       
  1287 			if (whoami == SDO_SERVER) {
  1310 			if (whoami == SDO_SERVER) {
  1288 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
  1289 				if (!err) {
  1311 				if (!err) {
  1290 					resetSDOline( d, line );
  1312 					resetSDOline( d, line );
  1291 					MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
  1313 					MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
  1292 				}
  1314 				}
  1293 				else
  1315 				else
  1294 					MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
  1316 					MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
  1295 				/* Tips : The end user has no way to know that the server node has received an abort SDO. */
  1317 				/* Tips : The end user has no way to know that the server node has received an abort SDO. */
  1296 				/* Its is ok, I think.*/
  1318 				/* Its is ok, I think.*/
  1297 			}
  1319 			}
  1298 			else { /* If I am CLIENT */
  1320 			else { /* If I am CLIENT */
  1299 				err = getSDOlineOnUse( d, CliServNbr, whoami, &line );
       
  1300 				if (!err) {
  1321 				if (!err) {
  1301 					/* The line *must* be released by the core program. */
  1322 					/* The line *must* be released by the core program. */
  1302 					StopSDO_TIMER(line)
  1323 					StopSDO_TIMER(line)
  1303 						d->transfers[line].state = SDO_ABORTED_RCV;
  1324 						d->transfers[line].state = SDO_ABORTED_RCV;
  1304 					d->transfers[line].abortCode = abortCode;
  1325 					d->transfers[line].abortCode = abortCode;
  1307 				}
  1328 				}
  1308 				else
  1329 				else
  1309 					MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
  1330 					MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
  1310 			}
  1331 			}
  1311 			break;
  1332 			break;
       
  1333 		case 5: /* Command specifier for data transmission - the client or server is the data producer */
       
  1334 			SubCommand = getSDOblockSC(m->data[0]);
       
  1335 			if (whoami == SDO_SERVER) { /* Server block upload */
       
  1336 				if (SubCommand == SDO_BCS_INITIATE_UPLOAD_REQUEST) {
       
  1337 				    index = getSDOindex(m->data[1],m->data[2]);
       
  1338 				    subIndex = getSDOsubIndex(m->data[3]);
       
  1339 				    MSG_WAR(0x3AB2, "Received SDO Initiate block upload defined at index 0x1200 + ",
       
  1340 						CliServNbr);
       
  1341 				    MSG_WAR(0x3AB3, "Reading at index : ", index);
       
  1342 				    MSG_WAR(0x3AB4, "Reading at subIndex : ", subIndex);
       
  1343 				    /* Search if a SDO transfert have been yet initiated */
       
  1344 				    if (! err) {
       
  1345 					    MSG_ERR(0x1A93, "SDO error : Transmission yet started at line : ", line);
       
  1346 					    MSG_WAR(0x3AB5, "Server Nbr = ", CliServNbr);
       
  1347 					    failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
       
  1348 					    return 0xFF;
       
  1349 				    }
       
  1350 				    /* No line on use. Great !*/
       
  1351 				    /* Try to open a new line.*/
       
  1352 				    err = getSDOfreeLine( d, whoami, &line );
       
  1353 				    if (err) {
       
  1354 					    MSG_ERR(0x1A73, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
       
  1355 					    failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
       
  1356 					    return 0xFF;
       
  1357 				    }
       
  1358 				    initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);
       
  1359                     d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
       
  1360                     d->transfers[line].blksize = m->data[4];
       
  1361 				    /* Transfer data from dictionary to the line structure. */
       
  1362 				    errorCode = objdictToSDOline(d, line);
       
  1363 				    if (errorCode) {
       
  1364 					    MSG_ERR(0x1A95, "SDO error : Unable to copy the data from object dictionary. Err code : ",
       
  1365 							errorCode);
       
  1366 					    failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);
       
  1367 					    return 0xFF;
       
  1368 				    }
       
  1369  				    /* Preparing the response.*/
       
  1370 				    getSDOlineRestBytes(d, line, &nbBytes);	/* get Nb bytes to transfer */
       
  1371                     d->transfers[line].objsize = nbBytes;
       
  1372                     data[0] = (6 << 5) | (1 << 1) | SDO_BSS_INITIATE_UPLOAD_RESPONSE;
       
  1373 					data[1] = index & 0xFF;        /* LSB */
       
  1374 					data[2] = (index >> 8) & 0xFF; /* MSB */
       
  1375 					data[3] = subIndex;
       
  1376 					data[4] = nbBytes;
       
  1377 					data[5] = nbBytes >> 8;
       
  1378 					data[6] = nbBytes >> 16;
       
  1379 					data[7] = nbBytes >> 24;
       
  1380 					MSG_WAR(0x3A9A, "SDO. Sending normal block upload initiate response defined at index 0x1200 + ", nodeId);
       
  1381 					sendSDO(d, whoami, CliServNbr, data);
       
  1382                 }
       
  1383 				else if (SubCommand == SDO_BCS_END_UPLOAD_REQUEST) {
       
  1384 				    MSG_WAR(0x3AA2, "Received SDO block END upload request defined at index 0x1200 + ", CliServNbr);
       
  1385  				    /* A SDO transfert should have been yet initiated. */
       
  1386 				    if (!err)
       
  1387 					    err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;
       
  1388 				    if (err) {
       
  1389 					    MSG_ERR(0x1AA1, "SDO error : Received block upload request for unstarted trans. index 0x1200 + ",
       
  1390 							    CliServNbr);
       
  1391 					    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1392 					    return 0xFF;
       
  1393 				    }
       
  1394                     /* Release the line */
       
  1395 					resetSDOline(d, line);
       
  1396                 }
       
  1397 				else if ((SubCommand == SDO_BCS_UPLOAD_RESPONSE) || (SubCommand == SDO_BCS_START_UPLOAD)) {
       
  1398  				    /* A SDO transfert should have been yet initiated. */
       
  1399 				    if (!err)
       
  1400 					    err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;
       
  1401 				    if (err) {
       
  1402 					    MSG_ERR(0x1AA1, "SDO error : Received block upload response for unstarted trans. index 0x1200 + ",
       
  1403 							    CliServNbr);
       
  1404 					    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1405 					    return 0xFF;
       
  1406 				    }
       
  1407 				    /* Reset the wathdog */
       
  1408 				    RestartSDO_TIMER(line);
       
  1409 				    /* Uploading first or next block */
       
  1410 				    index = d->transfers[line].index;
       
  1411 				    subIndex = d->transfers[line].subIndex;
       
  1412                     if (SubCommand == SDO_BCS_UPLOAD_RESPONSE) {
       
  1413 					    MSG_WAR(0x3AA2, "Received SDO block upload response defined at index 0x1200 + ", CliServNbr);
       
  1414                         d->transfers[line].blksize = m->data[2];
       
  1415                         AckSeq = (m->data[1]) & 0x7f;
       
  1416                         getSDOlineRestBytes(d, line, &nbBytes);
       
  1417                         if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){ /* Si tout est envoyé et confirmé reçu on envoi un block end upload response */
       
  1418                             data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BSS_END_UPLOAD_RESPONSE;
       
  1419                             for (i = 1 ; i < 8 ; i++)
       
  1420 						        data[i] = 0;
       
  1421 					        MSG_WAR(0x3AA5, "SDO. Sending block END upload response defined at index 0x1200 + ", CliServNbr);
       
  1422 					        sendSDO(d, whoami, CliServNbr, data);
       
  1423                             break;
       
  1424                         }
       
  1425                         else
       
  1426                             d->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;
       
  1427                         if(d->transfers[line].offset > d->transfers[line].count) { /* Bad AckSeq reveived (too high) */
       
  1428 					        MSG_ERR(0x1AA1, "SDO error : Received upload response with bad ackseq index 0x1200 + ",
       
  1429 							    CliServNbr);
       
  1430 					        failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1431 					        return 0xFF;
       
  1432                         }
       
  1433            			}
       
  1434                     else
       
  1435 					    MSG_WAR(0x3AA2, "Received SDO block START upload defined at index 0x1200 + ", CliServNbr);
       
  1436                     d->transfers[line].lastblockoffset = d->transfers[line].offset;
       
  1437                     for(SeqNo = 1 ; SeqNo <= d->transfers[line].blksize ; SeqNo++) {
       
  1438                         d->transfers[line].seqno = SeqNo;
       
  1439 				        getSDOlineRestBytes(d, line, &nbBytes);
       
  1440                         if (nbBytes > 7) {
       
  1441 					        /* The segment to transfer is not the last one.*/
       
  1442  					        data[0] = SeqNo;
       
  1443 					        err = lineToSDO(d, line, 7, data + 1);
       
  1444 					        if (err) {
       
  1445 						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
       
  1446 						        return 0xFF;
       
  1447 					        }
       
  1448 					        MSG_WAR(0x3AA5, "SDO. Sending upload segment defined at index 0x1200 + ", CliServNbr);
       
  1449 					        sendSDO(d, whoami, CliServNbr, data);
       
  1450 				        }
       
  1451 				        else {
       
  1452 					        /* Last segment is in this block */
       
  1453 					        data[0] = 0x80 | SeqNo;
       
  1454 					        err = lineToSDO(d, line, nbBytes, data + 1);
       
  1455 					        if (err) {
       
  1456 						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
       
  1457 						        return 0xFF;
       
  1458 					        }
       
  1459 					        for (i = nbBytes + 1 ; i < 8 ; i++)
       
  1460 						        data[i] = 0;
       
  1461 					        MSG_WAR(0x3AA5, "SDO. Sending last upload segment defined at index 0x1200 + ", CliServNbr);
       
  1462 					        sendSDO(d, whoami, CliServNbr, data);
       
  1463                             d->transfers[line].endfield = 7 - nbBytes;
       
  1464                             break;
       
  1465 				        }
       
  1466                     }
       
  1467                 }
       
  1468 			}      /* end if SERVER */
       
  1469 			else { /* if CLIENT (block download) */
       
  1470                 if ((SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) || (SubCommand == SDO_BSS_DOWNLOAD_RESPONSE)) {
       
  1471                     /* We should find a line opened for this. */
       
  1472                     if (!err)
       
  1473                         err = d->transfers[line].state != SDO_BLOCK_DOWNLOAD_IN_PROGRESS;
       
  1474                     if (err) {
       
  1475                         MSG_ERR(0x1AAA, "SDO error : Received response for unknown block download request from node id", nodeId);
       
  1476                         failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1477                         return 0xFF;
       
  1478                     }
       
  1479                     /* Reset the watchdog */
       
  1480                     RestartSDO_TIMER(line)
       
  1481                     if (SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) {
       
  1482                            index = d->transfers[line].index;
       
  1483                         subIndex = d->transfers[line].subIndex;
       
  1484                         d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
       
  1485                         d->transfers[line].blksize = m->data[4];
       
  1486                     }
       
  1487                     else {
       
  1488                     	d->transfers[line].blksize = m->data[2];
       
  1489                         AckSeq = (m->data[1]) & 0x7f;
       
  1490                         getSDOlineRestBytes(d, line, &nbBytes);
       
  1491                         if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){ /* Si tout est envoyé et confirmé reçu on envoi un block end download request */
       
  1492                             data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BCS_END_DOWNLOAD_REQUEST;
       
  1493                             for (i = 1 ; i < 8 ; i++)
       
  1494 						        data[i] = 0;
       
  1495 					        MSG_WAR(0x3AA5, "SDO. Sending block END download request defined at index 0x1200 + ", CliServNbr);
       
  1496 					        sendSDO(d, whoami, CliServNbr, data);
       
  1497                             break;
       
  1498                         }
       
  1499                         else
       
  1500                             d->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;
       
  1501                         if(d->transfers[line].offset > d->transfers[line].count) { /* Bad AckSeq reveived (too high) */
       
  1502 					        MSG_ERR(0x1AA1, "SDO error : Received upload segment with bad ackseq index 0x1200 + ",
       
  1503 							    CliServNbr);
       
  1504 					        failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1505 					        return 0xFF;
       
  1506                         }
       
  1507 					}
       
  1508                  	d->transfers[line].lastblockoffset = d->transfers[line].offset;
       
  1509                 	for(SeqNo = 1 ; SeqNo <= d->transfers[line].blksize ; SeqNo++) {
       
  1510                         d->transfers[line].seqno = SeqNo;
       
  1511 				        getSDOlineRestBytes(d, line, &nbBytes);
       
  1512                         if (nbBytes > 7) {
       
  1513 					        /* The segment to transfer is not the last one.*/
       
  1514  					        data[0] = SeqNo;
       
  1515 					        err = lineToSDO(d, line, 7, data + 1);
       
  1516 					        if (err) {
       
  1517 						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
       
  1518 						        return 0xFF;
       
  1519 					        }
       
  1520 					        MSG_WAR(0x3AAB, "SDO. Sending download segment to node id ", nodeId);
       
  1521 					        sendSDO(d, whoami, CliServNbr, data);
       
  1522 				        }
       
  1523 				        else {
       
  1524 					        /* Last segment is in this block */
       
  1525 					        data[0] = 0x80 | SeqNo;
       
  1526 					        err = lineToSDO(d, line, nbBytes, data + 1);
       
  1527 					        if (err) {
       
  1528 						        failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
       
  1529 						        return 0xFF;
       
  1530 					        }
       
  1531 					        for (i = nbBytes + 1 ; i < 8 ; i++)
       
  1532 						        data[i] = 0;
       
  1533 					        MSG_WAR(0x3AAB, "SDO. Sending last download segment to node id ", nodeId);
       
  1534 					        sendSDO(d, whoami, CliServNbr, data);
       
  1535                             d->transfers[line].endfield = 7 - nbBytes;
       
  1536                             break;
       
  1537 				        }
       
  1538                     }
       
  1539 				}
       
  1540 				else if (SubCommand == SDO_BSS_END_DOWNLOAD_RESPONSE) {
       
  1541 					MSG_WAR(0x3AAC, "SDO End block download response from nodeId", nodeId);
       
  1542 					StopSDO_TIMER(line)
       
  1543 					d->transfers[line].state = SDO_FINISHED;
       
  1544 					if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
       
  1545 					return 0x00;
       
  1546 				}
       
  1547 				else {
       
  1548 			    	MSG_ERR(0x1AAB, "SDO error block download : Received wrong subcommand from nodeId", nodeId);
       
  1549     				failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1550 	    			return 0xFF;
       
  1551 				}
       
  1552 			}      /* end if CLIENT */
       
  1553 			break;
       
  1554 		case 6: /* Command specifier for data reception - the client or server is the data consumer */
       
  1555 			if (whoami == SDO_SERVER) { /* Server block download */
       
  1556 				if (err) {
       
  1557 					/* Nothing already started */
       
  1558 					SubCommand = (m->data[0]) & 1;
       
  1559 					if (SubCommand != SDO_BCS_INITIATE_DOWNLOAD_REQUEST) {
       
  1560 			    	    MSG_ERR(0x1AAC, "SDO error block download : Received wrong subcommand from node id", nodeId);
       
  1561     				    failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1562 	    			    return 0xFF;
       
  1563 				    }
       
  1564 					index = getSDOindex(m->data[1],m->data[2]);
       
  1565 					subIndex = getSDOsubIndex(m->data[3]);
       
  1566 					MSG_WAR(0x3A9B, "Received SDO block download initiate defined at index 0x1200 + ",
       
  1567 						CliServNbr);
       
  1568 					MSG_WAR(0x3A9B, "Writing at index : ", index);
       
  1569 					MSG_WAR(0x3A9B, "Writing at subIndex : ", subIndex);
       
  1570 					/* Try to open a new line. */
       
  1571 					err = getSDOfreeLine( d, whoami, &line );
       
  1572 					if (err) {
       
  1573 						MSG_ERR(0x1A89, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
       
  1574 						failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
       
  1575 						return 0xFF;
       
  1576 					}
       
  1577 					initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);
       
  1578                     d->transfers[line].rxstep = RXSTEP_STARTED;
       
  1579                     d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
       
  1580 					if ((m->data[0]) & 2)	/* if data set size is indicated */
       
  1581                     	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;
       
  1582                     data[0] = (5 << 5) | SDO_BSS_INITIATE_DOWNLOAD_RESPONSE;
       
  1583 					data[1] = index;        /* LSB */
       
  1584 					data[2] = index >> 8;   /* MSB */
       
  1585 					data[3] = subIndex;
       
  1586 					data[4] = SDO_BLOCK_SIZE;
       
  1587 					data[5] = data[6] = data[7] = 0;
       
  1588 					MSG_WAR(0x3AAD, "SDO. Sending block download initiate response - index 0x1200 + ", CliServNbr);
       
  1589 					sendSDO(d, whoami, CliServNbr, data);
       
  1590 				}
       
  1591 				else if (d->transfers[line].rxstep == RXSTEP_STARTED) {
       
  1592 					MSG_WAR(0x3A9B, "Received SDO block download data segment - index 0x1200 + ", CliServNbr);
       
  1593     		    	RestartSDO_TIMER(line)
       
  1594 					SeqNo = m->data[0] & 0x7F;
       
  1595 					if (m->data[0] & 0x80) {	/* Last segment ? */
       
  1596 					    if(SeqNo == (d->transfers[line].seqno + 1)) {
       
  1597 							d->transfers[line].rxstep = RXSTEP_END;
       
  1598 							d->transfers[line].seqno = SeqNo;
       
  1599 							/* Store the data temporary because we don't know yet how many bytes do not contain data */
       
  1600 							memcpy(d->transfers[line].tmpData, m->data, 8);
       
  1601 						}
       
  1602 						data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;
       
  1603 						data[1] = d->transfers[line].seqno;
       
  1604 						data[2] = SDO_BLOCK_SIZE;
       
  1605 						data[3] = data[4] = data[5] = data[6] = data[7] = 0;
       
  1606 						MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);
       
  1607 						sendSDO(d, whoami, CliServNbr, data);
       
  1608                         d->transfers[line].seqno = 0;
       
  1609 					}
       
  1610 					else {
       
  1611 					   	if (SeqNo == (d->transfers[line].seqno + 1)) {	
       
  1612 							d->transfers[line].seqno = SeqNo;
       
  1613 							/* Store the data in the transfert structure. */
       
  1614 							err = SDOtoLine(d, line, 7, (*m).data + 1);
       
  1615 							if (err) {
       
  1616 								failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
       
  1617 								return 0xFF;
       
  1618 							}
       
  1619 						}
       
  1620 						if (SeqNo == SDO_BLOCK_SIZE) {
       
  1621 							data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;
       
  1622 							data[1] = d->transfers[line].seqno;
       
  1623 							data[2] = SDO_BLOCK_SIZE;
       
  1624 							data[3] = data[4] = data[5] = data[6] = data[7] = 0;
       
  1625 							MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);
       
  1626 							sendSDO(d, whoami, CliServNbr, data);
       
  1627                             d->transfers[line].seqno = 0;
       
  1628 						}
       
  1629 					}
       
  1630 				}
       
  1631 				else if (d->transfers[line].rxstep == RXSTEP_END) { /* endphase */
       
  1632 					MSG_WAR(0x3A9B, "Received SDO block download end request - index 0x1200 + ", CliServNbr);
       
  1633 					/* here store remaining bytes in tmpData to line, check size and confirm or abort */
       
  1634 					if ((m->data[0] & 1) != SDO_BCS_END_DOWNLOAD_REQUEST) {
       
  1635 		    			MSG_ERR(0x1AAD, "SDO error block download : Received wrong subcommand - index 0x1200 + ", CliServNbr);
       
  1636     					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1637 	    				return 0xFF;
       
  1638 					}
       
  1639     		    	RestartSDO_TIMER(line)
       
  1640 					NbBytesNoData = (m->data[0]>>2) & 0x07;
       
  1641 					/* Store the data in the transfert structure. */
       
  1642 					err = SDOtoLine(d, line, 7-NbBytesNoData, d->transfers[line].tmpData + 1);
       
  1643 					if (err) {
       
  1644 						failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
       
  1645 						return 0xFF;
       
  1646 					}
       
  1647 					if(d->transfers[line].objsize){ /* If size was indicated in the initiate request */
       
  1648 						if (d->transfers[line].objsize != d->transfers[line].offset){
       
  1649 		    					MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - index 0x1200 + ", CliServNbr);
       
  1650     							failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);
       
  1651 	    						return 0xFF;
       
  1652 						}
       
  1653 					}
       
  1654 					data[0] = (5 << 5) | SDO_BSS_END_DOWNLOAD_RESPONSE;
       
  1655 					for (i = 1 ; i < 8 ; i++)
       
  1656 						data[i] = 0;
       
  1657 					MSG_WAR(0x3AAF, "SDO. Sending block download end response - index 0x1200 + ", CliServNbr);
       
  1658 					sendSDO(d, whoami, CliServNbr, data);
       
  1659 					/* Transfering line data to object dictionary. */
       
  1660 					errorCode = SDOlineToObjdict(d, line);
       
  1661 					if (errorCode) {
       
  1662 						MSG_ERR(0x1AAF, "SDO error : Unable to copy the data in the object dictionary", 0);
       
  1663 						failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, errorCode);
       
  1664 						return 0xFF;
       
  1665 					}
       
  1666 					/* Release of the line */
       
  1667 					resetSDOline(d, line);
       
  1668 					MSG_WAR(0x3AAF, "SDO. End of block download defined at index 0x1200 + ", CliServNbr);
       
  1669 				}
       
  1670 		    }      /* end if SERVER */
       
  1671 		    else { /* if CLIENT (block upload) */
       
  1672 				if (err) {
       
  1673        				/* Nothing already started */
       
  1674 			    	MSG_ERR(0x1AAD, "SDO error block upload : no transmission started", nodeId);
       
  1675     				failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1676 	    			return 0xFF;
       
  1677 				}
       
  1678     			RestartSDO_TIMER(line)
       
  1679 				if (d->transfers[line].rxstep == RXSTEP_INIT) {
       
  1680 				    if ((m->data[0] & 1) == SDO_BSS_INITIATE_UPLOAD_RESPONSE) {
       
  1681 					    MSG_WAR(0x3A9C, "Received SDO block upload response from node id ", nodeId);
       
  1682 						d->transfers[line].rxstep = RXSTEP_STARTED;
       
  1683                         d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;
       
  1684 					    if ((m->data[0]) & 2)	/* if data set size is indicated */
       
  1685                     	    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;
       
  1686                         data[0] = (5 << 5) | SDO_BCS_START_UPLOAD;
       
  1687 					    for (i = 1 ; i < 8 ; i++)
       
  1688 						    data[i] = 0;
       
  1689                         MSG_WAR(0x3AB6, "SDO. Sending block upload start to node id ", nodeId);
       
  1690 					    sendSDO(d, whoami, CliServNbr, data);
       
  1691                     }
       
  1692                 }
       
  1693 				else if (d->transfers[line].rxstep == RXSTEP_STARTED) {
       
  1694 					SeqNo = m->data[0] & 0x7F;
       
  1695 					if (m->data[0] & 0x80) {	/* Last segment ? */
       
  1696 					    if(SeqNo == (d->transfers[line].seqno + 1)) {
       
  1697 							d->transfers[line].rxstep = RXSTEP_END;
       
  1698 							d->transfers[line].seqno = SeqNo;
       
  1699 							/* Store the data temporary because we don't know yet how many bytes do not contain data */
       
  1700 							memcpy(d->transfers[line].tmpData, m->data, 8);
       
  1701 						}
       
  1702 						data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;
       
  1703 						data[1] = d->transfers[line].seqno;
       
  1704 						data[2] = SDO_BLOCK_SIZE;
       
  1705 						data[3] = data[4] = data[5] = data[6] = data[7] = 0;
       
  1706 						MSG_WAR(0x3AB7, "SDO. Sending block upload response to node id ", nodeId);
       
  1707 						sendSDO(d, whoami, CliServNbr, data);
       
  1708                         d->transfers[line].seqno = 0;
       
  1709 					}
       
  1710 					else {
       
  1711 					   	if (SeqNo == (d->transfers[line].seqno + 1)) {	
       
  1712 							d->transfers[line].seqno = SeqNo;
       
  1713 							/* Store the data in the transfert structure. */
       
  1714 							err = SDOtoLine(d, line, 7, (*m).data + 1);
       
  1715 							if (err) {
       
  1716 								failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
       
  1717 								return 0xFF;
       
  1718 							}
       
  1719 						}
       
  1720 						if (SeqNo == SDO_BLOCK_SIZE) {
       
  1721 							data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;
       
  1722 							data[1] = d->transfers[line].seqno;
       
  1723 							data[2] = SDO_BLOCK_SIZE;
       
  1724 							data[3] = data[4] = data[5] = data[6] = data[7] = 0;
       
  1725 							MSG_WAR(0x3AAE, "SDO. Sending block upload response to node id ", nodeId);
       
  1726 							sendSDO(d, whoami, CliServNbr, data);
       
  1727                             d->transfers[line].seqno = 0;
       
  1728 						}
       
  1729 					}
       
  1730 				}
       
  1731 				else if (d->transfers[line].rxstep == RXSTEP_END) { /* endphase */
       
  1732 					/* here store remaining bytes in tmpData to line, check size and confirm or abort */
       
  1733 					if ((m->data[0] & 1) != SDO_BSS_END_UPLOAD_RESPONSE) {
       
  1734 			    		MSG_ERR(0x1AAD, "SDO error block upload : Received wrong subcommand from node id ", nodeId);
       
  1735     					failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
       
  1736 	    				return 0xFF;
       
  1737 					}
       
  1738 					NbBytesNoData = (m->data[0]>>2) & 0x07;
       
  1739 					/* Store the data in the transfert structure. */
       
  1740 					err = SDOtoLine(d, line, 7-NbBytesNoData, d->transfers[line].tmpData + 1);
       
  1741 					if (err) {
       
  1742 						failedSDO(d, CliServNbr, whoami, d->transfers[line].index,  d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);
       
  1743 						return 0xFF;
       
  1744 					}
       
  1745 					if(d->transfers[line].objsize){ /* If size was indicated in the initiate request */
       
  1746 						if (d->transfers[line].objsize != d->transfers[line].offset){
       
  1747 			    				MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - from node id ", nodeId);
       
  1748     							failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);
       
  1749 	    						return 0xFF;
       
  1750 						}
       
  1751 					}
       
  1752 					data[0] = (5 << 5) | SDO_BCS_END_UPLOAD_REQUEST;
       
  1753 					for (i = 1 ; i < 8 ; i++)
       
  1754 						data[i] = 0;
       
  1755 					MSG_WAR(0x3AAF, "SDO. Sending block upload end request to node id ", nodeId);
       
  1756 					sendSDO(d, whoami, CliServNbr, data);
       
  1757 					MSG_WAR(0x3AAF, "SDO. End of block upload request", 0);
       
  1758                     StopSDO_TIMER(line)
       
  1759 					d->transfers[line].state = SDO_FINISHED;
       
  1760 				    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
       
  1761 				}
       
  1762 			}      /* end if CLIENT */
       
  1763 			break;
  1312 		default:
  1764 		default:
  1313 			/* Error : Unknown cs */
  1765 			/* Error : Unknown cs */
  1314 			MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
  1766 			MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", cs);
  1315 			return 0xFF;
  1767 			return 0xFF;
  1316 
  1768 
  1317 	} /* End switch */
  1769 	} /* End switch */
  1318 	return 0;
  1770 	return 0;
  1319 }
  1771 }
  1386  ** @param endianize
  1838  ** @param endianize
  1387  **
  1839  **
  1388  ** @return
  1840  ** @return
  1389  **/
  1841  **/
  1390 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
  1842 INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
  1391 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
  1843 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode)
  1392 {
  1844 {
  1393 	UNS8 err;
  1845 	UNS8 err;
  1394 	UNS8 line;
  1846 	UNS8 line;
  1395 	UNS8 CliNbr;
  1847 	UNS8 CliNbr;
  1396 	UNS32 j;
  1848 	UNS32 j;
  1416 	err = getSDOfreeLine( d, SDO_CLIENT, &line );
  1868 	err = getSDOfreeLine( d, SDO_CLIENT, &line );
  1417 	if (err) {
  1869 	if (err) {
  1418 		MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
  1870 		MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
  1419 		return (0xFF);
  1871 		return (0xFF);
  1420 	}
  1872 	}
  1421 	initSDOline(d, line, CliNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
  1873     if(useBlockMode) {
       
  1874 	    initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);
       
  1875 	    d->transfers[line].objsize = count;
       
  1876     }
       
  1877     else 
       
  1878 	    initSDOline(d, line, CliNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
  1422 	d->transfers[line].count = count;
  1879 	d->transfers[line].count = count;
  1423 	d->transfers[line].dataType = dataType;
  1880 	d->transfers[line].dataType = dataType;
  1424 
       
  1425 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
  1881 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
  1426 	{
  1882 	{
  1427 		UNS8* lineData = d->transfers[line].data;
  1883 		UNS8* lineData = d->transfers[line].data;
  1428 		if (count > SDO_MAX_LENGTH_TRANSFERT)
  1884 		if (count > SDO_MAX_LENGTH_TRANSFERT)
  1429 		{
  1885 		{
  1459 #  else
  1915 #  else
  1460 		d->transfers[line].data[j] = ((char *)data)[j];
  1916 		d->transfers[line].data[j] = ((char *)data)[j];
  1461 #  endif
  1917 #  endif
  1462 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
  1918 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
  1463 	}
  1919 	}
  1464 	/* Send the SDO to the server. Initiate download, cs=1. */
  1920     if(useBlockMode) {
  1465 	if (count <= 4) { /* Expedited transfert */
  1921 	    buf[0] = (6 << 5) | (1 << 1 );   /* CCS = 6 , CC = 0 , S = 1 , CS = 0 */
  1466 		buf[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
  1922  	    for (i = 0 ; i < 4 ; i++)
  1467 		for (i = 4 ; i < 8 ; i++)
  1923 		    buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
  1468 			buf[i] = d->transfers[line].data[i - 4];
  1924     }
  1469 		d->transfers[line].offset = count;
  1925     else {
  1470 	}
  1926 	    /* Send the SDO to the server. Initiate download, cs=1. */
  1471 	else { /** Normal transfert */
  1927 	    if (count <= 4) { /* Expedited transfert */
  1472 		buf[0] = (1 << 5) | 1;
  1928 		    buf[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
  1473 		for (i = 0 ; i < 4 ; i++)
  1929 		    for (i = 4 ; i < 8 ; i++)
  1474 			buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
  1930 			    buf[i] = d->transfers[line].data[i - 4];
  1475 	}
  1931 		    d->transfers[line].offset = count;
       
  1932 	    }
       
  1933 	    else { /** Normal transfert */
       
  1934 		    buf[0] = (1 << 5) | 1;
       
  1935 		    for (i = 0 ; i < 4 ; i++)
       
  1936 			    buf[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
       
  1937 	    }
       
  1938     }
  1476 	buf[1] = index & 0xFF;        /* LSB */
  1939 	buf[1] = index & 0xFF;        /* LSB */
  1477 	buf[2] = (index >> 8) & 0xFF; /* MSB */
  1940 	buf[2] = (index >> 8) & 0xFF; /* MSB */
  1478 	buf[3] = subIndex;
  1941 	buf[3] = subIndex;
  1479 
  1942 
  1480 	d->transfers[line].Callback = Callback;
  1943 	d->transfers[line].Callback = Callback;
  1503  ** @param data
  1966  ** @param data
  1504  **
  1967  **
  1505  ** @return
  1968  ** @return
  1506  **/
  1969  **/
  1507 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
  1970 UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
  1508 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
  1971 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode)
  1509 {
  1972 {
  1510 	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
  1973 	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1, useBlockMode);
  1511 }
  1974 }
  1512 
  1975 
  1513 /*!
  1976 /*!
  1514  **
  1977  **
  1515  **
  1978  **
  1523  ** @param Callback
  1986  ** @param Callback
  1524  **
  1987  **
  1525  ** @return
  1988  ** @return
  1526  **/
  1989  **/
  1527 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
  1990 UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
  1528 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
  1991 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 useBlockMode)
  1529 {
  1992 {
  1530 	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
  1993 	return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1, useBlockMode);
  1531 }
  1994 }
  1532 
  1995 
  1533 UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
  1996 UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
  1534 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
  1997 		UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode)
  1535 {
  1998 {
  1536 	UNS8 ret;
  1999 	UNS8 ret;
  1537 	UNS16 lastIndex;
  2000 	UNS16 lastIndex;
  1538 	UNS16 offset;
  2001 	UNS16 offset;
  1539 	UNS8 nodeIdServer;
  2002 	UNS8 nodeIdServer;
  1540 	UNS8 i;
  2003 	UNS8 i;
  1541 
  2004 
  1542 	ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize);
  2005 	ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize, useBlockMode);
  1543 	if(ret == 0xFE)
  2006 	if(ret == 0xFE)
  1544 	{
  2007 	{
  1545 		offset = d->firstIndex->SDO_CLT;
  2008 		offset = d->firstIndex->SDO_CLT;
  1546 		lastIndex = d->lastIndex->SDO_CLT;
  2009 		lastIndex = d->lastIndex->SDO_CLT;
  1547 		if (offset == 0)
  2010 		if (offset == 0)
  1561 			if(nodeIdServer == 0)
  2024 			if(nodeIdServer == 0)
  1562 			{
  2025 			{
  1563 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
  2026 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
  1564 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
  2027 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
  1565 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
  2028 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
  1566 				return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
  2029 				return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1, useBlockMode);
  1567 			}
  2030 			}
  1568 			offset++;
  2031 			offset++;
  1569 		}
  2032 		}
  1570 		return 0xFF;
  2033 		return 0xFF;
  1571 	}
  2034 	}
  1589  ** @param dataType
  2052  ** @param dataType
  1590  ** @param Callback
  2053  ** @param Callback
  1591  **
  2054  **
  1592  ** @return
  2055  ** @return
  1593  **/
  2056  **/
  1594 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
  2057 INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
  1595 {
  2058 {
  1596 	UNS8 err;
  2059 	UNS8 err;
  1597 	UNS8 i;
  2060 	UNS8 i;
  1598 	UNS8 CliNbr;
  2061 	UNS8 CliNbr;
  1599 	UNS8 line;
  2062 	UNS8 line;
  1621 		return (0xFF);
  2084 		return (0xFF);
  1622 	}
  2085 	}
  1623 	else
  2086 	else
  1624 		MSG_WAR(0x3AE0, "Transmission on line : ", line);
  2087 		MSG_WAR(0x3AE0, "Transmission on line : ", line);
  1625 
  2088 
  1626 	initSDOline(d, line, CliNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
  2089     if(useBlockMode) {
  1627 	getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);
  2090 	    initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);
  1628 	/* Send the SDO to the server. Initiate upload, cs=2. */
  2091 	    /* Send the SDO to the server. Initiate block upload, cs=0. */
  1629 	d->transfers[line].dataType = dataType;
  2092 	    d->transfers[line].dataType = dataType;
  1630 	data[0] = (2 << 5);
  2093 	    data[0] = (5 << 5) | SDO_BCS_INITIATE_UPLOAD_REQUEST;
  1631 	data[1] = index & 0xFF;        /* LSB */
  2094 	    data[1] = index & 0xFF;        /* LSB */
  1632 	data[2] = (index >> 8) & 0xFF; /* MSB */
  2095 	    data[2] = (index >> 8) & 0xFF; /* MSB */
  1633 	data[3] = subIndex;
  2096 	    data[3] = subIndex;
  1634 	for (i = 4 ; i < 8 ; i++)
  2097 	    data[4] = SDO_BLOCK_SIZE;
  1635 		data[i] = 0;
  2098 	    for (i = 5 ; i < 8 ; i++)
       
  2099 		    data[i] = 0;
       
  2100     }
       
  2101     else {
       
  2102 	    initSDOline(d, line, CliNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
       
  2103 	    /* Send the SDO to the server. Initiate upload, cs=2. */
       
  2104 	    d->transfers[line].dataType = dataType;
       
  2105 	    data[0] = (2 << 5);
       
  2106 	    data[1] = index & 0xFF;        /* LSB */
       
  2107 	    data[2] = (index >> 8) & 0xFF; /* MSB */
       
  2108 	    data[3] = subIndex;
       
  2109 	    for (i = 4 ; i < 8 ; i++)
       
  2110 		    data[i] = 0;
       
  2111     }
  1636 	d->transfers[line].Callback = Callback;
  2112 	d->transfers[line].Callback = Callback;
  1637 	err = sendSDO(d, SDO_CLIENT, CliNbr, data);
  2113 	err = sendSDO(d, SDO_CLIENT, CliNbr, data);
  1638 	if (err) {
  2114 	if (err) {
  1639 		MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
  2115 		MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
  1640 		/* release the line */
  2116 		/* release the line */
  1653  ** @param subIndex
  2129  ** @param subIndex
  1654  ** @param dataType
  2130  ** @param dataType
  1655  **
  2131  **
  1656  ** @return
  2132  ** @return
  1657  **/
  2133  **/
  1658 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
  2134 UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, UNS8 useBlockMode)
  1659 {
  2135 {
  1660 	return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
  2136 	return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL, useBlockMode);
  1661 }
  2137 }
  1662 
  2138 
  1663 /*!
  2139 /*!
  1664  **
  2140  **
  1665  **
  2141  **
  1670  ** @param dataType
  2146  ** @param dataType
  1671  ** @param Callback
  2147  ** @param Callback
  1672  **
  2148  **
  1673  ** @return
  2149  ** @return
  1674  **/
  2150  **/
  1675 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
  2151 UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
  1676 {
  2152 {
  1677 	return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
  2153 	return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
  1678 }
  2154 }
  1679 
  2155 
  1680 UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
  2156 UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode)
  1681 {
  2157 {
  1682 	UNS8 ret;
  2158 	UNS8 ret;
  1683 	UNS16 lastIndex;
  2159 	UNS16 lastIndex;
  1684 	UNS16 offset;
  2160 	UNS16 offset;
  1685 	UNS8 nodeIdServer;
  2161 	UNS8 nodeIdServer;
  1686 	UNS8 i;
  2162 	UNS8 i;
  1687 
  2163 
  1688 	ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
  2164 	ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
  1689 	if(ret == 0xFE)
  2165 	if(ret == 0xFE)
  1690 	{
  2166 	{
  1691 		offset = d->firstIndex->SDO_CLT;
  2167 		offset = d->firstIndex->SDO_CLT;
  1692 		lastIndex = d->lastIndex->SDO_CLT;
  2168 		lastIndex = d->lastIndex->SDO_CLT;
  1693 		if (offset == 0)
  2169 		if (offset == 0)
  1707 			if(nodeIdServer == 0)
  2183 			if(nodeIdServer == 0)
  1708 			{
  2184 			{
  1709 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
  2185 				*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
  1710 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
  2186 				*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
  1711 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
  2187 				*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
  1712 				return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
  2188 				return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode);
  1713 			}
  2189 			}
  1714 			offset++;
  2190 			offset++;
  1715 		}
  2191 		}
  1716 		return 0xFF;
  2192 		return 0xFF;
  1717 	}
  2193 	}
  1729  **
  2205  **
  1730  **
  2206  **
  1731  ** @param d
  2207  ** @param d
  1732  ** @param nodeId
  2208  ** @param nodeId
  1733  ** @param data
  2209  ** @param data
  1734  ** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
  2210  ** @param size : *size MUST contain the size of *data buffer before calling
       
  2211  **                     The function set it to the actual number of written bytes
  1735  ** @param abortCode
  2212  ** @param abortCode
  1736  **
  2213  **
  1737  ** @return
  2214  ** @return
       
  2215  **    SDO_PROVIDED_BUFFER_TOO_SMALL if *data is not big enough
       
  2216  **    or any transmission status value.
  1738  **/
  2217  **/
  1739 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
  2218 UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
  1740 		UNS32 * abortCode)
  2219 		UNS32 * abortCode)
  1741 {
  2220 {
  1742 	UNS32 i;
  2221 	UNS32 i;
  1745 	UNS8 line;
  2224 	UNS8 line;
  1746 	* abortCode = 0;
  2225 	* abortCode = 0;
  1747 
  2226 
  1748 	/* First let's find the corresponding SDO client in our OD  */
  2227 	/* First let's find the corresponding SDO client in our OD  */
  1749 	CliNbr = GetSDOClientFromNodeId(d, nodeId);
  2228 	CliNbr = GetSDOClientFromNodeId(d, nodeId);
  1750 	if(CliNbr >= 0xFE)
  2229 	if(CliNbr >= 0xFE) {
       
  2230         *size = 0;
  1751 		return SDO_ABORTED_INTERNAL;
  2231 		return SDO_ABORTED_INTERNAL;
       
  2232     }
  1752 
  2233 
  1753 	/* Looking for the line tranfert. */
  2234 	/* Looking for the line tranfert. */
  1754 	err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);
  2235 	err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);
  1755 	if (err) {
  2236 	if (err) {
  1756 		MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
  2237 		MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
  1757 		return SDO_ABORTED_INTERNAL;
  2238         *size = 0;
  1758 	}
  2239         return SDO_ABORTED_INTERNAL;
  1759 	* abortCode = d->transfers[line].abortCode;
  2240 	}
  1760 	if (d->transfers[line].state != SDO_FINISHED)
  2241 
       
  2242     /* If transfert not finished just return, but if aborted set abort code and size to 0 */
       
  2243     if (d->transfers[line].state != SDO_FINISHED) {
       
  2244 	    if((d->transfers[line].state == SDO_ABORTED_RCV) || (d->transfers[line].state == SDO_ABORTED_INTERNAL)) {
       
  2245             *abortCode = d->transfers[line].abortCode;
       
  2246             *size = 0;
       
  2247         }
  1761 		return d->transfers[line].state;
  2248 		return d->transfers[line].state;
       
  2249     }
  1762 
  2250 
  1763 	/* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
  2251 	/* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
  1764 	if( d->transfers[line].count == 0)
  2252 	if( d->transfers[line].count == 0)
  1765 		d->transfers[line].count = d->transfers[line].offset;
  2253 		d->transfers[line].count = d->transfers[line].offset;
  1766 	/* use transfers[line].count as max size */
  2254 
  1767 	if( d->transfers[line].count < *size )
  2255     /* Check if the provided buffer is big enough */
  1768 		*size = d->transfers[line].count;
  2256     if(*size < d->transfers[line].count) {
       
  2257 		*size = 0;
       
  2258 		return SDO_PROVIDED_BUFFER_TOO_SMALL;
       
  2259     }
       
  2260 	
       
  2261     /* Give back actual size */
       
  2262     *size = d->transfers[line].count;
  1769 
  2263 
  1770 	/* Copy payload to data pointer */
  2264 	/* Copy payload to data pointer */
  1771 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
  2265 #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
  1772 	{
  2266 	{
  1773 		UNS8 *lineData = d->transfers[line].data;
  2267 		UNS8 *lineData = d->transfers[line].data;
  1797 # else
  2291 # else
  1798 		( (char *) data)[i] = d->transfers[line].data[i];
  2292 		( (char *) data)[i] = d->transfers[line].data[i];
  1799 # endif
  2293 # endif
  1800 	}
  2294 	}
  1801 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
  2295 #endif //SDO_DYNAMIC_BUFFER_ALLOCATION
       
  2296     resetSDOline(d, line);
  1802 	return SDO_FINISHED;
  2297 	return SDO_FINISHED;
  1803 }
  2298 }
  1804 
  2299 
  1805 /*!
  2300 /*!
  1806  **
  2301  **
  1828 	if (err) {
  2323 	if (err) {
  1829 		MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
  2324 		MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
  1830 		return SDO_ABORTED_INTERNAL;
  2325 		return SDO_ABORTED_INTERNAL;
  1831 	}
  2326 	}
  1832 	* abortCode = d->transfers[line].abortCode;
  2327 	* abortCode = d->transfers[line].abortCode;
  1833 	return d->transfers[line].state;
  2328     if (d->transfers[line].state != SDO_FINISHED)
  1834 }
  2329 	    return d->transfers[line].state;
       
  2330     resetSDOline(d, line);
       
  2331 	return SDO_FINISHED;
       
  2332 }