diff options
author | Bartosz Golaszewski <bartekgola@gmail.com> | 2015-06-05 10:27:31 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-06-07 18:05:47 +0200 |
commit | aeb11a949667f82173c733e55e9f762c56a1fcba (patch) | |
tree | b34319d0e9d089ded4007d59e1adb51d1d7e16ab /miscutils | |
parent | 2204472497285dd6fd7b686bb49732fda7394492 (diff) | |
download | busybox-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.c | 316 |
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 |
819 | static 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. */ | ||
852 | static 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 | |||
946 | static 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; |