How can I programmatically enable and disable the power to a particular USB port on Linux? Is such a thing even possible? Mac answers appreciated as well!
I was tryi
Don't buy an expensive smart hub just for turning USB gadgets on and off.
All you need is a microcontroller.
Arduino Nano™ ATmega328 *
The Nano is a 16MHz 8-bit computer with 2K RAM and 32K of flash storage.
It has 22 programmable pins (8 analog and 14 digital).
It can read/write USB, and is powered by its 5.0V microUSB port (up to 12.0V external).
// USB Blinker
// Blink LED while receiving USB stream
//
// For Arduino Nano™
int LED = 13;
// setup() is run once at powerup or when reset button is pressed
//
void setup() {
pinMode(LED, OUTPUT); // Configure pin D13 as output
Serial.begin(9600); // Open 9600bps USB stream
}
// loop() runs forever at 16Mhz, blinking the LED at 1Hz when receiving USB data.
//
void loop() {
if (Serial.available() > 0) { // When stream is buffering
digitalWrite(LED, HIGH); // turn on LED
delay(500); // wait half second
digitalWrite(LED, LOW); // turn off LED
delay(500); // wait half second
while (Serial.available() > 0) // drain the buffer
Serial.read();
}
}
Exquisite tiny cases are available (also free 3d printables).
C4Labs Zebra Black Ice Case
* Use Genuine Arduino Nano™ only. Beware of counterfeits.
UPDATE: Miniaturised ATtiny and wireless microcontollers are also available.
As I understand, your devices are supplied by USB power line VCC(~5V). The problem is that this power-line can't be controlled from user-space in standard linux framework, unless you interface your device with the hubs enabled with power-control. Ony kernel code can touch this power-line.
This is an example with a Logitech USB wireless mouse under linux.
Read relevant paragraph of "/proc/bus/usb/devices" according to your devices "Vendor" (vendor id) and "ProdID" (product id) or "Manufacturer" and "Product" (all these values are constant per device).
cat /proc/bus/usb/devices
(first paragraph with device powered on, second one with same device powered off but still pluged in)
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=1.5 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=046d ProdID=c50e Rev=25.10
S: Manufacturer=Logitech
S: Product=USB RECEIVER
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=1.5 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=046d ProdID=c50e Rev=25.10
S: Manufacturer=Logitech
S: Product=USB RECEIVER
C: #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms
You need two variables here. They are located in the "T:" line (first line of paragraph). These variables are : Bus (Bus=01 in this example) Cnt (Cnt=01 in this example)
You will need to add "1" (arithmetic one) to "Cnt" to get the rank Rank=Cnt+1 (this is a mathematical function, Rank=2 in this example)
So the device you are looking for is the following string : Bus-Rank (this is not a mathematical function, its a string, 1-2 in this example)
Mind also the "C:" line. It contains info regarding the power (current) of the device. If there is an asterisk in "C:" (like in our 1st example) then the device is powered. If not ("C:") then the device is "more or less" powered off meaning there is always a tiny current when a device is pluged, otherwise we wouldn't be able to read all this info.
Mind finaly the "I:" line. If the field "I:*" contains asterisk (like in our 1st example) then there is input, from or to the device, i am not sure, maybe both. The final line field contains the driver used ("usbhid" in our 1st example)
We are ready to switch the power of our device :
power off
echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/unbind
echo -n "1-2" > /sys/bus/usb/drivers/usb/unbind (in our example)
power on
echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/bind
echo -n "1-2" > /sys/bus/usb/drivers/usb/bind (in our example)
The following is a simple bash script "USBMS" (USB Mouse Switch) that controls the power of the device in our example above. It is not very dynamical and it uses the "Product" and "Manufacturer" constants to locate the relevant paragraph of "/proc/bus/usb/devices" You should use the "Vendor" (vendor id) and "ProdID" (product id) instead. It also checks the power state of the device. Run as superuser.
Command : ./USBMS action
parameter : action = "off" or "0" to power off - action = "on" or "1" to power on (without the quotes)
#!/bin/bash
USBmouseProduct="USB RECEIVER"
USBmouseManufacturer="Logitech"
signal=$1
nr3=$(awk '/Product='"$USBmouseProduct"'/ {print NR}' /proc/bus/usb/devices)
nr3=$(expr $nr3 + 0)
nr2=$(awk '/Manufacturer='"$USBmouseManufacturer"'/ {print NR}' /proc/bus/usb/devices)
nr2=$(expr $nr2 + 0)
nr1=$(expr $nr2 - 3)
nr4=$(expr $nr3 + 1)
nrdiff=$(expr $nr3 - $nr2)
[ $nr3 != 0 -a $nr2 != 0 -a $nrdiff = 1 ] && (
usbmbus0=$(awk 'NR=='$nr1' {print $2}' /proc/bus/usb/devices | awk -F= '{print $2}')
usbmbus=$(expr $usbmbus0 + 0)
usbmdev=$(awk 'NR=='$nr1' {print $8}' /proc/bus/usb/devices)
usbmrank=$(awk 'NR=='$nr1' {print $5}' /proc/bus/usb/devices | awk -F= '{print $2}')
usbmrank=$(expr $usbmrank + 1)
usbmbusrank="$usbmbus""-""$usbmrank"
usbmpower=$(awk 'NR=='$nr4' {if ( $1=="C:" ) {print 0}; if ( $1=="C:*" ) {print 1}}' /proc/bus/usb/devices)
case $signal in
off|0)
[ $usbmpower = 1 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/unbind
;;
on|1)
[ $usbmpower = 0 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/bind
;;
esac
)
I'd be more inclined to cut the wire and hook it up to a serial port w/ some type of simple relay running ofF one of the 'recieve ready'pin. Then you could just pull the line down (signal 'i'm ready to receive') to the serial port file every time there is some isssue. When it's done, just signal 'i'm full'
My understanding of those things, however, is that they draw a lot of current until they fully charge the capacitor, then release it all at once to flash the bulb. I can't imagine such a sudden discharge is good for the circuitry of the computer. you may need some diode current traps to prevent feedback into the serial port.
Every time my alarm goes off, the computer shuts down!
Digs through bookmarks
http://blog.andrew.net.au/2009/01/01#usb_power_control
Seems like you need to connect it to a hub and control the hub's power. None of the root hubs I have seen seems to be able to support power control.
There is a sys entry for this in Linux. From Documentation/usb/power-management.txt:
power/level
This file contains one of three words: "on", "auto", or "suspend". You can write those words to the file to change the device's setting. "on" means that the device should be resumed and autosuspend is not allowed. (Of course, system suspends are still allowed.) "auto" is the normal state in which the kernel is allowed to autosuspend and autoresume the device. "suspend" means that the device should remain suspended, and autoresume is not allowed. (But remote wakeup may still be allowed, since it is controlled separately by the power/wakeup attribute.)
Something like: echo on > /sys/bus/usb/devices/usb5/power/level
You may need to play with the autosuspend setting as well. Without telling the kernel to stop trying, it may suspend the port automatically.
Good luck!