#include "standard_i2c.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#if 0
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#else
#define I2C_M_WT 0x0000 /* write data, from master to slave */
#define I2C_M_RD 0x0001 /* read data, from slave to master */
#define I2C_ADDR (0x48>>1)
#define I2C_ADDR_16BIT 1 // 1:16bit i2c_addr 0:8bit i2c_addr
#define I2C_RETRIES 0x0701 /*設定收不到ACK時的重試次數 */
#define I2C_TIMEOUT 0x0702 /* 設定逾時時限的jiffies */
#define I2C_SLAVE 0x0703 /*設定從機地址 */
#define I2C_SLAVE_FORCE 0x0706 /* 強制設定從機地址 */
#define I2C_TENBIT 0x0704 /*選擇地址位長:=0 for 7bit , != 0 for 10 bit */
#define I2C_FUNCS 0x0705 /*擷取適配器支援的功能 */
#define I2C_RDWR 0x0707 /*Combined R/W transfer (one STOP only) */
#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
#define I2C_SMBUS 0x0720 /*SMBus transfer */
#define I2C_SMBUS_BYTE_DATA 2
#define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 8
#define I2C_SLAVE_FORCE 0x0706
#define I2C_SMBUS_BLOCK_MAX 32
// exact-width types
typedef char s8;
typedef short s16;
typedef int s32;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef float f32;
typedef double f64;
union i2c_smbus_data {
unsigned char byte;
unsigned short word;
unsigned char block[I2C_SMBUS_BLOCK_MAX + 2];
};
struct i2c_smbus_ioctl_data {
char read_write;
unsigned char command;
int size;
union i2c_smbus_data *data;
};
struct i2c_msg {
u16 addr; /* slave address */
u16 flags;
u16 len; /* msg length */
u8 *buf; /* pointer to msg data */
} ;
/* In ./include/linux/i2c-dev.h */
struct i2c_rdwr_ioctl_data {
/* pointers to i2c_msgs */
struct i2c_msg *msgs;
/* number of i2c_msgs */
u32 nmsgs;
};
#endif
int Standard_i2c_open(int index)
{
char dev_name[32];
sprintf(dev_name, "/dev/i2c-%d", index);
return open(dev_name, O_RDWR);
}
#if I2C_ADDR_16BIT
int write_16bit_i2c(int bus_index, u8 device_addr/*8bits*/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[3]={0,0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_read Standard_i2c_open Failed\n");
goto _OVER_;
}
ioctl(i2c_dev_fd,I2C_TIMEOUT,1);/*逾時時間*/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/*重複次數*/
e2prom_data.nmsgs=1;
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
perror("malloc error");
goto _OVER_;
}
reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom資料地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom資料地址
reg_buf[2] = pBuffer[0] ; //寫一個資料
(e2prom_data.msgs[0]).len=3; //
(e2prom_data.msgs[0]).addr=I2C_ADDR; // e2prom 裝置地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;
ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
perror("ioctl error2");
goto _OVER_;
}
printf("** %x ** \n",pBuffer[0]);
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
free(e2prom_data.msgs);
}
}
int read_16bit_i2c(int bus_index, u8 device_addr/*8bits*/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[2]={0,0},buf[2]={0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_read Standard_i2c_open Failed\n");
goto _OVER_;
}
ioctl(i2c_dev_fd,I2C_TIMEOUT,1);/*逾時時間*/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/*重複次數*/
e2prom_data.nmsgs=2;
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
perror("malloc error");
goto _OVER_;
}
reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom資料地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom資料地址
e2prom_data.nmsgs=2;
(e2prom_data.msgs[0]).len=2; //e2prom 要寫的位元組數
(e2prom_data.msgs[0]).addr=I2C_ADDR; // e2prom 裝置地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;
(e2prom_data.msgs[1]).len=1; //讀出的資料個數
(e2prom_data.msgs[1]).addr=I2C_ADDR; // e2prom 裝置地址
(e2prom_data.msgs[1]).flags=I2C_M_RD;//read
(e2prom_data.msgs[1]).buf=buf;
ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
perror("ioctl error2");
goto _OVER_;
}
printf("***0x%x***\n",(e2prom_data.msgs[1]).buf[0]);
pBuffer[0] = (e2prom_data.msgs[1]).buf[0];
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
free(e2prom_data.msgs);
}
}
//#else
int read_8bit_i2c(int bus_index, unsigned char device_addr/*8bits*/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;
/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
printf("standard_i2c_read Invalid parameter(%d >= %d)\n", byte_number, I2C_SMBUS_BLOCK_MAX);
return -1;
}
/**/
i2c_dev_fd = Standard_i2c_open(index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_read Standard_i2c_open Failed\n");
goto _OVER_;
}
/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr >> 1) & 0x7f) < 0)
{
perror("i2c ioctl:");
printf("standard_i2c_read ioctl(I2C_SLAVE) Failed\n");
goto _OVER_;
}
/**/
smbus_data.block[0] = byte_number;
ioctl_data.read_write = I2C_SMBUS_READ;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
printf("standard_i2c_read ioctl(I2C_SMBUS) Failed(%d)\n", index);
goto _OVER_;
}
if(smbus_data.block[0] != byte_number)
{
printf("standard_i2c_read ioctl read Failed(%d)(%d)\n", smbus_data.block[0], byte_number);
goto _OVER_;
}
for(index = 0; index < byte_number; index ++)
{
pBuffer[index] = smbus_data.block[index + 1];
}
ret_val = 0;
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
return ret_val;
}
int write_8bit_i2c(int bus_index, unsigned char device_addr/*8bits*/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;
/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
printf("standard_i2c_write ioctl Invalid parameter(%d)\n", byte_number);
return -1;
}
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_write Standard_i2c_open Failed\n");
goto _OVER_;
}
/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr >> 1) & 0x7f) < 0)
{
perror("i2c ioctl:");
printf("standard_i2c_write ioctl(I2C_SLAVE) Failed\n");
goto _OVER_;
}
/**/
smbus_data.block[0] = byte_number;
for(index = 0; index < byte_number; index ++)
{
smbus_data.block[index + 1] = pBuffer[index];
}
/**/
ioctl_data.read_write = I2C_SMBUS_WRITE;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
/**/
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
printf("standard_i2c_write ioctl(I2C_SMBUS) Failed(%d)\n", index);
goto _OVER_;
}
ret_val = 0;
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
return ret_val;
}
#endif
int usage(char *pname)
{
printf("%s <8/16> <dev> <reg> [value]\n", pname);
return 0;
}
/* read ./iis 16 0x24 0x0111 */
/* write ./iis 16 0x24 0x0111 0x3 */
int main(int argc, char *argv[])
{
unsigned char i2c_dev;
unsigned int i2c_reg;
unsigned char value[4];
unsigned int readvalue;
unsigned char reg_bit;
int i;
if(argc < 3)
{
usage(argv[0]);
exit(1);
}
reg_bit=strtoll(argv[1], NULL, 0);
i2c_dev=strtoll(argv[2], NULL, 0);
i2c_reg=strtoll(argv[3], NULL, 0);
printf("reg_bit %d \n",reg_bit);
if(argc == 4)
{
if(16 == reg_bit){
read_16bit_i2c(0, i2c_dev,i2c_reg, &value[0]);
}else{
read_8bit_i2c(0, i2c_dev,i2c_reg, &value[0], 1);
}
printf("read reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}
else if(argc == 5)
{
value[0]=strtoll(argv[4], NULL, 0);
if(16 == reg_bit){
write_16bit_i2c(0, i2c_dev,i2c_reg, &value[0]);
}else{
write_8bit_i2c(0, i2c_dev,i2c_reg, &value[0], 1);
}
printf("write reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}
}