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

Revision 4583, 8.3 kB (checked in by khali, 1 year ago)

Fix single & instead of && in logical test in eepromer (Fedora patch).

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