第三篇.WDF驱动之Helloworld

2023-11-01

  借助Microsoft提供的kmdf框架,来理解一下驱动的一般流程.



驱动的开发流程

 

1 驱动程序入口函数

DriverEntry  驱动程序的入口函数。   类似于 main函数

程序的标准入口函数是DriverEntry

与WDM不同,WDF的DriverEntry只负责创建和初始化WDFDRIVER对象,告诉WDF框架处理添加新设备连接的回调函数。

NTSTATUS  DriverEntry(PDRIVER-OBJECT DriverObj,PUNICODE-STRING  RegistryPath)

{

NTSTATUSstatus;

WDF-DRIVER-CONFIGconfig;

WDFDRIVER hDriver;

//初始化驱动配置结构,指定设备添加事件callback

WDF-DRIVER-CONFIG-INIT-NO-CONSTRAINTS(&config,MyEvtDeviceAdd);

//创建WDFDRIVER对象

status=WdfDriverCreate(DriverObj, RegistryPath,WDF-NO-OBJECT-ATTRIBUTES,

&config,//指向config结构的指针

NULL

);

return(status);

}

每当有新设备连接到系统时,WDF框架自动调用

EvtDeviceAdd设备添加callback。该回调函数初始化PNP和电源管理相关结构,设置相应的事件处理callbacks,然后创建WDFDEVICE对象和符号连接,初始化请求队列、中断处理等相关结构,设置相应的回调函数。

WDFSTATUSMyEvtDeviceAdd(WDFDRIVER Driver,PWDFDEVICE-INITDeviceInit)

{

WDFSTATUSstatus=STATUS-SUCCESS;

WDF-PNPPOWER-EVENT-CALLBACKS   pnpPowerCallbacks;

WDF-OBJECT-ATTRIBUTES   objAttributes;

WDFDEVICEdevice;

PMY-DEVICE-CONTEXTdevContext;

WDF-IO-QUEUE-CONFIGioCallbacks;

WDF-INTERRUPT-CONFIG    interruptConfig;

//初始化PnPPowerCallbacks,设置与PnP和电源管理相关

的事件回调函数

WDF-PNPPOWER-EVENT-CALLBACKS-INIT(&pnpPowerCallbacks);

pnpPowerCallbacks.EvtDevicePrepareHardware=MyEvtPrepareHardware;

pnpPowerCallbacks.EvtDeviceReleaseHardware=MyEvtReleaseHardware;

pnpPowerCallbacks.EvtDeviceD0Entry=MyEvtDeviceD0Entry;

pnpPowerCallbacks.EvtDeviceD0Exit=MyEvtDeviceD0Exit;

WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,pnpPowerCallbacks);

//创建设备对象,初始化相关的属性

WDF-OBJECT-ATTRIBUTES-INIT(&objAttributes);

WDF-OBJECT-ATTRIBUTES-SET-CONTEXT-TYPE(&objAttributes,MY-DEVICE-CONTEXT);

//命名设备

status=WdfDeviceInitUpdateName(DeviceInit,L“\\de2vice\\WDFDEMO”)

;if(!NT-SUCCESS(status))return(status);

status=WdfDeviceCreate(&DeviceInit,&objAttributes,&device);

if(!NT-SUCCESS(status))return(status);

devContext=MyGetContextFromDevice(device);

 devContext->WdfDevice=device;

//创建符号连接

status=WdfDeviceCreateSymbolicLink(device,L“\\Dos2Devices\\WDFDEMO”);

if(!NT-SUCCESS(status))

return(status);//创建和初始化请求队列

WDF-IO-QUEUE-CONFIG-INIT(&ioCallbacks,WdfIo2QueueDispatchSerial,WDF-NO-EVENT-CALLBACK,WDF-NO-EVENT-CALLBACK);

ioCallbacks.EvtIoDeviceControl=MyEvtDeviceControlIoctl;

status=WdfDeviceCreateDefaultQueue(device,&ioCallbacks,WDF-NO-OBJECT-ATTRIBUTES,NULL);

if(!NT-SUCCESS(status))return(status);

//创建和初始化中断对象,MyIsr和MyDpc分别是中断服务例程和DPC例程

