主要数据结构分析
主要有四个数据结构,分别是
1------USB设备usb_device,保存了一个USB设备的信息,包括设备地址,设备描述符,配置描述符,等等。
2-----USB总线系统usb_bus,保存了一个USB总线系统的信息,包括总线上设备地址信息,根集线器,带宽使用情况等。一个USB总线系统肯定有一个主机控制器和一个根集线器。Linux支持多USB总线系统。
3-----客户端驱动程序usb_driver,保存了客户驱动信息,包括驱动名称,以及驱动提供给USB内核使用的函数指针等
4------(USB Request Block)urb,是进行USB通信的数据结构。Linux的USB子系统只使用这么一种数据结构来进行USB通信,urb包含了建立任何 USB传输所需的所有信息,并贯穿于USB协议栈对数据处理的整个过程。
下面是对各部分进行详细分析。
struct usb_bus {
struct device *controller; /* host/master side hardware */
int busnum; /* Bus number (in order of reg) */
const char *bus_name; /* stable id (PCI slot_name etc) */
u8 uses_dma; /* Does the host controller use DMA? */
u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
int devnum_next; /* Next open device number in
* round-robin allocation */
struct usb_devmap devmap; /* device address allocation map */
struct usb_device *root_hub; /* Root hub */
struct list_head bus_list; /* list of busses */
int bandwidth_allocated; /* on this bus: how much of the time
* reserved for periodic (intr/iso)
* requests is used, on average?
* Units: microseconds/frame.
* Limits: Full/low speed reserve 90%,
* while high speed reserves 80%.
*/
int bandwidth_int_reqs; /* number of Interrupt requests */
int bandwidth_isoc_reqs; /* number of Isoc. requests */
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
#endif
struct device *dev; /* device for this bus */
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
struct mon_bus *mon_bus; /* non-null when associated */
int monitored; /* non-zero when monitored */
#endif
}
struct usb_device { //代表一个USB设备
int devnum; //分配的设备地址,1-127
enum {
USB_SPEED_UNKNOWN = 0, /* enumerating */
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
USB_SPEED_HIGH /* usb 2.0 */
} speed; //设备速度,低速/全速/高速
struct usb_device *tt; /* usb1.1 device on usb2.0 bus */,事务处理解释器
int ttport; /* device/hub port on that tt */设备所连接的具有事务处理解释器功能的集线器端口
atomic_t refcnt; /* Reference count */引用计数
struct semaphore serialize; //用于同步
unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */用于同步切换的位图,每个端点占用1位,[0]表示输入,[1]输出
unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; [0] = IN, [1] = OUT */表示端点是否处于停止状态的位图
int epmaxpacketin[16]; /* INput endpoint specific maximums */输入端点的最大包长
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */输出端点的最大包长
struct usb_device *parent; //表示设备所连的上游集线器指针
struct usb_bus *bus; /* Bus we're part of */设备所属的USB总线系统
struct usb_device_descriptor descriptor;/* Descriptor */ 设备描述符
struct usb_config_descriptor *config; /* All of the configs */指向设备的配置描述符和其所包含的接口描述符,端点描述符的指针
struct usb_config_descriptor *actconfig;/* the active configuration */当前的配置描述符指针
char **rawdescriptors; /* Raw descriptors for each config */
int have_langid; /* whether string_langid is valid yet *// 是否有string_langid
int string_langid; /* language ID for strings */和字符描述符相关的语言ID
void *hcpriv; /* Host Controller private data */设备在HCD层占用的资源指针,对USB内核层是透明的
/* usbdevfs inode list */ 设备在usbdevfs中的inode列表
struct list_head inodes;
struct list_head filelist;
/*
* Child devices - these can be either new devices
* (if this is a hub device), or different instances
* of this same device.
*
* Each instance needs its own set of data structures.
*/只对当前设备是集线器的情况有效
int maxchild; /* Number of ports if hub */ hub的下游端口数
struct usb_device *children[USB_MAXCHILDREN]; hub所连设备指针
};
struct usb_bus { //USB总线系统
int busnum; /* Bus number (in order of reg) */当前总线系统的序列号,Linux支持多总线系统并为它们编号
#ifdef DEVNUM_ROUND_ROBIN
int devnum_next; /* Next open device number in round-robin allocation */
#endif /* DEVNUM_ROUND_ROBIN */给连接到子系统上的设备分配设备号的数据结构
struct usb_devmap devmap; /* Device map */给连接到子系统上的设备分配设备号的数据结构
struct usb_operations *op; /* Operations (specific to the HC) */HCD为USB内核提供的一系统函数集指针
struct usb_device *root_hub; /* Root hub */指向根Hub的指针
struct list_head bus_list; 双向链表指针,USB内核用一个双向链表来维护系统中所有USB总线系统
void *hcpriv; /* Host Controller private data */与主机控制器相关数据,对USB内核层是透明
int bandwidth_allocated; /* on this Host Controller; applies to Int. and Isoc. pipes; measured in microseconds/frame; range is 0..900, where 900 = 90% of a 1-millisecond frame */当前子系统的带宽使用情况,单位是毫秒/帧,取值范围[0,900]
int bandwidth_int_reqs; /* number of Interrupt requesters */子系统中当前的中断传输的数量
int bandwidth_isoc_reqs; /* number of Isoc. requesters */子系统中当前的实时传输的数量
/* usbdevfs inode list */ 在usbdevfs中的inode列表 struct list_head inodes;
atomic_t refcnt;
};
struct usb_driver { //客户端驱动程序为USB内核提供的调用接口
const char *name; //客户端驱动程序的字符串名称,用于避免重复安装和卸载
void *(*probe)(//给USB内核提供的函数,用于判断驱动程序是否能对设备的某个接口进行驱动,如能则分配资源
struct usb_device *dev, /* the device */
unsigned intf, /* what interface */
const struct usb_device_id *id /* from id_table */
);
void (*disconnect)(struct usb_device *, void *);//给USB内核提供的函数,用于释放设备的某个接口所占用的资源
struct list_head driver_list;//对应的双向指针,USB内核通过一个双向指针链表维护USB子系统中所用的客户端驱动程序
struct file_operations *fops;
int minor; 驱动的次版本号
struct semaphore serialize;
/* ioctl -- userspace apps can talk to drivers through usbdevfs */
int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
/* support for "new-style" USB hotplugging
* binding policy can be driven from user mode too
*/
const struct usb_device_id *id_table;
/* suspend before the bus suspends;
* disconnect or resume when the bus resumes */
// void (*suspend)(struct usb_device *dev);
// void (*resume)(struct usb_device *dev);
};
typedef struct urb //USB Request Block,包含了建立任何 USB传输所需的所有信息,并贯穿于USB协议栈对数据处理的整个过程
{
spinlock_t lock; // lock for the URB
void *hcpriv; // private data for host controller与主机控制器相关数据,对USB内核层是透明
struct list_head urb_list; // list pointer to all active urbs双向指针,用于将此URB连接到处于活动的URB双向链表中
struct urb *next; // pointer to next URB 指向下一个URB的指针
struct usb_device *dev; // pointer to associated USB device 接受此URB的USB设备指针
unsigned int pipe;// pipe information表示设备的某个端点和客户端驱动程序之间的管道
int status; // returned status 返回状态
unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc.
USB_DISABLE_SPD //拒绝短数据包,即比最大传输包长度小的数据包
USB_ISO_ASAP //用于实时传输,告诉主机控制器立即进行此请求的数据传输。如果没有置位,则需要给start_frame赋值,用来通知主机控制器该在哪个帧上开始此请求的数据传输
USB_ASYNC_UNLINK //告诉USBD采用异步方式取消请求
USB_QUEUE_BULK //表示批量请求可以排队,一般一个设备的批量请求端点只有一个URB
USB_NO_FSBR //表示全速传输站用的带宽不要回收
USB_ZERO_PACKET //表示批量传输的数据长度等于端点的包最大长度时,主机控制器在发送完数据后,再发送一个零长度的包表示数据结束
USB_TIMEOUT_KILLED //本位只被HCD设置,表示发生了超时。客户驱动可以给URB的处理设置一个超时时间,如果处理超时,则要求USBD结束对此URB的处理,URB的返回信息中会反映该此状态。
void *transfer_buffer; // associated data buffer传输数据缓存区指针,接收或发送设备的数据,它必须是物理连续的,不可换页的内存块,用kmalloc(,GFP_KERNEL)分配
int transfer_buffer_length; // data buffer length缓存区长度
int actual_length; // actual data buffer length 实际数据长度
int bandwidth; // bandwidth for this transfer request (INT or ISO) 此请求每次占用一帧的带宽,只适用实时/中断传输
unsigned char *setup_packet; // setup packet (control only) 用于指向控制传输中控制命令的指针,只适用控制传输
int start_frame; // start frame (iso/irq only)此请求所开始传输的帧号,只适用实时/中断传输。中断传输时,表示返回启动此请求的第一次中断传输的帧号。实时传输时,指明处理第一个实时请求数据报包的帧号,如果设置了USB_ISO_ASAP,此变量表示返回启动第一次实时传输的帧号。
int number_of_packets; // number of packets in this request (iso)此请求所包含的数据包数,只适合实时传输
int interval; // polling interval (irq only) 中断传输的周期,1〈= interval〈=255
int error_count; // number of errors in this transfer (iso only)发生传输错误次数的累加值,只适用实时传输
int timeout; // timeout (in jiffies)
void *context; // context for completion routine回调函数中的参数
usb_complete_t complete; // pointer to completion routine 指向回调函数的指针。当数据传输完成后,主机控制器驱动会回调该函数。
iso_packet_descriptor_t iso_frame_desc[0]; 要进行实时传输的结构数组,每个结构表示一次数据传输
} urb_t, *purb_t;
对于初学者,如果直接看USB驱动代码,大概会被那些名字相近的结构体弄得晕头转向,比如usb_host_interface和usb_interface,看着看着就把两个混淆了。所以,在学习USB驱动之前,建议把相关结构体都拎出来看一下,其实,也就那么几个结构体在那装神弄鬼。USB skeleton驱动中用到的主要字段已用蓝色标出:
endpoint:
struct usb_host_endpoint {
struct usb_endpoint_descriptor desc;
struct list_head urb_list;
void *hcpriv;
unsigned char *extra;
int extralen;
};
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
bEndpointAddress,最高位用来判断传输方向:
#define USB_ENDPOINT_NUMBER_MASK 0x0f
#define USB_ENDPOINT_DIR_MASK 0x80
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
bmAttributes,表示endpoint的类型:
#define USB_ENDPOINT_XFERTYPE_MASK 0x03
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
bInterval,如果该endpoint是interrupt类型的(USB鼠标驱动就是该类型),那么bInterval就表示中断时间间隔,单位毫秒。
interface:
struct usb_interface{
struct usb_host_interface *altsetting;
struct usb_host_interface *cur_altsetting;
unsigned num_altsetting;
int minor;
enum usb_interface_condition condition;
struct device dev;
struct class_device *class_dev;
};
struct usb_host_interface{
struct usb_interface_descriptor desc;
struct usb_host_endpoint *endpoint;
char *string;
unsigned char *extra;
int extralen;
};
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
usb_device:
struct usb_device {
int devnum;
char devpath [16];
enum usb_device_state state;
enum usb_device_speed speed;
struct usb_tt *tt;
int ttport;
struct semaphore serialize;
unsigned int toggle[2];
struct usb_device *parent;
struct usb_bus *bus;
struct usb_host_endpoint ep0;
struct device dev;
struct usb_device_descriptor descriptor;
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;
int have_langid;
int string_langid;
char *product;
char *manufacturer;
char *serial;
struct list_head filelist;
struct dentry *usbfs_dentry;
int maxchild;
struct usb_device *children[USB_MAXCHILDREN];
};
usb_driver:
struct usb_driver{
struct module *owner;
const char *name;
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
int (*suspend) (struct usb_interface *intf, pm_message_t message);
int (*resume) (struct usb_interface *intf);
const struct usb_device_id *id_table;
struct device_driver driver;
};
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sandflee/archive/2010/01/18/5202473.aspx