4 hub_ctrl.py - a tool to control port power/led of USB hub
6 Copyright (C) 2006, 2011 Free Software Initiative of Japan
8 Author: NIIBE Yutaka <gniibe@fsij.org>
10 This file is a part of Gnuk, a GnuPG USB Token implementation.
12 Gnuk is free software: you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
17 Gnuk is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 USB_RT_HUB = (usb.TYPE_CLASS | usb.RECIP_DEVICE)
29 USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
30 USB_PORT_FEAT_RESET = 4
31 USB_PORT_FEAT_POWER = 8
32 USB_PORT_FEAT_INDICATOR = 22
33 USB_DIR_IN = 0x80 # device to host
41 def find_hubs(listing, verbose, busnum=None, devnum=None, hub=None):
42 number_of_hubs_with_feature = 0
46 raise ValueError, "can't access USB"
51 if dev.deviceClass != usb.CLASS_HUB:
57 and ((bus.dirname == busnum and dev.devnum == devnumd)
58 or hub == number_of_hubs_with_feature))):
65 # Get USB Hub descriptor
66 desc = uh.controlMsg(requestType = USB_DIR_IN | USB_RT_HUB,
67 request = usb.REQ_GET_DESCRIPTOR,
68 value = usb.DT_HUB << 8,
69 index = 0, buffer = 1024, timeout = 1000)
76 # desc[3] is lower byte of wHubCharacteristics
77 if (desc[3] & 0x80) == 0 and (desc[3] & 0x03) >= 2:
78 # Hub doesn't have features of controling port power/indicator
82 print "Hub #%d at %s:%03d" % (number_of_hubs_with_feature,
83 bus.dirname, dev.devnum)
84 if (desc[3] & 0x03) == 0:
85 print " INFO: ganged power switching."
86 elif (desc[3] & 0x03) == 1:
87 print " INFO: individual power switching."
88 elif (desc[3] & 0x03) == 2 or (desc[3] & 0x03) == 3:
89 print " WARN: no power switching."
91 if (desc[3] & 0x80) == 0:
92 print " WARN: Port indicators are NOT supported."
94 hubs.append({ 'busnum' : bus.dirname, 'devnum' : dev.devnum,
95 'indicator_support' : (desc[3] & 0x80) == 0x80,
96 'dev' : dev, 'num_ports' : desc[2] })
97 number_of_hubs_with_feature += 1
101 def hub_port_status(handle, num_ports):
102 print " Hub Port Status:"
103 for i in range(num_ports):
105 status = handle.controlMsg(requestType = USB_RT_PORT | usb.ENDPOINT_IN,
106 request = usb.REQ_GET_STATUS,
108 index = port, buffer = 4,
111 print " Port %d: %02x%02x.%02x%02x" % (port, status[3], status[2],
112 status[1], status[0]),
141 COMMAND_SET_POWER = 2
145 print >> sys.stderr, """Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}]
146 [-P PORT] [{-p [VALUE]|-l [VALUE]}]
149 def exit_with_usage(progname):
153 if __name__ == '__main__':
160 cmd = COMMAND_SET_NONE
162 if len(sys.argv) == 1:
166 while len(sys.argv) >= 2:
170 if busnum != None or devnum != None:
171 exit_with_usage(sys.argv[0])
172 hub = int(sys.argv[1])
175 busnum = int(sys.argv[1])
178 devnum = int(sys.argv[1])
181 port = int(sys.argv[1])
184 if cmd != COMMAND_SET_NONE:
185 exit_with_usage(sys.argv[0])
186 if len(sys.argv) > 1:
187 value = int(sys.argv[1])
190 value = HUB_LED_GREEN
191 cmd = COMMAND_SET_LED
193 if cmd != COMMAND_SET_NONE:
194 exit_with_usage(sys.argv[0])
195 if len(sys.argv) > 1:
196 value = int(sys.argv[1])
200 cmd = COMMAND_SET_POWER
203 if len(sys.argv) == 1:
206 exit_with_usage(sys.argv[0])
208 exit_with_usage(sys.argv[0])
210 if ((busnum != None and devnum == None)
211 or (busnum == None and devnum != None)):
212 exit_with_usage(sys.argv[0])
214 if hub == None and busnum == None:
215 hub = 0 # Default hub = 0
217 if cmd == COMMAND_SET_NONE:
218 cmd = COMMAND_SET_POWER
220 hubs = find_hubs(listing, verbose, busnum, devnum, hub)
222 print >> sys.stderr, "No hubs found."
229 if h['busnum'] == busnum and h['devnum'] == devnum:
231 nports = h['num_ports']
233 dev_hub = hubs[hub]['dev']
234 nports = hubs[hub]['num_ports']
237 if cmd == COMMAND_SET_POWER:
238 feature = USB_PORT_FEAT_POWER
241 request = usb.REQ_SET_FEATURE
243 request = usb.REQ_CLEAR_FEATURE
245 request = usb.REQ_SET_FEATURE
246 feature = USB_PORT_FEAT_INDICATOR
247 index = (value << 8) | port
249 print "Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d) " % (request, feature, index)
251 uh.controlMsg(requestType = USB_RT_PORT, request = request, value = feature,
252 index = index, buffer = None, timeout = 1000)
254 hub_port_status(uh,nports)