文章讲述了设备描述符在USB设备中的作用,它是一个结构体,用于存储设备的信息,如制造商、产品ID等。设备描述符的设计使得CPU能识别并处理不同设备,结构体的定义基于USB规范,确保与硬件寄存器对应。通过理解设备描述符,可以更好地了解设备如何与操作系统交互。
一直以来对设备描述符这个概念云里雾里的:
今天看《Linux那些事儿之我是USB》,书中的一句话拨开了我心中的迷雾:
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
} __attribute__ ((packed));
哦,设备描述符就是个结构体,它是根据 Spec(或者 Chip Datasheet)定义的。
这时候我先没着急打开 Spec 去看 Table 9-8 长啥样,但是已经猜的八九不离十了,肯定是一组寄存器。
我先去想,如果让我去设计一颗 IC(比如说 USB_LED 控制芯片),我
肯定得有一组寄存器(或者 e2prom)来存储以上信息,这样 CPU 就可以从我的寄存器中读取我的设备信息,进而知道我是一个什么设备,应该给我安装什么样的驱动,我具有哪些属性,后续可以对我进行哪些操作等等。
同时,CPU 也得有变量去存储我的设备信息,因为设备信息不止一个,同时它们又都有一个共性都是设备信息,所以就把这些变量统一放在一个结构体里面方便维护和使用,这个结构体就是设备描述符。
我画个图把脑海中的图像展现出来,如下:
打开 USB2.0 Spec,看到了 Table 9-8 描述的设备信息,和内核代码中定义的 struct usb_device_descriptor 完全一致,就连变量名称都是完全使用 Spec 中的。
外设有一组寄存器用来表示自身的设备信息,内核需要一个设备描述符用来存储外设的这一组设备信息。因此设备描述符中的每个成员变量对应一个寄存器,通常设备描述符这个 struct 会设置成字节对齐,以保证整个结构体大小和一组寄存器大小完全相等,且其中每个成员一一对应。