windows USB 设备驱动开发-编写 UCSI 客户端驱动程序

编写 UCSI 客户端驱动程序

USB Type-C 连接or 系统软件接口(UCSI)驱动程序充当带有嵌入式控制器(EC)的 USB Type-C 系统的控制器驱动程序。

如果实现平台策略管理器(PPM)的系统,如 UCSI 规范中所述,请在连接到系统的 EC 中通过以下方式进行:

  • ACPI 传输不需要编写驱动程序。 加载 Microsoft 提供的内置驱动程序(UcmUcsiCx.sys和UcmUcsiAcpiClient.sys); 
  • 非 ACPI 传输(如 USB、PCI、I2C 或 UART)需要为控制器编写客户端驱动程序;
  • 如果 USB Type-C 硬件没有处理电源交付(PD)状态机的功能,请考虑编写 USB Type-C 端口控制器驱动程序;

从 Windows 10 版本 1809 开始,添加了 UCSI(UcmUcsiCx.sys)的新类扩展,该扩展以与传输无关的方式实现 UCSI 规范。 只需编写极少量的代码,驱动程序(即 UcmUcsiCx 的客户端)即可通过非 ACPI 传输来与 USB Type C 硬件通信。 本主题介绍 UCSI 类扩展提供的服务,以及客户端驱动程序的预期行为。

UCSI 类扩展体系结构

UCSI 类扩展 UcmUcsiCx 允许编写驱动程序,该驱动程序使用非 ACPI 传输与其嵌入式控制器通信。 控制器驱动程序是 UcmUcsiCx 的客户端驱动程序。 UcmUcsiCx 又是 USB 连接器管理器(UCM)的客户端。 因此,UcmUcsiCx 不自行做出任何策略决策。 而是实现 UCM 提供的策略。 UcmUcsiCx 实现状态机来处理来自客户端驱动程序的平台策略管理器(PPM)通知,并发送命令来实现 UCM 策略决策,从而允许更可靠的问题检测和错误处理。

OS 策略管理器 (OPM)

OS 策略管理器(OPM)实现与 PPM 交互的逻辑,如 UCSI 规范中所述。 OPM 负责:

  • 将 UCM 策略转换为 UCSI 命令,将 UCSI 通知转换为 UCM 通知;
  • 发送初始化 PPM、检测错误和恢复机制所需的 UCSI 命令;
处理 UCSI 命令

典型的操作涉及由 UCSI 复杂硬件完成的多个命令。 例如,让我们考虑GET_CONNECTOR_STATUS命令。

  • PPM 固件将连接更改通知发送到 UcmUcsiCx/客户端驱动程序;
  • 作为响应,UcmUcsiCx/客户端驱动程序将GET_CONNECTOR_STATUS命令发送回 PPM 固件;
  • PPM 固件执行GET_CONNECTOR_STATUS,并异步将命令完成通知发送到 UcmUcsiCx/客户端驱动程序。 该通知包含有关实际连接状态的数据;
  • UcmUcsiCx/客户端驱动程序处理状态信息并将ACK_CC_CI发送到 PPM 固件;
  • PPM 固件执行ACK_CC_CI,并异步将命令完成通知发送到 UcmUcsiCx/客户端驱动程序;
  • UcmUcsiCx/客户端驱动程序将GET_CONNECTOR_STATUS命令视为已完成;
与平台策略管理器(PPM)的通信

UcmUcsiCx 抽象化了将 UCSI 命令从 OPM 发送到 PPM 固件以及从 PPM 固件接收通知的详细信息。 它将 PPM 命令转换为 WDFREQUEST 对象,并将其转发到客户端驱动程序。

  • PPM 通知:客户端驱动程序向 UcmUcsiCx 通知固件中的 PPM 通知。 驱动程序提供包含 CCI 的 UCSI 数据块。 UcmUcsiCx 将通知转发到 OPM 和其他组件,这些组件基于数据采取适当的操作;
  • 客户端驱动程序的 IOCTL:UcmUcsiCx 将 UCSI 命令(通过 IOCTL 请求)发送到客户端驱动程序以发送到 PPM 固件。 驱动程序负责在将 UCSI 命令发送到固件后完成请求;
处理电源转换

客户端驱动程序是电源策略所有者。如果客户端驱动程序由于 S0-Idle 而进入 Dx 状态,则当 UcmUcsiCx 向客户端驱动程序的电源托管队列发送包含 UCSI 命令的 IOCTL 时,WDF 会将驱动程序引入 D0。 当固件中有 PPM 通知时,S0-Idle 中的客户端驱动程序应重新进入电源状态,因为在 S0-Idle 中,仍会启用 PPM 通知。

开始之前
  • 根据硬件或固件是否实现 PD 状态机和传输,确定需要写入的驱动程序类型。

  • 安装 Windows 10 桌面版(家庭版、专业版、企业版和教育版)。
  • 在开发计算机上安装最新的 Windows 驱动程序工具包(WDK)。 该工具包具有用于编写客户端驱动程序所需的头文件和库,具体而言,需要:库(UcmUcsiCxStub.lib)。 该库转换客户端驱动程序发出的调用,并将其传递给类扩展;头文件 Ucmucsicx.h。

客户端驱动程序在内核模式下运行,并绑定到 KMDF 1.27 库。

1.向 UcmUcsiCx 注册客户端驱动程序

在EVT_WDF_DRIVER_DEVICE_ADD实现中。

  • 设置即插即用和电源管理事件回调函数(WdfDeviceInitSetPnpPowerEventCallbacks)后,调用 UcmUcsiDeviceInitInitInitialize 初始化WDFDEVICE_INIT不透明结构。 调用将客户端驱动程序与框架相关联;
  • 创建框架设备对象(WDFDEVICE)后,调用 UcmUcsiDeviceInitialize 以向 UcmUcsiCx 注册客户端 diver;
2. 使用 UcmUcsiCx 创建 PPM 对象

在EVT_WDF_DEVICE_PREPARE_HARDWARE的实现中,收到原始和已翻译的资源列表后,请使用资源来准备硬件。 例如,如果传输为 I2C,请读取硬件资源以打开信道。 接下来,创建 PPM 对象。 若要创建对象,需要设置某些配置选项。

2.1. 为设备上的连接器集合提供句柄。

通过调用 UcmUcsi连接orCollectionCreate 创建连接器集合;通过调用 UcmUcsi连接orCollectionAdd连接or 枚举设备上的连接器并将其添加到集合:

// Create the connector collection.UCMUCSI_CONNECTOR_COLLECTION* ConnectorCollectionHandle;status = UcmUcsiConnectorCollectionCreate(Device, //WDFDeviceWDF_NO_OBJECT_ATTRIBUTES,ConnectorCollectionHandle);// Enumerate the connectors on the device.
// ConnectorId of 0 is reserved for the parent device.
// In this example, we assume the parent has no children connectors.UCMUCSI_CONNECTOR_INFO_INIT(&connectorInfo);
connectorInfo.ConnectorId = 0;status = UcmUcsiConnectorCollectionAddConnector ( &ConnectorCollectionHandle,&connectorInfo);

2.2. 确定是否要启用设备控制器。

2.3. 配置并创建 PPM 对象。

通过提供在步骤 1 中创建的连接器句柄来初始化UCMUCSI_PPM_CONFIG结构。将 UsbDeviceControllerEnabled 成员设置为步骤 2 中确定的布尔值。在WDF_OBJECT_ATTRIBUTES中设置事件回调。通过传递所有配置的结构来调用 UcmUcsiPpmCreate:

UCMUCSIPPM ppmObject = WDF_NO_HANDLE;
PUCMUCSI_PPM_CONFIG UcsiPpmConfig;
WDF_OBJECT_ATTRIBUTES attrib;UCMUCSI_PPM_CONFIG_INIT(UcsiPpmConfig, ConnectorCollectionHandle);UcsiPpmConfig->UsbDeviceControllerEnabled = TRUE;WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attrib, Ppm);
attrib->EvtDestroyCallback = &EvtObjectContextDestroy;status = UcmUcsiPpmCreate(wdfDevice, UcsiPpmConfig, &attrib, &ppmObject);
3. 设置 IO 队列

UcmUcsiCx 将 UCSI 命令发送到客户端驱动程序以发送到 PPM 固件。 这些命令以 WDF 队列中的这些 IOCTL 请求的形式发送。

  • IOCTL_UCMUCSI_PPM_标准版ND_UCSI_DATA_BLOCK
  • IOCTL_UCMUCSI_PPM_GET_UCSI_DATA_BLOCK

客户端驱动程序负责通过调用 UcmUcsiPpmSetUcsiCommandRequestQueue 来创建和注册该队列到 UcmUcsiCx。 队列必须进行电源管理。

