Windows 驱动开发 - 6

来源:互联网 发布:笔记本安装linux 编辑:程序博客网 时间:2024/06/06 20:20

    上篇《Windows 驱动开发 - 5》我们设置了回调事件EvtIoDeviceControl,我们在此篇来实现他。

    我们知道在进行读写之前我们要进行一定约定,比如同步。

    在WDF中控制同步约定的方法为:WdfUsbTargetDeviceSendControlTransferSynchronously

NTSTATUS WdfUsbTargetDeviceSendControlTransferSynchronously(  [in]            WDFUSBDEVICE                  UsbDevice,  [in, optional]  WDFREQUEST                    Request,  [in, optional]  PWDF_REQUEST_SEND_OPTIONS     RequestOptions,  [in]            PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,  [in, optional]  PWDF_MEMORY_DESCRIPTOR        MemoryDescriptor,  [out, optional] PULONG                        BytesTransferred);
    (1) 选项请求

          对WDF_REQUEST_SEND_OPTIONS结构的设置。

typedef struct _WDF_REQUEST_SEND_OPTIONS {  ULONG    Size;  ULONG    Flags;  LONGLONG Timeout;} WDF_REQUEST_SEND_OPTIONS, *PWDF_REQUEST_SEND_OPTIONS;
        1). 初始化

            使用WDF_REQUEST_SEND_OPTIONS_INIT方法进行初始化.

VOID WDF_REQUEST_SEND_OPTIONS_INIT(  _Out_ PWDF_REQUEST_SEND_OPTIONS Options,  _In_  ULONG                     Flags);

        2). 设置超时
            使用WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT方法进行超时设置。

VOID WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(  _Inout_ PWDF_REQUEST_SEND_OPTIONS Options,  _In_    LONGLONG                  Timeout);

    (2) 包设置

          使用WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR方法进行包设置。

VOID WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(  _Out_ PWDF_USB_CONTROL_SETUP_PACKET Packet,  _In_  WDF_USB_BMREQUEST_DIRECTION   Direction,  _In_  WDF_USB_BMREQUEST_RECIPIENT   Recipient,  _In_  BYTE                          Request,  _In_  USHORT                        Value,  _In_  USHORT                        Index);

    (3) 内存描述

        1). 内存请求

             使用WdfRequestRetrieveInputMemory方法进行请求。

NTSTATUS WdfRequestRetrieveInputMemory(  [in]  WDFREQUEST Request,  [out] WDFMEMORY  *Memory);

        2). 初始化内存句柄

             使用WDF_MEMORY_DESCRIPTOR_INIT_HANDLE方法进行内存句柄的初始化。

VOID WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(  _Out_    PWDF_MEMORY_DESCRIPTOR Descriptor,  _In_     WDFMEMORY              Memory,  _In_opt_ PWDFMEMORY_OFFSET      Offsets);

代码:

step3.c

