/*****************************************************************************
 * Copyright (C) Cinterion Wireless Modules GmbH
 *****************************************************************************
 * Project: CE-MUX-Driver
 *****************************************************************************
 * Author : Siemens AG Berlin COM WM RD SW1
 *****************************************************************************
 * $Workfile: Y:/z_ms-d/src/working/Classic/MuxDrv/MuxChannel.h $
 * $Revision: /main/ms-d/14 $
 * $Date: 2009-02-18 11:58:12 $
 * $Author: ctna0256 $
 *****************************************************************************
 * Target:
 *  Microsoft Windows CE 4.2 or 5.0
 *****************************************************************************
 * Description:
 *  Cinterion Multiplex Driver virtual mux port class CMuxChannel definition
 *****************************************************************************
 *
 * $Log: Y:/z_ms-d/src/working/Classic/MuxDrv/MuxChannel.h$ 
 * 
 * /main/ms-d/14   2009-02-18 11:58:12   ctna0256 
 * Set copyright text 
 * 
 * /main/ms-d/13   2009-01-13 14:22:12   ctna0450 
 * Make mux port instancable to properly support handling of multiple WaitCommEvent() calls
 *
 * /main/ms-d/12   2008-10-17 12:04:02   ctna0450
 * Added debug zone for IOCTLs
 *
 * /main/ms-d/11   2008-08-20 11:38:36   ctna0450
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/10   2008-06-04 11:06:28   wm36264
 * Fixed problem with parsing of escape sequence
 *
 * /main/ms-d/9   2005-11-28 11:29:59   wm36264
 * Improved unexpected mux shutdown handling
 *
 * /main/ms-d/8   2005-11-24 16:42:50   wm36264
 * Properly handle unexpected mux shutdown
 *
 * /main/ms-d/7   2005-11-09 10:59:22   wm36264
 * Switched to new instancable mux interface
 *
 * /main/ms-d/6   2005-10-28 13:15:50   WM36264
 * Fixed some return values, replaced some usages of "SYNCBLOCK()"
 *
 * /main/ms-d/5   2005-10-28 14:05:56   kr36712
 * handle permission for the application pointer
 *
 * /main/ms-d/4   2005-10-24 14:19:26   WM36264
 * Added file descriptions
 *
 * /main/ms-d/3   2005-10-20 13:13:07   WM36264
 * Added proper copyright header
 *
 * /main/ms-d/2   2005-10-13 16:27:38   wm36264
 * Allow virtual port to be opened more than once
 *
 * /main/ms-d/1   2005-10-07 16:30:06   wm36264
 * First version of Windows CE Muxer
 *
*/

//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Cinterion Wireless Modules GmbH
// Copyright (C) 2005-2008 Siemens AG
//
// Version: 1.0
// Date:    dummy
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//
// MuxChannel.cpp
//
// This file contains the definition of the class "CMuxChannel" which
// provides the functionality of the virtual COM ports.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

class CMuxChannel {
public:
  CMuxChannel(LPCTSTR szRegKey);
  ~CMuxChannel();
  BOOL                 Open(LPVOID pInstance);
  BOOL                 Close(LPVOID pInstance);
  BOOL                 GetDcb(DCB* pDst);
  BOOL                 SetDcb(DCB* pSrc);
  BOOL                 GetTimeouts(COMMTIMEOUTS* pDst);
  BOOL                 SetTimeouts(COMMTIMEOUTS* pSrc);
  BOOL                 GetWaitMask(LPVOID pInstance, PDWORD pdwWaitMask);
  BOOL                 SetWaitMask(LPVOID pInstance, DWORD dwWaitMask);
  BOOL                 WaitOnMask(LPVOID pInstance, PDWORD pdwWaitEvent);
  BOOL                 GetProperties(COMMPROP* pDst);
  BOOL                 GetComStat(COMSTAT* pDst);
  BOOL                 ClearRts(void);
  BOOL                 SetRts(void);
  BOOL                 ClearDtr(void);
  BOOL                 SetDtr(void);
  BOOL                 GetModemState(PDWORD pdwState);
  BOOL                 ClearSendBuffer(void);
  BOOL                 ClearReceiveBuffer(void);
  DWORD                ReadData(PBYTE pData, DWORD dwLen);
  DWORD                WriteData(PBYTE pData, DWORD dwLen);
  DWORD                GetDlci(void) { return m_dwDlci; };

private:
  BOOL                 StopThreads(void);
  BOOL                 DlciOpen(void);
  BOOL                 DlciClose(void);
  void                 ParseEscape(PCHAR pData, DWORD dwLen);
  void                 ParsePlus(PCHAR pData, DWORD dwLen);
  BOOL                 IsMuxRunning(void) { return (m_dwOpenCount && (WaitForSingleObject(m_hCloseEvent, 0) == WAIT_TIMEOUT)); };
  // Callbacks from the mux protocol implementation
  static void          MuxEstablishResult(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci, DWORD dwResult);
  static void          MuxReleaseResult(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci, DWORD dwResult);
  static void          MuxSendDataContinue(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci, DWORD dwLen);
  static DWORD         MuxReceiveData(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci, PBYTE pData, DWORD dwLen);
  static void          MuxReceiveV24Status(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci, MUX_V24STATUS_t V24Status);
  static void          MuxShutdown(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwDlci);
  // Thread functions
  static DWORD WINAPI  ThreadDetectEscape(LPVOID lpParameter);

  CRITICAL_SECTION     m_csLock;
  CRITICAL_SECTION     m_csLockDcb;
  CRITICAL_SECTION     m_csLockRead;
  CRITICAL_SECTION     m_csLockModuleState;
  DCB                  m_Dcb;
  COMMTIMEOUTS         m_Timeouts;
  TCHAR                m_szMuxInstance[16];
  HANDLE               m_hCloseEvent;
  HANDLE               m_hStartStopEvent;
  HANDLE               m_hReadEvent;
  HANDLE               m_hWriteContinueEvent;
  HANDLE               m_hStopEscapeThreadEvent;
  HANDLE               m_hDetectEscapeThread;
  DWORD                m_dwMuxInstance;
  DWORD                m_dwOpenCount;
  DWORD                m_dwDlci;
  DWORD                m_dwStartStopResult;
  DWORD                m_dwTimeLastChar;
  DWORD                m_dwTimeFirstPlus;
  DWORD                m_dwPlusCnt;
  DWORD                m_dwReadLen;
  DWORD                m_dwRead;
  DWORD                m_dwReadPending;
  DWORD                m_dwCurrentPermissions;
  PBYTE                m_pReadBuffer;
  MUX_V24STATUS_t      m_ModuleState;
  CWaitCommInstance    m_WaitCommEvent;
};

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

class CPortInstance {
public:
  CPortInstance(CMuxChannel* pMuxChannel) : m_pMuxChannel(pMuxChannel) {};
  ~CPortInstance() {};
  BOOL                 Open(void) { return m_pMuxChannel->Open((LPVOID)this); };
  BOOL                 Close(void) { return m_pMuxChannel->Close((LPVOID)this); };
  BOOL                 GetDcb(DCB* pDst) { return m_pMuxChannel->GetDcb(pDst); };
  BOOL                 SetDcb(DCB* pSrc) { return m_pMuxChannel->SetDcb(pSrc); };
  BOOL                 GetTimeouts(COMMTIMEOUTS* pDst) { return m_pMuxChannel->GetTimeouts(pDst); };
  BOOL                 SetTimeouts(COMMTIMEOUTS* pSrc) { return m_pMuxChannel->SetTimeouts(pSrc); };
  BOOL                 GetWaitMask(PDWORD pdwWaitMask) { return m_pMuxChannel->GetWaitMask((LPVOID)this, pdwWaitMask); };
  BOOL                 SetWaitMask(DWORD dwWaitMask) { return m_pMuxChannel->SetWaitMask((LPVOID)this, dwWaitMask); };
  BOOL                 WaitOnMask(PDWORD pdwWaitEvent) { return m_pMuxChannel->WaitOnMask((LPVOID)this, pdwWaitEvent); };
  BOOL                 GetProperties(COMMPROP* pDst) { return m_pMuxChannel->GetProperties(pDst); };
  BOOL                 GetComStat(COMSTAT* pDst) { return m_pMuxChannel->GetComStat(pDst); };
  BOOL                 ClearRts(void) { return m_pMuxChannel->ClearRts(); };
  BOOL                 SetRts(void) { return m_pMuxChannel->SetRts(); };
  BOOL                 ClearDtr(void) { return m_pMuxChannel->ClearDtr(); };
  BOOL                 SetDtr(void) { return m_pMuxChannel->SetDtr(); };
  BOOL                 GetModemState(PDWORD pdwState) { return m_pMuxChannel->GetModemState(pdwState); };
  BOOL                 ClearSendBuffer(void) { return m_pMuxChannel->ClearSendBuffer(); };
  BOOL                 ClearReceiveBuffer(void) { return m_pMuxChannel->ClearReceiveBuffer(); };
  DWORD                ReadData(PBYTE pData, DWORD dwLen) { return m_pMuxChannel->ReadData(pData, dwLen); };
  DWORD                WriteData(PBYTE pData, DWORD dwLen) { return m_pMuxChannel->WriteData(pData, dwLen); };
  DWORD                GetDlci(void) { return m_pMuxChannel->GetDlci(); };

private:
  CMuxChannel*         m_pMuxChannel;
};