UcmUcsiCx 保证 WDF 队列中最多可以有一个未完成的请求。 客户端驱动程序还负责在将 UCSI 命令发送到固件后完成 WDF 请求。

通常,驱动程序在实现EVT_WDF_DEVICE_PREPARE_HARDWARE时设置队列。

WDFQUEUE UcsiCommandRequestQueue = WDF_NO_HANDLE;
WDF_OBJECT_ATTRIBUTES attrib;
WDF_IO_QUEUE_CONFIG queueConfig;WDF_OBJECT_ATTRIBUTES_INIT(&attrib);
attrib.ParentObject = GetObjectHandle();// In this example, even though the driver creates a sequential queue,
// UcmUcsiCx guarantees that will not send another request
// until the previous one has been completed.WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);// The queue must be power-managed.queueConfig.PowerManaged = WdfTrue;
queueConfig.EvtIoDeviceControl = EvtIoDeviceControl;status = WdfIoQueueCreate(device, &queueConfig, &attrib, &UcsiCommandRequestQueue);UcmUcsiPpmSetUcsiCommandRequestQueue(ppmObject, UcsiCommandRequestQueue);

此外,客户端驱动程序还必须调用 UcmUcsiPpmStart 来通知 UcmUcsiCx 驱动程序已准备好接收 IOCTL 请求。 建议在创建用于接收 UCSI 命令的 WDFQUEUE 句柄后,在 EVT_WDF_DEVICE_PREPARE_HARDWARE 中发出该调用,通过 UcmUcsiPpmSetUcsiCommandRequestQueue。 相反,当驱动程序不想再处理任何请求时,它必须调用 UcmUcsiPpmStop。 执行此操作在EVT_WDF_DEVICE_RELEA标准版_HARDWARE实现中。

4.处理 IOCTL 请求

请考虑将 USB Type C 合作伙伴附加到连接器时发生的事件的此示例序列。

  1. PPM 固件确定附加事件并向客户端驱动程序发送通知;
  2. 客户端驱动程序调用 UcmUcsiPpmNotification 将通知发送到 UcmUcsiCx;
  3. UcmUcsiCx 通知 OPM 状态机,并将 Get 连接or Status 命令发送到 UcmUcsiCx;
  4. UcmUcsiCx 创建一个请求,并将IOCTL_UCMUCSI_PPM_标准版ND_UCSI_DATA_BLOCK发送到客户端驱动程序;
  5. 客户端驱动程序处理请求命令并将其发送到 PPM 固件。 驱动程序以异步方式完成此请求,并将另一个通知发送到 UcmUcsiCx;
  6. 成功发出命令完成通知后,OPM 状态机将读取有效负载(包含连接器状态信息),并通知 UCM Type C 附加事件;

在此示例中,有效负载还指示固件与端口合作伙伴之间的电源交付协商状态更改已成功。 OPM 状态机发送另一个 UCSI 命令:获取 PDO。 与 Get 连接or Status 命令类似,当 Get PDO 命令成功完成时,OPM 状态机会通知 UCM 此事件。

EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL的客户端驱动程序处理程序类似于此示例代码。 

void EvtIoDeviceControl(_In_ WDFREQUEST Request,_In_ ULONG IoControlCode)
{
...switch (IoControlCode){case IOCTL_UCMUCSI_PPM_SEND_UCSI_DATA_BLOCK:EvtSendData(Request);break;case IOCTL_UCMUCSI_PPM_GET_UCSI_DATA_BLOCK:EvtReceiveData(Request);break;default:status = STATUS_NOT_SUPPORTED;goto Exit;}status = STATUS_SUCCESS;Exit:if (!NT_SUCCESS(status)){WdfRequestComplete(Request, status);}}VOID EvtSendData(WDFREQUEST Request)
{NTSTATUS status;PUCMUCSI_PPM_SEND_UCSI_DATA_BLOCK_IN_PARAMS inParams;status = WdfRequestRetrieveInputBuffer(Request, sizeof(*inParams),reinterpret_cast<PVOID*>(&inParams), nullptr);if (!NT_SUCCESS(status)){goto Exit;}// Build a UCSI command request and send to the PPM firmware.Exit:WdfRequestComplete(Request, status);
}VOID EvtReceiveData(WDFREQUEST Request)
{NTSTATUS status;PUCMUCSI_PPM_GET_UCSI_DATA_BLOCK_IN_PARAMS inParams;PUCMUCSI_PPM_GET_UCSI_DATA_BLOCK_OUT_PARAMS outParams;status = WdfRequestRetrieveInputBuffer(Request, sizeof(*inParams),reinterpret_cast<PVOID*>(&inParams), nullptr);if (!NT_SUCCESS(status)){goto Exit;}status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*outParams),reinterpret_cast<PVOID*>(&outParams), nullptr);if (!NT_SUCCESS(status)){goto Exit;}// Receive data from the PPM firmware.if (!NT_SUCCESS(status)){goto Exit;}WdfRequestSetInformation(Request, sizeof(*outParams));Exit:WdfRequestComplete(Request, status);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/380968.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产化低功耗HDMI转VGA方案,大量出货产品,广泛应用在显示器以及广告机产品

