📄 isostrm.c
字号:
for(i=0; i<urb->UrbIsochronousTransfer.NumberOfPackets; i++) {
urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * packetSize;
//
// For input operation, length is set to whatever the device supplies.
//
urb->UrbIsochronousTransfer.IsoPacket[i].Length = 0;
}
IsoUsb_DbgPrint(3, ("IsoUsb_InitializeStreamUrb - ends\n"));
return STATUS_SUCCESS;
}
NTSTATUS
IsoUsb_IsoIrp_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the completion routine of the irp in the irp/urb pair
passed down the stack for stream transfers.
If the transfer was cancelled or the device yanked out, then we
release resources, dump the statistics and return
STATUS_MORE_PROCESSING_REQUIRED, so that the cleanup module can
free the irp.
otherwise, we reinitialize the transfers and continue recirculaiton
of the irps.
Arguments:
DeviceObject - pointer to device object below us.
Irp - I/O completion routine.
Context - context passed to the completion routine
Return Value:
--*/
{
NTSTATUS ntStatus;
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION nextStack;
PISOUSB_STREAM_OBJECT streamObject;
PISOUSB_TRANSFER_OBJECT transferObject;
transferObject = (PISOUSB_TRANSFER_OBJECT) Context;
streamObject = transferObject->StreamObject;
deviceObject = streamObject->DeviceObject;
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete - begins\n"));
ntStatus = IsoUsb_ProcessTransfer(transferObject);
if((ntStatus == STATUS_CANCELLED) ||
(ntStatus == STATUS_DEVICE_NOT_CONNECTED)) {
IsoUsb_DbgPrint(3, ("Isoch irp cancelled/device removed\n"));
//
// this is the last irp to complete with this erroneous value
// signal an event and return STATUS_MORE_PROCESSING_REQUIRED
//
if(InterlockedDecrement(&streamObject->PendingIrps) == 0) {
KeSetEvent(&streamObject->NoPendingIrpEvent,
1,
FALSE);
IsoUsb_DbgPrint(3, ("-----------------------------\n"));
}
IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete::"));
IsoUsb_IoDecrement(deviceExtension);
transferObject->Irp = NULL;
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// otherwise circulate the irps.
//
IsoUsb_InitializeStreamUrb(deviceObject, transferObject);
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,
IsoUsb_IsoIrp_Complete,
transferObject,
TRUE,
TRUE,
TRUE);
transferObject->TimesRecycled++;
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete - ends\n"));
IsoUsb_DbgPrint(3, ("-----------------------------\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
IsoUsb_ProcessTransfer(
IN PISOUSB_TRANSFER_OBJECT TransferObject
)
/*++
Routine Description:
This routine is invoked from the completion routine to check the status
of the irp, urb and the isochronous packets.
updates statistics
Arguments:
TranferObject - pointer to transfer object for the irp/urb pair which completed.
Return Value:
NT status value
--*/
{
PIRP irp;
PURB urb;
ULONG i;
NTSTATUS ntStatus;
USBD_STATUS usbdStatus;
irp = TransferObject->Irp;
urb = TransferObject->Urb;
ntStatus = irp->IoStatus.Status;
IsoUsb_DbgPrint(3, ("IsoUsb_ProcessTransfer - begins\n"));
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(3, ("Isoch irp failed with status = %X\n", ntStatus));
}
usbdStatus = urb->UrbHeader.Status;
if(!USBD_SUCCESS(usbdStatus)) {
IsoUsb_DbgPrint(3, ("urb failed with status = %X\n", usbdStatus));
}
//
// check each of the urb packets
//
for(i = 0; i < urb->UrbIsochronousTransfer.NumberOfPackets; i++) {
TransferObject->TotalPacketsProcessed++;
usbdStatus = urb->UrbIsochronousTransfer.IsoPacket[i].Status;
if(!USBD_SUCCESS(usbdStatus)) {
// IsoUsb_DbgPrint(3, ("Iso packet %d failed with status = %X\n", i, usbdStatus));
TransferObject->ErrorPacketCount++;
}
else {
TransferObject->TotalBytesProcessed += urb->UrbIsochronousTransfer.IsoPacket[i].Length;
}
}
IsoUsb_DbgPrint(3, ("IsoUsb_ProcessTransfer - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_StopIsoStream(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_STREAM_OBJECT StreamObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is invoked from the IOCTL to stop the stream transfers.
Arguments:
DeviceObject - pointer to device object
StreamObject - pointer to stream object
Irp - pointer to Irp
Return Value:
NT status value
--*/
{
ULONG i;
KIRQL oldIrql;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
//
// initialize vars
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
IsoUsb_DbgPrint(3, ("IsoUsb_StopIsoStream - begins\n"));
if((StreamObject == NULL) ||
(StreamObject->DeviceObject != DeviceObject)) {
IsoUsb_DbgPrint(1, ("invalid streamObject\n"));
return STATUS_INVALID_PARAMETER;
}
IsoUsb_StreamObjectCleanup(StreamObject, deviceExtension);
IsoUsb_DbgPrint(3, ("IsoUsb_StopIsoStream - ends\n"));
return STATUS_SUCCESS;
}
NTSTATUS
IsoUsb_StreamObjectCleanup(
IN PISOUSB_STREAM_OBJECT StreamObject,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine is invoked either when the user-mode app passes an IOCTL to
abort stream transfers or when the the cleanup dispatch routine is run.
It is guaranteed to run only once for every stream transfer.
Arguments:
StreamObject - StreamObject corresponding to stream transfer which
needs to be aborted.
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
ULONG i;
ULONG timesRecycled;
ULONG totalPacketsProcessed;
ULONG totalBytesProcessed;
ULONG errorPacketCount;
PISOUSB_TRANSFER_OBJECT xferObject;
//
// initialize the variables
//
timesRecycled = 0;
totalPacketsProcessed = 0;
totalBytesProcessed = 0;
errorPacketCount = 0;
//
// cancel transferobject irps/urb pair
// safe to touch these irps because the
// completion routine always returns
// STATUS_MORE_PRCESSING_REQUIRED
//
//
for(i = 0; i < ISOUSB_MAX_IRP; i++) {
if(StreamObject->TransferObjectList[i] &&
StreamObject->TransferObjectList[i]->Irp) {
IoCancelIrp(StreamObject->TransferObjectList[i]->Irp);
}
}
//
// wait for the transfer objects irps to complete.
//
KeWaitForSingleObject(&StreamObject->NoPendingIrpEvent,
Executive,
KernelMode,
FALSE,
NULL);
//
// dump the statistics
//
for(i = 0; i < ISOUSB_MAX_IRP; i++) {
xferObject = StreamObject->TransferObjectList[i];
if(xferObject) {
timesRecycled += xferObject->TimesRecycled;
totalPacketsProcessed += xferObject->TotalPacketsProcessed;
totalBytesProcessed += xferObject->TotalBytesProcessed;
errorPacketCount += xferObject->ErrorPacketCount;
}
}
IsoUsb_DbgPrint(3, ("TimesRecycled = %d\n", timesRecycled));
IsoUsb_DbgPrint(3, ("TotalPacketsProcessed = %d\n", totalPacketsProcessed));
IsoUsb_DbgPrint(3, ("TotalBytesProcessed = %d\n", totalBytesProcessed));
IsoUsb_DbgPrint(3, ("ErrorPacketCount = %d\n", errorPacketCount));
//
// free all the buffers, urbs and transfer objects
// associated with stream object
//
for(i = 0; i < ISOUSB_MAX_IRP; i++) {
xferObject = StreamObject->TransferObjectList[i];
if(xferObject) {
if(xferObject->Urb) {
ExFreePool(xferObject->Urb);
xferObject->Urb = NULL;
}
if(xferObject->DataBuffer) {
ExFreePool(xferObject->DataBuffer);
xferObject->DataBuffer = NULL;
}
ExFreePool(xferObject);
StreamObject->TransferObjectList[i] = NULL;
}
}
ExFreePool(StreamObject);
// IsoUsb_ResetParentPort(DeviceObject);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -