- Linux那些事儿之我是USB
- 肖林甫 肖季东 任桥伟
- 1212字
- 2020-08-27 00:52:23
16.端点
端点是USB数据传输的终点。看一看它在内核中的定义。
59 struct usb_host_endpoint { 60 struct usb_endpoint_descriptor desc; 61 struct list_head urb_list; 62 void *hcpriv; 63 struct ep_device *ep_dev; /* For sysfs info */ 64 65 unsigned char *extra; /* Extra descriptors */ 66 int extralen; 67 };
60行,desc,端点描述符,四大描述符的第二个隆重登场了。它也在include/linux/usb/ch9.h中定义。
312 /* USB_DT_ENDPOINT: Endpoint descriptor */ 313 struct usb_endpoint_descriptor { 314 __u8 bLength; 315 __u8 bDescriptorType; 316 317 __u8 bEndpointAddress; 318 __u8 bmAttributes; 319 __le16 wMaxPacketSize; 320 __u8 bInterval; 321 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)); 327 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~bits 3表示的就是端点号,你使用0x0f和它相与就可以得到端点号。不过,开发内核的人想得都很周到,定义好了一个掩码USB_ENDPOINT_NUMBER_MASK,它的值就是0x0f。当然,这是为了让我们更容易去读代码,也为了以后的扩展。另外,它的bit 8表示方向,输入还是输出,同样有掩码USB_ENDPOINT_DIR_MASK,值为0x80,将它和bEndpointAddress相与,并结合USB_DIR_IN和USB_DIR_OUT做判断就可以得到端点的方向。
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是轮询式总线,这个值表达了端点一种美好的期待,希望主机轮询自己的时间间隔,但实际上批不批准就是主机的事了。不同的传输类型bInterval也有不同的意义,暂时就提一下,碰到各个实际的传输类型了再去说它。
回到struct usb_host_endpoint,61行,urb_list,端点要处理的urb队列。urb是什么?它可是USB通信的主角,包含了执行USB传输所需要的全部信息,你要想和你的USB通信,就得创建一个urb,并且为它赋值,交给USB Core,然后USB Core会找到合适的主机控制器,从而进行具体的数据传输。设备中的每个端点都可以处理一个urb队列。当然,urb是内核中对USB传输数据的封装也叫抽象,协议中可不这么叫。
62行,hcpriv,这是提供给HCD(Host Controller Driver)用的。比如等时端点会在里边儿放一个ehci_iso_stream。
63行,ep_dev,这个字段是供sysfs用的。好奇的话可以去/sys下看一看。
localhost:/usr/src/linux # 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行,extra;66行,extralen,有关一些额外扩展的描述符的,和struct usb_host_interface里差不多,只是这里是针对端点的,如果你请求从设备中获得描述符信息,它们会跟在标准的端点描述符后面返回给你。