⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbfx2lk_pnp.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//    (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 + -