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

📄 pnp.c

📁 ir 驱动程序源代码,make成功了,有兴趣的朋友可以看看
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright 2005 OSR, Open Systems Resources, Inc. All rights Reserved.
// 
// Module Name:
// 
//     pnp.c
// 
// Abstract:
//
//     Contains routines to handle PnP and power transitions
// 
// Author:
//
// Revision History:
//      
#include "smscir.h"

#ifdef WPP_TRACING
#include "pnp.tmh"
#endif

VOID
SmscIrEvtIoQueueStop(
    IN WDFQUEUE Queue,
    IN WDFREQUEST Request,
    IN ULONG  ActionFlags
    );


NTSTATUS
SmscIrEvtDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    ) {
/*++
Routine Description.

  This routine is called when the FDO for the SMSC
  IR device needs to be created

Arguments:

  Driver     - Our WDF Driver object (not used)
  
  DeviceInit - The WDFDEVICE_INIT structure that we will use to
                indicate the characteristics of our device

--*/
    NTSTATUS                         status;
    PSMSCIR_DATA                     deviceData;
    WDF_PNPPOWER_EVENT_CALLBACKS     pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES            fdoAttributes;
    WDFDEVICE                        device;
    WDF_IO_QUEUE_CONFIG              ioQueueConfig;
    WDF_FILEOBJECT_CONFIG            fileConfig;
    WDF_INTERRUPT_CONFIG             interruptConfig;
    WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;
    WDF_TIMER_CONFIG                 timerConfig;
    WDF_OBJECT_ATTRIBUTES            timerAttributes;

    SmscIrTracePrint(
            TRACE_LEVEL_VERBOSE,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Entered"));


    //
    // Initialize all the properties specific to the device.
    // Framework has default values for the one that are not
    // set explicitly here.
    //
    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SMSCIR);

    //
    // We want MDLs...
    //
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    //
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,    
    // the Framework will take appropriate default actions for an FDO
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    // 
    // We'll need to get our port resource in the prepare
    //  callback and return it in the release.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware 
                                        = SmscIrEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware 
                                        = SmscIrEvtDeviceReleaseHardware;
    
    //
    // These two callbacks are called as we go in and out of the D0-working 
    //  state.
    //
    pnpPowerCallbacks.EvtDeviceD0Entry = SmscIrEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = SmscIrEvtDeviceD0Exit;    

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);


    WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);

    //
    // We might need to arm the device for wake, so provide
    //  an "arming for wake" callback
    //
    powerPolicyCallbacks.EvtDeviceArmWakeFromSx = SmscIrEvtDeviceWakeArm;


    //
    // Register the power policy callbacks.
    //
    WdfDeviceInitSetPowerPolicyEventCallbacks(DeviceInit, &powerPolicyCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);

    //
    // We deal with our synchronization
    //
    fdoAttributes.SynchronizationScope = WdfSynchronizationScopeNone;

    //
    // Specify size and accessor function for storing device context.
    //
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, SMSCIR_DATA);

    //
    // We want to specify an open and close routine so we know 
    //  when IRCLASS is trying to open our device...
    //
    WDF_FILEOBJECT_CONFIG_INIT(&fileConfig,
                               SmscIrEvtDeviceFileCreate,
                               SmscIrEvtFileClose,
                               NULL);

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                                     &fileConfig,
                                     NULL);


    //
    // Create a framework device object. In response to this call, framework
    // creates a WDM deviceobject and attaches it to the PDO.
    //
    status = WdfDeviceCreate(&DeviceInit, 
                             &fdoAttributes, 
                             &device);

    if (!NT_SUCCESS(status)) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: WdfDeviceCreate failed - 0x%x", status));

        return status;
    }


    //
    // Initialize our context area....
    //
    deviceData = (PSMSCIR_DATA)GetIrData(device);

    //
    // Keep a pointer to the driver
    //
    deviceData->WdfDriverObject = Driver;

    //
    // Set the default number of FFs we need to see to signal
    //  a data end
    //
    deviceData->NumFFsForDataEnd = SMSCIR_NUM_FFS_FOR_DATA_END;


    //
    // Initialize the basic portions of our receivers
    //
    SMSCIR_INITIALIZE_RECEIVER(&deviceData->Receiver, 
                               deviceData, 
                               FALSE);
    SMSCIR_INITIALIZE_RECEIVER(&deviceData->PriorityReceiver, 
                               deviceData, 
                               TRUE);

    KeInitializeSpinLock(&deviceData->TxFifoDataLock);
    InitializeListHead(&deviceData->TxFifoDataList);

    //
    // Create our deadman timer
    //
    WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, 
                                   SmscIrEvtDeadManTimerForTransmit,
                                   SMSCIR_DEADMAN_TIMER_PERIOD);

    WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);

    //
    // Set the device as the parent of the timer so
    //  that the timer will go away when the 
    //  device does
    //
    timerAttributes.ParentObject = device;

    status = WdfTimerCreate(&timerConfig,
                            &timerAttributes,
                            &deviceData->DeadManTimer);

    if (!NT_SUCCESS(status)) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Error creating timer - 0x%x", status));
        return status;
    }                            


    //
    // Create our interrupt object.
    //
    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                              SmscIrEvtInterruptIsr,
                              SmscIrEvtInterruptDpc);

    interruptConfig.EvtInterruptEnable  = SmscIrEvtInterruptEnable;
    interruptConfig.EvtInterruptDisable = SmscIrEvtInterruptDisable;

    status = WdfInterruptCreate(device,
                                &interruptConfig,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &deviceData->Interrupt);

    if( !NT_SUCCESS(status) ) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Error creating interrupt - 0x%x", status));
        return status;
    }

    //
    // Create a parallel default queue
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                           WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl = SmscIrEvtIoDeviceControl;

    //
    // And we need a stop callback so that we can kill the current
    //  IR receive request
    //
    ioQueueConfig.EvtIoStop          = SmscIrEvtIoQueueStop;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              NULL);

    if (!NT_SUCCESS(status)) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: WdfIoQueueCreate failed - 0x%x", status));
        return status;
    }


    //
    // Serial queue for things that we want to process 
    //  exclusive to each other.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig,
                             WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDeviceControl = SmscIrEvtIoDeviceControlSerial;
    ioQueueConfig.EvtIoStop          = SmscIrEvtIoQueueStop;
    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &deviceData->SerialQueue);

    if(!NT_SUCCESS (status)){
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Creating IOCTL queue - 0x%x", status));
        return status;
    }


    //
    // Manual internal queue for regular receives reqeusts. 
    //  This will be used to queue the recieve requests presented 
    //  to us from the parallel default queue
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig,
                             WdfIoQueueDispatchManual);


    ioQueueConfig.EvtIoStop = SmscIrEvtIoQueueStop;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &deviceData->Receiver.PendingReceiveQueue);

    if(!NT_SUCCESS (status)){
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Error creating read queue - 0x%x", status));
        return status;
    }


    //
    // One more queue...We need a place to put the priority receive 
    //  requests that we get from the parallel queue.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig,
                             WdfIoQueueDispatchManual);

    ioQueueConfig.EvtIoStop = SmscIrEvtIoQueueStop;

    status = WdfIoQueueCreate(
                            device,
                            &ioQueueConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &deviceData->PriorityReceiver.PendingReceiveQueue);

    if(!NT_SUCCESS (status)){
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Error creating priority queue - 0x%x", 
                status));
        return status;
    }

    //
    // Register a device interface. IRCLASS will be notified of our
    //  presence when WDF enables the interface and will then create
    //  a HID PDO for our device.
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                            (LPGUID)&GUID_DEVINTERFACE_IRPORT,
                                            NULL);

    if (!NT_SUCCESS(status)) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: WdfDeviceCreateDeviceInterface "\
             "failed - 0x%x", status));

        return status;
    }

    //
    // Setup the wake key
    //
    SmscIrSetWakeKeyInfo(deviceData);

    SmscIrTracePrint(
            TRACE_LEVEL_VERBOSE,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtDeviceAdd: Exit"));

    return STATUS_SUCCESS;
}

