aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorBartosz Golaszewski <bartekgola@gmail.com>2015-06-05 10:27:31 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2015-06-07 18:05:47 +0200
commitaeb11a949667f82173c733e55e9f762c56a1fcba (patch)
treeb34319d0e9d089ded4007d59e1adb51d1d7e16ab /miscutils
parent2204472497285dd6fd7b686bb49732fda7394492 (diff)
downloadbusybox-w32-aeb11a949667f82173c733e55e9f762c56a1fcba.tar.gz
busybox-w32-aeb11a949667f82173c733e55e9f762c56a1fcba.tar.bz2
busybox-w32-aeb11a949667f82173c733e55e9f762c56a1fcba.zip
i2cdump: code rework
Split i2cdump_main() into shorter functions. Simplify the code a bit. Make block an array of ints so that we can store negative results of read functions (fixes a bug found by Denys Vlasenko). Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/i2c_tools.c316
1 files changed, 167 insertions, 149 deletions
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index 16784e948..2f501cd9c 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -816,6 +816,163 @@ int i2cset_main(int argc, char **argv)
816#endif /* ENABLE_I2CSET */ 816#endif /* ENABLE_I2CSET */
817 817
818#if ENABLE_I2CDUMP 818#if ENABLE_I2CDUMP
819static int read_block_data(int buf_fd, int mode, int *block)
820{
821 uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS];
822 int res, blen = 0, tmp, i;
823
824 if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) {
825 res = i2c_smbus_read_block_data(buf_fd, 0, cblock);
826 blen = res;
827 } else {
828 for (res = 0; res < I2C_MAX_REGS; res += tmp) {
829 tmp = i2c_smbus_read_i2c_block_data(
830 buf_fd, res, I2C_SMBUS_BLOCK_MAX,
831 cblock + res);
832 if (tmp < 0) {
833 bb_error_msg_and_die("block read failed");
834 }
835 }
836
837 if (res >= I2C_MAX_REGS)
838 res = I2C_MAX_REGS;
839
840 for (i = 0; i < res; i++)
841 block[i] = cblock[i];
842
843 if (mode != I2C_SMBUS_BLOCK_DATA)
844 for (i = res; i < I2C_MAX_REGS; i++)
845 block[i] = -1;
846 }
847
848 return blen;
849}
850
851/* Dump all but word data. */
852static void dump_data(int bus_fd, int mode, unsigned first,
853 unsigned last, int *block, int blen)
854{
855 int i, j, res;
856
857 printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
858 " 0123456789abcdef\n");
859
860 for (i = 0; i < I2C_MAX_REGS; i += 0x10) {
861 if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
862 break;
863 if (i/16 < first/16)
864 continue;
865 if (i/16 > last/16)
866 break;
867
868 printf("%02x: ", i);
869 for (j = 0; j < 16; j++) {
870 fflush_all();
871 /* Skip unwanted registers */
872 if (i+j < first || i+j > last) {
873 printf(" ");
874 if (mode == I2C_SMBUS_WORD_DATA) {
875 printf(" ");
876 j++;
877 }
878 continue;
879 }
880
881 switch (mode) {
882 case I2C_SMBUS_BYTE_DATA:
883 res = i2c_smbus_read_byte_data(bus_fd, i+j);
884 block[i+j] = res;
885 break;
886 case I2C_SMBUS_WORD_DATA:
887 res = i2c_smbus_read_word_data(bus_fd, i+j);
888 if (res < 0) {
889 block[i+j] = res;
890 block[i+j+1] = res;
891 } else {
892 block[i+j] = res & 0xff;
893 block[i+j+1] = res >> 8;
894 }
895 break;
896 case I2C_SMBUS_BYTE:
897 res = i2c_smbus_read_byte(bus_fd);
898 block[i+j] = res;
899 break;
900 default:
901 res = block[i+j];
902 }
903
904 if (mode == I2C_SMBUS_BLOCK_DATA &&
905 i+j >= blen) {
906 printf(" ");
907 } else if (res < 0) {
908 printf("XX ");
909 if (mode == I2C_SMBUS_WORD_DATA)
910 printf("XX ");
911 } else {
912 printf("%02x ", block[i+j]);
913 if (mode == I2C_SMBUS_WORD_DATA)
914 printf("%02x ", block[i+j+1]);
915 }
916
917 if (mode == I2C_SMBUS_WORD_DATA)
918 j++;
919 }
920 printf(" ");
921
922 for (j = 0; j < 16; j++) {
923 if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
924 break;
925 /* Skip unwanted registers */
926 if (i+j < first || i+j > last) {
927 printf(" ");
928 continue;
929 }
930
931 res = block[i+j];
932 if (res < 0) {
933 printf("X");
934 } else if (res == 0x00 || res == 0xff) {
935 printf(".");
936 } else if (res < 32 || res >= 127) {
937 printf("?");
938 } else {
939 printf("%c", res);
940 }
941 }
942 printf("\n");
943 }
944}
945
946static void dump_word_data(int bus_fd, unsigned first, unsigned last)
947{
948 int i, j, rv;
949
950 /* Word data. */
951 printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n");
952 for (i = 0; i < 256; i += 8) {
953 if (i/8 < first/8)
954 continue;
955 if (i/8 > last/8)
956 break;
957
958 printf("%02x: ", i);
959 for (j = 0; j < 8; j++) {
960 /* Skip unwanted registers. */
961 if (i+j < first || i+j > last) {
962 printf(" ");
963 continue;
964 }
965
966 rv = i2c_smbus_read_word_data(bus_fd, i+j);
967 if (rv < 0)
968 printf("XXXX ");
969 else
970 printf("%04x ", rv & 0xffff);
971 }
972 printf("\n");
973 }
974}
975
819//usage:#define i2cdump_trivial_usage 976//usage:#define i2cdump_trivial_usage
820//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]" 977//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]"
821//usage:#define i2cdump_full_usage "\n\n" 978//usage:#define i2cdump_full_usage "\n\n"
@@ -842,12 +999,10 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
842 const char *const optstr = "fyr:"; 999 const char *const optstr = "fyr:";
843 1000
844 int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; 1001 int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
845 unsigned first = 0x00, last = 0xff; 1002 unsigned first = 0x00, last = 0xff, opts;
846 int fd, i, j, res, blen = 0, tmp; 1003 int *block = (int *)bb_common_bufsiz1;
847 unsigned char cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS];
848 unsigned char block[I2C_SMBUS_BLOCK_MAX];
849 char *opt_r_str, *dash; 1004 char *opt_r_str, *dash;
850 unsigned opts; 1005 int fd, res, blen;
851 1006
852 opt_complementary = "-2:?3"; /* from 2 to 3 args */ 1007 opt_complementary = "-2:?3"; /* from 2 to 3 args */
853 opts = getopt32(argv, optstr, &opt_r_str); 1008 opts = getopt32(argv, optstr, &opt_r_str);
@@ -858,7 +1013,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
858 1013
859 if (argv[2]) { 1014 if (argv[2]) {
860 switch (argv[2][0]) { 1015 switch (argv[2][0]) {
861 case 'b': /* Already set */ break; 1016 case 'b': /* Already set. */ break;
862 case 'c': mode = I2C_SMBUS_BYTE; break; 1017 case 'c': mode = I2C_SMBUS_BYTE; break;
863 case 'w': mode = I2C_SMBUS_WORD_DATA; break; 1018 case 'w': mode = I2C_SMBUS_WORD_DATA; break;
864 case 'W': 1019 case 'W':
@@ -887,7 +1042,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
887 bb_error_msg_and_die("invalid range"); 1042 bb_error_msg_and_die("invalid range");
888 last = xstrtou_range(++dash, 0, first, 0xff); 1043 last = xstrtou_range(++dash, 0, first, 0xff);
889 1044
890 /* Range is not available for every mode */ 1045 /* Range is not available for every mode. */
891 switch (mode) { 1046 switch (mode) {
892 case I2C_SMBUS_BYTE: 1047 case I2C_SMBUS_BYTE:
893 case I2C_SMBUS_BYTE_DATA: 1048 case I2C_SMBUS_BYTE_DATA:
@@ -912,156 +1067,19 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
912 if (!(opts & opt_y)) 1067 if (!(opts & opt_y))
913 confirm_action(bus_addr, mode, -1 /* data_addr */, pec); 1068 confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
914 1069
915 /* All but word data */ 1070 /* All but word data. */
916 if (mode != I2C_SMBUS_WORD_DATA || even) { 1071 if (mode != I2C_SMBUS_WORD_DATA || even) {
917 /* 1072 blen = read_block_data(fd, mode, block);
918 * FIXME This section has been ported from upstream i2cdump.
919 * It has been reworked a bit but is still pretty spaghetti
920 * and needs splitting into several functions.
921 */
922 if (mode == I2C_SMBUS_BLOCK_DATA ||
923 mode == I2C_SMBUS_I2C_BLOCK_DATA) {
924 res = i2c_smbus_read_block_data(fd, 0, cblock);
925 blen = res;
926 } else {
927 for (res = 0; res < I2C_MAX_REGS; res += tmp) {
928 tmp = i2c_smbus_read_i2c_block_data(
929 fd, res, I2C_SMBUS_BLOCK_MAX,
930 cblock + res);
931 if (tmp < 0) {
932 bb_error_msg_and_die(
933 "block read failed");
934 }
935 }
936 if (res >= I2C_MAX_REGS)
937 res = I2C_MAX_REGS;
938 for (i = 0; i < res; i++)
939 block[i] = cblock[i];
940 if (mode != I2C_SMBUS_BLOCK_DATA)
941 for (i = res; i < I2C_MAX_REGS; i++)
942 cblock[i] = -1;
943 }
944 1073
945 if (mode == I2C_SMBUS_BYTE) { 1074 if (mode == I2C_SMBUS_BYTE) {
946 res = i2c_smbus_write_byte(fd, first); 1075 res = i2c_smbus_write_byte(fd, first);
947 if (res < 0) 1076 if (res < 0)
948 bb_perror_msg_and_die( 1077 bb_perror_msg_and_die("write start address");
949 "write start address failed");
950 } 1078 }
951 1079
952 printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" 1080 dump_data(fd, mode, first, last, block, blen);
953 " 0123456789abcdef\n");
954
955 for (i = 0; i < I2C_MAX_REGS; i += 0x10) {
956 if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
957 break;
958 if (i/16 < first/16)
959 continue;
960 if (i/16 > last/16)
961 break;
962
963 printf("%02x: ", i);
964 for (j = 0; j < 16; j++) {
965 fflush_all();
966 /* Skip unwanted registers */
967 if (i+j < first || i+j > last) {
968 printf(" ");
969 if (mode == I2C_SMBUS_WORD_DATA) {
970 printf(" ");
971 j++;
972 }
973 continue;
974 }
975
976 switch (mode) {
977 case I2C_SMBUS_BYTE_DATA:
978 res = i2c_smbus_read_byte_data(fd, i+j);
979 block[i+j] = res;
980 break;
981 case I2C_SMBUS_WORD_DATA:
982 res = i2c_smbus_read_word_data(fd, i+j);
983 if (res < 0) {
984 block[i+j] = res;
985 block[i+j+1] = res;
986 } else {
987 block[i+j] = res & 0xff;
988 block[i+j+1] = res >> 8;
989 }
990 break;
991 case I2C_SMBUS_BYTE:
992 res = i2c_smbus_read_byte(fd);
993 block[i+j] = res;
994 break;
995 default:
996 res = block[i+j];
997 }
998
999 if (mode == I2C_SMBUS_BLOCK_DATA &&
1000 i+j >= blen) {
1001 printf(" ");
1002 } else if (res < 0) {
1003 printf("XX ");
1004 if (mode == I2C_SMBUS_WORD_DATA)
1005 printf("XX ");
1006 } else {
1007 printf("%02x ", block[i+j]);
1008 if (mode == I2C_SMBUS_WORD_DATA)
1009 printf("%02x ", block[i+j+1]);
1010 }
1011
1012 if (mode == I2C_SMBUS_WORD_DATA)
1013 j++;
1014 }
1015 printf(" ");
1016
1017 for (j = 0; j < 16; j++) {
1018 if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
1019 break;
1020 /* Skip unwanted registers */
1021 if (i+j < first || i+j > last) {
1022 printf(" ");
1023 continue;
1024 }
1025
1026 res = block[i+j];
1027 if (res < 0) {
1028//FIXME: impossible, block[] is uchar[]
1029 printf("X");
1030 } else if (res == 0x00 || res == 0xff) {
1031 printf(".");
1032 } else if (res < 32 || res >= 127) {
1033 printf("?");
1034 } else {
1035 printf("%c", res);
1036 }
1037 }
1038 printf("\n");
1039 }
1040 } else { 1081 } else {
1041 /* Word data. */ 1082 dump_word_data(fd, first, last);
1042 printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n");
1043 for (i = 0; i < 256; i += 8) {
1044 if (i/8 < first/8)
1045 continue;
1046 if (i/8 > last/8)
1047 break;
1048
1049 printf("%02x: ", i);
1050 for (j = 0; j < 8; j++) {
1051 /* Skip unwanted registers. */
1052 if (i+j < first || i+j > last) {
1053 printf(" ");
1054 continue;
1055 }
1056
1057 res = i2c_smbus_read_word_data(fd, i+j);
1058 if (res < 0)
1059 printf("XXXX ");
1060 else
1061 printf("%04x ", res & 0xffff);
1062 }
1063 printf("\n");
1064 }
1065 } 1083 }
1066 1084
1067 return 0; 1085 return 0;