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. 5 6 import argparse 7 import fcntl 8 import logging 9 import os 10 import re 11 import sys 12 13 if __name__ == '__main__': 14 sys.path.append( 15 os.path.abspath(os.path.join(os.path.dirname(__file__), 16 '..', '..'))) 17 18 from devil.android import device_errors 19 from devil.utils import lsusb 20 from devil.utils import run_tests_helper 21 22 logger = logging.getLogger(__name__) 23 24 _INDENTATION_RE = re.compile(r'^( *)') 25 _LSUSB_BUS_DEVICE_RE = re.compile(r'^Bus (\d{3}) Device (\d{3}):') 26 _LSUSB_ENTRY_RE = re.compile(r'^ *([^ ]+) +([^ ]+) *([^ ].*)?$') 27 _LSUSB_GROUP_RE = re.compile(r'^ *([^ ]+.*):$') 28 29 _USBDEVFS_RESET = ord('U') << 8 | 20 30 31 32 def reset_usb(bus, device): 33 """Reset the USB device with the given bus and device.""" 34 usb_file_path = '/dev/bus/usb/%03d/%03d' % (bus, device) 35 with open(usb_file_path, 'w') as usb_file: 36 logger.debug('fcntl.ioctl(%s, %d)', usb_file_path, _USBDEVFS_RESET) 37 fcntl.ioctl(usb_file, _USBDEVFS_RESET) 38 39 40 def reset_android_usb(serial): 41 """Reset the USB device for the given Android device.""" 42 lsusb_info = lsusb.lsusb() 43 44 bus = None 45 device = None 46 for device_info in lsusb_info: 47 device_serial = lsusb.get_lsusb_serial(device_info) 48 if device_serial == serial: 49 bus = int(device_info.get('bus')) 50 device = int(device_info.get('device')) 51 52 if bus and device: 53 reset_usb(bus, device) 54 else: 55 raise device_errors.DeviceUnreachableError( 56 'Unable to determine bus(%s) or device(%s) for device %s' 57 % (bus, device, serial)) 58 59 60 def reset_all_android_devices(): 61 """Reset all USB devices that look like an Android device.""" 62 _reset_all_matching(lambda i: bool(lsusb.get_lsusb_serial(i))) 63 64 65 def _reset_all_matching(condition): 66 lsusb_info = lsusb.lsusb() 67 for device_info in lsusb_info: 68 if int(device_info.get('device')) != 1 and condition(device_info): 69 bus = int(device_info.get('bus')) 70 device = int(device_info.get('device')) 71 try: 72 reset_usb(bus, device) 73 serial = lsusb.get_lsusb_serial(device_info) 74 if serial: 75 logger.info( 76 'Reset USB device (bus: %03d, device: %03d, serial: %s)', 77 bus, device, serial) 78 else: 79 logger.info( 80 'Reset USB device (bus: %03d, device: %03d)', 81 bus, device) 82 except IOError: 83 logger.error( 84 'Failed to reset USB device (bus: %03d, device: %03d)', 85 bus, device) 86 87 88 def main(): 89 parser = argparse.ArgumentParser() 90 parser.add_argument('-v', '--verbose', action='count') 91 parser.add_argument('-s', '--serial') 92 parser.add_argument('--bus', type=int) 93 parser.add_argument('--device', type=int) 94 args = parser.parse_args() 95 96 run_tests_helper.SetLogLevel(args.verbose) 97 98 if args.serial: 99 reset_android_usb(args.serial) 100 elif args.bus and args.device: 101 reset_usb(args.bus, args.device) 102 else: 103 parser.error('Unable to determine target. ' 104 'Specify --serial or BOTH --bus and --device.') 105 106 return 0 107 108 109 if __name__ == '__main__': 110 sys.exit(main()) 111 112