mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
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:
committed by
Gerrit
parent
141e16c2fa
commit
e1f4dfc082
118
util/comm-i2c.c
118
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;
|
||||
}
|
||||
/*
|
||||
* 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)
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user