📄 isodev.c
字号:
/*++
Copyright (c) 2004 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) 2004 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
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PFILE_OBJECT_CONTENT fileObjectContent;
LONG i;
NTSTATUS ntStatus;
PAGED_CODE();
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchCreate - begins\n"));
if (deviceExtension->DeviceState != Working)
{
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;
}
// Exclude configuration changes while trying to open a pipe
//
KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
Executive,
KernelMode,
FALSE,
NULL);
fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
fileObjectContent->PipeInformation = NULL;
fileObjectContent->StreamInformation = NULL;
if (fileObject->FileName.Length != 0)
{
// Convert the pipe name string into a pipe number
//
i = IsoUsb_ParseStringForPipeNumber(&fileObject->FileName);
IsoUsb_DbgPrint(3, ("create request for pipe # %X\n", i));
// Bounds check the pipe number
//
if ((i < 0) || (i >= (LONG)(deviceExtension->NumberOfPipes)))
{
// Failure opening a pipe
//
IsoUsb_DbgPrint(1, ("invalid pipe number\n"));
ExFreePool(fileObject->FsContext);
fileObject->FsContext = NULL;
ntStatus = STATUS_INVALID_PARAMETER;
}
else
{
// Success opening a pipe
//
fileObjectContent->PipeInformation =
(PVOID) deviceExtension->PipeInformation[i];
InterlockedIncrement(&deviceExtension->OpenHandleCount);
ntStatus = STATUS_SUCCESS;
}
}
else
{
// No pipe name string, Success opening entire device
//
InterlockedIncrement(&deviceExtension->OpenHandleCount);
ntStatus = STATUS_SUCCESS;
}
KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
IO_NO_INCREMENT,
1,
FALSE);
// 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 (NT_SUCCESS(ntStatus) && 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
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PFILE_OBJECT_CONTENT fileObjectContent;
NTSTATUS ntStatus;
PAGED_CODE();
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - begins\n"));
KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
Executive,
KernelMode,
FALSE,
NULL);
if (fileObject && fileObject->FsContext)
{
fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
ASSERT(NULL == fileObjectContent->StreamInformation);
ExFreePool(fileObjectContent);
fileObject->FsContext = NULL;
}
InterlockedDecrement(&deviceExtension->OpenHandleCount);
KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
IO_NO_INCREMENT,
1,
FALSE);
//
// set ntStatus to STATUS_SUCCESS
//
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_IoctlSelectAltInterface(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PFILE_OBJECT_CONTENT fileObjectContent;
PUCHAR ioBuffer;
ULONG inputBufferLength;
UCHAR interfaceNumber;
UCHAR alternateSetting;
NTSTATUS ntStatus;
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
if (inputBufferLength != 2 * sizeof(UCHAR))
{
return STATUS_INVALID_BUFFER_SIZE;
}
interfaceNumber = ioBuffer[0];
alternateSetting = ioBuffer[1];
// Exclude other configuration changes and handle opens.
//
KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
Executive,
KernelMode,
FALSE,
NULL);
fileObject = irpStack->FileObject;
fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
// Make sure there is only one handle open (i.e. the one that is
// being used to issue this request) and it is for the entire
// device, not for a pipe.
//
if (deviceExtension->OpenHandleCount == 1 &&
fileObjectContent->PipeInformation == NULL)
{
ntStatus = IsoUsb_SelectAlternateInterface(DeviceObject,
interfaceNumber,
alternateSetting);
}
else
{
ntStatus = STATUS_DEVICE_BUSY;
}
// Allow other configuration changes and handle opens.
//
KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
IO_NO_INCREMENT,
1,
FALSE);
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_AbortResetPipe(DeviceObject,
pipe->PipeHandle,
TRUE);
}
break;
}
case IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR:
{
ULONG length;
if(deviceExtension->ConfigurationDescriptor) {
length = deviceExtension->ConfigurationDescriptor->wTotalLength;
if(outputBufferLength >= length) {
RtlCopyMemory(ioBuffer,
deviceExtension->ConfigurationDescriptor,
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;
}
case IOCTL_ISOUSB_SELECT_ALT_INTERFACE:
ntStatus = IsoUsb_IoctlSelectAltInterface(DeviceObject, Irp);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -