/** * struct cros_ec_rpmsg_response - rpmsg message format from from EC. * * @type: The type of message, should be either HOST_COMMAND_MARK or * HOST_EVENT_MARK, representing that the message is a response to * host command, or a host event. * @data: ec_host_response for host command.
*/ struct cros_ec_rpmsg_response {
u8 type;
u8 data[] __aligned(4);
};
/** * struct cros_ec_rpmsg - information about a EC over rpmsg. * * @rpdev: rpmsg device we are connected to * @xfer_ack: completion for host command transfer. * @host_event_work: Work struct for pending host event. * @ept: The rpmsg endpoint of this channel. * @has_pending_host_event: Boolean used to check if there is a pending event. * @probe_done: Flag to indicate that probe is done.
*/ struct cros_ec_rpmsg { struct rpmsg_device *rpdev; struct completion xfer_ack; struct work_struct host_event_work; struct rpmsg_endpoint *ept; bool has_pending_host_event; bool probe_done;
};
/** * cros_ec_cmd_xfer_rpmsg - Transfer a message over rpmsg and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer * * This is only used for old EC proto version, and is not supported for this * driver. * * Return: -EINVAL
*/ staticint cros_ec_cmd_xfer_rpmsg(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg)
{ return -EINVAL;
}
/** * cros_ec_pkt_xfer_rpmsg - Transfer a packet over rpmsg and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer * * Return: number of bytes of the reply on success or negative error code.
*/ staticint cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg)
{ struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv; struct ec_host_response *response; unsignedlong timeout; int len; int ret;
u8 sum; int i;
ec_msg->result = 0;
len = cros_ec_prepare_tx(ec_dev, ec_msg); if (len < 0) return len;
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
reinit_completion(&ec_rpmsg->xfer_ack);
ret = rpmsg_send(ec_rpmsg->ept, ec_dev->dout, len); if (ret) {
dev_err(ec_dev->dev, "rpmsg send failed\n"); return ret;
}
timeout = msecs_to_jiffies(EC_MSG_TIMEOUT_MS);
ret = wait_for_completion_timeout(&ec_rpmsg->xfer_ack, timeout); if (!ret) {
dev_err(ec_dev->dev, "rpmsg send timeout\n"); return -EIO;
}
ret = cros_ec_check_result(ec_dev, ec_msg); if (ret) gotoexit;
if (response->data_len > ec_msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
response->data_len, ec_msg->insize);
ret = -EMSGSIZE; gotoexit;
}
if (!len) {
dev_warn(ec_dev->dev, "rpmsg received empty response"); return -EINVAL;
}
resp = data;
len -= offsetof(struct cros_ec_rpmsg_response, data); if (resp->type == HOST_COMMAND_MARK) { if (len > ec_dev->din_size) {
dev_warn(ec_dev->dev, "received length %d > din_size %d, truncating",
len, ec_dev->din_size);
len = ec_dev->din_size;
}
memcpy(ec_dev->din, resp->data, len);
complete(&ec_rpmsg->xfer_ack);
} elseif (resp->type == HOST_EVENT_MARK) { /* * If the host event is sent before cros_ec_register is * finished, queue the host event.
*/ if (ec_rpmsg->probe_done)
schedule_work(&ec_rpmsg->host_event_work); else
ec_rpmsg->has_pending_host_event = true;
} else {
dev_warn(ec_dev->dev, "rpmsg received invalid type = %d",
resp->type); return -EINVAL;
}
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.