WDF-INTERRUPT-CONFIG-INIT(&interruptConfig,FALSE,MyIsr,MyDpc);

interruptConfig.EvtInterruptEnable=MyEvtInterruptEnable;//中断使能

interruptConfig.EvtInterruptDisable=MyEvtInterruptDisable;//中断禁止

status=WdfInterruptCreate(device,&interruptConfig,&objAttributes,&devContext->WdfInterrupt);

//一些其他初始化操作(略)

return(status);}

开发WDF驱动程序下一步的工作就是编写各事件处理回调函数,当相应事件发生时,WDF框架会自动调用指定的回调函数进行处理。其中EvtDevicePrepareHardware回调函数在分配资源的时候被调用,框架将分配给设备的资源传递给回调函数,回调函数保存需要的资源,将共享内存映射到内核虚拟地址空间。与此对应的是EvtDeviceReleaseHardware回调函数,每当设备释放所占用的资源时,框架都将调用它。

EvtDeviceD0Entry和EvtDeviceD0Exit事件callbacks则分别在设备即将进入和离开D0电源状态时调用。EvtIoDeviceControl,EvtIoRead,EvtIoWrite等回调函数分别用来处理DeviceControl,Read,WriteI/O请求。当框架获得一个I/O请求时,它首先确定该请求应该放入哪个请求队列。如果驱动程序没有提供指定的队列,WDF框架默认将请求放入缺省请求队列会自动调用对应的回调函数。然后,框架寻找处理该请求的回调函数,如果驱动程序提供了相应的callback,则调用它处理请求。对于没有指定回调函数的I/O请求,WDF调用EvtIoStart回调函数处理。如果EvtIoStartcallback也不存在,框架将返回STATUS-NOT-SUPPORTED。

设备中断的管理由EvtInterruptEnablecallback、EvtInterruptDisablecallback、中断服务例程(ISR)和DpcForISr例程实现。WDF框架在调用EvtDeviceD0Entrycallback和注册ISR后,通过调用EvtInterruptEnable回调函数使能设备中断;而EvtInterruptDisable回调函数则在设备离开D0状态,EvtDeviceD0Exitcallback调用前获得调用,完成禁止设备中断的工作。此外,中断服务例程和DpcForIsr例程具体完成中断服务的功能,与WDM驱动程序相似。

 

2 创建驱动对象

WdfDriverCreate根据给定的属性配置创建driver对象.特别注意是  这里设置了SampleDriverEvtDeviceAdd函数,也就是创建driver时,会调用的 用于添加设备对象的方法。

 

3 创建设备对象

SampleDriverEvtDeviceAdd //这个是wdfDriverCreate时自己指定的

在 SampleDriverEvtDeviceAdd函数中通过调用WdfDeviceCreate函数,根据配置的属性创建对应的设备

 

4 创建设备接口

WdfDeviceCreateDeviceInterface创建一个唯一的接口(UUID)用于应用层程序通信,调用驱动层接口。

 

5 创建驱动处理队列

SampleDriverQueueInitialize

The I/O dispatchcallbacks for the frameworks device object

     are configured in this function.

     A single default I/O Queue is configuredfor parallel request

     processing, and a driver context memoryallocation is created

     to hold our structureQUEUE_CONTEXT.

 

       WdfIoQueueCreate创建一个事件队列用于处理驱动 I/O事件。需要注意的是,创建时

可以通过配置回调函数,来处理自己关心的那些事件。另外注意配置队列的分发方式:WdfIoQueueDispatchParallel

 

6 处理驱动的事件

SampleDriverEvtIoDeviceControl函数是在配置队列时设置的 用于处理IO控制的回调函数。大部分设备接口都是在这个函数中完成的。

 

7 驱动的卸载回调

驱动的卸载时调用的函数是  在driver创建时设置的,如果没有需要 可以不设置的。

