📄 ezusbsys.c
字号:
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);
//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);
Ezusb_KdPrint(("IsoTransferComplete Resubmit Irp Status 0x%x\n",status));
ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
}
else
{
Ezusb_KdPrint(("IsoTransferComplete All done, setting event\n"));
IoFreeIrp(Irp);
ExFreePool(urb);
KeSetEvent(&transferObject->Done,1,FALSE);
ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
}
return ntStatus;
}
NTSTATUS Ezusb_StartIsoTransfer(
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;
//
// verify that the selected pipe is valid, and get a handle to it. If anything
// is wrong, return an error
//
interfaceInfo = pdx->Interface;
if (!interfaceInfo)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() no interface info - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
if (isoControl->PipeNum > interfaceInfo->NumberOfPipes)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeInfo = &(interfaceInfo->Pipes[isoControl->PipeNum]);
if (!(pipeInfo->PipeType == UsbdPipeTypeIsochronous))
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeHandle = pipeInfo->PipeHandle;
if (!pipeHandle)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
//
// verify that the FramesPerBuffer and BufferCount parameters are correct.
// A "feature" of this function is that PacketCount must
// be zero modulus (FramesPerBuffer * BufferCount).
//
if (isoControl->PacketCount % (isoControl->FramesPerBuffer * isoControl->BufferCount))
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() Invalid parameter - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
//
// verify that the caller has provided a buffer large enough for
// the requested transfer. The buffer must have room for all of
// the ISO data plus room for an array of ISO Packet Descriptor
// objects (1 for each packet transferred).
//
packetSize = isoControl->PacketSize;
if (bufferLength < (isoControl->PacketCount * (packetSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR))))
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() OutputBuffer too small - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
//
// Allocate the streamObject
//
streamObject = ExAllocatePool(NonPagedPool, sizeof(ISO_STREAM_OBJECT));
if (!streamObject)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() unable to allocate stream object - Exiting\n"));
return STATUS_NO_MEMORY;
}
//
// FramesPerBuffer specifies how many frames of ISO data are transferred
// by a single URB. This field corresponds to the NumberOfPackets
// field in the ISO transfer URB (_URB_ISOCH_TRANSFER)
//
streamObject->FramesPerBuffer = isoControl->FramesPerBuffer;
//
// BufferCount specifies how many IRP's are queued to carry out an ISO transfer.
//
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)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() unable to allocate transfer object - Exiting\n"));
return STATUS_NO_MEMORY;
}
for (i=0; i < streamObject->BufferCount; i++)
{
InitTransferObject(streamObject,i);
}
for (i=0; i < streamObject->BufferCount; i++)
{
IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject[i].Irp);
}
//
// wait for those guys to finish
//
for (i=0; i < streamObject->BufferCount; i++)
{
KeWaitForSingleObject(
&streamObject->TransferObject[i].Done,
Suspended,
KernelMode,
FALSE,
NULL);
}
//
// free the stream and transfer objects
//
ExFreePool(streamObject->TransferObject);
ExFreePool(streamObject);
return STATUS_SUCCESS;
}
NTSTATUS IsoStreamTransferComplete(
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;
PUSBD_PIPE_INFORMATION pipeInfo = streamObject->PipeInfo;
Ezusb_KdPrint(("IsoTransferComplete Irp Status 0x%x\n",Irp->IoStatus.Status));
for (i=0;i<streamObject->FramesPerBuffer; i++)
{
Ezusb_KdPrint (("Packet %d length = %d status = %d\n",i,
urb->UrbIsochronousTransfer.IsoPacket[i].Length,urb->UrbIsochronousTransfer.IsoPacket[i].Status));
}
//
// write the transfer descriptors to the descriptor ring buffer
//
WriteRingBuffer(streamObject->DescriptorRingBuffer,
(PUCHAR) &urb->UrbIsochronousTransfer.IsoPacket[0],
(streamObject->FramesPerBuffer * sizeof(USBD_ISO_PACKET_DESCRIPTOR)));
//
// write the transfer data to the data ring buffer
//
WriteRingBuffer(streamObject->DataRingBuffer,
urb->UrbIsochronousTransfer.TransferBuffer,
(streamObject->FramesPerBuffer * streamObject->PacketSize));
//
// If no errors occured, re-initialize and re-submit the IRP/URB
//
if (NT_SUCCESS(Irp->IoStatus.Status) && !pdx->StopIsoStream)
{
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; i<streamObject->FramesPerBuffer; i++)
{
urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * streamObject->PacketSize;
urb->UrbIsochronousTransfer.IsoPacket[i].Length = streamObject->PacketSize;
}
//
// initialize the IRP for the next transfer
// cuz lynn says I hafta
//
IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->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,
IsoStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);
//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);
//Ezusb_KdPrint(("IsoTransferComplete Resubmit Irp Status 0x%x\n",status));
ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
}
else
{
Ezusb_KdPrint(("IsoTransferComplete All done, setting event\n"));
IoFreeIrp(Irp);
ExFreePool(urb);
streamObject->PendingTransfers--;
if (streamObject->PendingTransfers == 0)
{
ExFreePool(streamObject->TransferBuffer);
ExFreePool(streamObject->TransferObject);
FreeRingBuffer(streamObject->DataRingBuffer);
pdx->DataRingBuffer = NULL;
FreeRingBuffer(streamObject->DescriptorRingBuffer);
pdx->DescriptorRingBuffer = NULL;
ExFreePool(streamObject);
}
ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
}
return ntStatus;
}
NTSTATUS Ezusb_StartIsoStream(
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;
PUSBD_INTERFACE_INFORMATION interfaceInfo = NULL;
PUSBD_PIPE_INFORMATION pipeInfo = NULL;
USBD_PIPE_HANDLE pipeHandle = NULL;
PISO_STREAM_OBJECT streamObject;
ULONG i;
//
// verify that the selected pipe is valid, and get a handle to it. If anything
// is wrong, return an error
//
interfaceInfo = pdx->Interface;
if (!interfaceInfo)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() no interface info - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
if (isoControl->PipeNum > interfaceInfo->NumberOfPipes)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeInfo = &(interfaceInfo->Pipes[isoControl->PipeNum]);
if (!(pipeInfo->PipeType == UsbdPipeTypeIsochronous))
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeHandle = pipeInfo->PipeHandle;
if (!pipeHandle)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() invalid pipe - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -