/**
 * \brief IQI's IO-Link Master control interface
 * \copyright 2013-2014, IQ² Development GmbH, Neckartenzlingen. All rights reserved.
 */

#ifndef _iqi_mst_h
#define _iqi_mst_h

#include "iqi_define.h"

#define MST_SET_OPERATING_MODE_TIMEOUT     10                                   // 10 sec
#define MST_SET_PDOUT_VALUE_TIMEOUT        2                                    // 2 sec
#define MST_SET_PDOUT_VALIDITY_TIMEOUT     2                                    // 2 sec
#define MST_OD_TIMEOUT                     5                                    // 5 sec
#define MST_READ_FD_TIMEOUT                2                                    // 2 sec
#define MST_EVENT_TIMEOUT                  1                                    // 1 sec

#define MST_DEV_SER_NUM_MAX_LEN 16

typedef enum
{
  MST_OPERATING_MODE_INACTIVE   = 0,
  MST_OPERATING_MODE_AUTO       = 3,
  MST_OPERATING_MODE_PREOPERATE = 4,
  MST_OPERATING_MODE_OPERATE    = 5
} mst_OperModeT;

typedef enum
{
  MST_STATE_INACTIVE    = 0,
  MST_STATE_CHK_FAULT   = 3,
  MST_STATE_PREOPERATE  = 4,
  MST_STATE_OPERATE     = 5
} mst_StateT;

typedef struct
{
  uchar08    State        : 3;  // 0 - 2 bits, current master state
  uchar08    PDOutInvalid : 1;  // 3 bit, pd out invalidity flag
  uchar08    PDInInvalid  : 1;  // 4 bit, pd in invalidity flag
  uchar08    Event        : 1;  // 5 bit, flag of not read event pending
  uchar08    OD           : 1;  // 6 bit, flag of ISDU operation in progress
  uchar08    PDOutSet     : 1;  // 7 bit, flag of pd out setting in progress
} mst_StatusT;

typedef enum
{
  MST_IL_NO_CHECK = 0,
  MST_IL_TYPE_COMP = 1,
  MST_IL_IDENTICAL = 2
} mst_InspectionLevelT;

typedef enum
{
  MST_DS_ACTIV_STATE_ENABLED = 0,
  MST_DS_ACTIV_STATE_DISABLED = 1,
  MST_DS_ACTIV_STATE_CLEARED = 2
} mst_DSActivStateT;

typedef struct
{
  // readonly version of master iqStack
  uint16 stackVersion;

  // system manager
  uint16 cycleTimeOperate;                                 // 0 - auto, less than MAX_CYCLE_TIME, in ms: cycleTimeOperate/10
  uint16 restOfCycleTimeOperate;                           // matters if cycleTimeOperate != 0, 
                                                           // 0 - auto, less than MAX_CYCLE_TIME, in ms: restOfCycleTimeOperate/10 
  
  IOLRevisionIDT revisionID;
  mst_InspectionLevelT inspectionLevel;
  uint16 deviceVendorID;
  ulong32 deviceID;                                        // 3 LSB bytes
  uint16 deviceFunctionID;
  uchar08 deviceSerialNumber[MST_DEV_SER_NUM_MAX_LEN + 1];
  uchar08 deviceSerialNumberLen;

  // readonly real current (or last successful) connection
  IOLBaudrateT realBaudrate;

  // data storage
  mst_DSActivStateT dsActivState;
  boolean dsUploadEnable;
  boolean dsDownloadEnable;

} mst_ConfigT;

/**
 * \brief Get current DLL version
 *
 * \param[in]   p_major        pointer to output parameter: major version
 * \param[in]   p_minor        pointer to output parameter: minor version
 * \param[out]  cpErrMsg            an error message (minimum 256 symbols!)
 *
 * \return operation result
 */
DLL_API
int16 mst_GetVersion(uint16* p_major, uint16* p_minor, char08 *cpErrMsg);

/**
 * \brief Try to connect to iqInterface as IO-Link Master on ports range
 *
 * \param[in]   ucFromPortNo        com port number search from
 * \param[in]   ucUntilPortNo       com port number until search
 * \param[out]  cpErrMsg            an error message (minimum 256 symbols!)
 *
 * \return the first successfully found IQI's comport number
 */
DLL_API
int16 mst_Connect(uchar08 ucFromPortNo,
                  uchar08 ucUntilPortNo,
                  char08 *cpErrMsg);

