# linuxi2c.py
#
# Linux-compatible I2C interface using ioctl
#
# Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#   Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#
#   Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#
#   Neither the name of Texas Instruments Incorporated nor the names of
#   its contributors may be used to endorse or promote products derived
#   from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import os
import fcntl


class LinuxI2C(object):
    """Simple Linux I2C port access"""
    I2C_SLAVE = 0x0703
    I2C_TENBIT = 0x0704

    def __init__(self, busnum, slave_address):
        super(LinuxI2C, self).__init__()
        self.busnum = busnum
        self.slave_address = slave_address
        self.fd = None

    def open(self, ):
        self.fd = os.open('/dev/i2c-%d' % self.busnum, os.O_RDWR)
        if self.fd < 0:
            raise IOError('could not open I2C interface')
        self.set_slave_address(self.slave_address)

    def close(self, ):
        if self.fd > 0:
            os.close(self.fd)
        self.fd = None

    def set_slave_address(self, slave_address):
        if self.fd > 0:
            if fcntl.ioctl(self.fd, self.I2C_TENBIT, 0) < 0:
                raise IOError('cannot set 7 bit I2C addressing')
            if fcntl.ioctl(self.fd, self.I2C_SLAVE, slave_address >> 1) < 0:
                raise IOError('cannot set slave address')
            print('set slave address:', slave_address >> 1)
        else:
            raise IOError('I2C interface is not open!')

    def write(self, data): 
        if self.fd > 0:
            wrbuff = bytearray(data)
            if os.write(self.fd, wrbuff) < 0:
                raise IOError('cannot write to I2C interface')
        else:
            raise IOError('I2C interface is not open!')

    def read(self, numbytes):
        if self.fd > 0:
            rdbuff = os.read(self.fd, numbytes)
            return list(bytearray(rdbuff))
        else:
            raise IOError('I2C interface is not open!')
