25.2.4 USB驱动程序框架

25.2.4  USB驱动程序框架

Linux内核代码driver/usb/usb-skeleton.c文件是一个标准的USB设备驱动程序。编写一个USB设备的驱动可以参考usb-skeleton.c文件,实际上,可以直接修改该文件驱动新的USB设备。下面以usb-skeleton.c文件为例分析usb-skel设备驱动框架。

1.基本数据结构

usb-skel设备使用自定义结构usb_skel记录设备驱动用到的所有描述符,该结构定义如下:

 

struct usb_skel {

    struct usb_device * udev;           /* the usb device for this device */                                                // USB设备描述符

    struct usb_interface *  interface;      /* the interface for this device

    */                                              // USB接口描述符

    struct semaphore    limit_sem;      /* limiting the number of writes in

    progress */                                     // 互斥信号量

    unsigned char *     bulk_in_buffer;     /* the buffer to receive data */                                                // 数据接收缓冲区

    size_t          bulk_in_size;       /* the size of the receive buffer */                                                // 数据接收缓冲区大小

    __u8            bulk_in_endpointAddr;   /* the address of the bulk in

    endpoint */                                     // 入端点地址

    __u8            bulk_out_endpointAddr;  /* the address of the bulk out endpoint */                                     // 出端点地址

    struct kref     kref;

};

 

usb-skel设备驱动把usb_skel结构存放在了urb结构的context指针里。通过urb,设备的所有操作函数都可以访问到usb_skel结构。其中,limit_sem成员是一个信号量,当多个usb-skel类型的设备存在于系统中的时候,需要控制设备之间的数据同步。

2.驱动程序初始化和注销

与其他所有的Linux设备驱动程序一样,usb-skel驱动使用module_init()宏设置初始化函数,使用module_exit()宏设置注销函数。usb-skel驱动的初始化函数是usb_skel_init()函数,定义如下:

 

static int __init usb_skel_init(void)

{

       int result;

 

       /* register this driver with the USB subsystem */

       result = usb_register(&skel_driver);     // 注册USB设备驱动

       if (result)

              err("usb_register failed. Error number %d", result);

 

       return result;

}

 

usb_skel_init()函数调用内核提供的usb_register()函数注册了一个usb_driver类型的结构变量,该变量定义如下:

 

static struct usb_driver skel_driver = {

       .name =      "skeleton",             // USB设备名称

       .probe = skel_probe,                 // USB设备初始化函数

       .disconnect = skel_disconnect,    // USB设备注销函数

       .id_table =  skel_table,             // USB设备ID映射表

};

 

skel_driver结构变量中,定义了usb-skel设备的名、设备初始化函数、设备注销函数和USB ID映射表。其中usb-skel设备的USB ID映射表定义如下:

 

static struct usb_device_id skel_table [] = {

       { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },

       { }                  /* Terminating entry */

};

 

skel_table中只有一项,定义了一个默认的usb-skel设备的ID。其中,USB_SKEL_VENDOR_IDUSB设备的厂商IDUSB_SKEL_PRODUCT_IDUSB设备ID

注销函数的操作比较简单,调用usb_deregister()函数注销usb-skel设备驱动,函数定义如下:

 

static void __exit usb_skel_exit(void)

{

       /* deregister this driver with the USB subsystem */

       usb_deregister(&skel_driver); // 注销USB设备

}

 

3.设备初始化

skel_driver结构可以知道usb-skel设备的初始化函数是skel_probe()函数。设备初始化主要是探测设备类型,分配USB设备用到的urb资源,注册USB设备操作函数等。skel_class结构变量记录了usb-skel设备信息,定义如下:

 

static struct usb_class_driver skel_class = {

       .name =      "skel%d",       // 设备名称

       .fops =      &skel_fops,     // 设备操作函数

       .minor_base = USB_SKEL_MINOR_BASE,

};

 

name变量使用%d通配符表示一个整型变量,当一个usb-skel类型的设备连接到USB总线后会按照子设备编号自动设置设备名称。fops是设备操作函数结构变量,定义如下:

 

static struct file_operations skel_fops = {

       .owner = THIS_MODULE,

       .read =      skel_read,      // 读操作

       .write = skel_write,         // 写操作

       .open =      skel_open,      // 打开操作

       .release =   skel_release,   // 关闭操作

};

 

skel_ops定义了usb-skel设备的操作函数。当在usb-skel设备上发生相关事件时,USB文件系统会调用对应的函数处理。

4.设备注销

skel_disconnect()函数在注销设备的时候被调用,定义如下:

 

static void skel_disconnect(struct usb_interface *interface)

{

       struct usb_skel *dev;

      int minor = interface->minor;

 

       /* prevent skel_open() from racing skel_disconnect() */

       lock_kernel();                       // 在操作之前加锁

 

       dev = usb_get_intfdata(interface);   // 获得USB设备接口描述

       usb_set_intfdata(interface, NULL);   // 设置USB设备接口描述无效

 

       /* give back our minor */

       usb_deregister_dev(interface, &skel_class);  // 注销USB设备操作描述

 

       unlock_kernel();                     // 操作完毕解锁

 

       /* decrement our usage count */

       kref_put(&dev->kref, skel_delete);           // 减小引用计数

 

       info("USB Skeleton #%d now disconnected", minor);

}

 

skel_disconnect()函数释放usb-skel设备用到的资源。首先获取USB设备接口描述,之后设置为无效;然后调用usb_deregister_dev()函数注销USB设备的操作描述符,注销操作本身需要加锁;注销设备描述符后,更新内核对usb-skel设备的引用计数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值