关闭

Linux那些事儿 之 戏说USB(18)端点

标签: linuxdescriptorstructinterfaceaudiolist
4640人阅读 评论(1) 收藏 举报
分类:
于丹说,生与死,是人生起始的两个端点。
于丹?不会不知道这个人吧,我哭。百家讲坛继易中天之后放的第二颗大卫星,最开始讲论语一下子就红了的那个,接着又讲了庄子。咱可以不喜欢但不可以落后,是不。她在《庄子心得》的谈笑论生死里说了个寓言,我这儿给转一下。
兄弟两个人,他们家住在一座摩天大楼的第80层。这天,两个人深夜回家,恰好忘记了看通知,电梯停了。
  兄弟俩背着沉重的大背包,在楼底下商量一下,决定一鼓作气,爬楼梯回家。两人抖擞精神,开始爬楼。爬到20楼的时候,开始觉得背包很重了。两人商量,决定把背包存在20楼,到时候再回过头来取。卸下了背包,两个人觉得很轻松,说说笑笑地继续往上爬。
  爬到40楼的时候,两人已经很累了,就开始互相抱怨指责。哥哥说:你为什么不看通知啊?弟弟说:我忘了看通知这件事,你怎么不提醒我昵?两个人就这样吵吵闹闹,一路吵到60层。
  到了这时候,两人实在疲惫不堪,终于懒得吵了,觉得还是应该安安静静地继续爬楼。当他们终于爬完了最后20层,来到了家门口的时候,两个人互相一看,不约而同想起了一件事:钥匙忘在20楼了,在背包里。
  其实,这说的就是人的一生。
