编写设备驱动程序

设备电源管理

下面简要列出了要对 USB 设备进行电源管理时驱动程序需要执行的操作。后面对电源管理进行了较详细的说明。

  1. 在执行 attach(9E) 期间创建电源管理组件。请参见 usb_create_pm_components(9F) 手册页。

  2. 实现 power(9E) 入口点。

  3. 在访问设备之前调用 pm_busy_component(9F)pm_raise_power(9F)

  4. 完成设备访问后调用 pm_idle_component(9F)

USBA 2.0 框架支持 USB 接口电源管理规范指定的四种电源级别。有关 USB 电源级别与操作系统电源级别对应关系的信息,请参见 /usr/include/sys/usb/usbai.h

当设备进入 USB_DEV_OS_PWR_OFF 状态时,hubd 驱动程序将暂停端口。当设备进入 USB_DEV_OS_PWR_1 及以上状态时,hubd 驱动程序将恢复端口。请注意,端口暂停不同于系统暂停。端口暂停时,将仅关闭 USB 端口。系统电源管理中定义了系统暂停。

客户机驱动程序可以选择在设备上启用远程唤醒。请参见 usb_handle_remote_wakeup(9F) 手册页。当 hubd 驱动程序在端口上发现远程唤醒时,hubd 驱动程序将完成唤醒操作,并调用 pm_raise_power(9F) 以通知子级。

下图显示了电源管理的不同部分之间的关系。

图 20–5 USB 电源管理

图中显示了使用两种不同电源管理方案的时机。

驱动程序可以实现图 20–5 底部说明的两种电源管理方案之一。被动方案比主动方案简单,这是因为被动方案在设备传输期间不进行电源管理。

主动电源管理

本节介绍实现主动电源管理方案需使用的函数。

在驱动程序的 attach(9E) 入口点执行以下工作:

  1. 调用 usb_create_pm_components(9F)

  2. 可选择调用 usb_handle_remote_wakeup(9F)(使用 USB_REMOTE_WAKEUP_ENABLE 作为第二个参数),以在设备上启用远程唤醒。

  3. 调用 pm_busy_component(9F)

  4. 调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。

  5. 与设备通信以初始化该设备。

  6. 调用 pm_idle_component(9F)

在驱动程序的 detach(9E) 入口点执行以下工作:

  1. 调用 pm_busy_component(9F)

  2. 调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。

  3. 如果在 attach(9E) 入口点中调用了 usb_handle_remote_wakeup (9F) 函数,请在此处调用 usb_handle_remote_wakeup(9F)(使用 USB_REMOTE_WAKEUP_DISABLE 作为第二个参数)。

  4. 与设备通信以干净地关闭该设备。

  5. 调用 pm_lower_power(9F) 以使功耗达到 USB_DEV_OS_PWR_OFF 级别。

    这是唯一一次客户机驱动程序调用 pm_lower_power(9F)。

  6. 调用 pm_idle_component(9F)

当驱动程序线程要启动在设备上执行 I/O 操作时,该线程将执行以下任务:

  1. 调用 pm_busy_component(9F)

  2. 调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。

  3. 开始 I/O 传输。

当驱动程序收到 I/O 传输已完成的通知时,驱动程序将调用 pm_idle_component(9F)

在驱动程序的 power(9E) 入口点中,检查您要转换到的电源级别是否有效。此外,还可能需要考虑同时调用 power(9E) 的不同线程。

如果设备已空闲一段时间或者系统正在关闭,则可以调用 power(9E) 例程以使设备进入 USB_DEV_OS_PWR_OFF 状态。此状态对应于图 20–4 中所示的 PWRED_DWN 状态。如果设备将进入 USB_DEV_OS_PWR_OFF 状态,请在 power(9E) 例程中执行以下工作:

  1. 使所有打开的管道进入空闲状态。例如,停止对中断管道进行的轮询。

  2. 保存任何设备或需要保存的驱动程序上下文。

    在完成 power(9E) 调用后,将暂停设备所连接到的端口。

收到设备启动的远程唤醒或系统启动的唤醒时,可以调用 power(9E) 例程以打开设备电源。由于超出空闲时间或系统暂停而关闭设备电源后,将会发生唤醒通知。如果设备将进入 USB_DEV_OS_PWR_1 或以上状态,请在 power(9E) 例程中执行以下工作:

  1. 恢复任何所需的设备和驱动程序上下文。

  2. 在管道中重新启动适合指定电源级别的活动。例如,对中断管道启动轮询。

如果先前暂停了设备所连接到的端口,则在调用 power(9E) 之前将恢复该端口。

被动电源管理

被动电源管理方案比上面介绍的主动电源管理方案简单。在此被动方案中,在传输期间不执行任何电源管理。要实现此被动方案,请在打开设备时调用 pm_busy_component(9F)pm_raise_power(9F)。然后在关闭设备时调用 pm_idle_component(9F)