You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.6 KiB
85 lines
2.6 KiB
2 months ago
|
# License: Apache 2.0. See LICENSE file in root directory.
|
||
|
# Copyright(c) 2021 Intel Corporation. All Rights Reserved.
|
||
|
|
||
|
"""
|
||
|
USB interface library for Linux
|
||
|
|
||
|
Uses the lsusb built-in utility. Be careful to cache results or else it will
|
||
|
run every call!
|
||
|
"""
|
||
|
|
||
|
from rspy import log
|
||
|
import re, subprocess
|
||
|
|
||
|
|
||
|
def itree():
|
||
|
"""
|
||
|
Yields all device interfaces from 'lsusb -t' in tuples:
|
||
|
(bus, device, interface, ports)
|
||
|
All integers, and ports is a list of port numbers.
|
||
|
"""
|
||
|
df = subprocess.run( ['lsusb', '-t'],
|
||
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||
|
universal_newlines=True, timeout=2 )
|
||
|
bus = None
|
||
|
ports = []
|
||
|
for i in df.stdout.split('\n'):
|
||
|
if not i:
|
||
|
continue
|
||
|
spaces = len(i) - len(i.lstrip())
|
||
|
if spaces % 4:
|
||
|
raise ValueError( f'invalid number of spaces ({spaces}) in "{i}"')
|
||
|
indent = int(spaces / 4)
|
||
|
if indent == 0:
|
||
|
match = re.search( r'Bus (\d+).', i )
|
||
|
if not match:
|
||
|
raise ValueError( f'expected "Bus #." in "{i}"' )
|
||
|
bus = int( match.group(1) )
|
||
|
ports = []
|
||
|
continue
|
||
|
match = re.search( r'Port (\d+): Dev (\d+), If (\d+),', i )
|
||
|
if not match:
|
||
|
raise ValueError( f'unexpected format in "{i}"')
|
||
|
continue
|
||
|
while indent <= len(ports):
|
||
|
ports.pop()
|
||
|
port = int( match.group(1) )
|
||
|
ports.append( port )
|
||
|
device = int( match.group(2) )
|
||
|
interface = int( match.group(3) )
|
||
|
bus_device = f'{bus}-{device}'
|
||
|
yield (bus, device, interface, ports)
|
||
|
|
||
|
|
||
|
def tree():
|
||
|
"""
|
||
|
Yields all devices from 'lsusb -t' in tuples:
|
||
|
(device-id, ports)
|
||
|
Where both are strings: '<bus>-<device>' as device-id and '<bus>-<port#>(.<port#>)*' for the
|
||
|
port representation.
|
||
|
"""
|
||
|
devices = set()
|
||
|
for b,d,i,p in itree():
|
||
|
device_id = f'{b}-{d}'
|
||
|
if device_id not in devices:
|
||
|
devices.add( device_id )
|
||
|
port = f'{b}-' + '.'.join( [str(n) for n in p] )
|
||
|
yield (device_id, port)
|
||
|
|
||
|
|
||
|
def devices_by_vendor( vid ):
|
||
|
"""
|
||
|
"""
|
||
|
df = subprocess.run( ['lsusb', '-d', vid + ':'],
|
||
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||
|
universal_newlines=True, timeout=2 )
|
||
|
for i in df.stdout.split('\n'):
|
||
|
if i:
|
||
|
match = re.search( r'^Bus (\d+) Device (\d+):', i )
|
||
|
if not match:
|
||
|
raise ValueError( i )
|
||
|
bus = int( match.group(1) )
|
||
|
device = int( match.group(2) )
|
||
|
yield f'{bus}-{device}'
|
||
|
|