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.

852 lines
23 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. OCRW.C
  5. Abstract:
  6. This source file contains the dispatch routines which handle
  7. opening, closing, reading, and writing to the device, i.e.:
  8. IRP_MJ_CREATE
  9. IRP_MJ_CLOSE
  10. IRP_MJ_READ
  11. IRP_MJ_WRITE
  12. Environment:
  13. kernel mode
  14. Revision History:
  15. 06-01-98 : started rewrite
  16. --*/
  17. //*****************************************************************************
  18. // I N C L U D E S
  19. //*****************************************************************************
  20. #include <wdm.h>
  21. #include <usbdi.h>
  22. #include <usbdlib.h>
  23. #include "i82930.h"
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE, I82930_Create)
  26. #pragma alloc_text(PAGE, I82930_Close)
  27. #pragma alloc_text(PAGE, I82930_ReadWrite)
  28. #pragma alloc_text(PAGE, I82930_BuildAsyncUrb)
  29. #pragma alloc_text(PAGE, I82930_BuildIsoUrb)
  30. #pragma alloc_text(PAGE, I82930_GetCurrentFrame)
  31. #pragma alloc_text(PAGE, I82930_ResetPipe)
  32. #pragma alloc_text(PAGE, I82930_AbortPipe)
  33. #endif
  34. //******************************************************************************
  35. //
  36. // I82930_Create()
  37. //
  38. // Dispatch routine which handles IRP_MJ_CREATE
  39. //
  40. //******************************************************************************
  41. NTSTATUS
  42. I82930_Create (
  43. IN PDEVICE_OBJECT DeviceObject,
  44. IN PIRP Irp
  45. )
  46. {
  47. PDEVICE_EXTENSION deviceExtension;
  48. PIO_STACK_LOCATION irpStack;
  49. PFILE_OBJECT fileObject;
  50. UCHAR pipeIndex;
  51. PI82930_PIPE pipe;
  52. NTSTATUS ntStatus;
  53. DBGPRINT(2, ("enter: I82930_Create\n"));
  54. LOGENTRY('CREA', DeviceObject, Irp, 0);
  55. DBGFBRK(DBGF_BRK_CREATE);
  56. deviceExtension = DeviceObject->DeviceExtension;
  57. INCREMENT_OPEN_COUNT(deviceExtension);
  58. if (deviceExtension->AcceptingRequests)
  59. {
  60. irpStack = IoGetCurrentIrpStackLocation(Irp);
  61. fileObject = irpStack->FileObject;
  62. if (fileObject->FileName.Length != 0)
  63. {
  64. if ((fileObject->FileName.Length == 3*sizeof(WCHAR)) &&
  65. (fileObject->FileName.Buffer[0] == '\\') &&
  66. (fileObject->FileName.Buffer[1] >= '0' ) &&
  67. (fileObject->FileName.Buffer[1] <= '9' ) &&
  68. (fileObject->FileName.Buffer[2] >= '0' ) &&
  69. (fileObject->FileName.Buffer[2] <= '9' ))
  70. {
  71. pipeIndex = ((fileObject->FileName.Buffer[1] - '0') * 10 +
  72. (fileObject->FileName.Buffer[2] - '0'));
  73. if (pipeIndex < deviceExtension->InterfaceInfo->NumberOfPipes)
  74. {
  75. pipe = &deviceExtension->PipeList[pipeIndex];
  76. #if 0
  77. if (pipe->Opened)
  78. {
  79. // Pipe already open
  80. //
  81. DBGPRINT(2, ("Pipe already open\n"));
  82. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  83. }
  84. else
  85. #endif
  86. {
  87. // Good to open the pipe
  88. //
  89. DBGPRINT(2, ("Opened pipe %2d %08X\n",
  90. pipeIndex, pipe));
  91. pipe->Opened = TRUE;
  92. fileObject->FsContext = pipe;
  93. ntStatus = STATUS_SUCCESS;
  94. }
  95. }
  96. else
  97. {
  98. // Pipe index too big
  99. //
  100. DBGPRINT(2, ("Pipe index too big\n"));
  101. ntStatus = STATUS_NO_SUCH_DEVICE;
  102. }
  103. }
  104. else
  105. {
  106. // Pipe name bad format
  107. //
  108. DBGPRINT(2, ("Pipe name bad format\n"));
  109. ntStatus = STATUS_NO_SUCH_DEVICE;
  110. }
  111. }
  112. else
  113. {
  114. // Open entire device, not an individual pipe
  115. //
  116. DBGPRINT(2, ("Opened device\n"));
  117. fileObject->FsContext = NULL;
  118. ntStatus = STATUS_SUCCESS;
  119. }
  120. }
  121. else
  122. {
  123. ntStatus = STATUS_DELETE_PENDING;
  124. }
  125. Irp->IoStatus.Status = ntStatus;
  126. Irp->IoStatus.Information = 0;
  127. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  128. DBGPRINT(2, ("exit: I82930_Create %08X\n", ntStatus));
  129. LOGENTRY('crea', ntStatus, 0, 0);
  130. if (ntStatus != STATUS_SUCCESS)
  131. {
  132. DECREMENT_OPEN_COUNT(deviceExtension);
  133. }
  134. return ntStatus;
  135. }
  136. //******************************************************************************
  137. //
  138. // I82930_Close()
  139. //
  140. // Dispatch routine which handles IRP_MJ_CLOSE
  141. //
  142. //******************************************************************************
  143. NTSTATUS
  144. I82930_Close (
  145. IN PDEVICE_OBJECT DeviceObject,
  146. IN PIRP Irp
  147. )
  148. {
  149. PDEVICE_EXTENSION deviceExtension;
  150. PIO_STACK_LOCATION irpStack;
  151. PFILE_OBJECT fileObject;
  152. PI82930_PIPE pipe;
  153. DBGPRINT(2, ("enter: I82930_Close\n"));
  154. LOGENTRY('CLOS', DeviceObject, Irp, 0);
  155. DBGFBRK(DBGF_BRK_CLOSE);
  156. deviceExtension = DeviceObject->DeviceExtension;
  157. irpStack = IoGetCurrentIrpStackLocation(Irp);
  158. fileObject = irpStack->FileObject;
  159. pipe = fileObject->FsContext;
  160. if (pipe != NULL)
  161. {
  162. DBGPRINT(2, ("Closed pipe %2d %08X\n",
  163. pipe->PipeIndex, pipe));
  164. pipe->Opened = FALSE;
  165. }
  166. else
  167. {
  168. DBGPRINT(2, ("Closed device\n"));
  169. }
  170. Irp->IoStatus.Status = STATUS_SUCCESS;
  171. Irp->IoStatus.Information = 0;
  172. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  173. DBGPRINT(2, ("exit: I82930_Close\n"));
  174. LOGENTRY('clos', 0, 0, 0);
  175. DECREMENT_OPEN_COUNT(deviceExtension);
  176. return STATUS_SUCCESS;
  177. }
  178. //******************************************************************************
  179. //
  180. // I82930_ReadWrite()
  181. //
  182. // Dispatch routine which handles IRP_MJ_READ and IRP_MJ_WRITE
  183. //
  184. //******************************************************************************
  185. NTSTATUS
  186. I82930_ReadWrite (
  187. IN PDEVICE_OBJECT DeviceObject,
  188. IN PIRP Irp
  189. )
  190. {
  191. PDEVICE_EXTENSION deviceExtension;
  192. PIO_STACK_LOCATION irpStack;
  193. PIO_STACK_LOCATION nextStack;
  194. PFILE_OBJECT fileObject;
  195. PI82930_PIPE pipe;
  196. PURB urb;
  197. NTSTATUS ntStatus;
  198. DBGPRINT(2, ("enter: I82930_ReadWrite\n"));
  199. LOGENTRY('RW ', DeviceObject, Irp, 0);
  200. DBGFBRK(DBGF_BRK_READWRITE);
  201. deviceExtension = DeviceObject->DeviceExtension;
  202. if (!deviceExtension->AcceptingRequests)
  203. {
  204. ntStatus = STATUS_DELETE_PENDING;
  205. goto I82930_ReadWrite_Reject;
  206. }
  207. irpStack = IoGetCurrentIrpStackLocation(Irp);
  208. nextStack = IoGetNextIrpStackLocation(Irp);
  209. fileObject = irpStack->FileObject;
  210. pipe = fileObject->FsContext;
  211. // Only allow Reads and Writes on individual pipes, not the entire device
  212. //
  213. if (pipe == NULL)
  214. {
  215. ntStatus = STATUS_INVALID_PARAMETER;
  216. goto I82930_ReadWrite_Reject;
  217. }
  218. // Only allow Reads on IN endpoints and Writes on OUT endpoints
  219. //
  220. if ((USB_ENDPOINT_DIRECTION_OUT(pipe->PipeInfo->EndpointAddress) &&
  221. irpStack->MajorFunction != IRP_MJ_WRITE) ||
  222. (USB_ENDPOINT_DIRECTION_IN(pipe->PipeInfo->EndpointAddress) &&
  223. irpStack->MajorFunction != IRP_MJ_READ))
  224. {
  225. ntStatus = STATUS_INVALID_PARAMETER;
  226. goto I82930_ReadWrite_Reject;
  227. }
  228. // Don't allow a Read or Write on a zero bandwidth endpoint
  229. //
  230. if (pipe->PipeInfo->MaximumPacketSize == 0)
  231. {
  232. ntStatus = STATUS_INVALID_PARAMETER;
  233. goto I82930_ReadWrite_Reject;
  234. }
  235. // Build either a URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
  236. // or a URB_FUNCTION_ISOCH_TRANSFER based on the PipeType
  237. //
  238. switch (pipe->PipeInfo->PipeType)
  239. {
  240. case UsbdPipeTypeBulk:
  241. case UsbdPipeTypeInterrupt:
  242. urb = I82930_BuildAsyncUrb(DeviceObject,
  243. Irp,
  244. pipe);
  245. break;
  246. case UsbdPipeTypeIsochronous:
  247. urb = I82930_BuildIsoUrb(DeviceObject,
  248. Irp,
  249. pipe);
  250. break;
  251. default:
  252. ntStatus = STATUS_INVALID_PARAMETER;
  253. goto I82930_ReadWrite_Reject;
  254. }
  255. if (urb == NULL)
  256. {
  257. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  258. goto I82930_ReadWrite_Reject;
  259. }
  260. // Initialize the Irp stack parameters for the next lower driver
  261. // to submit the URB
  262. //
  263. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  264. nextStack->Parameters.DeviceIoControl.IoControlCode =
  265. IOCTL_INTERNAL_USB_SUBMIT_URB;
  266. nextStack->Parameters.Others.Argument1 = urb;
  267. // Set a completion routine which will update the Irp->IoStatus.Information
  268. // with the URB TransferBufferLength and then free the URB.
  269. //
  270. IoSetCompletionRoutine(Irp,
  271. I82930_ReadWrite_Complete,
  272. urb,
  273. TRUE,
  274. TRUE,
  275. TRUE);
  276. // Submit the URB to the next lower driver
  277. //
  278. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  279. Irp);
  280. goto I82930_Read_Done;
  281. I82930_ReadWrite_Reject:
  282. Irp->IoStatus.Status = ntStatus;
  283. Irp->IoStatus.Information = 0;
  284. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  285. I82930_Read_Done:
  286. DBGPRINT(2, ("exit: I82930_ReadWrite %08X\n", ntStatus));
  287. LOGENTRY('rw ', ntStatus, 0, 0);
  288. return ntStatus;
  289. }
  290. //******************************************************************************
  291. //
  292. // I82930_ReadWrite_Complete()
  293. //
  294. //******************************************************************************
  295. NTSTATUS
  296. I82930_ReadWrite_Complete (
  297. IN PDEVICE_OBJECT DeviceObject,
  298. IN PIRP Irp,
  299. IN PVOID Context
  300. )
  301. {
  302. PURB urb;
  303. urb = (PURB)Context;
  304. LOGENTRY('RWC1', DeviceObject, Irp, urb);
  305. LOGENTRY('RWC2', urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
  306. urb->UrbHeader.Status, 0);
  307. DBGPRINT(3, ("ReadWrite_Complete: Length 0x%08X, Urb Status 0x%08X, Irp Status 0x%08X\n",
  308. urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
  309. urb->UrbHeader.Status,
  310. Irp->IoStatus.Status));
  311. // Propagate the pending flag back up the Irp stack
  312. //
  313. if (Irp->PendingReturned)
  314. {
  315. IoMarkIrpPending(Irp);
  316. }
  317. Irp->IoStatus.Information =
  318. urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  319. ExFreePool(urb);
  320. return STATUS_SUCCESS;
  321. }
  322. //******************************************************************************
  323. //
  324. // I82930_BuildAsyncUrb()
  325. //
  326. // Allocates and initializes a URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
  327. // request URB
  328. //
  329. //******************************************************************************
  330. PURB
  331. I82930_BuildAsyncUrb (
  332. IN PDEVICE_OBJECT DeviceObject,
  333. IN PIRP Irp,
  334. IN PI82930_PIPE Pipe
  335. )
  336. {
  337. PIO_STACK_LOCATION irpStack;
  338. LARGE_INTEGER byteOffset;
  339. ULONG transferLength;
  340. USHORT urbSize;
  341. PURB urb;
  342. DBGPRINT(2, ("enter: I82930_BuildAsyncUrb\n"));
  343. irpStack = IoGetCurrentIrpStackLocation(Irp);
  344. // We will use the ByteOffset to control the USBD_SHORT_TRANSFER_OK flag
  345. //
  346. byteOffset = irpStack->Parameters.Read.ByteOffset;
  347. // Get the transfer length from the MDL
  348. //
  349. if (Irp->MdlAddress)
  350. {
  351. transferLength = MmGetMdlByteCount(Irp->MdlAddress);
  352. }
  353. else
  354. {
  355. transferLength = 0;
  356. }
  357. urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  358. urb = ExAllocatePool(NonPagedPool, urbSize);
  359. if (urb)
  360. {
  361. RtlZeroMemory(urb, urbSize);
  362. urb->UrbHeader.Length = urbSize;
  363. urb->UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  364. urb->UrbBulkOrInterruptTransfer.PipeHandle =
  365. Pipe->PipeInfo->PipeHandle;
  366. if (!byteOffset.HighPart)
  367. {
  368. urb->UrbBulkOrInterruptTransfer.TransferFlags =
  369. USBD_SHORT_TRANSFER_OK;
  370. }
  371. urb->UrbBulkOrInterruptTransfer.TransferBufferLength =
  372. transferLength;
  373. urb->UrbBulkOrInterruptTransfer.TransferBuffer =
  374. NULL;
  375. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL =
  376. Irp->MdlAddress;
  377. urb->UrbBulkOrInterruptTransfer.UrbLink =
  378. NULL;
  379. }
  380. DBGPRINT(2, ("exit: I82930_BuildAsyncUrb %08X\n", urb));
  381. return urb;
  382. }
  383. //******************************************************************************
  384. //
  385. // I82930_BuildIsoUrb()
  386. //
  387. // Allocates and initializes a URB_FUNCTION_ISOCH_TRANSFER request URB
  388. //
  389. //******************************************************************************
  390. PURB
  391. I82930_BuildIsoUrb (
  392. IN PDEVICE_OBJECT DeviceObject,
  393. IN PIRP Irp,
  394. IN PI82930_PIPE Pipe
  395. )
  396. {
  397. PIO_STACK_LOCATION irpStack;
  398. LARGE_INTEGER byteOffset;
  399. ULONG transferLength;
  400. ULONG packetSize;
  401. ULONG numPackets;
  402. ULONG packetIndex;
  403. ULONG urbSize;
  404. PURB urb;
  405. DBGPRINT(2, ("enter: I82930_BuildIsoUrb\n"));
  406. irpStack = IoGetCurrentIrpStackLocation(Irp);
  407. // We will use the ByteOffset for +/- offset to current frame
  408. //
  409. byteOffset = irpStack->Parameters.Read.ByteOffset;
  410. // Get the transfer length from the MDL
  411. //
  412. if (Irp->MdlAddress)
  413. {
  414. transferLength = MmGetMdlByteCount(Irp->MdlAddress);
  415. }
  416. else
  417. {
  418. transferLength = 0;
  419. }
  420. // Calculate the number of Iso packets based on the transfer length
  421. // and the endpoint MaxPacketSize
  422. //
  423. packetSize = Pipe->PipeInfo->MaximumPacketSize;
  424. numPackets = transferLength / packetSize;
  425. if (numPackets * packetSize < transferLength)
  426. {
  427. numPackets++;
  428. }
  429. urbSize = GET_ISO_URB_SIZE(numPackets);
  430. urb = ExAllocatePool(NonPagedPool, urbSize);
  431. if (urb)
  432. {
  433. RtlZeroMemory(urb, urbSize);
  434. urb->UrbHeader.Length = (USHORT)urbSize;
  435. urb->UrbHeader.Function = URB_FUNCTION_ISOCH_TRANSFER;
  436. urb->UrbBulkOrInterruptTransfer.PipeHandle =
  437. Pipe->PipeInfo->PipeHandle;
  438. urb->UrbIsochronousTransfer.TransferFlags =
  439. 0;
  440. urb->UrbIsochronousTransfer.TransferBufferLength =
  441. transferLength;
  442. urb->UrbIsochronousTransfer.TransferBuffer =
  443. NULL;
  444. urb->UrbIsochronousTransfer.TransferBufferMDL =
  445. Irp->MdlAddress;
  446. urb->UrbIsochronousTransfer.UrbLink =
  447. NULL;
  448. // Use the ByteOffset for +/- offset to current frame
  449. //
  450. if (byteOffset.HighPart)
  451. {
  452. urb->UrbIsochronousTransfer.StartFrame =
  453. I82930_GetCurrentFrame(DeviceObject, Irp) +
  454. byteOffset.LowPart;
  455. }
  456. else
  457. {
  458. urb->UrbIsochronousTransfer.StartFrame =
  459. 0;
  460. urb->UrbIsochronousTransfer.TransferFlags |=
  461. USBD_START_ISO_TRANSFER_ASAP;
  462. }
  463. urb->UrbIsochronousTransfer.NumberOfPackets =
  464. numPackets;
  465. for (packetIndex = 0; packetIndex < numPackets; packetIndex++)
  466. {
  467. urb->UrbIsochronousTransfer.IsoPacket[packetIndex].Offset
  468. = packetIndex * packetSize;
  469. }
  470. }
  471. DBGPRINT(2, ("exit: I82930_BuildIsoUrb %08X\n", urb));
  472. return urb;
  473. }
  474. //******************************************************************************
  475. //
  476. // I82930_CompletionStop()
  477. //
  478. // Completion Routine which just stops further completion of the Irp
  479. //
  480. //******************************************************************************
  481. NTSTATUS
  482. I82930_CompletionStop (
  483. IN PDEVICE_OBJECT DeviceObject,
  484. IN PIRP Irp,
  485. IN PVOID Context
  486. )
  487. {
  488. return STATUS_MORE_PROCESSING_REQUIRED;
  489. }
  490. //******************************************************************************
  491. //
  492. // I82930_GetCurrentFrame()
  493. //
  494. // Returns the current frame on the bus to which the device is attached.
  495. //
  496. // The next stack frame of the Irp is used, but the Irp is not completed.
  497. //
  498. //******************************************************************************
  499. ULONG
  500. I82930_GetCurrentFrame (
  501. IN PDEVICE_OBJECT DeviceObject,
  502. IN PIRP Irp
  503. )
  504. {
  505. PDEVICE_EXTENSION deviceExtension;
  506. PIO_STACK_LOCATION nextStack;
  507. NTSTATUS ntStatus;
  508. struct _URB_GET_CURRENT_FRAME_NUMBER urb;
  509. deviceExtension = DeviceObject->DeviceExtension;
  510. // Initialize the URB
  511. //
  512. urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER;
  513. urb.Hdr.Length = sizeof(urb);
  514. urb.FrameNumber = (ULONG)-1;
  515. // Set the IRP parameters to pass the URB down the stack
  516. //
  517. nextStack = IoGetNextIrpStackLocation(Irp);
  518. nextStack->Parameters.Others.Argument1 = &urb;
  519. nextStack->Parameters.DeviceIoControl.IoControlCode =
  520. IOCTL_INTERNAL_USB_SUBMIT_URB;
  521. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  522. // Since this Irp is borrowed for URB_FUNCTION_GET_CURRENT_FRAME_NUMBER
  523. // before it is passed down later for the real URB request after this
  524. // routine returns, set a completion routine which stop further completion
  525. // of the Irp.
  526. //
  527. IoSetCompletionRoutine(
  528. Irp,
  529. I82930_CompletionStop,
  530. NULL, // Context
  531. TRUE, // InvokeOnSuccess
  532. TRUE, // InvokeOnError
  533. TRUE // InvokeOnCancel
  534. );
  535. // Now pass the Irp down the stack
  536. //
  537. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  538. Irp);
  539. ASSERT(ntStatus != STATUS_PENDING);
  540. // Don't need to wait for completion because JD guarantees that
  541. // URB_FUNCTION_GET_CURRENT_FRAME_NUMBER will never return STATUS_PENDING
  542. return urb.FrameNumber;
  543. }
  544. //******************************************************************************
  545. //
  546. // I82930_ResetPipe()
  547. //
  548. // This will reset the host pipe to Data0 and should also reset the device
  549. // endpoint to Data0 for Bulk and Interrupt pipes by issuing a Clear_Feature
  550. // Endpoint_Stall to the device endpoint.
  551. //
  552. // For Iso pipes this will set the virgin state of pipe so that ASAP
  553. // transfers begin with the current bus frame instead of the next frame
  554. // after the last transfer occurred.
  555. //
  556. // Iso endpoints do not use the data toggle (all Iso packets are Data0).
  557. // However, it may be useful to issue a Clear_Feature Endpoint_Stall to a
  558. // device Iso endpoint.
  559. //
  560. // Must be called at IRQL <= DISPATCH_LEVEL
  561. //
  562. //******************************************************************************
  563. NTSTATUS
  564. I82930_ResetPipe (
  565. IN PDEVICE_OBJECT DeviceObject,
  566. IN PI82930_PIPE Pipe,
  567. IN BOOLEAN IsoClearStall
  568. )
  569. {
  570. PURB urb;
  571. NTSTATUS ntStatus;
  572. DBGPRINT(2, ("enter: I82930_ResetPipe\n"));
  573. LOGENTRY('RESP', DeviceObject, Pipe, IsoClearStall);
  574. // Allocate URB for RESET_PIPE request
  575. //
  576. urb = ExAllocatePool(NonPagedPool,
  577. sizeof(struct _URB_PIPE_REQUEST));
  578. if (urb != NULL)
  579. {
  580. // Initialize RESET_PIPE request URB
  581. //
  582. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  583. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  584. urb->UrbPipeRequest.PipeHandle = Pipe->PipeInfo->PipeHandle;
  585. // Submit RESET_PIPE request URB
  586. //
  587. ntStatus = I82930_SyncSendUsbRequest(DeviceObject, urb);
  588. // Done with URB for RESET_PIPE request, free it
  589. //
  590. ExFreePool(urb);
  591. }
  592. else
  593. {
  594. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  595. }
  596. // Issue Clear_Feature Endpoint_Stall request for Iso pipe, if desired
  597. //
  598. if (NT_SUCCESS(ntStatus) &&
  599. IsoClearStall &&
  600. (Pipe->PipeInfo->PipeType == UsbdPipeTypeIsochronous))
  601. {
  602. // Allocate URB for CONTROL_FEATURE request
  603. //
  604. urb = ExAllocatePool(NonPagedPool,
  605. sizeof(struct _URB_CONTROL_FEATURE_REQUEST));
  606. if (urb != NULL)
  607. {
  608. // Initialize CONTROL_FEATURE request URB
  609. //
  610. urb->UrbHeader.Length = sizeof (struct _URB_CONTROL_FEATURE_REQUEST);
  611. urb->UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT;
  612. urb->UrbControlFeatureRequest.UrbLink = NULL;
  613. urb->UrbControlFeatureRequest.FeatureSelector = USB_FEATURE_ENDPOINT_STALL;
  614. urb->UrbControlFeatureRequest.Index = Pipe->PipeInfo->EndpointAddress;
  615. // Submit CONTROL_FEATURE request URB
  616. //
  617. ntStatus = I82930_SyncSendUsbRequest(DeviceObject, urb);
  618. // Done with URB for CONTROL_FEATURE request, free it
  619. //
  620. ExFreePool(urb);
  621. }
  622. else
  623. {
  624. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  625. }
  626. }
  627. DBGPRINT(2, ("exit: I82930_ResetPipe %08X\n", ntStatus));
  628. LOGENTRY('resp', ntStatus, 0, 0);
  629. return ntStatus;
  630. }
  631. //******************************************************************************
  632. //
  633. // I82930_AbortPipe()
  634. //
  635. // Must be called at IRQL <= DISPATCH_LEVEL
  636. //
  637. //******************************************************************************
  638. NTSTATUS
  639. I82930_AbortPipe (
  640. IN PDEVICE_OBJECT DeviceObject,
  641. IN PI82930_PIPE Pipe
  642. )
  643. {
  644. PURB urb;
  645. NTSTATUS ntStatus;
  646. DBGPRINT(2, ("enter: I82930_AbortPipe\n"));
  647. LOGENTRY('ABRT', DeviceObject, Pipe, 0);
  648. // Allocate URB for ABORT_PIPE request
  649. //
  650. urb = ExAllocatePool(NonPagedPool,
  651. sizeof(struct _URB_PIPE_REQUEST));
  652. if (urb != NULL)
  653. {
  654. // Initialize ABORT_PIPE request URB
  655. //
  656. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  657. urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  658. urb->UrbPipeRequest.PipeHandle = Pipe->PipeInfo->PipeHandle;
  659. // Submit ABORT_PIPE request URB
  660. //
  661. ntStatus = I82930_SyncSendUsbRequest(DeviceObject, urb);
  662. // Done with URB for ABORT_PIPE request, free it
  663. //
  664. ExFreePool(urb);
  665. }
  666. else
  667. {
  668. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  669. }
  670. DBGPRINT(2, ("exit: I82930_AbortPipe %08X\n", ntStatus));
  671. LOGENTRY('abrt', ntStatus, 0, 0);
  672. return ntStatus;
  673. }