7 See documentation for brainstem here:
8 https://acroname.com/reference/api/python/index.html
11 from rspy
import log, device_hub
15 if __name__ ==
'__main__':
16 import os, sys, getopt
18 ourname = os.path.basename( sys.argv[0] )
19 print(
'Syntax: acroname [options]' )
20 print(
' Control the acroname USB hub' )
22 print(
' --enable Enable all ports' )
23 print(
' --disable Disable all ports' )
24 print(
' --recycle Recycle all ports' )
25 print(
' --reset Reset the acroname' )
28 opts,args = getopt.getopt( sys.argv[1:],
'',
29 longopts = [
'help',
'recycle',
'enable',
'disable',
'reset' ])
30 except getopt.GetoptError
as err:
40 except ModuleNotFoundError:
41 log.d(
'no acroname library is available' )
46 super().
__init__( self, message
or 'no Acroname module found' )
59 def connect(self, reset = False, req_spec = None ):
61 Connect to the hub. Raises RuntimeError on failure
62 :param reset: When true, the acroname will be reset as part of the connection process
63 :param req_spec: Required spec to connect to.
66 self.
hub = brainstem.stem.USBHub3p()
74 result = self.
hub.connectFromSpec( spec )
75 if result != brainstem.result.Result.NO_ERROR:
76 raise RuntimeError(
"failed to connect to Acroname (result={})".format( result ))
78 log.d(
'connected to', spec )
81 log.d(
"resetting Acroname...")
82 result = self.
hub.system.reset()
91 result = self.
hub.connectFromSpec(spec)
92 if result != brainstem.result.Result.NO_ERROR:
97 raise RuntimeError(
"failed to reconnect to Acroname (result={})".format(result))
101 return self.
hub is not None and self.
hub.isConnected()
113 :return: a list of all possible ports, even if currently unoccupied or disabled
120 :return: a list of all ports currently occupied (and enabled)
125 occupied_ports.append( port )
126 return occupied_ports
131 query if the input port number is enabled through Acroname
132 It doesn't mean the device is enumerated as sometimes if the FW crashed we can have a situation where the port is "Disconnected" and not "OK"
133 :param port: port number;
134 :return: True if Acroname enabled this port, False otherwise
141 if port < 0
or port > 7:
142 raise ValueError(
"port number must be [0-7]" )
144 status = self.
hub.usb.getPortState( port )
151 https://acroname.com/reference/devices/usbhub3p/entities/usb.html#usb-port-state
152 Bit | Port State: Result Bitwise Description
153 -----------------------------------------------
154 0 | USB Vbus Enabled - Port is Disabled/Enabled by the Acroname
155 1 | USB2 Data Enabled
157 3 | USB3 Data Enabled
159 11 | USB2 Device Attached
160 12 | USB3 Device Attached
163 20 | USB2 Boost Enabled
172 return "Disconnected"
175 return "Unknown Error ({})".format( bitmask )
178 def enable_ports(self, ports = None, disable_other_ports = False, sleep_on_change = 0 ):
180 Set enable state to provided ports
181 :param ports: List of port numbers; if not provided, enable all ports
182 :param disable_other_ports: if True, the ports not in the list will be disabled
183 :param sleep_on_change: Number of seconds to sleep if any change is made
184 :return: True if no errors found, False otherwise
190 if ports
is None or port
in ports:
193 action_result = self.
hub.usb.setPortEnable( port )
194 if action_result != brainstem.result.Result.NO_ERROR:
196 log.e(
"Failed to enable port", port)
200 elif disable_other_ports:
203 action_result = self.
hub.usb.setPortDisable( port )
204 if action_result != brainstem.result.Result.NO_ERROR:
209 if changed
and sleep_on_change:
211 time.sleep( sleep_on_change )
218 :param ports: List of port numbers; if not provided, disable all ports
219 :param sleep_on_change: Number of seconds to sleep if any change is made
220 :return: True if no errors found, False otherwise
225 if ports
is None or port
in ports:
228 action_result = self.
hub.usb.setPortDisable( port )
229 if action_result != brainstem.result.Result.NO_ERROR:
231 log.e(
"Failed to disable port", port)
234 if changed
and sleep_on_change:
236 time.sleep( sleep_on_change )
243 Set USB ports to USB2
246 portlist = self.
ports()
250 for port
in portlist:
251 self.
hub.usb.setSuperSpeedDataEnable( port )
252 self.
hub.usb.setHiSpeedDataEnable( port )
253 self.
hub.usb.setSuperSpeedDataDisable( port )
258 Set USB ports to support USB3
261 portlist = self.
ports()
265 for port
in portlist:
266 self.
hub.usb.setSuperSpeedDataEnable( port )
267 self.
hub.usb.setHiSpeedDataEnable( port )
268 self.
hub.usb.setHiSpeedDataDisable( port )
274 if port < 0
or port > 7:
275 raise ValueError(
"port number can be only within 0 and 7 (inclusive)")
277 micro_volt = self.
hub.usb.getPortVoltage( port )
278 micro_curr = self.
hub.usb.getPortCurrent( port )
279 volt = float(micro_volt.value) / 10.0 ** 6
280 amps = float(micro_curr.value) / 10.0 ** 6
284 if 'windows' in platform.system().lower():
291 match = re.fullmatch(
r'Port_#(\d+)\.Hub_#(\d+)', usb_location, re.IGNORECASE)
296 split_location = [int(x)
for x
in usb_location.split(
'.')]
299 get_last_two_digits =
lambda array: tuple(
300 reversed(list(reversed([i
for i
in array
if i != 0]))[:2]))
302 first_index, second_index = get_last_two_digits(split_location)
311 self.
all_hubs = set(device_hub.find_all_hubs(
'24ff'))
333 if usb_location.startswith(port +
'.'):
334 match = re.search(
r'^(\d+)\.(\d+)', usb_location[len(port) + 1:])
341 Return all Acroname module specs in a list. Raise NoneFoundError if one is not found!
346 log.d(
'discovering Acroname modules ...')
349 for i
in range(retries + 1):
350 specs = brainstem.discover.findAllModules(brainstem.link.Spec.USB)
367 Based on last two USB location index, provide the port number
369 acroname_port_usb_map = {(4, 4): 0,
378 return acroname_port_usb_map[(first_usb_index, second_usb_index)]
382 if __name__ ==
'__main__':
385 if opt
in (
'--enable'):
387 acroname.enable_ports()
388 elif opt
in (
'--disable'):
390 acroname.disable_ports()
391 elif opt
in (
'--recycle'):
393 acroname.enable_ports()
394 acroname.recycle_ports()
395 elif opt
in (
'--reset'):
396 acroname.connect( reset =
True )