# Lint as: python2, python3
# Copyright (c) 2014 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.
"""Input flow module which abstracts the entire flow for a specific input."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import itertools
import logging
import tempfile
import threading
import time
from abc import ABCMeta
from six import with_metaclass

from . import chameleon_common  # pylint: disable=W0611
from chameleond.devices import chameleon_device
from chameleond.utils import audio
from chameleond.utils import audio_utils
from chameleond.utils import common
from chameleond.utils import edid
from chameleond.utils import fpga
from chameleond.utils import frame_manager
from chameleond.utils import i2c
from chameleond.utils import ids
from chameleond.utils import chameleon_io as io
from chameleond.utils import rx
from six.moves import range
from six.moves import zip


class InputFlowError(Exception):
  """Exception raised when any error on FpgaInputFlow."""
  pass


# TODO(mojahsu): Rename the XxxxFlow to XxxxDevice
class FpgaInputFlow(with_metaclass(ABCMeta, chameleon_device.Flow)):
  """An abstraction of the entire flow for InputFlow on FPGA."""

  __PULSE_RETRY_COUNT = 3

  _RX_SLAVES = {
      ids.DP1: rx.DpRx.SLAVE_ADDRESSES[0],
      ids.DP2: rx.DpRx.SLAVE_ADDRESSES[1],
      ids.HDMI: rx.HdmiRx.SLAVE_ADDRESSES[0],
      ids.VGA: rx.VgaRx.SLAVE_ADDRESSES[0]
  }
  _MUX_CONFIGS = {
      # Use a dual-pixel-mode setting for IO as no support for two flows
      # simultaneously so far.
      ids.DP1: io.MuxIo.CONFIG_DP1_DUAL,
      ids.DP2: io.MuxIo.CONFIG_DP2_DUAL,
      ids.HDMI: io.MuxIo.CONFIG_HDMI_DUAL,
      ids.VGA: io.MuxIo.CONFIG_VGA
  }

  # Overwrite them if the device can be detected by reading value from I2C bus.
  _DETECT_OFFSET = 0
  _DETECT_VALUE = None

  def __init__(self, input_id, main_i2c_bus, fpga_ctrl):
    """Constructs a FpgaInputFlow object.

    Args:
      input_id: The ID of the input connector. Check the value in ids.py.
      main_i2c_bus: The main I2cBus object.
      fpga_ctrl: The FpgaController object.
    """
    super(FpgaInputFlow, self).__init__()
    self._input_id = input_id
    self._main_bus = main_i2c_bus
    self._fpga = fpga_ctrl
    self._power_io = self._main_bus.GetSlave(io.PowerIo.SLAVE_ADDRESSES[0])
    self._mux_io = self._main_bus.GetSlave(io.MuxIo.SLAVE_ADDRESSES[0])
    self._rx = self._main_bus.GetSlave(self._RX_SLAVES[self._input_id])
    self._frame_manager = frame_manager.FrameManager(
        input_id, self._rx, self._GetEffectiveVideoDumpers())
    self._edid = None  # be overwitten by a subclass.
    self._edid_enabled = True
    self._ddc_enabled = True
    self._timer = None

  def _GetEffectiveVideoDumpers(self):
    """Gets effective video dumpers on the flow."""
    if self.IsDualPixelMode():
      if fpga.VideoDumper.EVEN_PIXELS_FLOW_INDEXES[self._input_id] == 0:
        return [self._fpga.vdump0, self._fpga.vdump1]
      else:
        return [self._fpga.vdump1, self._fpga.vdump0]
    elif fpga.VideoDumper.PRIMARY_FLOW_INDEXES[self._input_id] == 0:
      return [self._fpga.vdump0]
    else:
      return [self._fpga.vdump1]

  def IsDetected(self):
    """Returns if the device can be detected."""
    try:
      value = self._rx.Get(self._DETECT_OFFSET)
      if value == self._DETECT_VALUE:
        return True
      logging.warn('Detected value fail, %d != %d', value, self._DETECT_VALUE)
      return False
    except i2c.I2cBusError:
      return False

  def InitDevice(self):
    """Initializes the input flow."""
    logging.info('Initialize FpgaInputFlow #%d.', self._input_id)
    self._power_io.ResetReceiver(self._input_id)
    self._rx.Initialize(self.IsDualPixelMode())

  def Reset(self):
    """Reset chameleon device."""
    self.Unplug()

  def Select(self):
    """Selects the input flow to set the proper muxes and FPGA paths."""
    logging.info('Select FpgaInputFlow #%d.', self._input_id)
    self._mux_io.SetConfig(self._MUX_CONFIGS[self._input_id])
    self._fpga.vpass.Select(self._input_id)
    self._fpga.vdump0.Select(self._input_id, self.IsDualPixelMode())
    self._fpga.vdump1.Select(self._input_id, self.IsDualPixelMode())

  def GetMaxFrameLimit(self, width, height):
    """Returns of the maximal number of frames which can be dumped."""
    return self._frame_manager.GetMaxFrameLimit(width, height)

  def GetFrameHashes(self, start, stop):
    """Returns the list of the frame hashes.

    Args:
      start: The index of the start frame.
      stop: The index of the stop frame (excluded).

    Returns:
      A list of frame hashes.
    """
    return self._frame_manager.GetFrameHashes(start, stop)

  def GetHistograms(self, start, stop):
    """Returns the list of the frame histograms.

    Args:
      start: The index of the start field.
      stop: The index of the stop field (excluded).

    Returns:
      A list of frame histograms.
    """
    return self._frame_manager.GetHistograms(start, stop)

  def DumpFramesToLimit(self, frame_limit, x, y, width, height, timeout):
    """Dumps frames and waits for the given limit being reached or timeout.

    Args:
      frame_limit: The limitation of frame to dump.
      x: The X position of the top-left corner of crop; None for a full-screen.
      y: The Y position of the top-left corner of crop; None for a full-screen.
      width: The width of the area of crop.
      height: The height of the area of crop.
      timeout: Time in second of timeout.

    Raises:
      common.TimeoutError on timeout.
    """
    self.WaitVideoOutputStable()
    try:
      self._frame_manager.DumpFramesToLimit(frame_limit, x, y, width, height,
                                            timeout)
    except common.TimeoutError:
      message = 'Frames failed to reach %d' % frame_limit
      logging.error(message)
      logging.error('RX dump: %r', self._rx.Get(0, 256))
      raise InputFlowError(message)

  def StartDumpingFrames(self, frame_buffer_limit, x, y, width, height,
                         hash_buffer_limit):
    """Starts dumping frames continuously.

    Args:
      frame_buffer_limit: The size of the buffer which stores the frame.
                          Frames will be dumped to the beginning when full.
      x: The X position of the top-left corner of crop; None for a full-screen.
      y: The Y position of the top-left corner of crop; None for a full-screen.
      width: The width of the area of crop.
      height: The height of the area of crop.
      hash_buffer_limit: The maximum number of hashes to monitor. Stop
                         capturing when this limitation is reached.
    """
    self.WaitVideoOutputStable()
    self._frame_manager.StartDumpingFrames(
        frame_buffer_limit, x, y, width, height, hash_buffer_limit)

  def StopDumpingFrames(self):
    """Stops dumping frames."""
    self._frame_manager.StopDumpingFrames()

  def GetCapturedResolution(self):
    """Gets the resolution of the captured frame."""
    return self._frame_manager.GetDumpedDimension()

  def GetDumpedFrameCount(self):
    """Gets the number of frames which is dumped."""
    return self._frame_manager.GetFrameCount()

  def ReadCapturedFrame(self, frame_index):
    """Reads the content of the captured frame from the buffer."""
    return self._frame_manager.ReadDumpedFrame(frame_index)

  def CacheFrameThumbnail(self, frame_index, ratio):
    """Caches the thumbnail of the dumped field to a temp file.

    Args:
      frame_index: The index of the frame to cache.
      ratio: The ratio to scale down the image.

    Returns:
      An ID to identify the cached thumbnail.
    """
    return self._frame_manager.CacheFrameThumbnail(frame_index, ratio)

  def DoFSM(self):
    """Does the Finite-State-Machine to ensure the input flow ready.

    The receiver requires to do the FSM in order to clear its state, in case
    of some events happended, like mode change, power reattach, etc.

    It should be called before doing any post-receiver-action, like capturing
    frames.
    """
    pass

  def WaitVideoInputStable(self, unused_timeout=None):
    """Waits the video input stable or timeout. Returns success or not."""
    return True

  def WaitVideoOutputStable(self, unused_timeout=None):
    """Waits the video output stable or timeout.

    Raises:
      InputFlowError if timeout.
    """
    pass

  def IsDualPixelMode(self):
    """Returns if the input flow uses dual pixel mode."""
    raise NotImplementedError('IsDualPixelMode')

  def SetEdidState(self, enabled):
    """Sets the enabled/disabled state of EDID.

    Args:
      enabled: True to enable EDID due to an user request; False to
               disable it.
    """
    if enabled and self.IsPlugged():
      self._edid.Enable()
    else:
      self._edid.Disable()
    self._edid_enabled = enabled

  def IsEdidEnabled(self):
    """Checks if the EDID is enabled or disabled.

    Returns:
      True if the EDID is enabled; False if disabled.
    """
    return self._edid_enabled

  def FireHpdPulse(
      self, deassert_interval_usec, assert_interval_usec, repeat_count,
      end_level):
    """Fires one or more HPD pulse (low -> high -> low -> ...).

    Args:
      deassert_interval_usec: The time in microsecond of the deassert pulse.
      assert_interval_usec: The time in microsecond of the assert pulse.
                            If None, then use the same value as
                            deassert_interval_usec.
      repeat_count: The count of HPD pulses to fire.
      end_level: HPD ends with 0 for LOW (unplugged) or 1 for HIGH (plugged).
    """
    for i in range(repeat_count):
      self.Unplug()
      time.sleep(deassert_interval_usec / 1000000.0)
      self.Plug()
      time.sleep(assert_interval_usec / 1000000.0)

    if not end_level:
      self.Unplug()

  def FireMixedHpdPulses(self, widths_msec):
    """Fires one or more HPD pulses, starting at low, of mixed widths.

    One must specify a list of segment widths in the widths_msec argument where
    widths_msec[0] is the width of the first low segment, widths_msec[1] is that
    of the first high segment, widths_msec[2] is that of the second low segment,
    etc.
    The HPD line stops at low if even number of segment widths are specified;
    otherwise, it stops at high.

    The method is equivalent to a series of calls to Unplug() and Plug()
    separated by specified pulse widths.

    Args:
      widths_msec: list of pulse segment widths in milli-second.
    """
    # Append a plug/unplug after the last pulse
    sleep_times = [w / 1000.0 for w in widths_msec] + [0.0]
    ops = [self.Unplug, self.Plug] * ((len(sleep_times) + 1) / 2)
    pulses = list(zip(ops, sleep_times))

    for op, sleep_time in pulses:
      count = 0
      while count < self.__PULSE_RETRY_COUNT:
        try:
          op()
          break
        except Exception as e:
          count += 1
          logging.info('%s error %d', op.__name__, count)
          logging.exception(e)
      else:
        raise

      time.sleep(sleep_time)

  def _RunHpdToggle(self, port_id, rising_edge):
    logging.info('Run HPD %s toggle on port #%d',
                 'rising' if rising_edge  else 'falling', port_id)

    if rising_edge:
      self.Plug()
    else:
      self.Unplug()

  def ScheduleHpdToggle(self, port_id, delay_ms, rising_edge):
    """Schedules one HPD Toggle, with a delay between the toggle.

    Args:
      port_id: The ID of the video input port.
      delay_ms: Delay in milli-second before the toggle takes place.
      rising_edge: Whether the toggle should be a rising edge or a falling edge.
    """

    if self._timer and self._timer.isAlive():
      raise InputFlowError('previous timer already enabled')

    self._timer = threading.Timer(delay_ms / 1000.0, self._RunHpdToggle,
                                  [port_id, rising_edge])
    self._timer.start()

    if rising_edge:
      self.Unplug()
    else:
      self.Plug()

  def _EnableDdc(self):
    """Enables the DDC bus."""
    raise NotImplementedError('EnableDdc')

  def _DisableDdc(self):
    """Disables the DDC bus."""
    raise NotImplementedError('DisableDdc')

  def SetDdcState(self, enabled):
    """Sets the enabled/disabled state of DDC bus.

    Args:
      enabled: True to enable DDC bus due to an user request; False to
              disable it.
    """
    if enabled and self.IsPlugged():
      self._EnableDdc()
    else:
      self._DisableDdc()
    self._ddc_enabled = enabled

  def IsDdcEnabled(self):
    """Checks if the DDC bus is enabled or disabled.

    Returns:
      True if the DDC bus is enabled; False if disabled.
    """
    return self._ddc_enabled

  def ReadEdid(self):
    """Reads the EDID content."""
    raise NotImplementedError('ReadEdid')

  def WriteEdid(self, data):
    """Writes the EDID content."""
    raise NotImplementedError('WriteEdid')

  def SetContentProtection(self, enabled):
    """Sets the content protection state.

    Args:
      enabled: True to enable; False to disable.
    """
    raise NotImplementedError('SetContentProtection')

  def IsContentProtectionEnabled(self):
    """Returns True if the content protection is enabled.

    Returns:
      True if the content protection is enabled; otherwise, False.
    """
    raise NotImplementedError('IsContentProtectionEnabled')

  def IsVideoInputEncrypted(self):
    """Returns True if the video input is encrypted.

    Returns:
      True if the video input is encrypted; otherwise, False.
    """
    raise NotImplementedError('IsVideoInputEncrypted')

  def GetVideoParams(self):
    """Gets video parameters.

    Returns:
      A dict containing video parameters. Fields are omitted if unknown.
    """
    (width, height) = self.GetResolution()
    return {
      'hactive': width,
      'vactive': height
    }

  def TriggerLinkFailure(self):
    raise NotImplementedError('TriggerLinkFailure')

  def GetLastInfoFrame(self, infoframe_type):
    """Obtains the last received InfoFrame of the specified type.

    Args:
      infoframe_type (string): the InfoFrame type

    Returns:
      A dict containing the InfoFrame.
    """
    raise NotImplementedError('GetLastInfoFrame')


class FpgaInputFlowWithAudio(FpgaInputFlow):  # pylint: disable=W0223
  """An abstraction of an input flow which supports audio."""

  def __init__(self, input_id, main_i2c_bus, fpga_ctrl):
    """Constructs a FpgaInputFlowWithAudio object.

    Args:
      input_id: The ID of the input connector. Check the value in ids.py.
      main_i2c_bus: The main I2cBus object.
      fpga_ctrl: The FpgaController object.
    """
    super(FpgaInputFlowWithAudio, self).__init__(input_id, main_i2c_bus,
                                                 fpga_ctrl)
    self._audio_capture_manager = audio_utils.AudioCaptureManager(
        self._fpga.adump, self)
    self._audio_route_manager = audio_utils.AudioRouteManager(
        self._fpga.aroute)
    self._audio_recorded_file = None

  @property
  def is_capturing_audio(self):
    """Is input flow capturing audio?"""
    return self._audio_capture_manager.is_capturing

  def GetAudioChannels(self):
    """Returns the number of received audio channels.

    Returns:
      An integer.
    """
    raise NotImplementedError('GetAudioChannels')

  def GetAudioChannelMapping(self):
    """Obtains the channel mapping."""
    mapping = [1, 0, 2, 3, 4, 5, 6, 7]
    for i in range(self.GetAudioChannels(), len(mapping)):
      mapping[i] = -1
    return mapping

  def GetAudioFormat(self):
    """Gets the format currently used by audio capture.

    Returns:
      An audio.AudioDataFormat object.
    """
    raise NotImplementedError('GetAudioFormat')

  def StartCapturingAudio(self, has_file):
    """Starts capturing audio.

    Args:
      has_file: True for saving audio data to file. False otherwise.
    """
    self._audio_route_manager.SetupRouteFromInputToDumper(self._input_id)
    self._audio_recorded_file = None
    file_path = None
    if has_file:
      self._audio_recorded_file = tempfile.NamedTemporaryFile(
          prefix='audio_', suffix='.raw', delete=False)
      file_path = self._audio_recorded_file.name
      logging.info('Save captured audio to %s',
                   self._audio_recorded_file.name)
    # Resets audio logic for issue crbug.com/623466.
    self._ResetAudioLogic()
    self._audio_capture_manager.StartCapturingAudio(file_path)

  def StopCapturingAudio(self):
    """Stops capturing audio.

    Returns:
      A tuple (path, format).
      path: The path to the captured audio data.
      format: The dict representation of AudioDataFormat. Refer to docstring
        of utils.audio.AudioDataFormat for detail.
      If we assign parameter has_file=False in StartCapturingAudio, we will get
      both None in path and format.

    Raises:
      AudioCaptureManagerError: If captured time or page exceeds the limit.
      AudioCaptureManagerError: If there is no captured data.
    """
    try:
      data_format = self._audio_capture_manager.StopCapturingAudio()
      if self._audio_recorded_file:
        return self._audio_recorded_file.name, data_format
      else:
        return None, None
    finally:
      self.ResetRoute()

  def ResetRoute(self):
    """Resets the audio route."""
    self._audio_route_manager.ResetRouteToDumper()


class DpInputFlow(FpgaInputFlowWithAudio):
  """An abstraction of the entire flow for DisplayPort."""

  _DEVICE_NAME = 'DP'

  _DELAY_VIDEO_MODE_PROBE = 1.0
  _TIMEOUT_VIDEO_STABLE_PROBE = 5

  _HPD_PULSE_WIDTH = 0.1

  _AUX_BYPASS_MUXES = {
      ids.DP1: io.MuxIo.MASK_DP1_AUX_BP_L,
      ids.DP2: io.MuxIo.MASK_DP2_AUX_BP_L
  }

  # Two thresholds defining a hysteresis zone to avoid rapid mode changes due
  # to pixel clock noise.
  _PIXEL_MODE_PCLK_THRESHOLD_HIGH = 200  # MHz
  _PIXEL_MODE_PCLK_THRESHOLD_LOW = 180  # MHz

  _DETECT_VALUE = 6

  def __init__(self, *args):
    self._is_dual_pixel_mode = False

    super(DpInputFlow, self).__init__(*args)
    self._edid = edid.DpEdid(args[0], self._main_bus)

  def IsDualPixelMode(self):
    """Returns if the input flow uses dual pixel mode."""
    return self._is_dual_pixel_mode

  def IsPhysicalPlugged(self):
    """Returns if the physical cable is plugged."""
    return self._rx.IsCablePowered()

  def IsPlugged(self):
    """Returns if the HPD line is plugged."""
    return self._fpga.hpd.IsPlugged(self._input_id)

  def Plug(self):
    """Asserts HPD line to high, emulating plug."""
    if self.IsEdidEnabled():
      self._edid.Enable()
    if self.IsDdcEnabled():
      self._EnableDdc()
    self._fpga.hpd.Plug(self._input_id)

  def Unplug(self):
    """Deasserts HPD line to low, emulating unplug."""
    self._edid.Disable()
    self._DisableDdc()
    self.UnplugHPD()

  def UnplugHPD(self):
    """Only deasserts HPD line to low"""
    self._fpga.hpd.Unplug(self._input_id)

  def FireHpdPulse(
      self, deassert_interval_usec, assert_interval_usec, repeat_count,
      end_level):
    """Fires one or more HPD pulse (low -> high -> low -> ...).

    Args:
      deassert_interval_usec: The time in microsecond of the deassert pulse.
      assert_interval_usec: The time in microsecond of the assert pulse.
                            If None, then use the same value as
                            deassert_interval_usec.
      repeat_count: The count of HPD pulses to fire.
      end_level: HPD ends with 0 for LOW (unplugged) or 1 for HIGH (plugged).
    """
    self._fpga.hpd.FireHpdPulse(
        self._input_id, deassert_interval_usec, assert_interval_usec,
        repeat_count, end_level)

  def _EnableDdc(self):
    """Enable the DDC bus."""
    # Enable AUX bypass
    self._mux_io.ClearOutputMask(self._AUX_BYPASS_MUXES[self._input_id])

  def _DisableDdc(self):
    """Disable the DDC bus."""
    # Disable AUX bypass
    self._mux_io.SetOutputMask(self._AUX_BYPASS_MUXES[self._input_id])

  def ReadEdid(self):
    """Reads the EDID content."""
    return self._edid.ReadEdid()

  def WriteEdid(self, data):
    """Writes the EDID content."""
    self._edid.WriteEdid(data)

  def WaitVideoInputStable(self, timeout=None):
    """Waits the video input stable or timeout."""
    return self._rx.WaitVideoInputStable(timeout)

  def _IsFrameLocked(self):
    """Returns whether the FPGA frame is locked.

    It compares the resolution reported from the receiver with the FPGA.

    Returns:
      True if the frame is locked; otherwise, False.
    """
    resolution_fpga = self._frame_manager.ComputeResolution()
    resolution_rx = self._rx.GetFrameResolution()
    if resolution_fpga == resolution_rx:
      logging.info('same resolution: %dx%d', *resolution_fpga)
      return True
    else:
      logging.info('diff resolution: fpga:%dx%d != rx:%dx%d',
                   *(resolution_fpga + resolution_rx))
      return False

  def WaitVideoOutputStable(self, timeout=None):
    """Waits the video output stable or timeout."""
    if timeout is None:
      timeout = self._TIMEOUT_VIDEO_STABLE_PROBE
    try:
      common.WaitForCondition(
          self._IsFrameLocked, True, self._DELAY_VIDEO_MODE_PROBE, timeout)
    except common.TimeoutError:
      return False
    return True

  def GetResolution(self):
    """Gets the resolution of the video flow."""
    if self.WaitVideoOutputStable():
      return self._rx.GetFrameResolution()
    else:
      raise InputFlowError(
          'Frame resolution not stable. Rx:%r, FPGA:%r',
          self._rx.GetFrameResolution(),
          self._frame_manager.ComputeResolution())

  def GetVideoParams(self):
    """Gets video parameters.

    Returns:
      A dict containing video parameters. Fields are omitted if unknown.
    """
    if not self.WaitVideoInputStable():
      raise InputFlowError('Video input not stable')
    return self._rx.GetVideoParams()

  def GetLastInfoFrame(self, infoframe_type):
    """Obtains the last received InfoFrame of the specified type.

    Args:
      infoframe_type (string): the InfoFrame type

    Returns:
      A dict containing the InfoFrame.
    """
    if not self.WaitVideoInputStable():
      raise InputFlowError('Video input is not stable')
    return self._rx.GetLastInfoFrame(infoframe_type)

  def _SetPixelMode(self):
    """Sets the pixel mode based on the pixel clock of the input signal.

    Returns:
      True if pixel mode is changed; False if nothing is changed.
    """
    pclk = self._rx.GetPixelClock()
    logging.info('PCLK = %s', pclk)
    if (self._PIXEL_MODE_PCLK_THRESHOLD_LOW <= pclk <=
        self._PIXEL_MODE_PCLK_THRESHOLD_HIGH):
      # Hysteresis: do not change mode if pclk is in this buffer zone.
      return False
    dual_pixel_mode = pclk >= self._PIXEL_MODE_PCLK_THRESHOLD_HIGH

    if self._is_dual_pixel_mode != dual_pixel_mode:
      self._is_dual_pixel_mode = dual_pixel_mode
      if dual_pixel_mode:
        self._rx.SetDualPixelMode()
        logging.info('Changed to dual pixel mode')
      else:
        self._rx.SetSinglePixelMode()
        logging.info('Changed to single pixel mode')
      self._frame_manager = frame_manager.FrameManager(
          self._input_id, self._rx, self._GetEffectiveVideoDumpers())
      self.Select()
      return True
    return False

  def DoFSM(self):
    """Does the Finite-State-Machine to ensure the input flow ready.

    The receiver requires to do the FSM in order to clear its state, in case
    of some events happended, like mode change, power reattach, etc.

    It should be called before doing any post-receiver-action, like capturing
    frames.
    """
    if not self._rx.IsVideoInputStable() or not self._IsFrameLocked():
      self.InitDevice()  # reset rx
      video_input_stable = self._rx.WaitVideoInputStable()

      if not video_input_stable:
        logging.info('Send DP HPD pulse to reset source...')
        self._fpga.hpd.Unplug(self._input_id)
        time.sleep(self._HPD_PULSE_WIDTH)
        self._fpga.hpd.Plug(self._input_id)
        video_input_stable = self._rx.WaitVideoInputStable()

      if video_input_stable:
        self._SetPixelMode()
        self.Select()  # to make sure mux is properly set for this FpgaInputFlow
        if self.WaitVideoOutputStable():
          logging.info('DP FSM done')
          return

      # Check the cable still connected, a common dongle problem
      if not self.IsPhysicalPlugged():
        logging.error('DP cable disconnected; probably a dongle issue')
        raise InputFlowError('DP cable disconnected')
      elif not self.IsPlugged():
        logging.error('DP port not plugged; probably a programming issue')
        raise InputFlowError('DP port not plugged')
      else:
        logging.error('DP FSM failed')
        raise InputFlowError('DP FSM failed')
    else:
      if self._SetPixelMode():
        self.WaitVideoOutputStable()
      logging.info('Skip resetting DP rx.')

  def SetContentProtection(self, enabled):
    """Sets the content protection state.

    Args:
      enabled: True to enable; False to disable.
    """
    raise NotImplementedError('SetContentProtection')

  def IsContentProtectionEnabled(self):
    """Returns True if the content protection is enabled.

    Returns:
      True if the content protection is enabled; otherwise, False.
    """
    raise NotImplementedError('IsContentProtectionEnabled')

  def IsVideoInputEncrypted(self):
    """Returns True if the video input is encrypted.

    Returns:
      True if the video input is encrypted; otherwise, False.
    """
    raise NotImplementedError('IsVideoInputEncrypted')

  def _ResetAudioLogic(self):
    self._rx.ResetAudioLogic()

  def GetAudioChannels(self):
    """Returns the number of received audio channels."""
    return self._rx.GetAudioChannels()

  def GetAudioFormat(self):
    """Gets the format currently used by audio capture.

    Returns:
      An audio.AudioDataFormat object.
    """
    return audio.AudioDataFormat(file_type='raw', sample_format='S32_LE',
        channel=8, rate=self._rx.GetAudioRate())

  def TriggerLinkFailure(self):
    """Trigger a link failure."""
    self._rx.SetLinkFailure()
    # Send a short pulse (0.5 <= width_ms <= 1.0). See DP spec section 3.3.
    self.FireHpdPulse(1000, 1000, 1, 1)


class HdmiInputFlow(FpgaInputFlowWithAudio):
  """An abstraction of the entire flow for HDMI."""

  _DEVICE_NAME = 'HDMI'

  # The firmware for the 6803 reference board sets the rx in dual pixel mode
  # when the pixel clock is greater than 160. Here, we use 130 instead of 160
  # as the FPGA works more reliably when the pixel clock is under this value.
  # Two thresholds defining a hysteresis zone to avoid rapid mode changes due
  # to pixel clock noise.
  _PIXEL_MODE_PCLK_THRESHOLD_HIGH = 130  # MHz
  _PIXEL_MODE_PCLK_THRESHOLD_LOW = 126  # MHz

  _DELAY_VIDEO_MODE_PROBE = 0.1
  _TIMEOUT_VIDEO_STABLE_PROBE = 10
  _DELAY_WAITING_GOOD_PIXELS = 3

  _DETECT_VALUE = 84

  def __init__(self, *args):
    self._is_dual_pixel_mode = True

    super(HdmiInputFlow, self).__init__(*args)
    self._edid = edid.HdmiEdid(self._main_bus)

  def IsDualPixelMode(self):
    """Returns if the input flow uses dual pixel mode."""
    return self._is_dual_pixel_mode

  def IsPhysicalPlugged(self):
    """Returns if the physical cable is plugged."""
    return self._rx.IsCablePowered()

  def IsPlugged(self):
    """Returns if the HPD line is plugged."""
    return self._fpga.hpd.IsPlugged(self._input_id)

  def Plug(self):
    """Asserts HPD line to high, emulating plug."""
    if self.IsEdidEnabled():
      self._edid.Enable()
    if self.IsDdcEnabled():
      self._EnableDdc()
    self._fpga.hpd.Plug(self._input_id)

  def Unplug(self):
    """Deasserts HPD line to low, emulating unplug."""
    self._edid.Disable()
    self._DisableDdc()
    self.UnplugHPD()

  def UnplugHPD(self):
    """Only deasserts HPD line to low"""
    self._fpga.hpd.Unplug(self._input_id)

  def FireHpdPulse(
      self, deassert_interval_usec, assert_interval_usec, repeat_count,
      end_level):
    """Fires one or more HPD pulse (low -> high -> low -> ...).

    Args:
      deassert_interval_usec: The time in microsecond of the deassert pulse.
      assert_interval_usec: The time in microsecond of the assert pulse.
                            If None, then use the same value as
                            deassert_interval_usec.
      repeat_count: The count of HPD pulses to fire.
      end_level: HPD ends with 0 for LOW (unplugged) or 1 for HIGH (plugged).
    """
    self._fpga.hpd.FireHpdPulse(
        self._input_id, deassert_interval_usec, assert_interval_usec,
        repeat_count, end_level)

  def _EnableDdc(self):
    """Enable the DDC bus."""
    self._mux_io.ClearOutputMask(io.MuxIo.MASK_HDMI_DDC_BP_L)

  def _DisableDdc(self):
    """Disable the DDC bus."""
    self._mux_io.SetOutputMask(io.MuxIo.MASK_HDMI_DDC_BP_L)

  def ReadEdid(self):
    """Reads the EDID content."""
    return self._edid.ReadEdid()

  def WriteEdid(self, data):
    """Writes the EDID content."""
    self._edid.WriteEdid(data)

  def _SetPixelMode(self):
    """Sets the pixel mode based on the pixel clock of the input signal.

    Returns:
      True if pixel mode is changed; False if nothing is changed.
    """
    pclk = self._rx.GetPixelClock()
    logging.info('PCLK = %s', pclk)
    if (self._PIXEL_MODE_PCLK_THRESHOLD_LOW <= pclk <=
        self._PIXEL_MODE_PCLK_THRESHOLD_HIGH):
      # Hysteresis: do not change mode if pclk is in this buffer zone.
      return False
    dual_pixel_mode = pclk >= self._PIXEL_MODE_PCLK_THRESHOLD_HIGH
    if self._is_dual_pixel_mode != dual_pixel_mode:
      self._is_dual_pixel_mode = dual_pixel_mode
      if dual_pixel_mode:
        self._rx.SetDualPixelMode()
        logging.info('Changed to dual pixel mode')
      else:
        self._rx.SetSinglePixelMode()
        logging.info('Changed to single pixel mode')
      self._frame_manager = frame_manager.FrameManager(
          self._input_id, self._rx, self._GetEffectiveVideoDumpers())
      self.Select()
      return True
    return False

  def DoFSM(self):
    """Does the Finite-State-Machine to ensure the input flow ready.

    The receiver requires to do the FSM in order to clear its state, in case
    of some events happended, like mode change, power reattach, etc.

    It should be called before doing any post-receiver-action, like capturing
    frames.
    """
    is_reset_needed = self._rx.IsResetNeeded()
    if is_reset_needed:
      self._rx.Reset()

    if self._rx.WaitVideoInputStable():
      pixel_mode_changed = self._SetPixelMode()
      if is_reset_needed or pixel_mode_changed:
        self.WaitVideoOutputStable()
        # TODO(waihong): Remove this hack only for Nyan-Big.
        # http://crbug.com/402152
        time.sleep(self._DELAY_WAITING_GOOD_PIXELS)
    else:
      message = 'Video input not stable.'
      logging.error(message)
      raise InputFlowError(message)

  def WaitVideoInputStable(self, timeout=None):
    """Waits the video input stable or timeout. Returns success or not."""
    return self._rx.WaitVideoInputStable(timeout)

  def _IsFrameLocked(self):
    """Returns whether the FPGA frame is locked.

    It compares the resolution reported from the receiver with the FPGA.

    Returns:
      True if the frame is locked; otherwise, False.
    """
    resolution_fpga = self._frame_manager.ComputeResolution()
    resolution_rx = self._rx.GetFrameResolution()
    if resolution_fpga == resolution_rx:
      logging.info('same resolution: %dx%d', *resolution_fpga)
      return True
    else:
      logging.info('diff resolution: fpga:%dx%d != rx:%dx%d',
                   *(resolution_fpga + resolution_rx))
      return False

  def WaitVideoOutputStable(self, timeout=None):
    """Waits the video output stable or timeout.

    Raises:
      InputFlowError if timeout.
    """
    if timeout is None:
      timeout = self._TIMEOUT_VIDEO_STABLE_PROBE
    try:
      common.WaitForCondition(
          self._IsFrameLocked, True, self._DELAY_VIDEO_MODE_PROBE, timeout)
    except common.TimeoutError:
      message = 'Timeout waiting video output stable'
      logging.error(message)
      logging.error('RX dump: %r', self._rx.Get(0, 256))
      raise InputFlowError(message)

  def GetResolution(self):
    """Gets the resolution of the video flow."""
    self.WaitVideoOutputStable()
    return self._rx.GetFrameResolution()

  def GetVideoParams(self):
    """Gets video parameters.

    Returns:
      A dict containing video parameters. Fields are omitted if unknown.
    """
    if not self.WaitVideoInputStable():
      raise InputFlowError('Video input not stable')
    return self._rx.GetVideoParams()

  def GetLastInfoFrame(self, infoframe_type):
    """Obtains the last received InfoFrame of the specified type.

    Args:
      infoframe_type (string): the InfoFrame type

    Returns:
      A dict containing the InfoFrame.
    """
    if not self.WaitVideoInputStable():
      raise InputFlowError('Video input is not stable')
    return self._rx.GetLastInfoFrame(infoframe_type)

  def SetContentProtection(self, enabled):
    """Sets the content protection state.

    Args:
      enabled: True to enable; False to disable.
    """
    self._rx.SetContentProtection(enabled)

  def IsContentProtectionEnabled(self):
    """Returns True if the content protection is enabled.

    Returns:
      True if the content protection is enabled; otherwise, False.
    """
    return self._rx.IsContentProtectionEnabled()

  def IsVideoInputEncrypted(self):
    """Returns True if the video input is encrypted.

    Returns:
      True if the video input is encrypted; otherwise, False.
    """
    return self._rx.IsVideoInputEncrypted()

  def _ResetAudioLogic(self):
    """Reset audio logic so receiver can resume from error state."""
    self._rx.ResetAudioLogic()

  def GetAudioChannels(self):
    """Returns the number of received audio channels."""
    return self._rx.GetAudioChannels()

  def GetAudioFormat(self):
    """Gets the format currently used by audio capture.

    Returns:
      An audio.AudioDataFormat object.
    """
    return audio.AudioDataFormat(file_type='raw', sample_format='S32_LE',
        channel=8, rate=self._rx.GetAudioRate())


class VgaInputFlow(FpgaInputFlow):
  """An abstraction of the entire flow for VGA."""

  _DEVICE_NAME = 'VGA'
  _IS_DUAL_PIXEL_MODE = False
  _DELAY_CHECKING_STABLE_PROBE = 0.1
  _TIMEOUT_CHECKING_STABLE = 5
  _DELAY_RESOLUTION_PROBE = 0.05

  _DETECT_VALUE = 52

  def __init__(self, *args):
    super(VgaInputFlow, self).__init__(*args)
    self._edid = edid.VgaEdid(self._fpga)
    self._auto_vga_mode = True

  def IsDualPixelMode(self):
    """Returns if the input flow uses dual pixel mode."""
    return self._IS_DUAL_PIXEL_MODE

  def IsPhysicalPlugged(self):
    """Returns if the physical cable is plugged."""
    # VGA has no HPD to detect hot-plug. We check the source signal
    # to make that decision. So plug it and wait a while to see any
    # signal received. It does not work if DUT is not well-behaved.
    plugged_before_check = self.IsPlugged()
    if not plugged_before_check:
      self.Plug()
    is_stable = self._rx.WaitVideoInputStable()
    if not plugged_before_check:
      self.Unplug()
    return is_stable

  def IsPlugged(self):
    """Returns if the HPD line is plugged."""
    return not bool(self._mux_io.GetOutput() & io.MuxIo.MASK_VGA_BLOCK_SOURCE)

  def Plug(self):
    """Asserts HPD line to high, emulating plug."""
    if self.IsEdidEnabled():
      self._edid.Enable()
    if self.IsDdcEnabled():
      self._EnableDdc()
    # For VGA, unblock the RGB source to emulate plug.
    self._mux_io.ClearOutputMask(io.MuxIo.MASK_VGA_BLOCK_SOURCE)

  def Unplug(self):
    """Deasserts HPD line to low, emulating unplug."""
    self._edid.Disable()
    self._DisableDdc()
    self.UnplugHPD()

  def UnplugHPD(self):
    """Only deasserts HPD line to low"""
    # For VGA, block the RGB source to emulate unplug.
    self._mux_io.SetOutputMask(io.MuxIo.MASK_VGA_BLOCK_SOURCE)

  def SetVgaMode(self, mode):
    """Sets the mode for VGA monitor."""
    if mode.lower() == 'auto':
      self._auto_vga_mode = True
    else:
      self._auto_vga_mode = False
      self._rx.SetMode(mode)

  def _EnableDdc(self):
    """Enable the DDC bus."""
    # Chameleon board does not support disabling the DDC bus on VGA.
    # Simply enable the EDID.
    self._edid.Enable()

  def _DisableDdc(self):
    """Disable the DDC bus."""
    # Chameleon board does not support disabling the DDC bus on VGA.
    # Simply disable the EDID.
    self._edid.Disable()

  def ReadEdid(self):
    """Reads the EDID content."""
    return self._edid.ReadEdid()

  def WriteEdid(self, data):
    """Writes the EDID content."""
    self._edid.WriteEdid(data)

  def DoFSM(self):
    """Does the Finite-State-Machine to ensure the input flow ready.

    The receiver requires to do the FSM in order to clear its state, in case
    of some events happended, like mode change, power reattach, etc.

    It should be called before doing any post-receiver-action, like capturing
    frames.
    """
    if self._auto_vga_mode:
      # Detect the VGA mode and set it properly.
      if self._rx.WaitVideoInputStable():
        self._rx.SetMode(self._rx.DetectMode())
        self.WaitVideoOutputStable()
      else:
        logging.warn('Skip doing receiver FSM as video input not stable.')

  def WaitVideoInputStable(self, timeout=None):
    """Waits the video input stable or timeout. Returns success or not."""
    return self._rx.WaitVideoInputStable(timeout)

  def _IsResolutionValid(self):
    """Returns True if the resolution from FPGA is valid and not floating."""
    resolution1 = self._frame_manager.ComputeResolution()
    time.sleep(self._DELAY_RESOLUTION_PROBE)
    resolution2 = self._frame_manager.ComputeResolution()
    return resolution1 == resolution2 and 0 not in resolution1

  def WaitVideoOutputStable(self, timeout=None):
    """Waits the video output stable or timeout.

    Raises:
      InputFlowError if timeout.
    """
    if timeout is None:
      timeout = self._TIMEOUT_CHECKING_STABLE
    try:
      # Wait a valid resolution and not floating.
      common.WaitForCondition(
          self._IsResolutionValid, True, self._DELAY_CHECKING_STABLE_PROBE,
          timeout)
    except common.TimeoutError:
      message = 'Timeout waiting video output stable'
      logging.error(message)
      logging.error('RX dump: %r', self._rx.Get(0, 256))
      raise InputFlowError(message)

  def GetResolution(self):
    """Gets the resolution of the video flow."""
    self.WaitVideoOutputStable()
    width, height = self._frame_manager.ComputeResolution()
    if width == 0 or height == 0:
      raise InputFlowError('Something wrong with the resolution: %dx%d' %
                           (width, height))
    return (width, height)

  def SetContentProtection(self, enabled):
    """Sets the content protection state.

    Args:
      enabled: True to enable; False to disable.
    """
    raise InputFlowError('VGA not support content protection')

  def IsContentProtectionEnabled(self):
    """Returns True if the content protection is enabled.

    Returns:
      True if the content protection is enabled; otherwise, False.
    """
    # VGA not support content protection.
    return False

  def IsVideoInputEncrypted(self):
    """Returns True if the video input is encrypted.

    Returns:
      True if the video input is encrypted; otherwise, False.
    """
    # VGA not support content protection.
    return False

  def _ResetAudioLogic(self):
    """Resets audio logic."""
    raise NotImplementedError('_ResetAudioLogic')
