# Copyright (c) 2013 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 i2c interface for beaglebone devices."""
import logging
import subprocess

import bbmux_controller


class BBi2cError(Exception):
  """Class for exceptions of BBi2c."""

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

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


class BBi2c(object):
  """Provide interface to i2c through beaglebone"""

  def __init__(self, interface):
    self._logger = logging.getLogger('BBi2c')
    self._interface = interface
    self._bus_num = interface['bus_num']
    # Older kernels utilizing the omap mux starts counting from 1
    if bbmux_controller.use_omapmux():
      self._bus_num += 1

  def open(self):
    """Opens access to FTDI interface as a i2c (MPSSE mode) interface.

    Raises:
      BBi2cError: If open fails
    """
    pass

  def close(self):
    """Close connection to i2c through beaglebone and cleanup.

    Raises:
      BBi2cError: If close fails
    """
    pass

  def setclock(self, speed=100000):
    """Sets i2c clock speed.

    Args:
      speed: clock speed in hertz.  Default is 100kHz
    """
    pass

  def _write(self, slv, address, wlist):
    """Preform a single i2cset write command.

    Args:
      slv: 7-bit address of the slave device.
      address: data address we are writing to. Will be written to the i2c bus.
      wlist: list of bytes to write to the slave. List length must be between
          0-2 bytes.

    Raises:
      BBi2cError: If wlist has more than 3 bytes or the i2cset call fails.
    """
    # i2cset can write up to 3 bytes to an i2c device in the format of:
    # [1-byte address][0-2 bytes of data]
    args = ['i2cset', '-y', str(self._bus_num), '0x%02x' % slv, address]
    if len(wlist) > 2:
      raise BBi2cError('Can only write up to 3 bytes (1-byte register address '
                       'and 2-byte word) per i2cset command. '
                       'wlist: %s' % wlist)
    # Form the data argument and reverse the bytes due to endianness.
    if wlist:
      data = '0x' + ''.join('%02x' % wbyte for wbyte in reversed(wlist))
      args.append(data)
      if len(wlist) == 2:
        # Put the command in word mode.
        args.append('w')
    try:
      logging.debug(' '.join(args))
      subprocess.check_call(args)
    except subprocess.CalledProcessError:
      raise BBi2cError('Failed i2c write to slave address: %s data: %s' %
                       (slv, wlist))

  def _read(self, slv, address, rcnt):
    """Read from a slave i2c device.

    Args:
      slv: 7-bit address of the slave device.
      address: data address to read.
      rcnt: number of bytes (0-2) to read from the device.

    Returns:
      list of bytes read from i2c device.

    Raises:
      BBi2cError: If read (i2cget call) fails or if rcnt > 2.
    """
    if not rcnt:
      return []

    if rcnt > 2:
      raise BBi2cError('Can only read up to 2 bytes per i2cget command.')

    if rcnt == 2:
      return self._read_two_bytes(slv, address)

    return self._read_one_byte(slv)

  def _read_one_byte(self, slv):
    """Read one byte from a slave i2c device.

    Args:
      slv: 7-bit address of the slave device.

    Returns:
      list of bytes read from i2c device.

    Raises:
      BBi2cError: If read (i2cget call) fails.
    """
    read_bytes = []
    args = ['i2cget', '-y', str(self._bus_num), '0x%x' % slv]
    try:
      logging.debug(' '.join(args))
      read_value = subprocess.check_output(args)
    except subprocess.CalledProcessError:
      raise BBi2cError('Failed i2c read of 1 byte from slave address: %s' % slv)
    read_value_int = int(read_value, 0)
    read_bytes.append(read_value_int)
    return read_bytes

  def _read_two_bytes(self, slv, address):
    """Read two byte from a slave i2c device.

    Args:
      slv: 7-bit address of the slave device.
      address: data address to read.

    Returns:
      list of bytes read from i2c device.

    Raises:
      BBi2cError: If read (i2cget call) fails.
    """
    read_bytes = []
    args = ['i2cget', '-y', str(self._bus_num), '0x%x' % slv, address, 'w']
    try:
      logging.debug(' '.join(args))
      read_value = subprocess.check_output(args)
    except subprocess.CalledProcessError:
      raise BBi2cError('Failed i2c read of 2 bytes from slave address: %s, '
                       'data address: %s.' % (slv, address))
    read_value_int = int(read_value, 0)
    # Grab the second byte first (converting little endian to big).
    read_bytes.append(read_value_int & 0xff)
    # Grab the first byte.
    read_bytes.append(read_value_int >> 8)
    return read_bytes

  def wr_rd(self, slv, wlist, rcnt):
    """Write and/or read a slave i2c device.

    Args:
      slv: 7-bit address of the slave device
      wlist: list of bytes to write to the slave.  If list length is zero its
          just a read.
      rcnt: number of bytes (0-2) to read from the device. If zero, its just a
          write.

    Returns:
      list of bytes read from i2c device.
    """
    self._logger.debug('wr_rd. slv: 0x%x, wlist: %s, rcnt: %s', slv, wlist,
                       rcnt)
    address = '0x%02x' % wlist[0]
    if wlist:
      self._write(slv, address, wlist[1:])

    return self._read(slv, address, rcnt)


def test():
  """Test code. (forked from ftdii2c.py)"""
  loglevel = logging.INFO
  logging.basicConfig(
      level=loglevel,
      format='%(asctime)s - %(name)s - ' + '%(levelname)s - %(message)s')
  i2c = BBi2c(3)

  wbuf = [0]
  slv = 0x21
  rbuf = i2c.wr_rd(slv, wbuf, 1)
  logging.info('first: i2c read of slv=0x%02x reg=0x%02x == 0x%02x', slv,
               wbuf[0], rbuf[0])
  errcnt = 0
  for cnt in xrange(1000):
    try:
      rbuf = i2c.wr_rd(slv, [], 1)
    except:
      errcnt += 1
      logging.error('errs = %d cnt = %d', errcnt, cnt)

  logging.info('last: i2c read of slv=0x%02x reg=0x%02x == 0x%02x', slv,
               wbuf[0], rbuf[0])


if __name__ == '__main__':
  test()
