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.

1461 lines
47 KiB

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