/*****************************************************************************
 * Copyright (C) Cinterion Wireless Modules GmbH
 *****************************************************************************
 * Project: CE-MUX-Driver
 *****************************************************************************
 * Author : Siemens AG Berlin COM WM RD SW1
 *****************************************************************************
 * $Workfile: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/MuxDrv/BasePort.h $
 * $Revision: /main/ms-d/23 $
 * $Date: 2014-03-14 11:53:41 $
 * $Author: mwohler $
 *****************************************************************************
 * Target:
 *  Microsoft Windows CE 4.2 or 5.0
 *****************************************************************************
 * Description:
 *  Cinterion Multiplex Driver hardware base port class CBasePort definition
 *****************************************************************************
 *
 * $Log: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/MuxDrv/BasePort.h$ 
 * 
 * /main/ms-d/23   2014-03-14 11:53:41   mwohler 
 * Use latest version of mux protocol implementation based on development for Miami client driver 
 * 
 * /main/ms-d/22   2010-10-18 11:39:37   ctna0256 
 * Set AT timeout to 3 seconds for all AT commands (timeout problems on MC75i)
 *
 * /main/ms-d/21   2009-09-02 16:02:06   ctna0450
 * Separated module shutdown detection from data reading
 *
 * /main/ms-d/20   2009-07-09 10:10:43   ctna0256
 * Configure task priorities via registry (IPIS100056661)
 *
 * /main/ms-d/19   2009-06-12 14:31:35   ctna0450
 * Fixed possible deadlock when closing read thread after power loss
 *
 * /main/ms-d/18   2009-02-18 11:58:02   ctna0256
 * Set copyright text
 *
 * /main/ms-d/17   2008-08-20 11:38:33   ctna0450
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/16   2007-05-08 16:47:08   kr36712
 * IPIS100034485
 * reopen implemented for suspend/resume over usb-driver
 *
 * /main/ms-d/15   2006-07-12 15:46:19   wm36264
 * Renamend Mux_Tick() -> Mux_MsgTick() and Mux_ResyncTick() -> Mux_TimerTick()
 *
 * /main/ms-d/14   2006-06-22 17:35:20   kr36712
 * 0xF9 resynchronisation integrated
 *
 * /main/ms-d/13   2006-06-16 12:16:08   wm36264
 * Fixed problem with registry controled part of deinit sequence
 *
 * /main/ms-d/12   2006-04-27 14:51:50   wm36264
 * Introduced callback to adjust hardware queue sizes from outside the mux protocol handling
 *
 * /main/ms-d/11   2006-04-20 10:49:51   wm36264
 * Allow increase of DLCIs after mux restart
 *
 * /main/ms-d/10   2005-11-28 15:01:15   wm36264
 * Improved module power off detection
 *
 * /main/ms-d/9   2005-11-21 11:46:33   wm36264
 * Enumerate the number of used mux channels in the registry
 *
 * /main/ms-d/8   2005-11-09 10:59:26   wm36264
 * Switched to new instancable mux interface
 *
 * /main/ms-d/7   2005-10-24 14:20:05   WM36264
 * Added file descriptions
 *
 * /main/ms-d/6   2005-10-23 14:49:27   WM36264
 * Removed obsolete pointer checks
 *
 * /main/ms-d/5   2005-10-23 14:44:58   WM36264
 * Added customer power on/off support
 *
 * /main/ms-d/4   2005-10-20 13:10:30   WM36264
 * Added proper copyright header
 *
 * /main/ms-d/3   2005-10-12 12:38:35   wm36264
 * Fixed bug in module off detection
 *
 * /main/ms-d/2   2005-10-11 15:42:52   wm36264
 * Modified logic for module initialization and deinitialization
 *
 * /main/ms-d/1   2005-10-07 16:30:03   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
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//
// BasePort.h
//
// This file contains the definition and some simple inline method
// implementations of the class "CBasePort" which handles access to the
// module via the hardware base port, it's initialization and deintialization
// as well as the management of the opening and closing virtual ports.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#define READ_BUFFER_SIZE     1024

#define DEFAULT_AT_TIMEOUT   3000

class CBasePort : public CReservation {
public:
  CBasePort(LPCTSTR szRegKey);
  ~CBasePort();
  DWORD                 AddVCom(DWORD dwDlci);
  BOOL                  RemoveVCom(void);
  BOOL                  ShutdownMux(BOOL fWaitForAliveThread = TRUE);
  BOOL                  SetPowerState(CEDEVICE_POWER_STATE PowerState);
  CEDEVICE_POWER_STATE  GetPowerState(void) { SYNCBLOCK(m_csLock); return m_PowerState; };

private:
  DWORD                 GetMaxChannels(void);
  BOOL                  OpenPort(LPCTSTR szPort, DWORD dwBaudRate);
  BOOL                  Suspend();
  BOOL                  Resume();
  BOOL                  StopDataFlow(void);
  BOOL                  StartDataFlow(void);
  BOOL                  SendATCmd(char* szATCommand, DWORD dwTimeout, DWORD dwRetries, char* szRsp = NULL, DWORD dwRspLen = 0);
  BOOL                  PowerModuleOn(void);
  BOOL                  PowerModuleOff(void);
  BOOL                  IsModulePowerOn(void);
  BOOL                  SwitchModuleOff(void);
  BOOL                  SyncBaudRate(DWORD dwBaudRate);
  BOOL                  EnableAllMuxChannels(void);
  BOOL                  InitModule(DWORD dwBaudRate);
  BOOL                  DeinitModule(void);
  BOOL                  StopThreads(BOOL fWaitForAliveThread = TRUE);
  BOOL                  StartMuxMode(DWORD dwBaudRate, LPCTSTR szBasePort);
  BOOL                  StopMuxMode(void);
  BOOL                  IsModuleLost(void) { return (WaitForSingleObject(m_hCloseEvent, 0) == WAIT_OBJECT_0); };
  // Callbacks from the mux protocol implementation
  static void*          MuxGetMem(DWORD dwUserData, DWORD dwSize) { return malloc(dwSize); };
  static void           MuxFreeMem(DWORD dwUserData, PVOID pMem) { free(pMem); };
  static void           MuxStartResult(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwResult);
  static void           MuxMsgAvailable(DWORD dwMuxInstance, DWORD dwUserData) { ReleaseSemaphore(((CBasePort*)dwUserData)->m_hMuxMsgSemaphore, 1, NULL); };
  static void           MuxReset(DWORD dwMuxInstance, DWORD dwUserData) { SetEvent(((CBasePort*)dwUserData)->m_hStartStopEvent); };
  static DWORD          MuxGetTickCount(DWORD dwMuxInstance, DWORD dwUserData) { return GetTickCount(); };
  static BOOL           MuxLock(DWORD dwMuxInstance, DWORD dwUserData)   { EnterCriticalSection(&(((CBasePort*)dwUserData)->m_csLockMuxLib)); return TRUE; };
  static BOOL           MuxUnlock(DWORD dwMuxInstance, DWORD dwUserData) { LeaveCriticalSection(&(((CBasePort*)dwUserData)->m_csLockMuxLib)); return TRUE; };
  static DWORD          MuxDevSendData(DWORD dwMuxInstance, DWORD dwUserData, PBYTE pData, DWORD dwDataLen);
  static void           MuxDevActivate(DWORD dwMuxInstance, DWORD dwUserData, DWORD dwLen);
  static DWORD          MuxDevGetFreeTxBytes(DWORD dwMuxInstance, DWORD dwUserData);
  static void           MuxDevSetQueueSizes(DWORD hMuxInstance, DWORD dwUserData, DWORD dwRxSize, DWORD dwTxSize);
  // Thread functions
  static DWORD WINAPI   ThreadReadData(LPVOID lpParameter);
  static DWORD WINAPI   ThreadIsAlive(LPVOID lpParameter);
  static DWORD WINAPI   ThreadCheckSendQueue(LPVOID lpParameter);
  static DWORD WINAPI   ThreadMuxMsg(LPVOID lpParameter);
  static DWORD WINAPI   ThreadMuxTimebase(LPVOID lpParameter);

  CRITICAL_SECTION      m_csLock;
  CRITICAL_SECTION      m_csLockMuxLib;
  CRITICAL_SECTION      m_csCheckSendQueueThread;
  CEDEVICE_POWER_STATE  m_PowerState;
  DWORD                 m_dwVComs;
  DWORD                 m_dwMaxChannels;
  DWORD                 m_dwTxQueueSize;
  DWORD                 m_dwDefaultThreadPrio;
  DWORD                 m_dwInitThreadPrio;
  TCHAR                 m_szRegKey[MAX_PATH + 1];
  HANDLE                m_hPort;
  HANDLE                m_hReadThread;
  HANDLE                m_hIsAliveThread;
  HANDLE                m_hCheckSendQueueThread;
  HANDLE                m_hMuxMsgThread;
  HANDLE                m_hMuxTimebaseThread;
  HANDLE                m_hCloseEvent;
  HANDLE                m_hStartStopEvent;
  HANDLE                m_hMuxMsgSemaphore;
  DWORD                 m_dwMuxInstance;
  DWORD                 m_dwMaxDlci;
  DWORD                 m_dwLastMaxDlci;
  DWORD                 m_dwTimeLastOff;
  DWORD                 m_dwStartResult;
  DWORD                 m_dwLenRestart;
  BOOL                  m_fFlowOn;
  BOOL                  m_fMuxShutdown;
  BOOL                  m_fMonitorDsr;
  BOOL                  m_fModuleDied;
  BOOL                  m_fSuspend;
};
