📄 isostrm.c
字号:
/*++
Copyright (c) 1997-1998 Microsoft Corporation
Module Name:
IsoStrm.c
Abstract:
Isochronous USB device driver for Intel 82930 USB test board
Isochronous stream test code
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1997-1998 Microsoft Corporation. All Rights Reserved.
Revision History:
7/7/98 : created
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#define DRIVER
#include "usbdi.h"
#include "usbdlib.h"
#include "Iso82930.h"
NTSTATUS
IsoUsb_ProcessTransfer(
IN PISOUSB_TRANSFER_OBJECT TransferObject
)
/*++
Routine Description:
This is where a real driver would process the data from the Iso transfer in some way;
In this sample all we do is check the IRP status from the OS and the URB status
from USBD
Arguments:
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
USBD_STATUS usbdStatus;
PIRP irp;
PURB urb;
PISOUSB_STREAM_OBJECT StreamObject;
ULONG i;
irp = TransferObject->Irp;
StreamObject = TransferObject->StreamObject;
urb = TransferObject->Urb;
ntStatus = irp->IoStatus.Status;
//
// check the irp
//
if (!NT_SUCCESS(ntStatus)) {
ISOUSB_KdPrint (DBGLVL_MEDIUM,(" IsoUsb_ProcessTransfer() **BAD Iso IRP status = 0x%x\n", ntStatus));
ISOUSB_Trap(DBGLVL_MAXIMUM);
}
else {
ISOUSB_KdPrint (DBGLVL_MAXIMUM,(" IsoUsb_ProcessTransfer() Good Iso IRP status = 0x%x\n", ntStatus));
}
//
// now check the urb header
//
usbdStatus = urb->UrbHeader.Status;
if (!USBD_SUCCESS(usbdStatus)) {
ISOUSB_KdPrint (DBGLVL_MEDIUM,(" IsoUsb_ProcessTransfer() **BAD URB HEADER USBD_STATUS status = 0x%x\n", usbdStatus));
ISOUSB_Trap(DBGLVL_MAXIMUM);
}
else {
ISOUSB_KdPrint (DBGLVL_MAXIMUM,(" IsoUsb_ProcessTransfer() Good URB HEADER USBD_STATUS status = 0x%x\n", usbdStatus));
}
// check the Urb packets
for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++)
{
StreamObject->TotalPacketsProcessed++;
if (!USBD_SUCCESS( urb->UrbIsochronousTransfer.IsoPacket[i].Status)) {
ISOUSB_KdPrint ( DBGLVL_MEDIUM , (" IsoUsb_ProcessTransfer() BAD PACKET USBD STATUS [%02d] Length 0x%08X, Status 0x%08X\n",
i,
urb->UrbIsochronousTransfer.IsoPacket[i].Length,
urb->UrbIsochronousTransfer.IsoPacket[i].Status
));
ntStatus = STATUS_UNSUCCESSFUL; // set error return code
StreamObject->ErrorPacketCount++;
}
else {
// Successfull;
// Note that here is the place we would do any data processing/copying to frame
// buffers, for example , if we were a video capture device, etc ...
StreamObject->TotalBytesProcessed += urb->UrbIsochronousTransfer.IsoPacket[i].Length;
}
}
return ntStatus;
}
NTSTATUS
IsoUsb_InitializeStreamUrb(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_TRANSFER_OBJECT TransferObject
)
/*++
Routine Description:
Arguments:
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG siz;
ULONG packetSize, numPackets, maxXferSize, i;
PURB urb;
PISOUSB_STREAM_OBJECT streamObject = TransferObject->StreamObject;
urb = TransferObject->Urb;
maxXferSize = streamObject->PipeInfo->MaximumTransferSize; // We set this
packetSize = streamObject->PipeInfo->MaximumPacketSize; // USBD sets this
numPackets = maxXferSize / packetSize;
siz = GET_ISO_URB_SIZE(numPackets);
ISOUSB_KdPrint (DBGLVL_MAXIMUM,("IsoUsb_InitializeStreamUrb() siz = 0x%x urb 0x%x\n", siz, urb));
RtlZeroMemory(urb, siz);
urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz;
urb->UrbIsochronousTransfer.Hdr.Function =
URB_FUNCTION_ISOCH_TRANSFER;
urb->UrbIsochronousTransfer.PipeHandle =
streamObject->PipeInfo->PipeHandle;
// We are reading from the device
urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN;
// A device will always use either TransferBufferMDL or TransferBuffer, NEVER both
urb->UrbIsochronousTransfer.TransferBufferMDL = NULL;
urb->UrbIsochronousTransfer.TransferBuffer = TransferObject->DataBuffer;
urb->UrbIsochronousTransfer.TransferBufferLength =
numPackets * packetSize;
// start sending/receiving right away
urb->UrbIsochronousTransfer.TransferFlags |=
USBD_START_ISO_TRANSFER_ASAP;
urb->UrbIsochronousTransfer.NumberOfPackets = numPackets;
urb->UrbIsochronousTransfer.UrbLink = 0;
for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) {
urb->UrbIsochronousTransfer.IsoPacket[i].Offset
= i * packetSize;
}
ISOUSB_KdPrint (DBGLVL_MAXIMUM,(" Init Stream iso urb Length = 0x%x buf = 0x%x\n",
urb->UrbIsochronousTransfer.TransferBufferLength,
urb->UrbIsochronousTransfer.TransferBuffer));
return ntStatus;
}
NTSTATUS
IsoUsb_StartTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_STREAM_OBJECT StreamObject,
IN ULONG Index
)
/*++
Routine Description:
Arguments:
Return Value:
nt status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
CCHAR stackSize;
PDEVICE_EXTENSION deviceExtension;
PISOUSB_TRANSFER_OBJECT transferObject;
ULONG packetSize, numPackets, maxXferSize;
maxXferSize = StreamObject->PipeInfo->MaximumTransferSize; // We set this
packetSize = StreamObject->PipeInfo->MaximumPacketSize; // USBD sets this
numPackets = maxXferSize / packetSize;
ISOUSB_KdPrint (DBGLVL_MEDIUM,(" ENTER IsoUsb_StartTransfer() \n"));
deviceExtension = DeviceObject->DeviceExtension;
transferObject = ExAllocatePool(NonPagedPool, sizeof(ISOUSB_TRANSFER_OBJECT));
if (transferObject) {
PIRP irp;
ISOUSB_KdPrint (DBGLVL_MEDIUM,(" TransferObject = %x \n", transferObject));
RtlZeroMemory( transferObject,sizeof(ISOUSB_TRANSFER_OBJECT));
StreamObject->TransferObjectList[Index] =
transferObject;
transferObject->StreamObject = StreamObject;
stackSize = (CCHAR)(deviceExtension->TopOfStackDeviceObject->StackSize + 1);
transferObject->Irp =
irp = IoAllocateIrp(stackSize,
FALSE);
transferObject->DataBuffer = ExAllocatePool(NonPagedPool,
numPackets *
StreamObject->PipeInfo->MaximumPacketSize);
transferObject->Urb =
ExAllocatePool(NonPagedPool, GET_ISO_URB_SIZE( numPackets ));
if (transferObject->Urb && transferObject->DataBuffer) {
PIO_STACK_LOCATION nextStack;
NTSTATUS status;
IsoUsb_InitializeStreamUrb(DeviceObject, transferObject);
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
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, //pass transfer object as Context
TRUE, // Invoke on Success
TRUE, // Invoke on Error
TRUE); // Invoke on Cancel
//
// submit the request
//
StreamObject->PendingIrps++; // increment this stream's pending irp count
IsoUsb_IncrementIoCount(DeviceObject); // also increment global pending IRP count
status = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
if (transferObject->DataBuffer) {
ExFreePool(transferObject->DataBuffer);
}
if (transferObject->Urb) {
ExFreePool(transferObject->Urb);
}
}
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
ISOUSB_KdPrint (DBGLVL_MEDIUM,(" EXIT IsoUsb_StartTransfer() %x\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_IsoIrp_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context, points to a transfer extension structure
for a pair of parallel iso requests.
Return Value:
The function value is the final status from the operation.
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT deviceObject;
PISOUSB_TRANSFER_OBJECT transferObject;
PISOUSB_STREAM_OBJECT streamObject;
PIO_STACK_LOCATION nextStack;
transferObject = Context;
streamObject = transferObject->StreamObject;
deviceObject = streamObject->DeviceObject;
deviceExtension = deviceObject->DeviceExtension;
streamObject->PendingIrps--; // Decrement this stream's pending irp count
if ( !streamObject->PendingIrps ) { // back to 0? signal no pending irps event
KeSetEvent(&streamObject->NoPendingIrpEvent,
1,
FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -