IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> Windows驱动开发(三)一个WDF入门实例 -> 正文阅读

[开发工具]Windows驱动开发(三)一个WDF入门实例

上一章大概介绍了WDM/WDF的IOControl,

链接:https://blog.csdn.net/o0xwh_93150o/article/details/104234021

鸽太久了,刚好闲下来,就把这个实例入门篇给补了吧。话不多说,先上代码。

DriverEntry例程:

NTSTATUS

DriverEntry(

????IN PDRIVER_OBJECT ?DriverObject,

????IN PUNICODE_STRING RegistryPath) {

????WDF_DRIVER_CONFIG config;

????NTSTATUS status = STATUS_SUCCESS;

????WDF_OBJECT_ATTRIBUTES attributes;

????//

????// Initialize WPP Tracing

????//

????WPP_INIT_TRACING( DriverObject, RegistryPath );

????TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

????

????//

????// Register a cleanup callback so that we can call WPP_CLEANUP when

????// the framework driver object is deleted during driver unload.

????//

????WDF_OBJECT_ATTRIBUTES_INIT(&attributes);

????attributes.EvtCleanupCallback = Spw_PCIeEvtDriverContextCleanup;

????WDF_DRIVER_CONFIG_INIT(&config, Spw_PCIeEvtDeviceAdd);

????status = WdfDriverCreate(DriverObject,

?????????????????????????????RegistryPath,

?????????????????????????????&attributes,

?????????????????????????????&config,

?????????????????????????????WDF_NO_HANDLE);

????if (!NT_SUCCESS(status)) {

????????TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);

????????WPP_CLEANUP(DriverObject);

????????return status;

????}

??

????TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

????return status;

}

每一个WDF驱动必须有一个DriverEntry例程,当操作系统监测到有硬件设备插入时,就会找到对应的DriverEntry例程,DriverEntry例程需要完成以下这些功能:

  1. 注册WDF的DeviceAdd回调函数,这是WDF驱动与NT驱动最大的不同之一
  2. 创建一个驱动对象,用于向框架注册我们的驱动程序

在WDF中,真正被我们当作初始化的函数,变成了DeviceAdd,所以可以把相关的初始化行为全部丢在DeviceAdd中。

DeviceAdd例程:

NTSTATUS

Spw_PCIeEvtDeviceAdd(_In_ ???WDFDRIVER ??????Driver,

?????????????????????_Inout_ PWDFDEVICE_INIT DeviceInit) {

????NTSTATUS status = STATUS_SUCCESS;

????WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;

????WDF_OBJECT_ATTRIBUTES ??deviceAttributes;

????WDFDEVICE device;

????PDEVICE_CONTEXT deviceContext;

????WDFQUEUE queue;

????WDF_IO_QUEUE_CONFIG ???queueConfig;

????UNREFERENCED_PARAMETER(Driver);

????PAGED_CODE();

????WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

????//When the I/O manager sends a request for buffered I/O, the IRP contains an internal copy of the caller's buffer

????//rather than the caller's buffer itself. The I/O manager copies data from the caller's buffer to the internal buffer

????//during a write request or from the internal buffer to the caller's buffer when the driver completes a read

????//request.

????//The WDF driver receives a WDF request object, which in turn contains an embedded WDF memory object.

????//The memory object contains the address of the buffer on which the driver should operate.

????

????//初始化即插即用和电源管理例程配置结构

????WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

????//设置即插即用基本例程

????pnpPowerCallbacks.EvtDevicePrepareHardware = Spw_PCIeEvtDevicePrepareHardware;

????pnpPowerCallbacks.EvtDeviceReleaseHardware = Spw_PCIeEvtDeviceReleaseHardware;

????pnpPowerCallbacks.EvtDeviceD0Entry = Spw_PCIeEvtDeviceD0Entry;

????pnpPowerCallbacks.EvtDeviceD0Exit = Spw_PCIeEvtDeviceD0Exit;

????//注册即插即用和电源管理例程

????WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

????

????WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

????//deviceAttributes.EvtCleanupCallback = Spw_PCIeEvtDriverContextCleanup;

????//

????// Set WDFDEVICE synchronization scope. By opting for device level

????// synchronization scope, all the queue and timer callbacks are

????// synchronized with the device-level spinlock.

????//

????deviceAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;

????status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

????if (!NT_SUCCESS(status)) {

????????return status;

????}

????deviceContext = GetDeviceContext(device);

????//用default初始化default 队列,用另一个初始化非default队列

????WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,

?????????????????????????????WdfIoQueueDispatchSequential);

????queueConfig.EvtIoDeviceControl = Spw_PCIeEvtIoDeviceControl;

????status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);

????if (!NT_SUCCESS(status)) { ???

????????return status;

????}

????//非默认队列,必须指定要分发的I/O请求类型

????//The WdfDeviceConfigureRequestDispatching method causes the framework to queue a specified type of I/O requests to a specified I/O queue.

????status = WdfDeviceConfigureRequestDispatching(device,

??????????????????????????????????????????????????queue,

??????????????????????????????????????????????????WdfRequestTypeDeviceControl);

????if (!NT_SUCCESS(status)) {

????????return status;

????}

????//创建驱动程序接口与应用程序通信

????status = WdfDeviceCreateDeviceInterface(device,

????????????????????????????????????????????(LPGUID)&GUID_DEVINTERFACE_Spw_PCIe,

????????????????????????????????????????????NULL // ReferenceString);

????if (!NT_SUCCESS(status)) {

????????return status;

????}

????return status;

}

此例程主要做了下面几件重要的事情:

  1. 创建初始化设备对象及其上下文
  2. 若该WDF驱动为支持PnP的,则要注册PnP相关的一系列回调函数
  3. 若该驱动需要处理IO,则需要配置一个消息队列,注册处理例程以及制定IO请求类型等等
  4. 若该驱动需要与其他程序进行交互,则可以注册一个GUID接口用于通信,当然,也可以使用符号链接的形式。

在PnP的管理例程注册部分,可以看到几个典型的回调,即PrepareHardware,ReleaseHardware,DeviceEntry以及DeviceExit。

PrepareHardware以及ReleaseHardware关系着你的硬件是否可以获得Windows分配的资源,而在PrepareHardware里面,你需要去实现内存资源,内存地址映射,IO端口映射以及CPU中断资源的分配等等。

在WDF中,给硬件分配资源的大致流程如下:

  1. 当插入一个PnP设备时,总线枚举驱动识别该设备
  2. 调用总线驱动的DeviceResourceQuery,创建资源列表
  3. 调用总线驱动的DeviceResourceRequirementQuery,创建资源需求列表
  4. 由PnP管理器来匹配驱动,随后申请必要的资源,将信息发送给驱动程序
  5. 当你的设备最终进入工作预备状态时,前面写的PrepareHardware即生效
  6. 之后进入到DeviceEntry例程,通常,DeviceEntry例程并需要额外处理事务

WDF的很多Sample之前在微软的msdn?sample里面都有,包含了各种各样的硬件设备驱动,过滤驱动,枚举驱动等等,可惜不知道为什么被微软下架了。。。不过好在万能的百度上还是能找得到的,不过这里面的sample都没有去实现具体的功能,只是阐述了一个个驱动开发的模型,虽然代码量很小,但这已经是我们能看到的最好的例子了,熟悉了之后,自己去具体开发符合你需求的功能驱动就不那么困难。

后面的话,因为这几年做的很多实际的驱动,会不定期写一些笔记,当然,不在仅限于小端口驱动了~

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 11:03:42  更:2021-09-10 11:06:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:33:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码