Linux驱动USB学习笔记(二)

USB驱动描述

在linux内核中,使用struct usb_driver结构描述一个USB驱动。

struct usb_driver{

const char *name;//驱动程序名

/*当USB核心发现了该驱动能够处理的USB接口时,调用该函数*/

int (*probe)(structusb_interface *intf,const struct usb_device_id *id);

/*当相应的USB接口被移除时,调用该函数*/

void (*disconnect)(structusb_interface *intf);

/*USB驱动能够处理的设备列表*/

const struct usb_device_id*id_table;

}

USB设备列表:

Linux内核提供了宏USB_DEVICE来定义一种USB设备的USB_DEVICE(vend,prod)可以设置一个设备或者一类设备

  • Vend:USB VendorID 
  • Prod:USB ProductID

Linux内核提供宏USB_INTERFACE_INFO来协助定义一类USB设备USB_INTERFACE_INFO(cl,sc,pl)

  • cl:blnterfaceClassValue(类)
  • sc:blnterfaceSubClassvalue(子类)
  • pr:blnterfaceProtocolvalue(协议)

注册USB驱动:

static inline int usb_register(struct usb_driver *driver);

USB设备描述

Linux内核使用struct usb_device来描述一个USB设备

struct usb_device {

         int              devnum;//USB设备号

         char            devpath[16];//设备ID字符串

         u32             route;

         enum usb_device_state        state;//设备状态、未连接、已配置

         enum usb_device_speed       speed;//高速、全速、低速

……………………………………………………..

struct usb_device_descriptordescriptor;//usb设备描述符

struct usb_host_bos *bos;

struct usb_host_config*config;

……………………………………………………..

/* static strings from thedevice */

char *product;//产品名

char *manufacturer;//厂商名

char *serial;//设备串号

……………………………………

};

Linux内核中使用usb_device_descriptor来描述USB描述符中的设备描述符(与USB协议相对应)

/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
                    __u8  bLength;
                    __u8  bDescriptorType;
                    __le16 bcdUSB;
                    __u8  bDeviceClass;
                    __u8  bDeviceSubClass;
                    __u8  bDeviceProtocol;
                    __u8  bMaxPacketSize0;
                    __le16 idVendor;
                    __le16 idProduct;
                    __le16 bcdDevice;
                    __u8  iManufacturer;
                    __u8  iProduct;
                    __u8  iSerialNumber;
                    __u8  bNumConfigurations;
} __attribute__ ((packed));

USB配置描述符:

Linux内核使用struct usb_host_config来描述一个USB配置

struct usb_host_config {
     struct usb_config_descriptor desc; //配置描述符,对应usb协议
     char *string;  /* iConfiguration string, if present */
     /* List of any Interface AssociationDescriptors in this
     * configuration. */
     struct usb_interface_assoc_descriptor*intf_assoc[USB_MAXIADS];
     //与本配置相关的usb接口,其顺序不重要。仅当本配置激活时,这些指针才有效
     struct usb_interface*interface[USB_MAXINTERFACES];
     //每一个指向一个usb_interface_cache结构体,每个结构体对应一个接口,并且它是在usb的整个

//生命周期都存在的!usb_interface 仅仅在配置激活的时候才存在
     struct usb_interface_cache*intf_cache[USB_MAXINTERFACES];
     unsigned char *extra; /* 其他一些配置信息 */
     int extralen;
};

USB配置描述符:(与协议相对应)

struct usb_config_descriptor {
 __u8 bLength;  //本描述符的size
 __u8 bDescriptorType;//描述符类型,这里是配置描述符CONFIGURATION       

 //为本配置而返回的总的数据的长度,包括所有为本设备而返回的描述符(如:配置,接口,端口)

 __le16 wTotalLength;
 __u8 bNumInterfaces; //本配置支持的接口是数量
 __u8 bConfigurationValue; //有设置配置请求来选择本配置
 __u8 iConfiguration; //字符串描述符中描述本配置的索引
 __u8 bmAttributes; //配置的特性,详见usb协议
 __u8 bMaxPower; //最大电源功耗
} __attribute__ ((packed));

USB接口描述:

struct usb_interface{
     //本接口对应的所有的设置(与配置不是一个概念)
     struct usb_host_interface *altsetting;
      structusb_host_interface *cur_altsetting;//当前活跃的设置
     unsignednum_altsetting; //可选设置的数量
      /* If there is an interface associationdescriptor then it will list the associated interfaces */
      struct usb_interface_assoc_descriptor*intf_assoc;
      int minor; //本接口绑定的次设备号
      enum usb_interface_condition condition; //接口是否绑定
     unsignedsysfs_files_created:1; /* 文件系统存在的文件的属性 */
      unsigned ep_devs_created:1; /* endpoint"devices" exist */
     unsignedunregistering:1; /* 标识卸载interface */
     unsignedneeds_remote_wakeup:1; /* 驱动要求远程唤醒 */
     unsignedneeds_altsetting0:1; /* 当设置0被推迟时标识 */
     unsignedneeds_binding:1; /* needs delayed unbind/rebind */
     unsignedreset_running:1;
     unsignedresetting_device:1; /* true: bandwidth alloc after reset */
      struct device dev;  /* interface specific device info */
     //当接口被绑定到usb主设备号的时候,它指向文件系统中表示的usb设备
     structdevice *usb_dev;
     atomic_tpm_usage_cnt;  /* usage counter forautosuspend */
     structwork_struct reset_ws; /* for resets in atomic context */
};

配置和设置:

一个配置包含一个或多个接口,一个接口包含一个或多个设置

USB接口描述符:对应usb协议中的接口描述符

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端点描述:

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才能被提交到此端口
};

USB端点描述符:(对应协议中的端点描述符)

struct usb_endpoint_descriptor{
         __u8 bLength;
         __u8 bDescriptorType;
         __u8 bEndpointAddress;
         __u8 bmAttributes;
         __le16wMaxPacketSize;
         __u8 bInterval;
         /* NOTE: these two are _only_ in audio endpoints. */
         /* useUSB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
         __u8 bRefresh;
         __u8 bSynchAddress;
} __attribute__ ((packed));

USB URB

USB请求快即URB是USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构,非常类似与网络设备驱动中的sk_buff结构体,是USB主机与设备通信的“电波”。

URB处理流程:

  • USB设备驱动程序创建并初始化一个访问特定USB设备特定端点URB,并交给USB core
  • USB core提交该URB到USB主控制器驱动程序
  • USB主控制器驱动程序根据该URB描述的信息,来访问USB设备
  • 当设备访问结束后,USB主控制器驱动程序通知USB设备驱动程序

创建URB的函数:

struct urb *usb_alloc_urb(int iso_packets,gfp_t mem_flags)iso_packets是urb所包含的等时数据包的个数。Mem_flags是内存分配标识。

URB初始化:

对于中断urb,使用usb_fill_int_urb进行初始化

static inline void usb_fill_int_urb(struct urb *urb,struct usb_device*dev,unsigned int pipe

                   void*transfer_buffer,int buffer_length,usb_complete_t complete_fn,void *context

                   int interval)

urb是要初始化的urb指针;dev是urb所要访问的设备;pipe是要访问的端点所对应的管道,使用usb_sndintpipe()或rcvintpipe()创建(管道:驱动程序的数据缓冲区与一个端点的连接,它代表了一种在两者之间移动数据的能力);transfer_buffer是要传输数据的缓冲区;buffer_length是transfer_buffer所指缓冲区的长度;complete_fn是当前完成该urb所请求的操作时,要调用的回调函数;context是complete_fn函数所需的上下文,通常取值为dev;interval是urb被调用的时间间隔。

对于批量urb使用usb_fill_bluk_urb函数初始化;

对于控制urb使用usb_fill_control_urb函数初始化;

等时urb没有像中断、控制和批量urb那样的初始化函数,我们只能手动的初始化urb
提交URB:

在完成urb的出创建和初始化后,urb便可以通过usb_submit_urb函数来提交给USB核心

int usb_submit_urb(struct urb *urb,gfp_t mem_flags)urb是指向urb的指针;mem_flags是内存分配标识,它是用与告知USB核心如何分配内存缓冲区。

处理URB:

URB被提交到USB核心后,USB核心指定USB主控制器驱动程序来处理URB,在3中情况下,URB会被认为是处理完成。

  • urb被成功发送给设备,并且设备返回正确的确认。如果urb->status为0,意味着对于一个输出urb,数据成功发送;对于一个输入urb,请求的数据被成功接收。
  •  如果发送数据到设备或从设备接收数据时发生错误,urb->status将记录错误值
  • urb被“取消”,这发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,或urb虽已提交,而usb设备被拔出的情况下。当处理完urb后,urb完成函数将被调用。

猜你喜欢

转载自blog.csdn.net/qq_35699583/article/details/80902928
今日推荐