/**
 * \brief Try to connect to iqInterface as IO-Link Master over TCP/IPv4/ethernet
 *
 * \param[in]   connection         TCP connection info, used only cpIqInterfaceIpAddr and uiPort
 * \param[in]   uiSendRecvTimoutMs TCP send/receive timout
 * \param[out]  cpErrMsg           an error message (minimum 256 symbols!)
 *
 * \return virtual port (TCP handle) of successfully connected IQI 
 *         to use in other functions or error
 */
DLL_API
int16 mst_EthernetConnect(enet_ConnectionT * connection,
                          uint16 uiSendRecvTimoutMs, 
                          char08 *cpErrMsg);

/**
 * \brief Disconnect iqInterface as IO-Link Master
 *
 * \param[in]   uiPortNo COM or virtual ethernet port number of iqInterface
 * \param[out]  cpErrMsg an error message (minimum 256 symbols!)
 *
 */
DLL_API
int16 mst_Disconnect(uint16 uiPortNo,
                     char08 *cpErrMsg);

/**
 * \brief Write to iqInterface its IO-Link Master configuration
 *
 * \param[in]   uiPortNo COM or virtual ethernet port number of iqInterface
 * \param[in]   pConfig  IO-Link Master configuration
 * \param[out]  cpErrMsg an error message (minimum 256 symbols!)
 *
 */
DLL_API
int16 mst_SetConfig(uint16 uiPortNo,
                    mst_ConfigT *pConfig,
                    char08 *cpErrMsg);

/**
 * \brief Read from iqInterface its IO-Link Master configuration
 *
 * \param[in]   uiPortNo COM or virtual ethernet port number of iqInterface
 * \param[out]  pConfig  IO-Link Master configuration
 * \param[out]  cpErrMsg an error message (minimum 256 symbols!)
 *
 */
DLL_API
int16 mst_GetConfig(uint16 uiPortNo,
                    mst_ConfigT *pConfig,
                    char08 *cpErrMsg);

/**
 * \brief Connected IO-Link device power supply control
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   ucSwitch		on/off power supply switch flag (0 - off / disable, 1 - on / enable)
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_PowerControl(uint16 uiPortNo,
                       uchar08 ucSwitch,
					   char08 *cpErrMsg);

/**
 * \brief Get IQI's status and PD, if available
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  pStatus         a pointer to an IQI's status
 * \param[out]  ucpPDInBuf      a PD buffer
 * \param[in]   uiPDInBufSize   a PD buffer size
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 *
 * \return the actual size of readed PD data bytes
 */
DLL_API
int16 mst_GetStatus(uint16 uiPortNo,
                    uchar08 *pStatus,
                    uchar08 *ucpPDInBuf,
                    uint16 uiPDInBufSize,
                    char08 *cpErrMsg);

/**
 * \brief Switch to a required operating mode
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   ucOperMode      a required operating mode
 * \param[in]   ucStateToWait   ucOperMode is considered to be set,
                                when state has changed to ucStateToWait before timeout.
 * \param[out]  ucpState        a pointer to an achieved IQI's state
 *                              or NULL just to send command and not to wait ucStateToWait
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_SetOperatingMode(uint16 uiPortNo,
                           uchar08 ucOperMode,
                           uchar08 ucStateToWait,
                           uchar08 *ucpState,
                           char08 *cpErrMsg);

/**
 * \brief Set process data output
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   ucpPDOutBuf     process data output buffer
 * \param[in]   uiBytesCount    a count of bytes to send
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_SetPDValue(uint16 uiPortNo,
                     uchar08 *ucpPDOutBuf,
                     uint16 uiBytesCount,
                     char08 *cpErrMsg);

/**
 * \brief Set a validity flag for process data output
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   ucValidity      a required validity flag, TRUE - valid, FALSE - invalid
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_SetPDValidity(uint16 uiPortNo,
                        boolean bValidity,
                        char08 *cpErrMsg);

/**
 * \brief Waits ISDU response from device
 * 
 * This function waits ISDU response from device with timeout MST_OD_TIMEOUT
 * after sending ISDU request with mst_StartReadOD() or mst_StartWriteOD().
 * 
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_WaitODRsp(uint16 uiPortNo, char08 *cpErrMsg);

/**
 * \brief Starts asynchronous ISDU read request
 *
 * Device response can be waited for by mst_WaitODRsp() and
 * read by mst_GetReadODRsp().
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   uiIndex         an IO-Link parameter index
 * \param[in]   ucSubindex      an IO-Link parameter sub-index
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_StartReadOD(uint16 uiPortNo,
                      uint16 uiIndex,
                      uchar08 ucSubindex,
                      char08 *cpErrMsg);

/**
 * \brief Reads ISDU read response from device
 *
 * Reads ISDU read response from device started by mst_StartReadOD() and waited by mst_WaitODRsp()
 * 
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  ucpBuf          a data buffer
 * \param[in]   uiBufSize       a data buffer size
 * \param[out]  uipISDUErr      a pointer to store an ISDU error code
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 *
 * \return the actual size of readed ISDU data bytes
 */
