├── at24c.h ├── README.md ├── main.c ├── at24c.c └── i2c-dev.h /at24c.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | ***************************************************************************/ 9 | #ifndef _24CXX_H_ 10 | #define _24CXX_H_ 11 | #include "i2c-dev.h" 12 | 13 | #define EEPROM_TYPE_UNKNOWN 0 14 | #define EEPROM_TYPE_8BIT_ADDR 1 15 | #define EEPROM_TYPE_16BIT_ADDR 2 16 | 17 | struct eeprom 18 | { 19 | char *dev; // device file i.e. /dev/i2c-N 20 | int i2c_addr; // i2c address 21 | int fd; // file descriptor 22 | int type; // eeprom register size(8bit/16bit) 23 | int write_cycle_time; 24 | int bits; // eeprom memory size(Kbits) 25 | //__u16 bytes; // eeprom memory size(byte) 26 | __u32 bytes; // eeprom memory size(byte) 27 | }; 28 | 29 | /* 30 | * opens the eeprom device at [dev_fqn] (i.e. /dev/i2c-N) 31 | * whose address is [i2c_addr] 32 | * number of bits is [bits] 33 | * and set the eeprom [e] 34 | */ 35 | int eeprom_open(char *dev_fqn, int i2c_addr, int bits, int delay, struct eeprom*); 36 | /* 37 | * closees the eeprom device [e] 38 | */ 39 | int eeprom_close(struct eeprom *e); 40 | /* 41 | * get EEPROM bytes 42 | */ 43 | __u32 getEEPROMbytes(struct eeprom* e); 44 | /* 45 | * read and returns the eeprom byte at memory address [mem_addr] 46 | * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 47 | */ 48 | int eeprom_read_byte(struct eeprom* e, __u16 mem_addr); 49 | /* 50 | * read the current byte 51 | * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 52 | */ 53 | int eeprom_read_current_byte(struct eeprom *e); 54 | /* 55 | * writes [data] at memory address [mem_addr] 56 | * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 57 | */ 58 | int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data); 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raspberry-at24c 2 | 3 | Two-Wire Serial EEPROM Access Library for RaspberryPi. 4 | 5 | I forked from [eeprog-0.7.6-tear5.tar.gz](https://www.richud.com/wiki/Rasberry_Pi_I2C_EEPROM_Program) 6 | 7 | --- 8 | 9 | # Memory size 10 | 11 | |Device|Number of Bits|Number of 8-bit Bytes|i2c address| 12 | |:---|:---|:---|:---| 13 | |24C02|2K|256|0x50-0x57| 14 | |24C04|4K|512|0x50/0x52/0x54/0x56| 15 | |24C08|8K|1024|0x50/0x54| 16 | |24C16|16K|2048|0x50| 17 | |24C32|32K|4096|0x50-0x57| 18 | |24C64|64K|8192|0x50-0x57| 19 | |24C128|128K|16384|0x50-0x57| 20 | |24C256|256K|32768|0x50-0x57| 21 | |24C512|512K|65536|0x50-0x57| 22 | 23 | --- 24 | 25 | # Build 26 | for 24C02 27 | cc -o main main.c at24c.c -DC02 28 | 29 | for 24C04 30 | cc -o main main.c at24c.c -DC04 31 | 32 | for 24C08 33 | cc -o main main.c at24c.c -DC08 34 | 35 | for 24C16 36 | cc -o main main.c at24c.c -DC16 37 | 38 | for 24C32 39 | cc -o main main.c at24c.c -DC32 40 | 41 | for 24C64 42 | cc -o main main.c at24c.c -DC64 43 | 44 | for 24C128 45 | cc -o main main.c at24c.c -DC128 46 | 47 | for 24C256 48 | cc -o main main.c at24c.c -DC256 49 | 50 | for 24C512 51 | cc -o main main.c at24c.c -DC512 52 | 53 | sudo ./main [i2c-address] 54 | Default i2c-address is 0x50. 55 | 56 | --- 57 | 58 | - 24C04 59 | ![24c04](https://user-images.githubusercontent.com/6020549/79177539-08dd1480-7e3e-11ea-82d1-0c2baf508fe8.jpg) 60 | 61 | - 24C16 62 | ![24c16](https://user-images.githubusercontent.com/6020549/79177549-0c709b80-7e3e-11ea-9342-39a12b610e21.jpg) 63 | 64 | - 24C32 65 | ![24c32](https://user-images.githubusercontent.com/6020549/79177555-0f6b8c00-7e3e-11ea-9dc1-ea0ee03f80f1.jpg) 66 | 67 | - 24C64 68 | ![24c64](https://user-images.githubusercontent.com/6020549/79177559-12ff1300-7e3e-11ea-811e-10c509326e99.jpg) 69 | 70 | - 24C128 71 | ![24c128](https://user-images.githubusercontent.com/6020549/79177565-15fa0380-7e3e-11ea-966e-85721f64bd66.jpg) 72 | 73 | - 24C256 74 | ![24c256](https://user-images.githubusercontent.com/6020549/79177569-198d8a80-7e3e-11ea-81fd-baaff732252f.jpg) 75 | 76 | - 24C512 77 | ![24c512](https://user-images.githubusercontent.com/6020549/83345333-c9ff1180-a34c-11ea-8c7c-24ed6d2f3777.jpg) 78 | 79 | --- 80 | 81 | # API 82 | 83 | ``` 84 | // Open device 85 | int eeprom_open(char *dev_fqn, int i2c_addr, int bits, int delay, struct eeprom*); 86 | 87 | // Get EEPROM memory size 88 | __u16 getEEPROMbytes(struct eeprom* e); 89 | 90 | // Read data from EEPROM 91 | int eeprom_read_byte(struct eeprom* e, __u16 mem_addr); 92 | 93 | // Write data to EEPROM 94 | int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data); 95 | ``` 96 | 97 | --- 98 | 99 | # Wireing 100 | A0 A1 A2 is used to select i2c address. 101 | When A0 A1 A2 is GND, i2c address is 0x50. 102 | 103 | ![24cxx](https://user-images.githubusercontent.com/6020549/59955416-fd8eb600-94c4-11e9-87f8-246db2913a04.jpg) 104 | 105 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | I forked from here. 3 | https://www.richud.com/wiki/Rasberry_Pi_I2C_EEPROM_Program 4 | 5 | 24C02 cc -o main main.c at24c.c -DC02 6 | 24C04 cc -o main main.c at24c.c -DC04 7 | 24C08 cc -o main main.c at24c.c -DC08 8 | 24C16 cc -o main main.c at24c.c -DC16 9 | 24C32 cc -o main main.c at24c.c -DC32 10 | 24C64 cc -o main main.c at24c.c -DC64 11 | 24C128 cc -o main main.c at24c.c -DC128 12 | 24C256 cc -o main main.c at24c.c -DC256 13 | 24C512 cc -o main main.c at24c.c -DC512 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "at24c.h" 27 | 28 | void dump(char * title, uint8_t *dt, uint32_t n) { 29 | uint16_t clm = 0; 30 | uint8_t data; 31 | uint8_t sum; 32 | uint8_t vsum[16]; 33 | uint8_t total =0; 34 | uint32_t saddr =0; 35 | uint32_t eaddr =n-1; 36 | 37 | printf("-------------------- [%s] --------------------\n", title); 38 | uint16_t i; 39 | for (i=0;i<16;i++) vsum[i]=0; 40 | uint32_t addr; 41 | for (addr = saddr; addr <= eaddr; addr++) { 42 | data = dt[addr]; 43 | if (clm == 0) { 44 | sum =0; 45 | printf("%05x: ",addr); 46 | } 47 | 48 | sum+=data; 49 | vsum[addr % 16]+=data; 50 | 51 | printf("%02x ",data); 52 | clm++; 53 | if (clm == 16) { 54 | printf("|%02x \n",sum); 55 | clm = 0; 56 | } 57 | } 58 | printf("-------------------- [%s] --------------------\n", title); 59 | printf(" "); 60 | for (i=0; i<16;i++) { 61 | total+=vsum[i]; 62 | printf("%02x ",vsum[i]); 63 | } 64 | printf("|%02x \n\n",total); 65 | } 66 | 67 | 68 | int main(int argc, char *argv[]) 69 | { 70 | char device[20]; 71 | struct stat st; 72 | int ret; 73 | 74 | // set device file name 75 | int adapter_nr = 0; // i2c-0 76 | snprintf(device, 19, "/dev/i2c-%d", adapter_nr); 77 | ret = stat(device, &st); 78 | printf("%s=%d\n", device,ret); 79 | if (ret != 0) { 80 | adapter_nr = 1; // i2c-1 81 | snprintf(device, 19, "/dev/i2c-%d", adapter_nr); 82 | ret = stat(device, &st); 83 | printf("%s=%d\n", device,ret); 84 | if (ret != 0) { 85 | printf("i2c device not found\n"); 86 | return 1; 87 | } 88 | } 89 | 90 | // set i2c address 91 | int i2c_addr = 0x50; 92 | if (argc == 2) i2c_addr = strtol(argv[1],NULL,16); 93 | printf("i2c address=0x%x\n",i2c_addr); 94 | 95 | // set EEPROM memory size 96 | int eeprom_bits = 0; 97 | #ifdef C02 98 | eeprom_bits = 2; 99 | #endif 100 | #ifdef C04 101 | eeprom_bits = 4; 102 | #endif 103 | #ifdef C08 104 | eeprom_bits = 8; 105 | #endif 106 | #ifdef C16 107 | eeprom_bits = 16; 108 | #endif 109 | #ifdef C32 110 | eeprom_bits = 32; 111 | #endif 112 | #ifdef C64 113 | eeprom_bits = 64; 114 | #endif 115 | #ifdef C128 116 | eeprom_bits = 128; 117 | #endif 118 | #ifdef C256 119 | eeprom_bits = 256; 120 | #endif 121 | #ifdef C512 122 | eeprom_bits = 512; 123 | #endif 124 | printf("eeprom_bits=%d\n",eeprom_bits); 125 | if (eeprom_bits == 0) { 126 | printf("EEPROM model not found\n"); 127 | return 1; 128 | } 129 | 130 | // open device 131 | int write_cycle_time = 2; 132 | //int write_cycle_time = 1; 133 | struct eeprom e; 134 | ret = eeprom_open(device, i2c_addr, eeprom_bits, write_cycle_time, &e); 135 | //printf("eeprom_open ret=%d\n",ret); 136 | if (ret != 0) { 137 | printf("eeprom_open ret=%d\n",ret); 138 | return 1; 139 | } 140 | 141 | 142 | // get EEPROM size(byte) 143 | uint32_t eeprom_bytes = getEEPROMbytes(&e); 144 | printf("EEPROM chip=24C%.02d bytes=%dByte\n",eeprom_bits,eeprom_bytes); 145 | 146 | uint16_t mem_addr; 147 | uint8_t data; 148 | uint8_t rdata[256]; 149 | int i; 150 | 151 | // write first blcok 152 | for(i=0;i<256;i++) { 153 | mem_addr = i; 154 | data = i; 155 | ret = eeprom_write_byte(&e, mem_addr, data); 156 | if (ret != 0) printf("eeprom_write_byte ret=%d\n",ret); 157 | } 158 | 159 | // write last blcok 160 | for(i=0;i<256;i++) { 161 | mem_addr = i + (eeprom_bytes - 0x100); 162 | data = 255 - i; 163 | ret = eeprom_write_byte(&e, mem_addr, data); 164 | if (ret != 0) printf("eeprom_write_byte ret=%d\n",ret); 165 | } 166 | 167 | char title[64]; 168 | sprintf(title,"address %d-%d",eeprom_bytes-0x100,eeprom_bytes-1); 169 | 170 | // read last blcok 171 | memset(rdata, 0, sizeof(rdata)); 172 | for(i=0;i<256;i++) { 173 | mem_addr = i + (eeprom_bytes - 0x100); 174 | rdata[i] = eeprom_read_byte(&e, mem_addr); 175 | //ret = eeprom_24c32_read_byte(&e, mem_addr); 176 | if (ret != 0) printf("eeprom_read_byte ret=%d\n",ret); 177 | } 178 | dump(title, rdata, 256); 179 | 180 | // read first blcok 181 | memset(rdata, 0, sizeof(rdata)); 182 | for(i=0;i<256;i++) { 183 | mem_addr = i; 184 | rdata[i] = eeprom_read_byte(&e, mem_addr); 185 | //ret = eeprom_24c32_read_byte(&e, mem_addr); 186 | if (ret != 0) printf("eeprom_read_byte ret=%d\n",ret); 187 | } 188 | dump("address 0-255", rdata, 256); 189 | 190 | eeprom_close(&e); 191 | 192 | } 193 | 194 | -------------------------------------------------------------------------------- /at24c.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | ***************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "at24c.h" 20 | 21 | static int i2c_write_1b(struct eeprom *e, __s8 i2c_addr, __u8 buf) 22 | { 23 | // set working device 24 | int r; 25 | if( ( r = ioctl(e->fd, I2C_SLAVE, i2c_addr)) < 0) 26 | { 27 | fprintf(stderr, "Error i2c_write_1b: %s\n", strerror(errno)); 28 | return r; 29 | } 30 | 31 | // we must simulate a plain I2C byte write with SMBus functions 32 | r = i2c_smbus_write_byte(e->fd, buf); 33 | if(r < 0) 34 | fprintf(stderr, "Error i2c_write_1b: %s\n", strerror(errno)); 35 | usleep(10); 36 | return r; 37 | } 38 | 39 | static int i2c_write_2b(struct eeprom *e, __s8 i2c_addr, __u8 buf[2]) 40 | { 41 | // set working device 42 | int r; 43 | if( ( r = ioctl(e->fd, I2C_SLAVE, i2c_addr)) < 0) 44 | { 45 | fprintf(stderr, "ioctl r=%d\n", r); 46 | fprintf(stderr, "Error i2c_write_2b: %s\n", strerror(errno)); 47 | return r; 48 | } 49 | 50 | // we must simulate a plain I2C byte write with SMBus functions 51 | r = i2c_smbus_write_byte_data(e->fd, buf[0], buf[1]); 52 | if(r < 0) { 53 | fprintf(stderr, "i2c_smbus_write_word_data r=%d\n", r); 54 | fprintf(stderr, "Error i2c_write_2b: %s\n", strerror(errno)); 55 | } 56 | usleep(10); 57 | return r; 58 | } 59 | 60 | static int i2c_write_3b(struct eeprom *e, __s8 i2c_addr, __u8 buf[3]) 61 | { 62 | // set working device 63 | int r; 64 | if( ( r = ioctl(e->fd, I2C_SLAVE, i2c_addr)) < 0) 65 | { 66 | fprintf(stderr, "ioctl r=%d\n", r); 67 | fprintf(stderr, "Error i2c_write_3b: %s\n", strerror(errno)); 68 | return r; 69 | } 70 | 71 | // we must simulate a plain I2C byte write with SMBus functions 72 | // the __u16 data field will be byte swapped by the SMBus protocol 73 | r = i2c_smbus_write_word_data(e->fd, buf[0], buf[2] << 8 | buf[1]); 74 | if(r < 0) { 75 | fprintf(stderr, "i2c_smbus_write_word_data r=%d\n", r); 76 | fprintf(stderr, "Error i2c_write_3b: %s\n", strerror(errno)); 77 | } 78 | usleep(10); 79 | return r; 80 | } 81 | 82 | 83 | #define CHECK_I2C_FUNC( var, label ) \ 84 | do { if(0 == (var & label)) { \ 85 | fprintf(stderr, "\nError: " \ 86 | #label " function is required. Program halted.\n\n"); \ 87 | exit(1); } \ 88 | } while(0); 89 | 90 | int eeprom_open(char *dev_fqn, int i2c_addr, int bits, int write_cycle_time, struct eeprom* e) 91 | { 92 | int funcs, fd, r; 93 | e->fd = e->i2c_addr = 0; 94 | e->dev = 0; 95 | 96 | fd = open(dev_fqn, O_RDWR); 97 | if(fd <= 0) 98 | { 99 | fprintf(stderr, "Error eeprom_open: %s\n", strerror(errno)); 100 | return -1; 101 | } 102 | 103 | // get funcs list 104 | if((r = ioctl(fd, I2C_FUNCS, &funcs) < 0)) 105 | { 106 | fprintf(stderr, "Error eeprom_open: %s\n", strerror(errno)); 107 | return -1; 108 | } 109 | 110 | 111 | // check for req funcs 112 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE ); 113 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE ); 114 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE_DATA ); 115 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE_DATA ); 116 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_WORD_DATA ); 117 | CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_WORD_DATA ); 118 | 119 | #if 0 120 | // set working device 121 | if( ( r = ioctl(fd, I2C_SLAVE, i2c_addr)) < 0) 122 | { 123 | fprintf(stderr, "Error eeprom_open: %s\n", strerror(errno)); 124 | return -1; 125 | } 126 | #endif 127 | e->fd = fd; 128 | e->i2c_addr = i2c_addr; 129 | e->dev = dev_fqn; 130 | e->bits = bits; 131 | e->type = EEPROM_TYPE_8BIT_ADDR; 132 | if (bits > 16) e->type = EEPROM_TYPE_16BIT_ADDR; 133 | e->bytes = (__u32)128 * (__u32)bits; 134 | e->write_cycle_time = write_cycle_time; 135 | //printf("bits=%d bytes=%d type=%d\n",e->bits, e->bytes, e->type); 136 | return 0; 137 | } 138 | 139 | int eeprom_close(struct eeprom *e) 140 | { 141 | close(e->fd); 142 | e->fd = -1; 143 | e->dev = 0; 144 | e->type = EEPROM_TYPE_UNKNOWN; 145 | return 0; 146 | } 147 | 148 | __u32 getEEPROMbytes(struct eeprom* e) 149 | { 150 | return(e->bytes); 151 | } 152 | 153 | int eeprom_read_current_byte(struct eeprom* e) 154 | { 155 | ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer 156 | return i2c_smbus_read_byte(e->fd); 157 | } 158 | 159 | int eeprom_read_byte(struct eeprom* e, __u16 mem_addr) 160 | { 161 | if (mem_addr >= e->bytes) { 162 | fprintf(stderr, "Your EEPROM is %d bytes\n", e->bytes); 163 | fprintf(stderr, "The address (%d) exceeds this.\n", mem_addr); 164 | return -1; 165 | } 166 | 167 | int r; 168 | ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer 169 | if(e->type == EEPROM_TYPE_8BIT_ADDR) 170 | { 171 | __u8 blockNumber = mem_addr / 256; 172 | __u8 _mem_addr = mem_addr - (blockNumber * 256); 173 | __s8 i2c_addr = e->i2c_addr + blockNumber; 174 | __u8 buf = _mem_addr; 175 | //printf("read_byte mem_addr=%x i2c_addr=%x _mem_addr=%x\n",mem_addr, i2c_addr, _mem_addr); 176 | r = i2c_write_1b(e, i2c_addr, buf); 177 | } else if(e->type == EEPROM_TYPE_16BIT_ADDR) { 178 | __s8 i2c_addr = e->i2c_addr; 179 | __u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff }; 180 | r = i2c_write_2b(e, i2c_addr, buf); 181 | } else { 182 | fprintf(stderr, "ERR: unknown eeprom type\n"); 183 | return -1; 184 | } 185 | if (r < 0) 186 | return r; 187 | r = i2c_smbus_read_byte(e->fd); 188 | return r; 189 | } 190 | 191 | int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data) 192 | { 193 | if (mem_addr >= e->bytes) { 194 | fprintf(stderr, "Your EEPROM is %d bytes\n", e->bytes); 195 | fprintf(stderr, "The address (%d) exceeds this.\n", mem_addr); 196 | return -1; 197 | } 198 | 199 | int ret; 200 | if(e->type == EEPROM_TYPE_8BIT_ADDR) { 201 | __u8 blockNumber = mem_addr / 256; 202 | __u8 _mem_addr = mem_addr - (blockNumber * 256); 203 | __s8 i2c_addr = e->i2c_addr + blockNumber; 204 | //__u8 buf[2] = { mem_addr & 0x00ff, data }; 205 | __u8 buf[2] = { _mem_addr, data }; 206 | //printf("write_byte mem_addr=%x i2c_addr=%x _mem_addr=%x\n",mem_addr, i2c_addr, _mem_addr); 207 | ret = i2c_write_2b(e, i2c_addr, buf); 208 | if (ret == 0 && e->write_cycle_time != 0) { 209 | usleep(1000 * e->write_cycle_time); 210 | } 211 | return ret; 212 | } else if(e->type == EEPROM_TYPE_16BIT_ADDR) { 213 | __s8 i2c_addr = e->i2c_addr; 214 | __u8 buf[3] = 215 | { (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data }; 216 | ret = i2c_write_3b(e, i2c_addr, buf); 217 | if (ret == 0 && e->write_cycle_time != 0) { 218 | usleep(1000 * e->write_cycle_time); 219 | } 220 | return ret; 221 | } 222 | fprintf(stderr, "ERR: unknown eeprom type\n"); 223 | return -1; 224 | } 225 | 226 | -------------------------------------------------------------------------------- /i2c-dev.h: -------------------------------------------------------------------------------- 1 | /* 2 | i2c-dev.h - i2c-bus driver, char device interface 3 | 4 | Copyright (C) 1995-97 Simon G. Vogl 5 | Copyright (C) 1998-99 Frodo Looijaard 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* $Id: i2c-dev.h,v 1.4 2003/11/27 23:08:06 tat Exp $ */ 23 | 24 | #ifndef LIB_I2CDEV_H 25 | #define LIB_I2CDEV_H 26 | 27 | #include 28 | #include 29 | 30 | 31 | /* -- i2c.h -- */ 32 | 33 | 34 | /* 35 | * I2C Message - used for pure i2c transaction, also from /dev interface 36 | */ 37 | struct i2c_msg { 38 | __u16 addr; /* slave address */ 39 | unsigned short flags; 40 | #define I2C_M_TEN 0x10 /* we have a ten bit chip address */ 41 | #define I2C_M_RD 0x01 42 | #define I2C_M_NOSTART 0x4000 43 | #define I2C_M_REV_DIR_ADDR 0x2000 44 | #define I2C_M_IGNORE_NAK 0x1000 45 | #define I2C_M_NO_RD_ACK 0x0800 46 | short len; /* msg length */ 47 | char *buf; /* pointer to msg data */ 48 | int err; 49 | short done; 50 | }; 51 | 52 | /* To determine what functionality is present */ 53 | 54 | #define I2C_FUNC_I2C 0x00000001 55 | #define I2C_FUNC_10BIT_ADDR 0x00000002 56 | #define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ 57 | #define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ 58 | #define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ 59 | #define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ 60 | #define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ 61 | #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ 62 | #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ 63 | #define I2C_FUNC_SMBUS_QUICK 0x00010000 64 | #define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 65 | #define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 66 | #define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 67 | #define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 68 | #define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 69 | #define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 70 | #define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 71 | #define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 72 | #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 73 | #define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ 74 | #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ 75 | #define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ 76 | #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ 77 | #define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ 78 | #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ 79 | 80 | #define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ 81 | I2C_FUNC_SMBUS_WRITE_BYTE 82 | #define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ 83 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA 84 | #define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ 85 | I2C_FUNC_SMBUS_WRITE_WORD_DATA 86 | #define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ 87 | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 88 | #define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ 89 | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 90 | #define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \ 91 | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 92 | #define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \ 93 | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 94 | #define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \ 95 | I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 96 | 97 | #define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA 98 | #define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA 99 | #define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA 100 | #define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA 101 | #define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA 102 | #define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA 103 | 104 | #define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ 105 | I2C_FUNC_SMBUS_BYTE | \ 106 | I2C_FUNC_SMBUS_BYTE_DATA | \ 107 | I2C_FUNC_SMBUS_WORD_DATA | \ 108 | I2C_FUNC_SMBUS_PROC_CALL | \ 109 | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ 110 | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ 111 | I2C_FUNC_SMBUS_I2C_BLOCK 112 | 113 | /* 114 | * Data for SMBus Messages 115 | */ 116 | #define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ 117 | #define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ 118 | union i2c_smbus_data { 119 | __u8 byte; 120 | __u16 word; 121 | __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */ 122 | /* one more for read length in block process call */ 123 | /* and one more for PEC */ 124 | }; 125 | 126 | /* smbus_access read or write markers */ 127 | #define I2C_SMBUS_READ 1 128 | #define I2C_SMBUS_WRITE 0 129 | 130 | /* SMBus transaction types (size parameter in the above functions) 131 | Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ 132 | #define I2C_SMBUS_QUICK 0 133 | #define I2C_SMBUS_BYTE 1 134 | #define I2C_SMBUS_BYTE_DATA 2 135 | #define I2C_SMBUS_WORD_DATA 3 136 | #define I2C_SMBUS_PROC_CALL 4 137 | #define I2C_SMBUS_BLOCK_DATA 5 138 | #define I2C_SMBUS_I2C_BLOCK_DATA 6 139 | #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ 140 | #define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */ 141 | #define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */ 142 | #define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */ 143 | #define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */ 144 | 145 | 146 | /* ----- commands for the ioctl like i2c_command call: 147 | * note that additional calls are defined in the algorithm and hw 148 | * dependent layers - these can be listed here, or see the 149 | * corresponding header files. 150 | */ 151 | /* -> bit-adapter specific ioctls */ 152 | #define I2C_RETRIES 0x0701 /* number of times a device address */ 153 | /* should be polled when not */ 154 | /* acknowledging */ 155 | #define I2C_TIMEOUT 0x0702 /* set timeout - call with int */ 156 | 157 | 158 | /* this is for i2c-dev.c */ 159 | #define I2C_SLAVE 0x0703 /* Change slave address */ 160 | /* Attn.: Slave address is 7 or 10 bits */ 161 | #define I2C_SLAVE_FORCE 0x0706 /* Change slave address */ 162 | /* Attn.: Slave address is 7 or 10 bits */ 163 | /* This changes the address, even if it */ 164 | /* is already taken! */ 165 | #define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ 166 | 167 | #define I2C_FUNCS 0x0705 /* Get the adapter functionality */ 168 | #define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ 169 | #define I2C_PEC 0x0708 /* != 0 for SMBus PEC */ 170 | #if 0 171 | #define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */ 172 | #endif 173 | 174 | #define I2C_SMBUS 0x0720 /* SMBus-level access */ 175 | 176 | /* -- i2c.h -- */ 177 | 178 | 179 | /* Note: 10-bit addresses are NOT supported! */ 180 | 181 | /* This is the structure as used in the I2C_SMBUS ioctl call */ 182 | struct i2c_smbus_ioctl_data { 183 | char read_write; 184 | __u8 command; 185 | int size; 186 | union i2c_smbus_data *data; 187 | }; 188 | 189 | /* This is the structure as used in the I2C_RDWR ioctl call */ 190 | struct i2c_rdwr_ioctl_data { 191 | struct i2c_msg *msgs; /* pointers to i2c_msgs */ 192 | int nmsgs; /* number of i2c_msgs */ 193 | }; 194 | 195 | 196 | static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, 197 | int size, union i2c_smbus_data *data) 198 | { 199 | struct i2c_smbus_ioctl_data args; 200 | 201 | args.read_write = read_write; 202 | args.command = command; 203 | args.size = size; 204 | args.data = data; 205 | return ioctl(file,I2C_SMBUS,&args); 206 | } 207 | 208 | 209 | static inline __s32 i2c_smbus_write_quick(int file, __u8 value) 210 | { 211 | return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); 212 | } 213 | 214 | static inline __s32 i2c_smbus_read_byte(int file) 215 | { 216 | union i2c_smbus_data data; 217 | if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) 218 | return -1; 219 | else 220 | return 0x0FF & data.byte; 221 | } 222 | 223 | static inline __s32 i2c_smbus_write_byte(int file, __u8 value) 224 | { 225 | return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, 226 | I2C_SMBUS_BYTE,NULL); 227 | } 228 | 229 | static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) 230 | { 231 | union i2c_smbus_data data; 232 | if (i2c_smbus_access(file,I2C_SMBUS_READ,command, 233 | I2C_SMBUS_BYTE_DATA,&data)) 234 | return -1; 235 | else 236 | return 0x0FF & data.byte; 237 | } 238 | 239 | static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, 240 | __u8 value) 241 | { 242 | union i2c_smbus_data data; 243 | data.byte = value; 244 | return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 245 | I2C_SMBUS_BYTE_DATA, &data); 246 | } 247 | 248 | static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) 249 | { 250 | union i2c_smbus_data data; 251 | if (i2c_smbus_access(file,I2C_SMBUS_READ,command, 252 | I2C_SMBUS_WORD_DATA,&data)) 253 | return -1; 254 | else 255 | return 0x0FFFF & data.word; 256 | } 257 | 258 | static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, 259 | __u16 value) 260 | { 261 | union i2c_smbus_data data; 262 | data.word = value; 263 | return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 264 | I2C_SMBUS_WORD_DATA, &data); 265 | } 266 | 267 | static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) 268 | { 269 | union i2c_smbus_data data; 270 | data.word = value; 271 | if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 272 | I2C_SMBUS_PROC_CALL,&data)) 273 | return -1; 274 | else 275 | return 0x0FFFF & data.word; 276 | } 277 | 278 | 279 | /* Returns the number of read bytes */ 280 | static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, 281 | __u8 *values) 282 | { 283 | union i2c_smbus_data data; 284 | int i; 285 | if (i2c_smbus_access(file,I2C_SMBUS_READ,command, 286 | I2C_SMBUS_BLOCK_DATA,&data)) 287 | return -1; 288 | else { 289 | for (i = 1; i <= data.block[0]; i++) 290 | values[i-1] = data.block[i]; 291 | return data.block[0]; 292 | } 293 | } 294 | 295 | static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, 296 | __u8 length, __u8 *values) 297 | { 298 | union i2c_smbus_data data; 299 | int i; 300 | if (length > 32) 301 | length = 32; 302 | for (i = 1; i <= length; i++) 303 | data.block[i] = values[i-1]; 304 | data.block[0] = length; 305 | return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 306 | I2C_SMBUS_BLOCK_DATA, &data); 307 | } 308 | 309 | /* Returns the number of read bytes */ 310 | static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, 311 | __u8 *values) 312 | { 313 | union i2c_smbus_data data; 314 | int i; 315 | if (i2c_smbus_access(file,I2C_SMBUS_READ,command, 316 | I2C_SMBUS_I2C_BLOCK_DATA,&data)) 317 | return -1; 318 | else { 319 | for (i = 1; i <= data.block[0]; i++) 320 | values[i-1] = data.block[i]; 321 | return data.block[0]; 322 | } 323 | } 324 | 325 | static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, 326 | __u8 length, __u8 *values) 327 | { 328 | union i2c_smbus_data data; 329 | int i; 330 | if (length > 32) 331 | length = 32; 332 | for (i = 1; i <= length; i++) 333 | data.block[i] = values[i-1]; 334 | data.block[0] = length; 335 | return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 336 | I2C_SMBUS_I2C_BLOCK_DATA, &data); 337 | } 338 | 339 | /* Returns the number of read bytes */ 340 | static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, 341 | __u8 length, __u8 *values) 342 | { 343 | union i2c_smbus_data data; 344 | int i; 345 | if (length > 32) 346 | length = 32; 347 | for (i = 1; i <= length; i++) 348 | data.block[i] = values[i-1]; 349 | data.block[0] = length; 350 | if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, 351 | I2C_SMBUS_BLOCK_PROC_CALL,&data)) 352 | return -1; 353 | else { 354 | for (i = 1; i <= data.block[0]; i++) 355 | values[i-1] = data.block[i]; 356 | return data.block[0]; 357 | } 358 | } 359 | 360 | 361 | #endif /* LIB_I2CDEV_H */ 362 | --------------------------------------------------------------------------------