为了简化USB设备的开发和接入到PC系统,微软开发了WinUSB,可以将Winusb.sys作为设备功能驱动程序安装,并提供WinUSB API供应用程序访问设备。一直以来,除了USB HID设备,其他类型的设备在WINDOWS环境下需要安装驱动程序才能工作……

为了简化USB设备的开发和接入到PC系统,微软开发了WinUSB,可以将Winusb.sys作为设备功能驱动程序安装,并提供WinUSB API供应用程序访问设备。一直以来,除了USB HID设备,其他类型的设备在WINDOWS环境下需要安装驱动程序才能工作。要实现USB设备免驱,就只能使用HID设备。而HID设备传输速度慢,在有些场合必须使用Bulk类型进行批量传输时,就必须使用第三方驱动,或者自己开发一个驱动,使得项目开发非常麻烦。现在好了,自从微软推出了WinUSB,在微软的最新操作系统上实现简单的Bulk类型批量传输也变得非常的方便快捷,在研发过程当中或者一些对于差异化要求不高的场合,是非常适用且容易实现的。本文致力于实现一个最简单的WinUSB通信系统,以满足此类需求。

如何让嵌入式设备枚举成WinUSB设备

系统通过USB描述符来确定以何种USB Class类型来工作。如果希望WINDOWS能够将嵌入式设备识别为WinUSB设备,则其描述符至少应当包含以下字段:

1、支持 OS 字符串描述符:

为了让 USB 驱动程序堆栈了解设备支持扩展的特征描述符,设备必须定义存储在字符串索引 0xEE 处的 OS 字符串描述符。在枚举过程中,驱动程序堆栈查询字符串描述符。如果存在描述符,驱动程序堆栈会假定设备包含一个或多个 OS 特征描述符和检索这些特征描述符所需要的数据。检索的字符串描述符具有 bMS_VendorCode 字段值。该值为1表示USB驱动程序堆栈必须用来检索扩展特征描述符的供应商代码。

#define bMS_VendorCode ( 0x01 )
// "MSFT100" : index : 0xEE : langId : 0x0000
const U8 OS_StringDescritpor[ ] =
{ 0x12, 0x03, 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, bMS_VendorCode, 0 };

2、设置兼容ID特征描述符:

const U8 WINUSB_ExtendedCompatId_Descritpor[ ] =
{
0x28, 0x00, 0x00, 0x00, // dwLength
0x00, 0x01, // bcdVersion
0x04, 0x00, // wIndex
0x01, // bCount
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved[7]
0x00, // bFirstInterfaceNumber
0x01, // RESERVED ( 0x01 )
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compactiableID[8]
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompactiableID[8]
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved[6]
};
注:WinUSB还支持复合设备,对于单一传输类型最简系统,我们忽略复合设备的要求即可。compatibleID字段必须指定 "WINUSB" 作为字段值。其他可以根据需求更改。

3、注册设备接口 GUID描述符:

该描述符用于区分不同的WinUSB设备。

const U8 WINUSB_ExtendedProperty_InterfaceGUID_Descritpor[ ] =
{
0x8E, 0x00, 0x00, 0x00, // dwTotalSize = Header + All sections
0x00, 0x01, // bcdVersion
0x05, 0x00, // wIndex
0x01, 0x00, // wCount
0x84, 0x00, 0x00, 0x00, // dwSize -- this section
0x01, 0x00, 0x00, 0x00, // dwPropertyDataType
0x28, 0x00, // wPropertyNameLength 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0x00,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0, 'G',0,'U',0,'I',0,'D',0,0,0,
0x4E, 0x00, 0x00, 0x00, // dwPropertyDataLength : 78 Bytes = 0x0000004E
'{',0,'1',0,'2',0,'3',0,'4',0, '5',0,'6',0,'7',0,'8',0,'-',0,'1',0,'2',0,'3',0,'4',0,'-',0,'1',0,'3',0,'4',0,'4',0,'-',0,'1',0,'2',0,'3',0,'4',0,'-',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,'A',0,'B',0,'C',0,'}',0,0,0
};// bPropertyData : WCHAR : L"{12345678-1234-1234-1234-123456789ABC}"

4、端点描述符:

按实际的需求的配置端点数量和类型,即可完成嵌入式设备的描述符配置了。

一般固件程序可以通过MCU厂家提供的范例程序进行修改,这里省略USB固件功能的说明。只要包含以上三个描述符中的必须的字段,就可以成功枚举成USB Device。枚举成功后在设备WINDOWS设备管理器中可看到类似设备,如下图1所示。
20181127-windows.gif
图1 成功枚举为USB Device

如何编写PC应用程序与嵌入式设备进行USB通信

PC机软件相对来说比较简单,并且微软官方也给出了示例代码。唯一需要注意的是,对应的软件程序获取WinUSB设备句柄的GUID参数,需要与嵌入式设备的描述符中的GUID保持一致。GUID是WinUSB用以区分设备的唯一标志。GUID,是Globally Unique Identifier的简称,翻译为全局唯一标识符,是一种由算法生成的二进制数据,长度为128位的数字标识符。

具体实现步骤如下:

1、创建设备的文件句柄:

调用 SetupDiGetClassDevs 获取设备信息集的句柄;调用 SetupDiEnumDeviceInterfaces 枚举设备信息集中的设备接口并获取有关设备接口的信息;调用 SetupDiGetDeviceInterfaceDetail 获取设备接口的详细信息,所获取的信息通过SP_DEVICE_INTERFACE_DETAIL_DATA结构返回。由于该结构大小无法提前获取,故需连续两次调用该函数,第二次调用时接口详细信息将填充到根据第一次调用返回值所确定大小的该缓冲区,通过缓冲内该结构的DevicePath成员中可获得“设备路径”。

2、获取设备的 WinUSB 接口句柄:

调用 WinUsb_Initialize通过传递在创建设备的文件句柄中创建的文件句柄。

3、查询设备以获取 USB 描述符:

接下来,查询设备以获取特定于 USB 的信息,如设备速度、接口描述符、相关端点及其管道。调用 WinUsb_QueryDeviceInformation 从设备的设备描述符请求信息。调用 WinUsb_QueryInterfaceSettings 并传递设备的接口句柄,以获得对应的接口描述符。调用 WinUsb_QueryPipe 获取有关每个接口每个终结点的信息。此步骤不是必须的,因为端点方向及传输特性由嵌入式设备描述符决定,是已知的。

4、向默认端点发送控制传输:

此步骤也不是必须的。一般都不通过默认端点发送有效载荷。

5、发送 I/O 请求:

将数据发送到设备的批量输入和批量输出端点,这些端点点可分别用于读取请求和写入请求。调用 WinUsb_ReadPipe 从设备的批量输入端点读取数据。调用 WinUsb_WritePipe 通过批量输出端点将数据写入设备。在嵌入式设备的输出端点内写入数据之后,就可以在PC端读出数据。反之,如果在PC端对嵌入式设备的输入端点写入数据,则嵌入式设备会产生一个USB端点写入事件,具体如何捕捉该事件,则由MCU厂家的产品硬件决定,产生相应的中断信息,供中断服务程序来判断。一般而言,芯片厂家会提供MCU的USB通信基础范例程序,在其基础上做简单的修改和适配即可。

6、释放设备句柄

在完成对设备的所有必要的调用之后,释放设备的文件句柄和 WinUSB 接口句柄。CloseHandle 释放由 CreateFile 创建的句柄。

WinUsb_Free 释放由 WinUsb_Initialize 返回的设备的 WinUSB 接口句柄。

至此,已经完成了嵌入式设备端固件的USB代码移植和PC端应用程序的编写,就可以实现USB免驱设备的通信方式了。

