# Copyright 2016 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 stm32 usb."""

import array
import logging
import struct
import usb

import gpio_interface
import stm32usb


class SgpioError(Exception):
  """Class for exceptions of Sgpio."""

  def __init__(self, msg, value=0):
    """SgpioError constructor.

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


class Sgpio(gpio_interface.GpioInterface):
  """Provide interface to stm32 gpio USB endpoint.

  Instance Variables:
  _logger: Sgpio tagged log output
  _susb: stm32 usb object
  """

  def __init__(self, vendor=0x18d1, product=0x500f, interface=1,
               serialname=None):
    """Sgpio constructor.

    Loads libraries for libusb.  Creates instance objects
    and Gpio to iteract with the library and intializes them.

    Args:
      vendor    : usb vendor id of stm32 device
      product   : usb product id of stm32 device
      interface : interface number ( 1 - 4 ) of stm32 device to use
      serialname: string of device serialname/number TODO: is this a thing?

    Raises:
      SgpioError: An error accessing Sgpio object
    """
    self._logger = logging.getLogger('Sgpio')
    self._logger.debug('')

    self._susb = stm32usb.Susb(vendor=vendor, product=product,
                               interface=interface, serialname=serialname,
                               logger=self._logger)

    self._logger.debug('Set up stm32 gpio')

  def __del__(self):
    """Sgpio destructor."""
    self._logger.debug('Close')

  def wr_rd(self, offset, width=1, 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 : Not used. defaulted to None.
      wr_val  : value to write to the GPIO. If unset, skips the write.
      chip    : Not used. defaulted to None.
      muxfile : Not used. defaulted to None.

    Returns:
      integer value from reading the gpio value ( masked & aligned )
    """
    self._logger.debug('Sgpio.wr_rd(offset='
                       '%s, width=%s, dir_val=%s, wr_val=%s)' %
                       (offset, width, dir_val, wr_val))
    # Read preexisting values for debug output.
    ret = self._susb._read_ep.read(4, self._susb.TIMEOUT_MS)
    read_mask = struct.unpack('<I', ret)[0]
    self._logger.debug('Read mask: 0x%08x' % read_mask)

    width_mask = (1 << width) - 1
    set_mask = 0
    clear_mask = 0

    if wr_val != None:
      set_mask = (wr_val & width_mask) << offset
      clear_mask = (~wr_val & width_mask) << offset

    byte_str = struct.pack('<II', set_mask, clear_mask)
    ret = self._susb._write_ep.write(byte_str, self._susb.TIMEOUT_MS)
    if (ret != len(byte_str)):
      raise SgpioError('Wrote %d bytes, expected %d' % (ret, len(byte_str)))

    # GPIO cached values update on read,
    ret = self._susb._read_ep.read(4, self._susb.TIMEOUT_MS)
    ret = self._susb._read_ep.read(4, self._susb.TIMEOUT_MS)
    if len(ret) != 4:
      raise SgpioError('Read error: expected 4 bytes, got %d [%s]' % (len(ret),
                                                                      ret))

    read_mask = struct.unpack('<I', ret)[0]
    self._logger.debug('Read mask: 0x%08x' % read_mask)

    readvalue = (read_mask >> offset) & width_mask
    self._logger.debug('Read value: 0x%x' % readvalue)
    return readvalue


def test():
  """Test code.
  """
  loglevel = logging.DEBUG
  logging.basicConfig(
      level=loglevel,
      format='%(asctime)s - %(name)s - ' + '%(levelname)s - %(message)s')

  logging.debug('Starting')
  sobj = Sgpio()
  for i in range(1, 2):
    rd_val = sobj.wr_rd(2, wr_val=0)
    logging.debug('rd_val = %d after <2> -> 0', (rd_val))
    if rd_val != 0:
      logging.error('rd_val = %d != 0', (rd_val))

    rd_val = sobj.wr_rd(2, wr_val=1)
    logging.debug('rd_val = %d after <2> -> 1', (rd_val))
    if rd_val != 1:
      logging.error('rd_val = %d != 1', (rd_val))

    rd_val = sobj.wr_rd(2, 1, wr_val=0)
    logging.debug('rd_val = %d after <2> -> 0', (rd_val))
    if rd_val != 0:
      logging.error('rd_val = %d != 0', (rd_val))

    # release as output
    rd_val = sobj.wr_rd(2)
    logging.debug('rd_val = %d after <2> dir released', (rd_val))
    logging.info('rd_val = %d should match pu/pd', (rd_val))
  logging.debug('Finished')


if __name__ == '__main__':
  test()