VOID
SmscIrEvtIoQueueStop(
    IN WDFQUEUE Queue,
    IN WDFREQUEST Request,
    IN ULONG  ActionFlags
    ) {
/*++
Routine Description.

  This routine is called when a queue of ours needs to 
  pause, notably due to power down.

Arguments:

  Queue   - The WDFQUEUE that is stopping

  Request - We're called here multiple times, once 
            for each request on the queue. This is one
            such request

  ActionFlags - More detailed info about the stop.
  
--*/

    PSMSCIR_DATA  deviceData;
    KIRQL         oldIrql;

    SmscIrTracePrint(
            TRACE_LEVEL_VERBOSE,
            SMSCDBG_PNP_INFO,
            ("SmscIrEvtIoQueueStop: Stopping request 0x%p - 0x%x", 
                Request, ActionFlags));

    deviceData = (PSMSCIR_DATA)GetIrData(WdfIoQueueGetDevice(Queue));

    KeAcquireSpinLock(&deviceData->Receiver.ListSpinLock, &oldIrql);

    if (deviceData->Receiver.CurrentIrReceiveRequest == Request) {

        //
        // Do not requeue the request, just ACK and leave it where it is
        //
        WdfRequestStopAcknowledge(Request, FALSE);

    }
   
    KeReleaseSpinLock(&deviceData->Receiver.ListSpinLock, oldIrql);

    KeAcquireSpinLock(&deviceData->PriorityReceiver.ListSpinLock, &oldIrql);

    if (deviceData->PriorityReceiver.CurrentIrReceiveRequest == Request) {

        //
        // Do not requeue the request, just ACK and leave it where it is
        //
        WdfRequestStopAcknowledge(Request, FALSE);

    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -