赞
踩
在以下情况下,需要编写 USB Type-C 连接器驱动程序:
下面介绍 USB 连接器管理器 (UCM) ,用于管理 USB Type-C 连接器和连接器驱动程序的预期行为。
UCM 是使用 WDF 类扩展客户端驱动程序模型设计的。 UcmCx类扩展是 Microsoft 提供的 WDF 驱动程序,它提供客户端驱动程序可以调用这些接口来报告有关连接器的信息。 UCM 客户端驱动程序使用连接器的硬件接口,并使类扩展能够识别连接器上发生的事件。 相反,类扩展调用客户端驱动程序为响应操作系统事件而实现的回调函数。
若要在系统上启用 USB Type-C 连接器,必须编写客户端驱动程序。
在开发 计算机上安装最新的 Windows 驱动程序工具包 (WDK) 。 该工具包具有编写 UCM 客户端驱动程序所需的头文件和库,具体而言,你需要:
可以编写在用户模式或内核模式下运行的 UCM 客户端驱动程序。 对于用户模式,它与 UMDF 2.x 库绑定;对于内核模式,则为 KMDF 1.15。 对于任一模式,编程接口都是相同的。
此支持使你能够构建具有 USB Type-C 连接器、USB Type-C 扩展坞和附件以及 USB Type-C 充电器的 Windows 设备。 客户端驱动程序报告连接器事件,这些事件允许操作系统针对系统中的 USB 和功耗实施策略。
UCM 类扩展使操作系统随时了解数据和电源角色、充电级别以及协商的 PD 协定的更改。 当客户端驱动程序与硬件交互时,它必须在发生这些更改时通知类扩展。 类扩展提供了一组方法,客户端驱动程序可以使用这些方法发送本主题 () 中讨论的通知。 以下是提供的服务:
在 USB Type C 系统上, (主机或功能) 的数据角色取决于连接器的 CC 引脚的状态。 客户端驱动程序读取 CC 线路端口控制器的状态,以确定端口是否已解析为面向上游的端口 (UFP) 或面向下游的端口 (UFP) 。 它将该信息报告给类扩展,以便它可以向 USB 角色切换驱动程序报告当前角色。
备注 USB 角色切换驱动程序用于Windows 10 移动版系统。 在桌面版系统的Windows 10上,类扩展和角色切换驱动程序之间的通信是可选的。 此类系统可能不使用双角色控制器,在这种情况下,不使用角色切换驱动程序。
客户端驱动程序读取 USB Type C 当前播发,或与合作伙伴连接器协商 PD 电源合同。
协商 PD 合同后,数据角色和权力角色可能会更改。 该更改可能由客户端驱动程序或合作伙伴连接器启动。 客户端驱动程序向类扩展报告该信息,以便它可以相应地重新配置内容。
操作系统可能会确定当前数据角色不正确。 在这种情况下,类扩展会调用驱动程序的回调函数来执行必要的角色交换操作。
Microsoft 提供的 USB Type C 策略管理器监视 USB Type C 连接器的活动。 Windows 版本 1809 引入了一组编程接口,可用于将客户端驱动程序写入策略管理器。 客户端驱动程序可以参与 USB Type C 连接器的策略决策。 使用此集,可以选择编写内核模式导出驱动程序或用户模式驱动程序。
客户端驱动程序负责执行以下任务:
UCM 连接器对象 (UCMCONNECTOR) 表示 USB Type C 连接器,是 UCM 类扩展和客户端驱动程序之间的main句柄。 对象跟踪连接器的操作模式和电源功能。
下面是客户端驱动程序检索连接器的 UCMCONNECTOR 句柄的序列摘要。 在驱动程序的 中执行这些任务
1.1. 通过将引用传递给 UCM_MANAGER_CONFIG 结构来调用 UcmInitializeDevice。 在调用 WdfDeviceCreate 之前,驱动程序必须在 EVT_WDF_DRIVER_DEVICE_ADD 回调函数中调用此方法。
1.2. 在 UCM_CONNECTOR_TYPEC_CONFIG 结构中指定 USB Type-C 连接器的初始化参数。 这包括连接器的操作模式,无论是面向下游的端口、面向上游端口,还是支持双重角色。 它还指定连接器为电源时的 USB Type C 电流级别。 可以设计 USB Type-C 连接器,使其可以充当 3.5 毫米音频插孔。 如果硬件支持该功能,则必须相应地初始化连接器对象。
在 结构中,还必须注册客户端驱动程序的回调函数以处理数据角色。
此回调函数与连接器对象相关联,连接器对象由 UCM 类扩展调用。 此函数必须由客户端驱动程序实现。
EVT_UCM_CONNECTOR_SET_DATA_ROLE 在附加到合作伙伴连接器时,将连接器的数据角色交换为指定角色。
1.3. 如果客户端驱动程序希望支持 PD,即处理连接器的 Power Delivery 2.0 硬件实现,则还必须初始化指定 PD 初始化参数 的 UCM_CONNECTOR_PD_CONFIG 结构。 这包括电源流,无论连接器是电源接收器还是电源。
在 结构中,还必须注册客户端驱动程序的回调函数来处理电源角色。
此回调函数与连接器对象相关联,连接器对象由 UCM 类扩展调用。 此函数必须由客户端驱动程序实现。
EVT_UCM_CONNECTOR_SET_POWER_ROLE 在连接到合作伙伴连接器时,将连接器的电源角色设置为指定角色。
1.4. 调用 UcmConnectorCreate 并检索连接器的 UCMCONNECTOR 句柄。 请确保在客户端驱动程序通过调用 WdfDeviceCreate 创建框架设备对象后调用此方法。 此调用的适当位置可以位于驱动程序 EVT_WDF_DEVICE_PREPARE_HARDWARE 或 EVT_WDF_DEVICE_D0_ENTRY。
- EVT_UCM_CONNECTOR_SET_DATA_ROLE EvtSetDataRole;
-
- NTSTATUS
- EvtDevicePrepareHardware(
- WDFDEVICE Device,
- WDFCMRESLIST ResourcesRaw,
- WDFCMRESLIST ResourcesTranslated
- )
- {
- NTSTATUS status = STATUS_SUCCESS;
- PDEVICE_CONTEXT devCtx;
- UCM_MANAGER_CONFIG ucmCfg;
- UCM_CONNECTOR_CONFIG connCfg;
- UCM_CONNECTOR_TYPEC_CONFIG typeCConfig;
- UCM_CONNECTOR_PD_CONFIG pdConfig;
- WDF_OBJECT_ATTRIBUTES attr;
- PCONNECTOR_CONTEXT connCtx;
-
- UNREFERENCED_PARAMETER(ResourcesRaw);
- UNREFERENCED_PARAMETER(ResourcesTranslated);
-
- TRACE_FUNC_ENTRY();
-
- devCtx = GetDeviceContext(Device);
-
- if (devCtx->Connector)
- {
- goto Exit;
- }
-
- //
- // Initialize UCM Manager
- //
- UCM_MANAGER_CONFIG_INIT(&ucmCfg);
-
- status = UcmInitializeDevice(Device, &ucmCfg);
- if (!NT_SUCCESS(status))
- {
- TRACE_ERROR(
- "UcmInitializeDevice failed with %!STATUS!.",
- status);
- goto Exit;
- }
-
- TRACE_INFO("UcmInitializeDevice() succeeded.");
-
- //
- // Create a USB Type-C connector #0 with PD
- //
- UCM_CONNECTOR_CONFIG_INIT(&connCfg, 0);
-
- UCM_CONNECTOR_TYPEC_CONFIG_INIT(
- &typeCConfig,
- UcmTypeCOperatingModeDrp,
- UcmTypeCCurrentDefaultUsb | UcmTypeCCurrent1500mA | UcmTypeCCurrent3000mA);
-
- typeCConfig.EvtSetDataRole = EvtSetDataRole;
-
- UCM_CONNECTOR_PD_CONFIG_INIT(&pdConfig, UcmPowerRoleSink | UcmPowerRoleSource);
-
- connCfg.TypeCConfig = &typeCConfig;
- connCfg.PdConfig = &pdConfig;
-
- WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CONNECTOR_CONTEXT);
-
- status = UcmConnectorCreate(Device, &connCfg, &attr, &devCtx->Connector);
- if (!NT_SUCCESS(status))
- {
- TRACE_ERROR(
- "UcmConnectorCreate failed with %!STATUS!.",
- status);
- goto Exit;
- }
-
- connCtx = GetConnectorContext(devCtx->Connector);
-
- UcmEventInitialize(&connCtx->EventSetDataRole);
-
- TRACE_INFO("UcmConnectorCreate() succeeded.");
-
- Exit:
-
- TRACE_FUNC_EXIT();
- return status;
- }
检测到与合作伙伴连接器的连接时,客户端驱动程序必须调用 UcmConnectorTypeCAttach 。 此调用通知 UCM 类扩展,这会进一步通知操作系统。 此时,系统可能会开始在 USB Type C 级别充电。
UCM 类扩展还会通知 USB 角色切换驱动程序 (URS) 。 根据合作伙伴的类型,URS 在Host角色或功能角色中配置控制器。 在调用此方法之前,请确保系统已正确配置。 否则,如果系统处于功能角色,它将以不正确的速度连接 (高速而不是 SuperSpeed) 。
- UCM_CONNECTOR_TYPEC_ATTACH_PARAMS attachParams;
-
- UCM_CONNECTOR_TYPEC_ATTACH_PARAMS_INIT(
- &attachParams,
- UcmTypeCPortStateDfp);
- attachParams.CurrentAdvertisement = UcmTypeCCurrent1500mA;
-
- status = UcmConnectorTypeCAttach(
- Connector,
- &attachParams);
- if (!NT_SUCCESS(status))
- {
- TRACE_ERROR(
- "UcmConnectorTypeCAttach() failed with %!STATUS!.",
- status);
- goto Exit;
- }
-
- TRACE_INFO("UcmConnectorTypeCAttach() succeeded.");
在初始附加事件中,合作伙伴连接器发送当前播发。 如果播发指定合作伙伴连接器的当前级别,则合作伙伴是面向 USB Type C 的端口。 否则,播发指定本地连接器的当前级别,由本地连接器 UCMCONNECTOR 句柄表示。 此初始播发可能会在连接的生存期内更改。 这些更改必须由客户端驱动程序监视。
如果本地连接器是电源接收器,并且当前播发发生了更改,则客户端驱动程序必须检测当前播发中的更改,并将其报告给类扩展。 在Windows 10 移动版系统上,CAD.sys 和电池子系统使用该信息来调整从源中抽取的电流量。 若要向类扩展报告当前级别的更改,客户端驱动程序必须调用 UcmConnectorTypeCCurrentAdChanged。
如果连接器支持 PD,在初始附加事件之后,连接器及其合作伙伴连接器之间传输了 PD 消息。 在两个合作伙伴之间,协商 PD 合同,确定连接器可以绘制或允许合作伙伴绘制的当前级别。 每次 PD 协定更改时,客户端驱动程序都必须调用这些方法来向类扩展报告更改。
UcmConnectorPdPartnerSourceCaps 用于报告合作伙伴连接器播发的源功能。
UcmConnectorPdConnectionStateChanged 用于报告合同的详细信息。 该协定在 Power Delivery 2.0 规范中定义的请求数据对象中描述。
UcmConnectorPdSourceCaps ,用于将系统播发的源功能报告给合作伙伴连接器。
UcmConnectorPdConnectionStateChanged 报告当前协商的 PD 协定的连接功能。
如果充电级别不足,客户端驱动程序可以通知 UCM 类扩展。 类扩展将此信息报告给操作系统。 系统使用该信息向用户显示充电器未以最佳方式为系统充电的通知。 可以通过以下方法报告充电状态:
这些方法指定充电状态。 如果报告的级别为 UcmChargingStateSlowCharging 或 UcmChargingStateTrickleCharging 。
如果连接器收到电源角色 (PR_Swap) 或数据角色 (DR_Swap) 交换来自合作伙伴的消息,则客户端驱动程序必须通知 UCM 类扩展。
处理 PD DR_Swap消息后调用此方法。 完成此调用后,操作系统会将新角色报告给 URS,这会删除现有角色驱动程序并加载新角色的驱动程序。
在处理 PD PR_Swap消息后调用此方法。 PR_Swap后,需要重新谈判 PD 协定。 客户端驱动程序必须通过调用 步骤 4 中所述的方法来报告 PD 协定协商。
UCM 类扩展可能会收到更改连接器的数据或电源方向的请求。 在这种情况下,如果连接器实现 PD) ,它将 (调用客户端驱动程序实现EVT_UCM_CONNECTOR_SET_DATA_ROLE 和EVT_UCM_CONNECTOR_SET_POWER_ROLE 回调函数。 客户端驱动程序之前在调用 UcmConnectorCreate 时注册了这些函数。
客户端驱动程序使用硬件接口执行角色交换操作。
在回调实现中,客户端驱动程序应:
- EVT_UCM_CONNECTOR_SET_DATA_ROLE EvtSetDataRole;
-
- NTSTATUS
- EvtSetDataRole(
- UCMCONNECTOR Connector,
- UCM_TYPE_C_PORT_STATE DataRole
- )
- {
- PCONNECTOR_CONTEXT connCtx;
-
- TRACE_INFO("EvtSetDataRole(%!UCM_TYPE_C_PORT_STATE!) Entry", DataRole);
-
- connCtx = GetConnectorContext(Connector);
-
- TRACE_FUNC_EXIT();
-
- return STATUS_SUCCESS;
- }
在回调实现中,客户端驱动程序应:
- EVT_UCM_CONNECTOR_SET_POWER_ROLE EvtSetPowerRole;
-
- NTSTATUS
- EvtSetPowerRole(
- UCMCONNECTOR Connector,
- UCM_POWER_ROLE PowerRole
- )
- {
- PCONNECTOR_CONTEXT connCtx;
-
- TRACE_INFO("EvtSetPowerRole(%!UCM_POWER_ROLE!) Entry", PowerRole);
-
- connCtx = GetConnectorContext(Connector);
-
- //PR_Swap operation.
-
- TRACE_FUNC_EXIT();
-
- return STATUS_SUCCESS;
- }
客户端驱动程序可以异步调用 UcmConnectorDataDirectionChanged 和 UcmConnectorPowerDirectionChanged ,这并非来自回调线程。 在典型的实现中, 类扩展调用回调函数,导致客户端驱动程序启动硬件事务以发送消息。 事务完成后,硬件会通知驱动程序。 驱动程序调用这些方法以通知类扩展。
当与合作伙伴连接器的连接结束时,客户端驱动程序必须调用 UcmConnectorTypeCDetach 。 此调用通知 UCM 类扩展,这会进一步通知操作系统。
当运行 Windows 10 移动版 的设备通过 USB Type-C 连接连接到运行 Windows 10 桌面版的电脑时,操作系统将确保移动设备是面向上游的端口 (UFP) ,因为 MTP 仅在该方向上工作。 在此方案中,数据角色更正的顺序如下:
如果两个Windows 10 移动版设备相互连接,则不会执行角色交换,并且通知用户该连接不是有效的连接。
Microsoft 提供的 USB Type C 策略管理器监视 USB Type C 连接器的活动。 Windows 版本 1809 引入了一组编程接口,可用于在本文中将客户端驱动程序写入策略管理器称为 PM 客户端驱动程序 。 客户端驱动程序可以参与 USB Type C 连接器的策略决策。 使用此集,可以选择编写内核模式导出驱动程序或用户模式驱动程序。
策略管理器从 USB 连接器管理器 (UCM) 、USB 主机控制器和 USB 功能以及 PM 客户端驱动程序获取和协调信息。 需要 UI 通知时,策略管理器会将请求发送到系统 Shell。
PM API 在 Usbpmapi.h 标头中声明。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。