windows-nt/Source/XPSP1/NT/printscan/wia/drivers/camera/ircamera/device.cpp
2020-09-26 16:20:57 +08:00

1344 lines
36 KiB
C++

//------------------------------------------------------------------------------
// Copyright (c) 1999-2000 Microsoft Corporation.
//
// device.cpp
//
// Implement IrTran-P device methods.
//
// Author:
//
// EdwardR 12-Aug-1999 Modeled from code by ReedB.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <irthread.h>
#include "ircamera.h"
#include "resource.h"
#include "tcamprop.h"
// #include "/nt/private/windows/imagein/ui/uicommon/simstr.h"
// #include "/nt/private/windows/imagein/ui/inc/shellext.h"
extern HINSTANCE g_hInst;
extern DWORD EnableDisableIrCOMM( IN BOOL fDisable ); // irtranp\irtranp.cpp
DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice ); // Forward Ref.
#define SZ_REG_KEY_INFRARED TEXT("Control Panel\\Infrared")
#define SZ_REG_KEY_IRTRANP TEXT("Control Panel\\Infrared\\IrTranP")
#define SZ_REG_DISABLE_IRCOMM TEXT("DisableIrCOMM")
HKEY g_hRegistryKey = 0;
//--------------------------------------------------------------------------
// SignalWIA()
//
// Helper function used by the IrTran-P code to signal WIA that a new
// picture has arrived.
//
// Arguments:
//
// pvIrUsdDevice -- Device object. IrTran-P only knows this as a void*.
//
//--------------------------------------------------------------------------
DWORD SignalWIA( IN char *pszPathPlusFileName,
IN void *pvIrUsdDevice )
{
HRESULT hr;
DWORD dwStatus = 0;
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
//
// First, add the new picture to the tree representing the images:
//
if (pIrUsdDevice && pIrUsdDevice->IsInitialized())
{
TCHAR *ptszPath;
TCHAR *ptszFileName;
#ifdef UNICODE
int iStatus;
WCHAR wszTemp[MAX_PATH];
iStatus = MultiByteToWideChar( CP_ACP,
0,
pszPathPlusFileName,
-1, // Auto-calculate length...
wszTemp,
MAX_PATH);
ptszPath = wszTemp;
ptszFileName = wcsrchr(wszTemp,L'\\');
ptszFileName++;
#else
ptszPath = pszPathPlusFileName;
ptszFileName = strrchr(pszPathPlusFileName,'\\');
ptszFileName++;
#endif
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
IWiaDrvItem *pNewImage;
hr = pIrUsdDevice->CreateItemFromFileName(
WiaItemTypeFile | WiaItemTypeImage,
ptszPath,
ptszFileName,
&pNewImage);
if (!FAILED(hr))
{
IWiaDrvItem *pDrvItemRoot = pIrUsdDevice->GetDrvItemRoot();
hr = pNewImage->AddItemToFolder(pDrvItemRoot);
pNewImage->Release();
}
else
{
WIAS_ERROR((g_hInst,"SignalWIA(): CreateItemFromFileName() Failed: %x",hr));
}
}
//
// Now, signal WIA:
//
if (pIrUsdDevice)
{
DWORD dwNewTime = GetTickCount();
DWORD dwDelta = dwNewTime - pIrUsdDevice->m_dwLastConnectTime;
if (dwDelta > RECONNECT_TIMEOUT)
{
pIrUsdDevice->m_guidLastEvent = WIA_EVENT_DEVICE_CONNECTED;
if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
{
dwStatus = GetLastError();
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
}
}
else
{
pIrUsdDevice->m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
{
dwStatus = GetLastError();
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
}
}
pIrUsdDevice->m_dwLastConnectTime = dwNewTime;
}
else
{
WIAS_ERROR((g_hInst,"SignalWIA(): null pvIrUsdDevice object"));
return dwStatus;
}
//
// Display IrCamera browser if it's not already up:
//
#if FALSE
HINSTANCE hInst = LoadLibrary(TEXT("WIASHEXT.DLL"));
if (hInst)
{
WIAMAKEFULLPIDLFORDEVICE pfn =
(WIAMAKEFULLPIDLFORDEVICE)GetProcAddress(hInst, "MakeFullPidlForDevice");
if (pfn)
{
LPITEMIDLIST pidl = NULL;
pfn( pIrUsdDevice->m_bstrDeviceID, &pidl );
if (pidl)
{
SHELLEXECUTEINFO sei;
memset( &sei, 0, sizeof(sei) );
sei.cbSize = sizeof(sei);
// sei.hwnd = hDlg;
sei.fMask = SEE_MASK_IDLIST;
sei.nShow = SW_SHOW;
sei.lpIDList = pidl;
ShellExecuteEx( &sei );
LPMALLOC pMalloc = NULL;
if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc)
{
pMalloc->Free(pidl);
pMalloc->Release();
}
}
}
FreeLibrary( hInst );
}
#endif
return dwStatus;
}
//--------------------------------------------------------------------------
// IrUsdDevice::IrUsdDevice()
//
// Device class constructor
//
// Arguments:
//
// punkOuter
//
// Return Value:
//
// None
//
//--------------------------------------------------------------------------
IrUsdDevice::IrUsdDevice( LPUNKNOWN punkOuter ):
m_cRef(1),
m_punkOuter(NULL),
m_dwLastConnectTime(0),
m_fValid(FALSE),
m_pIStiDevControl(NULL),
m_hShutdownEvent(INVALID_HANDLE_VALUE),
m_hRegistryEvent(INVALID_HANDLE_VALUE),
m_hSignalEvent(INVALID_HANDLE_VALUE),
m_hIrTranPThread(NULL),
m_hEventMonitorThread(NULL),
m_guidLastEvent(GUID_NULL),
m_pIWiaEventCallback(NULL),
m_pStiDevice(NULL),
m_bstrDeviceID(NULL),
m_bstrRootFullItemName(NULL),
m_pIDrvItemRoot(NULL)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::IrUsdDevice"));
//
// See if we are aggregated. If we are (almost always the case) save
// pointer to the controlling Unknown , so subsequent calls will be
// delegated. If not, set the same pointer to "this".
//
if (punkOuter)
{
m_punkOuter = punkOuter;
}
else
{
//
// Cast below is needed in order to point to right virtual table
//
m_punkOuter = reinterpret_cast<IUnknown*>
(static_cast<INonDelegatingUnknown*>
(this));
}
}
HRESULT IrUsdDevice::PrivateInitialize()
{
HRESULT hr = S_OK;
__try {
if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
WIAS_ERROR((g_hInst,"IrUsdDevice::PrivateInitialize, create shutdown CritSect failed"));
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
hr = E_OUTOFMEMORY;
}
if(hr == S_OK) {
//
// Create event for syncronization of notifications shutdown.
//
m_hShutdownEvent = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (m_hShutdownEvent && (INVALID_HANDLE_VALUE != m_hShutdownEvent))
{
m_fValid = TRUE;
}
else
{
hr = HRESULT_FROM_WIN32(::GetLastError());
WIAS_ERROR((g_hInst,"IrUsdDevice::PrivateInitialize, create shutdown event failed"));
}
}
return hr;
}
//------------------------------------------------------------------------
// IrUsdDevice::~IrUsdDevice
//
// Device class destructor
//
// Arguments:
//
// None
//
// Return Value:
//
// None
//
//------------------------------------------------------------------------
IrUsdDevice::~IrUsdDevice(void)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::~IrUsdDevice"));
//
// Kill notification thread if it exists.
//
SetNotificationHandle(NULL);
//
// Close event for syncronization of notifications shutdown.
//
if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE))
{
CloseHandle(m_hShutdownEvent);
}
if (m_hRegistryEvent && (m_hRegistryEvent != INVALID_HANDLE_VALUE))
{
CloseHandle(m_hRegistryEvent);
}
//
// Release the device control interface.
//
if (m_pIStiDevControl)
{
m_pIStiDevControl->Release();
m_pIStiDevControl = NULL;
}
//
// WIA member destruction
//
// Cleanup the WIA event sink.
//
if (m_pIWiaEventCallback)
{
m_pIWiaEventCallback->Release();
}
//
// Free the storage for the device ID.
//
if (m_bstrDeviceID)
{
SysFreeString(m_bstrDeviceID);
}
//
// Release the objects supporting device property storage.
//
if (m_bstrRootFullItemName)
{
SysFreeString(m_bstrRootFullItemName);
}
//
// Free the critical section.
//
DeleteCriticalSection(&m_csShutdown);
}
/**************************************************************************\
* IrUsdDevice::GetCapabilities
*
* Get the device STI capabilities.
*
* Arguments:
*
* pUsdCaps - Pointer to USD capabilities data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
{
ZeroMemory(pUsdCaps, sizeof(*pUsdCaps));
pUsdCaps->dwVersion = STI_VERSION;
//
// We do support device notifications, but do not requiring polling.
//
pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT;
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::GetStatus()
//
// Query device online and/or event status.
//
// Arguments:
//
// pDevStatus - Pointer to device status data.
//
// Return Value:
//
// HRESULT - STI_OK
// E_INVALIDARG
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::GetStatus( IN OUT PSTI_DEVICE_STATUS pDevStatus )
{
WIAS_TRACE((g_hInst,"IrUsdDevice::GetStatus()"));
//
// Validate parameters.
//
if (!pDevStatus)
{
WIAS_ERROR((g_hInst,"IrUsdDevice::GetStatus, NULL device status"));
return E_INVALIDARG;
}
//
// If we are asked, verify whether device is online.
//
pDevStatus->dwOnlineState = 0L;
if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE)
{
//
// The IrTran-P device is always on-line:
//
pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
}
//
// If we are asked, verify state of event.
//
pDevStatus->dwEventHandlingState &= ~STI_EVENTHANDLING_PENDING;
if (pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE)
{
//
// Generate an event the first time we load.
//
if (m_bUsdLoadEvent)
{
pDevStatus->dwEventHandlingState = STI_EVENTHANDLING_PENDING;
m_guidLastEvent = guidEventFirstLoaded;
m_bUsdLoadEvent = FALSE;
}
//
// event pending ???
//
}
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::DeviceReset()
//
// Reset data file pointer to start of file. For IrTran-P, we don't need
// to do anything.
//
// Arguments:
//
// None
//
// Return Value:
//
// HRESULT - STI_OK
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::DeviceReset(void)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::DeviceReset()"));
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::Diagnostic()
//
// Run the camera through a test diagnostic. The IrTran-P device will
// always pass the diagnostic.
//
// Arguments:
//
// pBuffer - Pointer o diagnostic results data.
//
// Return Value:
//
// HRESULT - STI_OK
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::Diagnostic( IN OUT LPSTI_DIAG pBuffer )
{
WIAS_TRACE((g_hInst,"IrUsdDevice::Diagnostic()"));
//
// Initialize response buffer
//
pBuffer->dwStatusMask = 0;
memset( &pBuffer->sErrorInfo, 0, sizeof(pBuffer->sErrorInfo) );
pBuffer->sErrorInfo.dwGenericError = NOERROR;
pBuffer->sErrorInfo.dwVendorError = 0;
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::StartIrTranPThread()
//
//--------------------------------------------------------------------------
DWORD IrUsdDevice::StartIrTranPThread()
{
DWORD dwStatus = S_OK;
DWORD dwThread;
if (!m_hIrTranPThread)
{
m_hIrTranPThread = CreateThread( NULL, // Default security
0, // Default stack size
IrTranP, // IrTran-P protocol eng.
(LPVOID)this,
0, // Creation flags
&dwThread); // New thread ID.
if (!m_hIrTranPThread)
{
dwStatus = ::GetLastError();
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
}
}
return dwStatus;
}
//--------------------------------------------------------------------------
// IrUsdDevice::StopIrTranPThread()
//
//--------------------------------------------------------------------------
DWORD IrUsdDevice::StopIrTranPThread()
{
DWORD dwStatus;
//
// Shutdown the listen on IrCOMM, this will cause the IrTran-P thread
// to exit.
//
dwStatus = EnableDisableIrCOMM(TRUE); // TRUE == Disable.
m_hIrTranPThread = NULL;
return dwStatus;
}
//--------------------------------------------------------------------------
// IrUsdDevice::StartEventMonitorThread()
//
//--------------------------------------------------------------------------
DWORD IrUsdDevice::StartEventMonitorThread()
{
DWORD dwStatus = S_OK;
DWORD dwThread;
//
// Event to signal for registry changes:
//
if ((!m_hRegistryEvent)||(m_hRegistryEvent == INVALID_HANDLE_VALUE))
{
m_hRegistryEvent = CreateEvent( NULL, // Security
FALSE, // Auto-reset
FALSE, // Initially not set
NULL ); // No name
}
if (!m_hRegistryEvent)
{
dwStatus = ::GetLastError();
WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Event: %d",dwStatus));
return dwStatus;
}
//
// Start monitoring the registry to look for enable/disable changes
// for access to the IrCOMM port.
//
if (!m_hEventMonitorThread)
{
m_hEventMonitorThread = CreateThread(
NULL, // Default security
0, // Default stack size
EventMonitorThread,
(LPVOID)this,// Function data
0, // Creation flags
&dwThread ); // New thread ID
if (!m_hEventMonitorThread)
{
dwStatus = ::GetLastError();
WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Thread: %d",dwStatus));
}
}
return dwStatus;
}
//--------------------------------------------------------------------------
// IrUsdDevice::SetNotificationHandle()
//
// Starts and stops the event notification thread.
//
// Arguments:
//
// hEvent - Event to use in signaling WIA of events (like CONNECT etc.)
// If valid start the notification thread otherwise kill the
// notification thread.
//
// Return Value:
//
// HRESULT - STI_OK
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::SetNotificationHandle( IN HANDLE hEvent )
{
DWORD dwStatus;
HRESULT hr = STI_OK;
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle"));
EnterCriticalSection(&m_csShutdown);
//
// Are we starting or stopping the notification thread?
//
if (hEvent && (hEvent != INVALID_HANDLE_VALUE))
{
m_hSignalEvent = hEvent;
//
// Initialize to no event.
//
m_guidLastEvent = GUID_NULL;
#if FALSE
//
// Create the notification thread.
//
if (!m_hIrTranPThread)
{
DWORD dwThread;
m_hIrTranPThread = CreateThread(
NULL, // Default security
0, // Default stack size
IrTranP, // IrTran-P protocol eng.
(LPVOID)this,
0, // Creation flags
&dwThread); // New thread ID.
if (m_hIrTranPThread)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): Enabling IrTran-P"));
}
else
{
dwStatus = ::GetLastError();
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
hr = HRESULT_FROM_WIN32(dwStatus);
}
}
else
{
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): spurious IrTran-P thread"));
hr = STI_OK; // STIERR_UNSUPPORTED;
}
#endif
dwStatus = StartEventMonitorThread();
if (dwStatus)
{
hr = HRESULT_FROM_WIN32(dwStatus);
}
}
else
{
//
// Disable event notifications.
//
SetEvent(m_hShutdownEvent);
if (m_hIrTranPThread)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): stopping IrTran-P thread"));
UninitializeIrTranP(m_hIrTranPThread);
}
}
LeaveCriticalSection(&m_csShutdown);
return hr;
}
//--------------------------------------------------------------------------
// IrUsdDevice::GetNotificationData()
//
// WIA calls this function to get data on the event. Currently for IrTran-P,
// we get one of two events either WIA_EVENT_DEVICE_CONNECTED or
// WIA_EVENT_ITEM_CREATED.
//
// Arguments:
//
// pStiNotify - Pointer to event data.
//
// Return Value:
//
// HRESULT - STI_OK
// STIERR_NOEVENT (not currently returned).
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::GetNotificationData( IN OUT LPSTINOTIFY pStiNotify )
{
DWORD dwStatus;
WIAS_TRACE((g_hInst,"IrUsdDevice::GetNotificationData()"));
memset(pStiNotify,0,sizeof(STINOTIFY));
pStiNotify->dwSize = sizeof(STINOTIFY);
pStiNotify->guidNotificationCode = m_guidLastEvent;
//
// If we are to return a device connected then follow it by an item
// created event.
//
if (IsEqualGUID(m_guidLastEvent,WIA_EVENT_DEVICE_CONNECTED))
{
m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
if (!SetEvent(m_hSignalEvent))
{
dwStatus = ::GetLastError();
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
}
}
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::Escape()
//
// Used to issue a command to the device. IrTran-P doesn't support this.
//
// Arguments:
//
// EscapeFunction - Command to be issued.
// pInData - Input data to be passed with command.
// cbInDataSize - Size of input data.
// pOutData - Output data to be passed back from command.
// cbOutDataSize - Size of output data buffer.
// pcbActualData - Size of output data actually written.
//
// Return Value:
//
// HRESULT - STI_OK
// STIERR_UNSUPPORTED
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::Escape(
STI_RAW_CONTROL_CODE EscapeFunction,
LPVOID pInData,
DWORD cbInDataSize,
LPVOID pOutData,
DWORD cbOutDataSize,
LPDWORD pcbActualData )
{
WIAS_TRACE((g_hInst,"IrUsdDevice::Escape(): unsupported"));
//
// Write command to device if needed.
//
return STIERR_UNSUPPORTED;
}
//--------------------------------------------------------------------------
// IrUsdDevice::GetLastError()
//
// Get the last error from the device.
//
// Arguments:
//
// pdwLastDeviceError - Pointer to last error data.
//
// Return Value:
//
// HRESULT - STI_OK
// STIERR_INVALID_PARAM
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::GetLastError( OUT LPDWORD pdwLastDeviceError )
{
WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastError()"));
if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD)))
{
return STIERR_INVALID_PARAM;
}
*pdwLastDeviceError = m_dwLastOperationError;
return STI_OK;
}
/**************************************************************************\
* IrUsdDevice::GetLastErrorInfo
*
* Get extended error information from the device.
*
* Arguments:
*
* pLastErrorInfo - Pointer to extended device error data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastErrorInfo"));
if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
return STIERR_INVALID_PARAM;
}
pLastErrorInfo->dwGenericError = m_dwLastOperationError;
pLastErrorInfo->szExtendedErrorText[0] = '\0';
return STI_OK;
}
/**************************************************************************\
* IrUsdDevice::LockDevice
*
* Lock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::LockDevice(void)
{
return STI_OK;
}
/**************************************************************************\
* IrUsdDevice::UnLockDevice
*
* Unlock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::UnLockDevice(void)
{
return STI_OK;
}
/**************************************************************************\
* IrUsdDevice::RawReadData
*
* Read raw data from the device.
*
* Arguments:
*
* lpBuffer -
* lpdwNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::RawReadData(
LPVOID lpBuffer,
LPDWORD lpdwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadData"));
return STI_OK;
}
/**************************************************************************\
* IrUsdDevice::RawWriteData
*
* Write raw data to the device.
*
* Arguments:
*
* lpBuffer -
* dwNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP IrUsdDevice::RawWriteData(
LPVOID lpBuffer,
DWORD dwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteData"));
return STI_OK;
}
//--------------------------------------------------------------------------
// IrUsdDevice::RawReadCommand()
//
// Raw read of bytes directly from the camera. Not supported by IrTran-P
// device.
//
// Arguments:
//
// lpBuffer -
// lpdwNumberOfBytes -
// lpOverlapped -
//
// Return Value:
//
// HRESULT - STIERR_UNSUPPORTED
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::RawReadCommand(
IN LPVOID lpBuffer,
IN LPDWORD lpdwNumberOfBytes,
IN LPOVERLAPPED lpOverlapped)
{
WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadCommand() not supported"));
return STIERR_UNSUPPORTED;
}
//--------------------------------------------------------------------------
// IrUsdDevice::RawWriteCommand()
//
// Raw write of byte directly to a camera. Not supported by IrTran-P device.
//
// Arguments:
//
// lpBuffer -
// nNumberOfBytes -
// lpOverlapped -
//
// Return Value:
//
// HRESULT - STIERR_UNSUPPORTED
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::RawWriteCommand(
IN LPVOID lpBuffer,
IN DWORD nNumberOfBytes,
IN LPOVERLAPPED lpOverlapped )
{
WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteCommand(): not supported"));
return STIERR_UNSUPPORTED;
}
//--------------------------------------------------------------------------
// IrUsdDevice::Initialize()
//
// Initialize the device object.
//
// Arguments:
//
// pIStiDevControlNone -
// dwStiVersion -
// hParametersKey -
//
// Return Value:
//
// HRESULT STI_OK
// STIERR_INVALID_PARAM
//
//--------------------------------------------------------------------------
STDMETHODIMP IrUsdDevice::Initialize(
PSTIDEVICECONTROL pIStiDevControl,
DWORD dwStiVersion,
HKEY hParametersKey )
{
HRESULT hr = STI_OK;
UINT uiNameLen = 0;
CAMERA_STATUS camStatus;
WIAS_TRACE((g_hInst,"IrUsdDevice::Initialize"));
if (!pIStiDevControl)
{
WIAS_ERROR((g_hInst,"IrUsdDevice::Initialize(): invalid device control interface"));
return STIERR_INVALID_PARAM;
}
//
// Cache the device control interface:
//
m_pIStiDevControl = pIStiDevControl;
m_pIStiDevControl->AddRef();
//
// Try to open the camera only once here during Initialize:
//
hr = CamOpenCamera(&camStatus);
return hr;
}
//--------------------------------------------------------------------------
// IrUsdDevice::RunNotifications()
//
// Monitor changes to the source data file parent directory.
//
// Arguments:
//
// None
//
// Return Value:
//
// None
//
//--------------------------------------------------------------------------
VOID IrUsdDevice::RunNotifications(void)
{
//
// Start up camera event dlg
//
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications: start up event dlg"));
HWND hWnd = GetDesktopWindow();
int iret = DialogBoxParam( g_hInst,
MAKEINTRESOURCE(IDD_EVENT_DLG),
hWnd,
CameraEventDlgProc,
(LPARAM)this );
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, iret = 0x%lx",iret));
if (iret == -1)
{
DWORD dwStatus = ::GetLastError();
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, dlg error = 0x%lx",dwStatus));
}
}
//--------------------------------------------------------------------------
// NotificationsThread()
//
// Calls RunNotifications() to put up a dialog to start events.
//
// Arguments:
//
// lpParameter - Pointer to device object.
//
// Return Value:
//
// None
//
//--------------------------------------------------------------------------
VOID NotificationsThread( LPVOID lpParameter )
{
WIAS_TRACE((g_hInst,"NotificationsThread(): Start"));
IrUsdDevice *pThisDevice = (IrUsdDevice*)lpParameter;
pThisDevice->RunNotifications();
}
//--------------------------------------------------------------------------
// OpenIrTranPKey()
//
// Open and return a registry handle to the IrTranP key in the registry.
// This key will be monitored for changes in value.
//--------------------------------------------------------------------------
DWORD OpenIrTranPKey( HKEY *phRegistryKey )
{
DWORD dwStatus = 0;
DWORD dwDisposition = 0;
HKEY hKey;
*phRegistryKey = 0;
//
// If we've been called before, then we don't need to reopen the key.
//
if (g_hRegistryKey)
{
*phRegistryKey = g_hRegistryKey;
return 0;
}
if (RegCreateKeyEx(HKEY_CURRENT_USER,
SZ_REG_KEY_INFRARED,
0, // reserved MBZ
0, // class name
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0, // security attributes
&hKey,
&dwDisposition))
{
// Create failed.
dwStatus = GetLastError();
WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_INFRARED, dwStatus));
}
if (RegCloseKey(hKey))
{
// Close failed.
}
if (RegCreateKeyEx(HKEY_CURRENT_USER,
SZ_REG_KEY_IRTRANP,
0, // reserved, MBZ
0, // class name
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey, // security attributes
&dwDisposition))
{
// Create failed
dwStatus = GetLastError();
WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_IRTRANP, dwStatus));
}
*phRegistryKey = g_hRegistryKey = hKey;
return dwStatus;
}
//--------------------------------------------------------------------------
// CheckForIrCOMMEnabled()
//
// Check the registry to see if IrCOMM for IrTran-P is enabled, if it is
// then return TRUE, else return FALSE.
//
// Note: Don't close the key, it is maintained globally and will be closed
// at shutdown.
//--------------------------------------------------------------------------
BOOL CheckForIrCOMMEnabled( IN IrUsdDevice *pIrUsdDevice )
{
DWORD dwStatus;
DWORD dwType;
DWORD dwDisabled;
DWORD dwValueSize = sizeof(dwDisabled);
HKEY hKey;
dwStatus = OpenIrTranPKey(&hKey);
if (dwStatus)
{
// If the key doesn't exist, or can't be opened, then assume that
// we are enabled...
return TRUE;
}
//
// Check the value of the "DisableIrCOMM" value. Zero or missing value
// means fEnabled == TRUE, non-zero value means fEnabled == FALSE.
//
if (RegQueryValueEx( hKey, // IrTranP registry key
SZ_REG_DISABLE_IRCOMM,
NULL, // reserved, MB NULL
&dwType, // out, value type (expect: REG_DWORD)
(BYTE*)&dwDisabled, // out, value
&dwValueSize)) // in/out, size of value
{
// Query disabled flag registry value failed, assume enabled.
return TRUE;
}
if ((dwType == REG_DWORD) && (dwDisabled))
{
// Disabled flag is set.
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------------
// EventMonitorThread()
//
//--------------------------------------------------------------------------
DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice )
{
DWORD dwStatus = 0;
BOOL fEnabled;
HANDLE hHandles[2];
HKEY hRegistryKey;
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
//
// Get the IrTranP registry key. We will monitor this key for
// changes...
//
dwStatus = OpenIrTranPKey(&hRegistryKey);
if (dwStatus)
{
return dwStatus;
}
//
// We will Monitor two events. One for shutdown of the USD, the
// other for registry state changes (to enable/disable listen on
// IrCOMM).
//
hHandles[0] = pIrUsdDevice->m_hShutdownEvent;
hHandles[1] = pIrUsdDevice->m_hRegistryEvent;
while (TRUE)
{
fEnabled = CheckForIrCOMMEnabled(pIrUsdDevice);
if ((fEnabled) && (!pIrUsdDevice->m_hIrTranPThread))
{
// Start IrTran-P listen/protocol thread.
dwStatus = pIrUsdDevice->StartIrTranPThread();
}
else if (pIrUsdDevice->m_hIrTranPThread)
{
// Stop IrTran-P listen/protocol thread.
dwStatus = pIrUsdDevice->StopIrTranPThread();
}
dwStatus = RegNotifyChangeKeyValue( hRegistryKey, // IrTranP key
FALSE, // don't watch subtree
REG_NOTIFY_CHANGE_LAST_SET,
pIrUsdDevice->m_hRegistryEvent,
TRUE ); // Asynchronous
dwStatus = WaitForMultipleObjects( 2,
hHandles,
FALSE,
INFINITE);
if (dwStatus == WAIT_FAILED)
{
dwStatus = GetLastError();
break;
}
if (dwStatus == WAIT_OBJECT_0)
{
// Received a shutdown event. If the IrTranP thread is running
// then shut it down. Break out of this while loop to stop this
// monitor thread.
break;
}
if (dwStatus == WAIT_OBJECT_0+1)
{
// Received a registry change event. We'll continue around the
// while loop and check to see if IrTranP over IrCOMM has been
// disabled...
continue;
}
else if (dwStatus == WAIT_ABANDONED_0)
{
// Wait abandonded on the shutdown event
}
else if (dwStatus == WAIT_ABANDONED_0+1)
{
// Wait abandonded on the registry change event
}
}
return dwStatus;
}