attributes.EvtCleanupCallback


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第三篇.WDF驱动之Helloworld 的相关文章

  • Linux·i2c驱动示例

    I2C 是很常用的一个串行通信接口 常用于连接各种外设 传感器等器件 一 Linux I2C 驱动框架 Linux 内核将 I2C 驱动分为两部分 I2C 总线驱动 I2C 总线驱动就是 SOC 的 I2C 控制器驱动 也叫做 I2C 适配
  • FPGA学习记录:第28章 VGA显示器驱动设计与验证

    硬件平台 Cyclone IV E EP4CE10F17C8 开发平台 Quartus II 64 Bit Version 13 0 1 Build 232 06 12 2013 SP 1 SJ Full Version 开发板 野火征途p
  • EDK II Module Writers Guide上

    一 EDK2简介 1 EDK2工作流 二 EDK2 Packages 1 Packages介绍 EDK2 Packages是一个容器 其中包含一组模块及模块的相关定义 每个Package是一个EDK2单元 整个Project的源代码可以被分
  • AutoSar标准下ADC的结果访问(Adc_ReadGroup与Adc_GetStreamLastPointer)的异同

    系列文章目录 等待更新中 文章目录 系列文章目录 前言 1 什么是ADC的结果访问 2 ADC访问模式 3 AUTOSAR标准配置案例分析 3 1 Configuration 3 2 图形展示结果指针初始化 3 3 使用Adc GetStr
  • 内核hwmon驱动框架详解以及海思芯片温度驱动分析

    1 hwmon驱动框架介绍 hwmon即hardware monitoring framework 硬件监视框架 可以把温度传感器 风扇 电源管理等设备的驱动都利用hwmon框架去实现 在设备的归类上比较容易理解 2 hwmon驱动框架分析
  • 嵌入式linux驱动之路19:U-Boot 移植(2)

    uboot 的最终目的就是启动 Linux 内核 所以需要通过启动 Linux 内核来判断 uboot 移植是否成功 在启动 Linux 内核之前我们先来学习两个重要的环境变量 bootcmd 和 bootargs bootcmd 环境变量
  • 微星b560m mortar wifi 开机二检(开机灭了1秒后自动重启)

    微星b560m mortar wifi 开机二检 开机灭了1秒后自动重启 1 起因 为了照顾旧CPU 还想把内存扩容到64GB 就选择了DDR4的4条插槽的 B560M主板 都弄好之后 开机发现在按下电源键之后 通电自检后断电了大概2秒左右
  • Linux设备驱动的软件架构思想与设备驱动的基础内容总结

    Linux设备驱动的软件架构思想与设备驱动的基础内容总结 Linux是一个兼容性特别强的一个系统 而兼容性的实现与驱动强大的适应性密不可分 而这个具体的实现是离不开 总线bus和类class的管理方式 Linux使用bus统一的管理一系列相
  • Linux SPI 驱动实验

    目录 Linux 下SPI 驱动框架简介 SPI 主机驱动 SPI 设备驱动 SPI 设备和驱动匹配过程 I MX6U SPI 主机驱动分析 SPI 设备驱动编写流程 SPI 设备信息描述 SPI 设备数据收发处理流程 硬件原理图分析 试验
  • Linux 块设备驱动实验

    一 块设备驱动要远比字符设备驱动复杂得多 不同类型的存储设备又对应不同的驱动子系统 本章我们重点学习一下块设备相关驱动概念 不涉及到具体的存储设备 1 什么是块设备 块设备是针对存储设备的 比如 SD 卡 EMMC NAND Flash N
  • 异步通知实验(信号)

    目录 异步通知 异步通知简介 驱动中的信号处理 应用程序对异步通知的处理 硬件原理图分析 实验程序编写 修改设备树文件 程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 在前面使用阻塞或者非阻塞的方式来读取驱动中按键值
  • fb设备驱动1:fb设备的显像原理和步骤

    lcd的显像原理 将DDR内存的一部分划分出来作为显存 显存与lcd显示屏幕之间做一个双向的映射 然后用户只需要将需要显示的内容放入显存之中 然后显存中的内容就会刷新到lcd的储存器中进行显示 显存 在内核之中申请一块内存作为显存 由于内核
  • 3.gendisk结构体

    在Linux内核中 使用gendisk 通用磁盘 结构体来表示一个独立的磁盘设备 或分区 1 gendisk结构体 major first minor和minors共同表征了磁盘的主 次设备号 同一个磁盘的各个分区共享一个主设备号 而此设备
  • Linux 帧缓冲子系统详解:LCD介绍、framebuffer驱动框架、LCD驱动源码分析

    1 LCD显示屏基础知识介绍 请看博客 嵌入式开发 S5PV210 LCD显示器 2 内核帧缓冲子系统 2 1 功能介绍 1 帧缓冲 framebuffer 是 Linux 为显示设备提供的一个接口 它把显示设备描述成一个缓冲 区 允许应用
  • 一个主设备号是如何支持多个次设备?

    1 主次设备号 参考博客 字符设备驱动详解 主次设备号 注册 卸载字符设备驱动 创建设备节点 地址映射 2 次设备号介绍 1 在老的驱动程序里是不需要次设备号的 在老版内核中注册驱动用register chrdev 函数 只需要传入主设备号
  • <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动

    Linux开发 驱动开发 之 基于pinctrl gpio子系统的LED驱动 交叉编译环境搭建 Linux开发 linux开发工具 之 交叉编译环境搭建 uboot移植可参考以下 Linux开发 之 系统移植 uboot移植过程详细记录 第
  • inux字符驱动之read、write部分

    本期主题 linux字符驱动之read write部分 往期链接 linux设备驱动中的并发 linux设备驱动中的编译乱序和执行乱序 linux设备驱动之内核模块 linux字符驱动 linux字符驱动之ioctl部分 linux字符驱动
  • 嵌入式开发--SPI介绍和驱动开发

    目录 一 通信总线SPI介绍 二 SPI时序介绍和工作模式 三 基于stm32的spi初始化步骤 一 通信总线SPI介绍 SPI 全称为Serial Peripheral Interface 是一种同步的串行通信协议 SPI协议最初由Mot
  • LCD背光调节实验

    目录 LCD 背光调节简介 硬件原理分析 实验程序编写 编译下载验证 编写Makefile 和链接脚本 编译下载 不管是使用显示器还是手机 其屏幕背光都是可以调节的 通过调节背光就可以控制屏幕的亮度 在户外阳光强烈的时候可以通过调高背光来看
  • linux应用程序直接return与exit的区别

    在Linux应用程序中 可以使用 return 语句直接从 main 函数返回 这将导致程序终止并返回给操作系统 然而 有时候使用 exit 函数比直接使用 return 语句更有优势 以下是一些原因 清理资源 exit 函数可以确保在程序

