/*****************************************************************************
 * Copyright (C) Gemalto M2M GmbH
 *****************************************************************************
 * Project: IMC-RIL-Driver
 *****************************************************************************
 * Author : Wireless Modules RD SW A2
 *****************************************************************************
 * $Workfile: Y:/z_ms-d/src/working/Quinn/RilDrv/ComManager.h $
 * $Revision: /main/ms-d/21 $
 *     $Date: 2012-11-21 13:30:08 $
 *   $Author: pmackent $
 *****************************************************************************
 * Target:
 *  Microsoft Windows Mobile 5.0
 *****************************************************************************
 * Description:
 *  Gemalto IMC RIL
 *****************************************************************************
 *
 * $Log: Y:/z_ms-d/src/working/Quinn/RilDrv/ComManager.h$ 
 * 
 * /main/ms-d/21   2012-11-21 13:30:08   pmackent 
 * Basic support of EHS5 Rel2
 *
 * /main/ms-d/20   2012-07-06 11:29:40   pmackent
 * Allow PPP traces on CSD/CDMA
 *
 * /main/ms-d/19   2011-09-26 13:34:22   ctna0256
 * Comply with CE6 warning level 4
 *
 * /main/ms-d/18   2011-03-09 14:24:38   ctna0256
 * Run code analysis on Windows CE7
 *
 * /main/ms-d/17   2010-08-24 10:37:56   ctna0256
 * Moved reading of port assignments from registry
 *
 * /main/ms-d/16   2010-05-07 10:18:25   ctna0256
 * New PPP trace feature needed to find connection problems (IPIS100064425)
 *
 * /main/ms-d/15   2008-08-22 10:23:11   ctna0256
 * Set Cinterion copyright text
 *
 * /main/ms-d/14   2008-08-21 09:34:11   ctna0256
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/13   2007-11-26 17:05:43   kr36712
 * integration of GPS support
 * use of the mux protocol
 *
 * /main/ms-d/12   2007-11-02 15:50:11   ht37010
 * fix for EPIC21309: passing parameter to avoid waiting for reopen if module is already powered off
 *
 * /main/ms-d/11   2007-09-21 16:08:09   mp49210
 * Optional usage of multiplexer for HC25 Rel2
 *
 * /main/ms-d/10   2007-04-27 08:33:50   mp49210
 * Removed Lint warnings
 *
 * /main/ms-d/9   2007-04-11 15:40:44   ht37010
 * Added port reopen preparation before suspend as workaround for USB reset problem
 *
 * /main/ms-d/8   2007-02-15 12:09:07   wm36264
 * Added port reopen after resume as workaround for USB reset problem
 *
 * /main/ms-d/7   2007-02-09 15:15:40   mp49210
 * Lint compatibility
 *
 * /main/ms-d/6   2007-01-03 17:04:20   mp49210
 * Replace +CIEV: sounder with +CIEV: audio
 *
 * /main/ms-d/5   2006-11-22 13:01:42   wm36264
 * Removed unused stuff
 *
 * /main/ms-d/4   2006-11-17 11:19:31   mp49210
 * Introduction of AT^SIND
 *
 * /main/ms-d/3   2006-11-02 09:31:43   mp49210
 * Minor changes for AT+CINF, AT^SNFS
 *
 * /main/ms-d/2   2006-10-30 10:26:39   wm36264
 * Removed unused stuff
 *
 * /main/ms-d/1   2006-10-25 16:53:10   wm36264
 * First transformation from classic RIL
 *
*/

//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Gemalto M2M GmbH
// Copyright (C) 2006-2008 Siemens AG
//
// Version: 1.0
// Date:    dummy
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//
// The class CComManger manages the internal used port objects. This is
// necessary because exclusive port access is required by the RIL driver
// itself for port initialization as well as from external applications for
// data connections. This makes a locking mechanism necessary which is
// implemented in this class together with the global creation and destruction
// of the port objects. The class manages also the global port capabilities.
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// The following lines define the supported capabilities of the available
// ports. Some combinations like GPRS and CSD or Cmd and Urc are possible.
//////////////////////////////////////////////////////////////////////////////
#define PORT_CAPS_DATA            0x00000001
#define PORT_CAPS_CMD             0x00000002
#define PORT_CAPS_URC             0x00000004
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// The following lines define the port assignments and corresponding values.
// The enum used in the past has been replaced on a dynamic port assignment
// based on the port capabilities defined globally.
//////////////////////////////////////////////////////////////////////////////
typedef int COM_PORT_TYPE;
#define INVALID_PORT              -1
#define DATA_PORT                 g_ComManager.GetDataPort()
#define URC_PORT                  g_ComManager.GetUrcPort()
#define NUMBER_OF_PORTS           2
//////////////////////////////////////////////////////////////////////////////

// Max. supported length for port names
#define MAX_PORT_NAME_LEN         64

// Max. number of data packets to be traced
#define DEFAULT_MAX_TRACE_DATA_COUNTER  30

// Macros for internal syncronization
#define CNTUSAGE(Info)            CNTUSAGE_Implementation CNTUSAGE_Object(Info)
#define CNTUSAGE2(Info)           CNTUSAGE_Implementation CNTUSAGE_Object2(Info)
#define WAITNOUSAGE(Info)         SYNCBLOCK(Info.csLock); while(Info.dwCnt) Sleep(100);

class CRilHandle;
class CComHandle;

class CComManager {
public:
  CComManager();
  ~CComManager();

  void           Init(CRilHandle* pRilHandle);
  void           Deinit(void);

  CRilHandle*    GetRILDevice(void) { return m_pRilHandle; };

