diff options
-rw-r--r-- | util/comm-i2c.c | 120 | ||||
-rw-r--r-- | util/ectool.c | 9 |
2 files changed, 78 insertions, 51 deletions
diff --git a/util/comm-i2c.c b/util/comm-i2c.c index 5ff71700fd..d1471495c8 100644 --- a/util/comm-i2c.c +++ b/util/comm-i2c.c @@ -32,6 +32,12 @@ #define debug(...) #endif +/* v2 protocol bytes + * OUT: (version, command, size, ... request ..., checksum) */ +#define PROTO_V2_IN 4 +/* IN: (command, size, ... response ..., checkcum) */ +#define PROTO_V2_OUT 3 + static int i2c_fd = -1; int comm_init(void) @@ -73,29 +79,37 @@ int comm_init(void) } -/* Sends a command to the EC. Returns the command status code, or - * -1 if other error. */ +/* + * Sends a command to the EC (protocol v2). Returns the command status code, or + * -1 if other error. + * + * Returns >= 0 for success, or negative if error. + * + */ int ec_command(int command, int version, const void *indata, int insize, void *outdata, int outsize) { struct i2c_rdwr_ioctl_data data; int ret = -1; int i; - uint8_t res_code; + int req_len; uint8_t *req_buf = NULL; + int resp_len; uint8_t *resp_buf = NULL; const uint8_t *c; uint8_t *d; uint8_t sum; struct i2c_msg i2c_msg[2]; - if (version > 0) { - fprintf(stderr, "Command versions >0 unsupported.\n"); + if (version > 1) { + fprintf(stderr, "Command versions >1 unsupported.\n"); return -EC_RES_ERROR; } - if (i2c_fd < 0) + if (i2c_fd < 0) { + fprintf(stderr, "i2c_fd is negative: %d\n", i2c_fd); return -EC_RES_ERROR; + } if (ioctl(i2c_fd, I2C_SLAVE, EC_I2C_ADDR) < 0) { fprintf(stderr, "Cannot set I2C slave address\n"); @@ -109,44 +123,41 @@ int ec_command(int command, int version, const void *indata, int insize, data.msgs = i2c_msg; data.nmsgs = 2; - if (outsize) { - /* allocate larger packet - * (one byte for checksum, one for result code) - */ - resp_buf = calloc(1, outsize + 2); - if (!resp_buf) - goto done; - i2c_msg[1].len = outsize + 2; - i2c_msg[1].buf = (char *)resp_buf; - } else { - i2c_msg[1].len = 1; - i2c_msg[1].buf = (char *)&res_code; - } - - if (insize) { - /* allocate larger packet - * (one byte for checksum, one for command code) - */ - req_buf = calloc(1, insize + 2); - if (!req_buf) - goto done; - i2c_msg[0].len = insize + 2; - i2c_msg[0].buf = (char *)req_buf; - req_buf[0] = command; - - debug("i2c req %02x:", command); - /* copy message payload and compute checksum */ - for (i = 0, sum = 0, c = indata; i < insize; i++, c++) { - req_buf[i + 1] = *c; - sum += *c; - debug(" %02x", *c); - } - debug(", sum=%02x\n", sum); - req_buf[insize + 1] = sum; - } else { - i2c_msg[0].len = 1; - i2c_msg[0].buf = (char *)&command; /* nasty cast */ + /* + * allocate larger packet + * (version, command, size, ..., checksum) + */ + req_len = insize + PROTO_V2_IN; + req_buf = calloc(1, req_len); + if (!req_buf) + goto done; + i2c_msg[0].len = req_len; + i2c_msg[0].buf = (char *)req_buf; + req_buf[0] = version + EC_CMD_VERSION0; + req_buf[1] = command; + req_buf[2] = insize; + + debug("i2c req %02x:", command); + sum = req_buf[0] + req_buf[1] + req_buf[2]; + /* copy message payload and compute checksum */ + for (i = 0, c = indata; i < insize; i++, c++) { + req_buf[i + 3] = *c; + sum += *c; + debug(" %02x", *c); } + debug(", sum=%02x\n", sum); + req_buf[req_len - 1] = sum; + + /* + * allocate larger packet + * (result, size, ..., checksum) + */ + resp_len = outsize + PROTO_V2_OUT; + resp_buf = calloc(1, resp_len); + if (!resp_buf) + goto done; + i2c_msg[1].len = resp_len; + i2c_msg[1].buf = (char *)resp_buf; /* send command to EC and read answer */ ret = ioctl(i2c_fd, I2C_RDWR, &data); @@ -158,7 +169,17 @@ int ec_command(int command, int version, const void *indata, int insize, } /* check response error code */ - ret = i2c_msg[1].buf[0]; + ret = resp_buf[0]; + /* TODO: handle EC_RES_IN_PROGRESS case. */ + + resp_len = resp_buf[1]; + if (resp_len > outsize) { + fprintf(stderr, "response size is too large %d > %d\n", + resp_len, outsize); + ret = -EC_RES_ERROR; + goto done; + } + if (ret) { debug("command 0x%02x returned an error %d\n", command, i2c_msg[1].buf[0]); @@ -167,21 +188,22 @@ int ec_command(int command, int version, const void *indata, int insize, } else if (outsize) { debug("i2c resp :"); /* copy response packet payload and compute checksum */ - for (i = 0, sum = 0, d = outdata; i < outsize; i++, d++) { - *d = resp_buf[i + 1]; + sum = resp_buf[0] + resp_buf[1]; + for (i = 0, d = outdata; i < resp_len; i++, d++) { + *d = resp_buf[i + 2]; sum += *d; debug(" %02x", *d); } debug(", sum=%02x\n", sum); - if (sum != resp_buf[outsize + 1]) { - debug("bad packet checksum\n"); + if (sum != resp_buf[resp_len + 2]) { + fprintf(stderr, "bad packet checksum\n"); ret = -EC_RES_ERROR; goto done; } /* Return output buffer size */ - ret = outsize; + ret = resp_len; } done: if (resp_buf) diff --git a/util/ectool.c b/util/ectool.c index 0623dc7e7f..1fc7009479 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -296,12 +296,17 @@ int cmd_version(int argc, char *argv[]) rv = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) + if (rv < 0) { + fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv); return rv; + } rv = ec_command(EC_CMD_GET_BUILD_INFO, 0, NULL, 0, build_string, sizeof(build_string)); - if (rv < 0) + if (rv < 0) { + fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n", + rv); return rv; + } /* Ensure versions are null-terminated before we print them */ r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0'; |