Chinaunix首页 | 论坛 | 博客
  • 博客访问: 61865
  • 博文数量: 16
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 17:12
文章分类
文章存档

2010年(10)

2009年(6)

我的朋友

分类: 嵌入式

2009-12-30 17:45:06

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) |
给主人留下些什么吧!~~