/*
    zi2c.c - I2C library
    Copyright (C) 2018 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#include <libziaint.h>

#include <zbus.h>
#include <zdebug.h>
#include <zi2c.h>
#include <zmisc.h>

#include <fcntl.h>
#include <glib.h>
#ifdef Z_HAVE_LINUX_I2C_DEV_H
#include <linux/i2c-dev.h>
#endif
#include <stdint.h>
#ifdef Z_HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef Z_HAVE_UNISTD_H
#include <unistd.h>
#endif


#ifdef Z_HAVE_LINUX_I2C_DEV_H


int zi2c_write(struct zbusdev *dev, void *buf, size_t len){
    if (dev->fd < 0) return -1;

    int ret = write(dev->fd, buf, len); 
    if (ret < 0) {
        close(dev->fd);
        dev->fd = -1;
        return -1;
    }
    return ret;
}

int zi2c_read(struct zbusdev *dev, void *buf, size_t len){
    if (dev->fd < 0) return -1;

    int ret = read(dev->fd, buf, len); 
    if (ret < 0) {
        close(dev->fd);
        dev->fd = -1;
        return -1;
    }
    return ret;
}

#else

int zi2c_write(struct zbusdev *dev, void *buf, size_t len) {
    zinternal("zi2c_write not supported on this system");

    return -1;
}

int zi2c_read(struct zbusdev *dev, void *buf, size_t len){
    zinternal("zi2c_read not supported on this system");

    return -1;
}

#endif

struct zbusdev *zi2c_init(int busnr, int slave){
    struct zbusdev *dev = (struct zbusdev *)g_new0(struct zbusdev, 1);
    dev->busnr = busnr;
    dev->slave = slave;
    
    dev->filename = g_strdup_printf("/dev/i2c-%d", dev->busnr);

#ifdef Z_HAVE_LINUX_I2C_DEV_H
    dev->free = zi2c_free;
    dev->write = zi2c_write;
    dev->read = zi2c_read;
    
    dev->fd = open(dev->filename, O_RDWR);
    if (dev->fd < 0) {
        zi2c_free(dev);
        return NULL;
    }
    
    //printf("I2C_SLAVE %d %d\n", I2C_SLAVE, dev->slave);
    int ret = ioctl(dev->fd, I2C_SLAVE, dev->slave);
    if (ret < 0) {
        zi2c_free(dev);
        return NULL;
    }

#endif
    return dev;
}

int zi2c_free(struct zbusdev *dev){
    if (dev->fd >= 0){
        close(dev->fd);
        dev->fd = -1;
    }
    return 0;
}

