#!/usr/bin/env python2
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Python version of Servo hardware debug & control board server."""

# pylint: disable=g-bad-import-order
# pkg_resources is erroneously suggested to be in the 3rd party segment
import collections
import errno
import logging
import os
import pkg_resources
import select
import signal
import SimpleXMLRPCServer
import socket
import sys
import threading
import time

import drv.loglevel
import ftdi_common
import servo_interfaces
import servo_parsing
import servo_server
import servodutil
import system_config
import terminal_freezer
import usb

VERSION = pkg_resources.require('servo')[0].version

MAX_ISERIAL_STR = 128

# If user does not specify a port to use, try ports in this range. Traverse
# the range from high to low addresses to maintain backwards compatibility
# (the first checked default port is 9999, the range is such that all possible
# port numbers are 4 digits).
DEFAULT_PORT_RANGE = (9990, 9999)

# This text file holds servod configuration parameters. This is especially
# handy for multi servo operation.
#
# The file format is pretty loose:
#  - text starting with # is ignored til the end of the line
#  - empty lines are ignored
#  - configuration lines consist of up to 4 comma separated fields (all
#    but the first field optional):
#        servo-name, serial-number, port-number, board-name
#
#    where
#     . servo-name - a user defined symbolic name, just a reference
#                     to a certain servo board
#     . serial-number - serial number of the servo board this line pertains to
#     . port-number - desired port number for servod for this board, can be
#                     overridden by the command line switch --port or
#                     environment variable setting SERVOD_PORT
#     . board-name - board configuration file to use, can be
#                     overridden by the command line switch --board
#     . model-name - model override to use, if applicable.
#                     overridden by command line --model
#
# Since the same parameters could be defined using different means, there is a
# hierarchy of definitions:
#   command line <- environment definition <- rc config file
DEFAULT_RC_FILE = '/home/%s/.servodrc' % os.getenv('SUDO_USER', '')


class ServoDeviceWatchdog(threading.Thread):
  """Watchdog to ensure servod stops when a servo device gets lost.

  Public Attributes:
    done: event to signal that the watchdog functionality can stop

  """

  REINIT_CAPABLE = set(servo_interfaces.CCD_DEFAULTS)

  # Attempts based on REINIT_POLL_RATE that will be made to reconnect a device.
  REINIT_ATTEMPTS = 100

  # Rate used to poll when attempting to reconnect a device.
  REINIT_POLL_RATE = 0.1

  def __init__(self, servod, poll_rate=1.0):
    """Setup watchdog thread.

    Args:
      servod: servod server the watchdog is watching over.
      poll_rate: poll rate in seconds
    """
    super(ServoDeviceWatchdog, self).__init__()
    self._logger = logging.getLogger(type(self).__name__)
    self.done = threading.Event()
    self._servod = servod
    self._rate = poll_rate
    # pylint: disable=protected-access
    self._devices = set(self._servod._devices)
    self._device_paths = {}
    usbmap = servodutil.UsbHierarchy()
    devices_not_found = set()
    for vid, pid, serial in self._devices:
      try:
        dev = servodutil.UsbHierarchy.GetUsbDevice(vid, pid, serial)
        dev_path = usbmap.GetPath(dev)
        if not dev_path:
          raise ServodError('No sysfs path found for device.')
        self._device_paths[(vid, pid, serial)] = dev_path
      # pylint: disable=broad-except
      except Exception as e:
        self._logger.error('Servod Watchdog ran into unexpected issue trying '
                           'to find device with vid: 0x%02x pid: 0x%02x '
                           'serial: %r. %s. Device will not be tracked.',
                           vid, pid, serial, e)
        devices_not_found.add((vid, pid, serial))
    # Only track devices that a sysfs path was successfully found for.
    self._devices -= devices_not_found

    # TODO(coconutruben): Here and below in addition to VID/PID also print out
    # the device type i.e. servo_micro.
    self._logger.info('Watchdog setup for devices: %s', str(self._devices))

  def run(self):
    """Poll |_devices| every |_rate| seconds. Send SIGTERM if device lost."""
    # Tokens a reinit capable device has to attempt reinit. If these run out
    # the watchdog will turn down servod.
    reinit_tokens = collections.defaultdict(lambda: self.REINIT_ATTEMPTS)
    rate = self._rate
    while not self.done.is_set():
      self.done.wait(rate)
      for vid, pid, serial in self._devices:
        sysfs_path = self._device_paths[(vid, pid, serial)]
        if os.path.exists(sysfs_path):
          # Device was found. Make sure it's not currently being considered
          # for reinit.
          if (vid, pid, serial) in reinit_tokens:
            # Device was waiting to be reinit. Remove from token tracker.
            del reinit_tokens[(vid, pid, serial)]
            if not reinit_tokens:
              # No device waiting for reinit anymore. Issue a servod interface
              # reinitialization.
              self._servod.reinitialize()
              # Return to slower poll rate after no devices are in a reinit
              # queue.
              rate = self._rate
        else:
          # Device was not found.
          if (vid, pid) in self.REINIT_CAPABLE:
            if reinit_tokens[(vid, pid, serial)]:
              # The device still has reinit tokens. Remove one.
              reinit_tokens[(vid, pid, serial)] -= 1
              self._logger.warn('Device - vid: 0x%02x pid: 0x%02x serial: %r '
                                'not found when polling. Device is marked as '
                                'reinit capable. %d more reinit attempts '
                                'before giving up.', vid, pid, serial,
                                reinit_tokens[(vid, pid, serial)])
              # pylint: disable=protected-access
              # Indicate to servod that interfaces are unavailable.
              self._servod._ifaces_available.clear()
              # Poll faster while there are devices that need to be reinit.
              rate = self.REINIT_POLL_RATE
              continue
          # Device was not found, thus signaling to end servod.
          self._logger.error('Device - vid: 0x%02x pid: 0x%02x serial: %r - '
                             'not found when polling. Turning down servod.',
                             vid, pid, serial)
          # Watchdog should run in the same process as servod thread.
          os.kill(os.getpid(), signal.SIGTERM)
          self.done.set()
          break


def usb_get_iserial(device):
  """Get USB device's iSerial string.

  Args:
    device: usb.Device object

  Returns:
    iserial: USB devices iSerial string or empty string if the device has
             no serial number.
  """
  # pylint: disable=broad-except
  device_handle = device.open()
  # The device has no serial number string descriptor.
  if device.iSerialNumber == 0:
    return ''
  iserial = ''
  try:
    iserial = device_handle.getString(device.iSerialNumber, MAX_ISERIAL_STR)
  except usb.USBError, e:
    # TODO(tbroch) other non-FTDI devices on my host cause following msg
    #   usb.USBError: error sending control message: Broken pipe
    # Need to investigate further
    pass
  except Exception as e:
    # This was causing servod to fail to start in the presence of
    # a broken usb interface.
    print 'usb_get_iserial failed in an unknown way: [%s]' % e
  return iserial


def usb_find(vendor, product, serialname):
  """Find USB devices based on vendor, product and serial identifiers.

  Locates all USB devices that match the criteria of the arguments.  In the
  case where input arguments are 'None' that argument is a don't care

  Args:
    vendor: USB vendor id (integer)
    product: USB product id (integer)
    serialname: USB serial id (string)

  Returns:
    matched_devices : list of pyusb devices matching input args
  """
  matched_devices = []
  for bus in usb.busses():
    for device in bus.devices:
      if (not vendor or device.idVendor == vendor) and \
            (not product or device.idProduct == product) and \
            (not serialname or usb_get_iserial(device).endswith(serialname)):
        matched_devices.append(device)
  return matched_devices


class ServodError(Exception):
  """Exception class for servod server."""
  pass


class ServodStarter(object):
  """Class to manage servod instance and rpc server its being served on."""

  def __init__(self, cmdline):
    """Prepare servod invocation.

    Parse cmdline and prompt user for missing information if necessary to start
    servod. Prepare servod instance & thread for it to be served from.

    Args:
      cmdline: list, cmdline components to parse

    Raises:
      ServodError: if automatic config cannot be found
    """
    options = self._parse_args(cmdline)
    if options.debug:
      level = 'debug'
    else:
      level = drv.loglevel.DEFAULT_LOGLEVEL

    loglevel, fmt = drv.loglevel.LOGLEVEL_MAP[level]
    logging.basicConfig(level=loglevel, format=fmt)

    # Servod needs to be running in the chroot without PID namespaces in order
    # to freeze terminals when reading from the UARTs.
    terminal_freezer.CheckForPIDNamespace()

    self._logger = logging.getLogger(os.path.basename(sys.argv[0]))
    self._logger.info('Start')
    # The scratch initialization here ensures that potentially stale entries
    # are removed from the scratch before attempting to create a new one.
    self._scratchutil = servodutil.ServoScratch()

    servo_parsing.get_env_options(self._logger, options)

    if options.name and options.serialname:
      self._logger.error("Mutually exclusive '--name' or '--serialname' is "
                         'allowed')
      sys.exit(-1)

    servo_device = self.discover_servo(options,
                                       servo_parsing.parse_rc(self._logger,
                                                              options.rcfile))
    if not servo_device:
      sys.exit(-1)

    self._host = options.host
    lot_id = self.get_lot_id(servo_device)
    board_version = self.get_board_version(lot_id, servo_device.idProduct)
    self._logger.debug('board_version = %s', board_version)
    all_configs = []
    if not options.noautoconfig:
      all_configs += self.get_auto_configs(board_version)

    if options.config:
      for config in options.config:
        # quietly ignore duplicate configs for backwards compatibility
        if config not in all_configs:
          all_configs.append(config)

    if not all_configs:
      raise ServodError('No automatic config found,'
                        ' and no config specified with -c <file>')

    scfg = system_config.SystemConfig()

    if options.board:
      # Handle differentiated model case.
      board_config = None
      if options.model:
        board_config = 'servo_%s_%s_overlay.xml' % (
            options.board, options.model)

        if not scfg.find_cfg_file(board_config):
          self._logger.info('No XML overlay for model '
              '%s, falling back to board %s default',
              options.model, options.board)
          board_config = None
        else:
          self._logger.info('Found XML overlay for model %s:%s',
                            options.board, options.model)

      # Handle generic board config.
      if not board_config:
        board_config = 'servo_' + options.board + '_overlay.xml'
        if not scfg.find_cfg_file(board_config):
          self._logger.error('No XML overlay for board %s', options.board)
          sys.exit(-1)

        self._logger.info('Found XML overlay for board %s', options.board)

      all_configs.append(board_config)

    for cfg_file in all_configs:
      scfg.add_cfg_file(cfg_file)

    self._logger.debug('\n%s', scfg.display_config())

    self._logger.debug('Servo is vid:0x%04x pid:0x%04x sid:%s',
                       servo_device.idVendor, servo_device.idProduct,
                       usb_get_iserial(servo_device))

    if options.port:
      start_port = options.port
      end_port = options.port
    else:
      end_port, start_port = DEFAULT_PORT_RANGE
    for self._servo_port in xrange(start_port, end_port - 1, -1):
      try:
        self._server = SimpleXMLRPCServer.SimpleXMLRPCServer((self._host,
                                                              self._servo_port),
                                                             logRequests=False)
        break
      except socket.error as e:
        if e.errno == errno.EADDRINUSE:
          continue  # Port taken, see if there is another one next to it.
        self._logger.fatal("Problem opening Server's socket: %s", e)
        sys.exit(-1)
    else:
      if options.port:
        err_msg = ('Port %d is busy' % options.port)
      else:
        err_msg = ('Could not find a free port in %d..%d range' % (end_port,
                                                                   start_port))

      self._logger.fatal(err_msg)
      sys.exit(-1)

    board_model = options.board
    if options.model:
      board_model += '_' + options.model
    self._servod = servo_server.Servod(
        scfg, vendor=servo_device.idVendor, product=servo_device.idProduct,
        serialname=usb_get_iserial(servo_device),
        interfaces=options.interfaces.split(), board=board_model,
        version=board_version, usbkm232=options.usbkm232)

    # Small timeout to allow interface threads to initialize.
    time.sleep(0.5)

    self._servod.hwinit(verbose=True)
    self._server.register_introspection_functions()
    self._server.register_multicall_functions()
    self._server.register_instance(self._servod)
    self._server_thread = threading.Thread(target=self._serve)
    self._server_thread.daemon = True
    self._turndown_initiated = False
    # pylint: disable=protected-access
    # Needs access to the servod instance.
    self._watchdog_thread = ServoDeviceWatchdog(self._servod)
    self._exit_status = 0

  def handle_sig(self, signum):
    """Handle a signal by turning off the server & cleaning up servod."""
    if not self._turndown_initiated:
      self._turndown_initiated = True
      self._logger.info('Received signal: %d. Attempting to turn off', signum)
      self._server.shutdown()
      self._server.server_close()
      self._servod.close()
      self._logger.info('Successfully turned off')

  def _parse_args(self, cmdline):
    """Parse commandline arguments.

    Args:
      cmdline: list of cmdline arguments

    Returns:
      args: argparse Namespace after parsing & processing cmdline
    """
    description = (
        '%(prog)s is server to interact with servo debug & control board. '
        'This server communicates to the board via USB and the client via '
        'xmlrpc library. Launcher most specify at least one --config <file> '
        'in order for the server to provide any functionality. In most cases, '
        'multiple configs will be needed to expose complete functionality '
        'between debug & DUT board.')
    examples = [('-c <path>/data/servo.xml',
                 'Launch server on default host:port with native servo config'),
                ('-c <file> -p 8888', 'Launch server listening on port 8888'),
                ('-c <file> --vendor 0x18d1 --product 0x5001',
                 'Launch targetting usb device with vid:pid == 0x18d1:0x5001 '
                 '(Google/Servo)')]
    # BaseServodParser adds port, host, debug args & name/rcfile args for rc.
    parser = servo_parsing.BaseServodParser(description=description,
                                            examples=examples,
                                            version='%(prog)s ' + VERSION)
    parser.add_argument('--vendor', default=None, type=lambda x: int(x,0),
                        help='vendor id of device to interface to')
    parser.add_argument('--product', default=None, type=lambda x: int(x,0),
                        help='USB product id of device to interface with')
    parser.add_argument('-s', '--serialname', default=None, type=str,
                        help='device serialname stored in eeprom')
    parser.add_argument('-c', '--config', default=None, type=str,
                        action='append', help='system config file (XML) to '
                                              'read')
    parser.add_argument('-b', '--board', default=None, type=str, action='store',
                        help='include config file (XML) for given board')
    parser.add_argument('-m', '--model', default='', type=str, action='store',
                        help='optional config for a model of the given board, '
                        'requires --board')
    parser.add_argument('--noautoconfig', action='store_true', default=False,
                        help='Disable automatic determination of config files')
    parser.add_argument('-i', '--interfaces', type=str, default='',
                        help='ordered space-delimited list of interfaces. '
                        'Valid choices are gpio|i2c|uart|gpiouart|dummy')
    parser.add_argument('-u', '--usbkm232', type=str,
                        help='path to USB-KM232 device which allow for '
                        'sending keyboard commands to DUTs that do not '
                        'have built in keyboards. Used in FAFT tests. '
                        '(Optional), e.g. /dev/ttyUSB0')
    servo_parsing.add_servo_parsing_rc_options(parser)
    return parser.parse_args(cmdline)

  def find_servod_match(self, options, all_servos, servodrc):
    """Find a servo matching one of servodrc lines.

    Given a list of servod objects matching discovered servos, display the list
    to the user and check if there is a configuration file line corresponding to
    one of the servos.

    If a line like that exists, and it includes options which are not yet
    defined in the options object - set these options' values. If the option is
    already defined - report that this config line setting is ignored.

    Args:
      options: an options object as returned by parse_options
      all_servos: a list of servod objects corresponding to discovered servo
                  devices
      servodrc: a dictionary representing the contents of the servodrc file, as
                returned by parse_rc() above (if any)

    Returns:
      a matching servod object, if found, None otherwise

    Raises:
      ServodError: in case required name is not found in the config file
    """

    for servo in all_servos:
      self._logger.info('Found servo, vid: 0x%04x pid: 0x%04x sid: %s',
                        servo.idVendor, servo.idProduct, usb_get_iserial(servo))

    # If user specified servod name in the command line - match it to the serial
    # number.

    if options.name:
      config = servodrc.get(options.name)
      if not config:
        raise ServodError("Name '%s' not in the config file" % options.name)
      options.serialname = config['sn']
    elif options.serialname:
      # Let's try finding config for a serial name
      for config in servodrc.itervalues():
        if config['sn'] == options.serialname:
          break
      else:
        return None

    if not options.serialname:
      # There is nothing to match
      return None

    for servo in all_servos:
      servo_sn = usb_get_iserial(servo)
      if servo_sn != options.serialname:
        continue

      # Match found, some sanity checks/updates before using it
      matching_servo = servo
      rc_port = config['port']
      if rc_port:
        if not options.port:
          options.port = rc_port
        elif options.port != rc_port:
          self._logger.warning('Ignoring rc configured port %s for servo %s',
                               rc_port, servo_sn)

      rc_board = config['board']
      if rc_board:
        if not options.board:
          options.board = rc_board
        elif options.board != rc_board:
          self._logger.warning('Ignoring rc configured board name %s for servo '
                               '%s', rc_board, servo_sn)
      if 'model' in config:
        rc_model = config['model']
        if not options.model:
          options.model = rc_model
        elif options.model != rc_model:
          self._logger.warning('Ignoring rc configured model name %s for servo '
                               '%s', rc_model, servo_sn)
      return matching_servo

    raise ServodError('No matching servo found')

  def choose_servo(self, all_servos):
    """Let user choose a servo from available list of unique devices.

    Args:
      all_servos: a list of servod objects corresponding to discovered servo
                  devices

    Returns:
      servo object for the matching (or single) device, otherwise None
    """
    self._logger.info('')
    for i, servo in enumerate(all_servos):
      self._logger.info("Press '%d' for servo, vid: 0x%04x pid: 0x%04x sid: %s",
                        i, servo.idVendor, servo.idProduct,
                        usb_get_iserial(servo))

    (rlist, _, _) = select.select([sys.stdin], [], [], 10)
    if not rlist:
      self._logger.warn('Timed out waiting for your choice\n')
      return None

    rsp = rlist[0].readline().strip()
    try:
      rsp = int(rsp)
    except ValueError:
      self._logger.warn('%s not a valid choice ... ignoring', rsp)
      return None

    if rsp < 0 or rsp >= len(all_servos):
      self._logger.warn('%s outside of choice range ... ignoring', rsp)
      return None

    logging.info('')
    servo = all_servos[rsp]
    logging.info('Chose %d ... starting servod on servo '
                 'vid: 0x%04x pid: 0x%04x sid: %s', rsp, servo.idVendor,
                 servo.idProduct, usb_get_iserial(servo))
    logging.info('')
    return servo

  def discover_servo(self, options, servodrc):
    """Find a servo USB device to use.

    First, find all servo devices matching command line options, this may result
    in discovering none, one or more devices.

    Then try matching discovered servos and the configuration defined in
    servodrc. A match this will result in reading missing options from servodrc
    file.

    If there is a match - return the matching device.

    If no match found, but there is only one servo connected - return it. If
    there is no match found and multiple servos are connected - report an error
    and return None.

    Args:
      options: the options object returned by opt_parse
      servodrc: a dictionary representing the contents of the servodrc file, as
                returned by parse_rc() above (if any)
    Returns:
      servo object for the matching (or single) device, otherwise None
    """

    vendor, product, serialname = (options.vendor, options.product,
                                   options.serialname)
    all_servos = []
    for (vid, pid) in servo_interfaces.SERVO_ID_DEFAULTS:
      if (vendor and vendor != vid) or \
            (product and product != pid):
        continue
      all_servos.extend(usb_find(vid, pid, serialname))

    if not all_servos:
      self._logger.error('No servos found')
      return None

    # See if there is a matching entry in servodrc
    matching_servo = self.find_servod_match(options, all_servos, servodrc)

    if matching_servo:
      return matching_servo

    if len(all_servos) == 1:
      return all_servos[0]

    # See if only one primary servo. Filter secordary servos, like servo-micro.
    secondary_servos = (
        servo_interfaces.SERVO_MICRO_DEFAULTS + servo_interfaces.CCD_DEFAULTS)
    all_primary_servos = [
        servo for servo in all_servos
        if (servo.idVendor, servo.idProduct) not in secondary_servos
    ]
    if len(all_primary_servos) == 1:
      return all_primary_servos[0]

    # Let user choose a servo
    matching_servo = self.choose_servo(all_servos)
    if matching_servo:
      return matching_servo

    self._logger.error('Use --vendor, --product or --serialname switches to '
                       'identify servo uniquely, or create a servodrc file '
                       'and use the --name switch')

    return None

  def get_board_version(self, lot_id, product_id):
    """Get board version string.

    Typically this will be a string of format <boardname>_<version>.
    For example, servo_v2.

    Args:
      lot_id: string, identifying which lot device was fabbed from or None
      product_id: integer, USB product id

    Returns:
      board_version: string, board & version or None if not found
    """
    if lot_id:
      for (board_version, lot_ids) in \
            ftdi_common.SERVO_LOT_ID_DEFAULTS.iteritems():
        if lot_id in lot_ids:
          return board_version

    for (board_version, vids) in \
          ftdi_common.SERVO_PID_DEFAULTS.iteritems():
      if product_id in vids:
        return board_version

    return None

  def get_lot_id(self, servo):
    """Get lot_id for a given servo.

    Args:
      servo: usb.Device object

    Returns:
      lot_id of the servo device.
    """
    lot_id = None
    iserial = usb_get_iserial(servo)
    self._logger.debug('iserial = %s', iserial)
    if not iserial:
      self._logger.warn('Servo device has no iserial value')
    else:
      try:
        (lot_id, _) = iserial.split('-')
      except ValueError:
        self._logger.warn("Servo device's iserial was unrecognized.")
    return lot_id

  def get_auto_configs(self, board_version):
    """Get xml configs that should be loaded.

    Args:
      board_version: string, board & version

    Returns:
      configs: list of XML config files that should be loaded
    """
    if board_version not in ftdi_common.SERVO_CONFIG_DEFAULTS:
      self._logger.warning('Unable to determine configs to load for board '
                           'version = %s', board_version)
      return []
    return ftdi_common.SERVO_CONFIG_DEFAULTS[board_version]

  def cleanup(self):
    """Perform any cleanup related work after servod server shut down."""
    self._scratchutil.RemoveEntry(self._servo_port)
    self._logger.info('Server on %s port %s turned down', self._host,
                      self._servo_port)

  def _serve(self):
    """Wrapper around rpc server's serve_forever to catch server errors."""
    # pylint: disable=broad-except
    self._logger.info('Listening on %s port %s', self._host, self._servo_port)
    try:
      self._server.serve_forever()
    except Exception:
      self._exit_status = 1

  def serve(self):
    """Add signal handlers, start servod on its own thread & wait for signal.

    Intercepts and handles SIGINT and SIGTERM.
    """
    handler = lambda signal, unused, starter=self: starter.handle_sig(signal)
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGTERM, handler)
    # pylint: disable=protected-access, invalid-name, unused-variable
    # current method of retrieving device information requires this
    serials = [serial for _vid, _pid, serial in self._servod._devices]
    try:
      self._scratchutil.AddEntry(self._servo_port, serials, os.getpid())
    except servodutil.ServodUtilError:
      self._servod.close()
      sys.exit(1)
    self._watchdog_thread.start()
    self._server_thread.start()
    signal.pause()
    # Set watchdog thread to end
    self._watchdog_thread.done.set()
    # Collect servo and watchdog threads
    self._server_thread.join()
    self._watchdog_thread.join()
    self.cleanup()
    sys.exit(self._exit_status)


# pylint: disable=dangerous-default-value
# Ability to pass an arbitrary or artifical cmdline for testing is desirable.
def main(cmdline=sys.argv[1:]):
  try:
    starter = ServodStarter(cmdline)
  except ServodError as e:
    print 'Error: ', e.message
    sys.exit(1)
  starter.serve()

if __name__ == '__main__':
  main()
