/*****************************************************************************
 * Copyright (C) Cinterion Wireless Modules GmbH
 *****************************************************************************
 * Project: Quinn-CE-USB-Driver
 *****************************************************************************
 * Author : Siemens AG Berlin COM WM RD SW
 *****************************************************************************
 * $Workfile: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/HcUsbDrv/SelectiveSuspend.h $
 * $Revision: /main/ms-d/14 $
 * $Date: 2012-09-21 13:42:34 $
 * $Author: mwohler $
 *****************************************************************************
 * Target:
 *  Microsoft Windows CE 5.0
 *****************************************************************************
 * Description:
 *  Quinn-USB-Driver: Definition for class CSelectiveSuspend
 *  doing the USB selective suspend handling.
 *****************************************************************************
 *
 * $Log: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/HcUsbDrv/SelectiveSuspend.h$ 
 * 
 * /main/ms-d/14   2012-09-21 13:42:34   mwohler 
 * Fixed memory leak by missing CloseHandle() call 
 * 
 * /main/ms-d/13   2011-02-02 10:27:44   ctna0450 
 * Removed unused USB-Reset workaround for Uranus USB problems
 *
 * /main/ms-d/12   2010-12-13 14:21:50   ctna0152
 * added USB reset handling
 *
 * /main/ms-d/11   2010-11-15 17:50:11   ctna0152
 * added workaround "PAUSE_ON_RESUME" for IPIS100068602
 *
 * /main/ms-d/10   2009-02-18 11:49:27   ctna0256
 * Set copyright text
 *
 * /main/ms-d/9   2008-08-20 11:39:43   ctna0450
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/8   2008-02-18 15:12:03   ht37010
 * added new event as bugfix for possible deadlock on closing a virtual port (may happen if pipe is waiting for device resume and the port is closed)
 *
 * /main/ms-d/7   2007-12-18 11:39:51   ht37010
 * added USB watchdog for lpSuspendDevice & lpResetPipe
 * bugfix for IPIS100044017
 *
 * /main/ms-d/6   2007-08-14 12:44:05   ht37010
 * removed SYNC-blocks
 *
 * /main/ms-d/5   2007-05-30 16:37:29   ht37010
 * encapsulation of WaitForTransition for notification event handling for USB suspend and resume
 *
 * /main/ms-d/4   2007-04-16 12:22:39   ht37010
 * workaround - reset pipe on resume
 *
 * /main/ms-d/3   2007-02-16 16:37:47   wm36264
 * Adapted selective suspend/resume notification to MS confirmend interface.
 * Untested and still deactivated by default!
 *
 * /main/ms-d/2   2006-12-14 12:15:46   wm36264
 * Prepared resume notification
 *
 * /main/ms-d/1   2006-11-03 17:04:56   wm36264
 * Created for selective suspend handling
 *
*/

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

//////////////////////////////////////////////////////////////////////////////
//
// SelectiveSuspend.h
//
// This file contains the definition of the class "CSelectiveSuspend" which
// implements the handling of the USB selective suspend feature for
// permanent power saving.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

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

#define RESUME_POLLING_INTERVAL     1000
#define TRANSITION_TIMEOUT          5000

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

class CUsbPipe;
class CUsbWatchDog;

typedef enum SSR_STATE {
  SSR_RESUMED,
  SSR_RESUMING,
  SSR_SUSPENDED,
  SSR_SUSPENDING
};

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

class CSelectiveSuspend {
public:
  CSelectiveSuspend();
  ~CSelectiveSuspend();
  BOOL Initialize(USB_HANDLE Device, LPCUSB_FUNCS Funcs, DWORD dwIfaces, DWORD dwDelay);
  BOOL Deinitialize(void);
  BOOL DeviceAccessed(void);
  BOOL WaitForResume(DWORD dwTimeout, HANDLE hEvent = NULL);
  BOOL IsResumed(void) { /*SYNCBLOCK(m_csLock);*/ return(m_State == SSR_RESUMED); };
  BOOL IsSuspended(void) { /*SYNCBLOCK(m_csLock);*/ return(m_State == SSR_SUSPENDED); };
  BOOL DeviceResumed(void);
  BOOL DeviceSuspended(void);
#ifdef USE_WA_RESET_ON_RESUME
  BOOL ResetPipeOnResume( CUsbPipe *pPipe, USB_PIPE pipe, BYTE index, BOOL isDefaultPipe );
#endif // USE_WA_RESET_ON_RESUME

#ifdef USE_WA_PAUSE_ON_RESUME
  void SetPauseOnResume(DWORD dwDelay) {m_dwPauseOnResumeDelay = dwDelay;};
#endif // USE_WA_PAUSE_ON_RESUME

#ifdef WA_RESUME_ON_UNEXPECTED_HOST_WAKEUPS
  BOOL SuspendAndResumeOnResetPipeOnResumeFailed(void);
#endif

private:
  BOOL IsRunning(void) { return((m_hCloseEvent != NULL) && WaitForSingleObject(m_hCloseEvent, 0) != WAIT_OBJECT_0); };

#if defined(USB_DEVICE_SUSPENDED) && defined(USB_DEVICE_RESUMED)
  BOOL WaitForResumeTransition(DWORD dwTimeout);
  BOOL WaitForSuspendTransition(DWORD dwTimeout);
#endif
  BOOL SuspendDevice(void);
  BOOL ResumeDevice(void);

  static DWORD WINAPI ExecutionThread(LPVOID lpParameter);

  CRITICAL_SECTION   m_csLock;
  HANDLE             m_hCloseEvent;
  HANDLE             m_hResumedEvent;
  HANDLE             m_hResumedNotificationEvent;
  HANDLE             m_hSuspendedNotificationEvent;
  HANDLE             m_hExecutionThread;
  BOOL               m_fExeThreadRunning;
  USB_HANDLE         m_hDevice;
  LPCUSB_FUNCS       m_pFuncs;
  DWORD              m_dwNumIfaces;
  DWORD              m_dwDelay;
  DWORD              m_dwNextExpiration;
  SSR_STATE          m_State;
#ifdef USE_WA_RESET_ON_RESUME
  DWORD              m_bmPipeReset;
  CRITICAL_SECTION   m_csPipeResetLock;
#endif // USE_WA_RESET_ON_RESUME

#ifdef USE_WA_PAUSE_ON_RESUME
  DWORD              m_dwPauseOnResumeDelay;
#endif // USE_WA_PAUSE_ON_RESUME

#ifdef USE_WATCHDOG_SUSPEND_DEVICE
  CUsbWatchDog    *m_pWDSuspend;
#endif
};
