usb 设备的一些结构
以前零星记录的一些信息,可能来自于网络,可能来自于自己的spec 阅读。
通常,一个USB设备由三个功能模块组成:USB总线接口、USB逻辑设备和功能单元。
1、设备中USB总线接口指的是USB设备中的串行接口引擎(SIE);
2、USB逻辑设备被USB系统软件看作是一个端点的集合;
3、功能单元被客户软件看作是一个接口的集合。
SIE、端点和接口都是USB设备的组成单元。为了更好地描述USB设备的特征,USB提出了设备架构的概念。从这个角度来看,可以认为USB设备是由一些配置、接口和端点组成的,即一个USB设备可以含有一个或多个配置,在每个配置中可含有一个或多个接口,在每个接口中可含有若干个端点。其中,配置和接口是对USB设备功能的抽象,实际的数据传输由端点来完成。
在使用USB设备前,必须指明其采用的配置和接口。这个步骤一般是在设备接入主机时设备进行 握手协议 时完成的。USB设备使用各种描述符来说明其设备架构,包括设备描述符、配置描述符、接口描述符、端点描述符以及字符串描述符,它们通常被保存在USB设备的固件程序中。
所以,在usb驱动程序中,也需要对应的设置描述符的结构体,以便完成程序数据结构的完整性。一般在usb 2.0的spec中第九章有介绍。或者在linux、uboot中有ch9.h定义这些数据结构。
1、设备描述符结构
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor { 设备描述符 如USB扬声器
__u8 bLength; 描述符的长度
__u8 bDescriptorType; 描述符类型的编号
__le16 bcdUSB; USB版本号
__u8 bDeviceClass; USB的设备类code
__u8 bDeviceSubClass; USB的子类code
__u8 bDeviceProtocol; USB的协议code
__u8 bMaxPacketSize0; 默认端口端口0的最大包大小
__le16 idVendor; 厂商编号
__le16 idProduct; 产品编号
__le16 bcdDevice; 设备出厂的编号
__u8 iManufacturer; 描述厂商的字符串的索引
__u8 iProduct; 描述产品的字符串的索引
__u8 iSerialNumber; 描述设备序列号的字符串的索引
__u8 bNumConfigurations; 可能的配置数量
} __attribute__ ((packed));
2、配置描述符结构
struct usb_config_descriptor { 多个配置描述符
__u8 bLength; 描述符的长度
__u8 bDescriptorType; 描述符类型的编号
__le16 wTotalLength; 配置 所返回的所有数据的大小
__u8 bNumInterfaces; 配置 所支持的interface数
__u8 bConfigurationValue; Set_Configuration命令需要的参数值
__u8 iConfiguration; 描述该配置的字符串的索引值
__u8 bmAttributes; 供电模式的选择
__u8 bMaxPower; 设备从总线提取的最大电流
} __attribute__ ((packed));
3、接口描述符结构
/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor { 多个接口描述符 如音频接口,旋钮和按钮接口
__u8 bLength; 描述符的长度
__u8 bDescriptorType; 描述符类型的编号
__u8 bInterfaceNumber; 接口的编号
__u8 bAlternateSetting; 备用的接口描述符编号,提供不同质量的服务参数.
__u8 bNumEndpoints; 该接口所使用的端口数,不包括端口0
__u8 bInterfaceClass; 接口类型
__u8 bInterfaceSubClass; 接口子类型
__u8 bInterfaceProtocol; 接口所遵循的协议
__u8 iInterface; 描述该接口的字符串索引值
} __attribute__ ((packed)
4、端点描述符结构
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor { 多个端口描述符
__u8 bLength; 描述符长度
__u8 bDescriptorType; 描述符的类型
__u8 bEndpointAddress; 端点号:0-3是端口点,第7位是方向(0-OUT,1-IN)
__u8 bmAttributes; 端口属性:bit[0:1] 00:控制端点 01:同步传输端点 02:批量传输端点 03:中断端点
__le16 wMaxPacketSize; 数据包的最大容量
__u8 bInterval; 轮询数据传送端点的时间间隔,即中断传送时轮询间隔,此域为1-255
批量和控制传送时,此域忽略
同步传送时,为1
5、字符串描述符结构
/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor { 字符串描述符
__u8 bLength; 描述符长度
__u8 bDescriptorType; 描述符类型
__le16 wData[1]; /* UTF-16LE encoded */
} __attribute__ ((packed))
那么usb驱动中,就会定义usb device 结构体:
struct usb_device {
int devnum; //设备号,是在USB总线的地址
char devpath [16]; //用于消息的设备ID字符串
enum usb_device_state state; //设备状态:已配置、未连接等等
enum usb_device_speed speed; //设备速度:高速、全速、低速或错误
struct usb_tt *tt; //处理传输者信息;用于低速、全速设备和高速HUB
int ttport; //位于tt HUB的设备口
unsigned int toggle[2]; //每个端点的占一位,表明端点的方向([0] = IN, [1] = OUT)
struct usb_device *parent; //上一级HUB指针
struct usb_bus *bus; //总线指针
struct usb_host_endpoint ep0; //端点0数据
struct device dev; //一般的设备接口数据结构
struct usb_device_descriptor descriptor; //USB设备描述符
struct usb_host_config *config; //设备的所有配置
struct usb_host_config *actconfig; //被激活的设备配置
struct usb_host_endpoint *ep_in[16]; //输入端点数组
struct usb_host_endpoint *ep_out[16]; //输出端点数组
char **rawdescriptors; //每个配置的raw描述符
unsigned short bus_mA; //可使用的总线电流
u8 portnum; //父端口号
u8 level; //USB HUB的层数
unsigned can_submit:1; //URB可被提交标志
unsigned discon_suspended:1; //暂停时断开标志
unsigned persist_enabled:1; //USB_PERSIST使能标志
unsigned have_langid:1; //string_langid存在标志
unsigned authorized:1;
unsigned authenticated:1;
unsigned wusb:1; //无线USB标志
int string_langid; //字符串语言ID
/* static strings from the device */ //设备的静态字符串
char *product; //产品名
char *manufacturer; //厂商名
char *serial; //产品串号
struct list_head filelist; //此设备打开的usbfs文件
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev; //用户空间访问的为usbfs设备创建的USB类设备
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; //设备的usbfs入口
#endif
int maxchild; //(若为HUB)接口数
struct usb_device *children[USB_MAXCHILDREN];//连接在这个HUB上的子设备
int pm_usage_cnt; //自动挂起的使用计数
u32 quirks;
atomic_t urbnum; //这个设备所提交的URB计数
unsigned long active_duration; //激活后使用计时
#ifdef CONFIG_PM //电源管理相关
struct delayed_work autosuspend; //自动挂起的延时
struct work_struct autoresume; //(中断的)自动唤醒需求
struct mutex pm_mutex; //PM的互斥锁
unsigned long last_busy; //最后使用的时间
int autosuspend_delay;
unsigned long connect_time; //第一次连接的时间
unsigned auto_pm:1; //自动挂起/唤醒
unsigned do_remote_wakeup:1; //远程唤醒
unsigned reset_resume:1; //使用复位替代唤醒
unsigned autosuspend_disabled:1; //挂起关闭
unsigned autoresume_disabled:1; //唤醒关闭
unsigned skip_sys_resume:1; //跳过下个系统唤醒
#endif
struct wusb_dev *wusb_dev; //(如果为无线USB)连接到WUSB特定的数据结构
};
配置的定义
一个USB设备可以有多个配置,并可在它们之间转换以改变设备的状态。一个时刻只能有一个配置可以被激活。
struct usb_host_config {
struct usb_config_descriptor desc; //配置描述符
char *string; /* 配置的字符串指针(如果存在) */
struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS]; //配置的接口联合描述符链表
struct usb_interface *interface[USB_MAXINTERFACES]; //接口描述符链表
struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
unsigned char *extra; /* 额外的描述符 */
int extralen;
};
设备usb接口
一个USB接口代表一个基本功能,每个USB驱动控制一个接口。所以一个物理上的硬件设备可能需要 一个以上的驱动程序。有时插入一个USB设备后,系统会识别出多个设备,并安装相应多个的驱动。
USB接口在内核中使用 struct usb_interface 来描述。USB core将其传递给USB驱动,并由USB驱动负责后续的控制。
struct usb_interface {
struct usb_host_interface *altsetting; /* 包含所有可用于该接口的可选设置的接口结构数组。每个 struct usb_host_interface 包含一 套端点配置(即struct usb_host_endpoint结构所定义的端点配置。这些接口结构没有特别的顺序。*/
struct usb_host_interface *cur_altsetting; /* 指向altsetting内部的指针,表示当前激活的接口配置*/
unsigned num_altsetting; /* 可选设置的数量*/
/* If there is an interface association descriptor then it will list the associated interfaces */
struct usb_interface_assoc_descriptor *intf_assoc;
int minor; /* 如果绑定到这个接口的 USB 驱动使用 USB 主设备号, 这个变量包 含由 USB 核心分配给接口的次设备号. 这只在一个成功的调用 usb_register_dev后才有效。*/
/*以下的数据在我们写的驱动中基本不用考虑,系统会自动设置*/
enum usb_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
unsigned ep_devs_created:1; /* endpoint "devices" exist */
unsigned unregistering:1; /* unregistration is in progress */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
unsigned reset_running:1;
struct device dev; /* 接口特定的设备信息 */
struct device *usb_dev;
int pm_usage_cnt; /* usage counter for autosuspend */
struct work_struct reset_ws; /* for resets in atomic context */
};
struct usb_host_interface {
struct usb_interface_descriptor desc; //接口描述符
struct usb_host_endpoint *endpoint; /* 这个接口的所有端点结构体的联合数组*/
char *string; /* 接口描述字符串 */
unsigned char *extra; /* 额外的描述符 */
int extralen;
};