Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 1 | From b5e7f70c9c43d9a0f819ac2f9942cefca5a79875 Mon Sep 17 00:00:00 2001 |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 2 | From: Crestez Dan Leonard <leonard.crestez@intel.com> |
| 3 | Date: Fri, 13 May 2016 21:54:25 +0300 |
| 4 | Subject: [PATCH] i2cget: Add support for i2c block data |
| 5 | |
| 6 | This adds mode 'i' for I2C_SMBUS_I2C_BLOCK_DATA. This is the same mode |
| 7 | letter from i2cdump. |
| 8 | |
| 9 | Length is optional and defaults to 32 (maximum). |
| 10 | |
| 11 | The indended use is debugging i2c devices with shell commands. |
| 12 | |
| 13 | Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com> |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 14 | Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com> |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 15 | --- |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 16 | tools/i2cget.c | 61 +++++++++++++++++++++++++++++++++++++++++--------- |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 17 | 1 file changed, 51 insertions(+), 10 deletions(-) |
| 18 | |
| 19 | diff --git a/tools/i2cget.c b/tools/i2cget.c |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 20 | index d2ed56a..83e57f7 100644 |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 21 | --- a/tools/i2cget.c |
| 22 | +++ b/tools/i2cget.c |
| 23 | @@ -41,14 +41,16 @@ static void help(void) __attribute__ ((noreturn)); |
| 24 | static void help(void) |
| 25 | { |
| 26 | fprintf(stderr, |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 27 | - "Usage: i2cget [-f] [-y] [-a] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]\n" |
| 28 | + "Usage: i2cget [-f] [-y] [-a] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE] [LENGTH]]\n" |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 29 | " I2CBUS is an integer or an I2C bus name\n" |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 30 | " ADDRESS is an integer (0x03 - 0x77, or 0x00 - 0x7f if -a is given)\n" |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 31 | " MODE is one of:\n" |
| 32 | " b (read byte data, default)\n" |
| 33 | " w (read word data)\n" |
| 34 | " c (write byte/read byte)\n" |
| 35 | - " Append p for SMBus PEC\n"); |
| 36 | + " i (read I2C block data)\n" |
| 37 | + " Append p for SMBus PEC\n" |
| 38 | + " LENGTH is length for block data reads\n"); |
| 39 | exit(1); |
| 40 | } |
| 41 | |
| 42 | @@ -89,6 +91,13 @@ static int check_funcs(int file, int size, int daddress, int pec) |
| 43 | return -1; |
| 44 | } |
| 45 | break; |
| 46 | + |
| 47 | + case I2C_SMBUS_I2C_BLOCK_DATA: |
| 48 | + if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { |
| 49 | + fprintf(stderr, MISSING_FUNC_FMT, "SMBus read I2C block data"); |
| 50 | + return -1; |
| 51 | + } |
| 52 | + break; |
| 53 | } |
| 54 | |
| 55 | if (pec |
| 56 | @@ -101,7 +110,7 @@ static int check_funcs(int file, int size, int daddress, int pec) |
| 57 | } |
| 58 | |
| 59 | static int confirm(const char *filename, int address, int size, int daddress, |
| 60 | - int pec) |
| 61 | + int length, int pec) |
| 62 | { |
| 63 | int dont = 0; |
| 64 | |
| 65 | @@ -132,11 +141,14 @@ static int confirm(const char *filename, int address, int size, int daddress, |
| 66 | fprintf(stderr, "current data\naddress"); |
| 67 | else |
| 68 | fprintf(stderr, "data address\n0x%02x", daddress); |
| 69 | - fprintf(stderr, ", using %s.\n", |
| 70 | - size == I2C_SMBUS_BYTE ? (daddress < 0 ? |
| 71 | - "read byte" : "write byte/read byte") : |
| 72 | - size == I2C_SMBUS_BYTE_DATA ? "read byte data" : |
| 73 | - "read word data"); |
| 74 | + if (size == I2C_SMBUS_I2C_BLOCK_DATA) |
| 75 | + fprintf(stderr, ", %d bytes using read I2C block data.\n", length); |
| 76 | + else |
| 77 | + fprintf(stderr, ", using %s.\n", |
| 78 | + size == I2C_SMBUS_BYTE ? (daddress < 0 ? |
| 79 | + "read byte" : "write byte/read byte") : |
| 80 | + size == I2C_SMBUS_BYTE_DATA ? "read byte data" : |
| 81 | + "read word data"); |
| 82 | if (pec) |
| 83 | fprintf(stderr, "PEC checking enabled.\n"); |
| 84 | |
| 85 | @@ -159,6 +171,8 @@ int main(int argc, char *argv[]) |
| 86 | int pec = 0; |
| 87 | int flags = 0; |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 88 | int force = 0, yes = 0, version = 0, all_addrs = 0; |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 89 | + int length; |
| 90 | + __u8 block_data[I2C_SMBUS_BLOCK_MAX]; |
| 91 | |
| 92 | /* handle (optional) flags first */ |
| 93 | while (1+flags < argc && argv[1+flags][0] == '-') { |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 94 | @@ -209,6 +223,7 @@ int main(int argc, char *argv[]) |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 95 | case 'b': size = I2C_SMBUS_BYTE_DATA; break; |
| 96 | case 'w': size = I2C_SMBUS_WORD_DATA; break; |
| 97 | case 'c': size = I2C_SMBUS_BYTE; break; |
| 98 | + case 'i': size = I2C_SMBUS_I2C_BLOCK_DATA; break; |
| 99 | default: |
| 100 | fprintf(stderr, "Error: Invalid mode!\n"); |
| 101 | help(); |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 102 | @@ -216,13 +231,27 @@ int main(int argc, char *argv[]) |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 103 | pec = argv[flags+4][1] == 'p'; |
| 104 | } |
| 105 | |
| 106 | + if (argc > flags + 5) { |
| 107 | + if (size != I2C_SMBUS_I2C_BLOCK_DATA) { |
| 108 | + fprintf(stderr, "Error: Length only valid for I2C block data!\n"); |
| 109 | + help(); |
| 110 | + } |
| 111 | + length = strtol(argv[flags+5], &end, 0); |
| 112 | + if (*end || length < 1 || length > I2C_SMBUS_BLOCK_MAX) { |
| 113 | + fprintf(stderr, "Error: Length invalid!\n"); |
| 114 | + help(); |
| 115 | + } |
| 116 | + } else { |
| 117 | + length = I2C_SMBUS_BLOCK_MAX; |
| 118 | + } |
| 119 | + |
| 120 | file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0); |
| 121 | if (file < 0 |
| 122 | || check_funcs(file, size, daddress, pec) |
| 123 | || set_slave_addr(file, address, force)) |
| 124 | exit(1); |
| 125 | |
| 126 | - if (!yes && !confirm(filename, address, size, daddress, pec)) |
| 127 | + if (!yes && !confirm(filename, address, size, daddress, length, pec)) |
| 128 | exit(0); |
| 129 | |
| 130 | if (pec && ioctl(file, I2C_PEC, 1) < 0) { |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 131 | @@ -244,6 +273,9 @@ int main(int argc, char *argv[]) |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 132 | case I2C_SMBUS_WORD_DATA: |
| 133 | res = i2c_smbus_read_word_data(file, daddress); |
| 134 | break; |
| 135 | + case I2C_SMBUS_I2C_BLOCK_DATA: |
| 136 | + res = i2c_smbus_read_i2c_block_data(file, daddress, length, block_data); |
| 137 | + break; |
| 138 | default: /* I2C_SMBUS_BYTE_DATA */ |
| 139 | res = i2c_smbus_read_byte_data(file, daddress); |
| 140 | } |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 141 | @@ -254,7 +286,16 @@ int main(int argc, char *argv[]) |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 142 | exit(2); |
| 143 | } |
| 144 | |
| 145 | - printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res); |
| 146 | + if (size == I2C_SMBUS_I2C_BLOCK_DATA) { |
| 147 | + int i; |
| 148 | + printf("%d:", res); |
| 149 | + for (i = 0; i < res; ++i) { |
| 150 | + printf(" 0x%02hhx", block_data[i]); |
| 151 | + } |
| 152 | + printf("\n"); |
| 153 | + } else { |
| 154 | + printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res); |
| 155 | + } |
| 156 | |
| 157 | exit(0); |
| 158 | } |
| 159 | -- |
Brad Bishop | 94ad3b2 | 2019-01-15 16:01:53 -0500 | [diff] [blame] | 160 | 2.20.1 |
Matt Spinler | f593045 | 2017-01-25 15:08:00 -0600 | [diff] [blame] | 161 | |