/*****************************************************************************
 * Copyright (C) Cinterion Wireless Modules GmbH
 *****************************************************************************
 * Project: CE-MUX-Driver
 *****************************************************************************
 * Author : Siemens AG Berlin COM WM RD SW1
 *****************************************************************************
 * $Workfile: O:/ctna0450_RIL/z_ms-d/src/working/Classic/MuxDrv/BufferedParentPort.h $
 * $Revision: /main/ms-d/17 $
 * $Date: 2008-08-20 11:38:33 $
 * $Author: ctna0450 $
 *****************************************************************************
 * Target:
 *  Microsoft Windows CE 4.2 and above
 *****************************************************************************
 * Description:
 *  Cinterion Multiplex Driver buffered parent port definition
 *****************************************************************************
 *
 * $Log: O:/ctna0450_RIL/z_ms-d/src/working/Classic/MuxDrv/BufferedParentPort.h$
 *
*/

//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2009 Cinterion Wireless Modules GmbH
//
// Version: 1.0
// Date:    dummy
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//
// BasePort.h
//
// This file contains the definition of the class "CBufferedParentPort"
// handling.
// The mutliplex protocol implementation requires a buffering of the data
// read from and written to the physical COM port. Unfortunately there do
// exist UART drivers without internal buffer handling using only the
// hardware fifos of the UARTs. For these rare cases the Cinterion multiplex
// driver provides an additional virtual COM port abstracting access to the
// physical COM port implementing its own data buffering. So in these cases
// where a serial driver of a physical COM port doesn't provide data
// buffering the parent port of the multiplex instance must be connected to
// an internal bufferd port instance and that instance must be connected to
// the physical COM port.
// This code is experimental and hadn't been put into comprehensive testing.
// It should therefore only be used for test purposes.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#define DEFAULT_BUFFER_SIZE    16
#define BUFPORT_REOPENS        3
#define BUFPORT_REOPEN_DELAY   100
#define BUFPORT_COM_MASK       (EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXFLAG)

class CBufferedParentPort {
public:
  CBufferedParentPort(LPCTSTR szRegKey);
  ~CBufferedParentPort();
  BOOL                  Open(LPVOID pInstance);
  BOOL                  Close(LPVOID pInstance);
  DWORD                 ReadData(PBYTE pData, DWORD dwLen);
  DWORD                 WriteData(PBYTE pData, DWORD dwLen);
  BOOL                  IoControl(LPVOID pInstance, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut);

private:
  BOOL                  Purge(DWORD dwFlags);
  static DWORD WINAPI   ThreadReadData(LPVOID lpParameter);
  static DWORD WINAPI   ThreadWriteData(LPVOID lpParameter);
  static DWORD WINAPI   ThreadWaitEvent(LPVOID lpParameter);

  TCHAR                 m_szRegKey[MAX_PATH + 1];
  HANDLE                m_hPort;
  DWORD                 m_dwOpenCount;
  HANDLE                m_hThreadReadData;
  HANDLE                m_hThreadWriteData;
  HANDLE                m_hThreadWaitEvent;
  HANDLE                m_hCloseEvent;
  CRingBuffer           m_ReadBuffer;
  CRingBuffer           m_WriteBuffer;
  COMMTIMEOUTS          m_Timeouts;
  CWaitCommInstance     m_WaitCommEvent;
  DWORD                 m_dwDefaultThreadPrio;
};

//////////////////////////////////////////////////////////////////////////////

class CBufferedPortInstance {
public:
  CBufferedPortInstance(CBufferedParentPort* pPort) : m_pPort(pPort) {};
  ~CBufferedPortInstance() {};
  BOOL                  Open(void) { return m_pPort->Open((LPVOID)this); };
  BOOL                  Close(void) { return m_pPort->Close((LPVOID)this); };
  DWORD                 ReadData(PBYTE pData, DWORD dwLen) { return m_pPort->ReadData(pData, dwLen); };
  DWORD                 WriteData(PBYTE pData, DWORD dwLen) { return m_pPort->WriteData(pData, dwLen); };
  BOOL                  IoControl(DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
                          { return m_pPort->IoControl((LPVOID)this, dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut); };
private:
  CBufferedParentPort*  m_pPort;
};