芯片描述&#xff1a; 兼具高性能和低成本效益的优点&#xff0c;是一款可以将高清视频 HDMI1.4 数字信号转换成 VGA 模拟信号输出的芯片。不需要提供外部电源&#xff0c;ICNM7301 就可以在正常模式下使用&#xff1b;ICNM7301 广 泛适用于各种市场系统和显示应用体系&#x…

LabVIEW异步和同步通信详细分析及比较

1. 基本原理 异步通信&#xff1a; 原理&#xff1a;异步通信&#xff08;Asynchronous Communication&#xff09;是一种数据传输方式&#xff0c;其中数据发送和接收操作在独立的时间进行&#xff0c;不需要在特定时刻对齐。发送方在任何时刻可以发送数据&#xff0c;而接收…

2024年广东省安全员B证第四批(项目负责人)证模拟考试题库及广东省安全员B证第四批(项目负责人)理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年广东省安全员B证第四批&#xff08;项目负责人&#xff09;证模拟考试题库及广东省安全员B证第四批&#xff08;项目负责人&#xff09;理论考试试题是由安全生产模拟考试一点通提供&#xff0c;广东省安全员B证…

手持式气象站:便携科技,掌握微观气象的利器

手持式气象站&#xff0c;顾名思义&#xff0c;是一种可以随身携带的气象监测设备。它小巧轻便&#xff0c;通常配备有温度、湿度、风速、风向、气压等多种传感器&#xff0c;能够实时测量并显示各种气象参数。不仅如此&#xff0c;它还具有数据存储、数据传输、远程控制等多种…

kafka开启kerberos和ACL

作者&#xff1a;恩慈 一、部署kafka-KB包 1&#xff0e;上传软件包 依次点击 部署中心----部署组件----上传软件包 选择需要升级的kafka版本并点击确定 2&#xff0e;部署kafka 依次点击部署中心----部署组件----物理/虚拟机部署----选择集群----下一步 选择手动部署-…

MongoDB自学笔记(四)

一、前文回顾 上一篇文章中我们学习了MongoDB中的更新方法&#xff0c;也学了一部分操作符。今天我们将学习最后一个操作“删除”。 二、删除 原始数据如下&#xff1a; 1、deleteOne 语法&#xff1a;db.collection.deleteOne(< query >,< options >) 具体参…

学生信息管理系统-可视化-科目管理CRUD代码生成器

学生管理系统中的科目管理是一个重要的组成部分&#xff0c;它负责维护和管理学校中所有的教学科目信息。 可视化快速界面生成CRUD界面&#xff0c;API通过代码生成器生成器生成。 新增数据库表 拷贝demo_table修改为clazz_kemu表 修改表结构 其中包括一个自增ID字段&#x…

在虚拟机 CentOS7 环境下安装 MySQL5.7 数据库

配置目标 在虚拟机的 Linux CentOS7 环境下安装 MySQL5.7 版数据库&#xff0c;并能从宿主机 Windows 系统连接该数据库&#xff08;默认端口&#xff1a;3306&#xff09;。 1. 准备工作 WMware 虚拟机&#xff1a;VMware Workstation 16 ProCentOS7 镜像&#xff1a;CentO…

Java面试题--JVM大厂篇之深入解析JVM中的Serial GC:工作原理与代际区别

目录 引言&#xff1a; 正文&#xff1a; 一、Serial GC工作原理 年轻代垃圾回收&#xff08;Minor GC&#xff09;&#xff1a; 老年代垃圾回收&#xff08;Major GC或Full GC&#xff09;&#xff1a; 二、年轻代和老年代的区别 年轻代&#xff08;Young Generation&a…

