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>
This commit is contained in:
Louis Yung-Chieh Lo
2012-08-30 15:32:47 +08:00
committed by Gerrit
parent 141e16c2fa
commit e1f4dfc082
2 changed files with 77 additions and 50 deletions

View File

@@ -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;
}
/*
* 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;
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 */
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)

View File

@@ -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';