diff options
Diffstat (limited to 'hub_ctrl.py')
-rw-r--r-- | hub_ctrl.py | 256 |
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 |