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;
}