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
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
)