Linux USB驱动开发
USB驱动介绍
Linux内核支持两种主要类型的USB驱动程序:USB主机(Host)驱动程序和USB设备(device)驱动。主机驱动程序控制插入其中的USB设备,而USB设备驱动程序控制该设备如何作为一个USB设备和主机通信(注重的是方式)。
一、USB驱动概览
在Linux驱动中,处于USB驱动最底层的是USB主机控制器硬件,在其上的是USB主机控制器驱动,在主机控制器驱动上的为USB核心层,再上层为USB设备驱动层。
USB核心层(USB core)向上为USB设备驱动提供编程接口,向下为USB主机控制器驱动提供编程接口,维护整个系统的USB设备信息,完成设备热插拔控制、总线数据传输控制等。
USB设备驱动负责驱动具体的设备,根据需要可注册成某个类型的设备驱动,例如U盘(块设备),键鼠(输入子系统),网卡,USB虚拟串口(TTY)等设备。
二、USB设备构成
USB通信的最基本形式为:端点(endpoint)
USB端点被捆绑为接口,一个接口对应一个设备驱动。
举例:复合设备,包含多个接口,会匹配多个驱动
USB接口被捆绑为配置
三、USB设备的sysfs和proc表示
USB的sysfs设备命名方案:
根集线器-集线器端口号:配置.接口
例:/sys/devices/pci0000:00/xxx/usb2/2-1/2-1:1.0
从sysfs中获取到的USB设备信息只限于接口级别,若需要查看USB设备可选配置,接口相关的具体信息如端点等,可以从usbfs文件系统找到,该系统挂载到/proc/bus/usb/目录。该目录下包含sysfs下信息,也包含其他具体信息。
四、USB设备驱动与USB设备的匹配
khubd是USB守护进程,当USB设备插入的时候,守护进程监测到,USB主机控制器就会产生一个hub_irq中断,控制器调用hub的探测(probe)函数,来解析设备信息。
设备驱动程序将包含usb_device_id结构体的对象注册到USB子系统后,USB核心使用该列表为解析完成的USB设备匹配驱动程序。通常:先匹配USB VID和PID,若未匹配到,再匹配接口类别一致的类驱动。如:CDC-ACM驱动,U盘驱动等。
五、USB驱动实现
USB设备驱动的注册与注销
Usb设备驱动程序的主要数据结构是结构usb_driver,被用来向usb核心注册和注销驱动程序。
注册usb驱动
接口:usb_register
注销usb驱动
接口:usb_unregister_driver
实现USB设备操作函数集
驱动探测与断开
接口:probe/disconnect
挂起与恢复
接口:suspend/resume
如:CDC驱动中相应实现
static struct usb_driver acm_driver = {
.name = "cdc_acm",
.probe = acm_probe,
.disconnect = acm_disconnect,
#ifdef CONFIG_PM
.suspend = acm_suspend,
.resume = acm_resume,
.reset_resume = acm_reset_resume,
#endif
.pre_reset = acm_pre_reset,
.id_table = acm_ids,
#ifdef CONFIG_PM
.supports_autosuspend = 1,
#endif
.disable_hub_initiated_lpm = 1,
};
USB通信实现
Linux内核中USB代码通过URB(usb Request block)和所有USB设备通信,urb是以一种异步的方式往/从特定USB设备的特定端点发送/接收数据。
URB完整生命周期:
- 由USB设备驱动程序创建
- 分配给特定USB端点
- 由USB设备驱动程序提交给USB核心
- 由USB核心递交到特定设备的特定USB主控器驱动程序
- 由USB主控制器驱动程序处理,进行实际USB传送到设备
- 当URB完成,USB主控制器驱动程序通知USB设备驱动程序
USB Core也提供了进行简单USB数据收发的函数,以同步方式进行,可以避免管理URB的繁琐。接口:usb_control_msg/usb_bulk_msg