return EC_MSG_TX_PROTO_BYTES + msg->out_len;
}
-static int cros_ec_command_recv(struct chromeos_ec_device *ec_dev,
- char cmd, void *buf, int buf_len)
+static int cros_ec_command_sendrecv(struct chromeos_ec_device *ec_dev,
+ uint16_t cmd, void *out_buf, int out_len,
+ void *in_buf, int in_len)
{
struct chromeos_ec_msg msg;
- msg.version = 0;
- msg.cmd = cmd;
- msg.in_buf = buf;
- msg.in_len = buf_len;
- msg.out_buf = NULL;
- msg.out_len = 0;
+ msg.version = cmd >> 8;
+ msg.cmd = cmd & 0xff;
+ msg.out_buf = out_buf;
+ msg.out_len = out_len;
+ msg.in_buf = in_buf;
+ msg.in_len = in_len;
return ec_dev->command_xfer(ec_dev, &msg);
}
-static int cros_ec_command_send(struct chromeos_ec_device *ec_dev,
- char cmd, void *buf, int buf_len)
+static int cros_ec_command_recv(struct chromeos_ec_device *ec_dev,
+ uint16_t cmd, void *buf, int buf_len)
{
- struct chromeos_ec_msg msg;
-
- msg.version = 0;
- msg.cmd = cmd;
- msg.out_buf = buf;
- msg.out_len = buf_len;
- msg.in_buf = NULL;
- msg.in_len = 0;
+ return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
+}
- return ec_dev->command_xfer(ec_dev, &msg);
+static int cros_ec_command_send(struct chromeos_ec_device *ec_dev,
+ uint16_t cmd, void *buf, int buf_len)
+{
+ return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
}
struct chromeos_ec_device *__devinit cros_ec_alloc(const char *name)
ec_dev->command_send = cros_ec_command_send;
ec_dev->command_recv = cros_ec_command_recv;
+ ec_dev->command_sendrecv = cros_ec_command_sendrecv;
if (ec_dev->din_size) {
ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL);
i2c_msg[1].addr = client->addr;
i2c_msg[1].flags = I2C_M_RD;
- if (msg->in_len) {
- /* allocate larger packet
- * (one byte for checksum, one for result code)
- */
- packet_len = msg->in_len + 2;
- 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;
- } else {
- i2c_msg[1].len = 1;
- i2c_msg[1].buf = (char *)&res_code;
- }
+ /*
+ * allocate larger packet (one byte for checksum, one byte for
+ * length, and one for result code)
+ */
+ packet_len = msg->in_len + 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;
- if (msg->out_len) {
- /* allocate larger packet
- * (one byte for checksum, one for command code)
- */
- packet_len = msg->out_len + 2;
- 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;
- out_buf[0] = msg->cmd;
-
- /* copy message payload and compute checksum */
- for (i = 0, sum = 0; i < msg->out_len; i++) {
- out_buf[i + 1] = msg->out_buf[i];
- sum += out_buf[i + 1];
- }
- out_buf[msg->out_len + 1] = sum;
- } else {
- i2c_msg[0].len = 1;
- i2c_msg[0].buf = (char *)&msg->cmd;
+ /*
+ * allocate larger packet (one byte for checksum, one for
+ * command code, one for length, and one for command version)
+ */
+ packet_len = msg->out_len + 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;
+
+ out_buf[0] = EC_CMD_VERSION0 + msg->version;
+ out_buf[1] = msg->cmd;
+ out_buf[2] = msg->out_len;
+
+ /* copy message payload and compute checksum */
+ sum = out_buf[0] + out_buf[1] + out_buf[2];
+ for (i = 0; i < msg->out_len; i++) {
+ out_buf[3 + i] = msg->out_buf[i];
+ sum += out_buf[3 + i];
}
+ out_buf[3 + msg->out_len] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2);
ret = -EINVAL;
goto done;
}
- if (msg->in_len) {
- /* copy response packet payload and compute checksum */
- for (i = 0, sum = 0; i < msg->in_len; i++) {
- msg->in_buf[i] = in_buf[i + 1];
- sum += in_buf[i + 1];
- }
+
+ /* copy response packet payload and compute checksum */
+ sum = in_buf[0] + in_buf[1];
+ for (i = 0; i < msg->in_len; i++) {
+ msg->in_buf[i] = in_buf[2 + i];
+ sum += in_buf[2 + i];
+ }
#ifdef DEBUG
- dev_dbg(ec_dev->dev, "packet: ");
- for (i = 0; i < i2c_msg[1].len; i++)
- printk(" %02x", in_buf[i]);
- printk(", sum = %02x\n", sum);
+ dev_dbg(ec_dev->dev, "packet: ");
+ for (i = 0; i < i2c_msg[1].len; i++)
+ printk(KERN_CONT " %02x", in_buf[i]);
+ printk(KERN_CONT ", sum = %02x\n", sum);
#endif
- if (sum != in_buf[msg->in_len + 1]) {
- dev_err(ec_dev->dev, "bad packet checksum\n");
- ret = -EBADMSG;
- goto done;
- }
+ if (sum != in_buf[2 + msg->in_len]) {
+ dev_err(ec_dev->dev, "bad packet checksum\n");
+ ret = -EBADMSG;
+ goto done;
}
ret = 0;
int din_size; /* Size of din buffer */
int dout_size; /* Size of dout buffer */
int (*command_send)(struct chromeos_ec_device *ec,
- char cmd, void *out_buf, int out_len);
+ uint16_t cmd, void *out_buf, int out_len);
int (*command_recv)(struct chromeos_ec_device *ec,
- char cmd, void *in_buf, int in_len);
+ uint16_t cmd, void *in_buf, int in_len);
+ int (*command_sendrecv)(struct chromeos_ec_device *ec,
+ uint16_t cmd, void *out_buf, int out_len,
+ void *in_buf, int in_len);
int (*command_xfer)(struct chromeos_ec_device *ec,
struct chromeos_ec_msg *msg);
int (*command_i2c)(struct chromeos_ec_device *ec,