/**
 * \brief IQI's direct mode via RS232
 * \copyright 2013-2014, IQ² Development GmbH, Neckartenzlingen. All rights reserved.
 */

#include "iqi_define.h"
#include "iqi_rs232.h"
#include "iqi_ethernet.h"
#include "iqi_ethernet_internal.h"
#include "iqi_comm.h"
#include "iqi_dm.h"


typedef int16 (*SendRecvFuncT)(uint16 uiPortNo,
                               uchar08 *ucpBuf,
                               ulong32 ulBytesCount,
                               char08 *cpErrMsg);

static void _SetSendRecv(uint16 uiPortNo, SendRecvFuncT *send, SendRecvFuncT *recv)
{
  *send = uiPortNo < MAX_COMPORT_NUM ? rs232_Write : enet_Send;
  *recv = uiPortNo < MAX_COMPORT_NUM ? rs232_Read : enet_Recv;
}

DLL_API
int16 dm_Start(uint16 uiPortNo,
			   uchar08 ucSpeed,
	           char08 *cpErrMsg)
{
  uchar08 ucIQIOperMode = IQMODE_DIRECT_MODE;

  if (ucSpeed >= DM_SPEED_END)
  {
    snprintf(cpErrMsg, MAX_ERR_STR_LEN, MAX_ERR_STR_LEN,
      "IQI wrong direct mode speed parameter ('%d', more than maximal '%d').", ucSpeed, DM_SPEED_END - 1);

    return ERR_PARAMETER;
  }

  CHK_RETURN(comm_WriteParameter(uiPortNo, IQParFDSpeed, &ucSpeed, 1, cpErrMsg));

  return comm_WriteParameter(uiPortNo, IQParIQIOperMode, &ucIQIOperMode, 1, cpErrMsg);
}


DLL_API
int16 dm_Stop(uint16 uiPortNo,
              char08 *cpErrMsg)
{
  SendRecvFuncT send, _recv;

  uchar08 ucpEndSeq[] = { 0x00, 0x56 };

  _SetSendRecv(uiPortNo, &send, &_recv);

  return send(uiPortNo, ucpEndSeq, 2, cpErrMsg);
}

DLL_API
int16 dm_SendRecv(uint16 uiPortNo,
	              uchar08 *ucpSendBuf,
				  uchar08 ucBytesCount,
				  uchar08 *ucpRecvBuf,
				  uint16 uiBufSize,
				  char08 *cpErrMsg)
{
  int i;

  uchar08 ucSize, ucpBuf[16];
  SendRecvFuncT send, recv;

  _SetSendRecv(uiPortNo, &send, &recv);

  CHK_RETURN(send(uiPortNo, &ucBytesCount, 1, cpErrMsg));
  CHK_RETURN(send(uiPortNo, ucpSendBuf, ucBytesCount, cpErrMsg));

  CHK_RETURN(recv(uiPortNo, &ucSize, 1, cpErrMsg));
  
  if (ucSize > uiBufSize)
  {
	for (i = 0; i < ucSize >> 4; i++)
	{
		CHK_RETURN(recv(uiPortNo, ucpBuf, 16, cpErrMsg));
    }
    
	CHK_RETURN(recv(uiPortNo, ucpBuf, ucSize % 16, cpErrMsg));

    snprintf(cpErrMsg, MAX_ERR_STR_LEN, MAX_ERR_STR_LEN,
      "Too small receive buffer depth ('%d', but '%d' is needed).", uiBufSize, ucSize);

    return ERR_BUFFER_OVERFLOW;
  }

  CHK_RETURN(recv(uiPortNo, ucpRecvBuf, ucSize, cpErrMsg));
  
  return ucSize;
}
