/*****************************************************************************
* 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 "DxbShim.h"

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

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

CAdapter::CAdapter()
{
   m_fStereo = FALSE;
   m_strBoard.Empty();
   m_nBoard = -1;
   ZeroMemory(&m_Info, sizeof(m_Info));
   m_hBoard = NULL;
   m_hStream = NULL;
   m_eSamplingState = SS_INACTIVE;
}

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

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

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

   m_strBoard.Empty();
   m_nBoard = -1;
   ZeroMemory(&m_Info, sizeof(m_Info));
}

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

   TRACE("Attaching to %s\n", strBoard);
   ASSERT(!strBoard.IsEmpty());

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

   m_strBoard = strBoard;
   m_nBoard = cfgGetBoardNoFromName(m_strBoard);
   TRACE("Board #%d\n", m_nBoard);

   get_mgmt_board_info_request_t InfoReq;
   InfoReq.BoardNo = m_nBoard;

   DWORD eCmdStatus = MgmtCommand(m_nBoard, GET_MGMT_BOARD_INFO, &InfoReq, sizeof(InfoReq), &m_Info, sizeof(m_Info));
   TRACE("MgmtCommand() returned %d\n", eCmdStatus);
   ASSERT(eCmdStatus == MGMT_OK);
   if (eCmdStatus == MGMT_OK)
   {
      TRACE("Board Info:\n"
            "  BoardNo = %d\n"
            "  BrdId = %d\n"
            "  BoardType = %d\n"
            "  TotalChannels = %d\n"
            "  TotalPorts = %d\n",
            m_Info.BoardNo, m_Info.BrdId, m_Info.BoardType, m_Info.TotalChannels, m_Info.TotalPorts);

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

   return fSuccess;
}

BOOL CAdapter::OpenStream(CString const & strStream)
{
   BOOL fSuccess = FALSE;

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

   ASSERT((strStream == EQM_NAME) ||
          (strStream == AUDIOTAP_NAME));

   ASSERT(m_eSamplingState == SS_INACTIVE);

   m_strStream = strStream;
   TRACE("Opening %s stream\n", m_strStream);

   LONG dwError = 0;
   SHIM_STATUS eShimStatus = DxbStreamOpen(m_hBoard, m_strStream, &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;
   }

   return fSuccess;
}

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

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

   TRACE("Closing %s stream\n", m_strStream);

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

   ASSERT(m_eSamplingState == SS_INACTIVE);

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

   m_hStream = NULL;

   fSuccess = TRUE;

   return fSuccess;
}

BOOL CAdapter::StartSampling(int const nChannel)
{
   BOOL fSuccess = FALSE;

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

   ASSERT(m_eSamplingState == SS_INACTIVE);

   TRACE("Start sampling channel %d, stereo mode:%s\n", nChannel, m_fStereo ? "on" : "off");

   static const char * const EQM_STREAM_START_FMT = "eqm binary %d 200 0";

   static const char * const AUDIOTAP_STREAM_START_FMT = "linear %d 0x4000 0x4000 0";

   static const char * const AUDIOTAP_STREAM_START_STEREO_FMT = "linear %d 0 0 0";

   const char * STREAM_START_FMT = NULL;

   if (m_strStream == EQM_NAME)
   {
      STREAM_START_FMT = EQM_STREAM_START_FMT;
   }
   else if (m_strStream == AUDIOTAP_NAME)
   {
      if (m_fStereo)
      {
         STREAM_START_FMT = AUDIOTAP_STREAM_START_STEREO_FMT;
      }
      else
      {
         STREAM_START_FMT = AUDIOTAP_STREAM_START_FMT;
      }
   }
   else
   {
      ASSERT(FALSE);
   }

   char BUF[128];
   sprintf(BUF, STREAM_START_FMT, nChannel);
   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hBoard, m_hStream, NULL, 0, BUF, strlen(BUF), MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("CAdapter::StartSampling():DxbStreamPutMsg() returned %d for command %s\n", eShimStatus, BUF);
   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_hBoard != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_SAMPLING);

   static const char * const STREAM_PAUSE_MSG = "pause 0";
   char BUF[128];
   sprintf(BUF, "%s", STREAM_PAUSE_MSG);

   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hBoard, m_hStream, NULL, 0, BUF, strlen(BUF), MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("CAdapter::PauseSampling():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_hBoard != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_PAUSED);

   static const char * const STREAM_RESUME_MSG = "pause 1";
   char BUF[128];
   sprintf(BUF, "%s", STREAM_RESUME_MSG);

   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hBoard, m_hStream, NULL, 0, BUF, strlen(BUF), MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("CAdapter::ResumeSampling():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_hBoard != NULL);
   ASSERT(m_hStream != NULL);

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

   static const char * const STREAM_STOP_MSG = "stop";
   char BUF[128];
   sprintf(BUF, "%s", STREAM_STOP_MSG);

   SHIM_STATUS eShimStatus = DxbStreamPutMsg(m_hBoard, m_hStream, NULL, 0, BUF, strlen(BUF), MSG_PRIORITY_LOW, 250, NULL, NULL);
   TRACE("CAdapter::StopSampling():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_hBoard != NULL);
   ASSERT(m_hStream != NULL);

   ASSERT(m_eSamplingState == SS_SAMPLING);

   SHIM_STATUS eShimStatus = DxbStreamGetMsg(m_hBoard, 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;
}
