summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2012-08-30 15:32:47 +0800
committerGerrit <chrome-bot@google.com>2012-09-05 02:24:07 -0700
commite1f4dfc0826fc35ace68324a6ff1d1f109a37264 (patch)
tree318a0b0bd40913c7406e14cfabd98acda3d61ff1
parent141e16c2fa89ff978008873bc11f2d82c4b5d354 (diff)
downloadchrome-ec-e1f4dfc0826fc35ace68324a6ff1d1f109a37264.tar.gz
comm-i2c.c upgrades to protocol v2.
Old i2c code uses protocol v1, which cannot handle veriable-length response (unknown lenght to calculate checksum). So, upgrade to procotol v2 anyway since command v1 needs protocol v2. BUG=chrome-os-partner:11608, Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org> BRANCH=None TEST=on snow, and both command v0/v1 are working on protocol v2. ectool version ectool hello ectool echash ectool flashinfo ectool flashprotect ectool flashwp Change-Id: Id8532fe51359dce18839d37de8a8c8669754041c Reviewed-on: https://gerrit.chromium.org/gerrit/31838 Commit-Ready: Yung-Chieh Lo <yjlou@chromium.org> Reviewed-by: Yung-Chieh Lo <yjlou@chromium.org> Tested-by: Yung-Chieh Lo <yjlou@chromium.org>
-rw-r--r--util/comm-i2c.c120
-rw-r--r--util/ectool.c9
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';