  TCHAR*         GetPortName(COM_PORT_TYPE PortType);
  TCHAR*         GetInternalPortName(COM_PORT_TYPE PortType);
  TCHAR*         GetInternalGpsPortName(void) { return SUPPORTS_GPS ? m_szInternalGpsPortName : NULL; };
  const TCHAR*   GetDebugName(COM_PORT_TYPE PortType) const { return m_PortInfo[PortType].strDbgName; };
  BOOL           IsDataPort(COM_PORT_TYPE PortType) const { return ((m_PortInfo[PortType].dwCaps & (PORT_CAPS_DATA)) != 0); };

  CComHandle*    CreatePortDevice(LPCWSTR szRegKey);
  CComHandle*    CreatePortDevice(COM_PORT_TYPE PortType);
  BOOL           DestroyPortDevice(COM_PORT_TYPE PortType);
  BOOL           DestroyPortDevice(const CComHandle* pPortDevice);
  BOOL           OpenPortDevice(COM_PORT_TYPE PortType);
  BOOL           ClosePortDevice(COM_PORT_TYPE PortType);
  BOOL           CloseAllPortDevices(void);
  BOOL           OpenBasePort(void);
  BOOL           CloseBasePort(void);
  BOOL           ReopenAllPortDevices(DWORD dwTimeout);
  BOOL           WaitReopen(DWORD dwTimeout);
  void           PrepareReopen( void );
  HANDLE         GetPortHandle(COM_PORT_TYPE PortType);
#ifdef RIL_ALLOW_TRACE_PPP_DATA
  void           TraceExtData(BOOL fTraceExtData, BOOL fCSDConnection);
  void           TraceExtDataCall1();
#endif

  BOOL           UnlockPortDevice(COM_PORT_TYPE PortType);
  BOOL           LockPortDevice(COM_PORT_TYPE PortType, BOOL fReopen = TRUE );

  DWORD          ExternalRead(COM_PORT_TYPE PortType, LPVOID pBuf, DWORD len);
  DWORD          ExternalWrite(COM_PORT_TYPE PortType, LPCVOID pBuf, DWORD len);
  BOOL           ExternalIoControl(COM_PORT_TYPE PortType, DWORD dwCode, const PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut);

  BOOL           SendPreInitCmds(COM_PORT_TYPE PortType);
  BOOL           SendInitCmds(BOOL fPreInitOnly);
  BOOL           SendUnlockedInitCmds(void);

  COM_PORT_TYPE  GetPortFromContextId(DWORD dwContextId);
  COM_PORT_TYPE  GetDataPort(void) const { return m_DataPort; };
  COM_PORT_TYPE  GetUrcPort(void) const { return m_UrcPort; };

private:
  BOOL           IsValidPort(COM_PORT_TYPE PortType) const { return ((PortType > INVALID_PORT) && (PortType < NUMBER_OF_PORTS)); };
#ifdef RIL_ALLOW_TRACE_PPP_DATA
  void           TraceBuffer(BYTE *pBufC, DWORD dwLen);
#endif
  void           ReadRegistrySettings();

  // Struct for information used to lock internal resources
  typedef struct {
    CRITICAL_SECTION   csLock;
    DWORD              dwCnt;
  } UsageLockInfo, *pUsageLockInfo;

  // Internal class to handle synchronization
  class CNTUSAGE_Implementation {
  public:
    CNTUSAGE_Implementation(pUsageLockInfo pInfo) {
      m_pInfo = pInfo;
      SYNCBLOCK(pInfo->csLock);
      (m_pInfo->dwCnt)++;
    };
    ~CNTUSAGE_Implementation() {
      (m_pInfo->dwCnt)--;
      m_pInfo = NULL;
    }
  private:
    pUsageLockInfo m_pInfo;
  };

  // General structure describing the capabilities and characteristics of the module ports
  // used in a global array describing the available ports for port virtualization.
  typedef struct {
    const TCHAR*  strDbgName;          // Name used in debug output
    const TCHAR*  strRegName;          // Registry key holding the port's system name
    const TCHAR*  strRegNameInternal;  // Registry key holding the port's internal name
    DWORD   dwCaps;                    // Port capabilities using defines PORT_CAPS_
  } PortInfo;

  enum PORT_USAGE {
    USAGE_INTERNAL,              // Port is used internal in RIL driver
    USAGE_DATA                   // Port is used for data transfer
  };

  static const PortInfo  m_PortInfo[NUMBER_OF_PORTS];

  TCHAR                  m_szPortName[NUMBER_OF_PORTS][MAX_PORT_NAME_LEN];
  TCHAR                  m_szPortNameInternal[NUMBER_OF_PORTS][MAX_PORT_NAME_LEN];
  CComHandle*            m_pComDevice[NUMBER_OF_PORTS];
  UsageLockInfo          m_PortLock[NUMBER_OF_PORTS];
  PORT_USAGE             m_PortUsage[NUMBER_OF_PORTS];
  DWORD                  m_dwIoCount[NUMBER_OF_PORTS];
  TCHAR                  m_szInternalGpsPortName[MAX_PORT_NAME_LEN];
  HANDLE                 m_hBasePort;
  UsageLockInfo          m_RilHandleLock;
  CRilHandle*            m_pRilHandle;
  COM_PORT_TYPE          m_DataPort;
  COM_PORT_TYPE          m_UrcPort;
  HANDLE                 m_hReopenEvent;
#ifdef RIL_ALLOW_TRACE_PPP_DATA
  BOOL                   m_fTraceExtData;
  BOOL                   m_fCSDConnection;
  DWORD                  m_dwTraceExtDataCounter;
  DWORD                  m_dwTraceExtDataCounterMax;
#endif
};

// Currently access to the CComManager is realized via a single global variable
extern CComManager g_ComManager;

