Add ICU message format support
[chromium-blink-merge.git] / build / android / devil / utils / reset_usb.py
blob95a6b15b397769227eb520701645d695445e089a
1 #!/usr/bin/env python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 import argparse
7 import fcntl
8 import logging
9 import re
10 import sys
12 from pylib import cmd_helper
13 from pylib.device import adb_wrapper
14 from pylib.device import device_errors
15 from pylib.utils import run_tests_helper
17 _INDENTATION_RE = re.compile(r'^( *)')
18 _LSUSB_BUS_DEVICE_RE = re.compile(r'^Bus (\d{3}) Device (\d{3}):')
19 _LSUSB_ENTRY_RE = re.compile(r'^ *([^ ]+) +([^ ]+) *([^ ].*)?$')
20 _LSUSB_GROUP_RE = re.compile(r'^ *([^ ]+.*):$')
22 _USBDEVFS_RESET = ord('U') << 8 | 20
25 def reset_usb(bus, device):
26 """Reset the USB device with the given bus and device."""
27 usb_file_path = '/dev/bus/usb/%03d/%03d' % (bus, device)
28 with open(usb_file_path, 'w') as usb_file:
29 logging.debug('fcntl.ioctl(%s, %d)', usb_file_path, _USBDEVFS_RESET)
30 fcntl.ioctl(usb_file, _USBDEVFS_RESET)
33 def reset_android_usb(serial):
34 """Reset the USB device for the given Android device."""
35 lsusb_info = lsusb()
37 bus = None
38 device = None
39 for device_info in lsusb_info:
40 device_serial = _get_lsusb_serial(device)
41 if device_serial == serial:
42 bus = int(device_info.get('bus'))
43 device = int(device_info.get('device'))
45 if bus and device:
46 reset_usb(bus, device)
47 else:
48 raise device_errors.DeviceUnreachableError(
49 'Unable to determine bus or device for device %s' % serial)
52 def reset_all_android_devices():
53 """Reset all USB devices that look like an Android device."""
54 _reset_all_matching(lambda i: bool(_get_lsusb_serial(i)))
57 def _reset_all_matching(condition):
58 lsusb_info = lsusb()
59 for device_info in lsusb_info:
60 if int(device_info.get('device')) != 1 and condition(device_info):
61 bus = int(device_info.get('bus'))
62 device = int(device_info.get('device'))
63 try:
64 reset_usb(bus, device)
65 serial = _get_lsusb_serial(device_info)
66 if serial:
67 logging.info('Reset USB device (bus: %03d, device: %03d, serial: %s)',
68 bus, device, serial)
69 else:
70 logging.info('Reset USB device (bus: %03d, device: %03d)',
71 bus, device)
72 except IOError:
73 logging.error(
74 'Failed to reset USB device (bus: %03d, device: %03d)',
75 bus, device)
78 def lsusb():
79 """Call lsusb and return the parsed output."""
80 lsusb_raw_output = cmd_helper.GetCmdOutput(['lsusb', '-v'])
81 device = None
82 devices = []
83 depth_stack = []
84 for line in lsusb_raw_output.splitlines():
85 if not line:
86 if device:
87 devices.append(device)
88 device = None
89 continue
91 if not device:
92 m = _LSUSB_BUS_DEVICE_RE.match(line)
93 if m:
94 device = {
95 'bus': m.group(1),
96 'device': m.group(2)
98 depth_stack = [device]
99 continue
101 indent_match = _INDENTATION_RE.match(line)
102 if not indent_match:
103 continue
105 depth = 1 + len(indent_match.group(1)) / 2
106 if depth > len(depth_stack):
107 logging.error('lsusb parsing error: unexpected indentation: "%s"', line)
108 continue
110 while depth < len(depth_stack):
111 depth_stack.pop()
113 cur = depth_stack[-1]
115 m = _LSUSB_GROUP_RE.match(line)
116 if m:
117 new_group = {}
118 cur[m.group(1)] = new_group
119 depth_stack.append(new_group)
120 continue
122 m = _LSUSB_ENTRY_RE.match(line)
123 if m:
124 new_entry = {
125 '_value': m.group(2),
126 '_desc': m.group(3),
128 cur[m.group(1)] = new_entry
129 depth_stack.append(new_entry)
130 continue
132 logging.error('lsusb parsing error: unrecognized line: "%s"', line)
134 if device:
135 devices.append(device)
137 return devices
140 def _get_lsusb_serial(device):
141 return device.get('Device Descriptor', {}).get('iSerial', {}).get('_desc')
144 def main():
145 parser = argparse.ArgumentParser()
146 parser.add_argument('-v', '--verbose', action='count')
147 parser.add_argument('-s', '--serial')
148 parser.add_argument('--bus', type=int)
149 parser.add_argument('--device', type=int)
150 args = parser.parse_args()
152 run_tests_helper.SetLogLevel(args.verbose)
154 if args.serial:
155 reset_android_usb(args.serial)
156 elif args.bus and args.device:
157 reset_usb(args.bus, args.device)
158 else:
159 parser.error('Unable to determine target. '
160 'Specify --serial or BOTH --bus and --device.')
162 return 0
165 if __name__ == '__main__':
166 sys.exit(main())