summaryrefslogtreecommitdiff
path: root/eepromer/24cXX.c
diff options
context:
space:
mode:
Diffstat (limited to 'eepromer/24cXX.c')
-rw-r--r--eepromer/24cXX.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/eepromer/24cXX.c b/eepromer/24cXX.c
new file mode 100644
index 0000000..134e5a1
--- /dev/null
+++ b/eepromer/24cXX.c
@@ -0,0 +1,182 @@
+/***************************************************************************
+ copyright : (C) by 2002-2003 Stefano Barbato
+ email : stefano@codesink.org
+
+ $Id: 24cXX.c 4230 2006-11-10 09:22:12Z khali $
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <linux/fs.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include "24cXX.h"
+
+static int i2c_write_1b(struct eeprom *e, __u8 buf)
+{
+ int r;
+ // we must simulate a plain I2C byte write with SMBus functions
+ r = i2c_smbus_write_byte(e->fd, buf);
+ if(r < 0)
+ fprintf(stderr, "Error i2c_write_1b: %s\n", strerror(errno));
+ usleep(10);
+ return r;
+}
+
+static int i2c_write_2b(struct eeprom *e, __u8 buf[2])
+{
+ int r;
+ // we must simulate a plain I2C byte write with SMBus functions
+ r = i2c_smbus_write_byte_data(e->fd, buf[0], buf[1]);
+ if(r < 0)
+ fprintf(stderr, "Error i2c_write_2b: %s\n", strerror(errno));
+ usleep(10);
+ return r;
+}
+
+static int i2c_write_3b(struct eeprom *e, __u8 buf[3])
+{
+ int r;
+ // we must simulate a plain I2C byte write with SMBus functions
+ // the __u16 data field will be byte swapped by the SMBus protocol
+ r = i2c_smbus_write_word_data(e->fd, buf[0], buf[2] << 8 | buf[1]);
+ if(r < 0)
+ fprintf(stderr, "Error i2c_write_3b: %s\n", strerror(errno));
+ usleep(10);
+ return r;
+}
+
+
+#define CHECK_I2C_FUNC( var, label ) \
+ do { if(0 == (var & label)) { \
+ fprintf(stderr, "\nError: " \
+ #label " function is required. Program halted.\n\n"); \
+ exit(1); } \
+ } while(0);
+
+int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom* e)
+{
+ int fd, r;
+ unsigned long funcs;
+ e->fd = e->addr = 0;
+ e->dev = 0;
+
+ fd = open(dev_fqn, O_RDWR);
+ if(fd <= 0)
+ return -1;
+
+ // get funcs list
+ if((r = ioctl(fd, I2C_FUNCS, &funcs) < 0))
+ return r;
+
+
+ // check for req funcs
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE );
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE );
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE_DATA );
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE_DATA );
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_WORD_DATA );
+ CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_WORD_DATA );
+
+ // set working device
+ if( ( r = ioctl(fd, I2C_SLAVE, addr)) < 0)
+ return r;
+ e->fd = fd;
+ e->addr = addr;
+ e->dev = dev_fqn;
+ e->type = type;
+ return 0;
+}
+
+int eeprom_close(struct eeprom *e)
+{
+ close(e->fd);
+ e->fd = -1;
+ e->dev = 0;
+ e->type = EEPROM_TYPE_UNKNOWN;
+ return 0;
+}
+
+#if 0
+int eeprom_24c32_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
+{
+ __u8 buf[3] = { (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
+ return i2c_write_3b(e, buf);
+}
+
+
+int eeprom_24c32_read_current_byte(struct eeprom* e)
+{
+ ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
+ return i2c_smbus_read_byte(e->fd);
+}
+
+int eeprom_24c32_read_byte(struct eeprom* e, __u16 mem_addr)
+{
+ int r;
+ ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
+ __u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
+ r = i2c_write_2b(e, buf);
+ if (r < 0)
+ return r;
+ r = i2c_smbus_read_byte(e->fd);
+ return r;
+}
+#endif
+
+
+int eeprom_read_current_byte(struct eeprom* e)
+{
+ ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
+ return i2c_smbus_read_byte(e->fd);
+}
+
+int eeprom_read_byte(struct eeprom* e, __u16 mem_addr)
+{
+ int r;
+ ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
+ if(e->type == EEPROM_TYPE_8BIT_ADDR)
+ {
+ __u8 buf = mem_addr & 0x0ff;
+ r = i2c_write_1b(e, buf);
+ } else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
+ __u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
+ r = i2c_write_2b(e, buf);
+ } else {
+ fprintf(stderr, "ERR: unknown eeprom type\n");
+ return -1;
+ }
+ if (r < 0)
+ return r;
+ r = i2c_smbus_read_byte(e->fd);
+ return r;
+}
+
+int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
+{
+ if(e->type == EEPROM_TYPE_8BIT_ADDR) {
+ __u8 buf[2] = { mem_addr & 0x00ff, data };
+ return i2c_write_2b(e, buf);
+ } else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
+ __u8 buf[3] =
+ { (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
+ return i2c_write_3b(e, buf);
+ } else {
+ fprintf(stderr, "ERR: unknown eeprom type\n");
+ return -1;
+ }
+}
+