/*
 * (C) Copyright 2014 Google, Inc.
 * All rights reserved.
 *
 */

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <unistd.h>

#include "i2c.h"

extern int ioctl(int, int, void *);

int i2cr(int controller, uint8_t device_addr, uint32_t cell_addr,
         uint32_t addr_len, uint32_t data_len, uint8_t *buf) {
  char filename[FILENAME_SIZE];
  int file;
  int i;
  uint32_t temp;
  unsigned char addrbuf[4]; /* up to 4 byte addressing ! */
  int return_code = 0;
  struct i2c_msg message[2];
  struct i2c_rdwr_ioctl_data rdwr_arg;
  unsigned int read_data_len;

  /* open the I2C adapter */
  snprintf(filename, sizeof(filename), I2C_DEV_FILE, controller);
  if ((file = open(filename, O_RDWR)) < 0) {
    printf("I2C Error open file %s: %s", filename, strerror(errno));
    return -1;
  }

  if ((return_code = flock(file, LOCK_EX)) < 0) {
    printf("I2C Error lock file %s: %s", filename, strerror(errno));
    goto i2cr_cleanup;
  }

  /* if we need to send addr, use combined transaction */
  if (addr_len > 0) {
    /* build struct i2c_msg 0 */
    message[0].addr = device_addr;
    message[0].flags = 0;
    message[0].len = addr_len;
    temp = cell_addr;
    /* store addr into buffer */
    for (i = addr_len - 1; i >= 0; i--) {
      addrbuf[i] = temp & 0xff;
      temp >>= 8;
    }
    message[0].buf = addrbuf;

    /* build struct i2c_msg 1 */
    message[1].addr = device_addr;
    message[1].flags = I2C_M_RD;
    message[1].len = data_len;
    message[1].buf = buf;

    /* build arg */
    rdwr_arg.msgs = message;
    rdwr_arg.nmsgs = 2;

    return_code = ioctl(file, I2C_RDWR, &rdwr_arg);

    /* since we pass in rdwr_arg.nmsgs = 2, expect a return of 2 on success */
    if (return_code == 2) {
      return_code = 0;
    }

    goto i2cr_cleanup;
  }

  /* setup device address */
  if ((return_code = ioctl(file, I2C_SLAVE, (void *)(uintptr_t)device_addr)) <
      0) {
    printf("I2C Error: Could not set device address to %x: %s", device_addr,
           strerror(errno));
    goto i2cr_cleanup;
  }

  /* now read data out of the device */
  read_data_len = read(file, buf, data_len);
  if (read_data_len == data_len) {
    return_code = 0;
  }

i2cr_cleanup:
  flock(file, LOCK_UN);
  close(file);

  return return_code;
}

int i2cw(int controller, uint8_t device_addr, uint32_t cell_addr,
         uint32_t addr_len, uint32_t data_len, uint8_t *buf) {
  char filename[FILENAME_SIZE];
  int file;
  int i;
  uint32_t temp;
  uint8_t tempbuf[I2C_PAGE_SIZE + 4];
  int return_code;
  uint8_t *writebuf = buf;
  unsigned int write_data_len;

  /* check data len */
  if (data_len > I2C_PAGE_SIZE) {
    return -1;
  }

  /* open the corrrsponding I2C adapter */
  snprintf(filename, sizeof(filename), I2C_DEV_FILE, controller);
  if ((file = open(filename, O_RDWR)) < 0) {
    printf("I2C Error open file %s: %s", filename, strerror(errno));
    return -1;
  }

  if ((return_code = flock(file, LOCK_EX)) < 0) {
    printf("I2C Error lock file %s: %s", filename, strerror(errno));
    goto i2cw_cleanup;
  }

  /* setup device address */
  if ((return_code =
           ioctl(file, I2C_SLAVE_FORCE, (void *)(uintptr_t)device_addr)) < 0) {
    printf("I2C Error: Could not set device address to %x: %s", device_addr,
           strerror(errno));
    goto i2cw_cleanup;
  }

  /* if we need to send addr */
  if (addr_len > 0) {
    temp = cell_addr;
    /* store addr into buffer */
    for (i = (int)(addr_len - 1); i >= 0; i--) {
      tempbuf[i] = temp & 0xff;
      temp >>= 8;
    }
    /* copy data over into tempbuf, right after the cell address */
    for (i = 0; i < (int)(data_len); i++) {
      tempbuf[addr_len + i] = buf[i];
    }
    writebuf = tempbuf;
  }

  /* now write addr + data out to the device */
  write_data_len = write(file, writebuf, addr_len + data_len);

  if (write_data_len == (addr_len + data_len)) {
    return_code = 0;
  }

i2cw_cleanup:
  flock(file, LOCK_UN);
  close(file);

  return return_code;
}
