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 )