redis其他类型和配置文件

很多博客只讲了五大基本类型&#xff0c;确实&#xff0c;是最常用的&#xff0c;而且百分之九十的程序员对于Redis只限于了解String这种最常用的。但是我个人认为&#xff0c;既然Redis官方提供了其他的数据类型&#xff0c;肯定是有相应的考量的&#xff0c;在某些特殊的业务…

【C++】——new和delete

文章目录 热身试题C中的内存管理new与delete对于内置类型的操作new与delete对于自定义类型的操作 malloc/free和new/delete的区别 热身试题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3…

嵌入式物联网在教育行业的应用——案例分析

作者主页: 知孤云出岫 嵌入式物联网在教育行业的应用——案例分析 目录 作者主页:嵌入式物联网在教育行业的应用——案例分析一、引言二、智能教室&#xff1a;环境监测系统1. 硬件需求2. 电路连接3. 代码实现 三、个性化学习&#xff1a;智能学习平台1. 数据处理与分析2. 代…

Flutter中GetX的用法(超详细使用指南之路由依赖管理篇)

目录 1.前言 2.GetX 依赖管理概述 1.GetX 依赖管理的基本概念 2.与其他依赖管理工具的比较 3. 基础依赖注入 1.Get.put 2.Get.lazyPut 3.Get.putAsync 4.高级依赖注入 1.使用Get.create 2.依赖生命周期管理 5. 参考资料 1.前言 今天这篇博客主要介绍Getx的三大功能…

ESP8266模块(2)

实例1 查看附近的WiFi 步骤1&#xff1a;进入AT指令模式 使用USB转串口适配器将ESP8266模块连接到电脑。打开串口终端软件&#xff0c;并设置正确的串口和波特率&#xff08;通常为115200&#xff09;。输入以下命令并按回车确认&#xff1a; AT如果模块响应OK&#xff0c;…

R语言包AMORE安装报错问题以及RStudio与Rtools环境配置

在使用R语言进行AMORE安装时会遇到报错,这时候需要采用解决办法: AMORE包安装,需要离线官网下载安装包: Index of /src/contrib/Archive/AMORE (r-project.org)https://cran.r-project.org/src/contrib/Archive/AMORE/ 一、出现的问题 最近开始学习R语言,安装了最新版…

Window中 Redis下载安装

Redis7.2.3连接&#xff1a; 我用夸克网盘分享了「redis-windows-7.2.3.zip」&#xff0c;点击链接即可保存。打开「夸克APP」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/4dfb0497707a 在安…

义务外贸wordpress独立站主题

健身器材wordpress网站模板 跑步机、椭圆机、划船机、动感单车、健身车、深蹲架、龙门架、健身器材wordpress网站模板。 https://www.jianzhanpress.com/?p4251 农业机械wordpress网站模板 植保机械、畜牧养殖机械、农机配件、土壤耕整机械、农业机械wordpress网站模板。 …

WebRTC音视频-前言介绍

目录 效果预期 1&#xff1a;WebRTC相关简介 1.1&#xff1a;WebRTC和RTC 1.2&#xff1a;WebRTC前景和应用 2&#xff1a;WebRTC通话原理 2.1&#xff1a;媒体协商 2.2&#xff1a;网络协商 2.3&#xff1a;信令服务器 效果预期 1&#xff1a;WebRTC相关简介 1.1&…

Windows FFmpeg 开发环境搭建

FFmpeg 开发环境搭建 FFmpeg命令行环境搭建使用FFmpeg官方编译的库Windows编译FFmpeg1. 下载[msys2](https://www.msys2.org/#installation)2. 安装完成之后,将安装⽬录下的msys2_shell.cmd中注释掉的 rem set3. 修改pacman 镜像源并安装依赖4. 下载并编译源码 FFmpeg命令行环境…

Python PDF Magic:合并和拆分随心所欲

大家好&#xff01;小编今天要为大家带来一篇关于Python操作PDF的秘籍——无论是要将PDF合并成一份整体&#xff0c;还是将一个庞大的PDF文件拆分成多个小伙伴&#xff0c;都轻松hold住&#xff01;你准备好了吗&#xff1f;让我们开始这场奇妙的PDF操作之旅吧&#xff01; 准…