1 #include <minix/i2c.h> 2 #include <minix/com.h> 3 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 7 #include <ctype.h> 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include "eepromread.h" 16 17 static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, 18 void *buf, size_t buflen, int flags, enum device_types device_type); 19 static int eeprom_dump(int fd, i2c_addr_t addr, int flags, 20 enum device_types device_type); 21 22 #define DEFAULT_I2C_DEVICE "/dev/i2c-1" 23 #define DEFAULT_I2C_ADDRESS 0x50 24 25 /* 26 * The /dev interface only supports 128 byte reads/writes and the EEPROM is 27 * larger, so to read the whole EEPROM, the task is broken down into 128 byte 28 * chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do 29 * the read. 30 */ 31 32 static int 33 __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, 34 size_t buflen, int flags, enum device_types device_type) 35 { 36 int r; 37 minix_i2c_ioctl_exec_t ioctl_exec; 38 39 if (buflen > I2C_EXEC_MAX_BUFLEN || buf == NULL 40 || ((memaddr + buflen) < memaddr)) { 41 errno = EINVAL; 42 return -1; 43 } 44 45 /* if /dev/eeprom, then use read() */ 46 if (device_type == EEPROM_DEVICE) { 47 48 off_t offset; 49 50 offset = lseek(fd, memaddr, SEEK_SET); 51 if (offset != memaddr) { 52 return -1; 53 } 54 55 return read(fd, buf, buflen); 56 57 } 58 /* else /dev/i2c, use i2c_ioctl_exec_t interface */ 59 memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); 60 61 ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; 62 ioctl_exec.iie_addr = addr; 63 64 /* set the address to read from */ 65 if ((BDEV_NOPAGE & flags) == BDEV_NOPAGE) { 66 /* reading within the current page */ 67 ioctl_exec.iie_cmd[0] = (memaddr & 0xff); 68 ioctl_exec.iie_cmdlen = 1; 69 } else { 70 /* reading from device with multiple pages */ 71 ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff); 72 ioctl_exec.iie_cmd[1] = (memaddr & 0xff); 73 ioctl_exec.iie_cmdlen = 2; 74 } 75 ioctl_exec.iie_buflen = buflen; 76 77 r = ioctl(fd, MINIX_I2C_IOCTL_EXEC, &ioctl_exec); 78 if (r == -1) { 79 return -1; 80 } 81 82 /* call was good, copy results to caller's buffer */ 83 memcpy(buf, ioctl_exec.iie_buf, buflen); 84 85 return 0; 86 } 87 88 int 89 eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, 90 size_t buflen, int flags, enum device_types device_type) 91 { 92 int r; 93 uint16_t i; 94 95 if (buf == NULL || ((memaddr + buflen) < memaddr)) { 96 errno = EINVAL; 97 return -1; 98 } 99 100 for (i = 0; i < buflen; i += 128) { 101 102 r = __eeprom_read128(fd, addr, memaddr + i, buf + i, 103 ((buflen - i) < 128) ? (buflen - i) : 128, flags, 104 device_type); 105 if (r == -1) { 106 return -1; 107 } 108 } 109 110 return 0; 111 } 112 113 /* 114 * Read 256 bytes and print it to the screen in HEX and ASCII. 115 */ 116 static int 117 eeprom_dump(int fd, i2c_addr_t addr, int flags, enum device_types device_type) 118 { 119 int i, j, r; 120 uint8_t buf[256]; 121 122 memset(buf, '\0', 256); 123 124 r = eeprom_read(fd, addr, 0x0000, buf, 256, flags, device_type); 125 if (r == -1) { 126 return r; 127 } 128 129 /* print table header */ 130 for (i = 0; i < 2; i++) { 131 printf(" "); 132 for (j = 0x0; j <= 0xf; j++) { 133 if (i == 0) { 134 printf(" "); 135 } 136 printf("%x", j); 137 } 138 } 139 printf("\n"); 140 141 /* print table data */ 142 for (i = 0x00; i < 0xff; i += 0x10) { 143 144 /* row label */ 145 printf("%02x:", i); 146 147 /* row data (in hex) */ 148 for (j = 0x0; j <= 0xf; j++) { 149 printf(" %02x", buf[i + j]); 150 } 151 152 printf(" "); 153 154 /* row data (in ASCII) */ 155 for (j = 0x0; j <= 0xf; j++) { 156 if (isprint(buf[i + j])) { 157 printf("%c", buf[i + j]); 158 } else { 159 printf("."); 160 } 161 } 162 163 printf("\n"); 164 } 165 166 return 0; 167 } 168 169 int 170 main(int argc, char *argv[]) 171 { 172 int r, fd; 173 int ch, iflag = 0, read_flags = 0; 174 char *device = DEFAULT_I2C_DEVICE; 175 i2c_addr_t address = DEFAULT_I2C_ADDRESS; 176 enum device_types device_type = DEFAULT_DEVICE; 177 178 setprogname(*argv); 179 180 while ((ch = getopt(argc, argv, "a:f:in")) != -1) { 181 switch (ch) { 182 case 'a': 183 address = strtol(optarg, NULL, 0x10); 184 break; 185 case 'f': 186 device = optarg; 187 break; 188 case 'i': 189 iflag = 1; 190 break; 191 case 'n': 192 read_flags |= BDEV_NOPAGE; 193 break; 194 default: 195 break; 196 } 197 } 198 199 /* determine whether to use /dev/i2c or /dev/eeprom interface */ 200 device_type = 201 strstr(device, "i2c") == NULL ? EEPROM_DEVICE : I2C_DEVICE; 202 203 fd = open(device, O_RDWR); 204 if (fd == -1) { 205 fprintf(stderr, "open(): %s\n", strerror(errno)); 206 return 1; 207 } 208 209 if (iflag == 1) { 210 r = board_info(fd, address, read_flags, device_type); 211 if (r == -1) { 212 fprintf(stderr, "board_info(): %s\n", strerror(errno)); 213 return 1; 214 } 215 } else { 216 r = eeprom_dump(fd, address, read_flags, device_type); 217 if (r == -1) { 218 fprintf(stderr, "eeprom_dump(): %s\n", 219 strerror(errno)); 220 return 1; 221 } 222 } 223 224 r = close(fd); 225 if (r == -1) { 226 fprintf(stderr, "close(): %s\n", strerror(errno)); 227 return 1; 228 } 229 230 return 0; 231 } 232