背景
以往项目使用串口通讯,通过空闲超时区分不同数据帧,但Window系统响应非实时,超时间隔不确定导致无法判断是否是完整的一帧数据,同时串口通讯还需要安装对应的驱动包,英文系统、繁体系统等可能安装失败导致用户体验差。USB HID 可以实现免驱(使用中断方式进行数据传输),但通讯速率慢(FS 62.5KB/s 受硬件影响)会64字节分包发送数据,导致上位机很难区分一包完整数据。针对以上存在的问题USB 虚拟串口能很好的提升通讯速率(FS 800KB/S 受硬件影响)但需要安装芯片驱动,针对不同环境可能会导致安装驱动失败问题。WinUsb可以很好的解决以上问题、既能快速通讯、又能即插即用。
WinUsb简介
WCID是WinUsb设备功能的扩展,由Microsoft在Windows8开发人员预览版期间提出,WinUsb自Windows XP SP2以来一直是Windows一部分的功能
WinUsb设备是一种通用串行总线(USB)设备,其固件定义了某些Microsoft操作系统(OS)特征描述符,这些描述符将兼容ID报告为"WINUSB"。WinUsb设备的用途是让Windows将Winusb.sys作为设备的功能驱动程序载入,而无需自定义INF文件。对于WinUsb设备,你无须为设备分发INF文件,这大大简化了驱动程序安装过程。截至2012年5月,从Windows Vista开始的所有平台上都提供了自动 WinUSB WCID 驱动程序。在 Windows 8 或更高版本地系统上已经集成了该驱动程序,这意味着Windows 8 或更高版本地系统上不需要安装驱动程序,系统自动会匹配WinUSB驱动,而对于Vista、Windows7、XP系统,可以通过一些第三方软件(如Zadig)来安装或生成WCID版本的驱动程序,同样只需要安装一次WCID版本的驱动软件,以后所有WCID设备都可以使用该驱动,间接实现了免驱。
WinUsb组成
WinUSB包括两大部分,分别为内核部分和应用层部分:
- 内核部分,主要是WinUSB.sys,该内核模式驱动程序,可以作为过滤器或功能驱动程序安装在USB设备的内核模式驱动协议栈中。
- 应用层:winusb.dll,其导出函数声名在winusb.h头文件中。当 Winusb.sys 作为设备的功能驱动程序安装时,应用程序可以使用这些功能与它进行通信
WinUsb的版本支持
- Windows 7 在基于 x86、基于 x64 和基于 Itanium 的系统上支持 WinUSB。
- 较新版本的 Windows 在基于 x86 和基于 x64 的系统上支持 WinUSB。
- WinUSB 支持从 Windows 8 开始支持同步传输。
WinUsb限制条件
WinUSB有许多限制条件,一般来说注意以下几点即可
- WinUSB不支持Windows 2003 ( 32bit/64bit );
- WinUSB不支持Windows XP 64位(可以通过第三方驱动支持);
- USB设备版本必需是2.0或2.0以上,WinUSB不支持USB1.0和1.1。
WinUsb通讯速率有多快(USB FS 800KB/S)
我们查看附图1:下载同样的数据WinUsb下载速度是HID的2倍还要多。
通过枚举信息来看 WinUsb Transfer Type : Bulk
设备如何被枚举成WINUSB 设备
WinUsb是在CDC虚拟串口基础上进行实现免驱功能,前期CDC虚拟串口必须通讯正常、方可通过修改枚举成WinUsb设备。关于CDC虚拟串口相关技术这里不做介绍。
WIUSB 设备枚举关键信息
设备枚举成WINUSB的三个关键信息
- OS字符串描述符 --判断设备是否支持 WCID设备
- 扩展兼容ID OS功能描述符 --判断设备是否为WinUsb设备
- 扩展属性OS功能描述符 -- 获取WinUsb设备GUID
支持OS 字符串描述
当有USB设备插入,系统会向设备索取设备描述符。根据设备描述符中的bcdUSB版本号判断是否检索0xEE位置的OS设备字串描述符,如果bcdUSB版本号大于等于2.0,则系统会检索0xEE位置的OS设备字串描述符,支持WinUSB的OS描述如下:
如果0xEE处的OS描述符不存在或者描述格式不正确,系统将设置osvc值为0x0000,表示该USB设备不是WCID设备。如果OS描述正确,系统将osvc设置为0x##。
获取该描述符的作用主要是:判断设备是否WCID设备,如果不是OSVC 赋值0x0000 如果是 OSVC 赋值Vendor Code 主要判断”MSFT100”字符串
设置兼容ID特征描述符
在获取到osvc为有效值的前提下,系统将进一步获取兼容ID特征描述符,索引号为0x04,兼容ID特征描述符包含紧跟一个或多个功能部分的标题部分,具体取决于是否是复合设备。标题部分指定整个描述符的长度、功能部分的数量以及版本号。对于非复合设备,标题后紧跟一个仅与设备的接口关联的功能部分。该部分的compatibleID字段必须指定"WINUSB"作为字段值。复合设备有多个功能部分。每个功能部分的compatibleID字段必须指定"WINUSB"。兼容ID特征描述符格式如下:
扩展属性描述符
最后是添加扩展属性描述符,注册设备接口GUID,包含紧跟一个或多个自定义属性部分的标题部分,索引号为0x05。标题部分描述整个扩展属性描述符,包含其总长度、版本号以及自定义属性部分的数量。WinUSB应用程序正是通过GUID来检索对应的USB设备,并进行访问,详细定义如下表所示:
注意点:
设备枚举过程中,如果以上都进行了修改、但还是出现感叹号 提示枚举失败。
下载PStool工具包、通过管理员身份运行、进入PStool目录
执行:psexec.exe -i -d -s regedit.exe
删除VID、PID之前的枚举信息
市场芯片移植WinUsb对比
- STM32(意法半导体芯片) 使用较多、相关文档总结、参考资料多
- GD32(兆易国产芯片) WinUsb移植资料几乎没有,驱动库也有点小bug
- AT32(雅特力国产芯片) 官方提供了WInUsb例程 入手快
附图1:
雅特力WinUsb、HID下载速度对比:
AT Link WinUSB下载速度提升对比_哔哩哔哩_bilibili
附图2:
使用工具zadig进行安装winusb
以管理员方式运行zadig-2.4.exe,然后在菜单的选择中选择列出所有设备。
这会软件会枚举系统中所有的USB设备,并显示在下列组合对话框中。我们选中我们需要安装winusb的设备,然后点击ReInstallDriver按钮进行安装。
如本人选中一个USB扬声器设备,其信息如下
查看设备的驱动信息:
注册表中的信息如下:
参考:
STM32 WinUSB(WCID)免驱高速通信 20M/s(附详细测试)_bingwueyi的博客-CSDN博客
https://www.cnblogs.com/yanye0xff/p/16710614.html
GD32移植WinUsb 成功例程如下:
https://download.csdn.net/download/qq_35257512/87838361?spm=1001.2014.3001.5503
STM32移植WinUsb成功例程如下:
https://download.csdn.net/download/qq_35257512/87755345?spm=1001.2014.3001.5503