| |
|
开发:
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例程需要完成以下这些功能:
在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; } 此例程主要做了下面几件重要的事情:
在PnP的管理例程注册部分,可以看到几个典型的回调,即PrepareHardware,ReleaseHardware,DeviceEntry以及DeviceExit。 PrepareHardware以及ReleaseHardware关系着你的硬件是否可以获得Windows分配的资源,而在PrepareHardware里面,你需要去实现内存资源,内存地址映射,IO端口映射以及CPU中断资源的分配等等。 在WDF中,给硬件分配资源的大致流程如下:
WDF的很多Sample之前在微软的msdn?sample里面都有,包含了各种各样的硬件设备驱动,过滤驱动,枚举驱动等等,可惜不知道为什么被微软下架了。。。不过好在万能的百度上还是能找得到的,不过这里面的sample都没有去实现具体的功能,只是阐述了一个个驱动开发的模型,虽然代码量很小,但这已经是我们能看到的最好的例子了,熟悉了之后,自己去具体开发符合你需求的功能驱动就不那么困难。 后面的话,因为这几年做的很多实际的驱动,会不定期写一些笔记,当然,不在仅限于小端口驱动了~ |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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年12日历 | -2024/12/23 4:34:41- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |