Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1343 lines
36 KiB

  1. //------------------------------------------------------------------------------
  2. // Copyright (c) 1999-2000 Microsoft Corporation.
  3. //
  4. // device.cpp
  5. //
  6. // Implement IrTran-P device methods.
  7. //
  8. // Author:
  9. //
  10. // EdwardR 12-Aug-1999 Modeled from code by ReedB.
  11. //
  12. //------------------------------------------------------------------------------
  13. #include <windows.h>
  14. #include <tchar.h>
  15. #include <irthread.h>
  16. #include "ircamera.h"
  17. #include "resource.h"
  18. #include "tcamprop.h"
  19. // #include "/nt/private/windows/imagein/ui/uicommon/simstr.h"
  20. // #include "/nt/private/windows/imagein/ui/inc/shellext.h"
  21. extern HINSTANCE g_hInst;
  22. extern DWORD EnableDisableIrCOMM( IN BOOL fDisable ); // irtranp\irtranp.cpp
  23. DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice ); // Forward Ref.
  24. #define SZ_REG_KEY_INFRARED TEXT("Control Panel\\Infrared")
  25. #define SZ_REG_KEY_IRTRANP TEXT("Control Panel\\Infrared\\IrTranP")
  26. #define SZ_REG_DISABLE_IRCOMM TEXT("DisableIrCOMM")
  27. HKEY g_hRegistryKey = 0;
  28. //--------------------------------------------------------------------------
  29. // SignalWIA()
  30. //
  31. // Helper function used by the IrTran-P code to signal WIA that a new
  32. // picture has arrived.
  33. //
  34. // Arguments:
  35. //
  36. // pvIrUsdDevice -- Device object. IrTran-P only knows this as a void*.
  37. //
  38. //--------------------------------------------------------------------------
  39. DWORD SignalWIA( IN char *pszPathPlusFileName,
  40. IN void *pvIrUsdDevice )
  41. {
  42. HRESULT hr;
  43. DWORD dwStatus = 0;
  44. IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
  45. //
  46. // First, add the new picture to the tree representing the images:
  47. //
  48. if (pIrUsdDevice && pIrUsdDevice->IsInitialized())
  49. {
  50. TCHAR *ptszPath;
  51. TCHAR *ptszFileName;
  52. #ifdef UNICODE
  53. int iStatus;
  54. WCHAR wszTemp[MAX_PATH];
  55. iStatus = MultiByteToWideChar( CP_ACP,
  56. 0,
  57. pszPathPlusFileName,
  58. -1, // Auto-calculate length...
  59. wszTemp,
  60. MAX_PATH);
  61. ptszPath = wszTemp;
  62. ptszFileName = wcsrchr(wszTemp,L'\\');
  63. ptszFileName++;
  64. #else
  65. ptszPath = pszPathPlusFileName;
  66. ptszFileName = strrchr(pszPathPlusFileName,'\\');
  67. ptszFileName++;
  68. #endif
  69. IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
  70. IWiaDrvItem *pNewImage;
  71. hr = pIrUsdDevice->CreateItemFromFileName(
  72. WiaItemTypeFile | WiaItemTypeImage,
  73. ptszPath,
  74. ptszFileName,
  75. &pNewImage);
  76. if (!FAILED(hr))
  77. {
  78. IWiaDrvItem *pDrvItemRoot = pIrUsdDevice->GetDrvItemRoot();
  79. hr = pNewImage->AddItemToFolder(pDrvItemRoot);
  80. pNewImage->Release();
  81. }
  82. else
  83. {
  84. WIAS_ERROR((g_hInst,"SignalWIA(): CreateItemFromFileName() Failed: %x",hr));
  85. }
  86. }
  87. //
  88. // Now, signal WIA:
  89. //
  90. if (pIrUsdDevice)
  91. {
  92. DWORD dwNewTime = GetTickCount();
  93. DWORD dwDelta = dwNewTime - pIrUsdDevice->m_dwLastConnectTime;
  94. if (dwDelta > RECONNECT_TIMEOUT)
  95. {
  96. pIrUsdDevice->m_guidLastEvent = WIA_EVENT_DEVICE_CONNECTED;
  97. if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
  98. {
  99. dwStatus = GetLastError();
  100. WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
  101. }
  102. }
  103. else
  104. {
  105. pIrUsdDevice->m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
  106. if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
  107. {
  108. dwStatus = GetLastError();
  109. WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
  110. }
  111. }
  112. pIrUsdDevice->m_dwLastConnectTime = dwNewTime;
  113. }
  114. else
  115. {
  116. WIAS_ERROR((g_hInst,"SignalWIA(): null pvIrUsdDevice object"));
  117. return dwStatus;
  118. }
  119. //
  120. // Display IrCamera browser if it's not already up:
  121. //
  122. #if FALSE
  123. HINSTANCE hInst = LoadLibrary(TEXT("WIASHEXT.DLL"));
  124. if (hInst)
  125. {
  126. WIAMAKEFULLPIDLFORDEVICE pfn =
  127. (WIAMAKEFULLPIDLFORDEVICE)GetProcAddress(hInst, "MakeFullPidlForDevice");
  128. if (pfn)
  129. {
  130. LPITEMIDLIST pidl = NULL;
  131. pfn( pIrUsdDevice->m_bstrDeviceID, &pidl );
  132. if (pidl)
  133. {
  134. SHELLEXECUTEINFO sei;
  135. memset( &sei, 0, sizeof(sei) );
  136. sei.cbSize = sizeof(sei);
  137. // sei.hwnd = hDlg;
  138. sei.fMask = SEE_MASK_IDLIST;
  139. sei.nShow = SW_SHOW;
  140. sei.lpIDList = pidl;
  141. ShellExecuteEx( &sei );
  142. LPMALLOC pMalloc = NULL;
  143. if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc)
  144. {
  145. pMalloc->Free(pidl);
  146. pMalloc->Release();
  147. }
  148. }
  149. }
  150. FreeLibrary( hInst );
  151. }
  152. #endif
  153. return dwStatus;
  154. }
  155. //--------------------------------------------------------------------------
  156. // IrUsdDevice::IrUsdDevice()
  157. //
  158. // Device class constructor
  159. //
  160. // Arguments:
  161. //
  162. // punkOuter
  163. //
  164. // Return Value:
  165. //
  166. // None
  167. //
  168. //--------------------------------------------------------------------------
  169. IrUsdDevice::IrUsdDevice( LPUNKNOWN punkOuter ):
  170. m_cRef(1),
  171. m_punkOuter(NULL),
  172. m_dwLastConnectTime(0),
  173. m_fValid(FALSE),
  174. m_pIStiDevControl(NULL),
  175. m_hShutdownEvent(INVALID_HANDLE_VALUE),
  176. m_hRegistryEvent(INVALID_HANDLE_VALUE),
  177. m_hSignalEvent(INVALID_HANDLE_VALUE),
  178. m_hIrTranPThread(NULL),
  179. m_hEventMonitorThread(NULL),
  180. m_guidLastEvent(GUID_NULL),
  181. m_pIWiaEventCallback(NULL),
  182. m_pStiDevice(NULL),
  183. m_bstrDeviceID(NULL),
  184. m_bstrRootFullItemName(NULL),
  185. m_pIDrvItemRoot(NULL)
  186. {
  187. WIAS_TRACE((g_hInst,"IrUsdDevice::IrUsdDevice"));
  188. //
  189. // See if we are aggregated. If we are (almost always the case) save
  190. // pointer to the controlling Unknown , so subsequent calls will be
  191. // delegated. If not, set the same pointer to "this".
  192. //
  193. if (punkOuter)
  194. {
  195. m_punkOuter = punkOuter;
  196. }
  197. else
  198. {
  199. //
  200. // Cast below is needed in order to point to right virtual table
  201. //
  202. m_punkOuter = reinterpret_cast<IUnknown*>
  203. (static_cast<INonDelegatingUnknown*>
  204. (this));
  205. }
  206. }
  207. HRESULT IrUsdDevice::PrivateInitialize()
  208. {
  209. HRESULT hr = S_OK;
  210. __try {
  211. if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG))
  212. {
  213. hr = HRESULT_FROM_WIN32(::GetLastError());
  214. WIAS_ERROR((g_hInst,"IrUsdDevice::PrivateInitialize, create shutdown CritSect failed"));
  215. }
  216. }
  217. __except(EXCEPTION_EXECUTE_HANDLER) {
  218. hr = E_OUTOFMEMORY;
  219. }
  220. if(hr == S_OK) {
  221. //
  222. // Create event for syncronization of notifications shutdown.
  223. //
  224. m_hShutdownEvent = CreateEvent(NULL,
  225. FALSE,
  226. FALSE,
  227. NULL);
  228. if (m_hShutdownEvent && (INVALID_HANDLE_VALUE != m_hShutdownEvent))
  229. {
  230. m_fValid = TRUE;
  231. }
  232. else
  233. {
  234. hr = HRESULT_FROM_WIN32(::GetLastError());
  235. WIAS_ERROR((g_hInst,"IrUsdDevice::PrivateInitialize, create shutdown event failed"));
  236. }
  237. }
  238. return hr;
  239. }
  240. //------------------------------------------------------------------------
  241. // IrUsdDevice::~IrUsdDevice
  242. //
  243. // Device class destructor
  244. //
  245. // Arguments:
  246. //
  247. // None
  248. //
  249. // Return Value:
  250. //
  251. // None
  252. //
  253. //------------------------------------------------------------------------
  254. IrUsdDevice::~IrUsdDevice(void)
  255. {
  256. WIAS_TRACE((g_hInst,"IrUsdDevice::~IrUsdDevice"));
  257. //
  258. // Kill notification thread if it exists.
  259. //
  260. SetNotificationHandle(NULL);
  261. //
  262. // Close event for syncronization of notifications shutdown.
  263. //
  264. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE))
  265. {
  266. CloseHandle(m_hShutdownEvent);
  267. }
  268. if (m_hRegistryEvent && (m_hRegistryEvent != INVALID_HANDLE_VALUE))
  269. {
  270. CloseHandle(m_hRegistryEvent);
  271. }
  272. //
  273. // Release the device control interface.
  274. //
  275. if (m_pIStiDevControl)
  276. {
  277. m_pIStiDevControl->Release();
  278. m_pIStiDevControl = NULL;
  279. }
  280. //
  281. // WIA member destruction
  282. //
  283. // Cleanup the WIA event sink.
  284. //
  285. if (m_pIWiaEventCallback)
  286. {
  287. m_pIWiaEventCallback->Release();
  288. }
  289. //
  290. // Free the storage for the device ID.
  291. //
  292. if (m_bstrDeviceID)
  293. {
  294. SysFreeString(m_bstrDeviceID);
  295. }
  296. //
  297. // Release the objects supporting device property storage.
  298. //
  299. if (m_bstrRootFullItemName)
  300. {
  301. SysFreeString(m_bstrRootFullItemName);
  302. }
  303. //
  304. // Free the critical section.
  305. //
  306. DeleteCriticalSection(&m_csShutdown);
  307. }
  308. /**************************************************************************\
  309. * IrUsdDevice::GetCapabilities
  310. *
  311. * Get the device STI capabilities.
  312. *
  313. * Arguments:
  314. *
  315. * pUsdCaps - Pointer to USD capabilities data.
  316. *
  317. * Return Value:
  318. *
  319. * Status.
  320. *
  321. * History:
  322. *
  323. * 9/11/1998 Original Version
  324. *
  325. \**************************************************************************/
  326. STDMETHODIMP IrUsdDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
  327. {
  328. ZeroMemory(pUsdCaps, sizeof(*pUsdCaps));
  329. pUsdCaps->dwVersion = STI_VERSION;
  330. //
  331. // We do support device notifications, but do not requiring polling.
  332. //
  333. pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT;
  334. return STI_OK;
  335. }
  336. //--------------------------------------------------------------------------
  337. // IrUsdDevice::GetStatus()
  338. //
  339. // Query device online and/or event status.
  340. //
  341. // Arguments:
  342. //
  343. // pDevStatus - Pointer to device status data.
  344. //
  345. // Return Value:
  346. //
  347. // HRESULT - STI_OK
  348. // E_INVALIDARG
  349. //
  350. //--------------------------------------------------------------------------
  351. STDMETHODIMP IrUsdDevice::GetStatus( IN OUT PSTI_DEVICE_STATUS pDevStatus )
  352. {
  353. WIAS_TRACE((g_hInst,"IrUsdDevice::GetStatus()"));
  354. //
  355. // Validate parameters.
  356. //
  357. if (!pDevStatus)
  358. {
  359. WIAS_ERROR((g_hInst,"IrUsdDevice::GetStatus, NULL device status"));
  360. return E_INVALIDARG;
  361. }
  362. //
  363. // If we are asked, verify whether device is online.
  364. //
  365. pDevStatus->dwOnlineState = 0L;
  366. if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE)
  367. {
  368. //
  369. // The IrTran-P device is always on-line:
  370. //
  371. pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
  372. }
  373. //
  374. // If we are asked, verify state of event.
  375. //
  376. pDevStatus->dwEventHandlingState &= ~STI_EVENTHANDLING_PENDING;
  377. if (pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE)
  378. {
  379. //
  380. // Generate an event the first time we load.
  381. //
  382. if (m_bUsdLoadEvent)
  383. {
  384. pDevStatus->dwEventHandlingState = STI_EVENTHANDLING_PENDING;
  385. m_guidLastEvent = guidEventFirstLoaded;
  386. m_bUsdLoadEvent = FALSE;
  387. }
  388. //
  389. // event pending ???
  390. //
  391. }
  392. return STI_OK;
  393. }
  394. //--------------------------------------------------------------------------
  395. // IrUsdDevice::DeviceReset()
  396. //
  397. // Reset data file pointer to start of file. For IrTran-P, we don't need
  398. // to do anything.
  399. //
  400. // Arguments:
  401. //
  402. // None
  403. //
  404. // Return Value:
  405. //
  406. // HRESULT - STI_OK
  407. //
  408. //--------------------------------------------------------------------------
  409. STDMETHODIMP IrUsdDevice::DeviceReset(void)
  410. {
  411. WIAS_TRACE((g_hInst,"IrUsdDevice::DeviceReset()"));
  412. return STI_OK;
  413. }
  414. //--------------------------------------------------------------------------
  415. // IrUsdDevice::Diagnostic()
  416. //
  417. // Run the camera through a test diagnostic. The IrTran-P device will
  418. // always pass the diagnostic.
  419. //
  420. // Arguments:
  421. //
  422. // pBuffer - Pointer o diagnostic results data.
  423. //
  424. // Return Value:
  425. //
  426. // HRESULT - STI_OK
  427. //
  428. //--------------------------------------------------------------------------
  429. STDMETHODIMP IrUsdDevice::Diagnostic( IN OUT LPSTI_DIAG pBuffer )
  430. {
  431. WIAS_TRACE((g_hInst,"IrUsdDevice::Diagnostic()"));
  432. //
  433. // Initialize response buffer
  434. //
  435. pBuffer->dwStatusMask = 0;
  436. memset( &pBuffer->sErrorInfo, 0, sizeof(pBuffer->sErrorInfo) );
  437. pBuffer->sErrorInfo.dwGenericError = NOERROR;
  438. pBuffer->sErrorInfo.dwVendorError = 0;
  439. return STI_OK;
  440. }
  441. //--------------------------------------------------------------------------
  442. // IrUsdDevice::StartIrTranPThread()
  443. //
  444. //--------------------------------------------------------------------------
  445. DWORD IrUsdDevice::StartIrTranPThread()
  446. {
  447. DWORD dwStatus = S_OK;
  448. DWORD dwThread;
  449. if (!m_hIrTranPThread)
  450. {
  451. m_hIrTranPThread = CreateThread( NULL, // Default security
  452. 0, // Default stack size
  453. IrTranP, // IrTran-P protocol eng.
  454. (LPVOID)this,
  455. 0, // Creation flags
  456. &dwThread); // New thread ID.
  457. if (!m_hIrTranPThread)
  458. {
  459. dwStatus = ::GetLastError();
  460. WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
  461. }
  462. }
  463. return dwStatus;
  464. }
  465. //--------------------------------------------------------------------------
  466. // IrUsdDevice::StopIrTranPThread()
  467. //
  468. //--------------------------------------------------------------------------
  469. DWORD IrUsdDevice::StopIrTranPThread()
  470. {
  471. DWORD dwStatus;
  472. //
  473. // Shutdown the listen on IrCOMM, this will cause the IrTran-P thread
  474. // to exit.
  475. //
  476. dwStatus = EnableDisableIrCOMM(TRUE); // TRUE == Disable.
  477. m_hIrTranPThread = NULL;
  478. return dwStatus;
  479. }
  480. //--------------------------------------------------------------------------
  481. // IrUsdDevice::StartEventMonitorThread()
  482. //
  483. //--------------------------------------------------------------------------
  484. DWORD IrUsdDevice::StartEventMonitorThread()
  485. {
  486. DWORD dwStatus = S_OK;
  487. DWORD dwThread;
  488. //
  489. // Event to signal for registry changes:
  490. //
  491. if ((!m_hRegistryEvent)||(m_hRegistryEvent == INVALID_HANDLE_VALUE))
  492. {
  493. m_hRegistryEvent = CreateEvent( NULL, // Security
  494. FALSE, // Auto-reset
  495. FALSE, // Initially not set
  496. NULL ); // No name
  497. }
  498. if (!m_hRegistryEvent)
  499. {
  500. dwStatus = ::GetLastError();
  501. WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Event: %d",dwStatus));
  502. return dwStatus;
  503. }
  504. //
  505. // Start monitoring the registry to look for enable/disable changes
  506. // for access to the IrCOMM port.
  507. //
  508. if (!m_hEventMonitorThread)
  509. {
  510. m_hEventMonitorThread = CreateThread(
  511. NULL, // Default security
  512. 0, // Default stack size
  513. EventMonitorThread,
  514. (LPVOID)this,// Function data
  515. 0, // Creation flags
  516. &dwThread ); // New thread ID
  517. if (!m_hEventMonitorThread)
  518. {
  519. dwStatus = ::GetLastError();
  520. WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Thread: %d",dwStatus));
  521. }
  522. }
  523. return dwStatus;
  524. }
  525. //--------------------------------------------------------------------------
  526. // IrUsdDevice::SetNotificationHandle()
  527. //
  528. // Starts and stops the event notification thread.
  529. //
  530. // Arguments:
  531. //
  532. // hEvent - Event to use in signaling WIA of events (like CONNECT etc.)
  533. // If valid start the notification thread otherwise kill the
  534. // notification thread.
  535. //
  536. // Return Value:
  537. //
  538. // HRESULT - STI_OK
  539. //
  540. //--------------------------------------------------------------------------
  541. STDMETHODIMP IrUsdDevice::SetNotificationHandle( IN HANDLE hEvent )
  542. {
  543. DWORD dwStatus;
  544. HRESULT hr = STI_OK;
  545. WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle"));
  546. EnterCriticalSection(&m_csShutdown);
  547. //
  548. // Are we starting or stopping the notification thread?
  549. //
  550. if (hEvent && (hEvent != INVALID_HANDLE_VALUE))
  551. {
  552. m_hSignalEvent = hEvent;
  553. //
  554. // Initialize to no event.
  555. //
  556. m_guidLastEvent = GUID_NULL;
  557. #if FALSE
  558. //
  559. // Create the notification thread.
  560. //
  561. if (!m_hIrTranPThread)
  562. {
  563. DWORD dwThread;
  564. m_hIrTranPThread = CreateThread(
  565. NULL, // Default security
  566. 0, // Default stack size
  567. IrTranP, // IrTran-P protocol eng.
  568. (LPVOID)this,
  569. 0, // Creation flags
  570. &dwThread); // New thread ID.
  571. if (m_hIrTranPThread)
  572. {
  573. WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): Enabling IrTran-P"));
  574. }
  575. else
  576. {
  577. dwStatus = ::GetLastError();
  578. WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
  579. hr = HRESULT_FROM_WIN32(dwStatus);
  580. }
  581. }
  582. else
  583. {
  584. WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): spurious IrTran-P thread"));
  585. hr = STI_OK; // STIERR_UNSUPPORTED;
  586. }
  587. #endif
  588. dwStatus = StartEventMonitorThread();
  589. if (dwStatus)
  590. {
  591. hr = HRESULT_FROM_WIN32(dwStatus);
  592. }
  593. }
  594. else
  595. {
  596. //
  597. // Disable event notifications.
  598. //
  599. SetEvent(m_hShutdownEvent);
  600. if (m_hIrTranPThread)
  601. {
  602. WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): stopping IrTran-P thread"));
  603. UninitializeIrTranP(m_hIrTranPThread);
  604. }
  605. }
  606. LeaveCriticalSection(&m_csShutdown);
  607. return hr;
  608. }
  609. //--------------------------------------------------------------------------
  610. // IrUsdDevice::GetNotificationData()
  611. //
  612. // WIA calls this function to get data on the event. Currently for IrTran-P,
  613. // we get one of two events either WIA_EVENT_DEVICE_CONNECTED or
  614. // WIA_EVENT_ITEM_CREATED.
  615. //
  616. // Arguments:
  617. //
  618. // pStiNotify - Pointer to event data.
  619. //
  620. // Return Value:
  621. //
  622. // HRESULT - STI_OK
  623. // STIERR_NOEVENT (not currently returned).
  624. //
  625. //--------------------------------------------------------------------------
  626. STDMETHODIMP IrUsdDevice::GetNotificationData( IN OUT LPSTINOTIFY pStiNotify )
  627. {
  628. DWORD dwStatus;
  629. WIAS_TRACE((g_hInst,"IrUsdDevice::GetNotificationData()"));
  630. memset(pStiNotify,0,sizeof(STINOTIFY));
  631. pStiNotify->dwSize = sizeof(STINOTIFY);
  632. pStiNotify->guidNotificationCode = m_guidLastEvent;
  633. //
  634. // If we are to return a device connected then follow it by an item
  635. // created event.
  636. //
  637. if (IsEqualGUID(m_guidLastEvent,WIA_EVENT_DEVICE_CONNECTED))
  638. {
  639. m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
  640. if (!SetEvent(m_hSignalEvent))
  641. {
  642. dwStatus = ::GetLastError();
  643. WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
  644. }
  645. }
  646. return STI_OK;
  647. }
  648. //--------------------------------------------------------------------------
  649. // IrUsdDevice::Escape()
  650. //
  651. // Used to issue a command to the device. IrTran-P doesn't support this.
  652. //
  653. // Arguments:
  654. //
  655. // EscapeFunction - Command to be issued.
  656. // pInData - Input data to be passed with command.
  657. // cbInDataSize - Size of input data.
  658. // pOutData - Output data to be passed back from command.
  659. // cbOutDataSize - Size of output data buffer.
  660. // pcbActualData - Size of output data actually written.
  661. //
  662. // Return Value:
  663. //
  664. // HRESULT - STI_OK
  665. // STIERR_UNSUPPORTED
  666. //
  667. //--------------------------------------------------------------------------
  668. STDMETHODIMP IrUsdDevice::Escape(
  669. STI_RAW_CONTROL_CODE EscapeFunction,
  670. LPVOID pInData,
  671. DWORD cbInDataSize,
  672. LPVOID pOutData,
  673. DWORD cbOutDataSize,
  674. LPDWORD pcbActualData )
  675. {
  676. WIAS_TRACE((g_hInst,"IrUsdDevice::Escape(): unsupported"));
  677. //
  678. // Write command to device if needed.
  679. //
  680. return STIERR_UNSUPPORTED;
  681. }
  682. //--------------------------------------------------------------------------
  683. // IrUsdDevice::GetLastError()
  684. //
  685. // Get the last error from the device.
  686. //
  687. // Arguments:
  688. //
  689. // pdwLastDeviceError - Pointer to last error data.
  690. //
  691. // Return Value:
  692. //
  693. // HRESULT - STI_OK
  694. // STIERR_INVALID_PARAM
  695. //
  696. //--------------------------------------------------------------------------
  697. STDMETHODIMP IrUsdDevice::GetLastError( OUT LPDWORD pdwLastDeviceError )
  698. {
  699. WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastError()"));
  700. if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD)))
  701. {
  702. return STIERR_INVALID_PARAM;
  703. }
  704. *pdwLastDeviceError = m_dwLastOperationError;
  705. return STI_OK;
  706. }
  707. /**************************************************************************\
  708. * IrUsdDevice::GetLastErrorInfo
  709. *
  710. * Get extended error information from the device.
  711. *
  712. * Arguments:
  713. *
  714. * pLastErrorInfo - Pointer to extended device error data.
  715. *
  716. * Return Value:
  717. *
  718. * Status.
  719. *
  720. * History:
  721. *
  722. * 9/11/1998 Original Version
  723. *
  724. \**************************************************************************/
  725. STDMETHODIMP IrUsdDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
  726. {
  727. WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastErrorInfo"));
  728. if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
  729. return STIERR_INVALID_PARAM;
  730. }
  731. pLastErrorInfo->dwGenericError = m_dwLastOperationError;
  732. pLastErrorInfo->szExtendedErrorText[0] = '\0';
  733. return STI_OK;
  734. }
  735. /**************************************************************************\
  736. * IrUsdDevice::LockDevice
  737. *
  738. * Lock access to the device.
  739. *
  740. * Arguments:
  741. *
  742. * None
  743. *
  744. * Return Value:
  745. *
  746. * Status.
  747. *
  748. * History:
  749. *
  750. * 9/11/1998 Original Version
  751. *
  752. \**************************************************************************/
  753. STDMETHODIMP IrUsdDevice::LockDevice(void)
  754. {
  755. return STI_OK;
  756. }
  757. /**************************************************************************\
  758. * IrUsdDevice::UnLockDevice
  759. *
  760. * Unlock access to the device.
  761. *
  762. * Arguments:
  763. *
  764. * None
  765. *
  766. * Return Value:
  767. *
  768. * Status.
  769. *
  770. * History:
  771. *
  772. * 9/11/1998 Original Version
  773. *
  774. \**************************************************************************/
  775. STDMETHODIMP IrUsdDevice::UnLockDevice(void)
  776. {
  777. return STI_OK;
  778. }
  779. /**************************************************************************\
  780. * IrUsdDevice::RawReadData
  781. *
  782. * Read raw data from the device.
  783. *
  784. * Arguments:
  785. *
  786. * lpBuffer -
  787. * lpdwNumberOfBytes -
  788. * lpOverlapped -
  789. *
  790. * Return Value:
  791. *
  792. * Status.
  793. *
  794. * History:
  795. *
  796. * 9/11/1998 Original Version
  797. *
  798. \**************************************************************************/
  799. STDMETHODIMP IrUsdDevice::RawReadData(
  800. LPVOID lpBuffer,
  801. LPDWORD lpdwNumberOfBytes,
  802. LPOVERLAPPED lpOverlapped)
  803. {
  804. WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadData"));
  805. return STI_OK;
  806. }
  807. /**************************************************************************\
  808. * IrUsdDevice::RawWriteData
  809. *
  810. * Write raw data to the device.
  811. *
  812. * Arguments:
  813. *
  814. * lpBuffer -
  815. * dwNumberOfBytes -
  816. * lpOverlapped -
  817. *
  818. * Return Value:
  819. *
  820. * Status.
  821. *
  822. * History:
  823. *
  824. * 9/11/1998 Original Version
  825. *
  826. \**************************************************************************/
  827. STDMETHODIMP IrUsdDevice::RawWriteData(
  828. LPVOID lpBuffer,
  829. DWORD dwNumberOfBytes,
  830. LPOVERLAPPED lpOverlapped)
  831. {
  832. WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteData"));
  833. return STI_OK;
  834. }
  835. //--------------------------------------------------------------------------
  836. // IrUsdDevice::RawReadCommand()
  837. //
  838. // Raw read of bytes directly from the camera. Not supported by IrTran-P
  839. // device.
  840. //
  841. // Arguments:
  842. //
  843. // lpBuffer -
  844. // lpdwNumberOfBytes -
  845. // lpOverlapped -
  846. //
  847. // Return Value:
  848. //
  849. // HRESULT - STIERR_UNSUPPORTED
  850. //
  851. //--------------------------------------------------------------------------
  852. STDMETHODIMP IrUsdDevice::RawReadCommand(
  853. IN LPVOID lpBuffer,
  854. IN LPDWORD lpdwNumberOfBytes,
  855. IN LPOVERLAPPED lpOverlapped)
  856. {
  857. WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadCommand() not supported"));
  858. return STIERR_UNSUPPORTED;
  859. }
  860. //--------------------------------------------------------------------------
  861. // IrUsdDevice::RawWriteCommand()
  862. //
  863. // Raw write of byte directly to a camera. Not supported by IrTran-P device.
  864. //
  865. // Arguments:
  866. //
  867. // lpBuffer -
  868. // nNumberOfBytes -
  869. // lpOverlapped -
  870. //
  871. // Return Value:
  872. //
  873. // HRESULT - STIERR_UNSUPPORTED
  874. //
  875. //--------------------------------------------------------------------------
  876. STDMETHODIMP IrUsdDevice::RawWriteCommand(
  877. IN LPVOID lpBuffer,
  878. IN DWORD nNumberOfBytes,
  879. IN LPOVERLAPPED lpOverlapped )
  880. {
  881. WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteCommand(): not supported"));
  882. return STIERR_UNSUPPORTED;
  883. }
  884. //--------------------------------------------------------------------------
  885. // IrUsdDevice::Initialize()
  886. //
  887. // Initialize the device object.
  888. //
  889. // Arguments:
  890. //
  891. // pIStiDevControlNone -
  892. // dwStiVersion -
  893. // hParametersKey -
  894. //
  895. // Return Value:
  896. //
  897. // HRESULT STI_OK
  898. // STIERR_INVALID_PARAM
  899. //
  900. //--------------------------------------------------------------------------
  901. STDMETHODIMP IrUsdDevice::Initialize(
  902. PSTIDEVICECONTROL pIStiDevControl,
  903. DWORD dwStiVersion,
  904. HKEY hParametersKey )
  905. {
  906. HRESULT hr = STI_OK;
  907. UINT uiNameLen = 0;
  908. CAMERA_STATUS camStatus;
  909. WIAS_TRACE((g_hInst,"IrUsdDevice::Initialize"));
  910. if (!pIStiDevControl)
  911. {
  912. WIAS_ERROR((g_hInst,"IrUsdDevice::Initialize(): invalid device control interface"));
  913. return STIERR_INVALID_PARAM;
  914. }
  915. //
  916. // Cache the device control interface:
  917. //
  918. m_pIStiDevControl = pIStiDevControl;
  919. m_pIStiDevControl->AddRef();
  920. //
  921. // Try to open the camera only once here during Initialize:
  922. //
  923. hr = CamOpenCamera(&camStatus);
  924. return hr;
  925. }
  926. //--------------------------------------------------------------------------
  927. // IrUsdDevice::RunNotifications()
  928. //
  929. // Monitor changes to the source data file parent directory.
  930. //
  931. // Arguments:
  932. //
  933. // None
  934. //
  935. // Return Value:
  936. //
  937. // None
  938. //
  939. //--------------------------------------------------------------------------
  940. VOID IrUsdDevice::RunNotifications(void)
  941. {
  942. //
  943. // Start up camera event dlg
  944. //
  945. WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications: start up event dlg"));
  946. HWND hWnd = GetDesktopWindow();
  947. int iret = DialogBoxParam( g_hInst,
  948. MAKEINTRESOURCE(IDD_EVENT_DLG),
  949. hWnd,
  950. CameraEventDlgProc,
  951. (LPARAM)this );
  952. WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, iret = 0x%lx",iret));
  953. if (iret == -1)
  954. {
  955. DWORD dwStatus = ::GetLastError();
  956. WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, dlg error = 0x%lx",dwStatus));
  957. }
  958. }
  959. //--------------------------------------------------------------------------
  960. // NotificationsThread()
  961. //
  962. // Calls RunNotifications() to put up a dialog to start events.
  963. //
  964. // Arguments:
  965. //
  966. // lpParameter - Pointer to device object.
  967. //
  968. // Return Value:
  969. //
  970. // None
  971. //
  972. //--------------------------------------------------------------------------
  973. VOID NotificationsThread( LPVOID lpParameter )
  974. {
  975. WIAS_TRACE((g_hInst,"NotificationsThread(): Start"));
  976. IrUsdDevice *pThisDevice = (IrUsdDevice*)lpParameter;
  977. pThisDevice->RunNotifications();
  978. }
  979. //--------------------------------------------------------------------------
  980. // OpenIrTranPKey()
  981. //
  982. // Open and return a registry handle to the IrTranP key in the registry.
  983. // This key will be monitored for changes in value.
  984. //--------------------------------------------------------------------------
  985. DWORD OpenIrTranPKey( HKEY *phRegistryKey )
  986. {
  987. DWORD dwStatus = 0;
  988. DWORD dwDisposition = 0;
  989. HKEY hKey;
  990. *phRegistryKey = 0;
  991. //
  992. // If we've been called before, then we don't need to reopen the key.
  993. //
  994. if (g_hRegistryKey)
  995. {
  996. *phRegistryKey = g_hRegistryKey;
  997. return 0;
  998. }
  999. if (RegCreateKeyEx(HKEY_CURRENT_USER,
  1000. SZ_REG_KEY_INFRARED,
  1001. 0, // reserved MBZ
  1002. 0, // class name
  1003. REG_OPTION_NON_VOLATILE,
  1004. KEY_ALL_ACCESS,
  1005. 0, // security attributes
  1006. &hKey,
  1007. &dwDisposition))
  1008. {
  1009. // Create failed.
  1010. dwStatus = GetLastError();
  1011. WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_INFRARED, dwStatus));
  1012. }
  1013. if (RegCloseKey(hKey))
  1014. {
  1015. // Close failed.
  1016. }
  1017. if (RegCreateKeyEx(HKEY_CURRENT_USER,
  1018. SZ_REG_KEY_IRTRANP,
  1019. 0, // reserved, MBZ
  1020. 0, // class name
  1021. REG_OPTION_NON_VOLATILE,
  1022. KEY_ALL_ACCESS,
  1023. 0,
  1024. &hKey, // security attributes
  1025. &dwDisposition))
  1026. {
  1027. // Create failed
  1028. dwStatus = GetLastError();
  1029. WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_IRTRANP, dwStatus));
  1030. }
  1031. *phRegistryKey = g_hRegistryKey = hKey;
  1032. return dwStatus;
  1033. }
  1034. //--------------------------------------------------------------------------
  1035. // CheckForIrCOMMEnabled()
  1036. //
  1037. // Check the registry to see if IrCOMM for IrTran-P is enabled, if it is
  1038. // then return TRUE, else return FALSE.
  1039. //
  1040. // Note: Don't close the key, it is maintained globally and will be closed
  1041. // at shutdown.
  1042. //--------------------------------------------------------------------------
  1043. BOOL CheckForIrCOMMEnabled( IN IrUsdDevice *pIrUsdDevice )
  1044. {
  1045. DWORD dwStatus;
  1046. DWORD dwType;
  1047. DWORD dwDisabled;
  1048. DWORD dwValueSize = sizeof(dwDisabled);
  1049. HKEY hKey;
  1050. dwStatus = OpenIrTranPKey(&hKey);
  1051. if (dwStatus)
  1052. {
  1053. // If the key doesn't exist, or can't be opened, then assume that
  1054. // we are enabled...
  1055. return TRUE;
  1056. }
  1057. //
  1058. // Check the value of the "DisableIrCOMM" value. Zero or missing value
  1059. // means fEnabled == TRUE, non-zero value means fEnabled == FALSE.
  1060. //
  1061. if (RegQueryValueEx( hKey, // IrTranP registry key
  1062. SZ_REG_DISABLE_IRCOMM,
  1063. NULL, // reserved, MB NULL
  1064. &dwType, // out, value type (expect: REG_DWORD)
  1065. (BYTE*)&dwDisabled, // out, value
  1066. &dwValueSize)) // in/out, size of value
  1067. {
  1068. // Query disabled flag registry value failed, assume enabled.
  1069. return TRUE;
  1070. }
  1071. if ((dwType == REG_DWORD) && (dwDisabled))
  1072. {
  1073. // Disabled flag is set.
  1074. return FALSE;
  1075. }
  1076. return TRUE;
  1077. }
  1078. //--------------------------------------------------------------------------
  1079. // EventMonitorThread()
  1080. //
  1081. //--------------------------------------------------------------------------
  1082. DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice )
  1083. {
  1084. DWORD dwStatus = 0;
  1085. BOOL fEnabled;
  1086. HANDLE hHandles[2];
  1087. HKEY hRegistryKey;
  1088. IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
  1089. //
  1090. // Get the IrTranP registry key. We will monitor this key for
  1091. // changes...
  1092. //
  1093. dwStatus = OpenIrTranPKey(&hRegistryKey);
  1094. if (dwStatus)
  1095. {
  1096. return dwStatus;
  1097. }
  1098. //
  1099. // We will Monitor two events. One for shutdown of the USD, the
  1100. // other for registry state changes (to enable/disable listen on
  1101. // IrCOMM).
  1102. //
  1103. hHandles[0] = pIrUsdDevice->m_hShutdownEvent;
  1104. hHandles[1] = pIrUsdDevice->m_hRegistryEvent;
  1105. while (TRUE)
  1106. {
  1107. fEnabled = CheckForIrCOMMEnabled(pIrUsdDevice);
  1108. if ((fEnabled) && (!pIrUsdDevice->m_hIrTranPThread))
  1109. {
  1110. // Start IrTran-P listen/protocol thread.
  1111. dwStatus = pIrUsdDevice->StartIrTranPThread();
  1112. }
  1113. else if (pIrUsdDevice->m_hIrTranPThread)
  1114. {
  1115. // Stop IrTran-P listen/protocol thread.
  1116. dwStatus = pIrUsdDevice->StopIrTranPThread();
  1117. }
  1118. dwStatus = RegNotifyChangeKeyValue( hRegistryKey, // IrTranP key
  1119. FALSE, // don't watch subtree
  1120. REG_NOTIFY_CHANGE_LAST_SET,
  1121. pIrUsdDevice->m_hRegistryEvent,
  1122. TRUE ); // Asynchronous
  1123. dwStatus = WaitForMultipleObjects( 2,
  1124. hHandles,
  1125. FALSE,
  1126. INFINITE);
  1127. if (dwStatus == WAIT_FAILED)
  1128. {
  1129. dwStatus = GetLastError();
  1130. break;
  1131. }
  1132. if (dwStatus == WAIT_OBJECT_0)
  1133. {
  1134. // Received a shutdown event. If the IrTranP thread is running
  1135. // then shut it down. Break out of this while loop to stop this
  1136. // monitor thread.
  1137. break;
  1138. }
  1139. if (dwStatus == WAIT_OBJECT_0+1)
  1140. {
  1141. // Received a registry change event. We'll continue around the
  1142. // while loop and check to see if IrTranP over IrCOMM has been
  1143. // disabled...
  1144. continue;
  1145. }
  1146. else if (dwStatus == WAIT_ABANDONED_0)
  1147. {
  1148. // Wait abandonded on the shutdown event
  1149. }
  1150. else if (dwStatus == WAIT_ABANDONED_0+1)
  1151. {
  1152. // Wait abandonded on the registry change event
  1153. }
  1154. }
  1155. return dwStatus;
  1156. }