学习目标:分析USB摄像头驱动的描述符;
一、USB设备描述符
在usb设备驱动分析那一节,也用到了usb描述符。
usb描述符可分为:
USB设备描述符(usb_device_descriptor);
USB配置描述符(usb_config_descriptor);
USB接口描述符(usb_interface_descriptor);
USB端点描述符(usb_endpoint_descriptor);
其中,一个USB设备描述符可以有多个配置描述符;配置描述符可以有多个接口描述符(比如声卡驱动,就有两个接口:录音接口和播放接口);一个接口描述符可以有多个端点描述符。
二、结构体分析
1、USB设备描述符(usb_device_descriptor)
定义:
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_device_descriptor *descriptor = &dev->descriptor;
struct usb_device_descriptor {
__u8 bLength; //本描述符的size
__u8 bDescriptorType; //描述符的类型,这里是设备描述符DEVICE
__u16 bcdUSB; //指明usb的版本,比如usb2.0
__u8 bDeviceClass; //类
__u8 bDeviceSubClass; //子类
__u8 bDeviceProtocol; //指定协议
__u8 bMaxPacketSize0; //端点0对应的最大包大小
__u16 idVendor; //厂家ID
__u16 idProduct; //产品ID
__u16 bcdDevice; //设备的发布号
__u8 iManufacturer; //字符串描述符中厂家ID的索引
__u8 iProduct; //字符串描述符中产品ID的索引
__u8 iSerialNumber; //字符串描述符中设备序列号的索引
__u8 bNumConfigurations; //配置描述符的个数,表示有多少个配置描述符
} __attribute__ ((packed));
源码位置:usb_device结构体下
struct usb_device {
int devnum; //设备号,是在USB总线的地址
char devpath []; //用于消息的设备ID字符串
enum usb_device_state state; //设备状态:已配置、未连接等等
enum usb_device_speed speed; //设备速度:高速、全速、低速或错误
struct usb_tt *tt; //处理传输者信息;用于低速、全速设备和高速HUB
int ttport; //位于tt HUB的设备口
unsigned int toggle[]; //每个端点的占一位,表明端点的方向([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[]; //输入端点数组
struct usb_host_endpoint *ep_out[]; //输出端点数组
char **rawdescriptors; //每个配置的raw描述符
unsigned short bus_mA; //可使用的总线电流 u8 portnum; //父端口号
u8 level; //USB HUB的层数
unsigned can_submit:; //URB可被提交标志
unsigned discon_suspended:; //暂停时断开标志
unsigned persist_enabled:; //USB_PERSIST使能标志
unsigned have_langid:; //string_langid存在标志
unsigned authorized:;
unsigned authenticated:;
unsigned wusb:; //无线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:; //自动挂起/唤醒
unsigned do_remote_wakeup:; //远程唤醒
unsigned reset_resume:; //使用复位替代唤醒
unsigned autosuspend_disabled:; //挂起关闭
unsigned autoresume_disabled:; //唤醒关闭
unsigned skip_sys_resume:; //跳过下个系统唤醒
#endif
struct wusb_dev *wusb_dev; //(如果为无线USB)连接到WUSB特定的数据结构
};
2、USB配置描述符(usb_config_descriptor)
变量定义:
struct usb_host_config *hostconfig;
struct usb_config_descriptor *config;
位于:usb_device结构体下
源码:
struct usb_config_descriptor {
__u8 bLength; //描述符的长度
__u8 bDescriptorType; //描述符类型的编号 __le16 wTotalLength; //配置 所返回的所有数据的大小
__u8 bNumInterfaces; //配置 所支持的接口个数, 表示有多少个接口描述符
__u8 bConfigurationValue; //Set_Configuration命令需要的参数值
__u8 iConfiguration; //描述该配置的字符串的索引值
__u8 bmAttributes; //供电模式的选择
__u8 bMaxPower; //设备从总线提取的最大电流
} __attribute__ ((packed));
3、USB接口描述符(usb_interface_descriptor)
一个USB接口代表一个逻辑上的设备,例如摄像头驱动有两种接口:VC和VS。
定义:
struct usb_interface *intf;
struct usb_interface_descriptor *interface;
interface = &intf->altsetting[j].desc;
struct usb_interface_descriptor {
__u8 bLength; //描述符的长度
__u8 bDescriptorType; //描述符类型的编号 __u8 bInterfaceNumber; //接口的编号
__u8 bAlternateSetting; //备用的接口描述符编号,提供不同质量的服务参数.
__u8 bNumEndpoints; //要使用的端点个数(不包括端点0), 表示有多少个端点描述符,比如鼠标就只有一个端点
__u8 bInterfaceClass; //接口类型,与驱动的id_table
__u8 bInterfaceSubClass; //接口子类型
__u8 bInterfaceProtocol; //接口所遵循的协议
__u8 iInterface; //描述该接口的字符串索引值
} __attribute__ ((packed)
4、USB端点描述符(usb_endpoint_descriptor)
定义:
struct usb_endpoint_descriptor *endpoint;
endpoint = &intf->altsetting[j].endpoint[m].desc;
源码:
struct usb_host_endpoint {
struct usb_endpoint_descriptor desc; //端点描述符
struct usb_ss_ep_comp_descriptor ss_ep_comp;//超快速端点描述符
struct list_head urb_list; //本端口对应的urb链表
void *hcpriv;
struct ep_device *ep_dev; /* For sysfs info */ unsigned char *extra; /* Extra descriptors */
int extralen;
int enabled;//使能的话urb才能被提交到此端口
};
struct usb_endpoint_descriptor {
__u8 bLength; //描述符的长度
__u8 bDescriptorType; //描述符类型的编号 __u8 bEndpointAddress; //端点编号,比如端点1,就是1
__u8 bmAttributes; //端点的属性, 比如中断传输类型,输入类型
__le16 wMaxPacketSize; //一个端点的最大包大小,
__u8 bInterval; //间隔时间,用在中断传输上,比如间隔时间查询鼠标的数据 /* NOTE: these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress; } __attribute__ ((packed));
5、接口关联描述符 (Interface Association Descriptor)
作用:描述设备功能需要的一个视频控制接口VC和一个或多个视频流接口VS的视频接口集合。
定义:
struct usb_interface_assoc_descriptor *assoc_desc;
assoc_desc = hostconfig->intf_assoc[0];
源码:
/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
struct usb_interface_assoc_descriptor {
__u8 bLength; //描述符的长度
__u8 bDescriptorType; //描述符类型的编号
__u8 bFirstInterface;
__u8 bInterfaceCount; //接口数目
__u8 bFunctionClass; //接口类型,与驱动的id_table
__u8 bFunctionSubClass; //接口子类型
__u8 bFunctionProtocol; //接口所遵循的协议
__u8 iFunction;
} __attribute__ ((packed));