LINUX中USB驱动架构—设备驱动

一、usb_driver结构体描述一个USB设备驱动

usb_driver

复制代码
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 (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,10 void *buf);

  int (*suspend) (struct usb_interface *intf, pm_message_t message);
  int (*resume) (struct usb_interface *intf);
  int (*reset_resume)(struct usb_interface *intf);

  int (*pre_reset)(struct usb_interface *intf);
  int (*post_reset)(struct usb_interface *intf);
 
  const struct usb_device_id *id_table;
 
  struct usb_dynids dynids;
  struct usbdrv_wrap drvwrap;
  unsigned int no_dynamic_id:1;
  unsigned int supports_autosuspend:1;
  unsigned int disable_hub_initiated_lpm:1;
  unsigned int soft_unbind:1;
};

二、编写USB设备驱动

在编写新的USB设备驱动时,主要应该完成的工作是probe()和disconnect()函数,即探测和断开函数,它们分别在设备被插入和拔出的时候调用,用于初始化和释放软硬件资源。对usb_driver的注册和 注销可通过下面两个函数完成:

复制代码
int usb_register(struct usb_driver *new_driver);
void usb_deregister(struct usb_driver *driver);

usb_driver结构体中的id_table成员描述了这个USB驱动所支持的USB设备列表,它指向一个

usb_device_id数组,usb_device_id结构体包含有USB设备的制造商ID、产品ID、产品版本、设备类、接口类等信息及其要匹配标志成员match_flags(标明要与哪些成员匹配,包含DEV_LO、DEV_HI、DEV_CLASS、DEV_SUBCLASS、DEV_PROTOCOL、INT_CLASS、INT_SUBCLASS、INT_PROTOCOL)。

可以借助下面一组宏来生成usb_device_id结构体的实例:

复制代码
USB_DEVICE(vendor, product);

该宏根据制造商ID和产品ID生成一个usb_device_id结构体的实例,在数组中增加该元素将意味着该驱 动可支持与制造商ID、产品ID匹配的设备。

复制代码
USB_DEVICE_VER(vendor, product, lo, hi);

该宏根据制造商ID、产品ID、产品版本的最小值和最大值生成一个usb_device_id结构体的实例,在数 组中增加该元素将意味着该驱动可支持与制造商ID、产品ID匹配和lo~hi范围内版本的设备。

复制代码
USB_DEVICE_INFO(class, subclass, protocol);

该宏用于创建一个匹配设备指定类型的usb_device_id结构体实例。

复制代码
USB_INTERFACE_INFO(class, subclass, protocol);

该宏用于创建一个匹配接口指定类型的usb_device_id结构体实例。


usb_device_id结构体数组实例

两个用于描述某USB驱动支持的USB设备的usb_device_id结构体数组实例

复制代码
/* 本驱动支持的USB设备列表 */
 
 /* 实例1 */
static struct usb_device_id id_table [] = {
  { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
  { },
};
 MODULE_DEVICE_TABLE (usb, id_table);
 
/* 实例2 */
static struct usb_device_id id_table [] = {
 { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },13 { },
};
MODULE_DEVICE_TABLE (usb, id_table);

当USB核心检测到某个设备的属性和某个驱动程序的usb_device_id结构体所携带的信息一致时,这个 驱动程序的probe()函数就被执行(如果这个USB驱动是个模块的话,相关的.ko还应被Linux自动加载)。拔掉设备或者卸掉驱动模块后,USB核心就执行disconnect()函数来响应这个动作。

上述usb_driver结构体中的函数是USB设备驱动中与USB相关的部分,而USB只是一个总线,USB设备 驱动真正的主体工作仍然是USB设备本身所属类型的驱动,如字符设备、tty设备、块设备、输入设备等。 因此USB设备驱动包含其作为总线上挂接设备的驱动和本身所属设备类型的驱动两部分。

与platform_driver、i2c_driver类似,usb_driver起到了"牵线"的作用,即在probe()里注册相应的字符、tty等设备,在disconnect()注销相应的字符、tty等设备,而原先对设备的注册和注销一般直接发生在模块加载和卸载函数中。

相关推荐
aitav037 分钟前
⚡ WSL2 搭建 s5p6818 Linux 嵌入式开发平台 (part 3):Wifi驱动移植、ssh移植、e2fsprogs移植
linux·wifi·ssh·嵌入式·e2fsprogs
南枝异客3 小时前
CentOS 7 网络连接问题
linux·运维·centos
牛奶咖啡134 小时前
实现Linux的ssh免密登录实操保姆级教程
linux·ssh·生成ssh密钥对的三种方法·添加公钥到需ssh免登录服务器·测试ssh免登录的服务器·生产环境linux的优化策略
zhangrelay5 小时前
操作系统全解析:Windows、macOS与Linux的深度对比与选择指南(AI)
linux·笔记·学习
阿方索6 小时前
Linux 正则表达式
linux·运维
金色熊族7 小时前
ubuntu20.04编译qt源码5.15.3
linux·c++·qt
zhaotiannuo_19988 小时前
【Linux CentOS 7 版本更换yum源】
linux
aitav09 小时前
⚡ WSL2 搭建 s5p6818 Linux 嵌入式开发平台(part 1):环境准备与架构设计
linux·嵌入式·wsl·wsl2
一袋米扛几楼989 小时前
【软件安全】fgets / strncpy / gets(不安全) / snprintf的对比
linux·服务器·安全
防搞活机10 小时前
ubuntu 服务器(带NVLink)更新显卡驱动 (巨坑!!)
linux·服务器·深度学习·ubuntu·gpu算力·显卡驱动