libccid and USB selective suspend

I committed in revision 5706 a patch to activate the USB automatic power suspend. The idea is to power off a reader when it is not used.

What is it?

From the LessWatts page about Device and Bus Power Management:

USB selective suspend

This is a project in progress for the USB subsystem. USB selective suspend allows you to suspend a USB device on demand. If one device doesn't support selective suspend, then the entire bus must remain active. This not only consumes USB bus power unnecessarily, but also prevents the CPU from entering lower power states.
It should be a good idea to use the USB selective suspend for USB smart card readers.

How does it work?

The very good news is that USB selective suspend is managed by the kernel itself when set in automatic mode. The libccid driver source code do not have to be changed in any way.

The only thing to do is to tell the kernel to use the automatic mode (instead of always on mode). This can be done by a udev rule. Since libccid version 1.4.1 a udev rule file is provided to set the access rights for the pcscd auto start feature.

I just needed to a new line to the udev rule file to enable the automatic USB selective suspend:
ENV{ID_USB_INTERFACES}=="*:0b0000:*", RUN+="/bin/sh -c 'echo auto > /sys/$devpath/power/level ; echo auto > /sys/$devpath/power/control'"


Details

For every device with ID_USB_INTERFACES set to 0xB or 11 (CCID devices) do:
  • echo auto in /sys/$devpath/power/level
  • echo auto in /sys/$devpath/power/control

$devpath will be expanded by udev to something like bus/usb/devices/8-1.3. So the full filename is something like /sys/bus/usb/devices/8-1.3/power/level.

I use two echo lines because .../power/level is used in "old" kernels like the 2.6.32 used by Debian squeeze (stable) but has been deprecated in Linux kernel 2.6.35 and replaced by .../power/control. So to be able to work on a majority of kernel versions I use both filenames. The old filename should be removed at some point in the future.

Automatic USB selective suspend does work if no process if using the USB device. So pcscd must not be running so no driver is using the USB device. Since pcscd auto start feature, pcscd also does an auto stop so if no application is using the PC/SC API no pcscd should be running and then the kernel will be able to suspend unused USB smart card readers.

The default kernel timeout is 2 seconds. So 2 seconds after pcscd exits the USB smart card readers should be suspended. For example with my Gemalto PC Twin reader the LED will stop blinking and will be off.

Possible issues

I have not used many different readers with this change. So it may be possible that some readers does not support well the USB selective suspend.

Conclusion

I have not measured the power saving of this new feature. The MaxPower (returned by lsusb) of the Gemalto PC Twin reader is 200mA. But I guess the power really consumed if less than that. And on a desktop computer the difference will be quiet small.

But if you have a laptop and you rarely use your smart card reader the saving will be more interesting.