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