summaryrefslogtreecommitdiff
path: root/hub_ctrl.py
diff options
context:
space:
mode:
Diffstat (limited to 'hub_ctrl.py')
-rw-r--r--hub_ctrl.py256
1 files changed, 256 insertions, 0 deletions
diff --git a/hub_ctrl.py b/hub_ctrl.py
new file mode 100644
index 0000000..684b3bd
--- /dev/null
+++ b/hub_ctrl.py
@@ -0,0 +1,256 @@
+#! /usr/bin/python
+
+"""
+hub_ctrl.py - a tool to control port power/led of USB hub
+
+Copyright (C) 2006, 2011 Free Software Initiative of Japan
+
+Author: NIIBE Yutaka <gniibe@fsij.org>
+
+This file is a part of Gnuk, a GnuPG USB Token implementation.
+
+Gnuk is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Gnuk is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import usb
+
+USB_RT_HUB = (usb.TYPE_CLASS | usb.RECIP_DEVICE)
+USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
+USB_PORT_FEAT_RESET = 4
+USB_PORT_FEAT_POWER = 8
+USB_PORT_FEAT_INDICATOR = 22
+USB_DIR_IN = 0x80 # device to host
+
+COMMAND_SET_NONE = 0
+COMMAND_SET_LED = 1
+COMMAND_SET_POWER = 2
+
+HUB_LED_GREEN = 2
+
+def find_hubs(listing, verbose, busnum=None, devnum=None, hub=None):
+ number_of_hubs_with_feature = 0
+ hubs = []
+ busses = usb.busses()
+ if not busses:
+ raise ValueError, "can't access USB"
+
+ for bus in busses:
+ devices = bus.devices
+ for dev in devices:
+ if dev.deviceClass != usb.CLASS_HUB:
+ continue
+
+ printout_enable = 0
+ if (listing
+ or (verbose
+ and ((bus.dirname == busnum and dev.devnum == devnumd)
+ or hub == number_of_hubs_with_feature))):
+ printout_enable = 1
+
+ uh = dev.open()
+
+ desc = None
+ try:
+ # Get USB Hub descriptor
+ desc = uh.controlMsg(requestType = USB_DIR_IN | USB_RT_HUB,
+ request = usb.REQ_GET_DESCRIPTOR,
+ value = usb.DT_HUB << 8,
+ index = 0, buffer = 1024, timeout = 1000)
+ finally:
+ del uh
+
+ if not desc:
+ continue
+
+ # desc[3] is lower byte of wHubCharacteristics
+ if (desc[3] & 0x80) == 0 and (desc[3] & 0x03) >= 2:
+ # Hub doesn't have features of controling port power/indicator
+ continue
+
+ if printout_enable:
+ print "Hub #%d at %s:%03d" % (number_of_hubs_with_feature,
+ bus.dirname, dev.devnum)
+ if (desc[3] & 0x03) == 0:
+ print " INFO: ganged power switching."
+ elif (desc[3] & 0x03) == 1:
+ print " INFO: individual power switching."
+ elif (desc[3] & 0x03) == 2 or (desc[3] & 0x03) == 3:
+ print " WARN: no power switching."
+
+ if (desc[3] & 0x80) == 0:
+ print " WARN: Port indicators are NOT supported."
+
+ hubs.append({ 'busnum' : bus.dirname, 'devnum' : dev.devnum,
+ 'indicator_support' : (desc[3] & 0x80) == 0x80,
+ 'dev' : dev, 'num_ports' : desc[2] })
+ number_of_hubs_with_feature += 1
+
+ return hubs
+
+def hub_port_status(handle, num_ports):
+ print " Hub Port Status:"
+ for i in range(num_ports):
+ port = i + 1
+ status = handle.controlMsg(requestType = USB_RT_PORT | usb.ENDPOINT_IN,
+ request = usb.REQ_GET_STATUS,
+ value = 0,
+ index = port, buffer = 4,
+ timeout = 1000)
+
+ print " Port %d: %02x%02x.%02x%02x" % (port, status[3], status[2],
+ status[1], status[0]),
+ if status[1] & 0x10:
+ print " indicator",
+ if status[1] & 0x08:
+ print " test" ,
+ if status[1] & 0x04:
+ print " highspeed",
+ if status[1] & 0x02:
+ print " lowspeed",
+ if status[1] & 0x01:
+ print " power",
+
+ if status[0] & 0x10:
+ print " RESET",
+ if status[0] & 0x08:
+ print " oc",
+ if status[0] & 0x04:
+ print " suspend",
+ if status[0] & 0x02:
+ print " enable",
+ if status[0] & 0x01:
+ print " connect",
+
+ print
+
+import sys
+
+COMMAND_SET_NONE = 0
+COMMAND_SET_LED = 1
+COMMAND_SET_POWER = 2
+HUB_LED_GREEN = 2
+
+def usage(progname):
+ print >> sys.stderr, """Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}]
+ [-P PORT] [{-p [VALUE]|-l [VALUE]}]
+""" % progname
+
+def exit_with_usage(progname):
+ usage(progname)
+ exit(1)
+
+if __name__ == '__main__':
+ busnum = None
+ devnum = None
+ listing = False
+ verbose = False
+ hub = None
+ port = 1
+ cmd = COMMAND_SET_NONE
+
+ if len(sys.argv) == 1:
+ listing = True
+ else:
+ try:
+ while len(sys.argv) >= 2:
+ option = sys.argv[1]
+ sys.argv.pop(1)
+ if option == '-h':
+ if busnum != None or devnum != None:
+ exit_with_usage(sys.argv[0])
+ hub = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-b':
+ busnum = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-d':
+ devnum = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-P':
+ port = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-l':
+ if cmd != COMMAND_SET_NONE:
+ exit_with_usage(sys.argv[0])
+ if len(sys.argv) > 1:
+ value = int(sys.argv[1])
+ sys.argv.pop(1)
+ else:
+ value = HUB_LED_GREEN
+ cmd = COMMAND_SET_LED
+ elif option == '-p':
+ if cmd != COMMAND_SET_NONE:
+ exit_with_usage(sys.argv[0])
+ if len(sys.argv) > 1:
+ value = int(sys.argv[1])
+ sys.argv.pop(1)
+ else:
+ value = 0
+ cmd = COMMAND_SET_POWER
+ elif option == '-v':
+ verbose = True
+ if len(sys.argv) == 1:
+ listing = True
+ else:
+ exit_with_usage(sys.argv[0])
+ except:
+ exit_with_usage(sys.argv[0])
+
+ if ((busnum != None and devnum == None)
+ or (busnum == None and devnum != None)):
+ exit_with_usage(sys.argv[0])
+
+ if hub == None and busnum == None:
+ hub = 0 # Default hub = 0
+
+ if cmd == COMMAND_SET_NONE:
+ cmd = COMMAND_SET_POWER
+
+ hubs = find_hubs(listing, verbose, busnum, devnum, hub)
+ if len(hubs) == 0:
+ print >> sys.stderr, "No hubs found."
+ exit(1)
+ if listing:
+ exit(0)
+
+ if hub == None:
+ for h in hubs:
+ if h['busnum'] == busnum and h['devnum'] == devnum:
+ dev_hub = h['dev']
+ nports = h['num_ports']
+ else:
+ dev_hub = hubs[hub]['dev']
+ nports = hubs[hub]['num_ports']
+
+ uh = dev_hub.open()
+ if cmd == COMMAND_SET_POWER:
+ feature = USB_PORT_FEAT_POWER
+ index = port
+ if value:
+ request = usb.REQ_SET_FEATURE
+ else:
+ request = usb.REQ_CLEAR_FEATURE
+ else:
+ request = usb.REQ_SET_FEATURE
+ feature = USB_PORT_FEAT_INDICATOR
+ index = (value << 8) | port
+ if verbose:
+ print "Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d) " % (request, feature, index)
+
+ uh.controlMsg(requestType = USB_RT_PORT, request = request, value = feature,
+ index = index, buffer = None, timeout = 1000)
+ if verbose:
+ hub_port_status(uh,nports)
+
+ del uh