Leaked source code of windows server 2003
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.

1542 lines
45 KiB

  1. /*++
  2. Copyright (C) 1999- Microsoft Corporation
  3. Module Name:
  4. camusb.cpp
  5. Abstract:
  6. This module implements CUsbCamera object
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "ptppch.h"
  12. #include <atlbase.h>
  13. #include <atlconv.h>
  14. #include <devioctl.h>
  15. //
  16. // Private IOCTL to workaround #446466 (Whistler)
  17. //
  18. #define IOCTL_SEND_USB_REQUEST_PTP CTL_CODE(FILE_DEVICE_USB_SCAN,IOCTL_INDEX+20,METHOD_BUFFERED,FILE_ANY_ACCESS)
  19. //
  20. // Constructor for CUsbCamera
  21. //
  22. CUsbCamera::CUsbCamera() :
  23. m_hUSB(NULL),
  24. m_hEventUSB(NULL),
  25. m_hEventCancel(NULL),
  26. m_hEventRead(NULL),
  27. m_pUsbData(NULL),
  28. m_UsbDataSize(0),
  29. m_prevOpCode(0),
  30. m_prevTranId(0)
  31. {
  32. DBG_FN("CUsbCamera::CUsbCamera");
  33. memset(&m_EndpointInfo, NULL, sizeof(m_EndpointInfo));
  34. }
  35. CUsbCamera::~CUsbCamera()
  36. {
  37. }
  38. //
  39. // This function takes care of USB-specific processing for opening
  40. // a connection with a device.
  41. //
  42. // Input:
  43. // DevicePortName -- name used to access device via CreateFile
  44. // pIPTPEventCB -- IWiaPTPEventCallback interface pointer
  45. //
  46. HRESULT
  47. CUsbCamera::Open(
  48. LPWSTR DevicePortName,
  49. PTPEventCallback pPTPEventCB,
  50. PTPDataCallback pPTPDataCB,
  51. LPVOID pEventParam,
  52. BOOL bEnableEvents
  53. )
  54. {
  55. USES_CONVERSION;
  56. DBG_FN("CUsbCamera::Open");
  57. HRESULT hr = S_OK;
  58. //
  59. // Call the base class Open function first
  60. //
  61. hr = CPTPCamera::Open(DevicePortName, pPTPEventCB, pPTPDataCB, pEventParam, bEnableEvents);
  62. if (FAILED(hr))
  63. {
  64. wiauDbgError("Open", "base class Open failed");
  65. return hr;
  66. }
  67. //
  68. // Open another handle to talk with the device, to work around possible
  69. // bug in Usbscan.sys
  70. //
  71. m_hEventUSB = ::CreateFile(W2T(DevicePortName), // file name
  72. GENERIC_READ | GENERIC_WRITE, // desired access
  73. 0, // sharing mode
  74. NULL, // security descriptor
  75. OPEN_EXISTING, // creation disposition
  76. FILE_FLAG_OVERLAPPED, // file attributes
  77. NULL // template file
  78. );
  79. if (m_hEventUSB == INVALID_HANDLE_VALUE)
  80. {
  81. hr = HRESULT_FROM_WIN32(::GetLastError());
  82. wiauDbgErrorHr(hr, "Open", "CreateFile failed");
  83. m_hUSB = NULL;
  84. return hr;
  85. }
  86. //
  87. // Open a handle to talk with the device
  88. //
  89. m_hUSB = ::CreateFile(W2T(DevicePortName), // file name
  90. GENERIC_READ | GENERIC_WRITE, // desired access
  91. 0, // sharing mode
  92. NULL, // security descriptor
  93. OPEN_EXISTING, // creation disposition
  94. 0, // file attributes
  95. NULL // template file
  96. );
  97. if (m_hUSB == INVALID_HANDLE_VALUE)
  98. {
  99. hr = HRESULT_FROM_WIN32(::GetLastError());
  100. wiauDbgErrorHr(hr, "Open", "Second CreateFile failed");
  101. m_hUSB = NULL;
  102. return hr;
  103. }
  104. //
  105. // Create event handle that will cancel interrupt pipe read
  106. //
  107. m_hEventCancel = CreateEvent(NULL, TRUE, FALSE, NULL);
  108. if (!m_hEventCancel)
  109. {
  110. hr = HRESULT_FROM_WIN32(::GetLastError());
  111. wiauDbgErrorHr(hr, "Open", "CreateEvent failed");
  112. return hr;
  113. }
  114. //
  115. // Create event handle for reading interrupt pipe
  116. //
  117. m_hEventRead = CreateEvent(NULL, TRUE, FALSE, NULL);
  118. if (!m_hEventRead)
  119. {
  120. hr = HRESULT_FROM_WIN32(::GetLastError());
  121. wiauDbgErrorHr(hr, "Open", "CreateEvent failed");
  122. return hr;
  123. }
  124. //
  125. // Set up array used by WaitForMultipleObjects
  126. //
  127. m_EventHandles[0] = m_hEventCancel;
  128. m_EventHandles[1] = m_hEventRead;
  129. //
  130. // Get the pipe configuration information of each pipe
  131. //
  132. USBSCAN_PIPE_CONFIGURATION PipeCfg;
  133. DWORD BytesReturned;
  134. if (!DeviceIoControl(m_hUSB,
  135. IOCTL_GET_PIPE_CONFIGURATION,
  136. NULL,
  137. 0,
  138. &PipeCfg,
  139. sizeof(PipeCfg),
  140. &BytesReturned,
  141. NULL))
  142. {
  143. hr = HRESULT_FROM_WIN32(::GetLastError());
  144. wiauDbgErrorHr(hr, "Open", "get pipe config DeviceIoControl failed");
  145. return hr;
  146. }
  147. //
  148. // Loop through the pipe configurations and store the information we'll need
  149. // later (maximum packet size and address). Also make sure there is at least
  150. // one endpoint of each: bulk-in, bulk-out, and interrupt.
  151. //
  152. USBSCAN_PIPE_INFORMATION *pPipeInfo; // Temporary pointer
  153. for (ULONG count = 0; count < PipeCfg.NumberOfPipes; count++)
  154. {
  155. pPipeInfo = &PipeCfg.PipeInfo[count];
  156. switch (pPipeInfo->PipeType)
  157. {
  158. case USBSCAN_PIPE_BULK:
  159. if (pPipeInfo->EndpointAddress & BULKIN_FLAG)
  160. {
  161. m_EndpointInfo.BulkInMaxSize = pPipeInfo->MaximumPacketSize;
  162. m_EndpointInfo.BulkInAddress = pPipeInfo->EndpointAddress;
  163. wiauDbgTrace("Open", "found a bulk-in endpoint, address = 0x%04x, packet size = %d, index = %d",
  164. pPipeInfo->EndpointAddress, pPipeInfo->MaximumPacketSize, count);
  165. }
  166. else
  167. {
  168. m_EndpointInfo.BulkOutMaxSize = pPipeInfo->MaximumPacketSize;
  169. m_EndpointInfo.BulkOutAddress = pPipeInfo->EndpointAddress;
  170. wiauDbgTrace("Open", "found a bulk-out endpoint, address = 0x%04x, packet size = %d, index = %d",
  171. pPipeInfo->EndpointAddress, pPipeInfo->MaximumPacketSize, count);
  172. }
  173. break;
  174. case USBSCAN_PIPE_INTERRUPT:
  175. m_EndpointInfo.InterruptMaxSize = pPipeInfo->MaximumPacketSize;
  176. m_EndpointInfo.InterruptAddress = pPipeInfo->EndpointAddress;
  177. wiauDbgTrace("Open", "found an interrupt endpoint, address = 0x%02x, packet size = %d, index = %d",
  178. pPipeInfo->EndpointAddress, pPipeInfo->MaximumPacketSize, count);
  179. break;
  180. default:
  181. wiauDbgTrace("Open", "found an endpoint of unknown type, type = 0x%04x, address = 0x%02x, packet size = %d, index = %d",
  182. pPipeInfo->PipeType, pPipeInfo->EndpointAddress, pPipeInfo->MaximumPacketSize, count);
  183. }
  184. }
  185. //
  186. // Each of these endpoints must be present and have non-zero packet size
  187. //
  188. if (!m_EndpointInfo.BulkInMaxSize ||
  189. !m_EndpointInfo.BulkOutMaxSize ||
  190. !m_EndpointInfo.InterruptMaxSize)
  191. {
  192. wiauDbgError("Open", "At least one endpoint is invalid");
  193. return E_FAIL;
  194. }
  195. //
  196. // Allocate a re-usable buffer for handling the USB header during reads
  197. // and writes. It needs to be large enough to hold one packet and large
  198. // enough to hold a USB header.
  199. //
  200. m_UsbDataSize = max(m_EndpointInfo.BulkInMaxSize, m_EndpointInfo.BulkOutMaxSize);
  201. while (m_UsbDataSize < sizeof(m_pUsbData->Header))
  202. {
  203. m_UsbDataSize += m_UsbDataSize;
  204. }
  205. m_pUsbData = (PUSB_PTP_DATA) new BYTE[m_UsbDataSize];
  206. if (!m_pUsbData)
  207. {
  208. wiauDbgError("Open", "memory allocation failed");
  209. return E_OUTOFMEMORY;
  210. }
  211. return hr;
  212. }
  213. //
  214. // This function closes the connection to the camera
  215. //
  216. HRESULT
  217. CUsbCamera::Close()
  218. {
  219. DBG_FN("CUsbCamera::Close");
  220. HRESULT hr = S_OK;
  221. //
  222. // Call the base class Close function first
  223. //
  224. hr = CPTPCamera::Close();
  225. if (FAILED(hr))
  226. {
  227. wiauDbgError("Close", "base class Close failed");
  228. }
  229. //
  230. // Signal event to cancel interrupt pipe I/O
  231. //
  232. if (!SetEvent(m_hEventCancel))
  233. {
  234. hr = HRESULT_FROM_WIN32(::GetLastError());
  235. wiauDbgErrorHr(hr, "Close", "SetEvent failed");
  236. } else {
  237. if (m_bEventsEnabled)
  238. {
  239. //
  240. // We need to wait until event thread finishes, otherwise driver DLL may get unloaded
  241. // with a running thread in it
  242. //
  243. DWORD ret = WaitForSingleObject(m_hEventThread, INFINITE);
  244. if (ret != WAIT_OBJECT_0) {
  245. hr = HRESULT_FROM_WIN32(::GetLastError());
  246. wiauDbgErrorHr(hr, "Close", "WaitForSingleObject failed");
  247. }
  248. }
  249. }
  250. //
  251. // Close handle to the event thread
  252. //
  253. if (m_hEventThread)
  254. {
  255. CloseHandle(m_hEventThread);
  256. m_hEventThread = NULL;
  257. }
  258. //
  259. // Close the file handles and event handles
  260. //
  261. if (m_hUSB)
  262. {
  263. CloseHandle(m_hUSB);
  264. m_hUSB = NULL;
  265. }
  266. if (m_hEventUSB)
  267. {
  268. CloseHandle(m_hEventUSB);
  269. m_hEventUSB = NULL;
  270. }
  271. if (m_hEventCancel)
  272. {
  273. CloseHandle(m_hEventCancel);
  274. m_hEventCancel = NULL;
  275. }
  276. if (m_hEventRead)
  277. {
  278. CloseHandle(m_hEventRead);
  279. m_hEventRead = NULL;
  280. }
  281. //
  282. // Free memory used for reading/writing data
  283. //
  284. if (m_pUsbData)
  285. {
  286. delete[] (BYTE*)m_pUsbData;
  287. m_pUsbData = NULL;
  288. }
  289. return hr;
  290. }
  291. //
  292. // This function writes a command buffer to the device
  293. //
  294. // Input:
  295. // pCommand -- pointer to the command to send
  296. // NumParams -- number of parameters in the command
  297. //
  298. HRESULT
  299. CUsbCamera::SendCommand(
  300. PTP_COMMAND *pCommand,
  301. UINT NumParams
  302. )
  303. {
  304. DBG_FN("CUsbCamera::SendCommand");
  305. HRESULT hr = S_OK;
  306. if (!pCommand || NumParams > COMMAND_NUMPARAMS_MAX)
  307. {
  308. wiauDbgError("SendCommand", "invalid arg");
  309. return E_INVALIDARG;
  310. }
  311. //
  312. // Check for the reset command, and send it via the control pipe instead
  313. //
  314. if (pCommand->OpCode == PTP_OPCODE_RESETDEVICE)
  315. {
  316. wiauDbgTrace("SendCommand", "sending reset request");
  317. hr = ResetDevice();
  318. if (FAILED(hr))
  319. {
  320. wiauDbgError("SendCommand", "ResetDevice failed");
  321. return hr;
  322. }
  323. }
  324. else
  325. {
  326. //
  327. // Put the PTP command into a USB container
  328. //
  329. m_UsbCommand.Header.Len = sizeof(m_UsbCommand.Header) + sizeof(DWORD) * NumParams;
  330. m_UsbCommand.Header.Type = PTPCONTAINER_TYPE_COMMAND;
  331. m_UsbCommand.Header.Code = pCommand->OpCode;
  332. m_UsbCommand.Header.TransactionId = pCommand->TransactionId;
  333. if (NumParams > 0)
  334. {
  335. memcpy(m_UsbCommand.Params, pCommand->Params, sizeof(DWORD) * NumParams);
  336. }
  337. //
  338. // Send the command to the device
  339. //
  340. DWORD BytesWritten = 0;
  341. wiauDbgTrace("SendCommand", "writing command");
  342. if (!WriteFile(m_hUSB, &m_UsbCommand, m_UsbCommand.Header.Len, &BytesWritten, NULL))
  343. {
  344. hr = HRESULT_FROM_WIN32(::GetLastError());
  345. wiauDbgErrorHr(hr, "SendCommand", "WriteFile failed");
  346. return hr;
  347. }
  348. if (BytesWritten != m_UsbCommand.Header.Len)
  349. {
  350. wiauDbgError("SendCommand", "wrong amount of data written = %d", BytesWritten);
  351. return E_FAIL;
  352. }
  353. //
  354. // If the amount written is a multiple of the packet size, send a null packet
  355. //
  356. if (m_UsbCommand.Header.Len % m_EndpointInfo.BulkOutMaxSize == 0)
  357. {
  358. wiauDbgTrace("SendCommand", "sending null packet");
  359. if (!WriteFile(m_hUSB, NULL, 0, &BytesWritten, NULL))
  360. {
  361. hr = HRESULT_FROM_WIN32(::GetLastError());
  362. wiauDbgErrorHr(hr, "SendCommand", "second WriteFile failed");
  363. return hr;
  364. }
  365. if (BytesWritten != 0)
  366. {
  367. wiauDbgError("SendCommand", "wrong amount of data written = %d -", BytesWritten);
  368. return E_FAIL;
  369. }
  370. }
  371. }
  372. //
  373. // Save the opcode, because we need it for the data container header
  374. //
  375. m_prevOpCode = pCommand->OpCode;
  376. m_prevTranId = pCommand->TransactionId;
  377. wiauDbgTrace("SendCommand", "command successfully sent");
  378. return hr;
  379. }
  380. //
  381. // This function reads bulk data from the device
  382. //
  383. // Input:
  384. // pData -- pointer to a buffer to receive read data
  385. // BufferSize -- size of buffer
  386. //
  387. HRESULT
  388. CUsbCamera::ReadData(
  389. BYTE *pData,
  390. UINT *pBufferSize
  391. )
  392. {
  393. DBG_FN("CUsbCamera::ReadData");
  394. HRESULT hr = S_OK;
  395. BOOL bAbortTransfer = FALSE;
  396. if (!pData ||
  397. !pBufferSize ||
  398. *pBufferSize == 0)
  399. {
  400. wiauDbgError("ReadData", "invalid arg");
  401. return E_INVALIDARG;
  402. }
  403. //
  404. // First read the header from the device
  405. //
  406. memset(m_pUsbData, NULL, m_UsbDataSize);
  407. DWORD BytesRead = 0;
  408. wiauDbgTrace("ReadData", "reading data header");
  409. if (!ReadFile(m_hUSB, m_pUsbData, sizeof(m_pUsbData->Header), &BytesRead, NULL))
  410. {
  411. hr = HRESULT_FROM_WIN32(::GetLastError());
  412. wiauDbgErrorHr(hr, "ReadData", "ReadFile failed");
  413. return hr;
  414. }
  415. if (BytesRead != sizeof(m_pUsbData->Header))
  416. {
  417. wiauDbgError("ReadData", "wrong amount of data read = %d", BytesRead);
  418. return E_FAIL;
  419. }
  420. //
  421. // Check the type code in the header to make sure it's correct
  422. //
  423. if (m_pUsbData->Header.Type != PTPCONTAINER_TYPE_DATA)
  424. {
  425. wiauDbgError("ReadData", "expected a data header but received type = %d", m_pUsbData->Header.Type);
  426. return E_FAIL;
  427. }
  428. //
  429. // Check the opcode and transaction id in the header just to make sure they are correct
  430. //
  431. if ((m_pUsbData->Header.Code != m_prevOpCode) ||
  432. (m_pUsbData->Header.TransactionId != m_prevTranId))
  433. {
  434. wiauDbgError("ReadData", "fields in the data header were incorrect, opcode=0x%04x tranid=0x%08x",
  435. m_pUsbData->Header.Code, m_pUsbData->Header.TransactionId);
  436. return E_FAIL;
  437. }
  438. //
  439. // Loop, reading the data. The callback function will be called at least 10 times during
  440. // the transfer. More if the buffer size is small.
  441. //
  442. LONG lOffset = 0;
  443. UINT BytesToRead = 0;
  444. UINT TotalRead = 0;
  445. UINT TotalToRead = m_pUsbData->Header.Len - sizeof(m_pUsbData->Header);
  446. UINT TotalRemaining = TotalToRead;
  447. //
  448. // Make sure the buffer is large enough, unless a callback function is being used
  449. //
  450. if (m_pDataCallbackParam == NULL &&
  451. *pBufferSize < TotalToRead)
  452. {
  453. wiauDbgError("ReadData", "buffer is too small");
  454. return E_FAIL;
  455. }
  456. //
  457. // When doing callbacks, read the data in chunk sizes slightly
  458. // larger the 1/10 the total and divisible by 4.
  459. //
  460. if (m_pDataCallbackParam)
  461. BytesToRead = (TotalToRead / 40 + 1) * 4;
  462. else
  463. BytesToRead = *pBufferSize;
  464. //
  465. // Set time out values for Usbscan
  466. //
  467. USBSCAN_TIMEOUT TimeOut;
  468. DWORD BytesReturned = 0;
  469. TimeOut.TimeoutRead = PTP_READ_TIMEOUT + max(BytesToRead / 100000, 114);
  470. TimeOut.TimeoutWrite = PTP_WRITE_TIMEOUT;
  471. TimeOut.TimeoutEvent = PTP_EVENT_TIMEOUT;
  472. if (!DeviceIoControl(m_hUSB,
  473. IOCTL_SET_TIMEOUT,
  474. &TimeOut,
  475. sizeof(TimeOut),
  476. NULL,
  477. 0,
  478. &BytesReturned,
  479. NULL))
  480. {
  481. hr = HRESULT_FROM_WIN32(::GetLastError());
  482. wiauDbgErrorHr(hr, "Open", "set timeout DeviceIoControl failed");
  483. return hr;
  484. }
  485. while (TotalRemaining > 0)
  486. {
  487. //
  488. // Make sure the amount to read is never larger than the buffer size. The buffer size may
  489. // be updated by the callback function.
  490. //
  491. if (BytesToRead > *pBufferSize)
  492. BytesToRead = *pBufferSize;
  493. //
  494. // On the last read, the bytes to read may need to be reduced
  495. //
  496. if (BytesToRead > TotalRemaining)
  497. BytesToRead = TotalRemaining;
  498. wiauDbgTrace("ReadData", "reading a chunk of data = %d", BytesToRead);
  499. BytesRead = 0;
  500. if (!ReadFile(m_hUSB, pData, BytesToRead, &BytesRead, NULL))
  501. {
  502. hr = HRESULT_FROM_WIN32(::GetLastError());
  503. wiauDbgErrorHr(hr, "ReadData", "ReadFile failed");
  504. return hr;
  505. }
  506. if ((BytesRead > *pBufferSize) ||
  507. (BytesRead != BytesToRead))
  508. {
  509. wiauDbgError("ReadData", "wrong amount of data read = %d -", BytesRead);
  510. return E_FAIL;
  511. }
  512. TotalRemaining -= BytesRead;
  513. TotalRead += BytesRead;
  514. if (m_pDataCallbackParam &&
  515. !bAbortTransfer)
  516. {
  517. //
  518. // Call the callback function reporting percent complete, offset, and amount read.
  519. // The callback may update pData and BufferSize.
  520. //
  521. hr = m_pPTPDataCB(m_pDataCallbackParam, (TotalRead * 100 / TotalToRead),
  522. lOffset, BytesRead, &pData, (LONG *) pBufferSize);
  523. if (FAILED(hr))
  524. {
  525. //
  526. // Report the error
  527. //
  528. wiauDbgErrorHr(hr, "ReadData", "data callback failed");
  529. }
  530. //
  531. // Check if caller wants to cancel the transfer or returns error
  532. //
  533. if (hr == S_FALSE || FAILED(hr))
  534. {
  535. //
  536. // Do not send CancelRequest to cameras that do not support it, just read the
  537. // remainder of the object without reporting progress and return S_FALSE.
  538. //
  539. // Cameras not supporting CancelRequest are:
  540. // all Sony cameras with DeviceVersion < 1.0004
  541. // Nikon E2500 with DeviceVersion = 1.0
  542. //
  543. const double NIKON_E2500_VERSION_NOT_SUPPORTING_CANCEL = 1.0;
  544. const double MIN_SONY_VERSION_SUPPORTING_CANCEL = 1.0004;
  545. if ((GetHackModel() == HACK_MODEL_NIKON_E2500 &&
  546. GetHackVersion() == NIKON_E2500_VERSION_NOT_SUPPORTING_CANCEL) ||
  547. (GetHackModel() == HACK_MODEL_SONY &&
  548. GetHackVersion() < MIN_SONY_VERSION_SUPPORTING_CANCEL))
  549. {
  550. wiauDbgWarning("ReadData",
  551. "Transfer cancelled, reading but ignoring remainder of the object (%d bytes)", TotalRemaining);
  552. bAbortTransfer = TRUE;
  553. m_Phase = CAMERA_PHASE_RESPONSE; // camera will send response
  554. hr = S_OK;
  555. }
  556. else
  557. {
  558. wiauDbgWarning("ReadData", "Transfer cancelled, aborting current transfer");
  559. hr = SendCancelRequest(m_prevTranId);
  560. if (FAILED(hr))
  561. {
  562. wiauDbgErrorHr(hr, "ReadData", "SendCancelRequest failed");
  563. return hr;
  564. }
  565. m_Phase = CAMERA_PHASE_IDLE; // camera will not send response
  566. return S_FALSE;
  567. }
  568. }
  569. }
  570. //
  571. // Increment the offset
  572. //
  573. lOffset += BytesRead;
  574. }
  575. if ((TotalRead + sizeof(m_pUsbData->Header)) % m_EndpointInfo.BulkInMaxSize == 0)
  576. {
  577. //
  578. // Read the extra null packet
  579. //
  580. wiauDbgTrace("ReadData", "reading a null packet");
  581. BytesRead = 0;
  582. if (!ReadFile(m_hUSB, m_pUsbData, m_UsbDataSize, &BytesRead, NULL))
  583. {
  584. hr = HRESULT_FROM_WIN32(::GetLastError());
  585. wiauDbgErrorHr(hr, "ReadData", "ReadFile failed");
  586. return hr;
  587. }
  588. if (BytesRead != 0)
  589. {
  590. wiauDbgError("ReadData", "tried to read null packet but read %d bytes instead", BytesRead);
  591. return E_FAIL;
  592. }
  593. }
  594. *pBufferSize = TotalRead;
  595. wiauDbgTrace("ReadData", "%d bytes of data successfully read", TotalRead);
  596. if (bAbortTransfer)
  597. hr = S_FALSE;
  598. return hr;
  599. }
  600. //
  601. // This function writes bulk data to the device
  602. //
  603. // Input:
  604. // pData -- pointer to a buffer of data to write
  605. // BufferSize -- amount of data to write
  606. //
  607. HRESULT
  608. CUsbCamera::SendData(
  609. BYTE *pData,
  610. UINT BufferSize
  611. )
  612. {
  613. DBG_FN("CUsbCamera::SendData");
  614. HRESULT hr = S_OK;
  615. if (!pData ||
  616. BufferSize == 0)
  617. {
  618. wiauDbgError("SendData", "invalid arg");
  619. return E_INVALIDARG;
  620. }
  621. //
  622. // Figure out how many packets it will take to contain the header
  623. //
  624. UINT BytesToWrite = m_EndpointInfo.BulkOutMaxSize;
  625. while (BytesToWrite < sizeof(m_pUsbData->Header))
  626. {
  627. BytesToWrite += m_EndpointInfo.BulkOutMaxSize;
  628. }
  629. //
  630. // The first write will contain the USB header plus as much of the data as it
  631. // takes to fill out the packet. We need to write full packets, otherwise the device
  632. // will think the transfer is done.
  633. //
  634. UINT FirstWriteDataAmount = min(BufferSize, BytesToWrite - sizeof(m_pUsbData->Header));
  635. BytesToWrite = sizeof(m_pUsbData->Header) + FirstWriteDataAmount;
  636. //
  637. // Fill out header fields
  638. //
  639. m_pUsbData->Header.Len = BufferSize + sizeof(m_pUsbData->Header);
  640. m_pUsbData->Header.Type = PTPCONTAINER_TYPE_DATA;
  641. m_pUsbData->Header.Code = m_prevOpCode;
  642. m_pUsbData->Header.TransactionId = m_prevTranId;
  643. //
  644. // Copy the part of the data needed to fill out the packets
  645. //
  646. memcpy(m_pUsbData->Data, pData, FirstWriteDataAmount);
  647. //
  648. // Write the header plus partial data
  649. //
  650. wiauDbgTrace("SendData", "Writing first packet, length = %d", BytesToWrite);
  651. DWORD BytesWritten = 0;
  652. if (!WriteFile(m_hUSB, m_pUsbData, BytesToWrite, &BytesWritten, NULL))
  653. {
  654. hr = HRESULT_FROM_WIN32(::GetLastError());
  655. wiauDbgErrorHr(hr, "SendData", "WriteFile failed");
  656. return hr;
  657. }
  658. if (BytesWritten != BytesToWrite)
  659. {
  660. wiauDbgError("SendData", "wrong amount of data written = %d", BytesWritten);
  661. return E_FAIL;
  662. }
  663. UINT TotalBytesWritten = BytesWritten;
  664. //
  665. // The next write (if necessary) will include the remainder of the data
  666. //
  667. if (BufferSize > FirstWriteDataAmount)
  668. {
  669. BytesToWrite = BufferSize - FirstWriteDataAmount;
  670. BytesWritten = 0;
  671. wiauDbgTrace("SendData", "writing remainder of data, length = %d", BytesToWrite);
  672. if (!WriteFile(m_hUSB, &pData[FirstWriteDataAmount], BytesToWrite, &BytesWritten, NULL))
  673. {
  674. hr = HRESULT_FROM_WIN32(::GetLastError());
  675. wiauDbgErrorHr(hr, "SendData", "second WriteFile failed");
  676. return hr;
  677. }
  678. if (BytesWritten != BytesToWrite)
  679. {
  680. wiauDbgError("SendData", "wrong amount of data written = %d -", BytesWritten);
  681. return E_FAIL;
  682. }
  683. TotalBytesWritten += BytesWritten;
  684. }
  685. //
  686. // If the amount written is exactly a multiple of the packet size, send an empty packet
  687. // so the device knows we are done sending data
  688. //
  689. if (TotalBytesWritten % m_EndpointInfo.BulkOutMaxSize == 0)
  690. {
  691. BytesWritten = 0;
  692. wiauDbgTrace("SendData", "writing null packet");
  693. if (!WriteFile(m_hUSB, NULL, 0, &BytesWritten, NULL))
  694. {
  695. hr = HRESULT_FROM_WIN32(::GetLastError());
  696. wiauDbgErrorHr(hr, "SendData", "third WriteFile failed");
  697. return hr;
  698. }
  699. if (BytesWritten != 0)
  700. {
  701. wiauDbgError("SendData", "wrong amount of data written = %d --", BytesWritten);
  702. return E_FAIL;
  703. }
  704. }
  705. wiauDbgTrace("SendData", "%d bytes of data successfully written", TotalBytesWritten);
  706. return hr;
  707. }
  708. //
  709. // This function reads the response data from the device
  710. //
  711. // Input:
  712. // pResponse -- pointer to a response structure to receive the response data
  713. //
  714. HRESULT
  715. CUsbCamera::ReadResponse(
  716. PTP_RESPONSE *pResponse
  717. )
  718. {
  719. DBG_FN("CUsbCamera::ReadResponse");
  720. HRESULT hr = S_OK;
  721. if (!pResponse)
  722. {
  723. wiauDbgError("ReadResponse", "invalid arg");
  724. return E_INVALIDARG;
  725. }
  726. //
  727. // Handle response from reset command
  728. //
  729. if (m_prevOpCode == PTP_OPCODE_RESETDEVICE)
  730. {
  731. wiauDbgTrace("ReadResponse", "creating reset response");
  732. pResponse->ResponseCode = PTP_RESPONSECODE_OK;
  733. pResponse->SessionId = m_SessionId;
  734. pResponse->TransactionId = m_prevTranId;
  735. }
  736. else
  737. {
  738. //
  739. // Clear the USB response buffer
  740. //
  741. memset(&m_UsbResponse, NULL, sizeof(m_UsbResponse));
  742. //
  743. // Read the response from the device
  744. //
  745. DWORD BytesRead = 0;
  746. wiauDbgTrace("ReadResponse", "reading response");
  747. if (!ReadFile(m_hUSB, &m_UsbResponse, sizeof(m_UsbResponse), &BytesRead, NULL))
  748. {
  749. hr = HRESULT_FROM_WIN32(::GetLastError());
  750. wiauDbgErrorHr(hr, "ReadResponse", "ReadFile failed");
  751. return hr;
  752. }
  753. if ((BytesRead < sizeof(m_UsbResponse.Header)) ||
  754. (BytesRead > sizeof(m_UsbResponse)))
  755. {
  756. wiauDbgError("ReadResponse", "wrong amount of data read = %d", BytesRead);
  757. return E_FAIL;
  758. }
  759. //
  760. // Check the type code in the response to make sure it's correct
  761. //
  762. if (m_UsbResponse.Header.Type != PTPCONTAINER_TYPE_RESPONSE)
  763. {
  764. wiauDbgError("ReadResponse", "expected a response but received type = %d", m_UsbResponse.Header.Type);
  765. return E_FAIL;
  766. }
  767. //
  768. // Unwrap the PTP response from the USB container
  769. //
  770. pResponse->ResponseCode = m_UsbResponse.Header.Code;
  771. pResponse->SessionId = m_SessionId; // USB doesn't care about session id, so just use the one we have stored
  772. pResponse->TransactionId = m_UsbResponse.Header.TransactionId;
  773. DWORD ParamLen = BytesRead - sizeof(m_UsbResponse.Header);
  774. if (ParamLen > 0)
  775. {
  776. memcpy(pResponse->Params, m_UsbResponse.Params, ParamLen);
  777. }
  778. }
  779. wiauDbgTrace("ReadResponse", "response successfully read");
  780. return hr;
  781. }
  782. //
  783. // This function reads event data from the device
  784. //
  785. // Input:
  786. // pEvent -- pointer to a PTP event structure to receive the event data
  787. //
  788. HRESULT
  789. CUsbCamera::ReadEvent(
  790. PTP_EVENT *pEvent
  791. )
  792. {
  793. DBG_FN("CUsbCamera::ReadEvent");
  794. HRESULT hr = S_OK;
  795. if (!pEvent)
  796. {
  797. wiauDbgError("ReadEvent", "invalid arg");
  798. return E_INVALIDARG;
  799. }
  800. //
  801. // Allocate buffer for reading event from camera. It should be big enough to accomodate
  802. // packet of maximum allowed size, otherwise we'll get INVALID_ARG
  803. //
  804. DWORD cbEventBufSize = max(sizeof(USB_PTP_EVENT), m_EndpointInfo.InterruptMaxSize);
  805. USB_PTP_EVENT *pEventBuf = (USB_PTP_EVENT*) new BYTE[cbEventBufSize];
  806. if (pEventBuf == NULL)
  807. {
  808. wiauDbgError("ReadEvent", "Memory allocation failed");
  809. hr = E_OUTOFMEMORY;
  810. goto Cleanup;
  811. }
  812. memset(pEventBuf, 0, cbEventBufSize);
  813. //
  814. // Read the event from the device. DeviceIoControl is called in overlapped mode. If
  815. // no information is ready on the interrupt pipe, GetOverlappedResult will wait for
  816. // data to arrive. Unfortunately, DeviceIoControl returns after each packet, so keep
  817. // reading until a short packet is received.
  818. //
  819. DWORD BytesRead = 0;
  820. DWORD TotalBytesRead = 0;
  821. BOOL bReceivedShortPacket = FALSE;
  822. BYTE *pData = (BYTE*) pEventBuf;
  823. wiauDbgTrace("ReadEvent", "reading event");
  824. while (!bReceivedShortPacket)
  825. {
  826. if (!ResetEvent(m_hEventRead))
  827. {
  828. hr = HRESULT_FROM_WIN32(::GetLastError());
  829. wiauDbgErrorHr(hr, "ReadEvent", "ResetEvent failed");
  830. return hr;
  831. }
  832. memset(&m_Overlapped, 0, sizeof(OVERLAPPED));
  833. m_Overlapped.hEvent = m_hEventRead;
  834. if (!DeviceIoControl(m_hEventUSB,
  835. IOCTL_WAIT_ON_DEVICE_EVENT,
  836. NULL,
  837. 0,
  838. pData,
  839. cbEventBufSize - TotalBytesRead,
  840. &BytesRead,
  841. &m_Overlapped))
  842. {
  843. hr = HRESULT_FROM_WIN32(::GetLastError());
  844. if (hr == HRESULT_FROM_WIN32(ERROR_IO_PENDING))
  845. {
  846. hr = S_OK;
  847. DWORD ret;
  848. wiauDbgTrace("ReadEvent", "waiting for interrupt pipe data");
  849. ret = WaitForMultipleObjects(2, m_EventHandles, FALSE, INFINITE);
  850. if (ret == WAIT_FAILED)
  851. {
  852. hr = HRESULT_FROM_WIN32(::GetLastError());
  853. wiauDbgErrorHr(hr, "ReadEvent", "WaitForMultipleObjects failed");
  854. goto Cleanup;
  855. }
  856. else if (ret == WAIT_OBJECT_0)
  857. {
  858. //
  859. // Indicate to caller that I/O was cancelled
  860. //
  861. wiauDbgTrace("ReadEvent", "Cancelling I/O on the interrupt pipe");
  862. hr = S_FALSE;
  863. HRESULT temphr = S_OK;
  864. //
  865. // Cancel the pending I/O on the interrupt pipe
  866. //
  867. if (!CancelIo(m_hEventUSB))
  868. {
  869. temphr = HRESULT_FROM_WIN32(::GetLastError());
  870. wiauDbgErrorHr(hr, "ReadEvent", "CancelIo failed");
  871. }
  872. //
  873. // Exit point when I/O is cancelled!!!
  874. //
  875. goto Cleanup;
  876. }
  877. else
  878. {
  879. //
  880. // Get result of read
  881. //
  882. if (!GetOverlappedResult(m_hEventUSB, &m_Overlapped, &BytesRead, TRUE))
  883. {
  884. hr = HRESULT_FROM_WIN32(::GetLastError());
  885. wiauDbgErrorHr(hr, "ReadEvent", "GetOverlappedResult failed");
  886. goto Cleanup;
  887. }
  888. }
  889. }
  890. else
  891. {
  892. wiauDbgErrorHr(hr, "ReadEvent", "DeviceIoControl failed");
  893. goto Cleanup;
  894. }
  895. }
  896. if (BytesRead == 0) {
  897. bReceivedShortPacket = TRUE;
  898. }
  899. else {
  900. TotalBytesRead += BytesRead;
  901. pData += BytesRead;
  902. bReceivedShortPacket = (BytesRead % m_EndpointInfo.InterruptMaxSize != 0);
  903. }
  904. }
  905. //
  906. // Verify that camera sent correct amount of data
  907. //
  908. if ((TotalBytesRead < sizeof(USB_PTP_HEADER)) ||
  909. (TotalBytesRead > sizeof(USB_PTP_EVENT)))
  910. {
  911. wiauDbgError("ReadEvent", "wrong amount of data read by DeviceIoControl = %d", TotalBytesRead);
  912. hr = E_FAIL;
  913. goto Cleanup;
  914. }
  915. //
  916. // Check the type code in the response to make sure it's correct
  917. //
  918. if (pEventBuf->Header.Type != PTPCONTAINER_TYPE_EVENT)
  919. {
  920. wiauDbgError("ReadEvent", "expected an event but received type = %d", pEventBuf->Header.Type);
  921. hr = E_FAIL;
  922. goto Cleanup;
  923. }
  924. //
  925. // Unwrap the PTP event from the USB container
  926. //
  927. pEvent->EventCode = pEventBuf->Header.Code;
  928. pEvent->SessionId = m_SessionId; // USB doesn't care about session id, so just use the one we have stored
  929. pEvent->TransactionId = pEventBuf->Header.TransactionId;
  930. DWORD ParamLen = TotalBytesRead - sizeof(pEventBuf->Header);
  931. if (ParamLen > 0)
  932. {
  933. memcpy(pEvent->Params, pEventBuf->Params, ParamLen);
  934. }
  935. wiauDbgTrace("ReadEvent", "event successfully read, byte count = %d", TotalBytesRead);
  936. Cleanup:
  937. if (pEventBuf)
  938. {
  939. delete[] (BYTE*)pEventBuf;
  940. pEventBuf = NULL;
  941. }
  942. return hr;
  943. }
  944. //
  945. // This function cancels the remainder of a data transfer.
  946. //
  947. HRESULT
  948. CUsbCamera::AbortTransfer()
  949. {
  950. DBG_FN("CUsbCamera::AbortTransfer");
  951. HRESULT hr = S_OK;
  952. //
  953. // WIAFIX-8/28/2000-davepar Fill in the details:
  954. // 1. If usbscan.sys already transferred the data, clear it's buffer
  955. // 2. If not, send cancel control code to camera
  956. //
  957. return hr;
  958. }
  959. //
  960. // This function attempts to recover from an error. When this function returns, the
  961. // device will be in one of three states:
  962. // 1. Ready for more commands, indicated by S_OK
  963. // 2. Reset, indicated by S_FALSE
  964. // 3. Unreachable, indicated by FAILED(hr)
  965. //
  966. HRESULT
  967. CUsbCamera::RecoverFromError()
  968. {
  969. DBG_FN("CUsbCamera::RecoverFromError");
  970. HRESULT hr = S_OK;
  971. //
  972. // WIAFIX-7/29/2000-davepar Maybe first should cancel all pending I/O with IOCTL_CANCEL_IO??
  973. //
  974. //
  975. // Attempt to get status on the device
  976. //
  977. USB_PTPDEVICESTATUS DeviceStatus;
  978. hr = GetDeviceStatus(&DeviceStatus);
  979. //
  980. // If that worked, clear any stalls returned
  981. //
  982. if (SUCCEEDED(hr))
  983. {
  984. hr = ClearStalls(&DeviceStatus);
  985. //
  986. // If clearing all the stalls worked, exit
  987. //
  988. if (SUCCEEDED(hr))
  989. {
  990. wiauDbgTrace("RecoverFromError", "device is ready for more commands");
  991. return S_OK;
  992. }
  993. }
  994. //
  995. // Either the GetDeviceStatus or ClearStall failed, reset the device
  996. //
  997. hr = ResetDevice();
  998. //
  999. // If that worked, return S_FALSE
  1000. //
  1001. if (SUCCEEDED(hr))
  1002. {
  1003. wiauDbgWarning("RecoverFromError", "the device was reset");
  1004. return S_FALSE;
  1005. }
  1006. //
  1007. // If that fails, the device is unreachable
  1008. //
  1009. wiauDbgError("RecoverFromError", "ResetDevice failed");
  1010. return hr;
  1011. }
  1012. //
  1013. // This function gets the device status, used mainly after an error occurs. It
  1014. // may return an endpoint number that the device has intentionally stalled to
  1015. // cancel a transaction. The caller should be prepared to clear the stall.
  1016. //
  1017. // Input:
  1018. // pDeviceStatus -- the receive the status.
  1019. //
  1020. HRESULT
  1021. CUsbCamera::GetDeviceStatus(
  1022. USB_PTPDEVICESTATUS *pDeviceStatus
  1023. )
  1024. {
  1025. DBG_FN("CUsbCamera::GetDeviceStatus");
  1026. HRESULT hr = S_OK;
  1027. //
  1028. // Set up the request
  1029. //
  1030. IO_BLOCK_EX IoBlock;
  1031. IoBlock.bRequest = USB_PTPREQUEST_GETSTATUS;
  1032. IoBlock.bmRequestType = USB_PTPREQUEST_TYPE_IN;
  1033. IoBlock.fTransferDirectionIn = TRUE;
  1034. IoBlock.uOffset = 0;
  1035. IoBlock.uLength = sizeof(*pDeviceStatus);
  1036. IoBlock.pbyData = (UCHAR *) pDeviceStatus;
  1037. IoBlock.uIndex = 0;
  1038. pDeviceStatus->Header.Code = 0;
  1039. //
  1040. // Send the request
  1041. //
  1042. wiauDbgTrace("GetDeviceStatus", "sending GetDeviceStatus request");
  1043. DWORD BytesRead = 0;
  1044. if (!DeviceIoControl(m_hUSB,
  1045. IOCTL_SEND_USB_REQUEST_PTP,
  1046. &IoBlock,
  1047. sizeof(IoBlock),
  1048. pDeviceStatus,
  1049. sizeof(*pDeviceStatus),
  1050. &BytesRead,
  1051. NULL
  1052. ))
  1053. {
  1054. hr = HRESULT_FROM_WIN32(::GetLastError());
  1055. wiauDbgErrorHr(hr, "GetDeviceStatus", "DeviceIoControl failed");
  1056. return hr;
  1057. }
  1058. if (BytesRead < sizeof(USB_PTPDEVICESTATUS_HEADER) ||
  1059. BytesRead > sizeof(*pDeviceStatus))
  1060. {
  1061. wiauDbgError("GetDeviceStatus", "wrong amount of data returned = %d", BytesRead);
  1062. return E_FAIL;
  1063. }
  1064. if((HIBYTE(pDeviceStatus->Header.Code) & 0xF0) != 0x20 &&
  1065. (HIBYTE(pDeviceStatus->Header.Code) & 0xF0) != 0xA0)
  1066. {
  1067. wiauDbgError("GetDeviceStatus", "PTP status code (0x%x)is invalid ", pDeviceStatus->Header.Code);
  1068. return E_FAIL;
  1069. }
  1070. wiauDbgTrace("GetDeviceStatus", "read %d bytes", BytesRead);
  1071. if (g_dwDebugFlags & WIAUDBG_DUMP)
  1072. {
  1073. wiauDbgTrace("GetDeviceStatus", "Dumping device status:");
  1074. wiauDbgTrace("GetDeviceStatus", " Length = 0x%04x", pDeviceStatus->Header.Len);
  1075. wiauDbgTrace("GetDeviceStatus", " Response code = 0x%04x", pDeviceStatus->Header.Code);
  1076. ULONG NumParams = (ULONG)min(MAX_NUM_PIPES, (BytesRead - sizeof(pDeviceStatus->Header) / sizeof(pDeviceStatus->Params[0])));
  1077. for (ULONG count = 0; count < NumParams; count++)
  1078. {
  1079. wiauDbgTrace("GetDeviceStatus", " Param %d = 0x%08x", count, pDeviceStatus->Params[count]);
  1080. }
  1081. }
  1082. return hr;
  1083. }
  1084. //
  1085. // This function clears all the stalls listed in the given device status
  1086. //
  1087. // Input:
  1088. // pDeviceStatus -- lists zero or more stalled endpoints
  1089. //
  1090. HRESULT
  1091. CUsbCamera::ClearStalls(
  1092. USB_PTPDEVICESTATUS *pDeviceStatus
  1093. )
  1094. {
  1095. DBG_FN("CUsbCamera::ClearStalls");
  1096. HRESULT hr = S_OK;
  1097. if (!pDeviceStatus)
  1098. {
  1099. wiauDbgError("ClearStalls", "invalid arg");
  1100. return E_INVALIDARG;
  1101. }
  1102. PIPE_TYPE PipeType;
  1103. ULONG NumStalls = (pDeviceStatus->Header.Len - sizeof(pDeviceStatus->Header)) / sizeof(pDeviceStatus->Params[0]);
  1104. for (ULONG count = 0; count < NumStalls; count++)
  1105. {
  1106. //
  1107. // Translate the endpoint address to the pipe type
  1108. //
  1109. if ((UCHAR)pDeviceStatus->Params[count] == m_EndpointInfo.BulkInAddress)
  1110. {
  1111. PipeType = READ_DATA_PIPE;
  1112. }
  1113. else if ((UCHAR)pDeviceStatus->Params[count] == m_EndpointInfo.BulkOutAddress)
  1114. {
  1115. PipeType = WRITE_DATA_PIPE;
  1116. }
  1117. else if ((BYTE)pDeviceStatus->Params[count] == m_EndpointInfo.InterruptAddress)
  1118. {
  1119. PipeType = EVENT_PIPE;
  1120. }
  1121. else
  1122. {
  1123. //
  1124. // Unrecognized, ignore it
  1125. //
  1126. wiauDbgError("ClearStalls", "unrecognized pipe address 0x%08x", pDeviceStatus->Params[count]);
  1127. continue;
  1128. }
  1129. //
  1130. // Reset the endpoint
  1131. //
  1132. DWORD BytesRead;
  1133. if (!DeviceIoControl(m_hUSB,
  1134. IOCTL_RESET_PIPE,
  1135. &PipeType,
  1136. sizeof(PipeType),
  1137. NULL,
  1138. 0,
  1139. &BytesRead,
  1140. NULL
  1141. ))
  1142. {
  1143. hr = HRESULT_FROM_WIN32(::GetLastError());
  1144. wiauDbgErrorHr(hr, "ClearStalls", "DeviceIoControl failed");
  1145. return hr;
  1146. }
  1147. }
  1148. if(NumStalls) {
  1149. for(count = 0; count < 3; count++) {
  1150. if(FAILED(GetDeviceStatus(pDeviceStatus))) {
  1151. wiauDbgErrorHr(hr, "ClearStalls", "GetDeviceStatus failed");
  1152. return hr;
  1153. }
  1154. if(pDeviceStatus->Header.Code == PTP_RESPONSECODE_OK) {
  1155. break;
  1156. }
  1157. }
  1158. //
  1159. // check if still there are stalled endpoints
  1160. //
  1161. if(pDeviceStatus->Header.Code != PTP_RESPONSECODE_OK)
  1162. {
  1163. hr = E_FAIL;
  1164. }
  1165. }
  1166. //
  1167. // Device should be ready to receive commands again
  1168. //
  1169. m_Phase = CAMERA_PHASE_IDLE;
  1170. return hr;
  1171. }
  1172. //
  1173. // Reset the device
  1174. //
  1175. HRESULT
  1176. CUsbCamera::SendResetDevice()
  1177. {
  1178. DBG_FN("CUsbCamera::SendResetDevice");
  1179. HRESULT hr = S_OK;
  1180. //
  1181. // Set up the request
  1182. //
  1183. IO_BLOCK_EX IoBlock;
  1184. IoBlock.bRequest = USB_PTPREQUEST_RESET;
  1185. IoBlock.bmRequestType = USB_PTPREQUEST_TYPE_OUT;
  1186. IoBlock.fTransferDirectionIn = FALSE;
  1187. IoBlock.uOffset = 0;
  1188. IoBlock.uLength = 0;
  1189. IoBlock.pbyData = NULL;
  1190. IoBlock.uIndex = 0;
  1191. //
  1192. // Send the request
  1193. //
  1194. DWORD BytesRead;
  1195. if (!DeviceIoControl(m_hUSB,
  1196. IOCTL_SEND_USB_REQUEST_PTP,
  1197. &IoBlock,
  1198. sizeof(IoBlock),
  1199. NULL,
  1200. 0,
  1201. &BytesRead,
  1202. NULL
  1203. ))
  1204. {
  1205. hr = HRESULT_FROM_WIN32(::GetLastError());
  1206. wiauDbgErrorHr(hr, "ResetDevice", "DeviceIoControl failed");
  1207. goto Cleanup;
  1208. }
  1209. //
  1210. // Let the device settle
  1211. //
  1212. Sleep(1000);
  1213. //
  1214. // See if reset helped
  1215. //
  1216. USB_PTPDEVICESTATUS DeviceStatus;
  1217. hr = GetDeviceStatus(&DeviceStatus);
  1218. if (FAILED(hr) || DeviceStatus.Header.Code != PTP_RESPONSECODE_OK)
  1219. {
  1220. hr = E_FAIL; // device is still unconscious
  1221. goto Cleanup;
  1222. }
  1223. //
  1224. // Side effect of reseting the device is that the phase, session id, and transaction id get reset
  1225. //
  1226. m_Phase = CAMERA_PHASE_IDLE;
  1227. m_SessionId = 0;
  1228. m_NextTransactionId = PTP_TRANSACTIONID_MIN;
  1229. //
  1230. // Indicate that camera was reset, so that CWiaMiniDriver can notify caller
  1231. //
  1232. m_bCameraWasReset = TRUE;
  1233. Cleanup:
  1234. return hr;
  1235. }
  1236. //
  1237. // This function sends the class CancelRequest command to the device
  1238. // and wait for the device to complete the request.
  1239. // Input:
  1240. // dwTransactionId -- transaction being canceled
  1241. //
  1242. HRESULT
  1243. CUsbCamera::SendCancelRequest(DWORD dwTransactionId)
  1244. {
  1245. DBG_FN("CUsbCamera::CancelRequest");
  1246. HRESULT hr = S_OK;
  1247. IO_BLOCK_EX IoBlock;
  1248. USB_PTPCANCELIOREQUEST CancelRequest;
  1249. DWORD BytesReturned;
  1250. IoBlock.bRequest = USB_PTPREQUEST_CANCELIO;
  1251. IoBlock.bmRequestType = USB_PTPREQUEST_TYPE_OUT;
  1252. IoBlock.fTransferDirectionIn = FALSE; // Host to device
  1253. IoBlock.uOffset = 0; // 0 for this request
  1254. IoBlock.uLength = sizeof(USB_PTPCANCELIOREQUEST); // Data output length
  1255. IoBlock.pbyData = (BYTE *)&CancelRequest; // output data
  1256. IoBlock.uIndex = 0; // 0 for this request
  1257. CancelRequest.Id = USB_PTPCANCELIO_ID;
  1258. CancelRequest.TransactionId = dwTransactionId;
  1259. if (DeviceIoControl(m_hUSB,
  1260. IOCTL_SEND_USB_REQUEST_PTP,
  1261. &IoBlock,
  1262. sizeof(IoBlock),
  1263. NULL,
  1264. 0,
  1265. &BytesReturned,
  1266. NULL
  1267. ))
  1268. {
  1269. //
  1270. // Poll device until it returns to idle state
  1271. //
  1272. USB_PTPDEVICESTATUS DeviceStatus;
  1273. const UINT MAX_CANCEL_RECOVERY_MILLISECONDS = 3000;
  1274. const UINT SLEEP_BETWEEN_RETRIES = 100;
  1275. DWORD RetryCounts = MAX_CANCEL_RECOVERY_MILLISECONDS / SLEEP_BETWEEN_RETRIES;
  1276. while (RetryCounts--)
  1277. {
  1278. hr = GetDeviceStatus(&DeviceStatus);
  1279. if (SUCCEEDED(hr))
  1280. {
  1281. if (PTP_RESPONSECODE_OK == DeviceStatus.Header.Code)
  1282. {
  1283. //
  1284. // CancelRequest completed and device is back idle
  1285. //
  1286. hr = S_OK;
  1287. break;
  1288. }
  1289. else if (PTP_RESPONSECODE_DEVICEBUSY != DeviceStatus.Header.Code)
  1290. {
  1291. //
  1292. // This is wrong. Device must be either busy or idle
  1293. //
  1294. wiauDbgError("SendCancelRequest",
  1295. "Device is in invalid state, DeviceStatus=0x%X", DeviceStatus.Header.Code);
  1296. hr = E_FAIL;
  1297. break;
  1298. }
  1299. }
  1300. else
  1301. {
  1302. if (RetryCounts)
  1303. {
  1304. hr = S_OK;
  1305. wiauDbgWarning("CancelRequest", "GetDeviceStatus failed, retrying...");
  1306. }
  1307. else
  1308. {
  1309. wiauDbgError("CancelRequest", "GetDeviceStatus failed");
  1310. }
  1311. }
  1312. Sleep(SLEEP_BETWEEN_RETRIES);
  1313. }
  1314. //
  1315. // Flush system buffers - otherwise we'll get old data on next read
  1316. //
  1317. FlushFileBuffers(m_hUSB);
  1318. }
  1319. else
  1320. {
  1321. hr = HRESULT_FROM_WIN32(::GetLastError());
  1322. wiauDbgErrorHr(hr, "CancelRequest", "send USB request failed");
  1323. }
  1324. return hr;
  1325. }