25.2.3 设备驱动结构

本文介绍了Linux内核中USB设备驱动的基本结构和工作原理,包括USB设备类、设备驱动结构及USB请求块(URB)的概念。同时,详细解释了URB的创建、初始化和提交过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

25.2.3  设备驱动结构

USB协议规定了许多种USB设备类型。Linux内核实现了音频设备、通信设备、人机接口、存储设备、电源设备、打印设备等几种USB设备类。

1.基本概念

Linux内核实现的USB设备类驱动都是针对通用的设备类型设计的。如存储设备类,只要USB存储设备是按照标准的USB存储设备规范实现的,就可以直接被内核USB存储设备驱动程序驱动。如果一个USB设备是非标准的,则需要编写对应设备的驱动程序。

Linux内核为不同的USB设备分配了设备号。在内核中还提供了一个usbfs文件系统,通过usbfs文件系统,用户可以方便地使用USB设备。为了使用usbfs,使用root权限在控制台输入“mount –t usbfs none /proc/bus/usb”,可以加载USB文件系统到内核。在插入一个USB设备的时候,内核会试图加载对应的驱动程序。

2.设备驱动结构

内核使用usb_driver结构体描述USB设备驱动,定义如下:

 

struct usb_driver {

    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);                               // I/O控制函数

 

    int (*suspend) (struct usb_interface *intf, pm_message_t message);                                                              // 挂起函数

    int (*resume) (struct usb_interface *intf);         // 恢复函数

 

    void (*pre_reset) (struct usb_interface *intf);

    void (*post_reset) (struct usb_interface *intf);

 

    const struct usb_device_id *id_table;

 

    struct usb_dynids dynids;

    struct device_driver driver;

    unsigned int no_dynamic_id:1;

};

 

实现一个USB设备的驱动主要是实现probe()disconnect()函数接口。probe()函数在插入USB设备的时候被调用,disconnect()函数在拔出USB设备的时候被调用。在25.2.4节中详细讲解USB设备驱动程序框架。

3USB请求块

USB请求块(USB request blockurb)的功能类似于网络设备中的sk_buff,用于描述USB设备与主机通信的基本数据结构。urb结构在内核中定义如下:

 

struct urb

{

    /* private: usb core and host controller only fields in the urb */  // 私有数据,仅供USB核心和主机控制器使用

    struct kref kref;       /* reference count of the URB */                                                            // urb引用计数

    spinlock_t lock;        /* lock for the URB */  // urb

    void *hcpriv;           /* private data for host controller */                                                          // 主机控制器私有数据

    int bandwidth;          /* bandwidth for INT/ISO request */                                                             // 请求带宽

    atomic_t use_count;     /* concurrent submissions counter */                                                        // 并发传输计数

    u8 reject;          /* submissions will fail */ // 传输即将失败标志

 

    /* public: documented fields in the urb that can be used by drivers */  // 公有数据,可以被驱动使用

    struct list_head urb_list;  /* list head for use by the urb's                                                           // 链表头

                     * current owner */

    struct usb_device *dev; /* (in) pointer to associated device */                                                     // 关联的USB设备

    unsigned int pipe;      /* (in) pipe information */     // 管道信息

    int status;         /* (return) non-ISO status */       // 当前状态

    unsigned int transfer_flags;    /* (in) URB_SHORT_NOT_OK | ...*/

    void *transfer_buffer;      /* (in) associated data buffer */                                                           // 数据缓冲区

    dma_addr_t transfer_dma;    /* (in) dma addr for transfer_buffer */                                                     // DMA使用的缓冲区

    int transfer_buffer_length; /* (in) data buffer length */                                                               // 缓冲区大小

    int actual_length;      /* (return) actual transfer length */                                                       // 实际接收或发送数据的长度

    unsigned char *setup_packet;    /* (in) setup packet (control only) */

    dma_addr_t setup_dma;       /* (in) dma addr for setup_packet */                                                   // 设置数据包缓冲区

    int start_frame;        /* (modify) start frame (ISO) */                                                            // 等时传输中返回初始帧

    int number_of_packets;      /* (in) number of ISO packets */                                                        // 等时传输中缓冲区数据

    int interval;           /* (modify) transfer interval                                                                   // 轮询的时间间隔

                     * (INT/ISO) */

    int error_count;        /* (return) number of ISO errors */                                                         // 出错次数

    void *context;          /* (in) context for completion */

    usb_complete_t complete;    /* (in) completion routine */

    struct usb_iso_packet_descriptor iso_frame_desc[0];

                    /* (in) ISO ONLY */

};

 

内核提供了一组函数操作urb类型的结构变量。urb的使用流程如下:

1)创建urb。在使用之前,USB设备驱动需要调用usb_alloc_urb()函数创建一个urb,函数定义如下:

 

struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);

 

iso_packets参数是urb包含的等时数据包数目,如果为0表示不创建等时数据包。mem_flags参数是分配内存标志。如果分配urb成功,函数返回一个urb结构类型的指针,否则返回0

内核还提供了释放urb的函数,定义如下:

 

void usb_free_urb(struct urb *urb)

 

在不使用urb的时候(退出驱动程序或者挂起驱动),需要使用usb_free_urb()函数释放urb

2)初始化urb,设置USB设备的端点。使用内核提供的usb_int_urb()函数设置urb初始结构,定义如下:

 

void usb_init_urb(struct urb *urb);

 

3)提交urbUSB核心。在分配并设置urb完毕后,使用usb_submit_urb()函数把新的urb提交到USB核心,函数定义如下:

 

int usb_submit_urb(struct urb *urb, gfp_t mem_flags);

 

参数urb指向被提交的urb结构,mem_flags是传递给USB核心的内存选项,用于告知USB核心如何分配内存缓冲区。如果函数执行成功,urb的控制权被USB核心接管,否则函数返回错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值