/*++ Copyright (c) 1997 Microsoft Corporation Module Name: device.h Abstract: Handling opened device object on the monitor side Author: Vlad Sadovsky (vlads) 10-Jan-1997 Environment: User Mode - Win32 Revision History: 26-Jan-1997 VladS created --*/ #ifndef _DEVICE_H_ #define _DEVICE_H_ #include #include class CWiaDrvItem; // // If this code is moved into dll, methods will need to be exported in order to instantiate // objects of those classes outside module scope. Then we will need to replace line below // // #define dllexp __declspec( dllexport ) // #undef dllexp #define dllexp // #define PRIVATE_FOR_NO_SERVICE_UI // // Type of syncronization for accessing device object // #define USE_CRITICAL_SECTION 1 /*********************************************************** * Type Definitions ************************************************************/ #define ADEV_SIGNATURE (DWORD)'ADEV' #define ADEV_SIGNATURE_FREE (DWORD)'FDEV' // // Values for flags field for device object // #define STIMON_AD_FLAG_POLLING 0x000001 // Device requires polling #define STIMON_AD_FLAG_OPENED_FOR_DATA 0x000002 // Device is opened for data access #define STIMON_AD_FLAG_LAUNCH_PENDING 0x000004 // Auto launch is pending #define STIMON_AD_FLAG_REMOVING 0x000008 // Device is being removed #define STIMON_AD_FLAG_NOTIFY_ENABLED 0x000010 // Nobody disabled notifications #define STIMON_AD_FLAG_NOTIFY_CAPABLE 0x000020 // Device is capable to notify #define STIMON_AD_FLAG_NOTIFY_RUNNING 0x000040 // Currently monitor is receiving notificaitons from device #define STIMON_AD_FLAG_MARKED_INACTIVE 0x000080 // Currently monitor is receiving notificaitons from device #define STIMON_AD_FLAG_DELAYED_INIT 0x000100 // Currently monitor is receiving notificaitons from device #define STIDEV_POLL_FAILURE_REPORT_COUNT 25 // Skip reporting errors on each polling attempt #define STIDEV_DELAYED_INTIT_TIME 10 // No. of milliseconds to schedule delayed init #define STIDEV_MIN_POLL_TIME 100 // Shortest poll interval allowed // // Forward declarations // class STI_CONN; class ACTIVE_DEVICE; class FakeStiDevice; // // Device Event code structure. A list of these is maintained for each // active device. This list is initialized from the registry when the // device becomes active (in the ACTIVE_DEVICE constructor). // Each even code structure contains an event code that the device // can issue. This event code is validated against this list. If valid, // the action assoicated with the event is triggered. // typedef struct _DEVICEEVENT { LIST_ENTRY m_ListEntry; GUID m_EventGuid; StiCString m_EventSubKey; StiCString m_EventName; StiCString m_EventData; BOOL m_fLaunchable; } DEVICEEVENT, *PDEVICEEVENT; // // Container to pass parameters to auto launch thread // typedef struct _AUTO_LAUNCH_PARAM_CONTAINER { ACTIVE_DEVICE *pActiveDevice; PDEVICEEVENT pLaunchEvent; LPCTSTR pAppName; } AUTO_LAUNCH_PARAM_CONTAINER,*PAUTO_LAUNCH_PARAM_CONTAINER; class ACTIVE_DEVICE : public BASE { friend class TAKE_ACTIVE_DEVICE; friend VOID CALLBACK DumpActiveDevicesCallback( ACTIVE_DEVICE *pActiveDevice, VOID *pContext ); public: // *** IUnknown methods *** STDMETHODIMP QueryInterface( REFIID riid, LPVOID * ppvObj); STDMETHODIMP_(ULONG) AddRef( void); STDMETHODIMP_(ULONG) Release( void); // ACTIVE_DEVICE(IN LPCTSTR lpszDeviceName, DEVICE_INFO *pInfo = NULL); ~ACTIVE_DEVICE( VOID ) ; inline BOOL IsValid( VOID ) { return (m_fValid) && (m_dwSignature == ADEV_SIGNATURE); } inline BOOL EnterCrit(VOID) { return m_dwDeviceCritSec.Lock(); } inline void LeaveCrit(VOID) { m_dwDeviceCritSec.Unlock(); } inline DWORD SetFlags( DWORD dwNewFlags ) { DWORD dwTemp = m_dwFlags; m_dwFlags = dwNewFlags; return dwTemp; } inline DWORD QueryFlags( VOID ) { return m_dwFlags; } inline DWORD QueryPollingInterval(VOID) // get current polling interval { return m_dwPollingInterval; } inline DWORD SetPollingInterval( IN DWORD dwNewInterval) // Set new interval for polling { DWORD dwTemp = m_dwPollingInterval; m_dwPollingInterval = dwNewInterval; return dwTemp; } inline BOOL IsConnectedTo( VOID ) { return !IsListEmpty(&m_ConnectionListHead); } BOOL NotificationsNeeded( VOID ) { if (!IsListEmpty(&m_ConnectionListHead)) { return TRUE; } // // If setup is running - block all events // if ( IsSetupInProgressMode() ) { return FALSE; } // // For async. notification devices always assume they need support for notificaitons // It is rather hacky , but all USB devices we have now, need to initialize notifications // support on startup, otherwise their initialization routines would not complete properly. // It is not expensive to monitor async events and do nothing when they arrive // For polled devices on the ontrary , it is quite expensive to keep monitoring // events ,when they are really not needed if ((QueryFlags() & STIMON_AD_FLAG_NOTIFY_CAPABLE) && !(QueryFlags() & STIMON_AD_FLAG_POLLING) ) { return TRUE; } else { // If there are no connections, then check whether user does not want notifications or // event list is empty return ( !m_dwUserDisableNotifications && m_fLaunchableEventListNotEmpty ); } } WCHAR* GetDeviceID() { return m_DrvWrapper.getDeviceId(); } HANDLE GetNotificationsSink() { return m_hDeviceNotificationSink; } VOID GetDeviceSettings( VOID ); // // Device notifications spport // BOOL BuildEventList( VOID ); BOOL DestroyEventList( VOID ); DWORD DisableDeviceNotifications( VOID ); DWORD EnableDeviceNotifications( VOID ); DWORD StopNotifications( VOID ); DWORD StartRunningNotifications( VOID ); BOOL FlushDeviceNotifications( VOID ); BOOL DoPoll( VOID ); BOOL DoAsyncEvent( VOID ); BOOL ProcessEvent( STINOTIFY *psNotify, BOOL fForceLaunch=FALSE, LPCTSTR pszAppName=NULL ); BOOL AutoLaunch( PAUTO_LAUNCH_PARAM_CONTAINER pAutoContainer ); BOOL RetrieveSTILaunchInformation( PDEVICEEVENT pev, LPCTSTR pAppName, STRArray& saAppList, STRArray& saCommandLine, BOOL fForceSelection=FALSE ); BOOL IsDeviceAvailable( VOID ); BOOL RemoveConnection( STI_CONN *pConnection ); BOOL AddConnection( STI_CONN *pConnection ); STI_CONN * FindMyConnection( HANDLE hConnection ); BOOL FillEventFromUSD( STINOTIFY *psNotify ); BOOL SetHandleForUSD( HANDLE hEvent ); BOOL IsEventOnArrivalNeeded( VOID ); // // Load/Unload STI device // BOOL LoadDriver( BOOL bReReadDevInfo = FALSE ); BOOL UnLoadDriver( BOOL bForceUnload ); // // PnP support methods // BOOL InitPnPNotifications( HWND hwnd ); BOOL StopPnPNotifications( VOID ); BOOL IsRegisteredForDeviceRemoval( VOID ); // // Update WIA cached device information // BOOL UpdateDeviceInformation( VOID ); VOID SetDriverItem( CWiaDrvItem *pRootDrvItem) { // // Note: Technically, we should follow proper ref-counting // procedure for this this object. However, we should NEVER have // the case where this object goes out of scope (or otherwise // destroyed) without our knowledge, therefore there is no need. // m_pRootDrvItem = pRootDrvItem; }; // LIST_ENTRY m_ListEntry; LIST_ENTRY m_ConnectionListHead; DWORD m_dwSignature; StiCString m_strLaunchCommandLine; LONG m_lDeviceId; PVOID m_pLockInfo; DWORD m_dwDelayedOpCookie; FakeStiDevice *m_pFakeStiDevice; CDrvWrap m_DrvWrapper; CWiaDrvItem *m_pRootDrvItem; private: BOOL m_fValid; BOOL m_fLaunchableEventListNotEmpty; BOOL m_fRefreshedBusOnFailure; CRIT_SECT m_dwDeviceCritSec; DWORD m_dwFlags; DWORD m_dwPollingInterval; DWORD m_dwUserDisableNotifications; DWORD m_dwSchedulerCookie; DWORD m_dwLaunchEventTimeExpire; UINT m_uiSubscribersCount; UINT m_uiPollFailureCount; HANDLE m_hDeviceEvent; HANDLE m_hDeviceNotificationSink; HANDLE m_hDeviceInterface; STI_DEVICE_STATUS m_DevStatus; LIST_ENTRY m_DeviceEventListHead; PDEVICEEVENT m_pLastLaunchEvent; }; // // Take device class // class TAKE_ACTIVE_DEVICE { private: ACTIVE_DEVICE* m_pDev; BOOL m_bLocked; public: inline TAKE_ACTIVE_DEVICE(ACTIVE_DEVICE* pdev) : m_pDev(pdev), m_bLocked(FALSE) { if (m_pDev) { m_bLocked = m_pDev->EnterCrit(); } } inline ~TAKE_ACTIVE_DEVICE() { if (m_bLocked) { m_pDev->LeaveCrit(); } } }; // // Linked list for active STI devices, known to monitor // extern LIST_ENTRY g_pDeviceListHead; // // // Add/Remove device object from the list // BOOL AddDeviceByName( LPCTSTR pszDeviceName, BOOL fPnPInitiated = FALSE ); BOOL RemoveDeviceByName( LPTSTR pszDeviceName ); BOOL MarkDeviceForRemoval( LPTSTR pszDeviceName ); // Reload device list in response to PnP or ACPI notifications // VOID RefreshDeviceList( WORD wCommand, WORD wFlags ); // // Initialize/Terminate linked list // VOID InitializeDeviceList( VOID ); VOID TerminateDeviceList( VOID ); VOID DebugDumpDeviceList( VOID ); BOOL ResetAllPollIntervals( UINT dwNewPollInterval ); // // Enumerators with callbacks // typedef VOID (*PFN_DEVINFO_CALLBACK)( PSTI_DEVICE_INFORMATION pDevInfo, VOID *pContext ); typedef VOID (* PFN_ACTIVEDEVICE_CALLBACK)( ACTIVE_DEVICE *pActiveDevice, VOID *pContext ); /* VOID WINAPI EnumerateStiDevicesWithCallback( PFN_DEVINFO_CALLBACK pfn, VOID *pContext ); */ VOID WINAPI EnumerateActiveDevicesWithCallback( PFN_ACTIVEDEVICE_CALLBACK pfn, VOID *pContext ); #endif // _DEVICE_H_