| | 49 | int open_i2c_dev(const int i2cbus, char *filename) |
| | 50 | { |
| | 51 | int file; |
| | 52 | |
| | 53 | sprintf(filename, "/dev/i2c-%d", i2cbus); |
| | 54 | file = open(filename, O_RDWR); |
| | 55 | |
| | 56 | if (file >= 0 || errno != ENOENT) { |
| | 57 | return file; |
| | 58 | } |
| | 59 | |
| | 60 | sprintf(filename, "/dev/i2c/%d", i2cbus); |
| | 61 | file = open(filename, O_RDWR); |
| | 62 | |
| | 63 | return file; |
| | 64 | } |
| | 65 | |
| | 66 | int scan_i2c_bus(int file, const int mode, const int first, const int last) |
| | 67 | { |
| | 68 | int i, j; |
| | 69 | int res; |
| | 70 | |
| | 71 | printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); |
| | 72 | |
| | 73 | for (i = 0; i < 128; i += 16) { |
| | 74 | printf("%02x: ", i); |
| | 75 | for(j = 0; j < 16; j++) { |
| | 76 | /* Skip unwanted addresses */ |
| | 77 | if (i+j < first || i+j > last) { |
| | 78 | printf(" "); |
| | 79 | continue; |
| | 80 | } |
| | 81 | |
| | 82 | /* Set slave address */ |
| | 83 | if (ioctl(file, I2C_SLAVE, i+j) < 0) { |
| | 84 | if (errno == EBUSY) { |
| | 85 | printf("UU "); |
| | 86 | continue; |
| | 87 | } else { |
| | 88 | fprintf(stderr, |
| | 89 | "Error: Could not set address to 0x%02x: %s\n", |
| | 90 | i+j, strerror(errno)); |
| | 91 | return -1; |
| | 92 | } |
| | 93 | } |
| | 94 | |
| | 95 | /* Probe this address */ |
| | 96 | switch (mode) { |
| | 97 | case MODE_QUICK: |
| | 98 | /* This is known to corrupt the Atmel AT24RF08 EEPROM */ |
| | 99 | res = i2c_smbus_write_quick(file, I2C_SMBUS_WRITE); |
| | 100 | break; |
| | 101 | case MODE_READ: |
| | 102 | /* This is known to lock SMBus on various write-only chips |
| | 103 | (mainly clock chips) */ |
| | 104 | res = i2c_smbus_read_byte(file); |
| | 105 | break; |
| | 106 | default: |
| | 107 | if ((i+j >= 0x30 && i+j <= 0x37) |
| | 108 | || (i+j >= 0x50 && i+j <= 0x5F)) |
| | 109 | res = i2c_smbus_write_quick(file, I2C_SMBUS_WRITE); |
| | 110 | else |
| | 111 | res = i2c_smbus_read_byte(file); |
| | 112 | } |
| | 113 | |
| | 114 | if (res < 0) |
| | 115 | printf("XX "); |
| | 116 | else |
| | 117 | printf("%02x ", i+j); |
| | 118 | } |
| | 119 | printf("\n"); |
| | 120 | } |
| | 121 | |
| | 122 | return 0; |
| | 123 | } |
| | 124 | |
| 112 | | /* |
| 113 | | * Try all three variants and give the correct error message |
| 114 | | * upon failure |
| 115 | | */ |
| 116 | | |
| 117 | | sprintf(filename1,"/dev/i2c-%d",i2cbus); |
| 118 | | sprintf(filename2,"/dev/i2c%d",i2cbus); |
| 119 | | sprintf(filename3,"/dev/i2c/%d",i2cbus); |
| 120 | | if ((file = open(filename1,O_RDWR)) < 0) { |
| 121 | | e1 = errno; |
| 122 | | if ((file = open(filename2,O_RDWR)) < 0) { |
| 123 | | e2 = errno; |
| 124 | | if ((file = open(filename3,O_RDWR)) < 0) { |
| 125 | | e3 = errno; |
| 126 | | if(e1 == ENOENT && e2 == ENOENT && e3 == ENOENT) { |
| 127 | | fprintf(stderr,"Error: Could not open file `%s', `%s', or `%s': %s\n", |
| 128 | | filename1,filename2,filename3,strerror(ENOENT)); |
| 129 | | } |
| 130 | | if (e1 != ENOENT) { |
| 131 | | fprintf(stderr,"Error: Could not open file `%s' : %s\n", |
| 132 | | filename1,strerror(e1)); |
| 133 | | if(e1 == EACCES) |
| 134 | | fprintf(stderr,"Run as root?\n"); |
| 135 | | } |
| 136 | | if (e2 != ENOENT) { |
| 137 | | fprintf(stderr,"Error: Could not open file `%s' : %s\n", |
| 138 | | filename2,strerror(e2)); |
| 139 | | if(e2 == EACCES) |
| 140 | | fprintf(stderr,"Run as root?\n"); |
| 141 | | } |
| 142 | | if (e3 != ENOENT) { |
| 143 | | fprintf(stderr,"Error: Could not open file `%s' : %s\n", |
| 144 | | filename3,strerror(e3)); |
| 145 | | if(e3 == EACCES) |
| 146 | | fprintf(stderr,"Run as root?\n"); |
| 147 | | } |
| 148 | | exit(1); |
| 149 | | } else { |
| 150 | | filename = filename3; |
| 151 | | } |
| | 185 | |
| | 186 | file = open_i2c_dev(i2cbus, filename); |
| | 187 | if (file < 0) { |
| | 188 | if (errno == ENOENT) { |
| | 189 | fprintf(stderr, "Error: Could not open file `/dev/i2c-%d' or `/dev/i2c/%d': %s\n", |
| | 190 | i2cbus, i2cbus, strerror(ENOENT)); |
| 189 | | printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); |
| 190 | | for (i = 0; i < 128; i+=16) { |
| 191 | | printf("%02x: ",i); |
| 192 | | for(j = 0; j < 16; j++) { |
| 193 | | if (!force && (i+j<0x03 || i+j>0x77)) { |
| 194 | | printf(" "); |
| 195 | | continue; |
| 196 | | } |
| 197 | | if (ioctl(file,I2C_SLAVE,i+j) < 0) { |
| 198 | | if (errno == EBUSY) { |
| 199 | | printf("UU "); |
| 200 | | continue; |
| 201 | | } else { |
| 202 | | fprintf(stderr,"Error: Could not set address to %02x: %s\n",i+j, |
| 203 | | strerror(errno)); |
| 204 | | close(file); |
| 205 | | exit(1); |
| 206 | | } |
| 207 | | } |
| 208 | | |
| 209 | | switch(mode) { |
| 210 | | case MODE_QUICK: |
| 211 | | /* This is known to corrupt the Atmel AT24RF08 EEPROM */ |
| 212 | | res = i2c_smbus_write_quick(file, I2C_SMBUS_WRITE); |
| 213 | | break; |
| 214 | | case MODE_READ: |
| 215 | | /* This is known to lock SMBus on various write-only chips |
| 216 | | (mainly clock chips) */ |
| 217 | | res = i2c_smbus_read_byte(file); |
| 218 | | break; |
| 219 | | default: |
| 220 | | if((i+j>=0x30 && i+j<=0x37) |
| 221 | | || (i+j>=0x50 && i+j<=0x5F)) { |
| 222 | | res = i2c_smbus_write_quick(file, I2C_SMBUS_WRITE); |
| 223 | | } else { |
| 224 | | res = i2c_smbus_read_byte(file); |
| 225 | | } |
| 226 | | } |
| 227 | | |
| 228 | | if (res < 0) |
| 229 | | printf("XX "); |
| 230 | | else |
| 231 | | printf("%02x ",i+j); |
| 232 | | } |
| 233 | | printf("\n"); |
| 234 | | } |
| | 230 | if (force) |
| | 231 | res = scan_i2c_bus(file, mode, 0x00, 0x7F); |
| | 232 | else |
| | 233 | res = scan_i2c_bus(file, mode, 0x03, 0x77); |
| | 234 | |