当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 3 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : Linux下USB子系统软件结构分析
帖子发表于 : 2007-08-13 8:47 

注册: 2007-05-09 19:59
帖子: 28
送出感谢: 0 次
接收感谢: 0 次
Linux下USB子系统软件结构

USB内核(USB驱动,USBD )处于系统的中心,对于它进行研究是能够进行USB驱动开发(包括客户驱动和主机驱动)的第一步。它为客户端驱动和主机控制器驱动提供了主要数据结构和接口函数,主要有四类功能:客户端驱动管理,USB设备的配置和管理,主机控制器的管理,协议控制命令集和数据传输的管理。具体代码主要集中在linux/drivers/usb下的usb.c, usb.h中

主要数据结构分析

主要有四个数据结构,分别是USB设备usb_device,保存了一个USB设备的信息,包括设备地址,设备描述符,配置描述符,等等

USB总线系统usb_bus,保存了一个USB总线系统的信息,包括总线上设备地址信息,根集线器,带宽使用情况等。一个USB总线系统肯定有一个主机控制器和一个根集线器。Linux支持多USB总线系统

客户端驱动程序usb_driver,保存了客户驱动信息,包括驱动名称,以及驱动提供给USB内核使用的函数指针等

(USB Request Block)urb,是进行USB通信的数据结构。Linux的USB子系统只使用这么一种数据结构来进行USB通信,urb包含了建立任何 USB传输所需的所有信息,并贯穿于USB协议栈对数据处理的整个过程。

下面是对各部分进行详细分析。

代码:
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;


最后由 兰晓成 编辑于 2007-08-13 12:39,总共编辑了 1 次

页首
 用户资料  
 
2 楼 
 文章标题 :
帖子发表于 : 2007-08-13 9:48 
头像

注册: 2005-08-14 21:55
帖子: 58428
地址: 长沙
送出感谢: 4
接收感谢: 272
支持下,整理一个格式好点的个人笔记不。 :lol:


_________________
● 鸣学


页首
 用户资料  
 
3 楼 
 文章标题 :
帖子发表于 : 2007-08-13 12:21 

注册: 2007-05-09 19:59
帖子: 28
送出感谢: 0 次
接收感谢: 0 次
:lol: :lol:


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 3 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 1 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译