阅读全文,请先
您可能感兴趣
华为Mate 70系列中的Mate 70搭载了麒麟9010芯片,而Mate 70 Pro/Pro+/RS则首发了麒麟9020芯片。近日,百万粉丝的网红博主@杨长顺维修家 对华为Mate 70 RS进行了拆解……
此次发布的iQOO Neo10系列不仅在性能上进行了全面升级,还在用户体验方面引入了多项创新技术,其中再次采用汇顶科技超声波指纹方案,引发了广泛关注。
今年进博会上,瑞萨展示了不少AI相关的技术。在我们与赖长青的对谈中,他也解读了AI对于瑞萨而言意味着什么...
根据柏能科技集团官网的最新信息,公司已将总部从香港迁往新加坡,成立PC Partner Singapore PTE Ltd,并已于15日在新加坡证券交易所(SGX)成功挂牌上市。
尽管在生态系统建设、软件支持和安全性问题等方面,RISC-V仍需不断努力和完善,但凭借简洁高效、灵活多样的特点,RISC-V目前已经在嵌入式系统、云计算与大数据、人工智能与机器学习、物联网与边缘计算等领域展现出了强大的生命力和广阔的发展前景。
iPhone 16系列一经发售,除了被拆解分析机构盯上,也因为近期的黎巴嫩寻呼机爆炸事件,被一些造谣者盯上。网上出现了大量“禁止携带苹果手机”的通知,正好多家机构日前对iPhone 16进行了拆解,我们借此文还看看里面有没有引爆装置……
目前,智能终端NFC功能的使用频率越来越高,面对新场景新需求,ITMA多家成员单位一起联合推动iTAP(智能无感接近式协议)标准化项目,预计25年上半年发布1.0标准,通过功能测试、兼容性测试,确保新技术产业应用。
中科院微电子所集成电路制造技术重点实验室刘明院士团队提出了一种基于记忆交叉阵列的符号知识表示解决方案,首次实验演示并验证了忆阻神经-模糊硬件系统在无监督、有监督和迁移学习任务中的应用……
C&K Switches EITS系列直角照明轻触开关提供表面贴装 PIP 端子和标准通孔配置,为电信、数据中心和专业音频/视频设备等广泛应用提供创新的多功能解决方案。
投身国产浪潮向上而行,英韧科技再获“中国芯”认可
今日,长飞先进武汉基地建设再次迎来新进展——项目首批设备搬入仪式于光谷科学岛成功举办,长飞先进总裁陈重国及公司主要领导、嘉宾共同出席见证。对于半导体行业而言,厂房建设一般主要分为四个阶段:设备选型、设
12月18日,珠海京东方晶芯科技举行设备搬入仪式。插播:加入LED显示行业群,请加VX:hangjia188在10月31日,珠海京东方晶芯科技有限公司发布了Mini/Micro LED COB显示产品
来源:IT之家12 月 18 日消息,LG Display 韩国当地时间今日宣布,已将自行开发的“AI 生产系统”投入到 OLED 生产线的日常运行之中,该系统可提升 LG Display 的 OLE
对于华为来说,今年的重磅机型都已经发完了,而明年的机型已经在研发中,Pura 80就是期待很高的一款。有博主爆料称,华为Pura 80将会用上了豪威OV50K传感器,同时电池容量达到5600毫安时。至
阿里资产显示,随着深圳柔宇显示技术有限公司(下称:“柔宇显示”)旗下资产一拍以流拍告终,二拍将于12月24日开拍,起拍价为9.8亿元。拍卖标的包括位于深圳市龙岗区的12套不动产和一批设备类资产,其中不
又一地,新型储能机会来了?■ 印度:2032储能增长12倍,超60GW据印度国家银行SBI报告,印度准备大幅提升能源存储容量,预计到2032财年将增长12 倍,超60GW左右。这也将超过可再生能源本身
 “ 担忧似乎为时过早。 ”作者 | RichardSaintvilus编译 | 华尔街大事件由于担心自动驾驶汽车可能取消中介服务,Uber ( NYSE: UBER ) 的股价在短短几周内从 202
扫描关注一起学嵌入式,一起学习,一起成长在嵌入式开发软件中查找和消除潜在的错误是一项艰巨的任务。通常需要英勇的努力和昂贵的工具才能从观察到的崩溃,死机或其他计划外的运行时行为追溯到根本原因。在最坏的情
 “ AWS 的收入增长应该会继续加速。 ”作者 | RichardSaintvilus编译 | 华尔街大事件亚马逊公司( NASDAQ:AMZN ) 在当前水平上还有 38% 的上涨空间。这主要得益
亲爱的企业用户和开发者朋友们距离2024 RT-Thread开发者大会正式开幕仅剩最后3天!还没报名的小伙伴,抓紧报名噢,12月21日不见不散!大会时间与地点时间:2024年12月21日 9:30-1