随机推荐

  • cpu算力计算

    CPU的算力与CPU的核心的个数 核心的频率 核心单时钟周期的能力三个因素有关系 常用双精度浮点运算能力衡量CPU的科学计算的能力 就是处理64bit小数点浮动数据的能力 支持AVX2的处理器在1个核心1个时钟周期可以执行16次浮点运算 也
  • python selenium解决报错SessionNotCreatedException session not created: No matching capabilitie与问题解析

    解决方法 查看导包是否正确 如果是webdriver Chrome 那么导包的一切都要是chrome的 如果是webdriver Firefox 那么导入的包也都源于firefox的包 出现这个问题是因为由于selenium很多类都很相似
  • 怎么在springboot实现简单的登录操作关于拦截器中cookie,token,redis的使用,以及使用全局变量ThreadLocal

    1 什么情况下需要登录操作 首先抛出一个问题 什么情况下才需要登录操作 其实登录操作在很多的管理系统 后台系统中都会涉及到的一个看似简单 但是又特别重要的操作 2 登录是简单的验证数据库账号密码 这么简单吗 在之前我总觉得登录应该是一个很简
  • 树莓派之Linux内核源码(基础)

    目录 一 树莓派等芯片带操作系统的启动过程 二 树莓派Linux源码目录树分析 1 linux内核是开源的 支持多架构多平台代码 2 Linux内核源代码目录树结构 三 树莓派Linux源码配置 1 第一种配置方式 使用源码里自带的conf
  • csdn笔记

    一阶系统的单位阶跃响应 unit Step Response 时间常数 Time constant 1 对于一阶系统 线性时不变 来说 传递函数的一般形式 2 时间常数 是系统特性 可用来识别系统 1 a 稳定时间Tss 4 4 a 3 系
  • pandas写入数据到Excel

    pandas将dataframe写入Excel 大数据写入 split count df shape 0 1000000 1 for i in range split count writer pd ExcelWriter xlsx for
  • 第十九篇 ResNet——论文翻译

    文章目录 摘要 1 引言 2 相关工作 3 深度残差学习 3 1 残差学习 3 2 快捷恒等映射 3 3 网络架构 3 4 实现 4 实验 4 1 ImageNet 分类 4 2 CIFAR 10 和分析 4 3 PASCAL 和 MS C
  • kvm中支持SCSI硬盘接口

    在KVM中安装ubuntu14 硬盘接口采用SCSI 可以正常安装 但是安装centos7却不行 原因是Centos7中没有SCSI驱动 在ubuntu中用lsmod命令查看 可以发现ubuntu中加载了sym53c8xx驱动 就是因为缺少
  • vue3自定义指令之复制指令、拖拽指令、按钮长按指令

    1 复制指令 主要用到 document execCommand Copy 这个api app directive copy beforeMount el binding el targetContent binding value el
  • 设计模式学习书籍推荐(设计模式书籍你读过哪几本)

    概述 想成为大神级别的攻城狮 就读以下这些书籍吧 让你从小白到大神 写出有灵魂程序 进阶之路 始于行动 编程重在理解加多实践 在当今快速发展的时代 要学会站在巨人的肩膀上 吸取经验 看书就是最快与最低成本的进阶之路 史上没有最好的书籍 只有
  • Flutter 布局(一)- Container详解

    Flutter 布局 一 Container详解 Q吹个大气球Q关注 62018 06 03 18 36 26字数 2 301阅读 84 509 本文主要介绍Flutter中非常常见的Container 列举了一些实际例子介绍如何使用 1
  • C#学习路线

    导读 计算机课程是一门实践的课程 而编程尤甚 入门建议从 Visual C 从入门到精通 或者 C 入门经典 这本书中文翻译比较生硬晦涩 可看原版 开始学习 过度到 C 高级编程 和 深入理解C 学习C 前提是下载好Visual Studi
  • 高斯整数环学习心得随笔及其实现

    高斯整数环学习心得随笔 过些天补上 代码 两个高斯整数相伴 即为相等 小于和大于 用复数的范数Norm来比较 应用场景举例 高斯整数环的唯一分解定理证明 整除和取模 带余除法 复数除法的结果是个有理数 但为了方便还是直接用double存了
  • torch 矩阵操作

    1 按索引赋值 index put index put不改变变量本身 index put 改变变量本身 相当于inplace操作 index input 维度1坐标列表 维度2坐标列表 赋值列表 x torch ones 3 3 print
  • Ubuntu20.04换为清华的镜像源

    安装过程 Ubuntu 的软件源配置文件是 etc apt sources list 在修改之前 先将系统自带的该文件做个备份 将该文件替换为清华源官网提供的内容 即可使用 TUNA 的软件源镜像 第一步 切换到root账户 sudo s
  • web前端(HTML+CSS)试题总结

    一 填空题 1 网页的后缀名通常为 xxx html 或 xxx htm 的页面 2 请写出在网页中设定表格边框的厚度的属性 border 设定表格单元格之间宽度属性 cellspacing 设定表格资料与单元格线的距离属性 cellpad
  • docker_run_application

    docker三种方式运行application 1 一次性运行 docker run ubuntu 14 04 bin echo Hello world 登录到container ubuntu14 04 运行命令 bin echo Hell
  • 六、HSV颜色空间应用实例——颜色分割提取与替换

    教程汇总 python基础入门系列 通过之前的章节 四 OpenCV颜色空间 HSV颜色模型 我们已经初步认识了HSV颜色空间的特性与优势 现在就来看两个典型的应用实例 颜色分割提取 与 颜色替换 颜色分割 通过HSV颜色空间的操作我们可以
  • visual studio 2019 调试驱动

    搭建驱动开发环境 搭建环境需要两台机器 本地机器用来代码开发 一台虚拟机用来测试和安装驱动 搭建驱动开发环境参考 visual studio 添加调试机器 驱动工程的属性 gt Driver Installer gt Deployment
  • 第三篇.WDF驱动之Helloworld

    借助Microsoft提供的kmdf框架 来理解一下驱动的一般流程 驱动的开发流程 1 驱动程序入口函数 DriverEntry 驱动程序的入口函数 类似于 main函数 程序的标准入口函数是DriverEntry 与WDM不同 WDF的D