DLL_API
int16 mst_GetReadODRsp(uint16 uiPortNo, 
                       uchar08 *ucpBuf, 
                       uint16 uiBufSize, 
                       uint16* uipISDUErr, 
                       char08 *cpErrMsg);

/**
 * \brief Read on-request data
 *
 * Short hand for mst_StartReadOD() + mst_WaitODRsp() + mst_GetReadODRsp()
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   uiIndex         an IO-Link parameter index
 * \param[in]   ucSubindex      an IO-Link parameter sub-index
 * \param[out]  ucpBuf          a data buffer
 * \param[in]   uiBufSize       a data buffer size
 * \param[out]  uipISDUErr      a pointer to store an ISDU error code
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 *
 * \return the actual size of readed on-request data bytes
 */
DLL_API
int16 mst_ReadOD(uint16 uiPortNo,
                 uint16 uiIndex,
                 uchar08 ucSubindex,
                 uchar08 *ucpBuf,
                 uint16 uiBufSize,
                 uint16* uipISDUErr,
                 char08 *cpErrMsg);

/**
 * \brief Starts asynchronous ISDU write request
 *
 * Device response can be waited for by mst_WaitODRsp() and
 * read by mst_GetWriteODRsp().
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   uiIndex         an IO-Link parameter index
 * \param[in]   ucSubindex      an IO-Link parameter sub-index
 * \param[in]   ucpBuf          a data buffer
 * \param[in]   ucBytesCount    a count of bytes to send
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_StartWriteOD(uint16 uiPortNo,
                       uint16 uiIndex,
                       uchar08 ucSubindex,
                       uchar08 *ucpBuf,
                       uint16 uiBytesCount,
                       char08 *cpErrMsg);

/**
 * \brief Reads ISDU write response from device
 *
 * Reads ISDU write response from device started by mst_StartWriteOD and waited by mst_WaitODRsp()
 * 
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  uipISDUErr      a pointer to store an ISDU error code
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_GetWriteODRsp(uint16 uiPortNo, uint16* uipISDUErr, char08 *cpErrMsg);

/**
 * \brief Write on-request data
 *
 * Short hand for mst_StartWriteOD() + mst_WaitODRsp() + mst_GetWriteODRsp()
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[in]   uiIndex         an IO-Link parameter index
 * \param[in]   ucSubindex      an IO-Link parameter sub-index
 * \param[in]   ucpBuf          a data buffer
 * \param[in]   ucBytesCount    a count of bytes to send
 * \param[out]  uipISDUErr      a pointer to store an ISDU error code
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_WriteOD(uint16 uiPortNo,
                  uint16 uiIndex,
                  uchar08 ucSubindex,
                  uchar08 *ucpBuf,
                  uint16 uiBytesCount,
                  uint16* uipISDUErr,
                  char08 *cpErrMsg);

/**
 * \brief Wait event from device within timeout MST_EVENT_TIMEOUT
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  ucpQualifier    pointer to event qualifier
 * \param[out]  uipCode         pointer to event code
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_ReadEvent(uint16 uiPortNo,
                    uchar08 *ucpQualifier,
                    uint16 *uipCode,
                    char08 *cpErrMsg);

/**
 * \brief Reset device parameters to default
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_ResetParameters2Default(uint16 uiPortNo, char08 *cpErrMsg);

/**
 * \brief Reboot device
 *
 * \param[in]   uiPortNo        COM or virtual ethernet port number of iqInterface
 * \param[out]  cpErrMsg        an error message (minimum 256 symbols!)
 */
DLL_API
int16 mst_Reboot(uint16 uiPortNo, char08 *cpErrMsg);

#endif
