📄 usbfx2lk_pnp.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2005 OSR Open Systems Resources, Inc.
// Copyright (c) 2000 Microsoft Corporation
// All Rights Reserved
//
// This sofware is supplied for instructional purposes only.
//
// OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
// for this software. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
// WITH YOU. OSR's entire liability and your exclusive remedy shall not
// exceed the price paid for this material. In no event shall OSR or its
// suppliers be liable for any damages whatsoever (including, without
// limitation, damages for loss of business profit, business interruption,
// loss of business information, or any other pecuniary loss) arising out
// of the use or inability to use this software, even if OSR has been
// advised of the possibility of such damages. Because some states/
// jurisdictions do not allow the exclusion or limitation of liability for
// consequential or incidental damages, the above limitation may not apply
// to you.
//
// OSR Open Systems Resources, Inc.
// 105 Route 101A Suite 19
// Amherst, NH 03031 (603) 595-6500 FAX: (603) 595-6503
// email bugs to: bugs@osr.com
//
//
// MODULE:
//
// USBFx2LK_PnP.cpp
//
// ABSTRACT:
//
// This file contains the routines that handle Plug and Play processing for the
// OSR USB FX2 Learning Kit Device
//
// AUTHOR(S):
//
// OSR Open Systems Resources, Inc.
//
///////////////////////////////////////////////////////////////////////////////
#include "usbfx2lk.h"
#ifdef WPP_TRACING
//
// Include the necessary tmh file - this is
// just a matter of course if you're using WPP tracing.
//
extern "C" {
#include "usbfx2lk_pnp.tmh"
}
#endif
LONG InstanceNumber = 0;
//
// Forward Definitions
//
static NTSTATUS OsrStartDevice(PUSBFX2LK_EXT DevExt);
static VOID OsrDecrementOutstandingIoCountAndWait(PUSBFX2LK_EXT DevExt);
static VOID OsrReturnResources(PUSBFX2LK_EXT DevExt);
static NTSTATUS OsrCanStopDevice(PUSBFX2LK_EXT DevExt, PIRP Irp);
static NTSTATUS OsrCanRemoveDevice(PUSBFX2LK_EXT DevExt, PIRP Irp) ;
//
// Informational Strings
//
static PSTR pnpMinorCodes[] =
{
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"***** FUNCTION 0x0e",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION"
};
CONST PCHAR OsrPrintState(PUSBFX2LK_EXT DevExt)
{
switch(DevExt->DevicePnPState) {
case STATE_REMOVED:
return "STATE_REMOVED";
case STATE_STARTED:
return "STATE_STARTED";
case STATE_REMOVE_PENDING:
return "STATE_REMOVE_PENDING";
case STATE_SURPRISE_REMOVED:
return "STATE_SURPRISE_REMOVED";
case STATE_STOP_PENDING:
return "STATE_STOP_PENDING";
case STATE_STOPPED:
return "STATE_STOPPED";
case STATE_NEVER_STARTED:
return "STATE_NEVER_STARTED";
default:
break;
}
return "*********UNKNOWN STATE Value";
}
///////////////////////////////////////////////////////////////////////////////
//
// UsbFx2LkAddDevice
//
// We are called at this entry point by the Plug and Play Manager
// to add a Functional Device Object for a Physical Device Object.
// Note that we may NOT access our device via the USB bus in this routine,
// we must wait until we have received an IRP_MJ_PNP/IRP_START_DEVICE before
// we can try to talk to our device
//
// INPUTS:
//
// DriverObject - Address of our DRIVER_OBJECT.
//
// PhysicalDeviceObject - Address of our physical device
// object (PDO)
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_SUCCESS if success, an appropriate error otherwise
//
// IRQL:
//
// This routine is called at IRQL == PASSIVE_LEVEL.
//
// CONTEXT:
//
// This routine is called in the context of the System process
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS UsbFx2LkAddDevice(PDRIVER_OBJECT PDriverObject,
PDEVICE_OBJECT PPhysicalDeviceObject)
{
PUSBFX2LK_EXT devExt = NULL;
PDEVICE_OBJECT pFunctionalDeviceObject = NULL;
UNICODE_STRING devName;
NTSTATUS status = STATUS_SUCCESS;
WCHAR devNameBuffer[256];
size_t devNameBufferSize = sizeof(devNameBuffer);
OBJECT_ATTRIBUTES oa;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO, ("UsbFx2LkAddDevice: Entered\n"));
//
// We're guaranteed to be called here at IRQL PASSIVE_LEVEL
//
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Format a new device name string, based off a template and an instance
// number.
//
status = RtlStringCbPrintfW(devNameBuffer,devNameBufferSize,
L"\\Device\\USBFX2LK%d",InterlockedIncrement(&InstanceNumber));
//
// Make sure that the creation worked. If not, get out of here.
//
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: RtlStringCbPrintfW Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
return status;
}
//
// Initialize the Unicode Name structure to be used for the Device Name.
//
RtlInitUnicodeString(&devName, devNameBuffer);
//
// Create the FDO for the device.
//
status = IoCreateDevice(PDriverObject,
sizeof(USBFX2LK_EXT),
&devName,
FILE_DEVICE_OSRUSBFX2LK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pFunctionalDeviceObject);
if (!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: IoCreateDevice Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
return status;
}
//
// Get a pointer to the Device Extension and Initialize the fields that we need.
//
devExt = (PUSBFX2LK_EXT) pFunctionalDeviceObject->DeviceExtension;
RtlZeroMemory(devExt,sizeof(USBFX2LK_EXT));
devExt->MagicNumber = USBFX2LK_EXT_MAGIC_NUMBER;
devExt->InstanceNumber = InstanceNumber;
devExt->FunctionalDeviceObject = pFunctionalDeviceObject;
devExt->PhysicalDeviceObject = PPhysicalDeviceObject;
//
// Set the Initial PnP State.
//
devExt->DevicePnPState = STATE_NEVER_STARTED;
//
// The device and system are is implicitly in D0 when
// we arrive in the system
//
devExt->DevicePowerState = PowerDeviceD0;
devExt->SystemPowerState = PowerSystemWorking;
//
// Default to supporting selective suspend
//
devExt->SSEnabledByUser = TRUE;
devExt->SSState = SS_NOT_STARTED;
//
// Biased to 1. Transition to 0 during remove device
// means IO is finished. Transition to 1 means
// the device can be stopped.
//
devExt->OutStandingIoCount = 1;
//
// Initialize our stop and remove Events
//
KeInitializeEvent(&devExt->RemoveEvent,NotificationEvent,FALSE);
KeInitializeEvent(&devExt->StopEvent,NotificationEvent,TRUE);
//
// And initialize the other events used in selective suspend
// processing
//
KeInitializeEvent(&devExt->SSSubmissionThreadTerminateEvent,NotificationEvent,FALSE);
KeInitializeEvent(&devExt->SSDeviceNotSuspendedEvent,NotificationEvent,TRUE);
#ifndef W2K
KeInitializeEvent(&devExt->SSIdleCallbackCalled,NotificationEvent,FALSE);
KeInitializeEvent(&devExt->SSIdleCompletionRoutineCalled,NotificationEvent,FALSE);
#endif
//
// Initialize our locks...
//
KeInitializeSpinLock(&devExt->CancelSafeIoLock);
KeInitializeSpinLock(&devExt->IoStateLock);
KeInitializeSpinLock(&devExt->SSLock);
//
// ...and our list head...
//
InitializeListHead(&devExt->IoQueue);
//
// We need to create a thread for use in
// selective suspend
//
//
// We'll need a kernel handle for this thread
//
InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
//
// Create the thread
//
status = PsCreateSystemThread(&devExt->SSSubmissionThread,
THREAD_ALL_ACCESS,
&oa,
NULL,
NULL,
SSSubmissionThreadRoutine,
devExt);
if (!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: PsCreateSystemThread failed 0x%x (%s).\n",status,OsrNtStatusToString(status)));
IoDeleteDevice(devExt->FunctionalDeviceObject);
return status;
}
//
// We'll also need the object pointer for the thread
// so that we can wait for it to terminate when
// cleaning up selective suspend
//
status = ObReferenceObjectByHandle(devExt->SSSubmissionThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&devExt->SSSubmissionThreadObject,
NULL);
if (!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_SELECTIVE_SUSPEND,
("UsbFx2LkAddDevice: ObReferenceObjectByHandle failed 0x%x (%s).\n",status,OsrNtStatusToString(status)));
//
// Set the terminate thread event and close the HANDLE.
// Unfortunately we can't wait for the thread to terminate
// (we don't have an object to wait on) so we don't
// have any choice but to exit and hope that the thread
// terminates quickly (which it should).
//
// This call failing would be very strange indeed...
//
KeSetEvent(&devExt->SSSubmissionThreadTerminateEvent,
EVENT_INCREMENT, FALSE);
ZwClose(devExt->SSSubmissionThread);
IoDeleteDevice(devExt->FunctionalDeviceObject);
return status;
}
//
// Initialize the cancel safe I/O queue
//
#ifdef W2K3
status = IoCsqInitializeEx(&devExt->CancelSafeIoQueue,
OsrCsqInsertIoIrpEx,
OsrCsqRemoveIoIrp,
OsrCsqPeekNextIoIrp,
OsrCsqAcquireIoLock,
OsrCsqReleaseIoLock,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -