USB核心回调¶
usbcore会进行哪些回调?¶
Usbcore将通过驱动程序结构中定义的回调和驱动程序提交的URB的完成处理程序来调用驱动程序。只有前者在本文件的范围之内。这两种回调是完全独立的。关于完成回调的信息可以在USB请求块(URB)中找到。
驱动程序结构中定义的回调有:
热插拔回调
- @probe
调用以查看驱动程序是否愿意管理设备上的特定接口。
- @disconnect
当接口不再可访问时调用,通常是因为其设备已(或正在)断开连接或驱动程序模块正在卸载。
通过usbfs的奇怪后门
- @ioctl
用于希望通过“usbfs”文件系统与用户空间通信的驱动程序。这使设备能够提供向用户空间公开信息的方式,而不管它们是否以其他方式出现在文件系统中。
电源管理(PM)回调
- @suspend
当设备即将挂起时调用。
- @resume
当设备正在恢复时调用。
- @reset_resume
当挂起的设备已重置而不是恢复时调用。
设备级操作
- @pre_reset
在设备即将重置时调用。
- @post_reset
设备重置后调用
只有在您有非常好的理由时才应使用ioctl接口(2)。现在首选Sysfs。PM回调在USB电源管理中单独介绍。
调用约定¶
所有回调都是互斥的。无需针对其他USB回调进行锁定。所有回调都从任务上下文中调用。您可以睡眠。但是,重要的是所有睡眠都具有较小的固定时间上限。特别是,您不得调用用户空间并等待结果。
热插拔回调¶
这些回调旨在将驱动程序与接口关联和分离。驱动程序与接口的绑定是独占的。
probe()回调¶
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
接受或拒绝接口。如果您接受设备,则返回0,否则返回-ENODEV或-ENXIO。仅当初始化期间发生真正的错误,阻止驱动程序接受否则会被接受的设备时,才应使用其他错误代码。强烈建议您使用usbcore的工具usb_set_intfdata()
,将数据结构与接口关联,以便您知道将哪个内部状态和标识与特定接口关联。设备不会被挂起,您可以对您调用的接口和设备的端点0执行IO。时间不长的设备初始化在这里是个好主意。
disconnect()回调¶
void (*disconnect) (struct usb_interface *intf);
此回调是断开与接口的任何连接的信号。从此回调返回后,您不得对设备进行任何IO。您也不得执行任何可能干扰绑定到该接口的另一个驱动程序的操作,例如电源管理操作。必须在此回调返回之前完成或中止设备上的未完成操作。
如果您是由于物理断开连接而被调用的,则您的所有URB都将被usbcore杀死。请注意,在这种情况下,disconnect将在物理断开连接后的一段时间调用。因此,即使在回调之前,您的驱动程序也必须准备好处理失败的IO。
设备级回调¶
pre_reset¶
int (*pre_reset)(struct usb_interface *intf);
驱动程序或用户空间正在触发设备上的重置,该设备包含作为参数传递的接口。停止IO,等待所有未完成的URB完成,并保存您需要恢复的任何设备状态。在调用post_reset方法之前,不得提交更多URB。
如果您需要在此处分配内存,请使用GFP_NOIO或GFP_ATOMIC(如果您处于原子上下文中)。
post_reset¶
int (*post_reset)(struct usb_interface *intf);
重置已完成。恢复任何已保存的设备状态并再次开始使用该设备。
如果您需要在此处分配内存,请使用GFP_NOIO或GFP_ATOMIC(如果您处于原子上下文中)。
调用序列¶
对于未绑定到您的驱动程序的接口,不会调用除probe之外的任何回调。
永远不会为绑定到驱动程序的接口调用Probe。因此,在成功探测之后,在对同一接口进行另一次探测之前,将调用disconnect。
一旦您的驱动程序绑定到接口,就可以随时调用disconnect,除非在pre_reset和post_reset之间。pre_reset始终后跟post_reset,即使重置失败或设备已拔下。
suspend始终后跟以下之一:resume,reset_resume或disconnect。