nxdrvlinux/libcifx/Toolkit/Source/cifXFunctions.c

3714 lines
141 KiB
C
Raw Normal View History

/**************************************************************************************
Copyright (c) Hilscher Gesellschaft fuer Systemautomation mbH. All Rights Reserved.
***************************************************************************************
$Id: cifXFunctions.c 14699 2023-04-27 07:51:13Z RMayer $:
Description:
cifX API function implementation
Changes:
Date Description
-----------------------------------------------------------------------------------
2023-04-26 - Added new compiler option CIFX_TOOLKIT_USE_CUSTOM_DRV_FUNCS
- Moved check parameter macros to cifXtoolkit.h
2022-06-14 - Added option and handling for cached PLC memory pointers
- Reorganized xChannelPLCMemoryPtr() to handle caching option for IO area 0
2022-01-18 Fixed xSysdeviceResetEx() to allow additional flags passing to underlying functions
2021-09-13 Propagate changes of cifXErrors.h (spelling of name
CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED)
2020-02-06 xDriverEnumBoards() should return CIFX_NO_MORE_ENTRIES
if ulBoard exceeds actual board count, instead of invalid board
2019-10-11 Use internal buffer for endian conversion in xChannelControlBlock()
Propagate prototype changes of endian conversion function
2018-11-06 Added new function xSysdeviceResetEx()
2018-10-10 - Updated header and definitions to new Hilscher defines
- Derived from cifX Toolkit V1.6.0.0
**************************************************************************************/
/*****************************************************************************/
/*! \file cifXFunctions.c
* cifX API function implementation */
/*****************************************************************************/
#include "cifXToolkit.h"
#include "cifXErrors.h"
#include "cifXEndianess.h"
#include "Hil_Results.h"
#include "Hil_Packet.h"
#include "Hil_SystemCmd.h"
/* Commonly used function from cifXInit.c, not exposed to the user interface */
int32_t cifXStartModule ( PDEVICEINSTANCE ptDevInstance, uint32_t ulChannelNumber, char* pszModuleName,
uint32_t ulFileSize, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser);
int32_t cifXReadFirmwareIdent( PDEVICEINSTANCE ptDevInstance, uint32_t ulChannel,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser);
#ifdef CIFX_TOOLKIT_TIME
void cifXInitTime ( PDEVICEINSTANCE ptDevInstance);
#endif
/*****************************************************************************/
/*! \addtogroup CIFX_DRIVER_API cifX Driver API implementation
* \{ */
/*****************************************************************************/
/*****************************************************************************/
/*! Errorcode to Errordescription lookup table (english only) */
/*****************************************************************************/
static struct CIFX_ERROR_TO_DESCRtag
{
int32_t lError;
char* szErrorDescr;
} s_atErrorToDescrTable[] =
{
#ifndef CIFX_TOOLKIT_NO_ERRORLOOKUP
/*******************************************************************************
* cifX Device Driver Errors (Global)
*******************************************************************************/
{CIFX_INVALID_POINTER ,"Invalid pointer (e.g. NULL) passed to driver" },
{CIFX_INVALID_BOARD ,"No board with the given name / index available"},
{CIFX_INVALID_CHANNEL ,"No channel with the given index available" },
{CIFX_INVALID_HANDLE ,"Invalid handle passed to driver" },
{CIFX_INVALID_PARAMETER ,"Invalid parameter" },
{CIFX_INVALID_COMMAND ,"Invalid command" },
{CIFX_INVALID_BUFFERSIZE ,"Invalid buffer size" },
{CIFX_INVALID_ACCESS_SIZE ,"Invalid access size" },
{CIFX_FUNCTION_FAILED ,"Function failed" },
{CIFX_FILE_OPEN_FAILED ,"File could not be opened" },
{CIFX_FILE_SIZE_ZERO ,"File size is zero" },
{CIFX_FILE_LOAD_INSUFF_MEM ,"Insufficient memory to load file" },
{CIFX_FILE_READ_ERROR ,"Error reading from file" },
{CIFX_FILE_TYPE_INVALID ,"Invalid file type" },
{CIFX_FILE_NAME_INVALID ,"Invalid file name" },
{CIFX_FUNCTION_NOT_AVAILABLE ,"Driver function not available" },
{CIFX_BUFFER_TOO_SHORT ,"Given buffer is too short" },
{CIFX_MEMORY_MAPPING_FAILED ,"Failed to map the memory" },
{CIFX_NO_MORE_ENTRIES ,"No more entries available" },
{CIFX_CALLBACK_MODE_UNKNOWN ,"Unknown callback handling mode" },
{CIFX_CALLBACK_CREATE_EVENT_FAILED ,"Failed to create callback events" },
{CIFX_CALLBACK_CREATE_RECV_BUFFER ,"Failed to create callback receive buffer" },
{CIFX_CALLBACK_ALREADY_USED ,"Callback already used" },
{CIFX_CALLBACK_NOT_REGISTERED ,"Callback was not registered before" },
{CIFX_INTERRUPT_DISABLED ,"Interrupt is disabled" },
/*******************************************************************************
* Generic Driver Errors
*******************************************************************************/
{CIFX_DRV_NOT_INITIALIZED ,"Driver not initialized" },
{CIFX_DRV_INIT_STATE_ERROR ,"Driver init state error" },
{CIFX_DRV_READ_STATE_ERROR ,"Driver read state error" },
{CIFX_DRV_CMD_ACTIVE ,"Command is active on device" },
{CIFX_DRV_DOWNLOAD_FAILED ,"General error during download" },
{CIFX_DRV_WRONG_DRIVER_VERSION ,"Wrong driver version" },
{CIFX_DRV_DRIVER_NOT_LOADED ,"CIFx driver is not running" },
{CIFX_DRV_INIT_ERROR ,"Failed to initialize the device" },
{CIFX_DRV_CHANNEL_NOT_INITIALIZED ,"Channel not initialized (xChannelOpen not called)"},
{CIFX_DRV_IO_CONTROL_FAILED ,"IOControl call failed" },
{CIFX_DRV_NOT_OPENED ,"Driver was not opened" },
{CIFX_DRV_DOWNLOAD_STORAGE_UNKNOWN ,"Unknown download storage type (RAM/FLASH based) found"},
{CIFX_DRV_DOWNLOAD_FW_WRONG_CHANNEL,"Channel number for a firmware download not supported" },
{CIFX_DRV_DOWNLOAD_MODULE_NO_BASEOS,"Modules are not allowed without a Base OS firmware" },
/*******************************************************************************
* Generic Device Errors
*******************************************************************************/
{CIFX_DEV_DPM_ACCESS_ERROR ,"Dual port memory not accessible (board not found)"},
{CIFX_DEV_NOT_READY ,"Device not ready (ready flag failed)" },
{CIFX_DEV_NOT_RUNNING ,"Device not running (running flag failed)" },
{CIFX_DEV_WATCHDOG_FAILED ,"Watchdog test failed" },
{CIFX_DEV_SYSERR ,"Error in handshake flags" },
{CIFX_DEV_MAILBOX_FULL ,"Send mailbox is full" },
{CIFX_DEV_PUT_TIMEOUT ,"Send packet timeout" },
{CIFX_DEV_GET_TIMEOUT ,"Receive packet timeout" },
{CIFX_DEV_GET_NO_PACKET ,"No packet available" },
{CIFX_DEV_RESET_TIMEOUT ,"Reset command timeout" },
{CIFX_DEV_NO_COM_FLAG ,"COM-flag not set" },
{CIFX_DEV_EXCHANGE_FAILED ,"I/O data exchange failed" },
{CIFX_DEV_EXCHANGE_TIMEOUT ,"I/O data exchange timeout" },
{CIFX_DEV_COM_MODE_UNKNOWN ,"Unknown I/O exchange mode " },
{CIFX_DEV_FUNCTION_FAILED ,"Device function failed " },
{CIFX_DEV_DPMSIZE_MISMATCH ,"DPM size differs from configuration" },
{CIFX_DEV_STATE_MODE_UNKNOWN ,"Unknown state mode" },
{CIFX_DEV_HW_PORT_IS_USED ,"Output port already in use" },
{CIFX_DEV_CONFIG_LOCK_TIMEOUT ,"Configuration locking timeout" },
{CIFX_DEV_CONFIG_UNLOCK_TIMEOUT ,"Configuration unlocking timeout" },
{CIFX_DEV_HOST_STATE_SET_TIMEOUT ,"Set HOST state timeout" },
{CIFX_DEV_HOST_STATE_CLEAR_TIMEOUT ,"Clear HOST state timeout" },
{CIFX_DEV_INITIALIZATION_TIMEOUT ,"Timeout during channel initialization" },
{CIFX_DEV_BUS_STATE_ON_TIMEOUT ,"Set Bus ON timeout" },
{CIFX_DEV_BUS_STATE_OFF_TIMEOUT ," Set Bus OFF timeout" },
{CIFX_DEV_MODULE_ALREADY_RUNNING ,"Module already running" },
{CIFX_DEV_MODULE_ALREADY_EXISTS ,"Module already exists" },
{CIFX_DEV_DMA_INSUFF_BUFFER_COUNT ,"Number of configured DMA buffers insufficient" },
{CIFX_DEV_DMA_BUFFER_TOO_SMALL ,"DMA buffers size too small (min size 256Byte)" },
{CIFX_DEV_DMA_BUFFER_TOO_BIG ,"DMA buffers size too big (max size 63,75KByte)" },
{CIFX_DEV_DMA_BUFFER_NOT_ALIGNED ,"DMA buffer alignment failed (must be 256Byte)" },
{CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED ,"I/O data uncontrolled handshake mode not supported" },
{CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED,"I/O area in DMA mode not supported (only area 0 possible)" },
{CIFX_DEV_DMA_STATE_ON_TIMEOUT ,"Set DMA ON timeout" },
{CIFX_DEV_DMA_STATE_OFF_TIMEOUT ,"Set DMA OFF timeout" },
{CIFX_DEV_SYNC_STATE_INVALID_MODE ,"Device is in invalid mode for this operation" },
{CIFX_DEV_SYNC_STATE_TIMEOUT ,"Waiting for synchronization event bits timed out" },
/*******************************************************************************/
#else
{CIFX_NO_ERROR, ""},
#endif
};
/*****************************************************************************/
/*! Structure description of NETX_SYSTEM_CHANNEL_INFO */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atSystemChannelInfo[] =
{
/* Offset, Width, Elements */
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
{ 0x08, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* usSizeOfMailbox
usMailboxStartOffset */
};
/*****************************************************************************/
/*! Structure description of NETX_HANDSHAKE_CHANNEL_INFO */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atHandshakeChannelInfo[] =
{
/* Offset, Width, Elements */
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
};
/*****************************************************************************/
/*! Structure description of NETX_COMMUNICATION_CHANNEL_INFO */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atCommChannelInfo[] =
{
/* Offset, Width, Elements */
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
{ 0x08, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* usCommunicationClass
usProtocolClass
usProtocolConformanceClass */
};
/*****************************************************************************/
/*! Structure description of NETX_APPLICATION_CHANNEL_INFO */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atAppChannelInfo[] =
{
/* Offset, Width, Elements */
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
};
/*****************************************************************************/
/*! Structure description of NETX_SYSTEM_INFO_BLOCK */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atSystemInfoBlock[] =
{
/* Offset, Width, Elements */
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 3}, /* DpmTotalSize, DevNr, SerNr */
{ 0x10, eCIFX_ENDIANESS_WIDTH_16BIT, 6}, /* ausHwOptions, usMfg, usProdDat */
{ 0x1C, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulLicenseFlags1/2 */
{ 0x24, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* LicenseId/flags, DeviceClass */
{ 0x2C, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* ausReserved */
};
/*****************************************************************************/
/*! Structure description of NETX_SYSTEM_CONTROL_BLOCK */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atSystemControlBlock[] =
{
/* Offset, Width, Elements */
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulSystemCmdCOS, ulReserved */
};
/*****************************************************************************/
/*! Structure description of NETX_SYSTEM_STATUS_BLOCK */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atSystemStatusBlock[] =
{
/* Offset, Width, Elements */
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 5}, /* ulSystem-COS/Status/Error
ulReserved1 */
{ 0x14, eCIFX_ENDIANESS_WIDTH_16BIT, 1}, /* usCpuLoad */
};
/*****************************************************************************/
/*! Structure description of NETX_CONTROL_BLOCK */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atControlBlock[] =
{
/* Offset, Width, Elements */
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulApplCos, ulWatchdog */
};
/*****************************************************************************/
/*! Structure description of NETX_COMMON_STATUS_BLOCK */
/*****************************************************************************/
static const CIFX_ENDIANESS_ENTRY_T s_atCommonStatusBlock[] =
{
/* Offset, Width, Elements */
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 3}, /* ulCommCos,ulCommState,
ulCommError */
{ 0x0C, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* usVersion,usWatchDogTime
*/
{ 0x14, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulHostWatchDog, ulErrorCount,
*/
{ 0x22, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* ausReserved[3]
*/
{ 0x28, eCIFX_ENDIANESS_WIDTH_32BIT, 6}, /* ulSlaveState, ulSlaveErrLogInd
ulNumOfConfigSlaves,ulNumOfActiveSlaves
ulNumOfDiagSlaves, ulReserved */
};
extern uint32_t g_ulDeviceCount; /*!< Number of available device (Array size of g_pptDevices) */
extern PDEVICEINSTANCE* g_pptDevices; /*!< Array containing all handled device instances */
extern TKIT_DRIVER_INFORMATION g_tDriverInfo; /*!< Global driver information */
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
/*****************************************************************************/
/*! Checks if the given sysdevice handle is valid
* \param hChannel Sysdevice handle
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
static int32_t CheckSysdeviceHandle(CIFXHANDLE hChannel)
{
int32_t lRet = CIFX_INVALID_HANDLE;
if ( NULL != hChannel)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hChannel;
if ( ptSysDevice->fIsSysDevice)
{
if( 0 == ptSysDevice->ulOpenCount)
{
/* We are probably in the initialization phase without an opened device handle */
lRet = CIFX_NO_ERROR;
}else if ( (0 == g_ulDeviceCount) ||
(NULL == g_pptDevices) )
{
/* We can't search for the handle in the device list, because the list is not available. */
/* Maybe we are in the initialization phase and the list is not created yet. */
lRet = CIFX_NO_ERROR;
}else
{
/* Try to find the ptSysDevice pointer in one of the device instances */
uint32_t ulDev = 0;
for(ulDev = 0; ulDev < g_ulDeviceCount; ++ulDev)
{
if (ptSysDevice == &g_pptDevices[ulDev]->tSystemDevice)
{
lRet = CIFX_NO_ERROR;
break;
}
}
}
}
}
return lRet;
}
/*****************************************************************************/
/*! Checks if the given channel handle is valid
* \param hChannel Channel handle
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
static int32_t CheckChannelHandle(CIFXHANDLE hChannel)
{
int32_t lRet = CIFX_INVALID_HANDLE;
if ( NULL != hChannel)
{
PCHANNELINSTANCE ptDevice = (PCHANNELINSTANCE)hChannel;
if ( ptDevice->fIsChannel)
{
/* Check if we can find our device in the device table */
if ( 0 == g_ulDeviceCount)
{
/* We are in the initialization phase without an device entry in the g_pptDevices table */
lRet = CIFX_NO_ERROR;
}else if ( (0 == g_ulDeviceCount) ||
(NULL == g_pptDevices) )
{
/* We can't search for the handle in the device list, because the list is not available. */
/* Maybe we are in the initialization phase and the list is not created yet. */
lRet = CIFX_NO_ERROR;
}else
{
/* Try to find the ptSysDevice pointer in one of the device instances */
uint32_t ulDev = 0;
/* Check if we can find our channel inside a device */
for(ulDev = 0; ulDev < g_ulDeviceCount; ++ulDev)
{
uint32_t ulChannel = 0;
for( ulChannel = 0; ulChannel < g_pptDevices[ulDev]->ulCommChannelCount; ++ulChannel)
{
if ( ptDevice == g_pptDevices[ulDev]->pptCommChannels[ulChannel])
{
lRet = CIFX_NO_ERROR;
break;
}
}
}
}
}
}
return lRet;
}
#endif
/*****************************************************************************/
/*! Opens the System device on the given board
* \param hDriver Driver handle
* \param szBoard Name of the board to open
* \param phSysdevice Returned handle to the System device area
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceOpen(CIFXHANDLE hDriver, char* szBoard, CIFXHANDLE* phSysdevice)
{
int32_t lRet = CIFX_INVALID_BOARD;
uint32_t ulIdx;
if(0 == g_tDriverInfo.ulOpenCount)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(szBoard);
CHECK_POINTER(phSysdevice);
for(ulIdx = 0; ulIdx < g_ulDeviceCount; ++ulIdx)
{
if( (OS_Strcmp(g_pptDevices[ulIdx]->szName, szBoard) == 0) ||
(OS_Strcmp(g_pptDevices[ulIdx]->szAlias, szBoard) == 0) )
{
++g_pptDevices[ulIdx]->tSystemDevice.ulOpenCount;
*phSysdevice = (CIFXHANDLE)(&g_pptDevices[ulIdx]->tSystemDevice);
lRet = CIFX_NO_ERROR;
break;
}
}
return lRet; /*lint !e438 */
}
/*****************************************************************************/
/*! Closes an open System device
* \param hSysdevice Handle to the System device to close
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceClose(CIFXHANDLE hSysdevice)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
CHECK_SYSDEVICEHANDLE(hSysdevice);
--ptSysDevice->ulOpenCount;
return CIFX_NO_ERROR;
}
/*****************************************************************************/
/*! Gets the Mailbox state of an open system device
* \param hSysdevice Handle to the System device
* \param pulRecvPktCount Number of packets in receive mailbox
* \param pulSendPktCount Number of packets the application is able to send
* at once
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceGetMBXState(CIFXHANDLE hSysdevice, uint32_t* pulRecvPktCount, uint32_t* pulSendPktCount)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
return DEV_GetMBXState(ptSysDevice, pulRecvPktCount, pulSendPktCount);
}
/*****************************************************************************/
/*! Inserts a packet into the System Mailbox
* \param hSysdevice Handle to the System device
* \param ptSendPkt Packet to send to device
* \param ulTimeout maximum time to wait for packet to be accepted
* by device (in ms)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdevicePutPacket(CIFXHANDLE hSysdevice, CIFX_PACKET* ptSendPkt, uint32_t ulTimeout)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
if( !OS_WaitMutex( ptSysDevice->tSendMbx.pvSendMBXMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
lRet = DEV_PutPacket(ptSysDevice, ptSendPkt, ulTimeout);
OS_ReleaseMutex( ptSysDevice->tSendMbx.pvSendMBXMutex);
return lRet;
}
/*****************************************************************************/
/*! Retrieves a packet from the System Mailbox
* \param hSysdevice Handle to the System device
* \param ulSize Size of the buffer to retrieve the packet
* \param ptRecvPkt Pointer to buffer for received packet
* \param ulTimeout maximum time to wait for packet to be delivered
* by device (in ms)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceGetPacket(CIFXHANDLE hSysdevice, uint32_t ulSize, CIFX_PACKET* ptRecvPkt, uint32_t ulTimeout)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
if( !OS_WaitMutex( ptSysDevice->tRecvMbx.pvRecvMBXMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
lRet = DEV_GetPacket(ptSysDevice, ptRecvPkt, ulSize, ulTimeout);
OS_ReleaseMutex( ptSysDevice->tRecvMbx.pvRecvMBXMutex);
return lRet;
}
/*****************************************************************************/
/*! Download a file (Firmware, Configuration, etc) to the device
* \param hSysdevice Handle to the system device
* \param ulChannel Channel number to load the file to
* \param ulMode Download mode (DOWNLOAD_MODE_FIRMWARE, etc)
* \param pszFileName Name of the file
* \param pabFileData Pointer to the file data
* \param ulFileSize Length of the file data
* \param pfnCallback Callback for progress indication
* (NULL for no callback)
* \param pfnRecvPktCallback Callback Callback pointer for unsolicited receive packets
* (NULL for no callback)
* \param pvUser User parameter passed to callback
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceDownload( CIFXHANDLE hSysdevice,
uint32_t ulChannel,
uint32_t ulMode,
char* pszFileName,
uint8_t* pabFileData,
uint32_t ulFileSize,
PFN_PROGRESS_CALLBACK pfnCallback,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback,
void* pvUser)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
uint32_t ulTransferType = 0;
int32_t lRet = CIFX_NO_ERROR;
CHECK_SYSDEVICEHANDLE(hSysdevice);
CHECK_POINTER(pszFileName);
CHECK_POINTER(pabFileData);
switch(ulMode)
{
case DOWNLOAD_MODE_FIRMWARE:
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptSysDevice->pvDeviceInstance))->eChipType,
pszFileName, &ulTransferType)))
return lRet;
lRet = DEV_DownloadFile(ptSysDevice,
ulChannel,
ptSysDevice->tSendMbx.ulSendMailboxLength,
ulTransferType,
pszFileName,
ulFileSize,
pabFileData,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser);
break;
case DOWNLOAD_MODE_CONFIG:
case DOWNLOAD_MODE_FILE:
ulTransferType = HIL_FILE_XFER_FILE;
lRet = DEV_DownloadFile(ptSysDevice,
ulChannel,
ptSysDevice->tSendMbx.ulSendMailboxLength,
ulTransferType,
pszFileName,
ulFileSize,
pabFileData,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser);
break;
case DOWNLOAD_MODE_LICENSECODE:
ulTransferType = HIL_FILE_XFER_LICENSE_CODE;
lRet = DEV_DownloadFile(ptSysDevice,
ulChannel,
ptSysDevice->tSendMbx.ulSendMailboxLength,
ulTransferType,
pszFileName,
ulFileSize,
pabFileData,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser);
break;
case DOWNLOAD_MODE_MODULE:
{
/* We downloading a NXO file */
PDEVICEINSTANCE ptDevInstance = (PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance;
PCHANNELINSTANCE ptChannelInst = NULL;
/* Check if we have a NXO module file */
if ( !DEV_IsNXOFile( pszFileName))
{
lRet = CIFX_FILE_NAME_INVALID;
} else if(ulChannel >= ptDevInstance->ulCommChannelCount)
{
/* Invalid channel number */
lRet = CIFX_INVALID_CHANNEL;
} else
{
/* Check if the channel is READY and something is already loaded */
ptChannelInst = ptDevInstance->pptCommChannels[ulChannel];
/* Check if we are supporting modules */
if( !ptDevInstance->fModuleLoad)
{
lRet = CIFX_DRV_DOWNLOAD_MODULE_NO_BASEOS;
} else if( DEV_IsReady(ptChannelInst))
{
/* Channel already READY */
lRet = CIFX_DEV_MODULE_ALREADY_RUNNING;
} else
{
uint8_t bLoadState = CIFXTKIT_DOWNLOAD_NONE;
if ( CIFX_NO_ERROR == (lRet = DEV_ProcessFWDownload( ptDevInstance,
ulChannel,
NULL,
pszFileName,
ulFileSize,
pabFileData,
&bLoadState,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser)))
{
/* Start module */
if (CIFX_NO_ERROR == (lRet = cifXStartModule( ptDevInstance, ulChannel, pszFileName,
ulFileSize, pfnRecvPktCallback, pvUser)))
{
if ( CIFX_NO_ERROR == (lRet = cifXReadFirmwareIdent( ptDevInstance, ulChannel,
pfnRecvPktCallback, pvUser)))
{
if ( 0 == (bLoadState & CIFXTKIT_DOWNLOAD_EXECUTED))
{
/* Return download skipped, file exists */
lRet = CIFX_DEV_MODULE_ALREADY_EXISTS;
}
}
}
}
}
}
}
break;
default:
return CIFX_INVALID_PARAMETER;
}
return lRet;
}
/*****************************************************************************/
/*! Gets the information of a system device
* \param hSysdevice Handle to the system device
* \param ulCmd Information to fetch (see defines CIFX_INFO_CMD_SYSTEM_XXX)
* \param ulSize Size of the passed structure
* \param pvInfo Pointer to the structure for returned data
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceInfo(CIFXHANDLE hSysdevice, uint32_t ulCmd, uint32_t ulSize, void* pvInfo)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
CHECK_SYSDEVICEHANDLE(hSysdevice);
CHECK_POINTER(pvInfo);
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptSysDevice->pbDPMChannelStart;
switch(ulCmd)
{
case CIFX_INFO_CMD_SYSTEM_INFORMATION:
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFORMATION))
{
lRet = CIFX_INVALID_BUFFERSIZE;
} else
{
/* Insert global system channel information */
SYSTEM_CHANNEL_SYSTEM_INFORMATION* ptInfo = (SYSTEM_CHANNEL_SYSTEM_INFORMATION*)pvInfo;
/* These values are directly read from DPM, so they need to be converted to host endianess */
ptInfo->ulSystemError = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemState.ulSystemError));
ptInfo->ulDpmTotalSize = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulDpmTotalSize));
ptInfo->ulDeviceNumber = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulDeviceNumber));
ptInfo->ulSerialNumber = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulSerialNumber));
ptInfo->ulMBXSize = ptSysDevice->tRecvMbx.ulRecvMailboxLength;
ptInfo->ulOpenCnt = ptSysDevice->ulOpenCount;
}
break;
case CIFX_INFO_CMD_SYSTEM_INFO_BLOCK:
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFO_BLOCK))
{
lRet = CIFX_INVALID_BUFFERSIZE;
} else
{
uint32_t ulCopyLen = min( ulSize,
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFO_BLOCK));
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemInfo, ulCopyLen);
(void)cifXConvertEndianess(0,
pvInfo,
ulCopyLen,
s_atSystemInfoBlock,
sizeof(s_atSystemInfoBlock) / sizeof(s_atSystemInfoBlock[0]));
}
break;
case CIFX_INFO_CMD_SYSTEM_CHANNEL_BLOCK:
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK))
{
lRet = CIFX_INVALID_BUFFERSIZE;
} else
{
SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK* ptInfoBuffer = (SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK*) pvInfo; /* use the read buffer for data conversion */
uint32_t ulCopyLen = min( ulSize,
(uint32_t)sizeof(SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK));
int iChannel;
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->atChannelInfo[0], ulCopyLen);
/* Convert channel information structure. This depends on the first byte (bChannelType),
so we need to parse the whole array */
for(iChannel = 0;
iChannel < (int) (sizeof(ptSysChannel->atChannelInfo) / sizeof(ptSysChannel->atChannelInfo[0]));
++iChannel)
{
uint32_t ulBlockLength = (uint32_t)sizeof(ptSysChannel->atChannelInfo[0]);
uint32_t ulOffset = (uint32_t)(iChannel * ulBlockLength);
if( ulOffset > ulCopyLen)
break;
if( (ulOffset + sizeof(ptSysChannel->atChannelInfo[0])) > ulCopyLen)
{
/* part of block copied, so calculate restlen */
ulBlockLength = ulCopyLen - ulOffset;
}
/* Convert endianess */
switch(ptInfoBuffer->abInfoBlock[iChannel][0])
{
case HIL_CHANNEL_TYPE_SYSTEM:
(void)cifXConvertEndianess(0,
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
ulBlockLength,
s_atSystemChannelInfo,
sizeof(s_atSystemChannelInfo) / sizeof(s_atSystemChannelInfo[0]));
break;
case HIL_CHANNEL_TYPE_HANDSHAKE:
(void)cifXConvertEndianess(0,
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
ulBlockLength,
s_atHandshakeChannelInfo,
sizeof(s_atHandshakeChannelInfo) / sizeof(s_atHandshakeChannelInfo[0]));
break;
case HIL_CHANNEL_TYPE_COMMUNICATION:
(void)cifXConvertEndianess(0,
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
ulBlockLength,
s_atCommChannelInfo,
sizeof(s_atCommChannelInfo) / sizeof(s_atCommChannelInfo[0]));
break;
case HIL_CHANNEL_TYPE_APPLICATION:
(void)cifXConvertEndianess(0,
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
ulBlockLength,
s_atAppChannelInfo,
sizeof(s_atAppChannelInfo) / sizeof(s_atAppChannelInfo[0]));
break;
default:
/* This should never happen */
break;
}
}
}
break;
case CIFX_INFO_CMD_SYSTEM_CONTROL_BLOCK:
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_CONTROL_BLOCK))
{
lRet = CIFX_INVALID_BUFFERSIZE;
} else
{
uint32_t ulCopyLen = min(ulSize,
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_CONTROL_BLOCK));
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemControl, ulCopyLen);
(void)cifXConvertEndianess(0,
pvInfo,
ulCopyLen,
s_atSystemControlBlock,
sizeof(s_atSystemControlBlock) / sizeof(s_atSystemControlBlock[0]));
}
break;
case CIFX_INFO_CMD_SYSTEM_STATUS_BLOCK:
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_STATUS_BLOCK))
{
lRet = CIFX_INVALID_BUFFERSIZE;
} else
{
uint32_t ulCopyLen = min(ulSize,
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_STATUS_BLOCK));
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemState, ulCopyLen);
(void)cifXConvertEndianess(0,
pvInfo,
ulCopyLen,
s_atSystemStatusBlock,
sizeof(s_atSystemStatusBlock) / sizeof(s_atSystemStatusBlock[0]));
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
} /* end switch */
return lRet;
}
/*****************************************************************************/
/*! Hard resets a complete device via system channel with reset parameter
* \param hSysdevice Handle to system device
* \param ulTimeout Timeout to wait for card to finish reset
* \param ulMode Reset mode with parameter
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceResetEx(CIFXHANDLE hSysdevice, uint32_t ulTimeout, uint32_t ulMode)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE) hSysdevice;
int32_t lRet = CIFX_NO_ERROR;
CHECK_SYSDEVICEHANDLE(hSysdevice);
/* Evaluate which mode is selected, only write reset parameter if reset mode is supported */
if(CIFX_RESETEX_SYSTEMSTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
{
lRet = DEV_DoSystemStart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
}
else if(CIFX_RESETEX_BOOTSTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
{
lRet = DEV_DoSystemBootstart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
}
else if(CIFX_RESETEX_UPDATESTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
{
lRet = DEV_DoUpdateStart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
}
else
{
/* No handling for unknown reset mode */
lRet = CIFX_INVALID_PARAMETER;
}
#ifdef CIFX_TOOLKIT_TIME
if (CIFX_NO_ERROR == lRet)
cifXInitTime((PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance);
#endif
return lRet;
}
/*****************************************************************************/
/*! Hard resets a complete device via system channel
* \param hSysdevice Handle to system device
* \param ulTimeout Timeout to wait for card to finish reset
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceReset(CIFXHANDLE hSysdevice, uint32_t ulTimeout)
{
int32_t lRet;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
CHECK_SYSDEVICEHANDLE(hSysdevice);
lRet = DEV_DoSystemStart(ptSysDevice, ulTimeout, 0);
#ifdef CIFX_TOOLKIT_TIME
if (CIFX_NO_ERROR == lRet)
cifXInitTime((PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance);
#endif
return lRet;
}
/*****************************************************************************/
/*! Boot start reset to via system channel
* \param hSysdevice Handle to system device
* \param ulTimeout Timeout to wait for card to finish reset
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceBootstart(CIFXHANDLE hSysdevice, uint32_t ulTimeout)
{
int32_t lRet;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
CHECK_SYSDEVICEHANDLE(hSysdevice);
lRet = DEV_DoSystemBootstart(ptSysDevice, ulTimeout, 0);
return lRet;
}
/*****************************************************************************/
/*! Get/Return a memory pointer to an extended board memory if available
* \param hSysdevice Handle to system device
* \param ulCmd Command for get/free
* \param ptExtMemInfo Pointer to a user buffer to return the information
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceExtendedMemory(CIFXHANDLE hSysdevice, uint32_t ulCmd, CIFX_EXTENDED_MEMORY_INFORMATION* ptExtMemInfo)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance;
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
CHECK_SYSDEVICEHANDLE(hSysdevice);
CHECK_POINTER(ptExtMemInfo);
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptSysDevice->pbDPMChannelStart;
if(0 == g_tDriverInfo.ulOpenCount)
return CIFX_DRV_NOT_OPENED;
switch(ulCmd)
{
case CIFX_GET_EXTENDED_MEMORY_POINTER:
{
void* pvMemoryPtr = NULL;
if( (NULL == ptDevInst->pbExtendedMemory) ||
(0 == ptDevInst->ulExtendedMemorySize))
{
lRet = CIFX_MEMORY_MAPPING_FAILED;
}else
{
ptExtMemInfo->pvMemoryID = NULL;
ptExtMemInfo->pvMemoryPtr = NULL;
ptExtMemInfo->ulMemorySize = 0;
ptExtMemInfo->ulMemoryType = 0;
/* Return global memory information */
if(NULL == (ptExtMemInfo->pvMemoryID = OS_MapUserPointer(ptDevInst->pbExtendedMemory,
ptDevInst->ulExtendedMemorySize,
&pvMemoryPtr,
ptDevInst->pvOSDependent,
0)))
{
lRet = CIFX_MEMORY_MAPPING_FAILED;
} else
{
ptExtMemInfo->pvMemoryPtr = pvMemoryPtr;
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize;
ptExtMemInfo->ulMemoryType = LE32_TO_HOST(HWIF_READ32( ptDevInst, ptSysChannel->tSystemState.ulHWFeatures)) & (HIL_SYSTEM_EXTMEM_ACCESS_MSK | HIL_SYSTEM_EXTMEM_TYPE_MSK);
if( HIL_SYSTEM_EXTMEM_ACCESS_BOTH == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize / 2;
else if( HIL_SYSTEM_EXTMEM_ACCESS_INTERNAL == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
ptExtMemInfo->ulMemorySize = 0;
}
}
}
break;
case CIFX_FREE_EXTENDED_MEMORY_POINTER:
{
/* Clear user area */
if(!OS_UnmapUserPointer(ptExtMemInfo->pvMemoryID, ptDevInst->pvOSDependent))
{
lRet = CIFX_INVALID_HANDLE;
} else
{
ptExtMemInfo->pvMemoryID = NULL;
ptExtMemInfo->pvMemoryPtr = NULL;
ptExtMemInfo->ulMemorySize = 0;
ptExtMemInfo->ulMemoryType = 0;
}
}
break;
case CIFX_GET_EXTENDED_MEMORY_INFO:
{
ptExtMemInfo->pvMemoryID = NULL;
ptExtMemInfo->pvMemoryPtr = NULL;
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize;
ptExtMemInfo->ulMemoryType = LE32_TO_HOST(HWIF_READ32( ptDevInst, ptSysChannel->tSystemState.ulHWFeatures)) & (HIL_SYSTEM_EXTMEM_ACCESS_MSK | HIL_SYSTEM_EXTMEM_TYPE_MSK);
if( HIL_SYSTEM_EXTMEM_ACCESS_BOTH == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize / 2;
else if( HIL_SYSTEM_EXTMEM_ACCESS_INTERNAL == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
ptExtMemInfo->ulMemorySize = 0;
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
} /* end switch */
return lRet;
}
/*****************************************************************************/
/*! Opens a channel by name (Name can be obtained when enumerating Channels)
* \param hDriver Driver handle
* \param szBoard DOS Device Name of the Board to open
* \param ulChannel Channel number to open (0..n)
* \param phChannel Returned handle to the channel (Needed for all channel
* specific operations)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelOpen(CIFXHANDLE hDriver, char* szBoard, uint32_t ulChannel, CIFXHANDLE* phChannel)
{
int32_t lRet = CIFX_INVALID_BOARD;
uint32_t ulIdx;
if(0 == g_tDriverInfo.ulOpenCount)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(szBoard);
CHECK_POINTER(phChannel);
for(ulIdx = 0; ulIdx < g_ulDeviceCount; ++ulIdx)
{
/* Try to find the requested board */
if( (OS_Strcmp(g_pptDevices[ulIdx]->szName, szBoard) == 0) ||
(OS_Strcmp(g_pptDevices[ulIdx]->szAlias, szBoard) == 0) )
{
/* Try to open the given channel */
lRet = CIFX_INVALID_CHANNEL;
if(ulChannel < g_pptDevices[ulIdx]->ulCommChannelCount)
{
/* We found the channel */
PCHANNELINSTANCE ptChannel = g_pptDevices[ulIdx]->pptCommChannels[ulChannel];
++ptChannel->ulOpenCount;
*phChannel = (CIFXHANDLE)ptChannel;
lRet = CIFX_NO_ERROR;
}
break;
}
}
return lRet; /*lint !e438 */
}
/*****************************************************************************/
/*! Closes a previously opened channel
* \param hChannel Channel handle acquired by xChannelOpen
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelClose(CIFXHANDLE hChannel)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
--ptChannel->ulOpenCount;
return CIFX_NO_ERROR;
}
/*****************************************************************************/
/*! Download a file (Firmware, Configuration, etc) to the device
* \param hChannel Handle to the channel
* \param ulMode Download mode (DOWNLOAD_MODE_FIRMWARE, etc)
* \param pszFileName Name of the file
* \param pabFileData Pointer to the file data
* \param ulFileSize Length of the file data
* \param pfnCallback Callback for progress indication
* (NULL for no callback)
* \param pfnRecvPktCallback Callback Callback pointer for unsolicited receive packets
* (NULL for no callback)
* \param pvUser User parameter passed to callback
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelDownload(CIFXHANDLE hChannel, uint32_t ulMode,
char* pszFileName, uint8_t* pabFileData, uint32_t ulFileSize,
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
uint32_t ulTransferType = 0;
int32_t lRet = CIFX_NO_ERROR;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pszFileName);
CHECK_POINTER(pabFileData);
switch(ulMode)
{
case DOWNLOAD_MODE_FIRMWARE:
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->eChipType,
pszFileName, &ulTransferType)))
return lRet;
break;
case DOWNLOAD_MODE_CONFIG:
case DOWNLOAD_MODE_FILE:
ulTransferType = HIL_FILE_XFER_FILE;
break;
case DOWNLOAD_MODE_LICENSECODE:
ulTransferType = HIL_FILE_XFER_LICENSE_CODE;
break;
default:
return CIFX_INVALID_PARAMETER;
}
lRet = DEV_DownloadFile(ptChannel,
ptChannel->ulChannelNumber,
ptChannel->tSendMbx.ulSendMailboxLength,
ulTransferType,
pszFileName,
ulFileSize,
pabFileData,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser);
return lRet;
}
/*****************************************************************************/
/*! Returns the Mailbox state from a specific channel
* \param hChannel Channel handle acquired by xChannelOpen
* \param pulRecvPktCount Number of Messages waiting in receive mailbox
* \param pulSendPktCount State of the Send Mailbox
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelGetMBXState(CIFXHANDLE hChannel, uint32_t* pulRecvPktCount, uint32_t* pulSendPktCount)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
return DEV_GetMBXState(ptChannel, pulRecvPktCount, pulSendPktCount);
}
/*****************************************************************************/
/*! Inserts a packet into the channels mailbox
* \param hChannel Channel handle acquired by xChannelOpen
* \param ptSendPkt Packet to send to channel
* \param ulTimeout Time in ms to wait for card to accept the packet
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPutPacket(CIFXHANDLE hChannel, CIFX_PACKET* ptSendPkt, uint32_t ulTimeout)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if another command is active */
if ( 0 == OS_WaitMutex( ptChannel->tSendMbx.pvSendMBXMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
lRet = DEV_PutPacket(ptChannel, ptSendPkt, ulTimeout);
/* Release command */
OS_ReleaseMutex(ptChannel->tSendMbx.pvSendMBXMutex);
return lRet;
}
/*****************************************************************************/
/*! Gets a packet from the channels mailbox
* \param hChannel Channel handle acquired by xChannelOpen
* \param ulSize Size of the return packet buffer
* \param ptRecvPkt Returned packet
* \param ulTimeout Time in ms to wait for available message
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelGetPacket(CIFXHANDLE hChannel, uint32_t ulSize, CIFX_PACKET* ptRecvPkt, uint32_t ulTimeout)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if another command is active */
if ( 0 == OS_WaitMutex( ptChannel->tRecvMbx.pvRecvMBXMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
lRet = DEV_GetPacket(ptChannel, ptRecvPkt, ulSize, ulTimeout);
/* Release command */
OS_ReleaseMutex(ptChannel->tRecvMbx.pvRecvMBXMutex);
return lRet;
}
/*****************************************************************************/
/*! Gets send packet from the channels mailbox
* \param hChannel Channel handle acquired by xChannelOpen
* \param ulSize Size of the return packet buffer
* \param ptRecvPkt Returned packet
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelGetSendPacket(CIFXHANDLE hChannel, uint32_t ulSize, CIFX_PACKET* ptRecvPkt)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CIFX_PACKET* ptPacket = (CIFX_PACKET*)ptChannel->tSendMbx.ptSendMailboxStart->abSendMailbox;
uint32_t ulCopySize = 0;
ulCopySize = HWIF_READ32(ptChannel->pvDeviceInstance, ptPacket->tHeader.ulLen) + HIL_PACKET_HEADER_SIZE;
if( ulCopySize > ulSize)
{
/* Use the user buffer length if packet does not fit in the user buffer */
ulCopySize = ulSize;
lRet = CIFX_BUFFER_TOO_SHORT;
}
/* Just copy the available data into the user buffer */
HWIF_READN(ptChannel->pvDeviceInstance, ptRecvPkt, ptPacket, ulCopySize);
return lRet;
}
/*****************************************************************************/
/*! Lock the configuration on a communication channel
* \param hChannel Channel handle
* \param ulCmd CIFX_CONFIGURATION_XXX defines
* \param pulState Return locking state
* \param ulTimeout Timeout in [ms]
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelConfigLock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pulState);
/* Check if we are in interrupt mode */
if(!((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->fIrqEnabled)
DEV_ReadHandshakeFlags(ptChannel, 0, 1);
/* TODO: WAIT until card has recognized the LOCK command */
UNREFERENCED_PARAMETER(ulTimeout);
switch (ulCmd)
{
case CIFX_CONFIGURATION_LOCK:
{
/* Check if the configuration is already LOCKED */
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_CONFIG_LOCKED)
{
/* Configuration already locked */
*pulState = CIFX_CONFIGURATION_LOCK;
} else
{
lRet = DEV_DoHostCOSChange(ptChannel,
HIL_APP_COS_LOCK_CONFIGURATION | HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
0,
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
CIFX_DEV_CONFIG_LOCK_TIMEOUT,
ulTimeout);
if(CIFX_NO_ERROR == lRet)
{
/* Set actual state */
*pulState = CIFX_CONFIGURATION_LOCK;
}
}
}
break;
case CIFX_CONFIGURATION_UNLOCK:
{
/* Check if the configuration is NOT LOCKED */
if( !(ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_CONFIG_LOCKED))
{
/* Configuration is NOT locked */
*pulState = CIFX_CONFIGURATION_UNLOCK;
} else
{
lRet = DEV_DoHostCOSChange(ptChannel,
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
HIL_APP_COS_LOCK_CONFIGURATION,
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
CIFX_DEV_CONFIG_UNLOCK_TIMEOUT,
ulTimeout);
if(CIFX_NO_ERROR == lRet)
{
/* Set actual state */
*pulState = CIFX_CONFIGURATION_UNLOCK;
}
}
}
break;
case CIFX_CONFIGURATION_GETLOCKSTATE:
/* Get the actual state of the config lock bit */
if( 0 == (LE32_TO_HOST(HWIF_READ32(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->ulCommunicationCOS)) & HIL_COMM_COS_CONFIG_LOCKED))
{
/* Configuration is not locked */
*pulState = CIFX_CONFIGURATION_UNLOCK;
} else
{
/* Configuration is locked */
*pulState = CIFX_CONFIGURATION_LOCK;
}
break;
default:
/* Unknown command */
lRet = CIFX_INVALID_COMMAND;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Set BUS state off a communication channel
* \param hChannel Channel handle
* \param ulCmd CIFX_CONFIGURATION_XXX defines
* \param pulState Return actual state on CIFX_GET_BUS_STATE
* \param ulTimeout Timeout in [ms]
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelBusState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
{
int32_t lRet = CIFX_INVALID_PARAMETER;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pulState);
lRet = DEV_BusState( (PCHANNELINSTANCE)hChannel,
ulCmd,
pulState,
ulTimeout);
return lRet;
}
/*****************************************************************************/
/*! Reset a communication channel
* \param hChannel Channel handle
* \param ulResetMode Reset Mode
* \param ulTimeout Timeout to wait for reset complete in [ms]
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelReset(CIFXHANDLE hChannel, uint32_t ulResetMode, uint32_t ulTimeout)
{
int32_t lRet;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
/* TODO: Get packet and I/O mutexe before processing a channel init */
/* TODO: System start via channel ? */
switch(ulResetMode)
{
case CIFX_SYSTEMSTART:
lRet = DEV_DoSystemStart(ptChannel, ulTimeout, 0);
#ifdef CIFX_TOOLKIT_TIME
if (CIFX_NO_ERROR == lRet)
cifXInitTime((PDEVICEINSTANCE)ptChannel->pvDeviceInstance);
#endif
break;
case CIFX_CHANNELINIT:
lRet = DEV_DoChannelInit(ptChannel, ulTimeout);
break;
default:
lRet = CIFX_INVALID_PARAMETER;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Reads I/O Area information for the given Channel
* \param hChannel Channel handle
* \param ulCmd CIFX_IO_INPUT_AREA/CIFX_IO_OUTPUT_AREA
* \param ulAreaNumber Number of area to get information for
* \param ulSize Size of returned data structure
* \param pvData Pointer to returned data
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelIOInfo(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulAreaNumber, uint32_t ulSize, void* pvData)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHANNEL_IO_INFORMATION* ptIoInformation = (CHANNEL_IO_INFORMATION*)pvData;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvData);
if(ulSize != sizeof(*ptIoInformation))
return CIFX_INVALID_BUFFERSIZE;
if(!DEV_IsRunning(ptChannel))
{
lRet = CIFX_DEV_NOT_RUNNING;
}
switch(ulCmd)
{
case CIFX_IO_INPUT_AREA:
{
if(0 == ptChannel->ulIOInputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else if(ulAreaNumber >= ptChannel->ulIOInputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
PIOINSTANCE ptIoArea = ptChannel->pptIOInputAreas[ulAreaNumber];
if(HIL_IO_MODE_DEFAULT != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDInHskMode))
ptIoInformation->ulIOMode = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDInHskMode);
else
ptIoInformation->ulIOMode = ptIoArea->usHandshakeMode;
ptIoInformation->ulTotalSize = ptIoArea->ulDPMAreaLength;
}
}
break;
case CIFX_IO_OUTPUT_AREA:
{
if(0 == ptChannel->ulIOOutputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
PIOINSTANCE ptIoArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
if(HIL_IO_MODE_DEFAULT != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDOutHskMode))
ptIoInformation->ulIOMode = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDOutHskMode);
else
ptIoInformation->ulIOMode = ptIoArea->usHandshakeMode;
ptIoInformation->ulTotalSize = ptIoArea->ulDPMAreaLength;
}
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Reads the Input data from the channel
* \param hChannel Channel handle acquired by xChannelOpen
* \param ulAreaNumber Number of the I/O Area (0..n)
* \param ulOffset Data offset in Input area
* \param ulDataLen Length of data to read
* \param pvData Buffer to place returned data
* \param ulTimeout Timeout in ms to wait for finished I/O Handshake
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelIORead(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData, uint32_t ulTimeout)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
int32_t lRet = CIFX_NO_ERROR;
PIOINSTANCE ptIOArea = NULL;
uint8_t bIOBitState = HIL_FLAGS_NONE;
if(!DEV_IsRunning(ptChannel))
return CIFX_DEV_NOT_RUNNING;
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
return CIFX_INVALID_PARAMETER;
ptIOArea = ptChannel->pptIOInputAreas[ulAreaNumber];
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
#ifdef CIFX_TOOLKIT_DMA
/* Check for DMA transfer */
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
{
/*------------------------------*/
/* This is DMA IO data transfer */
/*------------------------------*/
/* This is DMACh n */
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_INPUT_BUFFER_IDX;
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Check if another command is active */
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
/* TODO: define read procedure ??Toggle -> Read or READ->Toggle */
if(HIL_FLAGS_NONE == bIOBitState)
{
/* Read data without handshake does not work in DMA operation*/
lRet = CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED;
} else
{
/* Read data */
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
{
lRet = CIFX_DEV_EXCHANGE_FAILED;
} else
{
/* Read data */
OS_Memcpy( pvData,
((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset,
ulDataLen);
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
/* Read data done */
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
}
/* Release command */
OS_ReleaseMutex( ptIOArea->pvMutex);
} else
#endif
{
/*---------------------------*/
/* This is DPM data transfer */
/*---------------------------*/
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Check if another command is active */
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
/* Read data */
if(HIL_FLAGS_NONE == bIOBitState)
{
/* Read data */
HWIF_READN( ptChannel->pvDeviceInstance,
pvData,
&ptIOArea->pbDPMAreaStart[ulOffset],
ulDataLen);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
} else if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
{
lRet = CIFX_DEV_EXCHANGE_FAILED;
} else
{
/* Read data */
HWIF_READN( ptChannel->pvDeviceInstance,
pvData,
&ptIOArea->pbDPMAreaStart[ulOffset],
ulDataLen);
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
/* Read data done */
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
/* Release command */
OS_ReleaseMutex( ptIOArea->pvMutex);
}
return lRet;
}
/*****************************************************************************/
/*! Writes the Output data to the channel
* \param hChannel Channel handle acquired by xChannelOpen
* \param ulAreaNumber Number of the I/O Area (0..n)
* \param ulOffset Data offset in Output area
* \param ulDataLen Length of data to send
* \param pvData Buffer containing send data
* \param ulTimeout Timeout in ms to wait for handshake completion
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelIOWrite(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData, uint32_t ulTimeout)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
int32_t lRet = CIFX_NO_ERROR;
PIOINSTANCE ptIOArea = NULL;
uint8_t bIOBitState = HIL_FLAGS_NONE;
if(!DEV_IsRunning(ptChannel))
return CIFX_DEV_NOT_RUNNING;
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
return CIFX_INVALID_PARAMETER;
ptIOArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
#ifdef CIFX_TOOLKIT_DMA
/* Check for DMA transfer */
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
{
/*------------------------------*/
/* This is DMA IO data transfer */
/*------------------------------*/
/* This is DMACh n+1 */
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX;
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Check if another command is active */
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
/* Read data */
/* TODO: define read procedure ??Toggle -> Read or READ->Toggle */
if(HIL_FLAGS_NONE == bIOBitState)
{
/* Read data without handshake does not work in DMA operation*/
lRet = CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED;
} else
{
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
{
lRet = CIFX_DEV_EXCHANGE_FAILED;
} else
{
/* Read data */
OS_Memcpy( (((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset),
pvData,
ulDataLen);
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
/* Read data done */
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
}
/* Release command */
OS_ReleaseMutex( ptIOArea->pvMutex);
} else
#endif
{
/*---------------------------*/
/* This is DPM data transfer */
/*---------------------------*/
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Check if another command is active */
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
return CIFX_DRV_CMD_ACTIVE;
/* Read data */
/* TODO: define write procedure ??Toggle -> Write or Write->Toggle */
if(HIL_FLAGS_NONE == bIOBitState)
{
/* Read data without handshake */
HWIF_WRITEN( ptChannel->pvDeviceInstance,
&ptIOArea->pbDPMAreaStart[ulOffset],
pvData,
ulDataLen);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
} else
{
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
{
lRet = CIFX_DEV_EXCHANGE_FAILED;
} else
{
/* Read data */
HWIF_WRITEN( ptChannel->pvDeviceInstance,
&ptIOArea->pbDPMAreaStart[ulOffset],
pvData,
ulDataLen);
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
/* Read data done */
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
/* Check COMM Flag for return value */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
}
/* Release command */
OS_ReleaseMutex( ptIOArea->pvMutex);
}
return lRet;
}
/*****************************************************************************/
/*! Read back Send Data Area from channel
* \param hChannel Channel handle acquired by xChannelOpen
* \param ulAreaNumber Number of the I/O Area (0..n)
* \param ulOffset Data start offset
* \param ulDataLen Data length to read
* \param pvData Data buffer
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelIOReadSendData(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
int32_t lRet = CIFX_NO_ERROR;
#ifdef CIFX_TOOLKIT_DMA
/* Check for DMA transfer */
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
{
/* This is DMACh n */
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX; /* We reading the Output buffer */
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Read data */
OS_Memcpy( pvData,
((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset,
ulDataLen);
} else
#endif
{
PIOINSTANCE ptIOArea = NULL;
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
return CIFX_INVALID_PARAMETER;
ptIOArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
/* Read data */
HWIF_READN(ptChannel->pvDeviceInstance,
pvData,
&ptIOArea->pbDPMAreaStart[ulOffset],
ulDataLen);
}
return lRet;
}
/*****************************************************************************/
/*! Read/Write Control block
* \param hChannel Handle to the channel
* \param ulCmd CIFX_CMD_READ_DATA/CIFX_CMD_WRITE_DATA
* \param ulOffset Start offset of read/write
* \param ulDataLen Length of data to read/write
* \param pvData Buffer to copy from/to
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelControlBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvData);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
/* Check if CONTROL block is available */
} else if(NULL == ptChannel->ptControlBlock)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
if ((ulOffset + ulDataLen) > ptChannel->ulControlBlockSize)
lRet = CIFX_INVALID_ACCESS_SIZE;
else
{
HIL_DPM_CONTROL_BLOCK_T tChannelControlBlockTmp = {0};
void* pvDataInternal = pvData; /* Default to user buffer */
int32_t lRetTmp = CIFX_NO_ERROR; /* Error from the conversion function */
if(CIFX_CMD_WRITE_DATA == ulCmd)
{
/* To prohibit changes to user supplied buffer on write, use a local copy instead */
pvDataInternal = (void*)(((uint8_t*)&tChannelControlBlockTmp) + ulOffset);
OS_Memcpy(pvDataInternal, pvData, ulDataLen);
lRetTmp = cifXConvertEndianess(ulOffset,
pvDataInternal,
ulDataLen,
s_atControlBlock,
sizeof(s_atControlBlock) / sizeof(s_atControlBlock[0]));
}
if(CIFX_NO_ERROR == lRetTmp)
{
lRet = DEV_ReadWriteBlock(ptChannel,
(void*)ptChannel->ptControlBlock,
ulOffset,
ptChannel->ulControlBlockSize,
pvDataInternal,
ulDataLen,
ulCmd,
1);
}
/* Note: We accept errors from the DEV_ReadWriteBlock() function because we want to inform the user in any case */
/* (e.g. CIFX_DEV_NOT_RUNNING) even if we running the conversion on an not filled / empty buffer! */
if(CIFX_CMD_READ_DATA == ulCmd)
{
lRetTmp = cifXConvertEndianess(ulOffset,
pvDataInternal,
ulDataLen,
s_atControlBlock,
sizeof(s_atControlBlock) / sizeof(s_atControlBlock[0]));
}
/* Error of DEV_ReadWriteBlock() takes priority over (possible) Endianess conversion error */
if((CIFX_NO_ERROR == lRet) && (CIFX_NO_ERROR != lRetTmp))
lRet = lRetTmp;
}
}
return lRet;
}
/*****************************************************************************/
/*! Read/Write Common status block
* \param hChannel Handle to the channel
* \param ulCmd CIFX_CMD_READ_DATA
* \param ulOffset Start offset of read
* \param ulDataLen Length of data to read
* \param pvData Buffer to copy to
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelCommonStatusBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvData);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
/* Check if STATUS block is available */
} else if(NULL == ptChannel->ptCommonStatusBlock)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
lRet = DEV_ReadWriteBlock(ptChannel,
(void*)ptChannel->ptCommonStatusBlock,
ulOffset,
ptChannel->ulCommonStatusSize,
pvData,
ulDataLen,
ulCmd,
0);
/* Note: We accept errors from the DEV_ReadWriteBlock() function because we want to inform the user in any case */
/* (e.g. CIFX_DEV_NOT_RUNNING) even if we running the conversion on an not filled / empty buffer! */
if(CIFX_CMD_READ_DATA == ulCmd)
{
int32_t lRetTmp = cifXConvertEndianess(ulOffset,
pvData,
ulDataLen,
s_atCommonStatusBlock,
sizeof(s_atCommonStatusBlock) / sizeof(s_atCommonStatusBlock[0]));
/* Error of DEV_ReadWriteBlock() takes priority over (possible) Endianess conversion error */
if((CIFX_NO_ERROR == lRet) && (CIFX_NO_ERROR != lRetTmp))
lRet = lRetTmp;
}
}
return lRet;
}
/*****************************************************************************/
/*! Read Extended status block
* \param hChannel Handle to the channel
* \param ulCmd CIFX_CMD_READ_DATA
* \param ulOffset Start offset of read
* \param ulDataLen Length of data to read
* \param pvData Buffer to copy to
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelExtendedStatusBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvData);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
/* Check if CONTROL block is available */
} else if(NULL == ptChannel->ptExtendedStatusBlock)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
lRet = DEV_ReadWriteBlock(ptChannel,
(void*)ptChannel->ptExtendedStatusBlock,
ulOffset,
ptChannel->ulExtendedStatusSize,
pvData,
ulDataLen,
ulCmd,
0);
}
return lRet;
}
/*****************************************************************************/
/*! Read a user block
* \param hChannel Handle to the channel
* \param ulAreaNumber Userblock number
* \param ulCmd CIFX_CMD_READ_DATA
* \param ulOffset Start offset of read
* \param ulDataLen Length of data to read
* \param pvData Buffer to copy to
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelUserBlock(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvData);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
/* Check if CONTROL block is available */
} else if( (ulAreaNumber >= ptChannel->ulUserAreas) ||
(NULL == ptChannel->pptUserAreas[ulAreaNumber]) )
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
PUSERINSTANCE ptUserInstance = ptChannel->pptUserAreas[ulAreaNumber];
lRet = DEV_ReadWriteBlock(ptChannel,
(void*)ptUserInstance->pbUserBlockStart,
ulOffset,
ptUserInstance->ulUserBlockLength,
pvData,
ulDataLen,
ulCmd,
1);
}
return lRet;
}
/*****************************************************************************/
/*! Gets a pointer to an IO Area
* \param hChannel Handle to the channel
* \param ulCmd CIFX_MEM_PTR_OPEN/CIFX_MEM_PTR_CLOSE
* \param pvMemoryInfo Pointer to requested memory structure
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPLCMemoryPtr(CIFXHANDLE hChannel, uint32_t ulCmd, void* pvMemoryInfo)
{
PLC_MEMORY_INFORMATION* ptMemory = (PLC_MEMORY_INFORMATION*)pvMemoryInfo;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
int fUseCaching = 0;
unsigned long ulAreaDefinition = 0;
PDEVICEINSTANCE ptDevInst = NULL;
int32_t lRet = CIFX_NO_ERROR;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvMemoryInfo);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
return CIFX_DRV_CHANNEL_NOT_INITIALIZED;
if( (0 == ptChannel->ulIOInputAreas) ||
(0 == ptChannel->ulIOOutputAreas) )
/* No IO blocks defined */
return CIFX_FUNCTION_NOT_AVAILABLE;
ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
fUseCaching = ptDevInst->fCachedMemAccess;
ulAreaDefinition = ptMemory->ulAreaDefinition;
#ifdef CIFX_CACHE_TEST
/* Check for additional option in area definition */
/* and overwrite if additional flags are set. */
if (0 != (ulAreaDefinition & ~CIFX_IO_AREA_MASK))
{
/* Override caching option to get uncached pointers */
ulAreaDefinition &= CIFX_IO_AREA_MASK;
fUseCaching = 0;
}
#endif
#ifdef CIFX_TOOLKIT_DMA
/* Check for DMA transfer */
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
{
/*------------------------------*/
/* This is DMA IO data transfer */
/*------------------------------*/
/* This is DMACh n */
PCIFX_DMABUFFER_T ptDmaInfo = NULL;
CACHED_MEMORY_AREA_T* ptCachedMemInfo = NULL;
uint32_t ulDMChIdx = 0;
if(0 != ptMemory->ulAreaNumber)
{
/* Invalid IO area */
lRet = CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED; /* Only support for area 0 in DMA mode */
} else
{
if (ulAreaDefinition == CIFX_IO_INPUT_AREA)
{
ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_INPUT_BUFFER_IDX;
ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
ptCachedMemInfo = &ptChannel->tCachedIOInputArea;
} else
{
ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX;
ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
ptCachedMemInfo = &ptChannel->tCachedIOOutputArea;
}
/* Check user command */
switch(ulCmd)
{
case CIFX_MEM_PTR_OPEN:
{
void* pvMappedDPM = NULL;
void* pvDPM = ptDmaInfo->pvBuffer;
uint32_t ulDPMSize = ptDmaInfo->ulSize;
/* Check for caching option */
if ((0 != fUseCaching) &&
(NULL != ptCachedMemInfo->pvMemPtr))
{
/* Mapping already exists */
lRet = CIFX_NO_MORE_ENTRIES;
} else
{
/* Return global memory information */
if (NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(pvDPM, ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, (unsigned char)fUseCaching)))
{
lRet = CIFX_MEMORY_MAPPING_FAILED;
} else
{
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
*(ptMemory->pulIOAreaStartOffset) = 0; /* In DMA mode, we don't have a DPM start offeset */
*(ptMemory->pulIOAreaSize) = ulDPMSize;
/* Store the memory pointer for later cache operation (e.g. flush) */
if (0 != fUseCaching)
{
ptCachedMemInfo->pvMemPtr = (void*)pvMappedDPM;
ptCachedMemInfo->ulAreaSize = ulDPMSize;
}
}
}
}
break;
case CIFX_MEM_PTR_CLOSE:
{
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
{
lRet = CIFX_INVALID_HANDLE;
} else
{
ptMemory->pvMemoryID = NULL;
*(ptMemory->ppvMemoryPtr) = NULL;
*(ptMemory->pulIOAreaStartOffset) = 0;
*(ptMemory->pulIOAreaSize) = 0;
if (0 != fUseCaching)
{
/* Remove any stored cache buffer information */
ptCachedMemInfo->pvMemPtr = NULL;
ptCachedMemInfo->ulAreaSize = 0;
}
}
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
} /* end switch */
}
} else
#endif
{
PIOINSTANCE* pptIOInstances = NULL;
uint32_t ulAreaCount = 0;
CACHED_MEMORY_AREA_T* ptCachedMemInfo = NULL;
if(ulAreaDefinition == CIFX_IO_INPUT_AREA)
{
ulAreaCount = ptChannel->ulIOInputAreas;
pptIOInstances = ptChannel->pptIOInputAreas;
ptCachedMemInfo = &ptChannel->tCachedIOInputArea;
} else
{
ulAreaCount = ptChannel->ulIOOutputAreas;
pptIOInstances = ptChannel->pptIOOutputAreas;
ptCachedMemInfo = &ptChannel->tCachedIOOutputArea;
}
/* Check if IO area is available */
if (ptMemory->ulAreaNumber >= ulAreaCount)
{
/* Invalid IO area */
lRet = CIFX_INVALID_PARAMETER;
} else
{
/* Check user command */
switch(ulCmd)
{
case CIFX_MEM_PTR_OPEN:
{
void* pvMappedDPM = NULL;
void* pvDPM = pptIOInstances[ptMemory->ulAreaNumber]->pbDPMAreaStart;
uint32_t ulDPMSize = pptIOInstances[ptMemory->ulAreaNumber]->ulDPMAreaLength;
/* Check for caching option */
if ((0 != fUseCaching) &&
(NULL != ptCachedMemInfo->pvMemPtr))
{
/* Mapping already exists */
lRet = CIFX_NO_MORE_ENTRIES;
}else
{
/* Return global memory information */
if (NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(pvDPM, ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, (unsigned char)fUseCaching)))
{
lRet = CIFX_MEMORY_MAPPING_FAILED;
} else
{
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
*(ptMemory->pulIOAreaStartOffset) = (uint32_t)(pptIOInstances[ptMemory->ulAreaNumber]->pbDPMAreaStart -
ptChannel->pbDPMChannelStart);
*(ptMemory->pulIOAreaSize) = ulDPMSize;
if (0 != fUseCaching)
{
/* Remove any stored cache buffer information */
ptCachedMemInfo->pvMemPtr = (void*)pvMappedDPM;
ptCachedMemInfo->ulAreaSize = ulDPMSize;
}
}
}
}
break;
case CIFX_MEM_PTR_CLOSE:
{
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
{
lRet = CIFX_INVALID_HANDLE;
} else
{
ptMemory->pvMemoryID = NULL;
*(ptMemory->ppvMemoryPtr) = NULL;
*(ptMemory->pulIOAreaStartOffset) = 0;
*(ptMemory->pulIOAreaSize) = 0;
if (0 != fUseCaching)
{
/* Remove any stored cache buffer information */
ptCachedMemInfo->pvMemPtr = NULL;
ptCachedMemInfo->ulAreaSize = 0;
}
}
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
} /* end switch */
}
}
return lRet;
}
/*****************************************************************************/
/*! Checks if the given IO Area is ready for the next handshake
* \param hChannel Handle to the channel
* \param ulAreaNumber Area to check
* \param pulReadState Returned state of the area (!=0 means area is ready)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPLCIsReadReady(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t* pulReadState)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
} else if(0 == ptChannel->ulIOInputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
/* Check if IO area is available */
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
/* Check if the device is communication. If only the COM flag is missing, we return the current bit state */
(void)DEV_IsCommunicating(ptChannel, &lRet);
if( (lRet != CIFX_DEV_NOT_READY) &&
(lRet != CIFX_DEV_NOT_RUNNING) )
{
/* Read back the send data area */
PIOINSTANCE ptIOInst = ptChannel->pptIOInputAreas[ulAreaNumber];
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOInst, 0);
*pulReadState = 0;
if( (HIL_FLAGS_NONE == bIOBitState) ||
(DEV_GetHandshakeBitState(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit)) == bIOBitState) )
{
*pulReadState = 1;
/* Invalidate the IO input buffer, for cache refresh */
if (NULL != ptChannel->tCachedIOInputArea.pvMemPtr)
{
OS_InvalidateCacheMemory_FromDevice(ptChannel->tCachedIOInputArea.pvMemPtr, ptChannel->tCachedIOInputArea.ulAreaSize);
}
}
}
}
}
/* Assuming that the request was handled */
return lRet;
}
/*****************************************************************************/
/*! Checks if the given IO Area is ready for the next handshake
* \param hChannel Handle to the channel
* \param ulAreaNumber Area to check
* \param pulWriteState Returned state of the area (!=0 means area is ready)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPLCIsWriteReady(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t* pulWriteState)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
} else if(0 == ptChannel->ulIOOutputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
/* Check if IO area is available */
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
/* Check if the device is communication. If only the COM flag is missing, we return the current bit state */
(void)DEV_IsCommunicating(ptChannel, &lRet);
if( (lRet != CIFX_DEV_NOT_READY) &&
(lRet != CIFX_DEV_NOT_RUNNING) )
{
/* Read back the send data area */
PIOINSTANCE ptIOInst = ptChannel->pptIOOutputAreas[ulAreaNumber];
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOInst, 1);
*pulWriteState = 0;
if( (HIL_FLAGS_NONE == bIOBitState) ||
(DEV_GetHandshakeBitState(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit)) == bIOBitState) )
{
*pulWriteState = 1;
}
}
}
}
/* Assuming that the request was handled */
return lRet;
}
/*****************************************************************************/
/*! Toggles the Handshake bit for the given IO Output Area
* \param hChannel Handle to the channel
* \param ulAreaNumber Areanumber
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPLCActivateWrite(CIFXHANDLE hChannel, uint32_t ulAreaNumber)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
} else if(0 == ptChannel->ulIOOutputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
/* Check if IO area is available */
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
/* Check if the device is communication. If only the COM flag is missing, we toggle the bits */
(void)DEV_IsCommunicating(ptChannel, &lRet);
if( (lRet != CIFX_DEV_NOT_READY) &&
(lRet != CIFX_DEV_NOT_RUNNING) )
{
PIOINSTANCE ptIOInst = ptChannel->pptIOOutputAreas[ulAreaNumber];
/* Flush the IO output cache to output buffer */
if (NULL != ptChannel->tCachedIOOutputArea.pvMemPtr)
{
OS_FlushCacheMemory_ToDevice(ptChannel->tCachedIOOutputArea.pvMemPtr, ptChannel->tCachedIOOutputArea.ulAreaSize);
}
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
}
}
}
return lRet;
}
/*****************************************************************************/
/*! Toggles the Handshake bit for the given IO Input Area
* \param hChannel Handle to the channel
* \param ulAreaNumber Areanumber
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelPLCActivateRead(CIFXHANDLE hChannel, uint32_t ulAreaNumber)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
} else if(0 == ptChannel->ulIOInputAreas)
{
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
} else
{
/* Check if IO area is available */
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
{
lRet = CIFX_INVALID_PARAMETER;
} else
{
/* Check if the device is communication. If only the COM flag is missing, we toggle the bits */
(void)DEV_IsCommunicating(ptChannel, &lRet);
if( (lRet != CIFX_DEV_NOT_READY) &&
(lRet != CIFX_DEV_NOT_RUNNING) )
{
PIOINSTANCE ptIOInst = ptChannel->pptIOInputAreas[ulAreaNumber];
/* Lock flag access */
OS_EnterLock(ptChannel->pvLock);
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit));
/* Unlock flag access */
OS_LeaveLock(ptChannel->pvLock);
}
}
}
return lRet;
}
#ifndef CIFX_TOOLKIT_USE_CUSTOM_DRV_FUNCS
/*****************************************************************************/
/*! Open a connection to the driver
* \param phDriver Returned handle to the driver
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverOpen(CIFXHANDLE* phDriver)
{
if(!g_tDriverInfo.fInitialized)
return CIFX_DRV_DRIVER_NOT_LOADED;
CHECK_POINTER(phDriver);
*phDriver = &g_tDriverInfo;
++g_tDriverInfo.ulOpenCount;
return CIFX_NO_ERROR;
}
/*****************************************************************************/
/*! Close a connection to the driver
* \param hDriver Handle to connection, that is being closed
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverClose(CIFXHANDLE hDriver)
{
if(!g_tDriverInfo.fInitialized)
return CIFX_DRV_DRIVER_NOT_LOADED;
if(g_tDriverInfo.ulOpenCount == 0)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
--g_tDriverInfo.ulOpenCount;
return CIFX_NO_ERROR; /*lint !e438 */
}
/*****************************************************************************/
/*! Query Driver information
* \param hDriver Handle to the driver
* \param ulSize Size of the passed DRIVER_INFORMATION Structure
* \param pvDriverInfo Pointer to returned data (DRIVER_INFORMATION
* structure)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverGetInformation(CIFXHANDLE hDriver, uint32_t ulSize, void* pvDriverInfo)
{
DRIVER_INFORMATION* ptDriverInfo = (DRIVER_INFORMATION*)pvDriverInfo;
if(g_tDriverInfo.ulOpenCount == 0)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(pvDriverInfo);
if(ulSize < (uint32_t)sizeof(*ptDriverInfo))
return CIFX_INVALID_BUFFERSIZE;
ptDriverInfo->ulBoardCnt = g_ulDeviceCount;
(void)OS_Strncpy(ptDriverInfo->abDriverVersion, TOOLKIT_VERSION, sizeof(ptDriverInfo->abDriverVersion));
return CIFX_NO_ERROR; /*lint !e438 */
}
#endif
/*****************************************************************************/
/*! Query human readable error description
* \param lError Error to look up
* \param szBuffer Pointer to return data
* \param ulBufferLen Length of return buffer
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverGetErrorDescription(int32_t lError, char* szBuffer, uint32_t ulBufferLen)
{
int32_t lRet = CIFX_FUNCTION_FAILED;
int iIdx = 0;
CHECK_POINTER(szBuffer);
for(iIdx = 0; iIdx < (int)(sizeof(s_atErrorToDescrTable) / sizeof(s_atErrorToDescrTable[0])); ++iIdx)
{
if(s_atErrorToDescrTable[iIdx].lError == lError)
{
(void)OS_Strncpy(szBuffer, s_atErrorToDescrTable[iIdx].szErrorDescr, ulBufferLen);
lRet = CIFX_NO_ERROR;
break;
}
}
return lRet;
}
/*****************************************************************************/
/*! Enumerate over all handled boards/devices
* \param hDriver Driver handle
* \param ulBoard Board number (incremented from 0 up)
* \param ulSize Size of return buffer
* \param pvBoardInfo Return buffer (BOARD_INFORMATION structure)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverEnumBoards(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulSize, void* pvBoardInfo)
{
BOARD_INFORMATION* ptBoardInfo = (BOARD_INFORMATION*)pvBoardInfo;
PDEVICEINSTANCE ptDevInstance = NULL;
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
if(g_tDriverInfo.ulOpenCount == 0)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(pvBoardInfo);
if(ulSize < (uint32_t)sizeof(*ptBoardInfo))
return CIFX_INVALID_BUFFERSIZE;
if(ulBoard >= g_ulDeviceCount)
return CIFX_NO_MORE_ENTRIES;
ptDevInstance = g_pptDevices[ulBoard];
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptDevInstance->pbDPM;
(void)OS_Strncpy(ptBoardInfo->abBoardName, ptDevInstance->szName, sizeof(ptBoardInfo->abBoardName));
(void)OS_Strncpy(ptBoardInfo->abBoardAlias, ptDevInstance->szAlias, sizeof(ptBoardInfo->abBoardAlias));
ptBoardInfo->ulBoardID = ulBoard;
{
ptBoardInfo->ulSystemError = LE32_TO_HOST(HWIF_READ32(ptDevInstance, ptSysChannel->tSystemState.ulSystemError));
ptBoardInfo->ulPhysicalAddress = ptDevInstance->ulPhysicalAddress;
ptBoardInfo->ulIrqNumber = ptDevInstance->ulIrqNumber;
ptBoardInfo->bIrqEnabled = ptDevInstance->fIrqEnabled? 1 : 0;
ptBoardInfo->ulDpmTotalSize = ptDevInstance->ulDPMSize;
ptBoardInfo->ulChannelCnt = ptDevInstance->ulCommChannelCount;
HWIF_READN(ptDevInstance, &ptBoardInfo->tSystemInfo, &ptSysChannel->tSystemInfo, sizeof(ptBoardInfo->tSystemInfo));
}
(void)cifXConvertEndianess(0,
&ptBoardInfo->tSystemInfo,
sizeof(ptBoardInfo->tSystemInfo),
s_atSystemInfoBlock,
sizeof(s_atSystemInfoBlock) / sizeof(s_atSystemInfoBlock[0]));
return CIFX_NO_ERROR; /*lint !e438 */
}
/*****************************************************************************/
/*! Enumerate over all channels on the given boards
* \param hDriver Driver handle
* \param ulBoard Board number
* \param ulChannel Channel number (incremented from 0 up)
* \param ulSize Size of return buffer
* \param pvChannelInfo Return buffer (CHANNEL_INFORMATION structure)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xDriverEnumChannels(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulChannel, uint32_t ulSize, void* pvChannelInfo)
{
CHANNEL_INFORMATION* ptChannelInfo = (CHANNEL_INFORMATION*)pvChannelInfo;
PDEVICEINSTANCE ptDevInstance = NULL;
PCHANNELINSTANCE ptChannel = NULL;
int32_t lRet = CIFX_NO_ERROR;
if(g_tDriverInfo.ulOpenCount == 0)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(pvChannelInfo);
if(ulSize < (uint32_t)sizeof(*ptChannelInfo))
return CIFX_INVALID_BUFFERSIZE;
if(ulBoard >= g_ulDeviceCount)
return CIFX_INVALID_BOARD;
ptDevInstance = g_pptDevices[ulBoard];
if(ulChannel >= ptDevInstance->ulCommChannelCount)
return CIFX_NO_MORE_ENTRIES;
ptChannel = ptDevInstance->pptCommChannels[ulChannel];
/* Read the channel information */
lRet = xChannelInfo( ptChannel, ulSize, ptChannelInfo);
return lRet; /*lint !e438 */
}
/*! **************************************************************************
* Get/Return a memory pointer to the boards dual-port memory
* \param hDriver Driver handle
* \param ulBoard The board number (0)
* \param ulCmd Function command (CIFX_MEM_PTR_OPEN/CIFX_MEM_PTR_CLOSE)
* \param pvMemoryInfo Memory information structure
* \return CIFX_NO_ERROR on success
******************************************************************************/
int32_t APIENTRY xDriverMemoryPointer(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulCmd, void* pvMemoryInfo)
{
int32_t lRet = CIFX_NO_ERROR;
MEMORY_INFORMATION* ptMemory = (MEMORY_INFORMATION*)pvMemoryInfo;
if(0 == g_tDriverInfo.ulOpenCount)
return CIFX_DRV_NOT_OPENED;
CHECK_DRIVERHANDLE(hDriver);
CHECK_POINTER(pvMemoryInfo);
/* We only support 1 board */
if(ulBoard >= g_ulDeviceCount)
{
lRet = CIFX_INVALID_BOARD;
} else
{
/* Get the device instance */
PDEVICEINSTANCE ptDevInst = g_pptDevices[ulBoard];
switch(ulCmd)
{
case CIFX_MEM_PTR_OPEN:
{
void* pvMappedDPM = NULL;
*(ptMemory->pulMemorySize) = 0;
*(ptMemory->ppvMemoryPtr) = NULL;
/* Return global memory information */
if(NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(ptDevInst->pbDPM, ptDevInst->ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, 0)))
{
lRet = CIFX_MEMORY_MAPPING_FAILED;
} else
{
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
*(ptMemory->pulMemorySize) = ptDevInst->ulDPMSize;
}
/* Check requested channel */
if(ptMemory->ulChannel != CIFX_NO_CHANNEL)
{
/* Process channel information */
if(ptMemory->ulChannel >= ptDevInst->ulCommChannelCount)
{
*(ptMemory->pulChannelStartOffset) = 0;
*(ptMemory->pulChannelSize) = 0;
lRet = CIFX_INVALID_CHANNEL;
} else
{
PCHANNELINSTANCE ptChannel = ptDevInst->pptCommChannels[ptMemory->ulChannel];
uint32_t ulOffset = (uint32_t)(ptChannel->pbDPMChannelStart -
ptDevInst->pbDPM);
/* Get Channel information */
*(ptMemory->pulChannelSize) = ptChannel->ulDPMChannelLength;
*(ptMemory->pulChannelStartOffset) = ulOffset;
}
}
}
break;
case CIFX_MEM_PTR_CLOSE:
/* Clear user area */
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
{
lRet = CIFX_INVALID_HANDLE;
} else
{
ptMemory->pvMemoryID = NULL;
*(ptMemory->ppvMemoryPtr) = NULL;
*(ptMemory->pulMemorySize) = 0;
*(ptMemory->ppvMemoryPtr) = NULL;
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
} /* end switch */
}
return lRet; /*lint !e438 */
}
/*****************************************************************************/
/*! Get Channel information on an open channel
* \param hChannel Handle to the channel
* \param ulSize Size of return buffer
* \param pvChannelInfo Return buffer (CHANNEL_INFORMATION structure)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelInfo(CIFXHANDLE hChannel, uint32_t ulSize, void* pvChannelInfo)
{
CHANNEL_INFORMATION* ptChannelInfo = (CHANNEL_INFORMATION*)pvChannelInfo;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
PDEVICEINSTANCE ptDevInstance = NULL;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pvChannelInfo);
ptDevInstance = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
if(ulSize < (uint32_t)sizeof(*ptChannelInfo))
return CIFX_INVALID_BUFFERSIZE;
(void)OS_Strncpy(ptChannelInfo->abBoardName,
ptDevInstance->szName,
(uint32_t)sizeof(ptChannelInfo->abBoardName));
(void)OS_Strncpy(ptChannelInfo->abBoardAlias,
ptDevInstance->szAlias,
(uint32_t)sizeof(ptChannelInfo->abBoardAlias));
ptChannelInfo->ulDeviceNumber = ptDevInstance->ulDeviceNumber;
ptChannelInfo->ulSerialNumber = ptDevInstance->ulSerialNumber;
ptChannelInfo->usFWMajor = ptChannel->tFirmwareIdent.tFwVersion.usMajor;
ptChannelInfo->usFWMinor = ptChannel->tFirmwareIdent.tFwVersion.usMinor;
ptChannelInfo->usFWRevision = ptChannel->tFirmwareIdent.tFwVersion.usRevision;
ptChannelInfo->usFWBuild = ptChannel->tFirmwareIdent.tFwVersion.usBuild;
ptChannelInfo->bFWNameLength = ptChannel->tFirmwareIdent.tFwName.bNameLength;
OS_Memcpy(ptChannelInfo->abFWName,
ptChannel->tFirmwareIdent.tFwName.abName,
sizeof(ptChannelInfo->abFWName));
ptChannelInfo->usFWYear = ptChannel->tFirmwareIdent.tFwDate.usYear;
ptChannelInfo->bFWMonth = ptChannel->tFirmwareIdent.tFwDate.bMonth;
ptChannelInfo->bFWDay = ptChannel->tFirmwareIdent.tFwDate.bDay;
ptChannelInfo->ulChannelError = 0;
if(0 != ptChannel->ptCommonStatusBlock)
{
ptChannelInfo->ulChannelError = LE32_TO_HOST(HWIF_READ32(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->ulCommunicationError));
}
ptChannelInfo->ulOpenCnt = ptChannel->ulOpenCount;
ptChannelInfo->ulPutPacketCnt = ptChannel->tSendMbx.ulSendPacketCnt;
ptChannelInfo->ulGetPacketCnt = ptChannel->tRecvMbx.ulRecvPacketCnt;
ptChannelInfo->ulMailboxSize = ptChannel->tSendMbx.ulSendMailboxLength;
ptChannelInfo->ulIOInAreaCnt = ptChannel->ulIOInputAreas;
ptChannelInfo->ulIOOutAreaCnt = ptChannel->ulIOOutputAreas;
ptChannelInfo->ulHskSize = ptChannel->bHandshakeWidth;
/* Check if we are in interrupt mode */
if(!((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->fIrqEnabled)
DEV_ReadHandshakeFlags(ptChannel, 0, 1);
ptChannelInfo->ulNetxFlags = ptChannel->usNetxFlags;
ptChannelInfo->ulHostFlags = ptChannel->usHostFlags;
ptChannelInfo->ulHostCOSFlags = ptChannel->ulHostCOSFlags;
ptChannelInfo->ulDeviceCOSFlags = ptChannel->ulDeviceCOSFlags;
return CIFX_NO_ERROR;
}
/*****************************************************************************/
/*! Trigger channels watchdog
* \param hChannel Handle to the channel
* \param ulCmd Trigger command (CIFX_WATCHDOG_START to
* trigger/start, CIFX_WATCHDOG_STOP to end watchdog)
* \param pulTrigger Old trigger value from device
* (informational use only)
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelWatchdog(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulTrigger)
{
return DEV_TriggerWatchdog( (PCHANNELINSTANCE)hChannel, ulCmd, pulTrigger);
}
/*****************************************************************************/
/*! Set/Get Host state of the card
* \param hChannel Handle to the channel
* \param ulCmd Host state command (CIFX_HOST_STATE_NOT_READY,
* CIFX_HOST_STATE_READY, CIFX_HOST_STATE_READ)
* \param pulState Returned state if command is CIFX_HOST_STATE_READ
* \param ulTimeout Time in ms to wait for start/stop communication
* flag
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelHostState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
{
int32_t lRet = CIFX_INVALID_PARAMETER;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pulState);
switch(ulCmd)
{
case CIFX_HOST_STATE_READ:
lRet = DEV_GetHostState( (PCHANNELINSTANCE)hChannel,
pulState);
break;
case CIFX_HOST_STATE_READY:
case CIFX_HOST_STATE_NOT_READY:
lRet = DEV_SetHostState( (PCHANNELINSTANCE)hChannel,
ulCmd,
ulTimeout);
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Starts directory enumeration on the given channel
* \param hChannel Handle to the channel
* \param ptDirectoryInfo Pointer to enumeration result.
* (Will be initialized inside function)
* \param pfnRecvPktCallback Callback for unhandled packets
* \param pvUser User data for callback function
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelFindFirstFile(CIFXHANDLE hChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
return xSysdeviceFindFirstFile(hChannel, ptChannel->ulChannelNumber, ptDirectoryInfo, pfnRecvPktCallback, pvUser);
}
/*****************************************************************************/
/*! Enumerate next entry in directory on the given channel
* \param hChannel Handle to the channel
* \param ptDirectoryInfo Pointer to enumeration result.
* \param pfnRecvPktCallback Callback for unhandled packets
* \param pvUser User data for callback function
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelFindNextFile(CIFXHANDLE hChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
return xSysdeviceFindNextFile(hChannel, ptChannel->ulChannelNumber, ptDirectoryInfo, pfnRecvPktCallback, pvUser);
}
/*****************************************************************************/
/*! Starts directory enumeration on the given channel
* \param hSysdevice Handle to the system device
* \param ulChannel Channel number to get directory from
* \param ptDirectoryInfo Pointer to enumeration result.
* (Will be initialized inside function)
* \param pfnRecvPktCallback Callback for unhandled packets
* \param pvUser User data for callback function
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceFindFirstFile(CIFXHANDLE hSysdevice, uint32_t ulChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hSysdevice;
union
{
CIFX_PACKET tPacket;
HIL_DIR_LIST_REQ_T tDirListReq;
} uSendPacket;
HIL_DIR_LIST_CNF_T tDirListCnf;
OS_Memset(&uSendPacket, 0, sizeof(uSendPacket));
OS_Memset(&tDirListCnf, 0, sizeof(tDirListCnf));
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
return CIFX_INVALID_HANDLE;
#endif
CHECK_POINTER(ptDirectoryInfo);
if(OS_Strlen(ptDirectoryInfo->szFilename) > 0)
{
uint16_t usDirNameLength = (uint16_t)(OS_Strlen(ptDirectoryInfo->szFilename) + 1);
uSendPacket.tDirListReq.tData.usDirNameLength = HOST_TO_LE16(usDirNameLength);
(void)OS_Strncpy( (char*)((&uSendPacket.tDirListReq.tData) + 1),
ptDirectoryInfo->szFilename,
usDirNameLength);
}
uSendPacket.tDirListReq.tHead.ulDest = HOST_TO_LE32(HIL_PACKET_DEST_SYSTEM);
uSendPacket.tDirListReq.tHead.ulSrc = HOST_TO_LE32(((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->ulPhysicalAddress);
uSendPacket.tDirListReq.tHead.ulCmd = HOST_TO_LE32(HIL_DIR_LIST_REQ);
uSendPacket.tDirListReq.tHead.ulLen = HOST_TO_LE32( ((uint32_t)sizeof(uSendPacket.tDirListReq.tData) +
uSendPacket.tDirListReq.tData.usDirNameLength) );
uSendPacket.tDirListReq.tData.ulChannelNo = HOST_TO_LE32(ulChannel);
lRet = DEV_TransferPacket(ptChannel,
&uSendPacket.tPacket,
(CIFX_PACKET*)&tDirListCnf,
sizeof(tDirListCnf),
CIFX_TO_SEND_PACKET,
pfnRecvPktCallback,
pvUser);
if( CIFX_NO_ERROR == lRet)
{
if( SUCCESS_HIL_OK == (lRet = LE32_TO_HOST(tDirListCnf.tHead.ulSta)) )
{
uint8_t* pbListEntry = (uint8_t*)&ptDirectoryInfo->hList;
if ((tDirListCnf.tHead.ulExt & HIL_PACKET_SEQ_MASK) == HIL_PACKET_SEQ_LAST)
{
/* this is the last packet */
lRet = CIFX_NO_MORE_ENTRIES;
/* invalidate handle */
*pbListEntry = 0;
} else
{
/* TODO: Store handle for directory list, which needs to be set by firmware */
*pbListEntry = 1;
(void)OS_Strncpy(ptDirectoryInfo->szFilename,
(const char*)tDirListCnf.tData.szName,
sizeof(ptDirectoryInfo->szFilename));
ptDirectoryInfo->bFiletype = tDirListCnf.tData.bFileType;
ptDirectoryInfo->ulFilesize = LE32_TO_HOST(tDirListCnf.tData.ulFileSize);
}
}
}
return lRet;
}
/*****************************************************************************/
/*! Enumerate next entry in directory on the given channel
* \param hSysdevice Handle to the system device
* \param ulChannel Channel number to get directory from
* \param ptDirectoryInfo Pointer to enumeration result
* \param pfnRecvPktCallback Callback for unhandled packets
* \param pvUser User data for callback function
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceFindNextFile(CIFXHANDLE hSysdevice, uint32_t ulChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hSysdevice;
union
{
CIFX_PACKET tPacket;
HIL_DIR_LIST_REQ_T tDirListReq;
} uSendPacket;
HIL_DIR_LIST_CNF_T tDirListCnf;
uint16_t usDirNameLen = 0;
OS_Memset(&uSendPacket, 0, sizeof(uSendPacket));
OS_Memset(&tDirListCnf, 0, sizeof(tDirListCnf));
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
return CIFX_INVALID_HANDLE;
#endif
CHECK_POINTER(ptDirectoryInfo);
usDirNameLen = (uint16_t)(OS_Strlen(ptDirectoryInfo->szFilename) + 1);
uSendPacket.tDirListReq.tData.usDirNameLength = HOST_TO_LE16(usDirNameLen);
(void)OS_Strncpy( (char*)((&uSendPacket.tDirListReq.tData) + 1),
ptDirectoryInfo->szFilename,
usDirNameLen);
uSendPacket.tDirListReq.tHead.ulDest = HOST_TO_LE32(HIL_PACKET_DEST_SYSTEM);
uSendPacket.tDirListReq.tHead.ulSrc = HOST_TO_LE32(((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->ulPhysicalAddress);
uSendPacket.tDirListReq.tHead.ulCmd = HOST_TO_LE32(HIL_DIR_LIST_REQ);
uSendPacket.tDirListReq.tHead.ulLen = HOST_TO_LE32( ((uint32_t)sizeof(uSendPacket.tDirListReq.tData) + usDirNameLen) );
uSendPacket.tDirListReq.tHead.ulExt = HOST_TO_LE32(HIL_PACKET_SEQ_MIDDLE);
uSendPacket.tDirListReq.tData.ulChannelNo = HOST_TO_LE32(ulChannel);
lRet = DEV_TransferPacket(ptChannel,
&uSendPacket.tPacket,
(CIFX_PACKET*)&tDirListCnf,
sizeof(tDirListCnf),
CIFX_TO_SEND_PACKET,
pfnRecvPktCallback,
pvUser);
if(CIFX_NO_ERROR == lRet)
{
if( SUCCESS_HIL_OK == (lRet = (LE32_TO_HOST(tDirListCnf.tHead.ulSta))) )
{
if(( LE32_TO_HOST(tDirListCnf.tHead.ulExt) & HIL_PACKET_SEQ_MASK) == HIL_PACKET_SEQ_LAST)
{
uint8_t* pbListEntry = (uint8_t*)&ptDirectoryInfo->hList;
/* invalidate handle */
*pbListEntry = 0;
/* this is the last packet */
lRet = CIFX_NO_MORE_ENTRIES;
} else
{
(void)OS_Strncpy(ptDirectoryInfo->szFilename,
(const char*)tDirListCnf.tData.szName,
sizeof(tDirListCnf.tData.szName));
ptDirectoryInfo->bFiletype = tDirListCnf.tData.bFileType;
ptDirectoryInfo->ulFilesize = LE32_TO_HOST(tDirListCnf.tData.ulFileSize);
}
}
}
return lRet;
}
/*****************************************************************************/
/*! Uploads a file via system channel
* \param hSysdevice Handle to the System device
* \param ulChannel Channel number to get directory from
* \param ulMode Transfer Mode
* \param pszFileName Filename to upload
* \param pabFileData Pointer to buffer receiving upload
* \param pulFileSize [in]Length of buffer, [out] Bytes copied to buffer
* \param pfnCallback Callback pointer for progress
* (NULL for no callback)
* \param pfnRecvPktCallback Callback pointer for unsolicited receive packets
* (NULL for no callback)
* \param pvUser User parameter on callback.
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xSysdeviceUpload(CIFXHANDLE hSysdevice, uint32_t ulChannel,
uint32_t ulMode, char* pszFileName, uint8_t* pabFileData, uint32_t* pulFileSize,
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
uint32_t ulTransferType = 0;
int32_t lRet = CIFX_NO_ERROR;
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
return CIFX_INVALID_HANDLE;
#endif
CHECK_POINTER(pszFileName);
CHECK_POINTER(pabFileData);
CHECK_POINTER(pulFileSize);
switch(ulMode)
{
case DOWNLOAD_MODE_FIRMWARE:
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptSysDevice->pvDeviceInstance))->eChipType,
pszFileName, &ulTransferType)))
return lRet;
break;
case DOWNLOAD_MODE_CONFIG:
case DOWNLOAD_MODE_FILE:
ulTransferType = HIL_FILE_XFER_FILE;
break;
default:
return CIFX_INVALID_PARAMETER;
}
lRet = DEV_UploadFile(ptSysDevice,
ulChannel,
ptSysDevice->tRecvMbx.ulRecvMailboxLength,
ulTransferType,
pszFileName,
pulFileSize,
pabFileData,
DEV_TransferPacket,
pfnCallback,
pfnRecvPktCallback,
pvUser);
return lRet;
}
/*****************************************************************************/
/*! Uploads a file via Communication channel
* \param hChannel Handle to the Channel
* \param ulMode Transfer Mode
* \param pszFileName Filename to upload
* \param pabFileData Pointer to buffer receiving upload
* \param pulFileSize [in]Length of buffer, [out] Bytes copied to buffer
* \param pfnCallback Callback pointer for progress
* (NULL for no callback)
* \param pfnRecvPktCallback Callback pointer for unsolicited receive packets
* (NULL for no callback)
* \param pvUser User parameter on callback.
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelUpload(CIFXHANDLE hChannel, uint32_t ulMode,
char* pszFileName, uint8_t* pabFileData, uint32_t* pulFileSize,
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
{
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
return xSysdeviceUpload(hChannel,
ptChannel->ulChannelNumber,
ulMode,
pszFileName,
pabFileData,
pulFileSize,
pfnCallback,
pfnRecvPktCallback,
pvUser);
}
/*****************************************************************************/
/*! Set DMA state of a communication channel
* \param hChannel Channel handle
* \param ulCmd Command CIFX_DMA_STATE_xxx
* \param pulState Return actual state on CIFX_GET_DMA_STATE
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelDMAState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState)
{
#ifdef CIFX_TOOLKIT_DMA
int32_t lRet = CIFX_INVALID_PARAMETER;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
PDEVICEINSTANCE ptDevInstance = NULL;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pulState);
ptDevInstance = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
/* Only possible on PCI devices */
if( !ptDevInstance->fPCICard)
return CIFX_FUNCTION_NOT_AVAILABLE;
/* Only possible if user provided DMA buffers */
if(0 == ptDevInstance->ulDMABufferCount)
return CIFX_DEV_DMA_INSUFF_BUFFER_COUNT;
/* Check if firmware supports DMA functions */
/*TODO: Check this */
/*if( !ptChannel->ptCommonStatusBlock->ulCommunicationCOS->fPCICard) */
/* return CIFX_FUNCTION_NOT_AVAILABLE; */
lRet = DEV_DMAState( (PCHANNELINSTANCE)hChannel,
ulCmd,
pulState);
return lRet;
#else
UNREFERENCED_PARAMETER(hChannel);
UNREFERENCED_PARAMETER(ulCmd);
UNREFERENCED_PARAMETER(pulState);
return CIFX_FUNCTION_NOT_AVAILABLE; /*lint !e438 : unused variables */
#endif
}
/*****************************************************************************/
/*! Register a callback notification
* \param hChannel Handle to the Channel
* \param ulNotification Notification
* \param pfnCallback Callback function
* \param pvUser User data pointer
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelRegisterNotification(CIFXHANDLE hChannel,
uint32_t ulNotification,
PFN_NOTIFY_CALLBACK pfnCallback,
void* pvUser)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
PDEVICEINSTANCE ptDevInst = NULL;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pfnCallback);
ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
if(!ptDevInst->fIrqEnabled)
return CIFX_INTERRUPT_DISABLED;
switch (ulNotification)
{
case CIFX_NOTIFY_RX_MBX_FULL:
/* Check if already registered */
if( NULL != ptChannel->tRecvMbx.pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
ptChannel->tRecvMbx.pvUser = pvUser;
ptChannel->tRecvMbx.pfnCallback = pfnCallback;
if(DEV_WaitForBitState(ptChannel,
ptChannel->tRecvMbx.bRecvACKBitoffset,
HIL_FLAGS_NOT_EQUAL,
0))
{
CIFX_NOTIFY_RX_MBX_FULL_DATA_T tData;
tData.ulRecvCount = LE16_TO_HOST(HWIF_READ16(ptDevInst, ptChannel->tRecvMbx.ptRecvMailboxStart->usWaitingPackages));
pfnCallback(CIFX_NOTIFY_RX_MBX_FULL, sizeof(tData), &tData, pvUser);
}
}
break;
case CIFX_NOTIFY_TX_MBX_EMPTY:
/* Check if already registered */
if( NULL != ptChannel->tSendMbx.pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
ptChannel->tSendMbx.pvUser = pvUser;
ptChannel->tSendMbx.pfnCallback = pfnCallback;
if(DEV_WaitForBitState(ptChannel,
ptChannel->tSendMbx.bSendCMDBitoffset,
HIL_FLAGS_EQUAL,
0))
{
CIFX_NOTIFY_TX_MBX_EMPTY_DATA_T tData;
tData.ulMaxSendCount = LE16_TO_HOST(HWIF_READ16(ptDevInst, ptChannel->tSendMbx.ptSendMailboxStart->usPackagesAccepted));
pfnCallback(CIFX_NOTIFY_TX_MBX_EMPTY, sizeof(tData), &tData, pvUser);
}
}
break;
case CIFX_NOTIFY_PD0_IN:
case CIFX_NOTIFY_PD0_OUT:
{
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[0];
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
if( CIFX_NOTIFY_PD0_OUT == ulNotification)
{
ptIOArea = ptChannel->pptIOOutputAreas[0];
ulAreaCount = ptChannel->ulIOOutputAreas;
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
}
/* Check if we have one input area */
if( 0 == ulAreaCount)
{
/* No input area */
lRet = CIFX_INVALID_PARAMETER;
} else if( NULL != ptIOArea->pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
/* Add the callback */
ptIOArea->pvUser = pvUser;
ptIOArea->pfnCallback = pfnCallback;
if(DEV_WaitForBitState(ptChannel,
ptIOArea->bHandshakeBit,
bIOBitState,
0))
{
pfnCallback(ulNotification, 0, NULL, pvUser);
}
lRet = CIFX_NO_ERROR;
}
}
break;
case CIFX_NOTIFY_PD1_IN:
case CIFX_NOTIFY_PD1_OUT:
{
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[1];
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
if( CIFX_NOTIFY_PD1_OUT == ulNotification)
{
ptIOArea = ptChannel->pptIOOutputAreas[1];
ulAreaCount = ptChannel->ulIOOutputAreas;
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
}
/* Check if we have two input areas */
if( 1 <= ulAreaCount)
{
/* No input area */
lRet = CIFX_INVALID_PARAMETER;
} else if( NULL != ptIOArea->pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
/* Add the callback */
ptIOArea->pvUser = pvUser;
ptIOArea->pfnCallback = pfnCallback;
if(DEV_WaitForBitState(ptChannel,
ptIOArea->bHandshakeBit,
bIOBitState,
0))
{
pfnCallback(ulNotification, 0, NULL, pvUser);
}
}
}
break;
case CIFX_NOTIFY_SYNC:
if( NULL != ptChannel->tSynch.pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
/* Add the callback */
uint8_t bState = HIL_FLAGS_NOT_EQUAL;
ptChannel->tSynch.pvUser = pvUser;
ptChannel->tSynch.pfnCallback = pfnCallback;
/* Add callback for sync on startup */
if( HIL_SYNC_MODE_HST_CTRL == HWIF_READ8(ptDevInst, ptChannel->ptCommonStatusBlock->bSyncHskMode))
bState = HIL_FLAGS_EQUAL;
if(DEV_WaitForSyncState(ptChannel,
bState,
0))
{
pfnCallback(ulNotification, 0, NULL, pvUser);
}
}
break;
case CIFX_NOTIFY_COM_STATE:
/* Check if already registered */
if( NULL != ptChannel->tComState.pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_ALREADY_USED;
} else
{
CIFX_NOTIFY_COM_STATE_T tData;
ptChannel->tComState.pvUser = pvUser;
ptChannel->tComState.pfnCallback = pfnCallback;
/* Just update the actual flag state by reading it once */
(void)DEV_WaitForBitState(ptChannel,
NCF_COMMUNICATING_BIT_NO,
HIL_FLAGS_SET,
0);
tData.ulComState = ptChannel->usNetxFlags & NCF_COMMUNICATING;
pfnCallback(CIFX_NOTIFY_COM_STATE, sizeof(tData), &tData, pvUser);
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Unregister a callback notification
* \param hChannel Handle to the Channel
* \param ulNotification Notification
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelUnregisterNotification( CIFXHANDLE hChannel,
uint32_t ulNotification)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
switch (ulNotification)
{
case CIFX_NOTIFY_RX_MBX_FULL:
/* Check if already registered */
if( NULL == ptChannel->tRecvMbx.pfnCallback)
{
/* Not registered */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
ptChannel->tRecvMbx.pfnCallback = NULL;
}
break;
case CIFX_NOTIFY_TX_MBX_EMPTY:
/* Check if already registered */
if( NULL == ptChannel->tSendMbx.pfnCallback)
{
/* Already registered */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
ptChannel->tSendMbx.pfnCallback = NULL;
}
break;
case CIFX_NOTIFY_PD0_IN:
case CIFX_NOTIFY_PD0_OUT:
{
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[0];
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
if( CIFX_NOTIFY_PD0_OUT == ulNotification)
{
ptIOArea = ptChannel->pptIOOutputAreas[0];
ulAreaCount = ptChannel->ulIOOutputAreas;
}
/* Check if we have one input area */
if( 0 == ulAreaCount)
{
/* No input area */
lRet = CIFX_INVALID_PARAMETER;
} else if( NULL == ptIOArea->pfnCallback)
{
/* Not registered before */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
/* Add the callback */
ptIOArea->pfnCallback = NULL;
ptIOArea->pvUser = NULL;
lRet = CIFX_NO_ERROR;
}
}
break;
case CIFX_NOTIFY_PD1_IN:
case CIFX_NOTIFY_PD1_OUT:
{
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[1];
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
if( CIFX_NOTIFY_PD1_OUT == ulNotification)
{
ptIOArea = ptChannel->pptIOOutputAreas[1];
ulAreaCount = ptChannel->ulIOOutputAreas;
}
/* Check if we have two input areas */
if( 1 <= ulAreaCount)
{
/* No input area */
lRet = CIFX_INVALID_PARAMETER;
} else if( NULL == ptIOArea->pfnCallback)
{
/* Not registered before */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
/* Add the callback */
ptIOArea->pfnCallback = NULL;
ptIOArea->pvUser = NULL;
}
}
break;
case CIFX_NOTIFY_SYNC:
if( NULL == ptChannel->tSynch.pfnCallback)
{
/* Not registered before */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
/* Add the callback */
ptChannel->tSynch.pfnCallback = NULL;
ptChannel->tSynch.pvUser = NULL;
}
break;
case CIFX_NOTIFY_COM_STATE:
if( NULL == ptChannel->tComState.pfnCallback)
{
/* Not registered before */
lRet = CIFX_CALLBACK_NOT_REGISTERED;
} else
{
/* delete the callback */
ptChannel->tComState.pfnCallback = NULL;
ptChannel->tComState.pvUser = NULL;
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
}
return lRet;
}
/*****************************************************************************/
/*! Signal a sync state, either a sync command or acknowledge
* \param hChannel Handle to the Channel
* \param ulCmd Sync command
* \param ulTimeout Timeout to wait for sync / sync signalling
* \param pulErrorCount Actual sync error counter
* \return CIFX_NO_ERROR on success */
/*****************************************************************************/
int32_t APIENTRY xChannelSyncState( CIFXHANDLE hChannel,
uint32_t ulCmd,
uint32_t ulTimeout,
uint32_t* pulErrorCount)
{
int32_t lRet = CIFX_NO_ERROR;
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
CHECK_CHANNELHANDLE(hChannel);
CHECK_POINTER(pulErrorCount);
/* Check if device installed and active */
if(ptChannel->ulOpenCount == 0)
{
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
} else
{
switch (ulCmd)
{
case CIFX_SYNC_SIGNAL_CMD:
/* Check if SYNC mode is host controlled */
if(HIL_SYNC_MODE_HST_CTRL != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
{
/* Invalid Device mode */
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
} else if(!DEV_WaitForSyncState(ptChannel, HIL_FLAGS_EQUAL, ulTimeout))
{
/* Sync cannot be signalled as bits are in wrong state */
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
} else
{
/* Signal new sync */
DEV_ToggleSyncBit( (PDEVICEINSTANCE)ptChannel->pvDeviceInstance, (1 << ptChannel->ulChannelNumber));
/* Return actual error counter */
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
/* Check if the device is communication */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
break;
case CIFX_SYNC_ACKNOWLEDGE_CMD:
/* Check if SYNC mode is device controlled */
if(HIL_SYNC_MODE_DEV_CTRL != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
{
/* Invalid Device mode */
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
} else if(!DEV_WaitForSyncState(ptChannel, HIL_FLAGS_NOT_EQUAL, ulTimeout))
{
/* Sync cannot be signalled as bits are in wrong state */
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
} else
{
/* Acknowledge an device sys */
DEV_ToggleSyncBit( (PDEVICEINSTANCE)ptChannel->pvDeviceInstance, (1 << ptChannel->ulChannelNumber));
/* Return actual error counter */
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
/* Check if the device is communication */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
break;
case CIFX_SYNC_WAIT_CMD:
{
if( (HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode) != HIL_SYNC_MODE_HST_CTRL) &&
(HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode) != HIL_SYNC_MODE_DEV_CTRL) )
{
/* Invalid Device mode */
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
} else
{
uint8_t bState = HIL_FLAGS_NOT_EQUAL;
if( HIL_SYNC_MODE_HST_CTRL == HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
bState = HIL_FLAGS_EQUAL;
/* Wait for sync */
if(!DEV_WaitForSyncState(ptChannel, bState, ulTimeout))
{
/* Sync timeout */
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
} else
{
/* Return actual error counter */
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
/* Check if the device is communication */
(void)DEV_IsCommunicating(ptChannel, &lRet);
}
}
}
break;
default:
lRet = CIFX_INVALID_COMMAND;
break;
}
}
return lRet;
}
/*****************************************************************************/
/*! \} */
/*****************************************************************************/