Windows 驱动开发 - 7
在《Windows 驱动开发 - 5》我们所说的读写操作在本篇实现。
在WDF中实现此功能主要为:EvtIoRead和EvtIoWrite。
首先,在EvtDeviceAdd设置以上两个回调事件。
ioQueueConfig.EvtIoRead = EvtIoRead;
ioQueueConfig.EvtIoWrite = EvtIoWrite;
然后。在EvtDevicePrepareHardware中获取WDFUSBPIPE并測试他。
pDeviceContext->BulkReadPipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
BULK_IN_ENDPOINT_INDEX,
NULL);// pipeInfo WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkReadPipe); pDeviceContext->BulkWritePipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
BULK_OUT_ENDPOINT_INDEX,
NULL);// pipeInfo
(1)获取WDFUSBPIPE
使用WdfUsbInterfaceGetConfiguredPipe方法。
WDFUSBPIPE WdfUsbInterfaceGetConfiguredPipe(
[in] WDFUSBINTERFACE UsbInterface,
[in] UCHAR PipeIndex,
[out, optional] PWDF_USB_PIPE_INFORMATION PipeInfo
);
(2) 測试WDFUSBPIPE
使用WdfUsbTargetPipeSetNoMaximumPacketSizeCheck方法.
VOID WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(
[in] WDFUSBPIPE Pipe
);
最后,实现以上两个回调事件和他们的完毕例程。
1. 获得传输缓存
读:WdfRequestRetrieveOutputMemory
NTSTATUS WdfRequestRetrieveOutputMemory(
[in] WDFREQUEST Request,
[out] WDFMEMORY *Memory
);
写:WdfRequestRetrieveInputMemory
NTSTATUS WdfRequestRetrieveInputMemory(
[in] WDFREQUEST Request,
[out] WDFMEMORY *Memory
);
2. 格式化并发送一个请求对象到USB驱动程序堆栈
读:WdfUsbTargetPipeFormatRequestForRead
NTSTATUS WdfUsbTargetPipeFormatRequestForRead(
[in] WDFUSBPIPE Pipe,
[in] WDFREQUEST Request,
[in, optional] WDFMEMORY ReadMemory,
[in, optional] PWDFMEMORY_OFFSET ReadOffset
);
写:WdfUsbTargetPipeFormatRequestForWrite
NTSTATUS WdfUsbTargetPipeFormatRequestForWrite(
[in] WDFUSBPIPE Pipe,
[in] WDFREQUEST Request,
[in, optional] WDFMEMORY WriteMemory,
[in, optional] PWDFMEMORY_OFFSET WriteOffset
);
3. 对请求实现一个完毕例程
(1)
设置完毕例程
使用WdfRequestSetCompletionRoutine方法。
VOID WdfRequestSetCompletionRoutine(
[in] WDFREQUEST Request,
[in, optional] PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine,
[in, optional] WDFCONTEXT CompletionContext
);
(2)完毕例程
1).检查请求状态
status = CompletionParams->IoStatus.Status;
2). 检查传输的字节数
读完:
bytesRead = usbCompletionParams->Parameters.PipeRead.Length;
写完:
bytesWritten = usbCompletionParams->Parameters.PipeWrite.Length;
3). 检查USBD状态
首先。赋值
usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
最后,获取
usbCompletionParams->UsbdStatus;
注:
读:EvtIoRead
写:EvtIoWrite
读完:EvtRequestReadCompletionRoutine
写完:EvtRequestWriteCompletionRoutine
附:
step4.c
/*++ Step4: This steps shows:
1) How to register Read and Write events on the default queue.
2) Retrieve memory from read and write request, format the
requests and send it to USB target.
--*/ #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 BULK_OUT_ENDPOINT_INDEX 1
#define BULK_IN_ENDPOINT_INDEX 2
#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;
WDFUSBPIPE BulkReadPipe;
WDFUSBPIPE BulkWritePipe;
} 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 Step4\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;
ioQueueConfig.EvtIoRead = EvtIoRead;
ioQueueConfig.EvtIoWrite = EvtIoWrite; 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; pDeviceContext->BulkReadPipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
BULK_IN_ENDPOINT_INDEX,
NULL);// pipeInfo WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkReadPipe); pDeviceContext->BulkWritePipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
BULK_OUT_ENDPOINT_INDEX,
NULL);// pipeInfo WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkWritePipe); 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;
} VOID
EvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
WDFUSBPIPE pipe;
NTSTATUS status;
WDFMEMORY reqMemory;
PDEVICE_CONTEXT pDeviceContext;
BOOLEAN ret; UNREFERENCED_PARAMETER(Length); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
if(!NT_SUCCESS(status)){
goto Exit;
} status = WdfUsbTargetPipeFormatRequestForRead(pipe,
Request,
reqMemory,
NULL // Offsets
);
if (!NT_SUCCESS(status)) {
goto Exit;
} WdfRequestSetCompletionRoutine(Request,
EvtRequestReadCompletionRoutine,
pipe);
ret = WdfRequestSend(Request,
WdfUsbTargetPipeGetIoTarget(pipe),
WDF_NO_SEND_OPTIONS); if (ret == FALSE) {
status = WdfRequestGetStatus(Request);
goto Exit;
} else {
return;
} Exit:
WdfRequestCompleteWithInformation(Request, status, 0); return;
} VOID
EvtRequestReadCompletionRoutine(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
NTSTATUS status;
size_t bytesRead = 0;
PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Context); status = CompletionParams->IoStatus.Status; usbCompletionParams = CompletionParams->Parameters.Usb.Completion; bytesRead = usbCompletionParams->Parameters.PipeRead.Length; if (NT_SUCCESS(status)){
KdPrint(("Number of bytes read: %I64d\n", (INT64)bytesRead));
} else {
KdPrint(("Read failed - request status 0x%x UsbdStatus 0x%x\n",
status, usbCompletionParams->UsbdStatus)); } WdfRequestCompleteWithInformation(Request, status, bytesRead); return;
} VOID
EvtIoWrite(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
NTSTATUS status;
WDFUSBPIPE pipe;
WDFMEMORY reqMemory;
PDEVICE_CONTEXT pDeviceContext;
BOOLEAN ret; UNREFERENCED_PARAMETER(Length); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkWritePipe; status = WdfRequestRetrieveInputMemory(Request, &reqMemory);
if(!NT_SUCCESS(status)){
goto Exit;
} status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
Request,
reqMemory,
NULL); // Offset
if (!NT_SUCCESS(status)) {
goto Exit;
} WdfRequestSetCompletionRoutine(
Request,
EvtRequestWriteCompletionRoutine,
pipe);
ret = WdfRequestSend(Request,
WdfUsbTargetPipeGetIoTarget(pipe),
WDF_NO_SEND_OPTIONS);
if (ret == FALSE) {
status = WdfRequestGetStatus(Request);
goto Exit;
} else {
return;
} Exit:
WdfRequestCompleteWithInformation(Request, status, 0); return;
} VOID
EvtRequestWriteCompletionRoutine(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
NTSTATUS status;
size_t bytesWritten = 0;
PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Context); status = CompletionParams->IoStatus.Status; usbCompletionParams = CompletionParams->Parameters.Usb.Completion; bytesWritten = usbCompletionParams->Parameters.PipeWrite.Length; if (NT_SUCCESS(status)){
KdPrint(("Number of bytes written: %I64d\n", (INT64)bytesWritten));
} else {
KdPrint(("Write failed: request Status 0x%x UsbdStatus 0x%x\n",
status, usbCompletionParams->UsbdStatus));
} WdfRequestCompleteWithInformation(Request, status, bytesWritten); return;
}
參考文章:
1. 《Working with USB Pipes》
2. 《How to send USB bulk transfer requests》
Windows 驱动开发 - 7的更多相关文章
- Windows驱动开发(中间层)
Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...
- [Windows驱动开发](一)序言
笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓——内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...
- windows驱动开发推荐书籍
[作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...
- Windows 驱动开发 - 5
上篇<Windows 驱动开发 - 4>我们已经完毕了硬件准备. 可是我们还没有详细的数据操作,比如接收读写操作. 在WDF中进行此类操作前须要进行设备的IO控制,已保持数据的完整性. 我 ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- Windows驱动——读书笔记《Windows驱动开发技术详解》
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- Windows 驱动开发 - 8
最后的一点开发工作:跟踪驱动. 一.驱动跟踪 1. 包括TMH头文件 #include "step5.tmh" 2. 初始化跟踪 在DriverEntry中初始化. WPP_INI ...
- Windows驱动开发-IRP的完成例程
<Windows驱动开发技术详解 >331页, 在将IRP发送给底层驱动或其他驱动之前,可以对IRP设置一个完成例程,一旦底层驱动将IRP完成后,IRP完成例程立刻被处罚,通过设置完成例程 ...
- C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载
基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...
随机推荐
- IDEA常见问题
IDEA常见问提解决 一:拉取git代码认证失败(无法重新输入账户和密码) git config --system --unset credential.helper 二:取消新建文件自动添加到S ...
- TX-LCN事务控制原理
TX-LCN由两大模块组成, TxClient.TxManager,TxClient作为模块的依赖框架,提供TX-LCN的标准支持,TxManager作为分布式事务的控制方.事务发起方或者参与方都由T ...
- hdfs深入:03、hdfs的架构以及副本机制和block块存储
HDFS分布式文件系统设计目标 1. 硬件错误 由于集群很多时候由数量众多的廉价机组成,使得硬件错误成为常态 2. 数据流访问 所有应用以流的方式访问数 ...
- Oracle learning note
oracle SQL select 'para1' || 'para2' as "para" must "" from table t where c.name ...
- scrollfix.js插件:滚动固定在某个位置
插件文件在/文件 scrollfix.js 用法: var fix = $(".fix"), fixtop = $(".fix-top"), fixStartT ...
- BZOJ 4519 不同的最小割 最小割树
题面: 把每两个点当成源汇,求N*(N-1)个最小割中不同的有多少个 N<=850 分析: 有这样一个结论:一张无向图不同的最小割最多有n-1个. 那么我们一定可以建出一棵树,使得这棵树中每两个 ...
- KBE_运作流程
图片来自官方手册:Switch Fabric:交换机网络,根据网络环境的不同而不同,根据用户自己的情况进行配置,不属于引擎范畴. 运作流程 Client连接Loginapp通过API连接,如下示例: ...
- PHP 获取LDAP服务器Schema数据
最近工作中一直在与LDAP打交道,在官方推荐的client-apis里,可以很容易找到每个语言对应的API,进而与LDAP服务器交互.但是在用ApacheDirectoryStudio时,这个软件竟然 ...
- jQuery对table排序
<script> //col对应列,cmp两数比较方法,返回值为TRUE,FALSE function sort(col, cmp) { var table = $("#test ...
- 集训第四周(高效算法设计)F题 (二分+贪心)
Description A set of n<tex2html_verbatim_mark> 1-dimensional items have to be packed in iden ...