标签:
上篇《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)
NTSTATUS
DriverEntry(
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;
}
NTSTATUS
EvtDeviceAdd(
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;
}
NTSTATUS
EvtDevicePrepareHardware(
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;
}
VOID
EvtIoDeviceControl(
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;
}
标签:
原文地址:http://blog.csdn.net/xiaobin_hlj80/article/details/46561875