www.pudn.com > data-isotransfer.rar > TestDispatch.c


#include "usbdriver.h" 
 
ULONG UsbGetCurrentFrameNumber(IN PDEVICE_OBJECT fdo); 
ULONG UsbGetDeviceDescriptor(IN PDEVICE_OBJECT fdo, 
							 PVOID pvOutputBuffer); 
ULONG UsbGetStringDescriptor(IN PDEVICE_OBJECT fdo, 
                             UCHAR             Index, 
                             USHORT            LanguageId, 
                             PVOID             pvOutputBuffer, 
                             ULONG             ulLength); 
ULONG UsbGetConfigDescriptor(IN PDEVICE_OBJECT fdo, 
                             PVOID   pvOutputBuffer, 
                             ULONG   ulLength); 
NTSTATUS UsbStartIsoTransfer(IN PDEVICE_OBJECT fdo,IN PIRP Irp); 
NTSTATUS InitTransferObject(IN OUT PISO_STREAM_OBJECT streamObject,IN ULONG index); 
NTSTATUS IsoTransferComplete(IN PDEVICE_OBJECT bunkfdo,IN PIRP Irp,IN PVOID Context); 
// 
NTSTATUS TestCreate(IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
{ 
	NTSTATUS ntStatus=STATUS_SUCCESS; 
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension; 
 
    pdx->OpenHandles++; 
							 
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    Irp->IoStatus.Information = 0; 
    IoCompleteRequest (Irp, IO_NO_INCREMENT); 
    return ntStatus; 
} 
// 
NTSTATUS TestClose(IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
{ 
   NTSTATUS ntStatus=STATUS_SUCCESS; 
   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension; 
 
   pdx->OpenHandles--; 
 
   Irp->IoStatus.Status = STATUS_SUCCESS; 
   Irp->IoStatus.Information = 0; 
   IoCompleteRequest (Irp, IO_NO_INCREMENT); 
   return ntStatus; 
} 
// 
NTSTATUS TestIOCTL(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
	NTSTATUS ntStatus; 
	PIO_STACK_LOCATION IrpStack; 
    PDEVICE_EXTENSION pdx; 
    ULONG IoControlCode; 
    PVOID IoBuffer; 
    ULONG InputBufferLength; 
    ULONG OutputBufferLength; 
    ULONG length; 
    PUCHAR pch; 
 
	pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension; 
    if (!LockDevice(fdo)) 
		return CompleteRequest(Irp, STATUS_DELETE_PENDING, 0); 
 
   IrpStack = IoGetCurrentIrpStackLocation (Irp); 
   Irp->IoStatus.Status = STATUS_SUCCESS; 
   Irp->IoStatus.Information = 0; 
 
   IoBuffer           = Irp->AssociatedIrp.SystemBuffer; 
   InputBufferLength  = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
   OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
   IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
 
   switch (IoControlCode) { 
       case IOCTL_EZUSB_GET_CURRENT_FRAME_NUMBER: 
		   { 
			   ULONG frameNumber = 0; 
 
               if (OutputBufferLength < sizeof(ULONG)) { 
				   Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 
                   break; 
			   } 
               frameNumber = UsbGetCurrentFrameNumber (fdo); 
               if (frameNumber) { 
				   *((PULONG)IoBuffer) = frameNumber; 
                   Irp->IoStatus.Information = sizeof(ULONG); 
                   Irp->IoStatus.Status = STATUS_SUCCESS; 
			   } 
               else 
				   Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
		   } 
           break; 
 
       case IOCTL_Ezusb_GET_DEVICE_DESCRIPTOR: 
		  { 
              length = UsbGetDeviceDescriptor (fdo, IoBuffer); 
              Irp->IoStatus.Information = length; 
              Irp->IoStatus.Status = STATUS_SUCCESS; 
		  } 
		  break; 
      case IOCTL_Ezusb_GET_STRING_DESCRIPTOR: 
		  { 
			  PGET_STRING_DESCRIPTOR_IN Input = IoBuffer; 
 
              if ((InputBufferLength = sizeof(GET_STRING_DESCRIPTOR_IN)) && 
                  (OutputBufferLength > 0)) { 
				  length = UsbGetStringDescriptor (fdo, 
                                                   Input->Index, 
                                                   Input->LanguageId, 
                                                   IoBuffer, 
                                                   OutputBufferLength); 
                  if (length) { 
					  Irp->IoStatus.Information = length; 
                      Irp->IoStatus.Status = STATUS_SUCCESS; 
				  } 
                  else 
					  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
			  } 
              else             
               Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 
		  }       
          break; 
 
         case IOCTL_Ezusb_GET_CONFIGURATION_DESCRIPTOR: 
			 { 
                 length = UsbGetConfigDescriptor (fdo, IoBuffer, OutputBufferLength); 
                 Irp->IoStatus.Information = length; 
                 Irp->IoStatus.Status = STATUS_SUCCESS; 
			 } 
             break; 
  
         case IOCTL_EZUSB_ISO_READ: 
         case IOCTL_EZUSB_ISO_WRITE: 
              Irp->IoStatus.Status = UsbStartIsoTransfer(fdo,Irp); 
              Irp->IoStatus.Information = 0; 
         break; 
          
		 case IOCTL_Ezusb_RESETPIPE: 
		 { 
             ULONG pipenum = *((PULONG) IoBuffer); 
             Irp->IoStatus.Status = UsbResetPipe(fdo,pipenum); 
		 } 
		 break; 
 
         default: 
			  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 
     }  
    UnlockDevice(fdo); 
    ntStatus = Irp->IoStatus.Status; 
    IoCompleteRequest (Irp,IO_NO_INCREMENT); 
    return ntStatus; 
} 
// 
ULONG UsbGetCurrentFrameNumber(IN PDEVICE_OBJECT fdo) 
{ 
	NTSTATUS  ntStatus = STATUS_SUCCESS; 
	PURB urb = NULL; 
    PDEVICE_EXTENSION   pdx; 
    ULONG  frameNumber = 0; 
     
    pdx = fdo->DeviceExtension; 
    urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_GET_CURRENT_FRAME_NUMBER)); 
    if (urb == NULL) 
		return 0; 
    RtlZeroMemory(urb,sizeof(struct _URB_GET_CURRENT_FRAME_NUMBER)); 
   
	urb->UrbHeader.Length = sizeof(struct _URB_GET_CURRENT_FRAME_NUMBER); 
    urb->UrbHeader.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER; 
  
	ntStatus = UsbCallUSBDI(fdo, urb); 
    if (NT_SUCCESS(ntStatus)) { 
		frameNumber = urb->UrbGetCurrentFrameNumber.FrameNumber; 
    } 
 
    ExFreePool(urb); 
    return frameNumber; 
} 
// 
ULONG UsbGetDeviceDescriptor(IN PDEVICE_OBJECT fdo, 
							 PVOID pvOutputBuffer) 
{ 
	NTSTATUS ntStatus = STATUS_SUCCESS; 
    PURB     urb = NULL; 
    ULONG    length = 0; 
    PDEVICE_EXTENSION   pdx = NULL; 
 
    pdx = fdo->DeviceExtension; 
    urb = ExAllocatePool(NonPagedPool,  
                         sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 
    if (urb==NULL) 
		return STATUS_NO_MEMORY;         
 
    if (pvOutputBuffer==NULL)  
		return STATUS_INVALID_PARAMETER; 
 
    UsbBuildGetDescriptorRequest(urb, 
                                 (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_DEVICE_DESCRIPTOR_TYPE,    
                                 0,                             
                                 0,                             
                                 pvOutputBuffer,                
                                 NULL,                           
                                 sizeof(USB_DEVICE_DESCRIPTOR),  
                                 NULL);                          
                                                                  
    ntStatus = UsbCallUSBDI(fdo, urb); 
 
    if (NT_SUCCESS(ntStatus)) { 
		length = urb->UrbControlDescriptorRequest.TransferBufferLength; 
	} 
	else 
		length = 0; 
    ExFreePool(urb); 
    return length; 
} 
// 
ULONG UsbGetStringDescriptor(IN PDEVICE_OBJECT fdo, 
                             UCHAR             Index, 
                             USHORT            LanguageId, 
                             PVOID             pvOutputBuffer, 
                             ULONG             ulLength) 
{ 
	NTSTATUS ntStatus = STATUS_SUCCESS; 
    PURB     urb = NULL; 
    ULONG    length = 0; 
 
    urb = ExAllocatePool(NonPagedPool,  
                         sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 
                          
    if (urb==NULL) 
		return STATUS_NO_MEMORY;         
 
    if (pvOutputBuffer==NULL) 
		return STATUS_INVALID_PARAMETER; 
 
    UsbBuildGetDescriptorRequest(urb, 
                                 (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), 
                                  USB_STRING_DESCRIPTOR_TYPE,     
                                  Index,                          
                                  LanguageId,                     
                                  pvOutputBuffer,                 
                                  NULL,                           
                                  ulLength,                       
                                  NULL);                          
                                                                   
    ntStatus = UsbCallUSBDI(fdo, urb); 
 
    if (NT_SUCCESS(ntStatus))  { 
         length = urb->UrbControlDescriptorRequest.TransferBufferLength; 
	} 
    else 
         length = 0; 
    ExFreePool(urb); 
    return length; 
} 
// 
ULONG UsbGetConfigDescriptor(IN PDEVICE_OBJECT fdo, 
                             PVOID   pvOutputBuffer, 
                             ULONG   ulLength) 
{ 
	NTSTATUS  ntStatus = STATUS_SUCCESS; 
    PURB      urb = NULL; 
    ULONG     length = 0; 
 
    urb = ExAllocatePool(NonPagedPool,  
                         sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 
                          
    if (urb==NULL) 
		return STATUS_NO_MEMORY;         
    
    if (pvOutputBuffer==NULL) 
		return STATUS_INVALID_PARAMETER; 
 
   	UsbBuildGetDescriptorRequest(urb, 
                                 (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE,  
                                 0,                             
                                 0,                             
                                 pvOutputBuffer,                
                                 NULL,                          
                                 ulLength,                      
                                 NULL);                         
                                                                   
    ntStatus = UsbCallUSBDI(fdo, urb); 
 
    if (NT_SUCCESS(ntStatus)) { 
         length = urb->UrbControlDescriptorRequest.TransferBufferLength; 
	} 
    else 
        length = 0; 
    ExFreePool(urb); 
    return length; 
} 
// 
NTSTATUS UsbStartIsoTransfer(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
   PDEVICE_EXTENSION          pdx = fdo->DeviceExtension; 
   PIO_STACK_LOCATION         irpStack = IoGetCurrentIrpStackLocation (Irp); 
   PISO_TRANSFER_CONTROL      isoControl = 
                              (PISO_TRANSFER_CONTROL)Irp->AssociatedIrp.SystemBuffer; 
   ULONG                      bufferLength = 
                              irpStack->Parameters.DeviceIoControl.OutputBufferLength; 
   ULONG                      packetSize = 0; 
   PUSBD_INTERFACE_INFORMATION interfaceInfo = NULL; 
   PUSBD_PIPE_INFORMATION     pipeInfo = NULL; 
   USBD_PIPE_HANDLE           pipeHandle = NULL; 
   PISO_STREAM_OBJECT         streamObject; 
   ULONG                      i; 
 
   interfaceInfo = pdx->Interface; 
 
   if (!interfaceInfo) 
   { 
      return STATUS_UNSUCCESSFUL; 
   } 
    
   if (isoControl->PipeNum > interfaceInfo->NumberOfPipes) 
   { 
      return STATUS_INVALID_PARAMETER; 
   } 
 
   pipeInfo = &(interfaceInfo->Pipes[isoControl->PipeNum]); 
 
   if (!(pipeInfo->PipeType == UsbdPipeTypeIsochronous)) 
   { 
      return STATUS_INVALID_PARAMETER; 
   } 
 
   pipeHandle = pipeInfo->PipeHandle; 
 
   if (!pipeHandle) 
   { 
      return STATUS_UNSUCCESSFUL; 
   } 
 
   if (isoControl->PacketCount % (isoControl->FramesPerBuffer * isoControl->BufferCount)) 
   { 
      return STATUS_INVALID_PARAMETER; 
   } 
 
   packetSize = isoControl->PacketSize; 
 
   if (bufferLength < (isoControl->PacketCount * (packetSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR)))) 
   { 
      return STATUS_UNSUCCESSFUL; 
   } 
 
   streamObject = ExAllocatePool(NonPagedPool, sizeof(ISO_STREAM_OBJECT)); 
 
   if (!streamObject) 
   { 
      return STATUS_NO_MEMORY; 
   } 
 
   streamObject->FramesPerBuffer = isoControl->FramesPerBuffer; 
 
   streamObject->BufferCount = isoControl->BufferCount; 
 
   streamObject->DeviceObject = fdo; 
   streamObject->PipeInfo = pipeInfo; 
   streamObject->PacketSize = packetSize; 
   streamObject->NumPackets = isoControl->PacketCount; 
   streamObject->TransferBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress); 
   streamObject->TransferBufferLength = streamObject->PacketSize * streamObject->NumPackets; 
   streamObject->IsoDescriptorBuffer = (PUCHAR) streamObject->TransferBuffer + streamObject->TransferBufferLength; 
    
   streamObject->TransferObject = ExAllocatePool(NonPagedPool, 
                            sizeof(ISO_TRANSFER_OBJECT) * streamObject->BufferCount); 
 
   if (!streamObject->TransferObject) 
   { 
      return STATUS_NO_MEMORY; 
   } 
 
   for (i=0; i < streamObject->BufferCount; i++) 
   { 
      InitTransferObject(streamObject,i); 
   } 
 
   for (i=0; i < streamObject->BufferCount; i++) 
   { 
      IoCallDriver(pdx->LowerDeviceObject, 
                  streamObject->TransferObject[i].Irp); 
   } 
 
   for (i=0; i < streamObject->BufferCount; i++) 
   { 
      KeWaitForSingleObject( 
                    &streamObject->TransferObject[i].Done, 
                    Suspended, 
                    KernelMode, 
                    FALSE, 
                    NULL); 
   } 
 
   ExFreePool(streamObject->TransferObject); 
   ExFreePool(streamObject); 
 
   return STATUS_SUCCESS; 
} 
// 
NTSTATUS InitTransferObject(IN OUT PISO_STREAM_OBJECT streamObject,IN ULONG index) 
{ 
   PISO_TRANSFER_OBJECT transferObject = &streamObject->TransferObject[index]; 
   PUSBD_PIPE_INFORMATION pipeInfo = streamObject->PipeInfo; 
   USHORT urbSize = 0; 
   CCHAR stackSize; 
   PIO_STACK_LOCATION nextStack = NULL; 
   PURB urb = NULL; 
   PIRP irp = NULL; 
   PDEVICE_EXTENSION pdx = 
      (PDEVICE_EXTENSION) streamObject->DeviceObject->DeviceExtension; 
   ULONG i; 
 
   urbSize = GET_ISO_URB_SIZE(streamObject->FramesPerBuffer); 
 
   urb = ExAllocatePool(NonPagedPool, urbSize); 
   RtlZeroMemory(urb,urbSize); 
 
   urb->UrbHeader.Length = urbSize; 
   urb->UrbHeader.Function = URB_FUNCTION_ISOCH_TRANSFER; 
   urb->UrbIsochronousTransfer.PipeHandle = pipeInfo->PipeHandle; 
   urb->UrbIsochronousTransfer.TransferFlags = 
      USB_ENDPOINT_DIRECTION_IN(pipeInfo->EndpointAddress) ? USBD_TRANSFER_DIRECTION_IN : 0; 
   urb->UrbIsochronousTransfer.TransferFlags |= 
      USBD_START_ISO_TRANSFER_ASAP; 
   urb->UrbIsochronousTransfer.TransferFlags |= 
      USBD_SHORT_TRANSFER_OK; 
   urb->UrbIsochronousTransfer.TransferBufferLength = 
      streamObject->PacketSize * streamObject->FramesPerBuffer; 
   urb->UrbIsochronousTransfer.TransferBuffer = 
      ((PUCHAR) streamObject->TransferBuffer) +  (index * streamObject->PacketSize * streamObject->FramesPerBuffer); 
 
   urb->UrbIsochronousTransfer.NumberOfPackets = streamObject->FramesPerBuffer; 
 
   for (i=0; iFramesPerBuffer; i++) 
   { 
      urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * streamObject->PacketSize; 
      urb->UrbIsochronousTransfer.IsoPacket[i].Length = streamObject->PacketSize; 
   } 
 
   stackSize = (CCHAR) (pdx->LowerDeviceObject->StackSize + 1); 
 
   irp = IoAllocateIrp(stackSize, FALSE); 
   IoInitializeIrp(irp, irp->Size, stackSize); 
 
   nextStack = IoGetNextIrpStackLocation(irp); 
 
   nextStack->Parameters.Others.Argument1 = urb; 
   nextStack->Parameters.DeviceIoControl.IoControlCode =  
      IOCTL_INTERNAL_USB_SUBMIT_URB;                     
   nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
 
   IoSetCompletionRoutine(irp, 
                          IsoTransferComplete, 
                          transferObject, 
                          TRUE, 
                          TRUE, 
                          TRUE); 
 
   transferObject->Frame = index * streamObject->FramesPerBuffer; 
   transferObject->Urb = urb; 
   transferObject->Irp = irp; 
   transferObject->StreamObject = streamObject; 
   KeInitializeEvent(&transferObject->Done, NotificationEvent, FALSE); 
 
   return STATUS_SUCCESS; 
} 
// 
NTSTATUS IsoTransferComplete(IN PDEVICE_OBJECT bunkfdo,IN PIRP Irp,IN PVOID Context) 
{ 
   NTSTATUS ntStatus,status; 
   PISO_TRANSFER_OBJECT transferObject = (PISO_TRANSFER_OBJECT) Context; 
   PISO_STREAM_OBJECT streamObject = transferObject->StreamObject; 
   PDEVICE_OBJECT fdo = streamObject->DeviceObject; 
   PDEVICE_EXTENSION          pdx = fdo->DeviceExtension; 
   PIO_STACK_LOCATION nextStack; 
   PURB urb = transferObject->Urb; 
   USHORT urbSize = 0; 
   ULONG i; 
 
   RtlCopyMemory((PUCHAR) streamObject->IsoDescriptorBuffer + (transferObject->Frame * sizeof(USBD_ISO_PACKET_DESCRIPTOR)), 
                 urb->UrbIsochronousTransfer.IsoPacket, 
                 (streamObject->FramesPerBuffer * sizeof(USBD_ISO_PACKET_DESCRIPTOR))); 
 
   transferObject->Frame += (streamObject->FramesPerBuffer * streamObject->BufferCount); 
 
   if (transferObject->Frame < streamObject->NumPackets) 
   { 
      urbSize = GET_ISO_URB_SIZE(streamObject->FramesPerBuffer); 
      RtlZeroMemory(urb,urbSize); 
 
      urb->UrbHeader.Length = urbSize; 
      urb->UrbHeader.Function = URB_FUNCTION_ISOCH_TRANSFER; 
      urb->UrbIsochronousTransfer.PipeHandle = streamObject->PipeInfo->PipeHandle; 
      urb->UrbIsochronousTransfer.TransferFlags = 
         USB_ENDPOINT_DIRECTION_IN(streamObject->PipeInfo->EndpointAddress) ? USBD_TRANSFER_DIRECTION_IN : 0; 
      urb->UrbIsochronousTransfer.TransferFlags |= 
         USBD_START_ISO_TRANSFER_ASAP; 
      urb->UrbIsochronousTransfer.TransferFlags |= 
         USBD_SHORT_TRANSFER_OK; 
      urb->UrbIsochronousTransfer.TransferBufferLength = 
         streamObject->PacketSize * streamObject->FramesPerBuffer; 
      urb->UrbIsochronousTransfer.TransferBuffer = 
         ((PUCHAR) streamObject->TransferBuffer) +  (transferObject->Frame * streamObject->PacketSize); 
      urb->UrbIsochronousTransfer.NumberOfPackets = streamObject->FramesPerBuffer; 
 
      for (i=0; iFramesPerBuffer; i++) 
      { 
         urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * streamObject->PacketSize; 
         urb->UrbIsochronousTransfer.IsoPacket[i].Length = streamObject->PacketSize; 
      } 
 
      IoInitializeIrp(Irp, 
                     IoSizeOfIrp((pdx->LowerDeviceObject->StackSize + 1)), 
                     (CCHAR)(pdx->LowerDeviceObject->StackSize + 1)); 
 
      nextStack = IoGetNextIrpStackLocation(Irp); 
 
      nextStack->Parameters.Others.Argument1 = transferObject->Urb; 
      nextStack->Parameters.DeviceIoControl.IoControlCode =  
         IOCTL_INTERNAL_USB_SUBMIT_URB;                     
      nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
 
      IoSetCompletionRoutine(Irp, 
             IsoTransferComplete, 
             transferObject, 
             TRUE, 
             TRUE, 
             TRUE); 
 
      status = IoCallDriver(pdx->LowerDeviceObject,Irp); 
      ntStatus = STATUS_MORE_PROCESSING_REQUIRED; 
   } 
   else 
   { 
 
      IoFreeIrp(Irp); 
      ExFreePool(urb); 
 
      KeSetEvent(&transferObject->Done,1,FALSE); 
 
      ntStatus = STATUS_MORE_PROCESSING_REQUIRED; 
   } 
 
   return ntStatus; 
} 
// 
NTSTATUS UsbResetPipe(IN PDEVICE_OBJECT fdo,ULONG PipeNum) 
{ 
   NTSTATUS ntStatus; 
   PDEVICE_EXTENSION             pdx = fdo->DeviceExtension; 
   PUSBD_INTERFACE_INFORMATION   interfaceInfo = NULL; 
   USBD_PIPE_HANDLE              pipeHandle = NULL; 
   PURB urb; 
   USBD_VERSION_INFORMATION VersionInformation; 
 
   interfaceInfo = pdx->Interface; 
 
   if (!interfaceInfo) 
   { 
      return STATUS_UNSUCCESSFUL; 
   } 
    
   if (PipeNum > interfaceInfo->NumberOfPipes) 
   { 
      return STATUS_INVALID_PARAMETER; 
   } 
 
   pipeHandle = interfaceInfo->Pipes[PipeNum].PipeHandle; 
 
   urb = ExAllocatePool(NonPagedPool, 
                      sizeof(struct _URB_PIPE_REQUEST)); 
 
   if (urb) 
   { 
      urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST); 
      urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE; 
      urb->UrbPipeRequest.PipeHandle = pipeHandle; 
 
      USBD_GetUSBDIVersion(&VersionInformation); 
      if (VersionInformation.USBDI_Version < 0x101)  
      { 
         urb->UrbHeader.Length -= sizeof(ULONG); 
      } 
 
      ntStatus = UsbCallUSBDI(fdo, urb); 
 
      ExFreePool(urb); 
   } 
   else 
   { 
      ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
   } 
 
   return ntStatus; 
}