# Copyright (c) 2011 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.
"""Allows creation of gpio interface via libftdigpio c library for FTDI
devices."""

import logging
import ctypes

import ftdi_utils
import ftdi_common
import gpio_interface


class FgpioError(Exception):
  """Class for exceptions of Fgpio."""
  def __init__(self, msg, value=0):
    """FgpioError constructor.

    Args:
      msg: string, message describing error in detail
      value: integer, value of error when non-zero status returned.  Default=0
    """
    super(FgpioError, self).__init__(msg, value)
    self.msg = msg
    self.value = value


class FgpioContext(ctypes.Structure):
  """Defines primary context structure for libftdigpio.

  Declared in ftdigpio.h and named fgpio_context.
  """
  _fields_ = [("fc", ctypes.POINTER(ftdi_common.FtdiContext)),
              ("gpio", ftdi_common.Gpio)]


class Fgpio(gpio_interface.GpioInterface):
  """Provide interface to libftdigpio c-library via python ctypes module.

  Instance Variables:
    _fargs: FTDI args for this interface.
    _is_closed: Whether or not the connection to this UART is closed.
    _gpio: _gpio: Instance of ftdi_common.GPIO()
    _fc: FTDI Context object.
    _fgc: FgpioContext object.
  """

  def __init__(self, vendor=ftdi_common.DEFAULT_VID,
               product=ftdi_common.DEFAULT_PID, interface=4, serialname=None):
    """Fgpio constructor.

    Loads libraries for libftdi, libftdigpio.  Creates instance objects
    (Structures), FgpioContext, FtdiContext and Gpio to iteract with the library
    and intializes them.

    Args:
      vendor    : usb vendor id of FTDI device
      product   : usb product id of FTDI device
      interface : interface number ( 1 - 4 ) of FTDI device to use
      serialname: string of device serialname/number as defined in FTDI eeprom.

    Raises:
      FgpioError: An error accessing Fgpio object
    """
    self._logger = logging.getLogger("Fgpio")
    self._logger.debug("")

    (self._flib, self._lib) = ftdi_utils.load_libs("ftdi", "ftdigpio")
    self._fargs = ftdi_common.FtdiCommonArgs(vendor_id=vendor,
                                             product_id=product,
                                             interface=interface,
                                             serialname=serialname)
    self._is_closed = True
    self._gpio = ftdi_common.Gpio()
    self._fc = ftdi_common.FtdiContext()
    self._fgc = FgpioContext()
    # initialize
    if self._flib.ftdi_init(ctypes.byref(self._fc)):
      raise FgpioError("doing ftdi_init")
    if self._lib.fgpio_init(ctypes.byref(self._fgc), ctypes.byref(self._fc)):
      raise FgpioError("doing fgpio_init")

  def __del__(self):
    """Fgpio destructor."""
    self._logger.debug("")
    if not self._is_closed:
      self.close()

  def open(self):
    """Opens access to FTDI interface as a GPIO (bitbang).

    Raises:
      FgpioError: If open fails
    """
    err = self._lib.fgpio_open(ctypes.byref(self._fgc),
                               ctypes.byref(self._fargs))
    if err:
      raise FgpioError("doing fgpio_open", err)
    self._is_closed = False

  def close(self):
    """Close access to FTDI interface as a GPIO (bitbang).

    Raises:
      FgpioError: If close fails
    """
    err = self._lib.fgpio_close(ctypes.byref(self._fgc))
    if err:
      raise FgpioError("doing fgpio_close", err)
    self._is_closed = True

  def wr_rd(self, offset, width, dir_val=None, wr_val=None, chip=None,
            muxfile=None):
    """Write and/or read GPIO bit.

    Args:
      offset  : bit offset of the gpio to read or write
      width   : integer, number of contiguous bits in gpio to read or write
      dir_val : direction value of the gpio.  dir_val is interpretted as:
                  None : read the pins via libftdi's ftdi_read_pins
                  0    : configure as input
                  1    : configure as output
      wr_val  : value to write to the GPIO.  Note wr_val is irrelevant if
                dir_val = 0
      chip    : Not used. defaulted to None.
      muxfile : Not used. defaulted to None.

    Returns:
      integer value from reading the gpio value ( masked & aligned )
    """
    rd_val = ctypes.c_ubyte()
    self._gpio.mask = (pow(2, width) - 1) << offset
    if wr_val is not None and dir_val is not None:
      self._gpio.direction = self._gpio.mask if dir_val else 0
      self._gpio.value = wr_val << offset
      self._lib.fgpio_wr_rd(ctypes.byref(self._fgc), ctypes.byref(self._gpio),
                            ctypes.byref(rd_val),
                            ftdi_common.INTERFACE_TYPE_GPIO)
    else:
      self._lib.fgpio_wr_rd(ctypes.byref(self._fgc), 0, ctypes.byref(rd_val),
                            ftdi_common.INTERFACE_TYPE_GPIO)
    self._logger.debug("dir:%s val:%s returned %d" %
                       (str(dir_val), str(wr_val), rd_val.value))
    return (rd_val.value & self._gpio.mask) >> offset


def test():
  """Test code.

  (TODO) tbroch: enhance and make Googley & pythonic from a unittest
  perspective.
  """
  (options, args) = ftdi_utils.parse_common_args()
  loglevel=logging.INFO
  if options.debug:
    loglevel = logging.DEBUG
  logging.basicConfig(level=loglevel,
                      format="%(asctime)s - %(name)s - " +
                      "%(levelname)s - %(message)s")
  for i in range(1, 5):
    fobj = Fgpio(options.vendor, options.product, i)
    fobj.open()
    rd_val = fobj.wr_rd(6,1,0)
    logging.debug("rd_val = %d after <6> -> 0" % (rd_val))
    if rd_val != 0:
      logging.error("rd_val = %d != 0" % (rd_val))

    rd_val = fobj.wr_rd(6,1,1)
    logging.debug("rd_val = %d after <6> -> 1" % (rd_val))
    if rd_val != 1:
      logging.error("rd_val = %d != 1" % (rd_val))

    rd_val = fobj.wr_rd(6,1,0)
    logging.debug("rd_val = %d after <6> -> 0" % (rd_val))
    if rd_val != 0:
      logging.error("rd_val = %d != 0" % (rd_val))

    # release as output
    rd_val = fobj.wr_rd(6,0,0)
    logging.debug("rd_val = %d after <6> dir released" % (rd_val))
    logging.info("rd_val = %d should match pu/pd" % (rd_val))
    fobj.close()

if __name__ == "__main__":
  test()
