前言
原项目中需要用到RNDIS,移植了一版,效果不是很好,项目最后没用上
现在计划重新基于CherryUSB来适配,记录一些调试笔记。
计划
因有一些USB基础,因此打算以突击的方式来推进。
开发环境
干活前先做准备工作,了解到目前CherryUSB HOST驱动适配相对较好的是STM32,刚好有个429开发板,因此就打算以这个板子来进行开发。
示例工程可以开箱即用,同时可以SWD仿真调试,应该能给后期调试带来方便。
网卡
RNDIS网卡选用的Air724UG,先插好4G SIM卡,接在电脑上确认能正常识别为RNDIS并能上网。建议抄下设备所有相关的信息,以方便后面调试时对比。
USB抓包分析仪
还在路上,现在居家办公,看起来一时半会快递不会送了
调试过程
抓包没有硬件抓包,就先来软件抓个包吧,Wireshark就可以,好用得很。
上板枚举
把我的4G网卡插到开发板上,提示
分析感觉不对,至少也得是full speed才对,low speed后面也无法切成高速。 大佬建议先插好网卡,再启动软件这边来枚举。
之前是自动启动USB的,现在改为命令启动,插好网卡后2秒后,再手动启动USB。
看起来都正常了,至少枚举过程是完成了。
项目中用的话,估计要从供电和开机过程中来找问题,不然怕起不来。
class驱动
根据现有calss驱动,照葫芦画瓢。
classwirelessu***h_rndis.c
core/u***h_core.c
发现Class:0xe0,Subclass:0x01,Protocl:0x03里面只有一个int endpoint。
真正传输数据是在Class:0x0a,Subclass:0x00,Protocl:0x00这个是CDC_DATA,
里面有bulkin和bulkout。 于是我机智的注册了2个class用于快速测试。
依样学样,在connect中alloc好class driver和bulk endpoint后。
就是试着u***h_ep_bulk_transfer(class->bulkout发了一个DHCP Discover数据包出去。
然后u***h_ep_bulk_async_transfer(bulkin的callback里面就收到一个一样长的数据包。
我凭经验感觉这就是DHCP Offer,直呼太行了,这就通了。
疯狂调试并对接相关API
有了基本通信能力后,开始整理代码,对接驱动。然后发现这收到的数据包和我发出去的完全一样。。
这不可能是DHCP Offer,看源和目标MAC地址就知道这不对,因为没有硬件分析仪,这里就假定这是设备发出的包。
于是脑补成这是网卡里面可能有类似交换机的机制,因为DHCP Discover是个广播包。
虽然这挺奇怪的,会有回环风险,但host这边并不会转发,所以回环不了。
等把驱动接口对得差不多了,通过软件dump发现所有网卡发出的数据包,根本就没有我想要的,基本都是我自己发出去的,有时连回弹也没有。
分析下来,应该是有些初始化和设置没有做。
于是逐步对接一些接口
rndis_init 发送RNDIS_MSG_INIT,用于初始化
rndis_query_oid 发送RNDIS_MSG_QUERY,查询设备的一些属性,调试下来感觉主要是MAC地址,其它参数在跑通阶段可以不用太关心。
不过RNDIS_OID_GEN_MEDIA_CONNECT_STATUS要关注下,这是反应网线连接状态。
4G网卡并没有网线,因此主要反应SIM卡和网络服务的状态。
rndis_msg_set 发送RNDIS_MSG_SET,设置设备的一些属性,主要是包过滤器。
rndis_keepalive 发送RNDIS_MSG_KEEPALIVE保活,用于在没有数据包时让USB一直有通信。
发RNDIS_MSG_KEEPALIVE时,有时会收到RNDIS_MSG_INDICATE。
此时应该再收1次RNDIS_MSG_KEEPALIVE_C。
开始不通时,以为这里是 关键,一直要等到INDICATE才行,后面换了一个android手机来测试。
发现手机根本就不发INDICATE,通过抓包发现PC在没有INDICATE时就已经在通信了,看来只需要RNDIS_OID_GEN_MEDIA_CONNECT_STATUS显示连接上就能收发数据了。
然而此时host上面的rndis网卡依然无法收到数据,甚至连有没有发出去都开始怀疑了,调试一度陷入困境,好在只是抽空研究一下,并非主要工作。
发现线索
在多次高度中,发现有时 callback中收到的数据,并不一定是我发出的。
有好几次都显示收到一串数据
00000000: 0D 0A 53 4D 53 20 52 45 41 44 59 0D 0A ..SMS READY..
看数据内容,绝对不是我发出的,且不可能是脏数据,那么至少说明这是网卡发出的。
另外看前面都有
,看起来是个文本交互。
看RNDIS的数据报头,都是二进制的结构体struct rndis_data_hdr
也不可能是这个文本啊,很是奇怪。
直到向大佬请教此问题时,说这个像是AT数据。
AT AT AT !!!
突然想起,这个网卡不就是有3个AT用的串口嘛?那应该是那边的数据,但我并没有读那几个intf啊。
像是错位了。。。
突然想到前面注册class时进行了非常规操作,然后抄过来的cdc代码中是用的[intf + 1],
用于intf[0]里面绑定intf[1]。
而我是自作聪明的写了2个class driver,那此第2个就不能用[intf + 1]。
不然往后挪1个,不正好是AT串口嘛。
把这改回,果然收到了网卡发出的数据。
至此,数据收发都通了,接下来就愉快写重构代码,整理驱动,优化性能并压测稳定性了!! 这种1个Control interface再加1个Data interface基本是标配,这块之前不了解,所以掉坑了!多沉下心来阅读理解规范就能少些弯路!
|