USB标准请求命令格式:
/* /include/linux/usb/ch9.h */
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__ ((packed));
|
1. GetDescriptor
用于获取硬件的描述符。
要注意的是wValue是big-endian的。也就是说,获取设备描述符时,这里是big-endian的0x0001,而获取配置描述符时,这里是big-endian的0x0002。
其它两个双字节的wIndex和wLength则一般是little-endian的。
下面是一个根正苗红的GetDescriptor命令数据示例:
80 06
00 01 00 00
12 00最后两个字节即是wLength,表示要获取的描述符的长度为0x0012。
在一些保守的系统上,在枚举时会这样干:
(1) 第一次获取设备描述符时,先指定wLength为0x0008:
80 06 00 01 00 00
08 00 因为是第一次,这时还不知道Device的Endpoint0的最大包长,所以先假设为8。成功获取8个字节的设备描述符后,取其最后一个字节,即Endpoint0的最大包长。
有的USB控制器需要设置Endpoint的最大包长才能工作,所以此时即可重新设置其为正确的值。
此时获取的设备描述是不完全的,所以要二次获取。
(2) 第二次获取设备描述符,指定wLength为0x0012。
80 06 00 01 00 00
12 00 之后得到完整的设备描述符。
2. ClearFeature
当Endpoint出错Halt时,此命令可以清除Halt状态,使该Endpoint重新开始正常工作。
在这个命令中,wIndex是待操作的Endpoint的索引值。
聊举两例:
(1) 对于Out Endpoint 0x01,命令数据如下:
02 01 00 00
01 00 00 00
(2) 对于In Endpoint 0x82,命令数据如下:
02 01 00 00
82 00 00 00
另外,需注意的是,对于Bulk类型的Endpoint,当ClearFeature命令执行后,该Endpoint的Data Toggle位要重置为初始状态。
GPRS/3G上网卡从使用过的华为和中兴的GPRS/3G上网卡来看,它们都使用了所谓的Zero-CD,从USB的层面来看,也就是实现了多个Interface,某些Interface用于Mass Storage来存储驱动文件,而某些用于Modem来传送网络数据。
不知道是什么原因,它们都隐藏了其余的Interface。比如你在装有Windows系统的PC机上插上一个上网卡,第一次时,只有一个用于Mass Storage的Interface,在用户看来也就是显示出来一个U盘或光驱,里面存储的是驱动程序。然后你运行之,装好驱动,在驱动正常工作后,其余几个Interface就显现出来,于是你看到了Modem,你运行相关的软件就可以拨号上网了。
为什么要多此一举呢?是为了给用户更好的使用界面吗?那Linux及其它系统的用户情何以堪?
还好现在Linux kernel里已经包含了相当一部分上网卡的驱动,让俺等菜鸟用户不再彷徨。不过貌似中兴的是提供了一个二进制的驱动文件,虽然也不难用,但却常常使不明真相的俺等冷汗满襟。
分析了一下,其实是这样的:
(1) 用户插入USB上网卡,系统进行第一次枚举,识别出各厂商设备类型。
(2) 根据不同设备,做不同操作。
<1>华为的大部分是一个标准设备请求SetFeature,命令数据如下:
00 03 01 00 00 00 00 00
而某些则还要有个BulkOnly命令,比如EC189是通过Endpoint8发送如下命令数据:
55 53 42 43 00 00 00 00 00 00 00 00 00 00 00 11
06 00 00 00 00 00 00 00 00 00 00 00 00 00 00
<2>中兴的则是一个BulkOnly命令(通过Endpoint1发送),命令数据示例如下:
55 53 42 43 11 22 33 44 c0 00 00 00 80 00 06 9f
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
也不是所有的型号都是这样,比如MF637则是通过Endpoint1发送如下命令数据:
55 53 42 43 11 22 33 44 00 00 00 00 80 00 06 85
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
(3) 上网卡接收到这个命令后,会自动复位,进行usb bus reset。
(4) 主机系统在复位完成后,进行第二次枚举,此时全部Interface即可得到。
注:Linux kernel中有关华为上网卡的部分可查看drivers/usb/storage/下的unusual_devs.h和initializers.c这两个文件。
阅读(4332) | 评论(0) | 转发(0) |