blob: 9c98fa6fd5c5c0a8a990a61a3cfdba0779fc339d [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import re
from pylib import cmd_helper
_INDENTATION_RE = re.compile(r'^( *)')
_LSUSB_BUS_DEVICE_RE = re.compile(r'^Bus (\d{3}) Device (\d{3}):')
_LSUSB_ENTRY_RE = re.compile(r'^ *([^ ]+) +([^ ]+) *([^ ].*)?$')
_LSUSB_GROUP_RE = re.compile(r'^ *([^ ]+.*):$')
_USBDEVFS_RESET = ord('U') << 8 | 20
def lsusb():
"""Call lsusb and return the parsed output."""
lsusb_raw_output = cmd_helper.GetCmdOutput(['lsusb', '-v'])
device = None
devices = []
depth_stack = []
for line in lsusb_raw_output.splitlines():
if not line:
if device:
devices.append(device)
device = None
continue
if not device:
m = _LSUSB_BUS_DEVICE_RE.match(line)
if m:
device = {
'bus': m.group(1),
'device': m.group(2)
}
depth_stack = [device]
continue
indent_match = _INDENTATION_RE.match(line)
if not indent_match:
continue
depth = 1 + len(indent_match.group(1)) / 2
if depth > len(depth_stack):
logging.error('lsusb parsing error: unexpected indentation: "%s"', line)
continue
while depth < len(depth_stack):
depth_stack.pop()
cur = depth_stack[-1]
m = _LSUSB_GROUP_RE.match(line)
if m:
new_group = {}
cur[m.group(1)] = new_group
depth_stack.append(new_group)
continue
m = _LSUSB_ENTRY_RE.match(line)
if m:
new_entry = {
'_value': m.group(2),
'_desc': m.group(3),
}
cur[m.group(1)] = new_entry
depth_stack.append(new_entry)
continue
logging.error('lsusb parsing error: unrecognized line: "%s"', line)
if device:
devices.append(device)
return devices
def get_lsusb_serial(device):
return device.get('Device Descriptor', {}).get('iSerial', {}).get('_desc')
def get_android_devices():
return [serial for serial in (get_lsusb_serial(d) for d in lsusb())
if serial]