root/i2c-tools/trunk/eepromer/eeprom.c

Revision 6048, 8.3 KB (checked in by khali, 3 weeks ago)

i2c-dev: Move SMBus helper functions to include/i2c/smbus.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2This program is hereby placed into the public domain.
3Of course the program is provided without warranty of any kind.
4*/
5#include <sys/ioctl.h>
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <string.h>
12#include <time.h>
13#include <linux/i2c.h>
14#include <linux/i2c-dev.h>
15
16/*
17  this program can read 24C16 (and probably smaller ones, too)
18  I wrote it as a quick and dirty hack because my satellite receiver
19  hung again... so I had to reprogram the eeprom where is stores it's
20  settings.
21 */
22
23#define DEFAULT_I2C_BUS      "/dev/i2c-0"
24#define DEFAULT_EEPROM_ADDR  0x50         /* the 24C16 sits on i2c address 0x50 */
25#define DEFAULT_NUM_PAGES    8            /* we default to a 24C16 eeprom which has 8 pages */
26#define BYTES_PER_PAGE       256          /* one eeprom page is 256 byte */
27#define MAX_BYTES            8            /* max number of bytes to write in one chunk */
28       /* ... note: 24C02 and 24C01 only allow 8 bytes to be written in one chunk.   *
29        *  if you are going to write 24C04,8,16 you can change this to 16            */
30
31/* write len bytes (stored in buf) to eeprom at address addr, page-offset offset */
32/* if len=0 (buf may be NULL in this case) you can reposition the eeprom's read-pointer */
33/* return 0 on success, -1 on failure */
34int eeprom_write(int fd,
35                 unsigned int addr,
36                 unsigned int offset,
37                 unsigned char *buf,
38                 unsigned char len
39){
40        struct i2c_rdwr_ioctl_data msg_rdwr;
41        struct i2c_msg             i2cmsg;
42        int i;
43        char _buf[MAX_BYTES + 1];
44
45        if(len>MAX_BYTES){
46            fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
47            return -1;
48        }
49
50        if(len+offset >256){
51            fprintf(stderr,"Sorry, len(%d)+offset(%d) > 256 (page boundary)\n",
52                        len,offset);
53            return -1;
54        }
55
56        _buf[0]=offset;    /* _buf[0] is the offset into the eeprom page! */
57        for(i=0;i<len;i++) /* copy buf[0..n] -> _buf[1..n+1] */
58            _buf[1+i]=buf[i];
59
60        msg_rdwr.msgs = &i2cmsg;
61        msg_rdwr.nmsgs = 1;
62
63        i2cmsg.addr  = addr;
64        i2cmsg.flags = 0;
65        i2cmsg.len   = 1+len;
66        i2cmsg.buf   = _buf;
67
68        if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
69            perror("ioctl()");
70            fprintf(stderr,"ioctl returned %d\n",i);
71            return -1;
72        }
73
74        if(len>0)
75            fprintf(stderr,"Wrote %d bytes to eeprom at 0x%02x, offset %08x\n",
76                    len,addr,offset);
77        else
78            fprintf(stderr,"Positioned pointer in eeprom at 0x%02x to offset %08x\n",
79                    addr,offset);
80
81        return 0;
82}
83
84/* read len bytes stored in eeprom at address addr, offset offset in array buf */
85/* return -1 on error, 0 on success */
86int eeprom_read(int fd,
87                 unsigned int addr,
88                 unsigned int offset,
89                 unsigned char *buf,
90                 unsigned char len
91){
92        struct i2c_rdwr_ioctl_data msg_rdwr;
93        struct i2c_msg             i2cmsg;
94        int i;
95
96        if(len>MAX_BYTES){
97            fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
98            return -1;
99        }
100
101        if(eeprom_write(fd,addr,offset,NULL,0)<0)
102            return -1;
103
104        msg_rdwr.msgs = &i2cmsg;
105        msg_rdwr.nmsgs = 1;
106
107        i2cmsg.addr  = addr;
108        i2cmsg.flags = I2C_M_RD;
109        i2cmsg.len   = len;
110        i2cmsg.buf   = buf;
111
112        if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
113            perror("ioctl()");
114            fprintf(stderr,"ioctl returned %d\n",i);
115            return -1;
116        }
117
118        fprintf(stderr,"Read %d bytes from eeprom at 0x%02x, offset %08x\n",
119                len,addr,offset);
120
121        return 0;
122}
123
124
125
126int main(int argc, char **argv){
127    int i,j;
128
129    /* filedescriptor and name of device */
130    int d; 
131    char *dn=DEFAULT_I2C_BUS;
132
133    /* filedescriptor and name of data file */
134    int f=-1;
135    char *fn=NULL;
136
137    unsigned int addr=DEFAULT_EEPROM_ADDR;
138    int rwmode=0;
139    int pages=DEFAULT_NUM_PAGES;
140
141    int force=0; /* suppress warning on write! */
142   
143    while((i=getopt(argc,argv,"d:a:p:wyf:h"))>=0){
144        switch(i){
145        case 'h':
146            fprintf(stderr,"%s [-d dev] [-a adr] [-p pgs] [-w] [-y] [-f file]\n",argv[0]);
147            fprintf(stderr,"\tdev: device, e.g. /dev/i2c-0    (def)\n");
148            fprintf(stderr,"\tadr: base address of eeprom, eg 0xA0 (def)\n");
149            fprintf(stderr,"\tpgs: number of pages to read, eg 8 (def)\n");
150            fprintf(stderr,"\t-w : write to eeprom (default is reading!)\n");
151            fprintf(stderr,"\t-y : suppress warning when writing (default is to warn!)\n");
152            fprintf(stderr,"\t-f file: copy eeprom contents to/from file\n");
153            fprintf(stderr,"\t         (default for read is test only; for write is all zeros)\n");
154            fprintf(stderr,"Note on pages/addresses:\n");
155            fprintf(stderr,"\teeproms with more than 256 byte appear as if they\n");
156            fprintf(stderr,"\twere several eeproms with consecutive addresses on the bus\n");
157            fprintf(stderr,"\tso we might as well address several separate eeproms with\n");
158            fprintf(stderr,"\tincreasing addresses....\n\n");
159            exit(1);
160            break;
161        case 'd':
162            dn=optarg;
163            break;
164        case 'a':
165            if(sscanf(optarg,"0x%x",&addr)!=1){
166                fprintf(stderr,"Cannot parse '%s' as addrs., example: 0xa0\n",
167                        optarg);
168                exit(1);
169            }
170            break;
171        case 'p':
172            if(sscanf(optarg,"%d",&pages)!=1){
173                fprintf(stderr,"Cannot parse '%s' as number of pages, example: 8\n",
174                        optarg);
175                exit(1);
176            }
177            break;
178        case 'w':
179            rwmode++;
180            break;
181        case 'f':
182            fn=optarg;
183            break;
184        case 'y':
185            force++;
186            break;
187        }
188
189    }
190   
191    fprintf(stderr,"base-address of eeproms       : 0x%02x\n",addr);
192    fprintf(stderr,"number of pages to read       : %d (0x%02x .. 0x%02x)\n",
193                    pages,addr,addr+pages-1);
194
195    if(fn){
196        if(!rwmode) /* if we are reading, *WRITE* to file */
197            f=open(fn,O_WRONLY|O_CREAT,0666);
198        else /* if we are writing to eeprom, *READ* from file */
199            f=open(fn,O_RDONLY);
200        if(f<0){
201            fprintf(stderr,"Could not open data-file %s for reading or writing\n",fn);
202            perror(fn);
203            exit(1);
204        }
205        fprintf(stderr,"file opened for %7s       : %s\n",rwmode?"reading":"writing",fn);
206        fprintf(stderr,"            on filedescriptor : %d\n",f);
207    }
208
209    if((d=open(dn,O_RDWR))<0){
210        fprintf(stderr,"Could not open i2c at %s\n",dn);
211        perror(dn);
212        exit(1);
213    }
214
215    fprintf(stderr,"i2c-devicenode is             : %s\n",dn);
216    fprintf(stderr,"            on filedescriptor : %d\n\n",d);
217
218    /***
219     *** I'm not the one to blame of you screw your computer!
220     ***/
221    if(rwmode && ! force){
222        unsigned char warnbuf[4];
223        fprintf(stderr,"**WARNING**\n");
224        fprintf(stderr," - \tYou have chosen to WRITE to this eeprom.\n");
225        fprintf(stderr,"\tMake sure that this tiny chip is *NOT* vital to the\n");
226        fprintf(stderr,"\toperation of your computer as you can easily corrupt\n");
227        fprintf(stderr,"\tthe configuration memory of your SDRAM-memory-module,\n");
228        fprintf(stderr,"\tyour IBM ThinkPad or whatnot...! Fixing these errors can be\n");
229        fprintf(stderr,"\ta time-consuming and very costly process!\n\n");
230        fprintf(stderr,"Things to consider:\n");
231        fprintf(stderr," - \tYou can have more than one i2c-bus, check in /proc/bus/i2c\n");
232        fprintf(stderr,"\tand specify the correct one with -d\n");
233        fprintf(stderr,"\tright now you have chosen to use '%s'\n",dn);
234        fprintf(stderr," - \tA eeprom can occupy several i2c-addresses (one per page)\n");
235        fprintf(stderr,"\tso please make sure that there is no vital eeprom in your computer\n");
236        fprintf(stderr,"\tsitting at addresses between 0x%02x and 0x%02x\n",addr,addr+pages-1);
237
238        fprintf(stderr,"Enter 'yes' to continue:");
239        fflush(stderr);
240        if(!fgets(warnbuf,sizeof(warnbuf),stdin)){
241            fprintf(stderr,"\nCould not read confirmation from stdin!\n");
242            exit(1);
243        }
244        if(strncmp(warnbuf,"yes",3)){
245            fprintf(stderr,"\n** ABORTING WRITE! **, you did not answer 'yes'\n");
246            exit(1);
247        }
248    }
249
250    for(i=0;i<pages;i++){
251        unsigned char buf[BYTES_PER_PAGE];
252
253        if(rwmode){
254
255            if(f>=0){
256                j=read(f,buf,sizeof(buf));
257                if(j<0){
258                    fprintf(stderr,"Cannot read from file '%s'\n",fn);
259                    perror(fn);
260                    exit(1);
261                }
262                if(j!=sizeof(buf)){
263                    fprintf(stderr,"File '%s' is too small, padding eeprom with zeroes\n",fn);
264                    while(j<sizeof(buf))
265                        buf[j++]=0;
266                }
267            } else {
268                for(j=0;j<sizeof(buf);j++)
269                    buf[j]=0;
270            }
271            for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
272                if(eeprom_write(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
273                    exit(1);
274        } else {
275            for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
276                if(eeprom_read(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
277                    exit(1);
278        }
279
280
281        if(!rwmode && f>=0){
282            j=write(f,buf,sizeof(buf));
283            if(j!=sizeof(buf)){
284                fprintf(stderr,"Cannot write to file '%s'\n",fn);
285                perror(fn);
286                exit(1);
287            }
288        }
289
290    }
291
292    if(f>=0)
293        close(f);
294
295    close(d);
296
297    exit(0);
298
299}
Note: See TracBrowser for help on using the browser.