📄 ezusbsys.c
字号:
// 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)
//
// MDNISO streamObject->PendingTransfers =
streamObject->FramesPerBuffer = isoControl->FramesPerBuffer;
//
// BufferCount specifies how many IRP's are queued to carry out an ISO transfer.
//
streamObject->PendingTransfers =
streamObject->BufferCount = isoControl->BufferCount;
streamObject->DeviceObject = fdo;
streamObject->PipeInfo = pipeInfo;
streamObject->PacketSize = isoControl->PacketSize;
streamObject->TransferBufferLength = streamObject->PacketSize * streamObject->FramesPerBuffer * streamObject->BufferCount;
streamObject->TransferBuffer = ExAllocatePool(NonPagedPool, streamObject->TransferBufferLength);
if (!streamObject->TransferBuffer)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() unable to allocate transfer buffer - Exiting\n"));
return STATUS_NO_MEMORY;
}
streamObject->DataRingBuffer = AllocRingBuffer(isoControl->PacketCount * isoControl->PacketSize);
if (!streamObject->DataRingBuffer)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() unable to allocate data ring buffer - Exiting\n"));
return STATUS_NO_MEMORY;
}
pdx->DataRingBuffer = streamObject->DataRingBuffer;
streamObject->DescriptorRingBuffer =
AllocRingBuffer(isoControl->PacketCount * sizeof(USBD_ISO_PACKET_DESCRIPTOR));
if (!streamObject->DescriptorRingBuffer)
{
Ezusb_KdPrint(("Ezusb_StartIsoTransfer() unable to allocate descriptor ring buffer - Exiting\n"));
return STATUS_NO_MEMORY;
}
pdx->DescriptorRingBuffer = streamObject->DescriptorRingBuffer;
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);
//
// override the completion routine that InitTransferObject registered
//
IoSetCompletionRoutine(streamObject->TransferObject[i].Irp,
IsoStreamTransferComplete,
&streamObject->TransferObject[i],
TRUE,
TRUE,
TRUE);
}
pdx->StopIsoStream = FALSE;
for (i=0; i < streamObject->BufferCount; i++)
{
IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject[i].Irp);
}
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;
//
// allocate and prepare the URB
//
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;
//
// setup the ISO packet descriptors
//
for (i=0; i<streamObject->FramesPerBuffer; i++)
{
urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * streamObject->PacketSize;
urb->UrbIsochronousTransfer.IsoPacket[i].Length = streamObject->PacketSize;
}
stackSize = (CCHAR) (pdx->StackDeviceObject->StackSize + 1);
//
// allocate and prepare the IRP
//
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;
}
PRING_BUFFER
AllocRingBuffer(
ULONG Size
)
{
PRING_BUFFER ringBuffer = NULL;
ringBuffer = ExAllocatePool(NonPagedPool, sizeof(RING_BUFFER));
if (!ringBuffer)
return NULL;
ringBuffer->buffer = ExAllocatePool(NonPagedPool, Size);
if (!ringBuffer->buffer)
{
ExFreePool(ringBuffer);
return NULL;
}
ringBuffer->inPtr = ringBuffer->buffer;
ringBuffer->outPtr = ringBuffer->buffer;
ringBuffer->totalSize = Size;
ringBuffer->currentSize = 0;
KeInitializeSpinLock(&ringBuffer->spinLock);
return ringBuffer;
}
VOID
FreeRingBuffer(
PRING_BUFFER ringBuffer
)
{
ExFreePool(ringBuffer->buffer);
ExFreePool(ringBuffer);
}
ULONG
ReadRingBuffer(
PRING_BUFFER ringBuffer,
PUCHAR readBuffer,
ULONG numberOfBytesToRead
)
/*
Routine Description:
This routine reads data from a ring buffer.
Arguments:
ringBuffer - pointer to a ring buffer structure
readBuffer - pointer to a user supplied buffer to transfer data into
numberOfBytesToRead - number of bytes to read from the ring buffer
Return Value:
ULONG - number of bytes read. May be smaller than requested number of bytes.
*/
{
ULONG byteCount;
KIRQL oldIrql;
Ezusb_KdPrint(( "ReadRingBuffer() enter\n"));
if (numberOfBytesToRead > ringBuffer->totalSize)
return 0;
if (ringBuffer->currentSize == 0)
return 0;
if ( numberOfBytesToRead > ringBuffer->currentSize )
byteCount = ringBuffer->currentSize;
else
byteCount = numberOfBytesToRead;
//
// two cases. Read either wraps or it doesn't.
// Handle the non-wrapped case first
//
if ((ringBuffer->outPtr + byteCount - 1) <
(ringBuffer->buffer + ringBuffer->totalSize))
{
Ezusb_KdPrint(( "ReadRingBuffer() about to copy a\n"));
RtlCopyMemory(readBuffer, ringBuffer->outPtr, byteCount);
ringBuffer->outPtr += byteCount;
if (ringBuffer->outPtr == ringBuffer->buffer + ringBuffer->totalSize)
ringBuffer->outPtr = ringBuffer->buffer;
}
// now handle the wrapped case
else
{
ULONG fragSize;
Ezusb_KdPrint(( "ReadRingBuffer() about to copy b\n"));
// get the first half of the read
fragSize = ringBuffer->buffer + ringBuffer->totalSize - ringBuffer->outPtr;
RtlCopyMemory(readBuffer, ringBuffer->outPtr, fragSize);
// now get the rest
RtlCopyMemory(readBuffer + fragSize, ringBuffer->buffer, byteCount - fragSize);
ringBuffer->outPtr = ringBuffer->buffer + byteCount - fragSize;
}
//
// update the current size of the ring buffer. Use spinlock to insure
// atomic operation.
//
KeAcquireSpinLock(&ringBuffer->spinLock, &oldIrql);
ringBuffer->currentSize -= byteCount;
KeReleaseSpinLock(&ringBuffer->spinLock, oldIrql);
Ezusb_KdPrint(( "ReadRingBuffer() exit\n"));
return byteCount;
}
ULONG
WriteRingBuffer(
PRING_BUFFER ringBuffer,
PUCHAR writeBuffer,
ULONG numberOfBytesToWrite
)
/*
Routine Description:
This routine writes data to a ring buffer. If the requested write size exceeds
available space in the ring buffer, then the write is rejected.
Arguments:
ringBuffer - pointer to a ring buffer structure
readBuffer - pointer to a user supplied buffer of data to copy to the ring buffer
numberOfBytesToRead - number of bytes to write to the ring buffer
Return Value:
ULONG - number of bytes written.
*/
{
ULONG byteCount;
KIRQL oldIrql;
if ( numberOfBytesToWrite >
(ringBuffer->totalSize - ringBuffer->currentSize) )
{
Ezusb_KdPrint(( "WriteRingBuffer() OVERFLOW\n"));
return 0;
}
byteCount = numberOfBytesToWrite;
//
// two cases. Write either wraps or it doesn't.
// Handle the non-wrapped case first
//
if ((ringBuffer->inPtr + byteCount - 1) <
(ringBuffer->buffer + ringBuffer->totalSize))
{
RtlCopyMemory(ringBuffer->inPtr, writeBuffer, byteCount);
ringBuffer->inPtr += byteCount;
if (ringBuffer->inPtr == ringBuffer->buffer + ringBuffer->totalSize)
ringBuffer->inPtr = ringBuffer->buffer;
}
// now handle the wrapped case
else
{
ULONG fragSize;
// write the first fragment
fragSize = ringBuffer->buffer + ringBuffer->totalSize - ringBuffer->inPtr;
RtlCopyMemory(ringBuffer->inPtr, writeBuffer, fragSize);
// now write the rest
RtlCopyMemory(ringBuffer->buffer, writeBuffer + fragSize, byteCount - fragSize);
ringBuffer->inPtr = ringBuffer->buffer + byteCount - fragSize;
}
//
// update the current size of the ring buffer. Use spinlock to insure
// atomic operation.
//
KeAcquireSpinLock(&ringBuffer->spinLock, &oldIrql);
ringBuffer->currentSize += byteCount;
KeReleaseSpinLock(&ringBuffer->spinLock, oldIrql);
return byteCount;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -