webusb的开发记录
写在前面的话
webusb简单的说就是可以通过web网页对USB设备进行通讯,当USB设备插上PC机时,可以连接到特定的网路。
所有的USB的开发就是配置一系列的USB描述符,当然webusb也不例外,我就是因为在开发的过程中忽略了一些描述符的配置,导致在开发过程中花费了大量的时间,好在最终问题都已解决。
USB的开发从描述符说起
1、BOS描述符
在webusb的开发中,第一个关于webusb非常重要的描述那便是这个描述符了。PC机要获取WebUSB Platform Capability Descriptor便要通过BOS描述符来实现,可以说WebUSB Platform Capability Descriptor是PC机识别该设备是否为webusb的一个关键描述符。
官方给该描述符定义翻译过来便是:设备通过在其二进制对象存储(BOS)中包含以下平台描述符来宣布对 WebUSB 命令集的支持。
关于获取这个描述符PC端的请求是:
关于这个请求的描述,上面的表格已经描述的非常清楚,这里就不在赘述,如果不懂可以翻看一下USB之类的书籍。
这个请求的应答分为两部分,即BOS描述符 + WebUSB Platform Capability Descriptor,先说BOS描述符部分的定义:
下表是WebUSB Platform Capability Descriptor的定义:
在这个描述符里面有两个要注意的地方,即bVendorCode和iLandingPage,bVendorCode就是告诉PC机后面关于发出 WebUSB 请求(Vendor request)的bRequest,所以这个值很重要。但是有一点需要注意的是,WebUSB 请求(Vendor request)的bRequest不单单和这个值有关系,还和另外一个描述符(Microsoft OS Descriptor)有关,后面在讲述Microsoft OS Descriptor时可以留意一下。iLandingPage我特意在上面的截图中将英文解释一并贴出来,这个字段我的理解是当不为0时,当设备每次插入PC机时,会弹出一个弹窗,询问我们是否连接相应的网页。
2、Microsoft OS Descriptor
这是一个很关键的描述符,我前文提到忽略而导致花费很长时间便是这个描述符了,之所以忽略是因为对于于一个PID和VID的设备,PC机只要在第一次插入的时候会去获取该描述符,如果第一次获取不到该描述符,那么PC机就不认该设备为webusb设备,而且后续再重新插入也不会再重新获取该描述符(除非在注册表中删除,位置"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\ ”)。只要不是第一次插入,你去截取USB的枚举信息,你会发现PC的所有描述符请求都应答了,并且应答的都还没有问题,但是PC机就是不能识别该设备。
该描述符的请求如下:
需要注意的是这是个字符串请求(wValue的高字节03代表是字符串,低字节0xEE是字符串的索引值)。
该请求的应答如下:
其他没什么可说的,只有一个字段bMS_VendorCode,这个字段要和上文WebUSB Platform Capability Descriptor中的bVendorCode保持一致,作为后面请求(Vendor request)的bRequest字段。
3、Extended Compat ID OS Feature Descriptor
该描述符的请求如下:
该描述符的应答:
Extended compat ID OS feature descriptor分为两个部分
-
一个固定长度的报头部分(header section),它包含关于整个描述符的信息,包括版本号、功能部分的数量和描述符的总长度。
-
一个或多个固定长度的功能部分(function sections),紧跟在报头部分(header section)之后。每个功能部分包含设备的数据,或单个接口、功能或单功能接口组的数据。
4、URL Descriptor
该描述符是PC机请求设备的URL的,也就是设备要告诉PC机该设备要连接的那个网页。此描述符包含一个 URL,由 Get URL 请求返回。
请求如下:
应答如下:
bDescriptorType:0x03,代表WEBUSB_URL
bScheme: 0 代码URL是以 “http://” 开头,1 代表以"https://"开头。
URL: 要连接网络的URL,比如:www.tinyusb.org/examples/webusb-serial
5、其他描述符
像设备秒速符,配置描述符,字符串描述符都是常规描述符,没有什么可说的,这里也就不在赘述。要说的一点就是webusb的配置描述符里面没有设备类相关的描述,就是配置描述符 + 接口描述符 + 端点描述符。
6、Linux下的一些处理
在linux下如果要识别webusb还需要做一些处理,以Ubuntu为例:
sudo echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"cafe\", ATTRS{idProduct}==\"4000\", MODE=\"0660\", GROUP=\"plugdev\"" >> /etc/udev/rules.d/20-Token.rules
udevadm trigger
udevadm control --reload-rules
以上是在USB插入时添加一个规则,我们只需要将PID和VID修改为我们自己设备的PID和VID即可。
写在最后
一般上述描述符配置好后,在PC请求后能正确应答的话,设备插上PC机便可以进行网络连接。但是要注意一点的是,webusb毕竟是新鲜的东西,支持的系统要在win8.1以上(这边没有细查,记得好像是),并且chrome浏览器的版本也有要求。
最后贴一张设备插入后的完整枚举过程:
图中1处请求BOS Descriptor。
图中2处请求Microsoft OS Descriptor。
图中3处请求Extended Compat ID OS Feature Descriptor。0x55是我在BOS Descriptor和Microsoft OS Descriptor中自定义的一个值。
图中4处请求URL Descriptor。本例中设置的是“www.tinyusb.org/examples/webusb-serial”
最后再贴一张连接成功的效果图(向网页发送了一包“hello world !”):