aboutsummaryrefslogtreecommitdiff
path: root/miscutils/i2c_tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/i2c_tools.c')
-rw-r--r--miscutils/i2c_tools.c210
1 files changed, 56 insertions, 154 deletions
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index 38d90ff10..d77e6bacf 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -61,112 +61,14 @@
61 61
62#include "libbb.h" 62#include "libbb.h"
63 63
64/* 64#include <linux/i2c.h>
65 * /dev/i2c-X ioctl commands. The ioctl's parameter is always an unsigned long, 65#include <linux/i2c-dev.h>
66 * except for:
67 * - I2C_FUNCS, takes pointer to an unsigned long
68 * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data
69 * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data
70 */
71
72/*
73 * NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
74 * are not supported due to code brokenness.
75 */
76 66
77/* Use this slave address. */ 67#define I2CDUMP_NUM_REGS 256
78#define I2C_SLAVE 0x0703
79/* Use this slave address, even if it is already in use by a driver. */
80#define I2C_SLAVE_FORCE 0x0706
81/* 0 for 7 bit addrs, != 0 for 10 bit. */
82#define I2C_TENBIT 0x0704
83/* Get the adapter functionality mask. */
84#define I2C_FUNCS 0x0705
85/* Combined R/W transfer (one STOP only). */
86#define I2C_RDWR 0x0707
87/* != 0 to use PEC with SMBus. */
88#define I2C_PEC 0x0708
89/* SMBus transfer. */
90#define I2C_SMBUS 0x0720
91
92/* Structure used in the I2C_SMBUS ioctl call. */
93struct i2c_smbus_ioctl_data {
94 uint8_t read_write;
95 uint8_t command;
96 uint32_t size;
97 union i2c_smbus_data *data;
98};
99
100/* Structure used in the I2C_RDWR ioctl call. */
101struct i2c_rdwr_ioctl_data {
102 struct i2c_msg *msgs; /* Pointers to i2c_msgs. */
103 uint32_t nmsgs; /* Number of i2c_msgs. */
104};
105
106/* As specified in SMBus standard. */
107#define I2C_SMBUS_BLOCK_MAX 32
108/* Not specified but we use same structure. */
109#define I2C_SMBUS_I2C_BLOCK_MAX 32
110
111/* Data for SMBus Messages. */
112union i2c_smbus_data {
113 uint8_t byte;
114 uint16_t word;
115 /* block[0] is used for length and one more for PEC */
116 uint8_t block[I2C_SMBUS_BLOCK_MAX + 2];
117};
118 68
119#define I2C_RDRW_IOCTL_MAX_MSGS 42 69#define I2CDETECT_MODE_AUTO 0
120#define I2C_MAX_REGS 256 70#define I2CDETECT_MODE_QUICK 1
121 71#define I2CDETECT_MODE_READ 2
122/* Smbus_access read or write markers. */
123#define I2C_SMBUS_READ 1
124#define I2C_SMBUS_WRITE 0
125
126/* SMBus transaction types (size parameter in the below functions). */
127#define I2C_SMBUS_QUICK 0
128#define I2C_SMBUS_BYTE 1
129#define I2C_SMBUS_BYTE_DATA 2
130#define I2C_SMBUS_WORD_DATA 3
131#define I2C_SMBUS_PROC_CALL 4
132#define I2C_SMBUS_BLOCK_DATA 5
133#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
134#define I2C_SMBUS_BLOCK_PROC_CALL 7
135#define I2C_SMBUS_I2C_BLOCK_DATA 8
136
137#define DETECT_MODE_AUTO 0
138#define DETECT_MODE_QUICK 1
139#define DETECT_MODE_READ 2
140
141/* Defines to determine what functionality is present. */
142#define I2C_FUNC_I2C 0x00000001
143#define I2C_FUNC_10BIT_ADDR 0x00000002
144#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004
145#define I2C_FUNC_SMBUS_PEC 0x00000008
146#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000
147#define I2C_FUNC_SMBUS_QUICK 0x00010000
148#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
149#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
150#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
151#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
152#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
153#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
154#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
155#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
156#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
157#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000
158#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000
159
160#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
161 I2C_FUNC_SMBUS_WRITE_BYTE)
162#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
163 I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
164#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
165 I2C_FUNC_SMBUS_WRITE_WORD_DATA)
166#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
167 I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
168#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
169 I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
170 72
171/* 73/*
172 * This is needed for ioctl_or_perror_and_die() since it only accepts pointers. 74 * This is needed for ioctl_or_perror_and_die() since it only accepts pointers.
@@ -456,7 +358,7 @@ static void check_read_funcs(int fd, int mode, int data_addr, int pec)
456 break; 358 break;
457#endif /* ENABLE_I2CDUMP */ 359#endif /* ENABLE_I2CDUMP */
458 default: 360 default:
459 bb_error_msg_and_die("Programmer goofed!"); 361 bb_error_msg_and_die("internal error");
460 } 362 }
461 check_funcs_test_end(funcs, pec, err); 363 check_funcs_test_end(funcs, pec, err);
462} 364}
@@ -799,7 +701,7 @@ int i2cset_main(int argc, char **argv)
799 } 701 }
800 702
801 if (status < 0) { 703 if (status < 0) {
802 printf("Warning - readback failed\n"); 704 puts("Warning - readback failed");
803 } else 705 } else
804 if (status != val) { 706 if (status != val) {
805 printf("Warning - data mismatch - wrote " 707 printf("Warning - data mismatch - wrote "
@@ -818,14 +720,14 @@ int i2cset_main(int argc, char **argv)
818#if ENABLE_I2CDUMP 720#if ENABLE_I2CDUMP
819static int read_block_data(int buf_fd, int mode, int *block) 721static int read_block_data(int buf_fd, int mode, int *block)
820{ 722{
821 uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS]; 723 uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS];
822 int res, blen = 0, tmp, i; 724 int res, blen = 0, tmp, i;
823 725
824 if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) { 726 if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) {
825 res = i2c_smbus_read_block_data(buf_fd, 0, cblock); 727 res = i2c_smbus_read_block_data(buf_fd, 0, cblock);
826 blen = res; 728 blen = res;
827 } else { 729 } else {
828 for (res = 0; res < I2C_MAX_REGS; res += tmp) { 730 for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) {
829 tmp = i2c_smbus_read_i2c_block_data( 731 tmp = i2c_smbus_read_i2c_block_data(
830 buf_fd, res, I2C_SMBUS_BLOCK_MAX, 732 buf_fd, res, I2C_SMBUS_BLOCK_MAX,
831 cblock + res); 733 cblock + res);
@@ -834,14 +736,14 @@ static int read_block_data(int buf_fd, int mode, int *block)
834 } 736 }
835 } 737 }
836 738
837 if (res >= I2C_MAX_REGS) 739 if (res >= I2CDUMP_NUM_REGS)
838 res = I2C_MAX_REGS; 740 res = I2CDUMP_NUM_REGS;
839 741
840 for (i = 0; i < res; i++) 742 for (i = 0; i < res; i++)
841 block[i] = cblock[i]; 743 block[i] = cblock[i];
842 744
843 if (mode != I2C_SMBUS_BLOCK_DATA) 745 if (mode != I2C_SMBUS_BLOCK_DATA)
844 for (i = res; i < I2C_MAX_REGS; i++) 746 for (i = res; i < I2CDUMP_NUM_REGS; i++)
845 block[i] = -1; 747 block[i] = -1;
846 } 748 }
847 749
@@ -854,10 +756,10 @@ static void dump_data(int bus_fd, int mode, unsigned first,
854{ 756{
855 int i, j, res; 757 int i, j, res;
856 758
857 printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" 759 puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
858 " 0123456789abcdef\n"); 760 " 0123456789abcdef");
859 761
860 for (i = 0; i < I2C_MAX_REGS; i += 0x10) { 762 for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) {
861 if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen) 763 if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
862 break; 764 break;
863 if (i/16 < first/16) 765 if (i/16 < first/16)
@@ -924,22 +826,22 @@ static void dump_data(int bus_fd, int mode, unsigned first,
924 break; 826 break;
925 /* Skip unwanted registers */ 827 /* Skip unwanted registers */
926 if (i+j < first || i+j > last) { 828 if (i+j < first || i+j > last) {
927 printf(" "); 829 bb_putchar(' ');
928 continue; 830 continue;
929 } 831 }
930 832
931 res = block[i+j]; 833 res = block[i+j];
932 if (res < 0) { 834 if (res < 0) {
933 printf("X"); 835 bb_putchar('X');
934 } else if (res == 0x00 || res == 0xff) { 836 } else if (res == 0x00 || res == 0xff) {
935 printf("."); 837 bb_putchar('.');
936 } else if (res < 32 || res >= 127) { 838 } else if (res < 32 || res >= 127) {
937 printf("?"); 839 bb_putchar('?');
938 } else { 840 } else {
939 printf("%c", res); 841 bb_putchar(res);
940 } 842 }
941 } 843 }
942 printf("\n"); 844 bb_putchar('\n');
943 } 845 }
944} 846}
945 847
@@ -948,7 +850,7 @@ static void dump_word_data(int bus_fd, unsigned first, unsigned last)
948 int i, j, rv; 850 int i, j, rv;
949 851
950 /* Word data. */ 852 /* Word data. */
951 printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n"); 853 puts(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f");
952 for (i = 0; i < 256; i += 8) { 854 for (i = 0; i < 256; i += 8) {
953 if (i/8 < first/8) 855 if (i/8 < first/8)
954 continue; 856 continue;
@@ -969,7 +871,7 @@ static void dump_word_data(int bus_fd, unsigned first, unsigned last)
969 else 871 else
970 printf("%04x ", rv & 0xffff); 872 printf("%04x ", rv & 0xffff);
971 } 873 }
972 printf("\n"); 874 bb_putchar('\n');
973 } 875 }
974} 876}
975 877
@@ -1120,33 +1022,33 @@ static const struct i2c_func i2c_funcs_tab[] = {
1120 { .value = I2C_FUNC_I2C, 1022 { .value = I2C_FUNC_I2C,
1121 .name = "I2C" }, 1023 .name = "I2C" },
1122 { .value = I2C_FUNC_SMBUS_QUICK, 1024 { .value = I2C_FUNC_SMBUS_QUICK,
1123 .name = "SMBus Quick Command" }, 1025 .name = "SMBus quick command" },
1124 { .value = I2C_FUNC_SMBUS_WRITE_BYTE, 1026 { .value = I2C_FUNC_SMBUS_WRITE_BYTE,
1125 .name = "SMBus Send Byte" }, 1027 .name = "SMBus send byte" },
1126 { .value = I2C_FUNC_SMBUS_READ_BYTE, 1028 { .value = I2C_FUNC_SMBUS_READ_BYTE,
1127 .name = "SMBus Receive Byte" }, 1029 .name = "SMBus receive byte" },
1128 { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA, 1030 { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
1129 .name = "SMBus Write Byte" }, 1031 .name = "SMBus write byte" },
1130 { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA, 1032 { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
1131 .name = "SMBus Read Byte" }, 1033 .name = "SMBus read byte" },
1132 { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA, 1034 { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
1133 .name = "SMBus Write Word" }, 1035 .name = "SMBus write word" },
1134 { .value = I2C_FUNC_SMBUS_READ_WORD_DATA, 1036 { .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
1135 .name = "SMBus Read Word" }, 1037 .name = "SMBus read word" },
1136 { .value = I2C_FUNC_SMBUS_PROC_CALL, 1038 { .value = I2C_FUNC_SMBUS_PROC_CALL,
1137 .name = "SMBus Process Call" }, 1039 .name = "SMBus process call" },
1138 { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, 1040 { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
1139 .name = "SMBus Block Write" }, 1041 .name = "SMBus block write" },
1140 { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA, 1042 { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
1141 .name = "SMBus Block Read" }, 1043 .name = "SMBus block read" },
1142 { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL, 1044 { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
1143 .name = "SMBus Block Process Call" }, 1045 .name = "SMBus block process call" },
1144 { .value = I2C_FUNC_SMBUS_PEC, 1046 { .value = I2C_FUNC_SMBUS_PEC,
1145 .name = "SMBus PEC" }, 1047 .name = "SMBus PEC" },
1146 { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, 1048 { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
1147 .name = "I2C Block Write" }, 1049 .name = "I2C block write" },
1148 { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK, 1050 { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
1149 .name = "I2C Block Read" }, 1051 .name = "I2C block read" },
1150 { .value = 0, .name = NULL } 1052 { .value = 0, .name = NULL }
1151}; 1053};
1152 1054
@@ -1298,7 +1200,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1298 opt_F = (1 << 4), opt_l = (1 << 5); 1200 opt_F = (1 << 4), opt_l = (1 << 5);
1299 const char *const optstr = "yaqrFl"; 1201 const char *const optstr = "yaqrFl";
1300 1202
1301 int fd, bus_num, i, j, mode = DETECT_MODE_AUTO, status; 1203 int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status;
1302 unsigned first = 0x03, last = 0x77, opts; 1204 unsigned first = 0x03, last = 0x77, opts;
1303 unsigned long funcs; 1205 unsigned long funcs;
1304 1206
@@ -1329,9 +1231,9 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1329 } 1231 }
1330 1232
1331 if (opts & opt_r) 1233 if (opts & opt_r)
1332 mode = DETECT_MODE_READ; 1234 mode = I2CDETECT_MODE_READ;
1333 else if (opts & opt_q) 1235 else if (opts & opt_q)
1334 mode = DETECT_MODE_QUICK; 1236 mode = I2CDETECT_MODE_QUICK;
1335 1237
1336 if (opts & opt_a) { 1238 if (opts & opt_a) {
1337 first = 0x00; 1239 first = 0x00;
@@ -1348,42 +1250,42 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1348 if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) { 1250 if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
1349 no_support("detection commands"); 1251 no_support("detection commands");
1350 } else 1252 } else
1351 if (mode == DETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) { 1253 if (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
1352 no_support("SMBus Quick Write command"); 1254 no_support("SMBus quick write");
1353 } else 1255 } else
1354 if (mode == DETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { 1256 if (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
1355 no_support("SMBus Receive Byte command"); 1257 no_support("SMBus receive byte");
1356 } 1258 }
1357 1259
1358 if (mode == DETECT_MODE_AUTO) { 1260 if (mode == I2CDETECT_MODE_AUTO) {
1359 if (!(funcs & I2C_FUNC_SMBUS_QUICK)) 1261 if (!(funcs & I2C_FUNC_SMBUS_QUICK))
1360 will_skip("SMBus Quick Write"); 1262 will_skip("SMBus quick write");
1361 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) 1263 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
1362 will_skip("SMBus Receive Byte"); 1264 will_skip("SMBus receive byte");
1363 } 1265 }
1364 1266
1365 if (!(opts & opt_y)) 1267 if (!(opts & opt_y))
1366 confirm_action(-1, -1, -1, 0); 1268 confirm_action(-1, -1, -1, 0);
1367 1269
1368 printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); 1270 puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
1369 for (i = 0; i < 128; i += 16) { 1271 for (i = 0; i < 128; i += 16) {
1370 printf("%02x: ", i); 1272 printf("%02x: ", i);
1371 for(j = 0; j < 16; j++) { 1273 for(j = 0; j < 16; j++) {
1372 fflush_all(); 1274 fflush_all();
1373 1275
1374 if (mode == DETECT_MODE_AUTO) { 1276 if (mode == I2CDETECT_MODE_AUTO) {
1375 if ((i+j >= 0x30 && i+j <= 0x37) || 1277 if ((i+j >= 0x30 && i+j <= 0x37) ||
1376 (i+j >= 0x50 && i+j <= 0x5F)) 1278 (i+j >= 0x50 && i+j <= 0x5F))
1377 mode = DETECT_MODE_READ; 1279 mode = I2CDETECT_MODE_READ;
1378 else 1280 else
1379 mode = DETECT_MODE_QUICK; 1281 mode = I2CDETECT_MODE_QUICK;
1380 } 1282 }
1381 1283
1382 /* Skip unwanted addresses. */ 1284 /* Skip unwanted addresses. */
1383 if (i+j < first 1285 if (i+j < first
1384 || i+j > last 1286 || i+j > last
1385 || (mode == DETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) 1287 || (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE))
1386 || (mode == DETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) 1288 || (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)))
1387 { 1289 {
1388 printf(" "); 1290 printf(" ");
1389 continue; 1291 continue;
@@ -1401,14 +1303,14 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1401 } 1303 }
1402 1304
1403 switch (mode) { 1305 switch (mode) {
1404 case DETECT_MODE_READ: 1306 case I2CDETECT_MODE_READ:
1405 /* 1307 /*
1406 * This is known to lock SMBus on various 1308 * This is known to lock SMBus on various
1407 * write-only chips (mainly clock chips). 1309 * write-only chips (mainly clock chips).
1408 */ 1310 */
1409 status = i2c_smbus_read_byte(fd); 1311 status = i2c_smbus_read_byte(fd);
1410 break; 1312 break;
1411 default: /* DETECT_MODE_QUICK: */ 1313 default: /* I2CDETECT_MODE_QUICK: */
1412 /* 1314 /*
1413 * This is known to corrupt the Atmel 1315 * This is known to corrupt the Atmel
1414 * AT24RF08 EEPROM. 1316 * AT24RF08 EEPROM.
@@ -1423,7 +1325,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1423 else 1325 else
1424 printf("%02x ", i+j); 1326 printf("%02x ", i+j);
1425 } 1327 }
1426 printf("\n"); 1328 bb_putchar('\n');
1427 } 1329 }
1428 1330
1429 return 0; 1331 return 0;