/*****************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/


// Adapter.cpp: implementation of the CAdapter class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Adapter.h"

#include "eqm.h"
#include "DxbShim.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAdapter::CAdapter()
{
   m_strDevice.Empty();
   m_hDevice = NULL;
   m_hStream = NULL;
   m_eSamplingState = SS_INACTIVE;
}

CAdapter::~CAdapter()
{
   CleanUp();
}

void CAdapter::CleanUp()
{
   if (m_hStream != NULL)
   {
      CloseStream();
   }

   if (m_hDevice != NULL)
   {
      TRACE("Closing the adapter\n");
      DxbDeviceClose(m_hDevice);
      m_hDevice = NULL;
   }

   m_strDevice.Empty();
}

BOOL CAdapter::Attach(CString const & strBoard)
{
   BOOL fSuccess = FALSE;

   ASSERT(!strBoard.IsEmpty());

   TRACE("Attaching to %s\n", strBoard);

   // clean up any old stuff if this isn't the 1st Attach
   CleanUp();

   m_strDevice = strBoard;

   SHIM_STATUS eShimStatus = DxbDeviceOpen(m_strDevice, &m_hDevice);
   TRACE("DxbDeviceOpen() returned %d\n", eShimStatus);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      ASSERT(m_hDevice != NULL);
      fSuccess = TRUE;
   }

   return fSuccess;
}

BOOL CAdapter::OpenStream(int const eStreamType /* = STREAM_EQM */)
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream == NULL);
   ASSERT(eStreamType == STREAM_EQM);

   ASSERT(m_eSamplingState == SS_INACTIVE);

   LONG dwError = 0;
   SHIM_STATUS eShimStatus = DxbStreamOpen(m_hDevice, EQM_NAME, &m_hStream, &dwError, 250, NULL, NULL);
   TRACE("DxbStreamOpen() returned %d with error code %d\n", eShimStatus, dwError);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      ASSERT(m_hStream != NULL);
      fSuccess = TRUE;
   }

   fSuccess = TRUE;

   return fSuccess;
}

BOOL CAdapter::CloseStream()
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   TRACE("Closing down the stream\n");

   if ((m_eSamplingState == SS_SAMPLING) || (m_eSamplingState == SS_PAUSED))
      StopSampling();

   ASSERT(m_eSamplingState == SS_INACTIVE);

   DxbStreamPurge(m_hDevice, m_hStream, PURGE_ALL, 250, NULL, NULL);
   DxbStreamClose(m_hDevice, m_hStream, 250, NULL, NULL);

   m_hStream = NULL;

   fSuccess = TRUE;

   return fSuccess;
}

BOOL CAdapter::StartSampling(int const nChannel, int const nRate /* = 100 */)
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_INACTIVE);

   TRACE("Start sampling channel %d at %dHz\n", nChannel, nRate);

   static const char * const EQM_STREAM_START_FMT = "eqm binary %d %d 0";
   char EQM_STREAM_START_MSG[64];

   sprintf(EQM_STREAM_START_MSG, EQM_STREAM_START_FMT, nChannel, nRate);

   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hDevice, m_hStream, NULL, 0,
                                             EQM_STREAM_START_MSG, strlen(EQM_STREAM_START_MSG),
                                             MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("DxbStreamPutMsg() returned %d\n", eShimStatus);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      m_eSamplingState = SS_SAMPLING;
      fSuccess = TRUE;
   }

   return fSuccess;
}

BOOL CAdapter::PauseSampling()
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_SAMPLING);

   static const char * const EQM_STREAM_PAUSE_MSG = "pause 0";
   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hDevice, m_hStream, NULL, 0,
                                             EQM_STREAM_PAUSE_MSG, strlen(EQM_STREAM_PAUSE_MSG),
                                             MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("DxbStreamPutMsg() returned %d\n", eShimStatus);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      m_eSamplingState = SS_PAUSED;
      fSuccess = TRUE;
   }

   return fSuccess;
}

BOOL CAdapter::ResumeSampling()
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_PAUSED);

   static const char * const EQM_STREAM_RESUME_MSG = "pause 1";
   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hDevice, m_hStream, NULL, 0,
                                             EQM_STREAM_RESUME_MSG, strlen(EQM_STREAM_RESUME_MSG),
                                             MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("DxbStreamPutMsg() returned %d\n", eShimStatus);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      m_eSamplingState = SS_SAMPLING;
      fSuccess = TRUE;
   }

   return fSuccess;
}

BOOL CAdapter::StopSampling()
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT((m_eSamplingState == SS_SAMPLING) || (m_eSamplingState == SS_PAUSED));

   static const char * const EQM_STREAM_STOP_MSG = "stop";
   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hDevice, m_hStream, NULL, 0,
                                             EQM_STREAM_STOP_MSG, strlen(EQM_STREAM_STOP_MSG),
                                             MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("DxbStreamPutMsg() returned %d\n", eShimStatus);
   ASSERT(eShimStatus == SHIM_STATUS_SUCCESS);
   if (eShimStatus == SHIM_STATUS_SUCCESS)
   {
      m_eSamplingState = SS_INACTIVE;
      fSuccess = TRUE;
   }

   return fSuccess;
}

BOOL CAdapter::GetSamples(void * const pDataBuffer,
                          ULONG const DataMaxLength,
                          ULONG * const pDataLength,
                          DWORD const TimeoutMs,
                          HANDLE const hEvent,
                          SHIM_STATUS * const pStatus)
{
   BOOL fSuccess = FALSE;

   ASSERT(m_hDevice != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_SAMPLING);

   SHIM_STATUS eShimStatus = DxbStreamGetMsg(m_hDevice, m_hStream, NULL, 0, NULL,
						                           pDataBuffer, DataMaxLength, pDataLength,
						                           MSG_PRIORITY_LOW, TimeoutMs, hEvent, pStatus);

   TRACE("DxbStreamGetMsg() returned %d\n", eShimStatus);
   ASSERT((eShimStatus == SHIM_STATUS_SUCCESS) || (eShimStatus == SHIM_STATUS_PENDING_OPERATION));
   if ((eShimStatus == SHIM_STATUS_SUCCESS) || (eShimStatus == SHIM_STATUS_PENDING_OPERATION))
   {
      fSuccess = TRUE;
   }

   return fSuccess;
}