/*++Step3: This steps shows:       1) How to create a default parallel queue to receive a IOCTL requests to           set bar graph display.       2) How to retreive memory handle from the requests and use that to send          a vendor command to the USB device.--*/#include "ntddk.h"#include "wdf.h"#include "prototypes.h"#pragma warning(disable:4200)  // suppress nameless struct/union warning#pragma warning(disable:4201)  // suppress nameless struct/union warning#pragma warning(disable:4214)  // suppress bit field types other than int warning#include "usbdi.h"#pragma warning(default:4200)#pragma warning(default:4201)#pragma warning(default:4214)#include "wdfusb.h"#include "initguid.h"DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, // Generated using guidgen.exe   0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}#define IOCTL_INDEX                     0x800#define FILE_DEVICE_OSRUSBFX2          0x65500#define USBFX2LK_SET_BARGRAPH_DISPLAY 0xD8#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,\                                                    IOCTL_INDEX + 5, \                                                    METHOD_BUFFERED, \                                                    FILE_WRITE_ACCESS)typedef struct _DEVICE_CONTEXT {  WDFUSBDEVICE      UsbDevice;  WDFUSBINTERFACE   UsbInterface;} DEVICE_CONTEXT, *PDEVICE_CONTEXT;WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)NTSTATUSDriverEntry(    IN PDRIVER_OBJECT  DriverObject,    IN PUNICODE_STRING RegistryPath    ){    WDF_DRIVER_CONFIG       config;    NTSTATUS                status;    KdPrint(("DriverEntry of Step3\n"));    WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd);    status = WdfDriverCreate(DriverObject,                        RegistryPath,                        WDF_NO_OBJECT_ATTRIBUTES,                         &config,                             WDF_NO_HANDLE                         );    if (!NT_SUCCESS(status)) {        KdPrint(("WdfDriverCreate failed 0x%x\n", status));    }    return status;}NTSTATUSEvtDeviceAdd(    IN WDFDRIVER        Driver,    IN PWDFDEVICE_INIT  DeviceInit    ){    WDF_OBJECT_ATTRIBUTES               attributes;    NTSTATUS                            status;    WDFDEVICE                           device;    PDEVICE_CONTEXT                     pDevContext;    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;        UNREFERENCED_PARAMETER(Driver);    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);    pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);    if (!NT_SUCCESS(status)) {        KdPrint(("WdfDeviceCreate failed 0x%x\n", status));        return status;    }    pDevContext = GetDeviceContext(device);    status = WdfDeviceCreateDeviceInterface(device,                                (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,                                NULL);// Reference String    if (!NT_SUCCESS(status)) {        KdPrint(("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));        return status;    }    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,                                    WdfIoQueueDispatchParallel);    ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;    status = WdfIoQueueCreate(device,                         &ioQueueConfig,                         WDF_NO_OBJECT_ATTRIBUTES,                         WDF_NO_HANDLE);    if (!NT_SUCCESS(status)) {        KdPrint(("WdfIoQueueCreate failed  %!STATUS!\n", status));        return status;    }    return status;}NTSTATUSEvtDevicePrepareHardware(    IN WDFDEVICE    Device,    IN WDFCMRESLIST ResourceList,    IN WDFCMRESLIST ResourceListTranslated    ){    NTSTATUS                            status;    PDEVICE_CONTEXT                     pDeviceContext;    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;     UNREFERENCED_PARAMETER(ResourceList);    UNREFERENCED_PARAMETER(ResourceListTranslated);    pDeviceContext = GetDeviceContext(Device);    //    // Create the USB device if it is not already created.    //    if (pDeviceContext->UsbDevice == NULL) {        status = WdfUsbTargetDeviceCreate(Device,                                    WDF_NO_OBJECT_ATTRIBUTES,                                    &pDeviceContext->UsbDevice);        if (!NT_SUCCESS(status)) {            KdPrint(("WdfUsbTargetDeviceCreate failed 0x%x\n", status));                    return status;        }    }    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);    status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,                                        WDF_NO_OBJECT_ATTRIBUTES,                                        &configParams);    if(!NT_SUCCESS(status)) {        KdPrint(("WdfUsbTargetDeviceSelectConfig failed 0x%x\n", status));        return status;    }    pDeviceContext->UsbInterface =                  configParams.Types.SingleInterface.ConfiguredUsbInterface;            return status;}VOIDEvtIoDeviceControl(    IN WDFQUEUE   Queue,    IN WDFREQUEST Request,    IN size_t     OutputBufferLength,    IN size_t     InputBufferLength,    IN ULONG      IoControlCode        ){    WDFDEVICE                           device;    PDEVICE_CONTEXT                     pDevContext;    size_t                              bytesTransferred = 0;    NTSTATUS                            status;    WDF_USB_CONTROL_SETUP_PACKET        controlSetupPacket;    WDF_MEMORY_DESCRIPTOR               memDesc;    WDFMEMORY                           memory;    WDF_REQUEST_SEND_OPTIONS            sendOptions;         UNREFERENCED_PARAMETER(InputBufferLength);    UNREFERENCED_PARAMETER(OutputBufferLength);        device = WdfIoQueueGetDevice(Queue);    pDevContext = GetDeviceContext(device);    switch(IoControlCode) {    case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:        if(InputBufferLength < sizeof(UCHAR)) {            status = STATUS_BUFFER_OVERFLOW;            bytesTransferred = sizeof(UCHAR);            break;        }         status = WdfRequestRetrieveInputMemory(Request, &memory);        if (!NT_SUCCESS(status)) {            KdPrint(("WdfRequestRetrieveMemory failed 0x%x", status));            break;        }        WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,                                        BmRequestHostToDevice,                                        BmRequestToDevice,                                        USBFX2LK_SET_BARGRAPH_DISPLAY, // Request                                        0, // Value                                        0); // Index                                                                WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, memory, NULL);       //       // Send the I/O with a timeout to avoid hanging the calling        // thread indefinitely.       //        WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions,                                  WDF_REQUEST_SEND_OPTION_TIMEOUT);        WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions,                                         WDF_REL_TIMEOUT_IN_MS(100));        status = WdfUsbTargetDeviceSendControlTransferSynchronously(                                        pDevContext->UsbDevice,                                         NULL, // Optional WDFREQUEST                                        &sendOptions, // PWDF_REQUEST_SEND_OPTIONS                                        &controlSetupPacket,                                        &memDesc,                                        (PULONG)&bytesTransferred);        if (!NT_SUCCESS(status)) {            KdPrint(("SendControlTransfer failed 0x%x", status));            break;        }        break;    default:        status = STATUS_INVALID_DEVICE_REQUEST;        break;    }    WdfRequestCompleteWithInformation(Request, status, bytesTransferred);    return;}

0 0
原创粉丝点击