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.

1386 lines
45 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2001
  3. Module Name:
  4. ocrw.c
  5. Abstract:
  6. Environment:
  7. kernel mode only
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include <stdio.h>
  12. #include "stddef.h"
  13. #include "wdm.h"
  14. #include "usbscan.h"
  15. #include "usbd_api.h"
  16. #include "private.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, USOpen)
  19. #pragma alloc_text(PAGE, USClose)
  20. #pragma alloc_text(PAGE, USFlush)
  21. #pragma alloc_text(PAGE, USRead)
  22. #pragma alloc_text(PAGE, USWrite)
  23. #pragma alloc_text(PAGE, USGetPipeIndexToUse)
  24. #pragma alloc_text(PAGE, USTransfer)
  25. #endif
  26. NTSTATUS
  27. USOpen(
  28. IN PDEVICE_OBJECT pDeviceObject,
  29. IN PIRP pIrp
  30. )
  31. /*++
  32. Routine Description:
  33. This routine is called to establish a connection to the device
  34. class driver. It does no more than return STATUS_SUCCESS.
  35. Arguments:
  36. pDeviceObject - Device object for a device.
  37. pIrp - Open request packet
  38. Return Value:
  39. NT Status - STATUS_SUCCESS
  40. --*/
  41. {
  42. NTSTATUS Status;
  43. PUSBSCAN_DEVICE_EXTENSION pde;
  44. PFILE_OBJECT fileObject;
  45. PUSBSCAN_FILE_CONTEXT pFileContext;
  46. PIO_STACK_LOCATION irpStack;
  47. PKEY_VALUE_PARTIAL_INFORMATION pValueInfo;
  48. ULONG nameLen, ix;
  49. PAGED_CODE();
  50. DebugTrace(TRACE_PROC_ENTER,("USOpen: Enter..\n",pIrp));
  51. //
  52. // Increment I/O processing counter.
  53. //
  54. USIncrementIoCount( pDeviceObject );
  55. //
  56. // Initialize locals.
  57. //
  58. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  59. irpStack = IoGetCurrentIrpStackLocation (pIrp);
  60. fileObject = irpStack->FileObject;
  61. pValueInfo = NULL;
  62. Status = STATUS_SUCCESS;
  63. //
  64. // Initialize file context.
  65. //
  66. fileObject->FsContext = NULL;
  67. //
  68. // Check if it's accepting requests.
  69. //
  70. if (FALSE == pde -> AcceptingRequests) {
  71. DebugTrace(TRACE_WARNING,("USOpen: WARNING!! Device isn't accepting request.\n"));
  72. Status = STATUS_DELETE_PENDING;
  73. goto USOpen_return;
  74. }
  75. //
  76. // Check device power state.
  77. //
  78. if (PowerDeviceD0 != pde -> CurrentDevicePowerState) {
  79. DebugTrace(TRACE_WARNING,("USOpen: WARNING!! Device is suspended.\n"));
  80. Status = STATUS_DELETE_PENDING;
  81. goto USOpen_return;
  82. }
  83. //
  84. // Allocate file context buffer.
  85. //
  86. pFileContext = USAllocatePool(NonPagedPool, sizeof(USBSCAN_FILE_CONTEXT));
  87. if(NULL == pFileContext){
  88. DebugTrace(TRACE_CRITICAL,("USOpen: ERROR!! Can't allocate file context\n"));
  89. Status = STATUS_INSUFFICIENT_RESOURCES;
  90. goto USOpen_return;
  91. }
  92. RtlZeroMemory(pFileContext, sizeof(USBSCAN_FILE_CONTEXT));
  93. //
  94. // Set allocated buffer to the context.
  95. //
  96. fileObject->FsContext = pFileContext;
  97. //
  98. // Check the length of CreateFile name to see if pipe is specified by prefix.
  99. //
  100. nameLen = fileObject->FileName.Length;
  101. DebugTrace(TRACE_STATUS,("USOpen: CreateFile name=%ws, Length=%d.\n", fileObject->FileName.Buffer, nameLen));
  102. if (0 == nameLen) {
  103. //
  104. // Use default pipe
  105. //
  106. pFileContext->PipeIndex = -1;
  107. } else {
  108. //
  109. // Pipe number must be '\' + one digit , like '\0'.
  110. // length would be 4.
  111. //
  112. if( (4 != nameLen)
  113. || (fileObject->FileName.Buffer[1] < (WCHAR) '0')
  114. || (fileObject->FileName.Buffer[1] > (WCHAR) '9') )
  115. {
  116. DebugTrace(TRACE_ERROR,("USOpen: ERROR!! Invalid CreateFile Name\n"));
  117. Status = STATUS_INVALID_PARAMETER;
  118. } else {
  119. pFileContext->PipeIndex = (LONG)(fileObject->FileName.Buffer[1] - (WCHAR) '0');
  120. //
  121. // Check if pipe index is lower than maximum
  122. //
  123. if(pFileContext->PipeIndex > (LONG)pde->NumberOfPipes){
  124. DebugTrace(TRACE_ERROR,("USOpen: ERROR!! Invalid pipe index(0x%x). Use default.\n", pFileContext->PipeIndex));
  125. pFileContext->PipeIndex = -1;
  126. Status = STATUS_INVALID_PARAMETER;
  127. }
  128. }
  129. }
  130. //
  131. // Read default timeout value from registry. If not exist, then set default.
  132. //
  133. // Timeout for Read.
  134. Status = UsbScanReadDeviceRegistry(pde,
  135. USBSCAN_REG_TIMEOUT_READ,
  136. &pValueInfo);
  137. if(NT_SUCCESS(Status)){
  138. if(NULL != pValueInfo){
  139. pFileContext->TimeoutRead = *((PULONG)pValueInfo->Data);
  140. USFreePool(pValueInfo);
  141. pValueInfo = NULL;
  142. } else {
  143. DebugTrace(TRACE_ERROR,("USOpen: ERROR!! UsbScanReadDeviceRegistry(1) succeeded but pValueInfo is NULL.\n"));
  144. pFileContext->TimeoutRead = USBSCAN_TIMEOUT_READ;
  145. }
  146. } else {
  147. pFileContext->TimeoutRead = USBSCAN_TIMEOUT_READ;
  148. }
  149. DebugTrace(TRACE_STATUS,("USOpen: Default Read timeout=0x%xsec.\n", pFileContext->TimeoutRead));
  150. // Timeout for Write.
  151. Status = UsbScanReadDeviceRegistry(pde,
  152. USBSCAN_REG_TIMEOUT_WRITE,
  153. &pValueInfo);
  154. if(NT_SUCCESS(Status)){
  155. if(NULL != pValueInfo){
  156. pFileContext->TimeoutWrite = *((PULONG)pValueInfo->Data);
  157. USFreePool(pValueInfo);
  158. pValueInfo = NULL;
  159. } else {
  160. DebugTrace(TRACE_ERROR,("USOpen: ERROR!! UsbScanReadDeviceRegistry(2) succeeded but pValueInfo is NULL.\n"));
  161. pFileContext->TimeoutRead = USBSCAN_TIMEOUT_WRITE;
  162. }
  163. } else {
  164. pFileContext->TimeoutWrite = USBSCAN_TIMEOUT_WRITE;
  165. }
  166. DebugTrace(TRACE_STATUS,("USOpen: Default Write timeout=0x%xsec.\n", pFileContext->TimeoutWrite));
  167. // Timeout for Event.
  168. Status = UsbScanReadDeviceRegistry(pde,
  169. USBSCAN_REG_TIMEOUT_EVENT,
  170. &pValueInfo);
  171. if(NT_SUCCESS(Status)){
  172. if(NULL != pValueInfo){
  173. pFileContext->TimeoutEvent = *((PULONG)pValueInfo->Data);
  174. USFreePool(pValueInfo);
  175. pValueInfo = NULL;
  176. } else {
  177. DebugTrace(TRACE_ERROR,("USOpen: ERROR!! UsbScanReadDeviceRegistry(3) succeeded but pValueInfo is NULL.\n"));
  178. pFileContext->TimeoutRead = USBSCAN_TIMEOUT_EVENT;
  179. }
  180. } else {
  181. pFileContext->TimeoutEvent = USBSCAN_TIMEOUT_EVENT;
  182. }
  183. DebugTrace(TRACE_STATUS,("USOpen: Default Event timeout=0x%xsec.\n", pFileContext->TimeoutEvent));
  184. //
  185. // Return successfully.
  186. //
  187. Status = STATUS_SUCCESS;
  188. USOpen_return:
  189. pIrp -> IoStatus.Information = 0;
  190. pIrp -> IoStatus.Status = Status;
  191. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  192. USDecrementIoCount(pDeviceObject);
  193. DebugTrace(TRACE_PROC_LEAVE,("USOpen: Leaving.. Status = %x.\n", Status));
  194. return Status;
  195. } // end USOpen()
  196. NTSTATUS
  197. USFlush(
  198. IN PDEVICE_OBJECT pDeviceObject,
  199. IN PIRP pIrp
  200. )
  201. /*++
  202. Routine Description:
  203. Arguments:
  204. pDeviceObject - Device object for a device.
  205. pIrp - Close request packet
  206. Return Value:
  207. NT Status - STATUS_SUCCESS
  208. --*/
  209. {
  210. NTSTATUS Status;
  211. PUSBSCAN_DEVICE_EXTENSION pde;
  212. ULONG i;
  213. PAGED_CODE();
  214. DebugTrace(TRACE_PROC_ENTER,("USFlush: Enter..\n",pIrp));
  215. USIncrementIoCount( pDeviceObject );
  216. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  217. Status = STATUS_SUCCESS;
  218. for(i = 0; i < pde->NumberOfPipes; i++){
  219. if( (pde->PipeInfo[i].PipeType == UsbdPipeTypeBulk)
  220. && (pde->PipeInfo[i].EndpointAddress & BULKIN_FLAG) )
  221. {
  222. DebugTrace(TRACE_STATUS,("USFlush: Flushing Buffer[%d].\n",i));
  223. if (pde->ReadPipeBuffer[i].RemainingData > 0) {
  224. DebugTrace(TRACE_STATUS,("USFlush: Buffer[%d] 0x%p -> 0x%p.\n",
  225. i,
  226. pde->ReadPipeBuffer[i].pBuffer,
  227. pde->ReadPipeBuffer[i].pStartBuffer));
  228. pde->ReadPipeBuffer[i].pBuffer = pde->ReadPipeBuffer[i].pStartBuffer;
  229. pde->ReadPipeBuffer[i].RemainingData = 0;
  230. }
  231. }
  232. }
  233. pIrp -> IoStatus.Information = 0;
  234. pIrp -> IoStatus.Status = Status;
  235. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  236. USDecrementIoCount(pDeviceObject);
  237. DebugTrace(TRACE_PROC_LEAVE,("USFlush: Leaving.. Status = %x.\n", Status));
  238. return Status;
  239. } // end USFlush()
  240. NTSTATUS
  241. USClose(
  242. IN PDEVICE_OBJECT pDeviceObject,
  243. IN PIRP pIrp
  244. )
  245. /*++
  246. Routine Description:
  247. Arguments:
  248. pDeviceObject - Device object for a device.
  249. pIrp - Close request packet
  250. Return Value:
  251. NT Status - STATUS_SUCCESS
  252. --*/
  253. {
  254. NTSTATUS Status;
  255. PFILE_OBJECT fileObject;
  256. PUSBSCAN_FILE_CONTEXT pFileContext;
  257. PIO_STACK_LOCATION pIrpStack;
  258. PAGED_CODE();
  259. DebugTrace(TRACE_PROC_ENTER,("USClose: Enter..\n",pIrp));
  260. USIncrementIoCount( pDeviceObject );
  261. //
  262. // Initialize locals.
  263. //
  264. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  265. fileObject = pIrpStack->FileObject;
  266. pFileContext = fileObject->FsContext;
  267. //
  268. // Free context buffer.
  269. //
  270. ASSERT(NULL != pFileContext);
  271. USFreePool(pFileContext);
  272. pFileContext = NULL;
  273. //
  274. // Complete.
  275. //
  276. Status = STATUS_SUCCESS;
  277. pIrp -> IoStatus.Information = 0;
  278. pIrp -> IoStatus.Status = Status;
  279. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  280. USDecrementIoCount(pDeviceObject);
  281. DebugTrace(TRACE_PROC_LEAVE,("USClose: Leaving.. Status = %x.\n", Status));
  282. return Status;
  283. } // end USClose()
  284. NTSTATUS
  285. USRead(
  286. IN PDEVICE_OBJECT pDeviceObject,
  287. IN PIRP pIrp
  288. )
  289. /*++
  290. Routine Description:
  291. Arguments:
  292. pDeviceObject - Device object for a device.
  293. pIrp - Read request packet
  294. Return Value:
  295. NT Status - STATUS_SUCCESS
  296. --*/
  297. {
  298. NTSTATUS Status;
  299. PUSBSCAN_DEVICE_EXTENSION pde;
  300. PIO_STACK_LOCATION pIrpStack;
  301. PFILE_OBJECT fileObject;
  302. PUSBSCAN_FILE_CONTEXT pFileContext;
  303. ULONG Timeout;
  304. PULONG pTimeout;
  305. PAGED_CODE();
  306. DebugTrace(TRACE_PROC_ENTER,("USRead: Enter..\n",pIrp));
  307. // DebugTrace(TRACE_ERROR,("USRead: Enter.. size=0x%x\n",pIrpStack -> Parameters.Write.Length));
  308. ASSERT(pIrp -> MdlAddress);
  309. USIncrementIoCount( pDeviceObject );
  310. //
  311. // Initialize locals.
  312. //
  313. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  314. //
  315. // Check if it's accepting requests.
  316. //
  317. if (pde -> AcceptingRequests == FALSE) {
  318. DebugTrace(TRACE_ERROR,("USRead: ERROR!! Read issued after device stopped/removed!\n"));
  319. Status = STATUS_FILE_CLOSED;
  320. pIrp -> IoStatus.Information = 0;
  321. pIrp -> IoStatus.Status = Status;
  322. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  323. goto USRead_return;
  324. }
  325. //
  326. // Check device power state.
  327. //
  328. if (PowerDeviceD0 != pde -> CurrentDevicePowerState) {
  329. DebugTrace(TRACE_WARNING,("USRead: WARNING!! Device is suspended.\n"));
  330. Status = STATUS_FILE_CLOSED;
  331. pIrp -> IoStatus.Information = 0;
  332. pIrp -> IoStatus.Status = Status;
  333. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  334. goto USRead_return;
  335. }
  336. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  337. fileObject = pIrpStack->FileObject;
  338. pFileContext = fileObject->FsContext;
  339. //
  340. // Copy timeout value for Read from file context.
  341. //
  342. Timeout = pFileContext->TimeoutRead;
  343. //
  344. // If timeout value is 0, then never timeout.
  345. //
  346. if(0 == Timeout){
  347. pTimeout = NULL;
  348. } else {
  349. DebugTrace(TRACE_STATUS,("USRead: Timeout is set to 0x%x sec.\n", Timeout));
  350. pTimeout = &Timeout;
  351. }
  352. //
  353. // Call worker funciton.
  354. //
  355. Status = USTransfer(pDeviceObject,
  356. pIrp,
  357. pde -> IndexBulkIn,
  358. NULL,
  359. pIrp -> MdlAddress,
  360. pIrpStack -> Parameters.Read.Length,
  361. pTimeout);
  362. //
  363. // IRP should be completed in USTransfer or its completion routine.
  364. //
  365. USRead_return:
  366. USDecrementIoCount(pDeviceObject);
  367. DebugTrace(TRACE_PROC_LEAVE,("USRead: Leaving.. Status = %x.\n", Status));
  368. return Status;
  369. }
  370. NTSTATUS
  371. USWrite(
  372. IN PDEVICE_OBJECT pDeviceObject,
  373. IN PIRP pIrp
  374. )
  375. /*++
  376. Routine Description:
  377. Arguments:
  378. pDeviceObject - Device object for a device.
  379. pIrp - Write request packet
  380. Return Value:
  381. NT Status - STATUS_SUCCESS
  382. --*/
  383. {
  384. NTSTATUS Status;
  385. PUSBSCAN_DEVICE_EXTENSION pde;
  386. PIO_STACK_LOCATION pIrpStack;
  387. PFILE_OBJECT fileObject;
  388. PUSBSCAN_FILE_CONTEXT pFileContext;
  389. ULONG Timeout;
  390. PULONG pTimeout;
  391. PAGED_CODE();
  392. DebugTrace(TRACE_PROC_ENTER,("USWrite: Enter..\n",pIrp));
  393. // DebugTrace(TRACE_ERROR,("USWrite: Enter.. size=0x%x\n",pIrpStack -> Parameters.Write.Length));
  394. // ASSERT(pIrp -> MdlAddress);
  395. USIncrementIoCount( pDeviceObject );
  396. //
  397. // Initialize locals.
  398. //
  399. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  400. //
  401. // Check if it's accepting requests.
  402. //
  403. if (pde -> AcceptingRequests == FALSE) {
  404. DebugTrace(TRACE_ERROR,("USWrite: ERROR!! Write issued after device stopped/removed!\n"));
  405. Status = STATUS_FILE_CLOSED;
  406. pIrp -> IoStatus.Information = 0;
  407. pIrp -> IoStatus.Status = Status;
  408. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  409. goto USWrite_return;
  410. }
  411. //
  412. // Check device power state.
  413. //
  414. if (PowerDeviceD0 != pde -> CurrentDevicePowerState) {
  415. DebugTrace(TRACE_WARNING,("USWrite: WARNING!! Device is suspended.\n"));
  416. Status = STATUS_FILE_CLOSED;
  417. pIrp -> IoStatus.Information = 0;
  418. pIrp -> IoStatus.Status = Status;
  419. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  420. goto USWrite_return;
  421. }
  422. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  423. fileObject = pIrpStack->FileObject;
  424. pFileContext = fileObject->FsContext;
  425. //
  426. // Copy timeout value for Write from file context.
  427. //
  428. Timeout = pFileContext->TimeoutWrite;
  429. //
  430. // If timeout value is 0, then never timeout.
  431. //
  432. if(0 == Timeout){
  433. pTimeout = NULL;
  434. } else {
  435. DebugTrace(TRACE_STATUS,("USWrite: Timeout is set to 0x%x sec.\n", Timeout));
  436. pTimeout = &Timeout;
  437. }
  438. //
  439. // Call worker funciton.
  440. //
  441. #if DBG
  442. {
  443. PUCHAR pDumpBuf = NULL;
  444. if (NULL != pIrp -> MdlAddress) {
  445. pIrp -> MdlAddress -> MdlFlags |= MDL_MAPPING_CAN_FAIL;
  446. pDumpBuf = MmGetSystemAddressForMdl(pIrp -> MdlAddress);
  447. }
  448. if(NULL != pDumpBuf){
  449. MyDumpMemory(pDumpBuf,
  450. pIrpStack -> Parameters.Write.Length,
  451. FALSE);
  452. }
  453. }
  454. #endif // DBG
  455. Status = USTransfer(pDeviceObject,
  456. pIrp,
  457. pde -> IndexBulkOut,
  458. NULL,
  459. pIrp -> MdlAddress,
  460. pIrpStack -> Parameters.Write.Length,
  461. pTimeout);
  462. //
  463. // IRP should be completed in USTransfer or its completion routine.
  464. //
  465. USWrite_return:
  466. USDecrementIoCount(pDeviceObject);
  467. DebugTrace(TRACE_PROC_LEAVE,("USWrite: Leaving.. Status = %x.\n", Status));
  468. return Status;
  469. }
  470. NTSTATUS
  471. USTransfer(
  472. IN PDEVICE_OBJECT pDeviceObject,
  473. IN PIRP pIrp,
  474. IN ULONG Index,
  475. IN PVOID pBuffer, // Either pBuffer or pMdl
  476. IN PMDL pMdl, // must be passed in.
  477. IN ULONG TransferSize,
  478. IN PULONG pTimeout
  479. )
  480. /*++
  481. Routine Description:
  482. Arguments:
  483. pDeviceObject - Device object for a device.
  484. pOrigianlIrp - Original IRP to Read/Write.
  485. Return Value:
  486. NT Status - STATUS_SUCCESS
  487. --*/
  488. {
  489. NTSTATUS Status;
  490. PUSBSCAN_DEVICE_EXTENSION pde;
  491. PIO_STACK_LOCATION pNextIrpStack;
  492. PTRANSFER_CONTEXT pTransferContext;
  493. PURB pUrb;
  494. PUSBSCAN_PACKETS pPackets;
  495. ULONG siz = 0;
  496. ULONG MaxPacketSize;
  497. ULONG MaxTransferSize;
  498. ULONG PipeIndex;
  499. BOOLEAN fNextReadBlocked;
  500. BOOLEAN fBulkIn;
  501. BOOLEAN fNeedCompletion;
  502. PAGED_CODE();
  503. DebugTrace(TRACE_PROC_ENTER,("USTransfer: Enter..\n"));
  504. //
  505. // Initialize status etc..
  506. //
  507. Status = STATUS_SUCCESS;
  508. fNeedCompletion = TRUE;
  509. pde = NULL;
  510. pNextIrpStack = NULL;
  511. pTransferContext = NULL;
  512. pUrb = NULL;
  513. pPackets = NULL;;
  514. //
  515. // Check the arguments.
  516. //
  517. if( (NULL == pIrp)
  518. || ( (NULL == pBuffer)
  519. && (NULL == pMdl)
  520. && (0 != TransferSize) )
  521. || (Index > MAX_NUM_PIPES) )
  522. {
  523. DebugTrace(TRACE_ERROR,("USTransfer: ERROR!! Invalid argment.\n"));
  524. Status = STATUS_INVALID_PARAMETER;
  525. goto USTransfer_return;
  526. }
  527. //
  528. // Initialize status etc..
  529. //
  530. pIrp -> IoStatus.Information = 0;
  531. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  532. pNextIrpStack = IoGetNextIrpStackLocation(pIrp);
  533. //
  534. // Pickup PipeIndex to use
  535. //
  536. PipeIndex = USGetPipeIndexToUse(pDeviceObject,
  537. pIrp,
  538. Index);
  539. DebugTrace(TRACE_STATUS,("USTransfer: Transfer [pipe %d] called. size = %d, pBuffer = 0x%p, Mdl = 0x%p \n",
  540. PipeIndex,
  541. TransferSize,
  542. pBuffer,
  543. pMdl
  544. ));
  545. MaxTransferSize = pde -> PipeInfo[PipeIndex].MaximumTransferSize;
  546. MaxPacketSize = pde -> PipeInfo[PipeIndex].MaximumPacketSize;
  547. fBulkIn = ((pde->PipeInfo[PipeIndex].PipeType == UsbdPipeTypeBulk)
  548. && (pde->PipeInfo[PipeIndex].EndpointAddress & BULKIN_FLAG));
  549. #if DBG
  550. if (TransferSize > MaxTransferSize) {
  551. DebugTrace(TRACE_STATUS,("USTransfer: Transfer > max transfer size.\n"));
  552. }
  553. #endif
  554. ASSERT(PipeIndex <= MAX_NUM_PIPES);
  555. fNextReadBlocked = FALSE;
  556. if (fBulkIn) {
  557. //
  558. // Get exclusive access to each read buffer by using event
  559. //
  560. DebugTrace(TRACE_STATUS,("USTransfer: Waiting for Sync event for Pipe %d...\n", PipeIndex));
  561. if(NULL != pTimeout){
  562. LARGE_INTEGER Timeout;
  563. Timeout = RtlConvertLongToLargeInteger(-10*1000*1000*(*pTimeout));
  564. Status = KeWaitForSingleObject(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, Executive, KernelMode, FALSE, &Timeout);
  565. } else {
  566. Status = KeWaitForSingleObject(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, Executive, KernelMode, FALSE, 0);
  567. }
  568. if(STATUS_SUCCESS != Status){
  569. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  570. DebugTrace(TRACE_ERROR,("USTransfer: ERROR!! KeWaitForSingleObject() failed. Status=0x%x.\n", Status));
  571. goto USTransfer_return;
  572. }
  573. DebugTrace(TRACE_STATUS,("USTransfer: Get access to Pipe %d !!\n", PipeIndex));
  574. fNextReadBlocked = TRUE;
  575. //
  576. // If there is remaining data in the read pipe buffer, copy it into the irp transfer buffer.
  577. // Update the irp transfer pointer, number of bytes left to transfer, the read pipe buffer pointer
  578. // and the remaining number of bytes left in the read pipe buffer.
  579. //
  580. if (pde -> ReadPipeBuffer[PipeIndex].RemainingData > 0) {
  581. DebugTrace(TRACE_STATUS,("USTransfer: Copying %d buffered bytes into irp\n",
  582. pde -> ReadPipeBuffer[PipeIndex].RemainingData));
  583. siz = min(pde -> ReadPipeBuffer[PipeIndex].RemainingData, TransferSize);
  584. if (NULL == pBuffer) {
  585. //
  586. // There's no buffer. Try to use Mdl instead.
  587. //
  588. if(NULL == pMdl){
  589. //
  590. // Error: Both Buffer and Mdl are NULL.
  591. //
  592. Status = STATUS_INVALID_PARAMETER;
  593. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  594. DebugTrace(TRACE_ERROR,("USTransfer: ERROR!! Both Buffer&Mdl=NULL.\n"));
  595. goto USTransfer_return;
  596. } else {
  597. pMdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  598. pBuffer = MmGetSystemAddressForMdl(pMdl);
  599. if(NULL == pBuffer){
  600. Status = STATUS_INSUFFICIENT_RESOURCES;
  601. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  602. DebugTrace(TRACE_ERROR,("USTransfer: ERROR!! MmGetSystemAddressForMdl failed.\n"));
  603. goto USTransfer_return;
  604. }
  605. pMdl = NULL;
  606. }
  607. }
  608. ASSERT(siz > 0);
  609. ASSERT(pBuffer);
  610. ASSERT(pde -> ReadPipeBuffer[PipeIndex].pBuffer);
  611. RtlCopyMemory(pBuffer,pde -> ReadPipeBuffer[PipeIndex].pBuffer, siz);
  612. pde -> ReadPipeBuffer[PipeIndex].pBuffer += siz;
  613. pde -> ReadPipeBuffer[PipeIndex].RemainingData -= siz;
  614. ASSERT((LONG)pde -> ReadPipeBuffer[PipeIndex].RemainingData >= 0);
  615. if (0 == pde -> ReadPipeBuffer[PipeIndex].RemainingData) {
  616. DebugTrace(TRACE_STATUS,("USTransfer: read buffer emptied.\n"));
  617. pde -> ReadPipeBuffer[PipeIndex].pBuffer = pde -> ReadPipeBuffer[PipeIndex].pStartBuffer;
  618. }
  619. (PUCHAR)(pBuffer) += siz;
  620. TransferSize -= siz;
  621. ASSERT((LONG)TransferSize >= 0);
  622. // If the read irp was completely satisfied from data in the read buffer, then
  623. // unblock the next pending read and return success.
  624. if (0 == TransferSize) {
  625. pIrp -> IoStatus.Information = siz;
  626. Status = STATUS_SUCCESS;
  627. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  628. DebugTrace(TRACE_STATUS,("USTransfer: Irp satisfied from ReadBuffer.\n"));
  629. goto USTransfer_return;
  630. }
  631. } // if (pde -> ReadPipeBuffer[PipeIndex].RemainingData > 0)
  632. //
  633. // If this read is an integer number of usb packets, it will not affect
  634. // the state of the read buffer. Unblock the next waiting read in this case.
  635. //
  636. if (0 == TransferSize % MaxPacketSize) {
  637. DebugTrace(MAX_TRACE,("USTransfer: Unblocking next read.\n"));
  638. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  639. fNextReadBlocked = FALSE;
  640. }
  641. } // if (fBulkIn)
  642. //
  643. // Allocate and initialize Transfer Context
  644. //
  645. pTransferContext = USAllocatePool(NonPagedPool, sizeof(TRANSFER_CONTEXT));
  646. if (NULL == pTransferContext) {
  647. DebugTrace(TRACE_CRITICAL,("USTransfer: ERROR!! cannot allocated Transfer Context\n"));
  648. DEBUG_BREAKPOINT();
  649. Status = STATUS_INSUFFICIENT_RESOURCES;
  650. if (fNextReadBlocked) {
  651. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  652. }
  653. goto USTransfer_return;
  654. }
  655. RtlZeroMemory(pTransferContext, sizeof(TRANSFER_CONTEXT));
  656. //
  657. // Allocate and initialize URB
  658. //
  659. pUrb = USAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
  660. if (NULL == pUrb) {
  661. DebugTrace(TRACE_CRITICAL,("USTransfer: ERROR!! cannot allocated URB\n"));
  662. DEBUG_BREAKPOINT();
  663. Status = STATUS_INSUFFICIENT_RESOURCES;
  664. if (fNextReadBlocked) {
  665. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  666. }
  667. goto USTransfer_return;
  668. }
  669. RtlZeroMemory(pUrb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
  670. ASSERT(pUrb);
  671. ASSERT(pTransferContext);
  672. pTransferContext -> fDestinedForReadBuffer = FALSE;
  673. pTransferContext -> fNextReadBlocked = fNextReadBlocked;
  674. pTransferContext -> RemainingTransferLength = TransferSize;
  675. pTransferContext -> ChunkSize = TransferSize;
  676. pTransferContext -> PipeIndex = PipeIndex;
  677. pTransferContext -> pTransferBuffer = pBuffer;
  678. pTransferContext -> pTransferMdl = pMdl;
  679. pTransferContext -> NBytesTransferred = siz;
  680. pTransferContext -> pUrb = pUrb;
  681. pTransferContext -> pThisIrp = pIrp;
  682. pTransferContext -> pDeviceObject = pDeviceObject;
  683. //
  684. // IF the transfer is > MaxTransferSize, OR
  685. // IF the transfer is not a multiple of a USB packet AND it is a read transfer THEN
  686. // Check if we have been passed an MDL. If so, we need to turn it into a pointer so
  687. // that we can advance it when the transfer is broken up into smaller transfers.
  688. //
  689. if( (pTransferContext -> ChunkSize > MaxTransferSize)
  690. || ( (0 != pTransferContext -> ChunkSize % MaxPacketSize)
  691. && (fBulkIn) ) )
  692. {
  693. if (NULL == pTransferContext -> pTransferBuffer) {
  694. DebugTrace(TRACE_STATUS,("USTransfer: Converting MDL to buffer pointer.\n"));
  695. ASSERT(pTransferContext -> pTransferMdl);
  696. pTransferContext -> pTransferMdl ->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  697. pTransferContext -> pTransferBuffer = MmGetSystemAddressForMdl(pTransferContext -> pTransferMdl);
  698. pTransferContext -> pTransferMdl = NULL;
  699. ASSERT(pTransferContext -> pTransferBuffer);
  700. if(NULL == pTransferContext -> pTransferBuffer){
  701. Status = STATUS_INSUFFICIENT_RESOURCES;
  702. if (fNextReadBlocked) {
  703. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  704. }
  705. goto USTransfer_return;
  706. }
  707. }
  708. }
  709. //
  710. // If chunksize is bigger than MaxTransferSize, then set it to MaxTransferSize. The
  711. // transfer completion routine will issue additional transfers until the total size has
  712. // been transferred.
  713. //
  714. if (pTransferContext -> ChunkSize > MaxTransferSize) {
  715. pTransferContext -> ChunkSize = MaxTransferSize;
  716. }
  717. if (fBulkIn) {
  718. //
  719. // If this read is smaller than a USB packet, then issue a request for a
  720. // whole usb packet and make sure it goes into the read buffer first.
  721. //
  722. if (pTransferContext -> ChunkSize < MaxPacketSize) {
  723. DebugTrace(TRACE_STATUS,("USTransfer: Request is < packet size - transferring whole packet into read buffer.\n"));
  724. pTransferContext -> fDestinedForReadBuffer = TRUE;
  725. pTransferContext -> pOriginalTransferBuffer = pTransferContext -> pTransferBuffer; // save off original transfer ptr.
  726. pTransferContext -> pTransferBuffer = pde -> ReadPipeBuffer[PipeIndex].pBuffer;
  727. pTransferContext -> ChunkSize = MaxPacketSize;
  728. }
  729. //
  730. // Truncate the size of the read to an integer number of packets. If necessary,
  731. // the completion routine will handle any fractional remaining packets (with the read buffer).
  732. //
  733. pTransferContext -> ChunkSize = (pTransferContext -> ChunkSize / MaxPacketSize) * MaxPacketSize;
  734. }
  735. // ASSERT(pTransferContext -> RemainingTransferLength);
  736. // ASSERT((pTransferContext -> pTransferBuffer) || (pTransferContext -> pTransferMdl));
  737. ASSERT(pTransferContext -> pUrb);
  738. //
  739. // Initialize URB
  740. //
  741. UsbBuildInterruptOrBulkTransferRequest(pUrb,
  742. sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
  743. pde ->PipeInfo[PipeIndex].PipeHandle,
  744. pTransferContext -> pTransferBuffer,
  745. pTransferContext -> pTransferMdl,
  746. pTransferContext -> ChunkSize,
  747. USBD_SHORT_TRANSFER_OK,
  748. NULL);
  749. //
  750. // Setup stack location for lower driver
  751. //
  752. pNextIrpStack -> MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  753. pNextIrpStack -> MinorFunction = 0;
  754. pNextIrpStack -> Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_INTERNAL_USB_SUBMIT_URB;
  755. pNextIrpStack -> Parameters.Others.Argument1 = pUrb;
  756. if(NULL != pTimeout){
  757. pTransferContext -> Timeout = RtlConvertLongToLargeInteger(-10*1000*1000*(*pTimeout));
  758. //
  759. // Initialize timer and DPC.
  760. //
  761. KeInitializeTimer(&(pTransferContext->Timer));
  762. KeInitializeDpc(&(pTransferContext->TimerDpc),
  763. (PKDEFERRED_ROUTINE)USTimerDpc,
  764. (PVOID)pIrp);
  765. //
  766. // Enqueue timer object for timeout.
  767. //
  768. DebugTrace(TRACE_STATUS,("USTransfer: Set timeout(0x%x x 100n sec).\n", -(pTransferContext -> Timeout.QuadPart)));
  769. if(KeSetTimer(&(pTransferContext->Timer),
  770. pTransferContext -> Timeout,
  771. &(pTransferContext->TimerDpc)))
  772. {
  773. DebugTrace(TRACE_ERROR,("USTransfer: Timer object already exist.\n"));
  774. }
  775. } else {
  776. DebugTrace(TRACE_STATUS,("USTransfer: No timeout for this IRP.\n"));
  777. }
  778. //
  779. // Increment processing I/O count, will be decremented in completion.
  780. //
  781. USIncrementIoCount( pDeviceObject );
  782. //
  783. // Mark pending to IRP.
  784. //
  785. IoMarkIrpPending(pIrp);
  786. //
  787. // Set Completion Routine.
  788. //
  789. IoSetCompletionRoutine(pIrp,
  790. USTransferComplete,
  791. pTransferContext,
  792. TRUE,
  793. TRUE,
  794. TRUE);
  795. //
  796. // Call down.
  797. //
  798. fNeedCompletion = FALSE;
  799. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  800. if(STATUS_PENDING != Status){
  801. DebugTrace(TRACE_ERROR,("USTransfer: ERROR!! Lower driver returned 0x%x.\n", Status));
  802. }
  803. //
  804. // Must return STATUS_PENDING.
  805. //
  806. Status = STATUS_PENDING;
  807. USTransfer_return:
  808. if(fNeedCompletion){
  809. DebugTrace(TRACE_STATUS,("USTransfer: Completeing IRP now.\n"));
  810. //
  811. // Error or data satisfied from buffer.
  812. //
  813. pIrp->IoStatus.Status = Status;
  814. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  815. if(NULL != pUrb){
  816. USFreePool(pUrb);
  817. }
  818. if(NULL != pTransferContext){
  819. USFreePool(pTransferContext);
  820. }
  821. }
  822. DebugTrace(TRACE_PROC_LEAVE,("USTransfer: Leaving.. Status = 0x%x.\n", Status));
  823. return Status;
  824. }
  825. NTSTATUS
  826. USTransferComplete(
  827. IN PDEVICE_OBJECT pPassedDeviceObject,
  828. IN PIRP pIrp,
  829. IN PTRANSFER_CONTEXT pTransferContext
  830. )
  831. /*++
  832. Routine Description:
  833. Arguments:
  834. pPassedDeviceObject - Device object for a device.
  835. pIrp - Read/write request packet
  836. pTransferContext - context info for transfer
  837. Return Value:
  838. NT Status - STATUS_SUCCESS
  839. --*/
  840. {
  841. NTSTATUS Status;
  842. PIO_STACK_LOCATION pIrpStack;
  843. PIO_STACK_LOCATION pNextIrpStack;
  844. PUSBSCAN_DEVICE_EXTENSION pde;
  845. PDEVICE_OBJECT pDeviceObject;
  846. PURB pUrb;
  847. ULONG CompletedTransferLength;
  848. NTSTATUS CompletedTransferStatus;
  849. ULONG MaxPacketSize;
  850. BOOLEAN fShortTransfer = FALSE;
  851. BOOLEAN fBulkIn;
  852. ULONG PipeIndex;
  853. DebugTrace(TRACE_PROC_ENTER,("USTransferComplete: Enter.. - called. irp = 0x%p\n",pIrp));
  854. ASSERT(pIrp);
  855. ASSERT(pTransferContext);
  856. Status = pIrp -> IoStatus.Status;
  857. pIrp -> IoStatus.Information = 0;
  858. if(NULL == pPassedDeviceObject){
  859. pDeviceObject = pTransferContext->pDeviceObject;
  860. } else {
  861. pDeviceObject = pPassedDeviceObject;
  862. }
  863. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  864. pNextIrpStack = IoGetNextIrpStackLocation(pIrp);
  865. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  866. PipeIndex = pTransferContext -> PipeIndex;
  867. MaxPacketSize = pde -> PipeInfo[PipeIndex].MaximumPacketSize;
  868. fBulkIn = ((pde->PipeInfo[PipeIndex].PipeType == UsbdPipeTypeBulk)
  869. && (pde->PipeInfo[PipeIndex].EndpointAddress & BULKIN_FLAG));
  870. pUrb = pTransferContext -> pUrb;
  871. CompletedTransferLength = pUrb -> UrbBulkOrInterruptTransfer.TransferBufferLength;
  872. CompletedTransferStatus = pUrb -> UrbBulkOrInterruptTransfer.Hdr.Status;
  873. if( (STATUS_SUCCESS == CompletedTransferStatus)
  874. && (STATUS_SUCCESS == Status) )
  875. {
  876. if (CompletedTransferLength < pTransferContext -> ChunkSize) {
  877. DebugTrace(TRACE_STATUS,("USTransferComplete: Short transfer received. Length = %d, ChunkSize = %d\n",
  878. CompletedTransferLength, pTransferContext -> ChunkSize));
  879. fShortTransfer = TRUE;
  880. }
  881. //
  882. // If this transfer went into the read buffer, then this should be the final read
  883. // of either a multipart larger read, or a single very small read (< single usb packet).
  884. // In either case, we need to copy the appropriate amount of data into the user's irp, update the
  885. // read buffer variables, and complete the user's irp.
  886. //
  887. if (pTransferContext -> fDestinedForReadBuffer) {
  888. DebugTrace(TRACE_STATUS,("USTransferComplete: Read transfer completed. size = %d\n", CompletedTransferLength));
  889. ASSERT(CompletedTransferLength <= MaxPacketSize);
  890. ASSERT(pTransferContext -> pOriginalTransferBuffer);
  891. ASSERT(pTransferContext -> pTransferBuffer);
  892. ASSERT(pde -> ReadPipeBuffer[PipeIndex].pBuffer == pTransferContext -> pTransferBuffer);
  893. ASSERT(pTransferContext -> RemainingTransferLength < MaxPacketSize);
  894. pde -> ReadPipeBuffer[PipeIndex].RemainingData = CompletedTransferLength;
  895. CompletedTransferLength = min(pTransferContext -> RemainingTransferLength,
  896. pde -> ReadPipeBuffer[PipeIndex].RemainingData);
  897. ASSERT(CompletedTransferLength < MaxPacketSize);
  898. RtlCopyMemory(pTransferContext -> pOriginalTransferBuffer,
  899. pde -> ReadPipeBuffer[PipeIndex].pBuffer,
  900. CompletedTransferLength);
  901. pde -> ReadPipeBuffer[PipeIndex].pBuffer += CompletedTransferLength;
  902. pde -> ReadPipeBuffer[PipeIndex].RemainingData -= CompletedTransferLength;
  903. if (0 == pde -> ReadPipeBuffer[PipeIndex].RemainingData) {
  904. DebugTrace(TRACE_STATUS,("USTransferComplete: Read buffer emptied.\n"));
  905. pde -> ReadPipeBuffer[PipeIndex].pBuffer = pde -> ReadPipeBuffer[PipeIndex].pStartBuffer;
  906. }
  907. pTransferContext -> pTransferBuffer = pTransferContext -> pOriginalTransferBuffer;
  908. }
  909. //
  910. // Update the number of bytes transferred, remaining bytes to transfer
  911. // and advance the transfer buffer pointer appropriately.
  912. //
  913. pTransferContext -> NBytesTransferred += CompletedTransferLength;
  914. if (pTransferContext -> pTransferBuffer) {
  915. pTransferContext -> pTransferBuffer += CompletedTransferLength;
  916. }
  917. pTransferContext -> RemainingTransferLength -= CompletedTransferLength;
  918. //
  919. // If there is still data to transfer and the previous transfer was NOT a
  920. // short transfer, then issue another request to move the next chunk of data.
  921. //
  922. if (pTransferContext -> RemainingTransferLength > 0) {
  923. if (!fShortTransfer) {
  924. DebugTrace(TRACE_STATUS,("USTransferComplete: Queuing next chunk. RemainingSize = %d, pBuffer = 0x%p\n",
  925. pTransferContext -> RemainingTransferLength,
  926. pTransferContext -> pTransferBuffer
  927. ));
  928. if (pTransferContext -> RemainingTransferLength < pTransferContext -> ChunkSize) {
  929. pTransferContext -> ChunkSize = pTransferContext -> RemainingTransferLength;
  930. }
  931. //
  932. // Reinitialize URB
  933. //
  934. // If the next transfer is < than 1 packet, change it's destination to be
  935. // the read buffer. When this transfer completes, the appropriate amount of data will be
  936. // copied out of the read buffer and into the user's irp. Left over data in the read buffer
  937. // will be available for subsequent reads.
  938. //
  939. if (fBulkIn) {
  940. if (pTransferContext -> ChunkSize < MaxPacketSize) {
  941. pTransferContext -> fDestinedForReadBuffer = TRUE;
  942. pTransferContext -> pOriginalTransferBuffer = pTransferContext -> pTransferBuffer;
  943. pTransferContext -> pTransferBuffer = pde -> ReadPipeBuffer[PipeIndex].pBuffer;
  944. pTransferContext -> ChunkSize = MaxPacketSize;
  945. }
  946. pTransferContext -> ChunkSize = (pTransferContext -> ChunkSize / MaxPacketSize) * MaxPacketSize;
  947. }
  948. ASSERT(pTransferContext -> ChunkSize >= MaxPacketSize);
  949. ASSERT(0 == pTransferContext -> ChunkSize % MaxPacketSize);
  950. UsbBuildInterruptOrBulkTransferRequest(pUrb,
  951. sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
  952. pde -> PipeInfo[PipeIndex].PipeHandle,
  953. pTransferContext -> pTransferBuffer,
  954. NULL,
  955. pTransferContext -> ChunkSize,
  956. USBD_SHORT_TRANSFER_OK,
  957. NULL);
  958. IoSetCompletionRoutine(pIrp,
  959. USTransferComplete,
  960. pTransferContext,
  961. TRUE,
  962. TRUE,
  963. FALSE);
  964. //
  965. // Setup stack location for lower driver
  966. //
  967. pNextIrpStack -> MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  968. pNextIrpStack -> MinorFunction = 0;
  969. pNextIrpStack -> Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_INTERNAL_USB_SUBMIT_URB;
  970. pNextIrpStack -> Parameters.Others.Argument1 = pUrb;
  971. IoCallDriver(pde -> pStackDeviceObject, pIrp);
  972. Status = STATUS_MORE_PROCESSING_REQUIRED;
  973. goto USTransferComplete_return;
  974. } // if (!fShortTransfer)
  975. } // if (pTransferContext -> RemainingTransferLength > 0)
  976. DebugTrace(TRACE_STATUS,("USTransferComplete: Completing transfer request. nbytes transferred = %d, irp = 0x%p\n",
  977. pTransferContext -> NBytesTransferred, pIrp));
  978. pIrp -> IoStatus.Information = pTransferContext -> NBytesTransferred;
  979. #if DBG
  980. {
  981. PUCHAR pDumpBuf = NULL;
  982. if(NULL != pTransferContext -> pTransferBuffer){
  983. pDumpBuf = pTransferContext -> pTransferBuffer;
  984. } else if (NULL != pTransferContext -> pTransferMdl) {
  985. pTransferContext -> pTransferMdl ->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  986. pDumpBuf = MmGetSystemAddressForMdl(pTransferContext -> pTransferMdl);
  987. }
  988. if(NULL != pDumpBuf){
  989. MyDumpMemory(pDumpBuf,
  990. pTransferContext -> NBytesTransferred,
  991. TRUE);
  992. }
  993. }
  994. #endif // DBG
  995. } else {
  996. DebugTrace(TRACE_ERROR,("USTransferComplete: ERROR!! Transfer error. USB status = 0x%X, status = 0x%X\n",
  997. CompletedTransferStatus,
  998. Status));
  999. if (USBD_STATUS_CANCELED == CompletedTransferStatus) {
  1000. Status = STATUS_CANCELLED;
  1001. }
  1002. }
  1003. //
  1004. // Running here means IRP is completed.
  1005. //
  1006. pIrp -> IoStatus.Status = Status;
  1007. if (pTransferContext -> fNextReadBlocked) {
  1008. KeSetEvent(&pde -> ReadPipeBuffer[PipeIndex].ReadSyncEvent, 1, FALSE);
  1009. }
  1010. //
  1011. // Dequeue timer object if exist.
  1012. //
  1013. if( (0 != pTransferContext -> Timeout.QuadPart)
  1014. && (!KeReadStateTimer(&(pTransferContext->Timer))) )
  1015. {
  1016. KeCancelTimer(&(pTransferContext->Timer));
  1017. }
  1018. //
  1019. // Clean-up
  1020. //
  1021. if(pTransferContext->pUrb){
  1022. USFreePool(pTransferContext->pUrb);
  1023. }
  1024. USDecrementIoCount(pTransferContext->pDeviceObject);
  1025. USFreePool(pTransferContext);
  1026. USTransferComplete_return:
  1027. DebugTrace(TRACE_PROC_LEAVE,("USTransferComplete: Leaving.. Status=%x.\n", Status));
  1028. return Status;
  1029. }
  1030. ULONG
  1031. USGetPipeIndexToUse(
  1032. IN PDEVICE_OBJECT pDeviceObject,
  1033. IN PIRP pIrp,
  1034. IN ULONG PipeIndex
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. Arguments:
  1039. pDeviceObject - Device object for a device.
  1040. pIrp - request packet
  1041. PipeIndex - Default pipe to use
  1042. Return Value:
  1043. ULONG - PipeIndex to use
  1044. --*/
  1045. {
  1046. PIO_STACK_LOCATION pIrpStack;
  1047. PUSBSCAN_DEVICE_EXTENSION pde;
  1048. PFILE_OBJECT fileObject;
  1049. PUSBSCAN_FILE_CONTEXT pFileContext;
  1050. LONG StoredIndex;
  1051. ULONG IndexToUse;
  1052. PAGED_CODE();
  1053. DebugTrace(TRACE_PROC_ENTER,("USGetPipeIndexToUse: Enter..\n"));
  1054. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1055. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  1056. fileObject = pIrpStack->FileObject;
  1057. pFileContext = fileObject->FsContext;
  1058. ASSERT(NULL != pFileContext);
  1059. StoredIndex = pFileContext->PipeIndex;
  1060. if( (StoredIndex >= 0) && (StoredIndex < MAX_NUM_PIPES) ){
  1061. if(pde->PipeInfo[PipeIndex].PipeType == pde->PipeInfo[StoredIndex].PipeType){
  1062. IndexToUse = (ULONG)StoredIndex;
  1063. } else {
  1064. IndexToUse = PipeIndex;
  1065. }
  1066. } else {
  1067. if(-1 != StoredIndex){
  1068. DebugTrace(TRACE_WARNING,("USGetPipeIndexToUse: WARINING!! Specified pipe index(0x%X) is incorrect. Using default." ,StoredIndex));
  1069. }
  1070. IndexToUse = PipeIndex;
  1071. }
  1072. DebugTrace(TRACE_PROC_LEAVE,("USGetPipeIndexToUse: Leaving.. passed=%d, returning=%d.\n",PipeIndex, IndexToUse));
  1073. return IndexToUse;
  1074. }
  1075. VOID
  1076. USTimerDpc(
  1077. IN PKDPC pDpc,
  1078. IN PVOID pIrp,
  1079. IN PVOID SystemArgument1,
  1080. IN PVOID SystemArgument2
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. DPC callback routine for timer.
  1085. Arguments:
  1086. pDpc - Pointer to DPC object.
  1087. pIrp - Passed context.
  1088. SystemArgument1 - system reserved.
  1089. SystemArgument2 - system reserved.
  1090. Return Value:
  1091. VOID
  1092. --*/
  1093. {
  1094. DebugTrace(TRACE_WARNING,("USTimerDpc: IRP(0x%x) timeout.\n", pIrp));
  1095. IoCancelIrp((PIRP)pIrp);
  1096. }