在MH2103上如何将usb cdc类虚拟出来的串口在Windows上使用固定串口号
最近遇到一个使用场景,带来了这个需求:
项目中使用usb cdc虚拟了一个usb串口,用来作为代码升级和图片资源下载使用,速度比物理串口要快很多。
但是官方usb cdc使用了默认的实现方式,每一个板子接入Windows系统的时候,都会出现一个新的串口号,这样子在批量升级或者下载资源的时候,随着板子的接入增多,串口号就会从com2一直飙升下去,直到com98,com99等等,在使用串口工具选择串口的时候非常麻烦,而且也容易和其他串口混淆(因为每一次接入一块新的板子的时候,串口号都不一样)。
那么,面对这种情况,我能不能让每一块板子接入Windows的时候都是同一个串口号呢?比如第一次接入Windows系统分配的是串口号10,以后这个类型的板子接入系统都是串口号10,那这样一来我所有的板子升级的时候就比较舒服了。
说干就干,查阅了一下Windows分配串口号的原理,翻阅了一下mh2103 usb cdc类实现的代码,轻松解决这个问题.
我们先看看Windows分配串口号的原理:
Windows会根据usb cdc类上报的供应商id和产品id,以及序列号来分配和标识一个com设备,如果每一个接入设备的这三个信息都相同,它会认为是同一个设备接入,会使用相同的驱动。
如上图,我们看到Windows描述了一个usb设备:USB\VID_0483&PID_5740\760C5577BB06
他们的意义如下:USB说明是一个usb类设备,然后使用vid(vendor id)和pid(product id)VID_0483&PID_5740作为一个子类,最后用序列号760C5577BB06来区别同一个类别产品的不同产品。
我们要解决这个问题的关键就是让设备上报的这上个数据在每一块板子保持一致就可以了。
先看看usb cdc类描述符的两个数据结构:
cdc类的设备描述符,有固定的vid和pid,和Windows上展现的一致的。序列号在这个结构中是一个字符串描述符的索引值,它最后会来自于另外一个数据结构,动态生成。
设备最后会响应主机的获取字符串描述符命令,上报这个结构的数据:
我们现在需要做的就是将Virtual_Com_Port_StringSerial这个结构的后面的"stm32"的序列号内容进行固定和替换。
我们查看代码,如下函数正是动态修改序列号的函数:
原始代码会读取芯片的电子签名ID(这个id每一片芯片都会不一样,具有唯一性):
然后做一个简单的运算后从新赋值Virtual_Com_Port_StringSerial结构的内容,最后运算的结果和Windows显示的序列号一致。
如上图我们将它的内容固定下来后,Windows每一次都会读取到相同的序列号,从而“被欺骗”,以为我们是同一个cdc设备接入。最终完成我们的初始需求。
深圳市新龙微电子科技有限责任公司在使用兆讯芯片开发相关产品的时候,进行了大量的适合批量化的代码改进和工具完善(下载,升级,图片处理,压缩,资源生成等),为客户提供定制化的产品开发,提供优化后的二次开发SDK,加速产品应用。淘宝(搜索店铺新龙微)也提供了相关的开发板可以用于前期功能评估。