Power Management During Driver Development Environment
You can use Power Per Port Switch (PPPS) functionality to power-cycle a USB device during driver development.
Introduction to the Problem
To reduce my hardware footprint, I typically work on device driver development in a VM running on the same multi-use personal system that houses my notes, files, picture backup, etc. This works fine for general development if the kernel crashes often the device is becomes unresponsible without a power-cycle. That leaves me with one of two options:
- Remove and reinsert – This means you can only work when physically next to it, which is not always an option.
- Rebooting the entire machine – In a multi-use system, the latter is not a valid option.
At least for me, neither option is desireable.
Solution: Using Power per Port Switch (PPPS)
Some USB hubs allow you to control the power state of individual ports, effectively allowing you to power-cycle a device without unplugging it. You can check if your Hub support this feature by running lsusb -v
and searching for Per-port power switching
.
Then use the uhubctl utility to confirm your device is supported:
# ./uhubctl
...
Current status for hub 1-2 [05e3:0608 USB2.0 Hub, USB 2.00, 3 ports, ppps]
Port 1: 0303 power lowspeed enable connect [058f:9410 KINESIS CORPORATION KB800HM Kinesis Freestyle2 for Mac]
Port 2: 0503 power highspeed enable connect [05e3:0608 USB2.0 Hub, USB 2.00, 4 ports, ganged]
Port 3: 0100 power
Port 2 is another hub with an LED indicator so I can visually confirm the status, but connecting a device directly into the port worked just the same.
In my case I wanted to turn off port 2 on hub 1-2, so I ran the following command:
# ./uhubctl -l 1-2 -p 2 -a off
Current status for hub 1-2 [05e3:0608 USB2.0 Hub, USB 2.00, 3 ports, ppps]
Port 2: 0100 power
Sent power off request
New status for hub 1-2 [05e3:0608 USB2.0 Hub, USB 2.00, 3 ports, ppps]
Port 2: 0000 off
And looking over, the LED went dark. I waited a few seconds to power it back:
# ./uhubctl -l 1-2 -p 2 -a on
Current status for hub 1-2 [05e3:0608 USB2.0 Hub, USB 2.00, 3 ports, ppps]
Port 2: 0000 off
Sent power on request
New status for hub 1-2 [05e3:0608 USB2.0 Hub, USB 2.00, 3 ports, ppps]
Port 2: 0100 power
And we just simulates had a power cycle!
Working with Proxmox
Working with Proxmox as my Hypervisor, I scripted the attachment and detachment proceses as follows:
Attach:
echo Power on...
ssh proxmox uhubctl -l 1-2 -p 2 -a on
echo Sleep for 3 seconds...
sleep 3
echo Attaching...
qm set <MY VM ID> -usb0 host=1234:5678 > /dev/null
Detach:
echo Detatching...
ssh proxmox qm set <MY VM ID> -delete usb0 > /dev/null
echo Powering Off...
ssh proxmox uhubctl -l 1-2 -p 2 -a off > /dev/null
Every so often uhubctl
seems to inexplicably hang when the VM kernel has crashed. While I find it annoying, it is not significantly long enough for it to be a problem.
Where to get a hub supporting PPPS?
In my anecdotal experience, much older USB 1.1 or newer higher-end USB-C hubs support this feature, while the vast majority of commodity hubs do not. The uhubctl
github page lists several supported devices, but I could not find any of them on Amazon or Ebay. One reasonably priced and still available option is from VirtualHere.
Hope this helps someone going forward!