📄 isodev.c
字号:
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
isodev.c
Abstract:
This file contains dispatch routines
for create and close. This file also
contains routines to selectively suspend
the device. The selective suspend feature
is usb specific and not hardware specific.
Environment:
Kernel mode
Notes:
Copyright (c) 2000 Microsoft Corporation.
All Rights Reserved.
--*/
#include "isousb.h"
#include "isopnp.h"
#include "isopwr.h"
#include "isodev.h"
#include "isousr.h"
#include "isowmi.h"
#include "isorwr.h"
#include "isostrm.h"
NTSTATUS
IsoUsb_DispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for create.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet.
Return Value:
NT status value
--*/
{
LONG i;
NTSTATUS ntStatus;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT_CONTENT fileObjectContent;
PUSBD_INTERFACE_INFORMATION interface;
i = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
PAGED_CODE();
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchCreate - begins\n"));
if(deviceExtension->DeviceState != Working) {
ntStatus = STATUS_INVALID_DEVICE_STATE;
goto IsoUsb_DispatchCreate_Exit;
}
if(deviceExtension->UsbInterface) {
interface = deviceExtension->UsbInterface;
}
else {
IsoUsb_DbgPrint(1, ("UsbInterface not found\n"));
ntStatus = STATUS_INVALID_DEVICE_STATE;
goto IsoUsb_DispatchCreate_Exit;
}
if(fileObject) {
fileObject->FsContext = NULL;
}
else {
ntStatus = STATUS_INVALID_PARAMETER;
goto IsoUsb_DispatchCreate_Exit;
}
fileObject->FsContext = ExAllocatePool(NonPagedPool,
sizeof(FILE_OBJECT_CONTENT));
if(NULL == fileObject->FsContext) {
IsoUsb_DbgPrint(1, ("failed to alloc memory for FILE_OBJECT_CONTENT\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_DispatchCreate_Exit;
}
fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
fileObjectContent->PipeInformation = NULL;
fileObjectContent->StreamInformation = NULL;
if(0 != fileObject->FileName.Length) {
i = IsoUsb_ParseStringForPipeNumber(&fileObject->FileName);
IsoUsb_DbgPrint(3, ("create request for pipe # %X\n", i));
if((i < 0) ||
(i >= (LONG)(deviceExtension->UsbInterface->NumberOfPipes))) {
ntStatus = STATUS_INVALID_PARAMETER;
IsoUsb_DbgPrint(1, ("invalid pipe number\n"));
ExFreePool(fileObject->FsContext);
fileObject->FsContext = NULL;
goto IsoUsb_DispatchCreate_Exit;
}
fileObjectContent->PipeInformation = (PVOID) &interface->Pipes[i];
}
ntStatus = STATUS_SUCCESS;
InterlockedIncrement(&deviceExtension->OpenHandleCount);
//
// the device is idle if it has no open handles or pending PnP Irps
// since we just received an open handle request, cancel idle req.
//
if(deviceExtension->SSEnable) {
CancelSelectSuspend(deviceExtension);
}
IsoUsb_DispatchCreate_Exit:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchCreate - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_DispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for close.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT_CONTENT fileObjectContent;
PAGED_CODE();
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - begins\n"));
if(fileObject && fileObject->FsContext) {
fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
ASSERT(NULL == fileObjectContent->StreamInformation);
ExFreePool(fileObjectContent);
fileObject->FsContext = NULL;
}
//
// set ntStatus to STATUS_SUCCESS
//
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
InterlockedDecrement(&deviceExtension->OpenHandleCount);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_DispatchDevCtrl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for IRP_MJ_DEVICE_CONTROL
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
ULONG code;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG info;
NTSTATUS ntStatus;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
//
// initialize variables
//
info = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
code = irpStack->Parameters.DeviceIoControl.IoControlCode;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
if(deviceExtension->DeviceState != Working) {
IsoUsb_DbgPrint(1, ("Invalid device state\n"));
Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchDevCtrl::"));
IsoUsb_IoIncrement(deviceExtension);
//
// make sure that the selective suspend request has been completed.
//
if(deviceExtension->SSEnable) {
//
// It is true that the client driver cancelled the selective suspend
// request in the dispatch routine for create.
// But there is no guarantee that it has indeed been completed.
// so wait on the NoIdleReqPendEvent and proceed only if this event
// is signalled.
//
IsoUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
switch(code) {
case IOCTL_ISOUSB_RESET_PIPE:
{
PUSBD_PIPE_INFORMATION pipe;
pipe = NULL;
if(fileObject && fileObject->FsContext) {
pipe = (PUSBD_PIPE_INFORMATION)
((PFILE_OBJECT_CONTENT)fileObject->FsContext)->PipeInformation;
}
if(pipe == NULL) {
ntStatus = STATUS_INVALID_PARAMETER;
}
else {
ntStatus = IsoUsb_ResetPipe(DeviceObject, pipe);
}
break;
}
case IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR:
{
ULONG length;
if(deviceExtension->UsbConfigurationDescriptor) {
length = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
if(outputBufferLength >= length) {
RtlCopyMemory(ioBuffer,
deviceExtension->UsbConfigurationDescriptor,
length);
info = length;
ntStatus = STATUS_SUCCESS;
}
else {
ntStatus = STATUS_INVALID_BUFFER_SIZE;
}
}
else {
ntStatus = STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_ISOUSB_RESET_DEVICE:
ntStatus = IsoUsb_ResetDevice(DeviceObject);
break;
case IOCTL_ISOUSB_START_ISO_STREAM:
ntStatus = IsoUsb_StartIsoStream(DeviceObject, Irp);
return STATUS_SUCCESS;
case IOCTL_ISOUSB_STOP_ISO_STREAM:
{
PFILE_OBJECT_CONTENT fileObjectContent;
if(fileObject && fileObject->FsContext) {
fileObjectContent = (PFILE_OBJECT_CONTENT)
fileObject->FsContext;
ntStatus = IsoUsb_StopIsoStream(
DeviceObject,
InterlockedExchangePointer(
&fileObjectContent->StreamInformation,
NULL),
Irp);
}
else {
ntStatus = STATUS_UNSUCCESSFUL;
}
break;
}
default :
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchDevCtrl::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
}
LONG
IsoUsb_ParseStringForPipeNumber(
IN PUNICODE_STRING PipeName
)
/*++
Routine Description:
This routine parses the PipeName for the Pipe#
Arguments:
PipeName - Unicode string for the pipe name
Return Value:
Pipe number
--*/
{
LONG bufferIndex;
ULONG uval;
ULONG umultiplier;
if(PipeName->Length == 0) {
return -1;
}
bufferIndex = (PipeName->Length / sizeof(WCHAR)) - 1;
while((bufferIndex > -1) &&
((PipeName->Buffer[bufferIndex] < (WCHAR) '0') ||
(PipeName->Buffer[bufferIndex] > (WCHAR) '9'))) {
bufferIndex--;
}
if(bufferIndex > -1) {
uval = 0;
umultiplier = 1;
while((bufferIndex > -1) &&
(PipeName->Buffer[bufferIndex] >= (WCHAR) '0') &&
(PipeName->Buffer[bufferIndex] <= (WCHAR) '9')) {
uval += (umultiplier *
(ULONG) (PipeName->Buffer[bufferIndex] - (WCHAR) '0'));
bufferIndex--;
umultiplier *= 10;
}
return uval;
}
return -1;
}
NTSTATUS
IsoUsb_ResetPipe(
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE_INFORMATION PipeInfo
)
/*++
Routine Description:
This routine submits an irp/urb pair synchronously
with function code URB_FUNCTION_RESET_PIPE to reset
the pipe
Arguments:
DeviceObject - pointer to device object
PipeInfo - pointer to USBD_PIPE_INFORMATION
Return Value:
NT status value
--*/
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -