?? bulkdev.c
字號:
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
bulkdev.c
Abstract:
This file contains dispatch routines for create,
close and selective suspend.
The selective suspend feature is enabled if
the SSRegistryEnable key in the registry is set to 1.
Environment:
Kernel mode
Notes:
Copyright (c) 2000 Microsoft Corporation.
All Rights Reserved.
--*/
#include "bulkusb.h"
#include "bulkpnp.h"
#include "bulkpwr.h"
#include "bulkdev.h"
#include "bulkusr.h"
#include "bulkwmi.h"
#include "bulkrwr.h"
NTSTATUS
BulkUsb_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
--*/
{
ULONG i;
NTSTATUS ntStatus;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PBULKUSB_PIPE_CONTEXT pipeContext;
PUSBD_INTERFACE_INFORMATION interface;
PAGED_CODE();
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchCreate - begins\n"));
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
if(deviceExtension->DeviceState != Working) {
ntStatus = STATUS_INVALID_DEVICE_STATE;
goto BulkUsb_DispatchCreate_Exit;
}
if(deviceExtension->UsbInterface) {
interface = deviceExtension->UsbInterface;
}
else {
BulkUsb_DbgPrint(1, ("UsbInterface not found\n"));
ntStatus = STATUS_INVALID_DEVICE_STATE;
goto BulkUsb_DispatchCreate_Exit;
}
//
// FsContext is Null for the device
//
if(fileObject) {
fileObject->FsContext = NULL;
}
else {
ntStatus = STATUS_INVALID_PARAMETER;
goto BulkUsb_DispatchCreate_Exit;
}
if(0 == fileObject->FileName.Length) {
//
// opening a device as opposed to pipe.
//
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);
}
goto BulkUsb_DispatchCreate_Exit;
}
pipeContext = BulkUsb_PipeWithName(DeviceObject, &fileObject->FileName);
if(pipeContext == NULL) {
ntStatus = STATUS_INVALID_PARAMETER;
goto BulkUsb_DispatchCreate_Exit;
}
ntStatus = STATUS_INVALID_PARAMETER;
for(i=0; i<interface->NumberOfPipes; i++) {
if(pipeContext == &deviceExtension->PipeContext[i]) {
//
// found a match
//
BulkUsb_DbgPrint(3, ("open pipe %d\n", i));
fileObject->FsContext = &interface->Pipes[i];
ASSERT(fileObject->FsContext);
pipeContext->PipeOpen = TRUE;
ntStatus = STATUS_SUCCESS;
//
// increment OpenHandleCounts
//
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);
}
}
}
BulkUsb_DispatchCreate_Exit:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchCreate - ends\n"));
return ntStatus;
}
NTSTATUS
BulkUsb_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;
PBULKUSB_PIPE_CONTEXT pipeContext;
PUSBD_PIPE_INFORMATION pipeInformation;
PAGED_CODE();
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pipeContext = NULL;
pipeInformation = NULL;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchClose - begins\n"));
if(fileObject && fileObject->FsContext) {
pipeInformation = fileObject->FsContext;
if(0 != fileObject->FileName.Length) {
pipeContext = BulkUsb_PipeWithName(DeviceObject,
&fileObject->FileName);
}
if(pipeContext && pipeContext->PipeOpen) {
pipeContext->PipeOpen = FALSE;
}
}
//
// set ntStatus to STATUS_SUCCESS
//
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
InterlockedDecrement(&deviceExtension->OpenHandleCount);
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchClose - ends\n"));
return ntStatus;
}
NTSTATUS
BulkUsb_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;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
//
// initialize variables
//
info = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
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) {
BulkUsb_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;
}
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::"));
BulkUsb_IoIncrement(deviceExtension);
//
// 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.
//
BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
//
// make sure that the selective suspend request has been completed.
//
if(deviceExtension->SSEnable) {
KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
switch(code) {
case IOCTL_BULKUSB_RESET_PIPE:
{
PFILE_OBJECT fileObject;
PUSBD_PIPE_INFORMATION pipe;
pipe = NULL;
fileObject = NULL;
//
// FileObject is the address of the kernel file object to
// which the IRP is directed. Drivers use the FileObject
// to correlate IRPs in a queue.
//
fileObject = irpStack->FileObject;
if(fileObject == NULL) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;
if(pipe == NULL) {
ntStatus = STATUS_INVALID_PARAMETER;
}
else {
ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe);
}
break;
}
case IOCTL_BULKUSB_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_BUFFER_TOO_SMALL;
}
}
else {
ntStatus = STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_BULKUSB_RESET_DEVICE:
ntStatus = BulkUsb_ResetDevice(DeviceObject);
break;
default :
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::"));
BulkUsb_IoDecrement(deviceExtension);
return ntStatus;
}
NTSTATUS
BulkUsb_ResetPipe(
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE_INFORMATION PipeInfo
)
/*++
Routine Description:
This routine synchronously submits a URB_FUNCTION_RESET_PIPE
request down the stack.
Arguments:
DeviceObject - pointer to device object
PipeInfo - pointer to PipeInformation structure
to retrieve the pipe handle
Return Value:
NT status value
--*/
{
PURB urb;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
//
// initialize variables
//
urb = NULL;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_PIPE_REQUEST));
if(urb) {
urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
urb->UrbPipeRequest.PipeHandle = PipeInfo->PipeHandle;
ntStatus = CallUSBD(DeviceObject, urb);
ExFreePool(urb);
}
else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if(NT_SUCCESS(ntStatus)) {
BulkUsb_DbgPrint(3, ("BulkUsb_ResetPipe - success\n"));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -