/*
* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
* The corresponding license agreement applies. This hint shall not be removed.
* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
*/

/**
\addtogroup CoE CAN Application Profile over EtherCAT
@{
*/

/**
\file    sdoserv.c
\author EthercatSSC@beckhoff.com
\brief Implementation
The SDO server handles all sdo and sdo information services

\version 5.13

<br>Changes to version V5.12:<br>
V5.13 COE5: handle complete access if segmented transfer is required, handle unsupported segmented uploads<br>
<br>Changes to version V5.11:<br>
V5.12 COE2: do not clear the object index low byte in case of creating a SDO Abort<br>
V5.12 COE5: updates in case of MBX_16BIT_ACCESS == 0<br>
V5.12 COE6: handle get object length in case of an out of range subindex<br>
V5.12 ECAT2: big endian changes<br>
V5.12 EOE4: handle 16bit only acceess, move ethernet protocol defines and structures to application header files<br>
V5.12 MBX3: handle incomplete mailbox communication<br>
V5.12 TEST3: Send  ping request or invalid mbx data in case of access to idx 0x1009<br>
<br>Changes to version V5.10:<br>
V5.11 ECAT10: change PROTO handling to prevent compiler errors<br>
V5.11 ECAT7: add missing big endian swapping<br>
V5.11 SDO10: add new SDO abort code 0x6010004 (complete access not supported)<br>
V5.11 SDO4: "if insufficient memory is available on complete download access return ""unsupported access"""<br>
<br>Changes to version V5.01:<br>
V5.10 ESC5: Add missing swapping<br>
V5.10 MBX1: Remove multiple swapping of length filed in mailbox header<br>
V5.10 SDO3: Add new SDO Abort Code (0x06090033)<br>
V5.10 SDO4: Block SDO Info services for indices less 0x1000<br>
V5.10 SDO7: Correct mailbox length calculation on segmented or normal SDO upload response<br>
V5.10 SDO8: Fix invalid fragment calculation on SdoInfo list response<br>
V5.10 TEST5: test 0x2020.1 change limit from 10 to 16 Byte <br>
			 Add test object 0x3009/0x300A (huge array and record objects)<br>
<br>Changes to version V5.0:<br>
V5.01 MBX1: Allocate always complete 16Bit memory areas<br>
V5.01 SDO2: Prevent invalid memory access in case of 8Bit mailbox memory handling<br>
V5.01 SDO3: Update mailbox data length calculation<br>
V5.01 SDO4: Update length calculation in case of an segmented SDO list response<br>
V5.01 SDO6: Update SDO response interface handling. (used if the object access function returns "ABORTIDX_WORKING" and SDO_RES_INTERFACE is active)<br>
V5.01 TEST2: Change Test 0x2020.1 (force Segmented transfer) to 16Byte<br>
<br>Changes to version V4.40:<br>
V5.0 TEST1: Add test application. see Application Note ET9300 for more details.<br>
V5.0 MBX3: Calculate MBX datagram length independent of SM size.<br>
V5.0 SDO2: SDO toggle bit don not do be cleared for segmented communication.<br>
V5.0 SDO3: Set SDO OpCode in list response.<br>
V5.0 SDO4: Update abort code for "BIG_ENDIAN_16BIT" configuration.<br>
V5.0 SDO5: Object code was calculated wrong for SDO Info service.<br>
V5.0 SDO6: Handle SDO segmented transfer if only 16Bit MBX memory access is allowed. <br>
<br>Changes to version V4.20:<br>
V4.40 SDO1: change size calculation for SDO services<br>
V4.40 MBX1: Prevent accessing odd address<br>
V4.40 COE1: Abort code is set in OBJ_GetObjectList()<br>
<br>Changes to version V4.11:<br>
V4.20 PIC24: Add EL9800_4 (PIC24) required source code<br>
V4.20 SDO 2: SDO mask value bug<br>
V4.20 SDO 1: check zero size object length<br>
<br>Changes to version V4.10:<br>
V4.11 SDO 1: fixed calculation of frame fragments during a object dictionary array list request<br>
V4.11 SDO 2-3: fixed size of entry description<br>
V4.11 SDO 4-7: add STRUCT_PACKED defines<br>
<br>Changes to version V4.08:\a<br>
V4.10 SDO 1: fixed zero size SDO comparison<br>
V4.10 SDO 2: set SdoService_CommandOffset to 0<br>
V4.10 SDO 3: fixed zero size SDO comparison<br>
V4.10 SDO 4: fixed struct_packed definition<br>
<br>Changes to version V4.07:<br>
V4.08 SDO 1: For an upload segment response the toggle bit was overwritten<br>
V4.08 SDO 2: For a segmented response the command was wrong in the response<br>
<br>Changes to version V4.06:<br>
V4.07 SDO 1: In SdoRes the command specifier was not set correctly in case of an abort<br>
V4.07 ECAT 1: The sources for SPI and MCI were merged (in ecat_def.h<br>
				   set the switch MCI_HW to 1 when using the MCI,<br>
				   set the switch SPI_HW to 1 when using the SPI<br>
<br>Changes to version V4.05:<br>
V4.06 SDO 1: The variable dataSize was used wrong in function SdoRes<br>
<br>Changes to version V4.03:<br>
V4.04 SDO 1: The SDO interface was changed in that way that a SDO response<br>
			 could be sent by the application to a later time. In that case<br>
				 the functions OBJ_Read and OBJ_Write shall return the value<br>
				 ABORTIDX_WORKING. To send the SDO response the new function SDOS_SdoRes<br>
				 has to be called by the application. While waiting for the call<br>
				 of SDOS_SdoRes the SDO interface will answer to another SDO request<br>
				 with the error MBXERR_SERVICEINWORK in the mailbox protocol <br>
<br>Changes to version V3.20:<br>
V4.00 SDO 1: The size of the written data in case of a SDO Download will be<br>
			 in the function OBJ_Write to be more flexible<br>
V4.00 SDO 2: The object lists will be generated in the functions OBJ_GetNoOfObjects<br>
			 and OBJ_GetObjectList in objdef.c to decouple the SDO services from<br>
			 the implementation of the object dictionary<br>
V4.00 SDO 3: The name of an object or entry description will only be transmitted<br>
			 if it fits in the mailbox because the fragmentation is not supported in the sample code.<br>
V4.00 SDO 4: SDOs with size greater than 65535 were not handled correctly, that is fixed now
*/

/*---------------------------------------------------------------------------------------
------
------    Includes
------
---------------------------------------------------------------------------------------*/

#include "ecat_def.h"

#include "ecatslv.h"


#define _SDOSERV_ 1
#include "objdef.h"
#undef  _SDOSERV_
/*remove definition of _SDOSERV_ (#ifdef is used in objdef.h)*/


/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 122 to 124 deleted*/

/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 126 to 128 deleted*/


extern OBJCONST TOBJECT OBJMEM asObjDef[];
extern UINT16 OBJ_GetDesc(UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData);
extern OBJCONST TSDOINFOENTRYDESC OBJMEM * OBJ_GetEntryDesc(OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 Subindex);
extern OBJCONST TSDOINFOOBJDESC OBJMEM * OBJ_GetObjDesc(OBJCONST TOBJECT OBJMEM * pObjEntry);

/*---------------------------------------------------------------------------------------
------
------    Modulintern variable definitions
------
---------------------------------------------------------------------------------------*/

const UINT32 MBXMEM cAbortCode[] =
{
	ABORT_NOERROR,
	ABORT_TOGGLE_BIT_NOT_CHANGED,
	ABORT_SDO_PROTOCOL_TIMEOUT,
	ABORT_COMMAND_SPECIFIER_UNKNOWN,
	ABORT_OUT_OF_MEMORY,
	ABORT_UNSUPPORTED_ACCESS,
	ABORT_WRITE_ONLY_ENTRY,
	ABORT_READ_ONLY_ENTRY,
	ABORT_OBJECT_NOT_EXISTING,
	ABORT_OBJECT_CANT_BE_PDOMAPPED,
	ABORT_MAPPED_OBJECTS_EXCEED_PDO,
	ABORT_PARAM_IS_INCOMPATIBLE,
	ABORT_INTERNAL_DEVICE_INCOMPATIBILITY,
	ABORT_HARDWARE_ERROR,
	ABORT_PARAM_LENGTH_ERROR,
	ABORT_PARAM_LENGTH_TOO_LONG,
	ABORT_PARAM_LENGTH_TOO_SHORT,
	ABORT_SUBINDEX_NOT_EXISTING,
	ABORT_VALUE_EXCEEDED,
	ABORT_VALUE_TOO_GREAT,
	ABORT_VALUE_TOO_SMALL,
	ABORT_MODULE_ID_LIST_NOT_MATCH,
	ABORT_MAX_VALUE_IS_LESS_THAN_MIN_VALUE,
	ABORT_GENERAL_ERROR,
	ABORT_DATA_CANNOT_BE_READ_OR_STORED,
	ABORT_DATA_CANNOT_BE_READ_OR_STORED_BECAUSE_OF_LOCAL_CONTROL,
	ABORT_DATA_CANNOT_BE_READ_OR_STORED_IN_THIS_STATE,
	ABORT_NO_OBJECT_DICTIONARY_IS_PRESENT,
	ABORT_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0,
	ABORT_COMPLETE_ACCESS_NOT_SUPPORTED
};

UINT16 VARMEM                            nSdoInfoIndex;
OBJCONST TOBJECT OBJMEM * VARMEM        pSdoInfoObjEntry;

/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 179 to 182 deleted*/

/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 184 to 203 deleted*/
/*---------------------------------------------------------------------------------------
------
------    module internal function declarations
------
---------------------------------------------------------------------------------------*/
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 209 to 212 deleted*/
/*---------------------------------------------------------------------------------------
------
------    Functions
------
---------------------------------------------------------------------------------------*/

/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 219 to 561 deleted*/

/////////////////////////////////////////////////////////////////////////////////////////
/**
 \param    abort                 Result of the SDO access
 \param    command		         SDO command index
 \param    completeAccess        Indicates if complete access was requested
 \param    dataSize              Available data buffer in the response
 \param    objLength             Complete size of the object
 \param     pSdoRes                Pointer to the mailbox buffer

 \brief    This function is called when a SDO response shall be sent
*////////////////////////////////////////////////////////////////////////////////////////

void SdoRes(UINT8 abort, UINT8 command, UINT8 completeAccess, UINT16 dataSize, UINT32 objLength, TINITSDOMBX MBXMEM *pSdoRes)
{
	/* for an upload segment response the toggle bit was overwritten */
	if ((command != SDOSERVICE_UPLOADSEGMENTREQ) && (command != SDOSERVICE_DOWNLOADSEGMENTREQ))
	{
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 580 to 586 deleted*/
		pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] = 0;
	}
	if (abort == 0)
	{
		/* SDO-Download or SDO-Upload was successful, generate the SDO- and CoE-Header */
		pSdoRes->CoeHeader &= ~COEHEADER_COESERVICEMASK;
		pSdoRes->CoeHeader |= ((UINT16)COESERVICE_SDORESPONSE) << COEHEADER_COESERVICESHIFT;
		if (command == SDOSERVICE_INITIATEUPLOADREQ)
		{
			// HBu 06.02.06: Complete Access Bit in the SDO-Upload-Response too */
			if ((objLength <= 4) && (objLength > 0))
			{
				/* Expedited Upload Response */
				pSdoRes->MbxHeader.Length = EXPEDITED_FRAME_SIZE;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 602 to 608 deleted*/
				pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOHEADER_SIZEINDICATOR |
					SDOHEADER_TRANSFERTYPE |
					completeAccess |
					((MAX_EXPEDITED_DATA - ((UINT8)objLength)) << SDOHEADERSHIFT_DATASETSIZE) |
					SDOSERVICE_INITIATEUPLOADRES;
			}
			else
			{
				/* Normal or Segmented Upload Response */
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 619 to 625 deleted*/
				{
					pSdoRes->MbxHeader.Length = UPLOAD_NORM_RES_SIZE + ((UINT16)objLength);
				}
				((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoRes)->CompleteSize[0] = SWAPWORD((UINT16)objLength);
				((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoRes)->CompleteSize[1] = SWAPWORD((UINT16)(objLength >> 16));
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 631 to 635 deleted*/
				pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOHEADER_SIZEINDICATOR |
					completeAccess |
					SDOSERVICE_INITIATEUPLOADRES;

			}
		}
		/* for a segmented response the command was wrong in the response */
		else if (command == SDOSERVICE_DOWNLOADSEGMENTREQ)
		{
			/* Download segmented response */
			pSdoRes->MbxHeader.Length = DOWNLOAD_NORM_RES_SIZE;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 648 to 650 deleted*/
			pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_DOWNLOADSEGMENTRES;
		}
		else if (command != SDOSERVICE_UPLOADSEGMENTREQ)
		{
			/* Download response */
			pSdoRes->MbxHeader.Length = DOWNLOAD_NORM_RES_SIZE;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 658 to 660 deleted*/
			pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_INITIATEDOWNLOADRES;
		}
	}
	else
	{
		/* generate a SDO-Abort-Request */
		pSdoRes->MbxHeader.Length = ABORT_NORM_RES_SIZE;
		pSdoRes->CoeHeader &= ~COEHEADER_COESERVICEMASK;
		pSdoRes->CoeHeader |= ((UINT16)COESERVICE_SDOREQUEST) << COEHEADER_COESERVICESHIFT;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 671 to 673 deleted*/
		pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_ABORTTRANSFER;

/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 677 to 680 deleted*/
		((TABORTSDOTRANSFERREQMBX MBXMEM *) pSdoRes)->AbortCode = SWAPDWORD(cAbortCode[abort]);
	}

	// HBu 02.05.06: if the CoE-response could not be sent because the
	//               send mailbox is full it should be stored
	if (MBX_MailboxSendReq((TMBX MBXMEM *) pSdoRes, COE_SERVICE) != 0)
	{
		/* we store the CoE mailbox service to send it later (in COE_ContinueInd) when the mailbox is read */
		pCoeSendStored = (TMBX MBXMEM *) pSdoRes;
	}
}

/////////////////////////////////////////////////////////////////////////////////////////
/**
 \param     pSdoInd    Pointer to the received mailbox data from the master.

 \return    Indicates if an error occurred while the operation ( good = 0 ).

 \brief    This function is called when a SDO request service
			is received from the master and calls depending from
			the command the concerning function.
*////////////////////////////////////////////////////////////////////////////////////////

UINT8 SDOS_SdoInd(TINITSDOMBX MBXMEM *pSdoInd)
{
	UINT8 abort = 0;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 708 to 710 deleted*/
	UINT8 sdoHeader = (pSdoInd->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] & SDOHEADER_COMMANDMASK);
	/* the SDO-command is in bit 5-7 of the first SDO-Byte */
	UINT8 command = (sdoHeader & SDOHEADER_COMMAND);
	/* mbxSize contains the size of the mailbox (CoE-Header (2 Bytes) + SDO-Header (8 Bytes) + SDO-Data (if the data length is greater than 4)) */
	UINT16 mbxSize = SWAPWORD(pSdoInd->MbxHeader.Length);
	UINT16 index;
	UINT8 subindex;
	OBJCONST TOBJECT OBJMEM * pObjEntry;
	/* this variable contains the information, if all entries of an object will be read (bCompleteAccess > 0) or a single entry */
	UINT8 bCompleteAccess = 0;
	UINT32 objLength = 0;
	UINT32 dataSize = 0;

/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 725 to 731 deleted*/

/* ECATCHANGE_START(V5.13) COE5*/
	if (sdoHeader & SDOHEADER_COMPLETEACCESS)
	{
		bCompleteAccess = 1;
	}
/* ECATCHANGE_END(V5.13) COE5*/

	switch (command)
	{
	case SDOSERVICE_INITIATEDOWNLOADREQ:
	case SDOSERVICE_INITIATEUPLOADREQ:
		/* the variable index contains the requested index of the SDO service */
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 745 to 747 deleted*/
		index = ((UINT16)(pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXHIOFFSET] & SDOHEADER_INDEXHIMASK));
		index <<= 8;
/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 753 to 757 deleted*/
		index += (pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXLOOFFSET]);
		/* the variable subindex contains the requested subindex of the SDO service */
		subindex = pSdoInd->SdoHeader.Sdo[SDOHEADER_SUBINDEXOFFSET];


/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 764 to 834 deleted*/


/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 837 to 855 deleted*/

		/* OBJ_GetObjectHandle checks if the requested index is defined in the object dictionary */
		pObjEntry = OBJ_GetObjectHandle(index);

		if (pObjEntry)
		{
			/* transferType contains the information if the SDO Download Request or the SDO Upload Response
			   can be an expedited service (SDO data length <= 4, that means the data is stored in the
				SDO-Header completely */
			UINT8 bTransferType = 0;
			/* pData is the pointer to the received (SDO-Download) or sent (SDO-Upload) SDO data in the mailbox */
			UINT16 MBXMEM * pData = NULL;
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 868 to 870 deleted*/

			{
				UINT8 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;

				if (subindex > maxSubindex)
				{
					abort = ABORTIDX_SUBINDEX_NOT_EXISTING;
				}
				else
				{
					dataSize = objLength = OBJ_GetObjectLength(index, subindex, pObjEntry, (UINT8)(sdoHeader & SDOHEADER_COMPLETEACCESS));
				}

				if (abort == 0)
				{
					if (command == SDOSERVICE_INITIATEUPLOADREQ)
					{
						/* SDO Upload */
						if (mbxSize != EXPEDITED_FRAME_SIZE)
						{
							/* a SDO Upload request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
							return MBXERR_INVALIDSIZE;
						}
						/* distinguish between expedited and normal upload response within the length of the response data */
						if ((objLength <= MAX_EXPEDITED_DATA) && objLength != 0)
						{
							/* Expedited Upload */
							bTransferType = 1;
							/* pData is the pointer where the object data has to be copied for the response */
							pData = (UINT16 MBXMEM *) ((TINITSDOUPLOADEXPRESMBX MBXMEM *) pSdoInd)->Data;
													/* initialize the 4 data bytes of the SDO upload response because the requested object data
														could be less than 4 */
							pData[0] = 0;
							pData[1] = 0;
						}
						else
						{
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 908 to 930 deleted*/
/* ECATCHANGE_START(V5.13) COE5*/
							dataSize = u16SendMbxSize - MBX_HEADER_SIZE - UPLOAD_NORM_RES_SIZE;
							if (dataSize < objLength)
							{
								/* Segmented Upload */
								if (bCompleteAccess)
								{
									abort = ABORTIDX_COMPLETE_ACCESS_NOT_SUPPORTED;
								}
								else
								{
									abort = ABORTIDX_PARAM_LENGTH_ERROR;
								}
							}
/* ECATCHANGE_END(V5.13) COE5*/
							else
							{
								/* Normal Upload */

								/* pData is the pointer where the object data has to be copied for the response */
								pData = (UINT16 MBXMEM *) ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data;
							}
						}
					}
					else
					{
						/* SDO-Download: store if the request is a expedited or normal request  */
						bTransferType = sdoHeader & SDOHEADER_TRANSFERTYPE;
					}
				}
			}

			if ((abort == 0) && (command == SDOSERVICE_INITIATEDOWNLOADREQ))
			{
				/* SDO Download */
				if (bTransferType)
				{
					/* Expedited Download */
					if (mbxSize != EXPEDITED_FRAME_SIZE)
					{
						/* an Expedited SDO Download request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
						return MBXERR_INVALIDSIZE;
					}
					/* dataSize gets the real size of the downloaded object data (1,2,3 or 4) */
					dataSize = MAX_EXPEDITED_DATA - ((sdoHeader & SDOHEADER_DATASETSIZE) >> SDOHEADERSHIFT_DATASETSIZE);
					/* pData is the pointer to the downloaded object data */
					pData = (UINT16 MBXMEM *) &pSdoInd[1];
				}
				else
				{
					/* Normal Download */
					/* downloadSize gets the real size of the downloaded data */
					/* '&' operator was too much */

					UINT32 downloadSize = ((UINT32)(SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[1])) << 16) + (SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[0]));

					/* HBu 29.03.06: if it is a segmented download the mbxSize has to be the complete mailbox size */
					if ((MBX_HEADER_SIZE + EXPEDITED_FRAME_SIZE + downloadSize) > u16ReceiveMbxSize)
					{
						if (mbxSize != (u16ReceiveMbxSize - MBX_HEADER_SIZE))
						{
							return MBXERR_INVALIDSIZE;
						}
					}
					else
					{
						if (mbxSize != (EXPEDITED_FRAME_SIZE + downloadSize))
						{
							/* the mbxSize and the downloadSize are not consistent (mbxSize = downloadSize + 2 byte CoE-Header + 8 byte SDO Header */
							return MBXERR_INVALIDSIZE;
						}
					}

					/* pData is the pointer to the downloaded object data */
					pData = (UINT16 MBXMEM *) ((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->Data;
					/* the received dataSize will be checked in the object specific functions called from
					   OBJ_Write (in objdef.c) */
					dataSize = downloadSize;
					if (dataSize > (UINT32)(mbxSize - DOWNLOAD_NORM_REQ_SIZE))
					{
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1012 to 1015 deleted*/
						abort = ABORTIDX_PARAM_LENGTH_ERROR;
					}
				}
			}

/* ECATCHANGE_START(V5.13) COE5*/
			if ((abort == 0) && (bCompleteAccess == 1))
/* ECATCHANGE_END(V5.13) COE5*/
/*ET9300 Project Handler :(#if COMPLETE_ACCESS_SUPPORTED) lines 1025 to 1033 deleted*/
			{
				abort = ABORTIDX_UNSUPPORTED_ACCESS;
			}

			if (abort == 0)
			{
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1041 to 1126 deleted*/
				{
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1128 to 1139 deleted*/
					if (command == SDOSERVICE_INITIATEUPLOADREQ)
					{
						/* Expedited or Normal Upload */
						abort = OBJ_Read(index, subindex, objLength, pObjEntry, pData, bCompleteAccess);
/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 1144 to 1165 deleted*/
					}
					else
					{
						/* Expedited or Normal Download */
						abort = OBJ_Write(index, subindex, dataSize, pObjEntry, pData, bCompleteAccess);
/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 1171 to 1192 deleted*/
					}
				} /* else if ( objLength == 0 ) */
			} /* if ( abort == 0 ) */

		} //if(pObjEntry) (Object handle found)
		else
		{
			abort = ABORTIDX_OBJECT_NOT_EXISTING;
		}
		break;

/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1204 to 1224 deleted*/
	default:
		abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
		break;
	}

/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 1230 to 1232 deleted*/
	{
		/*  type cast was added because of warning */
		SdoRes(abort, command, (UINT8)(sdoHeader & SDOHEADER_COMPLETEACCESS), (UINT16)dataSize, objLength, pSdoInd);
	}

	return 0;
}

