在总结完USB设备操作的具体实现时候,再对《Linux设备驱动程序》的第十三章—USB驱动程序,的内容进行简单总结。这个章节详细描述了Linux的USB设备驱动程序以及USB核心之间的接口信息。
USB设备包括了设备、配置、接口、端点四部分,文章也是按照这个顺序进行讲述的,下面直接进入主题。
13.1.1端点
Usb最近本的通讯形式就是端点,USB 端点只能在一个方向承载数据, 或者从主机到设备(称为输出端点)或者从设备到主机(称为输入端点). 端点可看作一个单向的管道.
在内核中使用struct usb_host_endpoint结构进行端点的描述,其中还包含一个非常重要的结构struct usb_endpoint_descriptor,这个结构包含的真正端点的信息,其结构对端点信息的定义与USB协议相符。
struct usb_endpoint_descriptor的完整定义如下:
Include/linux/usb/ch9.h(usb2.0协议P269 chapter9.6.6)
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress; //This is the USB address of this specific endpoint.
__u8 bmAttributes; //Thisis the type of endpoint. the endpoint is of type USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, or of type USB_ENDPOINT_XFER_INT. These macros define a isochronous, bulk, and interrupt endpoint.
__le16wMaxPacketSize; //This is themaximum size in bytes that this endpoint can handle at once.
__u8 bInterval; //Ifthis endpoint is of type interrupt, this value is the interval setting for theendpoint
/*NOTE: these two are _only_ in audioendpoints. */
/*use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
13.1.2. 接口
USB 端点被绑在接口中. USB 接口只处理一类 USB 逻辑连接, 例如一个鼠标, 一个键盘, 或者一个音频流. 一些 USB 设备有多个接口, 例如一个 USB 扬声器可能有 2 个接口: 一个 USB 键盘给按钮和一个 USB 音频流. 因为一个 USB 接口表示基本的功能, 每个 USB 驱动控制一个接口;
USB 接口在内核中使用 struct usb_interface 结构来描述. 这个结构是 USB 核传递给 USB 驱动的并且是 USB 驱动接下来负责控制的.
struct usb_interface {
/*array of alternate settings for this interface,
* stored in no particular order */
structusb_host_interface *altsetting;
structusb_host_interface *cur_altsetting; /*the currently
* active alternate setting */
unsignednum_altsetting; /* number of alternatesettings */
/*If there is an interface association descriptor then it will list
* the associated interfaces */
structusb_interface_assoc_descriptor *intf_assoc;
intminor; /* minor numberthis interface is
* bound to */
enumusb_interface_condition condition; /*state of binding */
unsignedsysfs_files_created:1; /* the sysfsattributes exist */
unsignedep_devs_created:1; /* endpoint"devices" exist */
unsignedunregistering:1; /* unregistration is inprogress */
unsignedneeds_remote_wakeup:1; /* driverrequires remote wakeup */
unsignedneeds_altsetting0:1; /* switch toaltsetting 0 is pending */
unsignedneeds_binding:1; /* needs delayedunbind/rebind */
unsignedreset_running:1;
unsignedresetting_device:1; /* true: bandwidthalloc after reset */
structdevice dev; /* interfacespecific device info */
structdevice *usb_dev;
atomic_tpm_usage_cnt; /* usage counterfor autosuspend */
structwork_struct reset_ws; /* for resets inatomic context */
};
13.1.3. 配置
linux 描述 USB 配置使用结构 structusb_host_config 和整个 USB 设备使用结构 struct usb_device. USB 设备驱动通常不会需要读写这些结构的任何值。
所以总结, USB 设备是非常复杂的, 并且由许多不同逻辑单元组成. 这些单元之间的关系可简单地描述如下:
· 设备通常有一个或多个配置.
· 配置常常有一个或多个接口.
· 接口常常有一个或多个设置.
· 接口有零或多个端点.
在USB的驱动中配置、接口、设置、端点在ch9.h都有与协议相应的定义,以方便驱动开发过程中与协议对应。
13.2. USB与Sysfs
物理 USB 设备(通过 struct usb_device 表示)和单个 USB 接口(由 struct usb_interface 表示)都作为单个设备出现在 sysfs .
结构 usb_device 在树中被表示在:
/sys/devices/pci0000:00/0000:00:09.0/usb2/2-1
而鼠标的 USB 接口 - USB 鼠标设备驱动被绑定到的接口 - 位于目录:
/sys/devices/pci0000:00/0000:00:09.0/usb2/2-1/2-1:1.0
第一个 USB 设备是一个根集线器. 这是 USB 控制器, 常常包含在一个 PCI 设备中. 控制器的命名是由于它控制整个连接到它上面的USB 总线. 控制器是一个 PCI 总线和 USB 总线之间的桥, 同时是总线上的第一个设备.
每个在 USB 总线上的设备采用根集线器的号作为它的名子的第一个数字. 紧跟着的是字符和设备插入的端口号. 由于我们例子中的设备插在第一个端口, 一个 1 被添加到名子. 因此给主 USB 鼠标设备的名子是2-1. 因为这个 USB 设备包含一个接口, 那使得树中的另一个设备被添加到 sysfs 路径. 到此点, USB 接口的命名方法是设备名:在我们的例子, 是 2-1 接着一个分号和 USB 配置名, 接着一个句点和接口名. 因此对这个例子, 设备名是 2-1:1.0 因为它是第一个配置并且有接口号 0.
USB sysfs 设备命名方法是:
root_hub-hub_port:config.interface
对一个 2 层的树, 设备名看来象:
root_hub-hub_port-hub_port:config.interface