下面简要列出了要对 USB 设备进行电源管理时驱动程序需要执行的操作。后面对电源管理进行了较详细的说明。
在执行 attach(9E) 期间创建电源管理组件。请参见 usb_create_pm_components(9F) 手册页。
实现 power(9E) 入口点。
在访问设备之前调用 pm_busy_component(9F) 和 pm_raise_power(9F)。
完成设备访问后调用 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 底部说明的两种电源管理方案之一。被动方案比主动方案简单,这是因为被动方案在设备传输期间不进行电源管理。
在驱动程序的 attach(9E) 入口点执行以下工作:
可选择调用 usb_handle_remote_wakeup(9F)(使用 USB_REMOTE_WAKEUP_ENABLE 作为第二个参数),以在设备上启用远程唤醒。
调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。
与设备通信以初始化该设备。
在驱动程序的 detach(9E) 入口点执行以下工作:
调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。
如果在 attach(9E) 入口点中调用了 usb_handle_remote_wakeup (9F) 函数,请在此处调用 usb_handle_remote_wakeup(9F)(使用 USB_REMOTE_WAKEUP_DISABLE 作为第二个参数)。
与设备通信以干净地关闭该设备。
调用 pm_lower_power(9F) 以使功耗达到 USB_DEV_OS_PWR_OFF 级别。
这是唯一一次客户机驱动程序调用 pm_lower_power(9F)。
当驱动程序线程要启动在设备上执行 I/O 操作时,该线程将执行以下任务:
调用 pm_raise_power(9F) 以使功耗达到 USB_DEV_OS_FULL_PWR 级别。
开始 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) 例程中执行以下工作:
使所有打开的管道进入空闲状态。例如,停止对中断管道进行的轮询。
保存任何设备或需要保存的驱动程序上下文。
在完成 power(9E) 调用后,将暂停设备所连接到的端口。
收到设备启动的远程唤醒或系统启动的唤醒时,可以调用 power(9E) 例程以打开设备电源。由于超出空闲时间或系统暂停而关闭设备电源后,将会发生唤醒通知。如果设备将进入 USB_DEV_OS_PWR_1 或以上状态,请在 power(9E) 例程中执行以下工作:
恢复任何所需的设备和驱动程序上下文。
在管道中重新启动适合指定电源级别的活动。例如,对中断管道启动轮询。
如果先前暂停了设备所连接到的端口,则在调用 power(9E) 之前将恢复该端口。
被动电源管理方案比上面介绍的主动电源管理方案简单。在此被动方案中,在传输期间不执行任何电源管理。要实现此被动方案,请在打开设备时调用 pm_busy_component(9F) 和 pm_raise_power(9F)。然后在关闭设备时调用 pm_idle_component(9F)。