text: #!/usr/bin/env python
  # 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 sys
  if sys.platform == 'win32':
    raise ImportError('devil.utils.reset_usb only supported on unix systems.')
  
  import argparse
  import fcntl
  import logging
  import os
  import re
  
  if __name__ == '__main__':
    sys.path.append(
        os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
  
  from devil.android import device_errors
  from devil.utils import lsusb
  from devil.utils import run_tests_helper
  
  logger = logging.getLogger(__name__)
  
  _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 reset_usb(bus, device):
    """Reset the USB device with the given bus and device."""
    usb_file_path = '/dev/bus/usb/%03d/%03d' % (bus, device)
    with open(usb_file_path, 'w') as usb_file:
      logger.debug('fcntl.ioctl(%s, %d)', usb_file_path, _USBDEVFS_RESET)
      fcntl.ioctl(usb_file, _USBDEVFS_RESET)
  
  
  def reset_android_usb(serial):
    """Reset the USB device for the given Android device."""
    lsusb_info = lsusb.lsusb()
  
    bus = None
    device = None
    for device_info in lsusb_info:
      device_serial = lsusb.get_lsusb_serial(device_info)
      if device_serial == serial:
        bus = int(device_info.get('bus'))
        device = int(device_info.get('device'))
  
    if bus and device:
      reset_usb(bus, device)
    else:
      raise device_errors.DeviceUnreachableError(
          'Unable to determine bus(%s) or device(%s) for device %s' %
          (bus, device, serial))
  
  
  def reset_all_android_devices():
    """Reset all USB devices that look like an Android device."""
    _reset_all_matching(lambda i: bool(lsusb.get_lsusb_serial(i)))
  
  
  def _reset_all_matching(condition):
    lsusb_info = lsusb.lsusb()
    for device_info in lsusb_info:
      if int(device_info.get('device')) != 1 and condition(device_info):
        bus = int(device_info.get('bus'))
        device = int(device_info.get('device'))
        try:
          reset_usb(bus, device)
          serial = lsusb.get_lsusb_serial(device_info)
          if serial:
            logger.info('Reset USB device (bus: %03d, device: %03d, serial: %s)',
                        bus, device, serial)
          else:
            logger.info('Reset USB device (bus: %03d, device: %03d)', bus, device)
        except IOError:
          logger.error('Failed to reset USB device (bus: %03d, device: %03d)',
                       bus, device)
  
  
  def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', action='count')
    parser.add_argument('-s', '--serial')
    parser.add_argument('--bus', type=int)
    parser.add_argument('--device', type=int)
    args = parser.parse_args()
  
    run_tests_helper.SetLogLevel(args.verbose)
  
    if args.serial:
      reset_android_usb(args.serial)
    elif args.bus and args.device:
      reset_usb(args.bus, args.device)
    else:
      parser.error('Unable to determine target. '
                   'Specify --serial or BOTH --bus and --device.')
  
    return 0
  
  
  if __name__ == '__main__':
    sys.exit(main())
  