这是于丹比的人生,咱们的不是,她和咱们隔了老远去了,咱们是前二十年无忧无虑,谈谈情说说爱没啥包袱,说说笑笑的爬了20年后,发现人生是需要找工作,需要赚钱,需要买房子的,于是自己捡的,或者被和谐过来的,一个接一个的包袱往身上丢,越来越沉重的向上爬,爬到40年、60年怎么样?不用去想它,也就一个字,累,两个字,很累,三个字,非常累,四个字,累死人了。
折腾USB spec的同志应该不会读过庄子,也不会知道于丹这个人物,可别人也知道端点,于是端点成了USB数据传输的终点。看看它在内核里的定义
46 /**
47 * struct usb_host_endpoint - host-side endpoint descriptor and queue
48 * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder
49 * @urb_list: urbs queued to this endpoint; maintained by usbcore
50 * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH)
51 *      with one or more transfer descriptors (TDs) per urb
52 * @ep_dev: ep_device for sysfs info
53 * @extra: descriptors following this endpoint in the configuration
54 * @extralen: how many bytes of "extra" are valid
55 *
56 * USB requests are always queued to a given endpoint, identified by a
57 * descriptor within an active interface in a given USB configuration.
58 */
60         struct usb_endpoint_descriptor desc;
61         struct list_head                urb_list;
62         void                            *hcpriv;
63         struct ep_device                *ep_dev;        /* For sysfs info */
65         unsigned char *extra;   /* Extra descriptors */
66         int extralen;
67 };
60行,desc,端点描述符,四大描述符的第二个隆重登场了。它也在include/linux/usb/ch9.h里定义
312 /* USB_DT_ENDPOINT: Endpoint descriptor */
314         __u8 bLength;
315         __u8 bDescriptorType;
317         __u8 bEndpointAddress;
318         __u8 bmAttributes;
319         __le16 wMaxPacketSize;
320         __u8 bInterval;
322         /* NOTE: these two are _only_ in audio endpoints. */
323         /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
324         __u8 bRefresh;
325         __u8 bSynchAddress;
326 } __attribute__ ((packed));
328 #define USB_DT_ENDPOINT_SIZE            7
329 #define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
这个结构与spec Table 9.13是一一对应的,0号端点仍然保持着它特殊的地位,它没有自己的端点描述符。
314行,bLength,描述符的字节长度,数一下,前边儿有7个,后边儿又多了两个字节,那是针对音频设备扩展的,不用管它,紧接着struct usb_host_endpoint定义的就是两个长度值的定义。
315行,bDescriptorType,描述符类型,这里对于端点就是USB_DT_ENDPOINT,0x05。
317行,bEndpointAddress,这个字段描述的信息挺多的,比如这个端点是输入端点还是输出端点,这个端点的地址,以及这个端点的端点号。它的bits 0~3表示的就是端点号,你使用0x0f和它相与就可以得到端点号。不过,开发内核的同志想的都很周到,定义好了一个掩码USB_ENDPOINT_NUMBER_MASK,它的值就是0x0f,当然,这是为了让咱们更容易去读他们的代码,也为了以后的扩展。另外,它的bit 8表示方向,输入还是输出,同样有掩码USB_ENDPOINT_DIR_MASK,值为0x80,将它和bEndpointAddress相与,并结合USB_DIR_IN和USB_DIR_OUT作判断就可以得到端点的方向。
42 /*
43 * USB directions
44 *
45 * This bit flag is used in endpoint descriptors' bEndpointAddress field.
46 * It's also one of three fields in control requests bRequestType.
47 */
48 #define USB_DIR_OUT                     0               /* to device */
49 #define USB_DIR_IN                      0x80            /* to host */
318行,bmAttributes,属性,总共8位,其中bit1和bit0 共同称为Transfer Type,即传输类型, 00 表示控制,01 表示等时,10 表示批量,11 表示中断。前面的端点号还有端点方向都有配对儿的掩码,这里当然也有,就在struct usb_endpoint_descriptor定义的下面
338 #define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
339 #define USB_ENDPOINT_XFER_CONTROL       0
340 #define USB_ENDPOINT_XFER_ISOC          1
341 #define USB_ENDPOINT_XFER_BULK          2
342 #define USB_ENDPOINT_XFER_INT           3
319行,wMaxPacketSize,端点一次可以处理的最大字节数。比如你老板比较看重你,一次给你交代了几个任务,于是你大声的疾呼,神啊,我一次只能做一个,当然神是听不到的,怎么办那,加班加点儿,一个一个的分开做呗。端点也是,如果你发送的数据量大于端点的这个值,也会分成多次一次一次来传输。友情提醒一下,这个字段还是有点门道的,对不同的传输类型也有不同的要求,日后碰到了再说。
320行,bInterval, USB是轮询式的总线,这个值表达了端点一种美好的期待,希望主机轮询自己的时间间隔,但实际上批准不批准就是host的事了。不同的传输类型bInterval也有不同的意义,暂时就提这么一下,碰到各个实际的传输类型了再去说它。不是俺捂盘惜售,而是初次照面儿就对人家寻根问底的不大礼貌,这里先留个印象,有缘总会再相见的。
回到struct usb_host_endpoint,61行,urb_list,端点要处理的urb队列。urb是什么?这年头儿钱不多就是新名词儿多,是个新名词爆炸的时代,不过urb可是usb通信的主角,它包含了执行urb传输所需要的所有信息,你要想和你的usb通信,就得创建一个urb,并且为它赋好值,交给咱们的usb core,它会找到合适的host controller,从而进行具体的数据传输。设备中的每个端点都可以处理一个urb队列,当然,urb是内核里对usb传输数据的封装也叫抽象吧,协议里可不这么叫。基于urb特殊的江湖地位,接下来的哪一个黄道吉日里,我会对它大书特书的。
62行,hcpriv,这是提供给HCD(host controller driver)用的。比如等时端点会在里边儿放一个ehci_iso_stream,什么意思?郑板桥告诉我们要难得糊涂。
63行,ep_dev,这个字段是供sysfs用的。好奇的话可以去/sys下看一看
localhost:/usr/src/linux/drivers/usb/core # ls /sys/bus/usb/devices/usb1/ep_00/
bEndpointAddress bmAtributes  direction   subsystem    wMaxpacketSize
bInterval        dev           interval    type
bLength          device         power      uevent
ep_00端点目录下的这些文件从哪儿来的?就是在usb_create_ep_files函数里使用ep_dev创建的。
65行,extra66行,extralen,有关一些额外扩展的描述符的,和struct usb_host_interface里差不多,只是这里的是针对端点的,如果你请求从设备里获得描述符信息,它们会跟在标准的端点描述符后面返回给你。 
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2430146次
    • 积分:7523
    • 等级:
    • 排名:第3048名
    • 原创:297篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2042条
    博客专栏