/*ET9300 Project Handler :(#if SDO_RES_INTERFACE) lines 1241 to 1308 deleted*/

/*ET9300 Project Handler :(#if SDO_RES_INTERFACE || SEGMENTED_SDO_SUPPORTED) lines 1310 to 1350 deleted*/

/////////////////////////////////////////////////////////////////////////////////////////
/**
 \param    pSdoInfoInd      Pointer to the received mailbox data from the master.

 \return    Indicates if an error occurred while the operation ( good = 0 ).

 \brief    This function is called when a SDO-Info request service
			is received from the master and calls depending from
			the opcode the concerning function.
*////////////////////////////////////////////////////////////////////////////////////////

UINT8 SDOS_SdoInfoInd(TSDOINFORMATION MBXMEM *pSdoInfoInd)
{
	UINT8 abort = 0;
	/* the variable opCode contains the requested SDO Information type */
	UINT8 opCode = (UINT8)((pSdoInfoInd->SdoHeader.InfoHead & INFOHEAD_OPCODE_MASK) >> INFOHEAD_OPCODE_SHIFT);
	OBJCONST TOBJECT OBJMEM * pObjEntry;
	UINT16 index;
	UINT8 flags = COE_SERVICE;

	/* it has to be checked if the mailbox protocol is correct, the sent mailbox data length has to
	   great enough for the service header of the requested SDO Information type */
	if (opCode == SDOINFOSERVICE_ENTRYDESCRIPTION_Q)
	{
		if (pSdoInfoInd->MbxHeader.Length < SIZEOF_SDOINFOENTRYREQSTRUCT)
		{
			return MBXERR_SIZETOOSHORT;
		}
	}
	else
	{
		if (pSdoInfoInd->MbxHeader.Length < SIZEOF_SDOINFOLISTSTRUCT)
		{
			return MBXERR_SIZETOOSHORT;
		}
	}

	switch (opCode)
	{
	case SDOINFOSERVICE_OBJDICTIONARYLIST_Q:
		/* an object list is requested, check if the list type is supported */
		if (SWAPWORD(pSdoInfoInd->SdoHeader.Data.List.ListType) <= INFO_LIST_TYPE_MAX)
		{
			UINT16 size = 0;
			/* the variable listType contains the requested listType */
			UINT8 listType = (UINT8)SWAPWORD(pSdoInfoInd->SdoHeader.Data.List.ListType);

			/* the SDO Information Header has to be stored because this function will be
			   called again if the response could not be sent with one mailbox service, the
			   variable nSdoInfoFragmentsLeft is 0 zero for the first call and unequal 0
			   for the following calls */
			MBXMEMCPY(aSdoInfoHeader, pSdoInfoInd, SDO_INFO_HEADER_BYTE_SIZE);
			if (listType-- == 0)
			{
				/* List-Type 0: length of the lists */
				UINT8 i;

				/* the needed mailbox size for List-Type 0 response is just 24 bytes, the mailbox has always
				   to be at least 24 bytes to support the SDO Information service */
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1411 to 1413 deleted*/
				for (i = 0; i < INFO_LIST_TYPE_MAX; i++)
				{
					UINT16 n = OBJ_GetNoOfObjects(i);

					/* copy the number of objects of the list type in the SDO Information response */
					((UINT16 MBXMEM *) &pSdoInfoInd->CoeHeader)[(SIZEOF_SDOINFOLISTSTRUCT >> 1) + i] = SWAPWORD(n);
				}

				/* size of the mailbox service response */
				size = (INFO_LIST_TYPE_MAX << 1) + SIZEOF_SDOINFOLISTSTRUCT;
			}
			else
			{
				/* object list with indexes is requested */
				UINT16 MBXMEM * pData;
				UINT16 n = 0;

/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1431 to 1455 deleted*/
				{
					/* the first fragment of the SDO Information response has to be sent */
					/* get the number of objects of the requested object list */
					n = OBJ_GetNoOfObjects(listType);
					/* we start with index 0x1000 */
					index = 0x1000;
					/* initialize size with the maximum size fits into one mailbox service */
/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1463 to 1470 deleted*/
					{
						size = u16SendMbxSize - SIZEOF_SDOINFOLISTSTRUCT - MBX_HEADER_SIZE;
					}
					/* initialize pData with the pointer where the fragment has to be copied */
					pData = &((UINT16 MBXMEM *) &pSdoInfoInd->CoeHeader)[SIZEOF_SDOINFOLISTSTRUCT >> 1];
					/*Check if List need to be send in fragments*/
					if ((n << 1) > size)
/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1478 to 1493 deleted*/
					{
						abort = ABORTIDX_UNSUPPORTED_ACCESS;
					}
				}

				/* get the next part of the requested object list */
				size = OBJ_GetObjectList(listType, &index, size, pData, &abort);

				/* store index for next fragment */
				nSdoInfoIndex = index;
				/* size contains before the instruction the size still available in the mailbox buffer
					and shall contain the size of the mailbox response data after the next instruction */
/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1507 to 1514 deleted*/
				{
					size = u16SendMbxSize - size - MBX_HEADER_SIZE;
				}
			}

			/* size of the mailbox response data */
			pSdoInfoInd->MbxHeader.Length = size;

			if (abort == 0)
			{
				pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
				pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)(SDOINFOSERVICE_OBJDICTIONARYLIST_S << INFOHEAD_OPCODE_SHIFT);
				pSdoInfoInd->SdoHeader.FragmentsLeft = 0;
/*ET9300 Project Handler :(#if !SEGMENTED_SDO_SUPPORTED #else) lines 1529 to 1545 deleted*/
			}
		}
		break;

	case SDOINFOSERVICE_OBJDESCRIPTION_Q:
	case SDOINFOSERVICE_ENTRYDESCRIPTION_Q:
		/* get the requested index */
		index = SWAPWORD(pSdoInfoInd->SdoHeader.Data.Obj.Index);

/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 1555 to 1623 deleted*/

/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1625 to 1642 deleted*/

		if (index < 0x1000)
		{
			/*SDO Info access is only allowed for objects >= 0x1000*/
			abort = ABORTIDX_UNSUPPORTED_ACCESS;
		}
		else
		{
			/* get the object handle of the requested index */
			pObjEntry = OBJ_GetObjectHandle(index);

			if (pObjEntry)
			{
				/* object exists */
				UINT16 size = 0;

				if (opCode == SDOINFOSERVICE_OBJDESCRIPTION_Q)
				{
					/* object description is requested */
/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 1662 to 1666 deleted*/
					OBJTOMBXMEMCPY(&pSdoInfoInd->SdoHeader.Data.Obj.Res, OBJ_GetObjDesc(pObjEntry), SDO_INFO_OBJ_DESC_SIZE);


/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1671 to 1683 deleted*/
					/* the mailbox should be big enough that the maximum object description
					fits in the mailbox (the fragmentation is not done in the sample code),
					so it will be checked only if the object description fits */
					size = OBJ_GetDesc(index, 0, pObjEntry, NULL) + SIZEOF_SDOINFOOBJSTRUCT;

					if (size > (u16SendMbxSize - MBX_HEADER_SIZE))
					{
						/* size of the object description does not fit in the mailbox,
						the object description will be sent without the name */
						size = SIZEOF_SDOINFOOBJSTRUCT;
					}
					else
					{
						/* object description fits in the mailbox, get the name of the object */
						size = OBJ_GetDesc(index, 0, pObjEntry, ((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Obj.Res)[1])) + SIZEOF_SDOINFOOBJSTRUCT;
					}
				}
				else
				{
					/* entry description is requested,
					get the requested subindex */
					UINT8 subindex = (UINT8)((pSdoInfoInd->SdoHeader.Data.Entry.Info & ENTRY_MASK_SUBINDEX) >> ENTRY_SUBINDEX_SHIFT);

					/* get the maximum subindex */
					UINT8 maxSubindex = (OBJ_GetObjDesc(pObjEntry)->ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;

					if (subindex <= maxSubindex)
					{
						UINT16 ObjectFlags;
						/* requested subindex is not too great */
						/* get the entry description of the requested entry */
/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 1715 to 1720 deleted*/
						OBJTOMBXMEMCPY(&pSdoInfoInd->SdoHeader.Data.Entry.Res, OBJ_GetEntryDesc(pObjEntry, subindex), SIZEOF(TSDOINFOENTRYDESC));

						/* the transmission of the value info is not supported yet of the sample code */
						pSdoInfoInd->SdoHeader.Data.Entry.Info &= ~ENTRY_MASK_VALUEINFO;
						ObjectFlags = OBJ_GetObjDesc(pObjEntry)->ObjFlags;
						ObjectFlags = (ObjectFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;

						if (((ObjectFlags == OBJCODE_ARR) || (ObjectFlags == OBJCODE_REC)) && (subindex == 0))
						{
							OBJTOMBXSTRCPY(((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Entry.Res)[1]), aSubindexDesc, SIZEOF(aSubindexDesc));
							size = 12 + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY); // 12: Length of "SubIndex 000"
						}
						else
						{
							/* the mailbox should be big enough that the maximum entry description
							fits in the mailbox (the fragmentation is not done in the sample code),
							so it will be checked only if the entry description fits */
							size = OBJ_GetDesc(index, subindex, pObjEntry, NULL) + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
							if (size > (u16SendMbxSize - MBX_HEADER_SIZE))
							{
								/* size of the object description does not fit in the mailbox,
								the object description will be sent without the name */
								size = SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
							}
							else
							{
								/* object description fits in the mailbox, get the name of the entry */
								size = OBJ_GetDesc(index, subindex, pObjEntry, ((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Entry.Res)[1])) + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
							}
						}
					}
					else
					{
						abort = ABORTIDX_SUBINDEX_NOT_EXISTING;
					}
				}

				if (abort == 0)
				{
					{
						/* for the object and entry description the sample code does not support the fragmentation,
						the mailbox has to be big enough */
						pSdoInfoInd->SdoHeader.FragmentsLeft = 0;
						/* store the size of the mailbox data in the mailbox buffer */
						pSdoInfoInd->MbxHeader.Length = size;
						/* set the opCode of the SDO Information response */
						pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
						pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)((opCode + 1) << INFOHEAD_OPCODE_SHIFT);
					}
				}
			}
			else
			{
				abort = ABORTIDX_OBJECT_NOT_EXISTING;
			}
		}
		break;
	default:
		abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
	}

	if (abort)
	{
		/* send a SDO Information Error response */
		pSdoInfoInd->MbxHeader.Length = SIZEOF_SDOINFOERRORSTRUCT;

		pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
		pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)((SDOINFOSERVICE_ERROR_Q) << INFOHEAD_OPCODE_SHIFT);

		pSdoInfoInd->SdoHeader.FragmentsLeft = 0;
/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 1792 to 1795 deleted*/
		pSdoInfoInd->SdoHeader.Data.Error.ErrorCode = SWAPDWORD(cAbortCode[abort]);

/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED) lines 1799 to 1801 deleted*/
	}

	if (MBX_MailboxSendReq((TMBX MBXMEM *) pSdoInfoInd, flags) != 0)
	{
		/* if the mailbox response could not be sent (or stored), the response will be
		   stored in the variable pCoeSendStored and will be sent automatically
			from the mailbox handler (COE_ContinueInd) when the send mailbox will be read
			the next time from the master */
		pCoeSendStored = (TMBX MBXMEM *) pSdoInfoInd;
	}

	return 0;
}

/** @} */


