📄 ocrwiso.c
字号:
/*++
Copyright (c) 1997-1998 Microsoft Corporation
Module Name:
OcrwIso.c
Abstract:
Isochronous USB device driver for Intel 82930 USB test board
Read/write io 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:
11/17/97 : created
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#define DRIVER
#include "usbdi.h"
#include "usbdlib.h"
#include "Iso82930.h"
PURB
IsoUsb_BuildIsoRequest(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUSBD_PIPE_INFORMATION PipeHandle,
IN BOOLEAN Read
)
/*++
Routine Description:
This is the routine used to build a USBD request for IRP_MJ_READ and IRP_MJ_WRITE ioctls.
IsoUsb_InitializeStreamUrb(), defined in IsoStrm.c, performs an analogous role
for the continuous stream test ( as initiated by IOCTL_ISOUSB_START_ISO_STREAM )
Arguments:
DeviceObject - pointer to the device extension for this instance of the
82930 device.
Irp -
PipeHandle - pointer to USBD-defined pipe descriptor
Return Value:
initialized iso urb.
--*/
{
ULONG siz;
ULONG length, packetSize, numPackets, i;
PURB urb = NULL;
PIO_STACK_LOCATION irpSp;
LARGE_INTEGER byteOffset;
irpSp = IoGetCurrentIrpStackLocation(Irp);
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IsoUsb_BuildIsoRequest handle = 0x%x\n", PipeHandle));
length = MmGetMdlByteCount(Irp->MdlAddress);
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" length = 0x%x, decimal %d\n", length, length));
byteOffset = irpSp->Parameters.Read.ByteOffset;
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" offset = 0x%08X.%08X decimal high %08d low %08d\n",
byteOffset.HighPart,
byteOffset.LowPart,
byteOffset.HighPart,
byteOffset.LowPart
));
packetSize = PipeHandle->MaximumPacketSize;
numPackets = length/packetSize;
if (numPackets*packetSize < length) {
numPackets++;
}
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" PipeHandle->MaximumPacketSize = 0x%x, decimal %d\n", PipeHandle->MaximumPacketSize, PipeHandle->MaximumPacketSize));
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" numPackets (length/maxPacketSize) = 0x%x, decimal %d\n", numPackets, numPackets));
siz = GET_ISO_URB_SIZE(numPackets);
urb = ExAllocatePool(NonPagedPool, siz);
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IsoUsb_BuildIsoRequest URB siz = 0x%x decimal %d urb 0x%x\n", siz, siz, urb));
if (urb) {
RtlZeroMemory(urb, siz);
urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz;
urb->UrbIsochronousTransfer.Hdr.Function =
URB_FUNCTION_ISOCH_TRANSFER;
urb->UrbIsochronousTransfer.PipeHandle =
PipeHandle->PipeHandle;
urb->UrbIsochronousTransfer.TransferFlags =
Read ? USBD_TRANSFER_DIRECTION_IN : 0;
urb->UrbIsochronousTransfer.TransferBufferMDL =
Irp->MdlAddress;
urb->UrbIsochronousTransfer.TransferBufferLength =
length;
if (byteOffset.HighPart)
{
urb->UrbIsochronousTransfer.StartFrame =
IsoUsb_GetCurrentFrame(DeviceObject, Irp) +
byteOffset.LowPart;
}
else
{
// start sending/receiving right away
urb->UrbIsochronousTransfer.TransferFlags |=
USBD_START_ISO_TRANSFER_ASAP;
}
urb->UrbIsochronousTransfer.NumberOfPackets = numPackets;
urb->UrbIsochronousTransfer.UrbLink = NULL;
for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) {
urb->UrbIsochronousTransfer.IsoPacket[i].Offset
= i * packetSize;
}
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IsoUsb_BuildIsoRequest Init iso urb Length = 0x%x buf = 0x%x\n",
urb->UrbIsochronousTransfer.TransferBufferLength,
urb->UrbIsochronousTransfer.TransferBuffer));
}
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" EXIT IsoUsb_BuildIsoRequest()\n"));
return urb;
}
NTSTATUS
IsoUsb_IsoReadWrite_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the routine used to complete IRP_MJ_READ and IRP_MJ_WRITE ioctls.
IsoUsb_IsoIrp_Complete(), defined in IsoStrm.c, performs an analogous role
for the continuous stream test ( as initiated by IOCTL_ISOUSB_START_ISO_STREAM )
Arguments:
DeviceObject - Pointer to the device object for the ISOUSB device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb = Context;
PUSBD_PIPE_INFORMATION pipeHandle;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack;
ULONG i;
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// ISSUE: check here for interesting iso error conditions
//
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IsoUsb_IsoReadWrite_Complete()\n Iso Completion: StartFrame 0x%08X, Status 0x%08X\n",
urb->UrbIsochronousTransfer.StartFrame,
urb->UrbHeader.Status));
for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++)
{
ISOUSB_KdPrint ( DBGLVL_MAXIMUM , (" IsoUsb_IsoReadWrite_Complete() [%02d] Length 0x%08X, Status 0x%08X\n",
i,
urb->UrbIsochronousTransfer.IsoPacket[i].Length,
urb->UrbIsochronousTransfer.IsoPacket[i].Status
));
if (!USBD_SUCCESS(
urb->UrbIsochronousTransfer.IsoPacket[i].Status)) {
ISOUSB_KdPrint ( DBGLVL_MEDIUM , (" IsoUsb_IsoReadWrite_Complete() BAD 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
}
}
//
// set the length based on the TransferBufferLength
// value in the URB
//
Irp->IoStatus.Information =
urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
// get pipe handle
pipeHandle = fileObject->FsContext;
IsoUsb_DecrementIoCount(DeviceObject);
ExFreePool(urb);
return ntStatus;
}
NTSTATUS
IsoUsb_Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PUSBD_PIPE_INFORMATION pipeHandle;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PDEVICE_EXTENSION deviceExtension;
PURB urb;
PISOUSB_RW_CONTEXT context = NULL;
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" ENTER IsoUsb_Read()\n"));
if ( !Irp->MdlAddress ) { // this is NULL for a 0-len request; just return SUCCESS
goto IsoUsb_Read_Reject;
}
IsoUsb_IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
if ( !IsoUsb_CanAcceptIoRequests( DeviceObject ) ) {
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
IsoUsb_DecrementIoCount(DeviceObject);
ISOUSB_KdPrint ( DBGLVL_DEFAULT, ("IsoUsb_Read() can't accept requests, returning STATUS_INSUFFICIENT_RESOURCES\n"));
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
if (!pipeHandle) {
ntStatus = STATUS_INVALID_HANDLE;
goto IsoUsb_Read_Reject;
}
//
// submit the write request to USB
//
ISOUSB_ASSERT( UsbdPipeTypeIsochronous == pipeHandle->PipeType );
IsoUsb_ResetPipe(DeviceObject, pipeHandle, FALSE);
urb = IsoUsb_BuildIsoRequest(DeviceObject,
Irp,
pipeHandle,
TRUE);
if (urb) {
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);
ASSERT(DeviceObject->StackSize>1);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp,
IsoUsb_IsoReadWrite_Complete,
urb, // pass URB as context
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancel
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IsoUsb_Read() IRP = 0x%x current = 0x%x next = 0x%x\n",
Irp, irpStack, nextStack));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
goto IsoUsb_Read_Done;
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
IsoUsb_Read_Reject:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
IsoUsb_Read_Done:
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" EXIT IsoUsb_Read()\n" ));
return ntStatus;
}
NTSTATUS
IsoUsb_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PUSBD_PIPE_INFORMATION pipeHandle;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PDEVICE_EXTENSION deviceExtension;
PURB urb;
PISOUSB_RW_CONTEXT context = NULL;
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" ENTER IsoUsb_Write()\n"));
if ( !Irp->MdlAddress ) { // this is NULL for a 0-len request; just return SUCCESS
goto IsoUsb_Write_Reject;
}
IsoUsb_IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
if ( !IsoUsb_CanAcceptIoRequests( DeviceObject ) ) {
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
IsoUsb_DecrementIoCount(DeviceObject);
ISOUSB_KdPrint ( DBGLVL_DEFAULT, ("IsoUsb_Write() can't accept requests, returning STATUS_INSUFFICIENT_RESOURCES\n"));
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
if (!pipeHandle)
{
ntStatus = STATUS_INVALID_HANDLE;
goto IsoUsb_Write_Reject;
}
//
// submit the write request to USB
//
IsoUsb_ResetPipe(DeviceObject, pipeHandle, FALSE);
urb = IsoUsb_BuildIsoRequest(DeviceObject,
Irp,
pipeHandle,
FALSE);
if (urb) {
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);
ASSERT(DeviceObject->StackSize>1);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp,
IsoUsb_IsoReadWrite_Complete,
urb, // pass urb as context
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancel
ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" IRP = 0x%x current = 0x%x next = 0x%x\n",
Irp, irpStack, nextStack));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
goto IsoUsb_Write_Done;
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
IsoUsb_Write_Reject:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
IsoUsb_Write_Done:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -