USB核心回调

usbcore会进行哪些回调?

Usbcore将通过驱动程序结构中定义的回调和驱动程序提交的URB的完成处理程序来调用驱动程序。只有前者在本文件的范围之内。这两种回调是完全独立的。关于完成回调的信息可以在USB请求块(URB)中找到。

驱动程序结构中定义的回调有:

  1. 热插拔回调

  • @probe

    调用以查看驱动程序是否愿意管理设备上的特定接口。

  • @disconnect

    当接口不再可访问时调用,通常是因为其设备已(或正在)断开连接或驱动程序模块正在卸载。

  1. 通过usbfs的奇怪后门

  • @ioctl

    用于希望通过“usbfs”文件系统与用户空间通信的驱动程序。这使设备能够提供向用户空间公开信息的方式,而不管它们是否以其他方式出现在文件系统中。

  1. 电源管理(PM)回调

  • @suspend

    当设备即将挂起时调用。

  • @resume

    当设备正在恢复时调用。

  • @reset_resume

    当挂起的设备已重置而不是恢复时调用。

  1. 设备级操作

  • @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。