switch (msg->result) { case EC_RES_SUCCESS: break; case EC_RES_IN_PROGRESS:
ret = -EAGAIN;
dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
msg->command); goto done;
default:
dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
msg->command, msg->result); /* * When we send v3 request to v2 ec, ec won't recognize the * 0xda (EC_COMMAND_PROTOCOL_3) and will return with status * EC_RES_INVALID_COMMAND with zero data length. * * In case of invalid command for v3 protocol the data length * will be at least sizeof(struct ec_host_response)
*/ if (ec_response_i2c->result == EC_RES_INVALID_COMMAND &&
ec_response_i2c->packet_length == 0) {
ret = -EPROTONOSUPPORT; goto done;
}
}
if (ec_response_i2c->packet_length < sizeof(struct ec_host_response)) {
dev_err(ec_dev->dev, "response of %u bytes too short; not a full header\n",
ec_response_i2c->packet_length);
ret = -EBADMSG; goto done;
}
if (msg->insize < ec_response->data_len) {
dev_err(ec_dev->dev, "response data size is too large: expected %u, got %u\n",
msg->insize,
ec_response->data_len);
ret = -EMSGSIZE; goto done;
}
/* copy response packet payload and compute checksum */
sum = 0; for (i = 0; i < sizeof(struct ec_host_response); i++)
sum += ((u8 *)ec_response)[i];
memcpy(msg->data,
in_buf + response_header_size,
ec_response->data_len); for (i = 0; i < ec_response->data_len; i++)
sum += msg->data[i];
/* All bytes should sum to zero */ if (sum) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG; goto done;
}
ret = ec_response->data_len;
done: if (msg->command == EC_CMD_REBOOT_EC)
msleep(EC_REBOOT_DELAY_MS);
return ret;
}
staticint cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev, struct cros_ec_command *msg)
{ struct i2c_client *client = ec_dev->priv; int ret = -ENOMEM; int i; int len; int packet_len;
u8 *out_buf = NULL;
u8 *in_buf = NULL;
u8 sum; struct i2c_msg i2c_msg[2];
/* * allocate larger packet (one byte for checksum, one byte for * length, and one for result code)
*/
packet_len = msg->insize + 3;
in_buf = kzalloc(packet_len, GFP_KERNEL); if (!in_buf) goto done;
i2c_msg[1].len = packet_len;
i2c_msg[1].buf = (char *)in_buf;
/* * allocate larger packet (one byte for checksum, one for * command code, one for length, and one for command version)
*/
packet_len = msg->outsize + 4;
out_buf = kzalloc(packet_len, GFP_KERNEL); if (!out_buf) goto done;
i2c_msg[0].len = packet_len;
i2c_msg[0].buf = (char *)out_buf;
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2]; for (i = 0; i < msg->outsize; i++) {
out_buf[3 + i] = msg->data[i];
sum += out_buf[3 + i];
}
out_buf[3 + msg->outsize] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2); if (ret < 0) {
dev_err(ec_dev->dev, "i2c transfer failed: %d\n", ret); goto done;
} elseif (ret != 2) {
dev_err(ec_dev->dev, "failed to get response: %d\n", ret);
ret = -EIO; goto done;
}
/* check response error code */
msg->result = i2c_msg[1].buf[0];
ret = cros_ec_check_result(ec_dev, msg); if (ret) goto done;
len = in_buf[1]; if (len > msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
len, msg->insize);
ret = -ENOSPC; goto done;
}
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1]; for (i = 0; i < len; i++) {
msg->data[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
i2c_msg[1].len, in_buf, sum); if (sum != in_buf[2 + len]) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG; goto done;
}
ret = len;
done:
kfree(in_buf);
kfree(out_buf); if (msg->command == EC_CMD_REBOOT_EC)
msleep(EC_REBOOT_DELAY_MS);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.