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完成函数将被调用。