在USB的通讯协议中,规定发起连接的一方为主机(Host),接受连接的一方为设备,这可以用U盘插入电脑举个例子,当U盘插入电脑后,电脑这边主动发起查询和枚举,U盘被动响应查询和数据存取。
USB 双角色驱动程序堆栈体系结构
Windows 现在支持 USB 双角色控制器,从Windows 10开始 ,包括家庭版、专业版、企业版和教育版和Windows 10 移动版。USB 双角色功能使系统成为 USB 设备 或 USB 主机成为可能。 可在 USB-IF 规范中找到 USB 双角色的详细规定。
此处的重要一点是,双重角色功能允许移动设备(如手机、平板手机或平板电脑)将自身指定为设备或主机:
- 当移动设备处于 功能 模式时,它将连接到电脑或充当附加移动设备主机的其他设备;
- 当移动设备处于 主机 模式时,用户可以将其设备(如鼠标或键盘)附加到其中。 在本例中,移动设备托管附加的设备;
通过在 Windows 10 中提供对 USB 双重角色的支持,我们提供以下优势:
- 通过 USB 连接到移动外围设备,与蓝牙等无线协议相比,USB 提供更大的数据带宽;
- 在连接到其他 USB 设备并与其他 USB 设备通信时通过 USB 充电的选项 前提是 存在所需的硬件支持;
- 允许最有可能拥有移动设备(如智能手机)的客户完成所有工作。 此功能将提高有线停靠方案中的工作效率,其中移动设备停靠并因此托管外围设备;
下表显示了 Windows 桌面 SKU 和移动 SKU 上可用的 主机 类驱动程序列表。
表中的类驱动程序是根据设备类遥测数据以及为Windows 10选择的关键方案选择的。 我们计划包括有限数量的系统更新、第三方主机驱动程序支持,以支持Windows 10 移动版上的关键设备。 对于桌面版Windows 10,这些驱动程序将在 OEM 网站上或通过 Windows 更新 (Windows Update) 提供。
对于Windows 10 移动版,未包含在支持列表中的第三方驱动程序在 Windows Update上不可用。 USB 主机堆栈 + HID 的磁盘占用空间一直很小。 这就是为什么并非所有类驱动程序,并且极少数第三方驱动程序包含在Windows 10 移动版的支持列表中。 希望提供第三方驱动程序的 OEM 可以使用板支持包 (BSP) 将其添加到移动设备的 OS 映像。
下表显示了 Windows 移动 SKU 上可用的 函数 类驱动程序。
windows会动态监视设备附件数据,以确定是否需要提供其他类驱动程序支持,因为设备类的受欢迎程度列表随时间而变化。
驱动程序实现
Microsoft USB 角色开关 (URS) 驱动程序允许系统实施者利用其平台的双角色 USB 功能。
URS 驱动程序旨在为使用单个 USB 控制器的平台提供双重角色功能,这些控制器可通过单个端口在主机和外围角色中运行。 外围角色也称为功能角色。 URS 驱动程序根据平台中的硬件事件管理端口的当前角色,以及相应软件堆栈的加载和卸载。
在具有 USB micro-AB 连接器的系统上,驱动程序使用硬件中断来指示连接器上的 ID 引脚的状态。 此引脚用于检测控制器是否需要在连接中承担主机角色或函数角色。在具有 USB Type-C 连接器的系统上,OEM 实现者应通过使用 USB Type-C 连接器驱动程序编程接口提供连接器客户端驱动程序。 客户端驱动程序与 Microsoft 提供的 USB 连接器管理器类扩展 (UcmCx) 进行通信,以管理 USB Type-C 连接器的所有方面,例如 CC 检测、PD 消息传送等。 对于角色切换,客户端驱动程序将 USB 类型 C 连接器的状态传达给 URS 驱动程序。
下图显示了使用 URS 驱动程序的双角色控制器的 USB 软件驱动程序堆栈。
请注意,URS 驱动程序永远不会同时加载上图中显示的函数堆栈和主机堆栈。 URS 驱动程序 将加载函数 堆栈 或 主机堆栈 ,具体取决于 USB 控制器的角色。
硬件要求
如果要开发利用 URS 驱动程序的平台以提供双角色 USB 功能,则必须满足以下硬件要求:
1. USB 控制器: 这些驱动程序由 Microsoft 作为内置驱动程序提供。
Synopsys DesignWare Core USB 3.0 控制器。 INF:UrsSynopsys.inf。
Chipidea High-Speed USB OTG 控制器。 INF:UrsChipidea.inf。
2. ID 引脚中断:非 USB 类型 C 系统的 ID 引脚中断可通过以下两种方式之一实现:
- 两个边缘触发的中断:一个在连接器上的 ID 引脚接地时触发,另一个在 ID 引脚浮动时触发;
- ID 引脚接地时处于活动级别的单个双活动中断;
3. USB 控制器枚举: USB 双角色控制器必须是 ACPI 枚举的。
软件支持
URS 驱动程序需要一个允许通过连接器控制 VBus 的软件接口。 此接口特定于 SoC。
Windows 不支持以下 USB OTG 功能:
- 附件充电器适配器检测 (ACA) ;
- 会话请求协议 (SRP) ;
- 主机协商协议 (HNP) ;
- (ADP) 附加检测协议;
ACPI 系统配置
若要使用 URS 驱动程序,必须为系统创建 ACPI 定义文件。 此外,还必须考虑一些与驱动程序相关的注意事项。
下面是 USB 双角色控制器的示例 ACPI 定义。
//
// You may name the device whatever you want; we don't depend on it being called 'URS0'.
//
Device(URS0)
{
//
// Replace with your own hardware ID. Microsoft will add it to the inbox INF,
// or you may choose to author a custom INF that uses Needs & Includes directives
// to include sections from the inbox INF.
//
Name(_HID, "ABCD1234")
Name(_CRS, ResourceTemplate() {
//
// The register space for the controller must be defined here.
//
Memory32Fixed(ReadWrite, 0xf1000000, 0xfffff)
//
// The ID pin interrupts, if you are using two edge-triggered interrupts.
//
GpioInt(Edge, ActiveHigh, Exclusive, PullUp, 0, "\\_SB.GPI0", 0, ResourceConsumer, , ){0x1001}
GpioInt(Edge, ActiveHigh, Exclusive, PullUp, 0, "\\_SB.GPI0", 0, ResourceConsumer, , ){0x1002}
//
// Following is an example of a single active-both interrupt.
//
// GpioInt(Edge, ActiveBoth, Exclusive, PullUp, 0, "\\_SB.GPI0", 0, ResourceConsumer, , ){0x12}
//
//
// For a Type-C platform, you do not need to specify any interrupts here.
//
})
//
// This child device represents the USB host controller. This device node is in effect
// when the controller is in host mode.
// You may name the device whatever you want; we don't depend on it being called 'USB0'.
//
Device(USB0)
{
//
// The host controller device node needs to have an address of '0'
//
Name(_ADR, 0)
Name(_CRS, ResourceTemplate() {
//
// The controller interrupt.
//
Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ){0x10}
})
}
//
// This child device represents the USB function controller. This device node is in effect
// when the controller is in device/function/peripheral mode.
// You may name the device whatever you want; we don't depend on it being called 'UFN0'.
//
Device(UFN0)
{
//
// The function controller device node needs to have an address of '1'
//
Name(_ADR, 1)
Name(_CRS, ResourceTemplate() {
//
// The controller interrupt (this could be the same as the one defined in
// the host controller).
//
Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ){0x11}
})
}
}
下面是有关 ACPI 文件的main部分的一些说明:
- URS0 是 USB 双角色控制器的 ACPI 定义。 这是将加载 URS 驱动程序的 ACPI 设备;
- USB0 和 UFN0 是 URS0 范围内的子设备。 USB0 和 UFN0 分别表示将由 URS 驱动程序枚举的两个子堆栈,以及主机堆栈和函数堆栈。 请注意,_ADR是 ACPI 将这些设备定义与 URS 驱动程序创建的设备对象匹配的方式;
- 如果控制器对两个角色使用相同的中断,则可以在两个子设备中描述相同的控制器中断。 即使在这种情况下,中断仍可描述为“独占”;
- 可以根据需要对此 ACPI 定义文件进行添加。 例如,可以在 ACPI 定义文件中的任何设备上设置任何其他必要的方法或属性。 此类添加不会干扰 URS 驱动程序的操作。 还可以在相应设备的_CRS中描述任何堆栈中所需的任何其他资源;
URS 驱动程序将硬件 ID 分配给主机和函数堆栈。 这些硬件 ID 派生自 URS 设备的硬件 ID。 例如,如果 URS 设备的硬件 ID 为 ACPI\ABCD1234,则 URS 驱动程序为主机和函数堆栈创建硬件 ID,如下所示:
- 主机堆栈:URS\ABCD1234&HOST
- 功能堆栈:URS\ABCD1234&FUNCTION
INF 驱动程序安装包
如有必要,第三方驱动程序包可以依赖于此方案。如果你是 IHV 或 OEM,并且正在考虑提供自己的驱动程序包,请考虑以下事项:
1. URS 驱动程序包
每个平台上双角色控制器的硬件 ID 预期将添加到 URS 的收件箱 INF 中。 但是,如果由于某种原因无法添加 ID,IHV/OEM 可能会提供一个驱动程序包,其中包含需要/包含收件箱 INF 并与其硬件 ID 匹配的 INF。
在 IHV/OEM 要求筛选器驱动程序存在于驱动程序堆栈中的情况下,这是必需的。
2. 主机驱动程序包。
需要/包括 usbxhci.inf 且与主机设备硬件 ID 匹配的 IHV/OEM 提供的驱动程序包。 硬件 ID 匹配将基于上一部分所述的方案。
在 IHV/OEM 要求筛选器驱动程序存在于驱动程序堆栈中的情况下,这是必需的。目前windows正在使 URS 驱动程序为主机设备分配 XHCI 兼容 ID。
3. 功能驱动程序包
需要一个 IHV/OEM 提供的驱动程序包,它需要/包括 Ufxsynopsys.inf ,并且与外围设备硬件 ID 相匹配。 硬件 ID 匹配将基于上一部分所述的方案。
IHV/OEM 还可以在驱动程序包中包含Filter驱动程序。